1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
49 #include <Resources.h>
51 #include <TextUtils.h>
55 #if defined (__MRC__) || (__MSL__ >= 0x6000)
56 #include <ControlDefinitions.h>
62 #endif /* not TARGET_API_MAC_CARBON */
75 #include "dispextern.h"
77 #include "termhooks.h"
84 #include "intervals.h"
90 /* Non-nil means Emacs uses toolkit scroll bars. */
92 Lisp_Object Vx_toolkit_scroll_bars
;
94 /* If non-zero, the text will be rendered using Core Graphics text
95 rendering which may anti-alias the text. */
96 int mac_use_core_graphics
;
99 /* Non-zero means that a HELP_EVENT has been generated since Emacs
102 static int any_help_event_p
;
104 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
105 static Lisp_Object last_window
;
107 /* Non-zero means make use of UNDERLINE_POSITION font properties.
108 (Not yet supported.) */
109 int x_use_underline_position_properties
;
111 /* This is a chain of structures for all the X displays currently in
114 struct x_display_info
*x_display_list
;
116 /* This is a list of cons cells, each of the form (NAME
117 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
118 x_display_list and in the same order. NAME is the name of the
119 frame. FONT-LIST-CACHE records previous values returned by
120 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
121 equivalent, which is implemented with a Lisp object, for the
124 Lisp_Object x_display_name_list
;
126 /* This is display since Mac does not support multiple ones. */
127 struct mac_display_info one_mac_display_info
;
129 /* Frame being updated by update_frame. This is declared in term.c.
130 This is set by update_begin and looked at by all the XT functions.
131 It is zero while not inside an update. In that case, the XT
132 functions assume that `selected_frame' is the frame to apply to. */
134 extern struct frame
*updating_frame
;
136 /* This is a frame waiting to be auto-raised, within XTread_socket. */
138 struct frame
*pending_autoraise_frame
;
142 Formerly, we used PointerMotionHintMask (in standard_event_mask)
143 so that we would have to call XQueryPointer after each MotionNotify
144 event to ask for another such event. However, this made mouse tracking
145 slow, and there was a bug that made it eventually stop.
147 Simply asking for MotionNotify all the time seems to work better.
149 In order to avoid asking for motion events and then throwing most
150 of them away or busy-polling the server for mouse positions, we ask
151 the server for pointer motion hints. This means that we get only
152 one event per group of mouse movements. "Groups" are delimited by
153 other kinds of events (focus changes and button clicks, for
154 example), or by XQueryPointer calls; when one of these happens, we
155 get another MotionNotify event the next time the mouse moves. This
156 is at least as efficient as getting motion events when mouse
157 tracking is on, and I suspect only negligibly worse when tracking
160 /* Where the mouse was last time we reported a mouse event. */
162 static Rect last_mouse_glyph
;
163 static FRAME_PTR last_mouse_glyph_frame
;
165 /* The scroll bar in which the last X motion event occurred.
167 If the last X motion event occurred in a scroll bar, we set this so
168 XTmouse_position can know whether to report a scroll bar motion or
171 If the last X motion event didn't occur in a scroll bar, we set
172 this to Qnil, to tell XTmouse_position to return an ordinary motion
175 static Lisp_Object last_mouse_scroll_bar
;
177 /* This is a hack. We would really prefer that XTmouse_position would
178 return the time associated with the position it returns, but there
179 doesn't seem to be any way to wrest the time-stamp from the server
180 along with the position query. So, we just keep track of the time
181 of the last movement we received, and return that in hopes that
182 it's somewhat accurate. */
184 static Time last_mouse_movement_time
;
186 struct scroll_bar
*tracked_scroll_bar
= NULL
;
188 /* Incremented by XTread_socket whenever it really tries to read
192 static int volatile input_signal_count
;
194 static int input_signal_count
;
197 extern Lisp_Object Vsystem_name
;
199 extern Lisp_Object Qeql
;
201 /* A mask of extra modifier bits to put into every keyboard char. */
203 extern EMACS_INT extra_keyboard_modifiers
;
205 /* The keysyms to use for the various modifiers. */
207 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
209 extern int inhibit_window_system
;
211 #if __MRC__ && !TARGET_API_MAC_CARBON
212 QDGlobals qd
; /* QuickDraw global information structure. */
215 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
217 struct mac_display_info
*mac_display_info_for_display (Display
*);
218 static void x_update_window_end
P_ ((struct window
*, int, int));
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 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
265 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
266 #define GC_FONT(gc) ((gc)->xgcv.font)
267 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
268 #define CG_SET_FILL_COLOR(context, color) \
269 CGContextSetRGBFillColor (context, \
270 RED_FROM_ULONG (color) / 255.0f, \
271 GREEN_FROM_ULONG (color) / 255.0f, \
272 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
273 #define CG_SET_STROKE_COLOR(context, color) \
274 CGContextSetRGBStrokeColor (context, \
275 RED_FROM_ULONG (color) / 255.0f, \
276 GREEN_FROM_ULONG (color) / 255.0f, \
277 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
279 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
281 /* Fringe bitmaps. */
283 static int max_fringe_bmp
= 0;
284 static CGImageRef
*fringe_bmp
= 0;
287 mac_begin_cg_clip (f
, gc
)
291 CGContextRef context
= FRAME_CG_CONTEXT (f
);
295 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
296 FRAME_CG_CONTEXT (f
) = context
;
299 CGContextSaveGState (context
);
300 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
301 CGContextScaleCTM (context
, 1, -1);
302 if (gc
&& gc
->n_clip_rects
)
303 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
312 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
316 mac_prepare_for_quickdraw (f
)
321 Lisp_Object rest
, frame
;
322 FOR_EACH_FRAME (rest
, frame
)
323 if (FRAME_MAC_P (XFRAME (frame
)))
324 mac_prepare_for_quickdraw (XFRAME (frame
));
328 CGContextRef context
= FRAME_CG_CONTEXT (f
);
332 CGContextSynchronize (context
);
333 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
334 &FRAME_CG_CONTEXT (f
));
340 static RgnHandle saved_port_clip_region
= NULL
;
346 static RgnHandle new_region
= NULL
;
348 if (saved_port_clip_region
== NULL
)
349 saved_port_clip_region
= NewRgn ();
350 if (new_region
== NULL
)
351 new_region
= NewRgn ();
353 if (gc
->n_clip_rects
)
355 GetClip (saved_port_clip_region
);
356 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
357 SetClip (new_region
);
365 if (gc
->n_clip_rects
)
366 SetClip (saved_port_clip_region
);
370 /* X display function emulation */
373 XFreePixmap (display
, pixmap
)
374 Display
*display
; /* not used */
377 DisposeGWorld (pixmap
);
381 /* Mac version of XDrawLine. */
384 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
390 CGContextRef context
;
391 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
394 gx1
+= 0.5f
, gx2
+= 0.5f
;
396 gy1
+= 0.5f
, gy2
+= 0.5f
;
398 context
= mac_begin_cg_clip (f
, gc
);
399 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
400 CGContextBeginPath (context
);
401 CGContextMoveToPoint (context
, gx1
, gy1
);
402 CGContextAddLineToPoint (context
, gx2
, gy2
);
403 CGContextClosePath (context
);
404 CGContextStrokePath (context
);
422 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
424 RGBForeColor (GC_FORE_COLOR (gc
));
434 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
458 GetGWorld (&old_port
, &old_gdh
);
461 RGBForeColor (GC_FORE_COLOR (gc
));
463 LockPixels (GetGWorldPixMap (p
));
466 UnlockPixels (GetGWorldPixMap (p
));
468 SetGWorld (old_port
, old_gdh
);
473 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
477 unsigned int width
, height
;
480 CGContextRef context
;
482 context
= mac_begin_cg_clip (f
, gc
);
483 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
484 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
489 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
491 RGBBackColor (GC_BACK_COLOR (gc
));
492 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
498 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
503 /* Mac version of XClearArea. */
506 mac_clear_area (f
, x
, y
, width
, height
)
509 unsigned int width
, height
;
511 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
514 /* Mac version of XClearWindow. */
521 CGContextRef context
;
522 GC gc
= FRAME_NORMAL_GC (f
);
524 context
= mac_begin_cg_clip (f
, NULL
);
525 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
526 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
527 FRAME_PIXEL_HEIGHT (f
)));
530 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
532 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
534 #if TARGET_API_MAC_CARBON
538 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
541 #else /* not TARGET_API_MAC_CARBON */
542 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
543 #endif /* not TARGET_API_MAC_CARBON */
548 /* Mac replacement for XCopyArea. */
552 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
553 dest_x
, dest_y
, overlay_p
)
558 unsigned int width
, height
;
559 int dest_x
, dest_y
, overlay_p
;
561 CGContextRef context
;
562 float port_height
= FRAME_PIXEL_HEIGHT (f
);
563 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
565 context
= mac_begin_cg_clip (f
, gc
);
568 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
569 CGContextFillRect (context
, dest_rect
);
571 CGContextClipToRect (context
, dest_rect
);
572 CGContextScaleCTM (context
, 1, -1);
573 CGContextTranslateCTM (context
, 0, -port_height
);
574 if (CGImageIsMask (image
))
575 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
576 CGContextDrawImage (context
,
577 CGRectMake (dest_x
- src_x
,
578 port_height
- (dest_y
- src_y
579 + CGImageGetHeight (image
)),
580 CGImageGetWidth (image
),
581 CGImageGetHeight (image
)),
586 #else /* !USE_CG_DRAWING */
589 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
592 int x
, y
, width
, height
;
593 unsigned short *bits
;
599 bitmap
.rowBytes
= sizeof(unsigned short);
600 bitmap
.baseAddr
= (char *)bits
;
601 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
603 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
605 RGBForeColor (GC_FORE_COLOR (gc
));
606 RGBBackColor (GC_BACK_COLOR (gc
));
607 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
610 #if TARGET_API_MAC_CARBON
616 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
617 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
618 UnlockPortBits (port
);
620 #else /* not TARGET_API_MAC_CARBON */
621 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
622 overlay_p
? srcOr
: srcCopy
, 0);
623 #endif /* not TARGET_API_MAC_CARBON */
626 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
628 #endif /* !USE_CG_DRAWING */
631 /* Mac replacement for XCreateBitmapFromBitmapData. */
634 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
639 static unsigned char swap_nibble
[16]
640 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
641 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
642 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
643 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
647 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
648 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
649 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
650 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
651 for (i
= 0; i
< h
; i
++)
653 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
654 for (j
= 0; j
< w1
; j
++)
656 /* Bitswap XBM bytes to match how Mac does things. */
657 unsigned char c
= *bits
++;
658 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
659 | (swap_nibble
[(c
>>4) & 0xf]));;
663 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
668 mac_free_bitmap (bitmap
)
671 xfree (bitmap
->baseAddr
);
676 XCreatePixmap (display
, w
, width
, height
, depth
)
677 Display
*display
; /* not used */
679 unsigned int width
, height
;
686 SetPortWindowPort (w
);
688 SetRect (&r
, 0, 0, width
, height
);
689 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
692 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
693 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
695 /* CreateCGImageFromPixMaps requires ARGB format. */
696 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
705 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
706 Display
*display
; /* not used */
709 unsigned int width
, height
;
710 unsigned long fg
, bg
;
717 static GC gc
= NULL
; /* not reentrant */
720 gc
= XCreateGC (display
, w
, 0, NULL
);
722 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
726 GetGWorld (&old_port
, &old_gdh
);
727 SetGWorld (pixmap
, NULL
);
728 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
729 XSetForeground (display
, gc
, fg
);
730 XSetBackground (display
, gc
, bg
);
731 RGBForeColor (GC_FORE_COLOR (gc
));
732 RGBBackColor (GC_BACK_COLOR (gc
));
733 LockPixels (GetGWorldPixMap (pixmap
));
734 #if TARGET_API_MAC_CARBON
735 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
736 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
737 #else /* not TARGET_API_MAC_CARBON */
738 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
739 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
740 #endif /* not TARGET_API_MAC_CARBON */
741 UnlockPixels (GetGWorldPixMap (pixmap
));
742 SetGWorld (old_port
, old_gdh
);
743 mac_free_bitmap (&bitmap
);
749 /* Mac replacement for XFillRectangle. */
752 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
756 unsigned int width
, height
;
759 CGContextRef context
;
761 context
= mac_begin_cg_clip (f
, gc
);
762 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
763 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
768 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
770 RGBForeColor (GC_FORE_COLOR (gc
));
771 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
774 PaintRect (&r
); /* using foreground color of gc */
780 /* Mac replacement for XDrawRectangle: dest is a window. */
783 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
787 unsigned int width
, height
;
790 CGContextRef context
;
792 context
= mac_begin_cg_clip (f
, gc
);
793 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
794 CGContextStrokeRect (context
,
795 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
800 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
802 RGBForeColor (GC_FORE_COLOR (gc
));
803 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
806 FrameRect (&r
); /* using foreground color of gc */
814 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
815 ConstUniCharArrayPtr text
;
816 UniCharCount text_length
;
818 ATSUTextLayout
*text_layout
;
821 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
823 if (saved_text_layout
== NULL
)
825 UniCharCount lengths
[] = {kATSUToTextEnd
};
826 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
827 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
828 static ATSLineLayoutOptions line_layout
=
829 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
830 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
831 | kATSLineUseQDRendering
833 kATSLineIsDisplayOnly
| kATSLineFractDisable
836 ATSUAttributeValuePtr values
[] = {&line_layout
};
838 err
= ATSUCreateTextLayoutWithTextPtr (text
,
839 kATSUFromTextBeginning
,
845 err
= ATSUSetLayoutControls (saved_text_layout
,
846 sizeof (tags
) / sizeof (tags
[0]),
847 tags
, sizes
, values
);
848 /* XXX: Should we do this? */
850 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
854 err
= ATSUSetRunStyle (saved_text_layout
, style
,
855 kATSUFromTextBeginning
, kATSUToTextEnd
);
857 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
858 kATSUFromTextBeginning
,
864 *text_layout
= saved_text_layout
;
871 mac_invert_rectangle (f
, x
, y
, width
, height
)
874 unsigned int width
, height
;
879 mac_prepare_for_quickdraw (f
);
881 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
883 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
890 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, bytes_per_char
)
895 int nchars
, bg_width
, bytes_per_char
;
897 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
900 if (GC_FONT (gc
)->mac_style
)
903 ATSUTextLayout text_layout
;
905 xassert (bytes_per_char
== 2);
907 #ifndef WORDS_BIG_ENDIAN
910 UniChar
*text
= (UniChar
*)buf
;
912 for (i
= 0; i
< nchars
; i
++)
913 text
[i
] = EndianU16_BtoN (text
[i
]);
916 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
918 GC_FONT (gc
)->mac_style
,
923 if (!mac_use_core_graphics
)
927 mac_prepare_for_quickdraw (f
);
930 RGBForeColor (GC_FORE_COLOR (gc
));
935 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
936 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
937 RGBBackColor (GC_BACK_COLOR (gc
));
939 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
942 ATSUDrawText (text_layout
,
943 kATSUFromTextBeginning
, kATSUToTextEnd
,
944 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
951 CGContextRef context
;
952 float port_height
= FRAME_PIXEL_HEIGHT (f
);
953 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
954 ByteCount sizes
[] = {sizeof (CGContextRef
)};
955 ATSUAttributeValuePtr values
[] = {&context
};
958 context
= mac_begin_cg_clip (f
, gc
);
961 QDBeginCGContext (port
, &context
);
962 if (gc
->n_clip_rects
|| bg_width
)
964 CGContextTranslateCTM (context
, 0, port_height
);
965 CGContextScaleCTM (context
, 1, -1);
966 if (gc
->n_clip_rects
)
967 CGContextClipToRects (context
, gc
->clip_rects
,
972 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
975 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
976 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
978 CGContextScaleCTM (context
, 1, -1);
979 CGContextTranslateCTM (context
, 0, -port_height
);
983 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
984 err
= ATSUSetLayoutControls (text_layout
,
985 sizeof (tags
) / sizeof (tags
[0]),
986 tags
, sizes
, values
);
988 ATSUDrawText (text_layout
,
989 kATSUFromTextBeginning
, kATSUToTextEnd
,
990 Long2Fix (x
), Long2Fix (port_height
- y
));
995 CGContextSynchronize (context
);
996 QDEndCGContext (port
, &context
);
999 /* This doesn't work on Mac OS X 10.1. */
1000 ATSUClearLayoutControls (text_layout
,
1001 sizeof (tags
) / sizeof (tags
[0]), tags
);
1003 ATSUSetLayoutControls (text_layout
,
1004 sizeof (tags
) / sizeof (tags
[0]),
1005 tags
, sizes
, values
);
1008 #endif /* MAC_OSX */
1011 #endif /* USE_ATSUI */
1013 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1016 if (mac_use_core_graphics
)
1017 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1020 mac_prepare_for_quickdraw (f
);
1022 mac_begin_clip (gc
);
1023 RGBForeColor (GC_FORE_COLOR (gc
));
1027 RGBBackColor (GC_BACK_COLOR (gc
));
1033 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1035 - Screen is double-buffered. (In srcCopy mode, a text is
1036 drawn into an offscreen graphics world first. So
1037 performance gain cannot be expected.)
1038 - It lowers rendering quality.
1039 - Some fonts leave garbage on cursor movement. */
1044 RGBBackColor (GC_BACK_COLOR (gc
));
1045 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1046 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1051 TextFont (GC_FONT (gc
)->mac_fontnum
);
1052 TextSize (GC_FONT (gc
)->mac_fontsize
);
1053 TextFace (GC_FONT (gc
)->mac_fontface
);
1055 DrawText (buf
, 0, nchars
* bytes_per_char
);
1057 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1060 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1061 if (mac_use_core_graphics
)
1062 SwapQDTextFlags(savedFlags
);
1068 /* Mac replacement for XDrawString. */
1071 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
1078 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, 0, 1);
1082 /* Mac replacement for XDrawString16. */
1085 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
1092 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, 0, 2);
1096 /* Mac replacement for XDrawImageString. */
1099 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1104 int nchars
, bg_width
;
1106 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, 1);
1110 /* Mac replacement for XDrawString16. */
1113 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1118 int nchars
, bg_width
;
1120 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
, 2);
1124 /* Mac replacement for XQueryTextExtents, but takes a character. If
1125 STYLE is NULL, measurement is done by QuickDraw Text routines for
1126 the font of the current graphics port. If CG_GLYPH is not NULL,
1127 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1130 mac_query_char_extents (style
, c
,
1131 font_ascent_return
, font_descent_return
,
1132 overall_return
, cg_glyph
)
1139 int *font_ascent_return
, *font_descent_return
;
1140 XCharStruct
*overall_return
;
1141 #if USE_CG_TEXT_DRAWING
1147 OSStatus err
= noErr
;
1154 ATSUTextLayout text_layout
;
1157 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1160 ATSTrapezoid glyph_bounds
;
1162 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1163 kATSUFromTextBeginning
, kATSUToTextEnd
,
1164 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1165 kATSUseFractionalOrigins
,
1167 kATSUseDeviceOrigins
,
1169 1, &glyph_bounds
, NULL
);
1172 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1173 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1175 width
= Fix2Long (glyph_bounds
.upperRight
.x
1176 - glyph_bounds
.upperLeft
.x
);
1177 if (font_ascent_return
)
1178 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1179 if (font_descent_return
)
1180 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1183 if (err
== noErr
&& overall_return
)
1185 err
= ATSUMeasureTextImage (text_layout
,
1186 kATSUFromTextBeginning
, kATSUToTextEnd
,
1187 0, 0, &char_bounds
);
1189 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1190 #if USE_CG_TEXT_DRAWING
1191 if (err
== noErr
&& cg_glyph
)
1194 ATSUGlyphInfoArray glyph_info_array
;
1195 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1197 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1198 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1200 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1201 kATSUToTextEnd
, &count
,
1205 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1206 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1217 if (font_ascent_return
|| font_descent_return
)
1221 GetFontInfo (&font_info
);
1222 if (font_ascent_return
)
1223 *font_ascent_return
= font_info
.ascent
;
1224 if (font_descent_return
)
1225 *font_descent_return
= font_info
.descent
;
1231 width
= CharWidth (ch
);
1232 QDTextBounds (1, &ch
, &char_bounds
);
1233 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1241 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1244 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1245 XFontStruct
*font_struct
;
1248 XCharStruct
*overall_return
;
1251 short width
= 0, lbearing
= 0, rbearing
= 0;
1254 for (i
= 0; i
< nchars
; i
++)
1256 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1258 width
+= FONT_WIDTH (font_struct
);
1261 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1262 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1263 width
+= pcm
->width
;
1268 overall_return
->lbearing
= lbearing
;
1269 overall_return
->rbearing
= rbearing
;
1270 overall_return
->width
= width
;
1272 /* What's the meaning of the return value of XTextExtents16? */
1276 #if USE_CG_TEXT_DRAWING
1277 static int cg_text_anti_aliasing_threshold
= 8;
1280 init_cg_text_anti_aliasing_threshold ()
1286 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1287 kCFPreferencesCurrentApplication
,
1290 cg_text_anti_aliasing_threshold
= threshold
;
1294 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1299 int nchars
, bg_width
;
1302 float port_height
, gx
, gy
;
1304 CGContextRef context
;
1308 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1311 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1312 port_height
= FRAME_PIXEL_HEIGHT (f
);
1314 gy
= port_height
- y
;
1315 glyphs
= (CGGlyph
*)buf
;
1316 advances
= alloca (sizeof (CGSize
) * nchars
);
1317 if (advances
== NULL
)
1319 for (i
= 0; i
< nchars
; i
++)
1321 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1323 advances
[i
].width
= pcm
->width
;
1324 advances
[i
].height
= 0;
1325 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1330 context
= mac_begin_cg_clip (f
, gc
);
1332 QDBeginCGContext (port
, &context
);
1333 if (gc
->n_clip_rects
|| bg_width
)
1335 CGContextTranslateCTM (context
, 0, port_height
);
1336 CGContextScaleCTM (context
, 1, -1);
1337 if (gc
->n_clip_rects
)
1338 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1342 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
1345 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1346 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1348 CGContextScaleCTM (context
, 1, -1);
1349 CGContextTranslateCTM (context
, 0, -port_height
);
1353 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
1354 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1355 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1356 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1357 CGContextSetShouldAntialias (context
, false);
1358 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1359 CGContextSetTextPosition (context
, gx
, gy
);
1360 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1362 for (i
= 0; i
< nchars
; i
++)
1364 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1365 gx
+= advances
[i
].width
;
1369 mac_end_cg_clip (f
);
1371 CGContextSynchronize (context
);
1372 QDEndCGContext (port
, &context
);
1381 /* Mac replacement for XCopyArea: dest must be window. */
1384 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1389 unsigned int width
, height
;
1394 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1396 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1397 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1399 ForeColor (blackColor
);
1400 BackColor (whiteColor
);
1402 mac_begin_clip (gc
);
1403 LockPixels (GetGWorldPixMap (src
));
1404 #if TARGET_API_MAC_CARBON
1409 LockPortBits (port
);
1410 CopyBits (GetPortBitMapForCopyBits (src
),
1411 GetPortBitMapForCopyBits (port
),
1412 &src_r
, &dest_r
, srcCopy
, 0);
1413 UnlockPortBits (port
);
1415 #else /* not TARGET_API_MAC_CARBON */
1416 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1417 &src_r
, &dest_r
, srcCopy
, 0);
1418 #endif /* not TARGET_API_MAC_CARBON */
1419 UnlockPixels (GetGWorldPixMap (src
));
1422 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1427 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1428 width
, height
, dest_x
, dest_y
)
1433 unsigned int width
, height
;
1438 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1440 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1441 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1443 ForeColor (blackColor
);
1444 BackColor (whiteColor
);
1446 mac_begin_clip (gc
);
1447 LockPixels (GetGWorldPixMap (src
));
1448 LockPixels (GetGWorldPixMap (mask
));
1449 #if TARGET_API_MAC_CARBON
1454 LockPortBits (port
);
1455 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1456 GetPortBitMapForCopyBits (port
),
1457 &src_r
, &src_r
, &dest_r
);
1458 UnlockPortBits (port
);
1460 #else /* not TARGET_API_MAC_CARBON */
1461 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1462 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1463 #endif /* not TARGET_API_MAC_CARBON */
1464 UnlockPixels (GetGWorldPixMap (mask
));
1465 UnlockPixels (GetGWorldPixMap (src
));
1468 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1470 #endif /* !USE_CG_DRAWING */
1473 /* Mac replacement for XCopyArea: used only for scrolling. */
1476 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1480 unsigned int width
, height
;
1483 #if TARGET_API_MAC_CARBON
1485 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1487 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1489 mac_prepare_for_quickdraw (f
);
1491 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1492 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1493 kScrollWindowNoOptions
, dummy
);
1495 #else /* not TARGET_API_MAC_CARBON */
1497 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1501 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1502 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1504 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1505 color mapping in CopyBits. Otherwise, it will be slow. */
1506 ForeColor (blackColor
);
1507 BackColor (whiteColor
);
1508 mac_begin_clip (gc
);
1509 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1512 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1513 #endif /* not TARGET_API_MAC_CARBON */
1517 /* Mac replacement for XChangeGC. */
1520 XChangeGC (display
, gc
, mask
, xgcv
)
1526 if (mask
& GCForeground
)
1527 XSetForeground (display
, gc
, xgcv
->foreground
);
1528 if (mask
& GCBackground
)
1529 XSetBackground (display
, gc
, xgcv
->background
);
1531 XSetFont (display
, gc
, xgcv
->font
);
1535 /* Mac replacement for XCreateGC. */
1538 XCreateGC (display
, window
, mask
, xgcv
)
1544 GC gc
= xmalloc (sizeof (*gc
));
1546 bzero (gc
, sizeof (*gc
));
1547 XChangeGC (display
, gc
, mask
, xgcv
);
1553 /* Used in xfaces.c. */
1556 XFreeGC (display
, gc
)
1560 if (gc
->clip_region
)
1561 DisposeRgn (gc
->clip_region
);
1566 /* Mac replacement for XGetGCValues. */
1569 XGetGCValues (display
, gc
, mask
, xgcv
)
1575 if (mask
& GCForeground
)
1576 xgcv
->foreground
= gc
->xgcv
.foreground
;
1577 if (mask
& GCBackground
)
1578 xgcv
->background
= gc
->xgcv
.background
;
1580 xgcv
->font
= gc
->xgcv
.font
;
1584 /* Mac replacement for XSetForeground. */
1587 XSetForeground (display
, gc
, color
)
1590 unsigned long color
;
1592 if (gc
->xgcv
.foreground
!= color
)
1594 gc
->xgcv
.foreground
= color
;
1595 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1596 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1597 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1602 /* Mac replacement for XSetBackground. */
1605 XSetBackground (display
, gc
, color
)
1608 unsigned long color
;
1610 if (gc
->xgcv
.background
!= color
)
1612 gc
->xgcv
.background
= color
;
1613 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1614 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1615 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1620 /* Mac replacement for XSetFont. */
1623 XSetFont (display
, gc
, font
)
1628 gc
->xgcv
.font
= font
;
1632 /* Mac replacement for XSetClipRectangles. */
1635 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1643 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1645 gc
->n_clip_rects
= n
;
1648 if (gc
->clip_region
== NULL
)
1649 gc
->clip_region
= NewRgn ();
1650 RectRgn (gc
->clip_region
, rectangles
);
1653 RgnHandle region
= NewRgn ();
1655 for (i
= 1; i
< n
; i
++)
1657 RectRgn (region
, rectangles
+ i
);
1658 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1660 DisposeRgn (region
);
1663 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1664 for (i
= 0; i
< n
; i
++)
1666 Rect
*rect
= rectangles
+ i
;
1668 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1669 rect
->right
- rect
->left
,
1670 rect
->bottom
- rect
->top
);
1676 /* Mac replacement for XSetClipMask. */
1679 mac_reset_clip_rectangles (display
, gc
)
1683 gc
->n_clip_rects
= 0;
1687 /* Mac replacement for XSetWindowBackground. */
1690 XSetWindowBackground (display
, w
, color
)
1693 unsigned long color
;
1695 #if !TARGET_API_MAC_CARBON
1696 AuxWinHandle aw_handle
;
1697 CTabHandle ctab_handle
;
1698 ColorSpecPtr ct_table
;
1703 bg_color
.red
= RED16_FROM_ULONG (color
);
1704 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1705 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1707 #if TARGET_API_MAC_CARBON
1708 SetWindowContentColor (w
, &bg_color
);
1710 if (GetAuxWin (w
, &aw_handle
))
1712 ctab_handle
= (*aw_handle
)->awCTable
;
1713 HandToHand ((Handle
*) &ctab_handle
);
1714 ct_table
= (*ctab_handle
)->ctTable
;
1715 ct_size
= (*ctab_handle
)->ctSize
;
1716 while (ct_size
> -1)
1718 if (ct_table
->value
== 0)
1720 ct_table
->rgb
= bg_color
;
1721 CTabChanged (ctab_handle
);
1722 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1730 /* Flush display of frame F, or of all frames if F is null. */
1736 #if TARGET_API_MAC_CARBON
1739 mac_prepare_for_quickdraw (f
);
1742 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1744 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1750 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1751 Calls to XFlush should be unnecessary because the X output buffer
1752 is flushed automatically as needed by calls to XPending,
1753 XNextEvent, or XWindowEvent according to the XFlush man page.
1754 XTread_socket calls XPending. Removing XFlush improves
1757 #define XFlush(DISPLAY) (void) 0
1760 /* Return the struct mac_display_info corresponding to DPY. There's
1763 struct mac_display_info
*
1764 mac_display_info_for_display (dpy
)
1767 return &one_mac_display_info
;
1772 /***********************************************************************
1773 Starting and ending an update
1774 ***********************************************************************/
1776 /* Start an update of frame F. This function is installed as a hook
1777 for update_begin, i.e. it is called when update_begin is called.
1778 This function is called prior to calls to x_update_window_begin for
1779 each window being updated. */
1785 #if TARGET_API_MAC_CARBON
1786 /* During update of a frame, availability of input events is
1787 periodically checked with ReceiveNextEvent if
1788 redisplay-dont-pause is nil. That normally flushes window buffer
1789 changes for every check, and thus screen update looks waving even
1790 if no input is available. So we disable screen updates during
1791 update of a frame. */
1793 DisableScreenUpdates ();
1799 /* Start update of window W. Set the global variable updated_window
1800 to the window being updated and set output_cursor to the cursor
1804 x_update_window_begin (w
)
1807 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1808 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1811 set_output_cursor (&w
->cursor
);
1815 if (f
== display_info
->mouse_face_mouse_frame
)
1817 /* Don't do highlighting for mouse motion during the update. */
1818 display_info
->mouse_face_defer
= 1;
1820 /* If F needs to be redrawn, simply forget about any prior mouse
1822 if (FRAME_GARBAGED_P (f
))
1823 display_info
->mouse_face_window
= Qnil
;
1825 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1826 their mouse_face_p flag set, which means that they are always
1827 unequal to rows in a desired matrix which never have that
1828 flag set. So, rows containing mouse-face glyphs are never
1829 scrolled, and we don't have to switch the mouse highlight off
1830 here to prevent it from being scrolled. */
1832 /* Can we tell that this update does not affect the window
1833 where the mouse highlight is? If so, no need to turn off.
1834 Likewise, don't do anything if the frame is garbaged;
1835 in that case, the frame's current matrix that we would use
1836 is all wrong, and we will redisplay that line anyway. */
1837 if (!NILP (display_info
->mouse_face_window
)
1838 && w
== XWINDOW (display_info
->mouse_face_window
))
1842 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1843 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1846 if (i
< w
->desired_matrix
->nrows
)
1847 clear_mouse_face (display_info
);
1856 /* Draw a vertical window border from (x,y0) to (x,y1) */
1859 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1863 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1866 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1868 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1871 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1874 /* End update of window W (which is equal to updated_window).
1876 Draw vertical borders between horizontally adjacent windows, and
1877 display W's cursor if CURSOR_ON_P is non-zero.
1879 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1880 glyphs in mouse-face were overwritten. In that case we have to
1881 make sure that the mouse-highlight is properly redrawn.
1883 W may be a menu bar pseudo-window in case we don't have X toolkit
1884 support. Such windows don't have a cursor, so don't display it
1888 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1890 int cursor_on_p
, mouse_face_overwritten_p
;
1892 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1894 if (!w
->pseudo_window_p
)
1899 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1901 output_cursor
.x
, output_cursor
.y
);
1903 if (draw_window_fringes (w
, 1))
1904 x_draw_vertical_border (w
);
1909 /* If a row with mouse-face was overwritten, arrange for
1910 XTframe_up_to_date to redisplay the mouse highlight. */
1911 if (mouse_face_overwritten_p
)
1913 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1914 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1915 dpyinfo
->mouse_face_window
= Qnil
;
1918 updated_window
= NULL
;
1922 /* End update of frame F. This function is installed as a hook in
1929 /* Mouse highlight may be displayed again. */
1930 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1933 #if TARGET_API_MAC_CARBON
1934 EnableScreenUpdates ();
1936 XFlush (FRAME_MAC_DISPLAY (f
));
1941 /* This function is called from various places in xdisp.c whenever a
1942 complete update has been performed. The global variable
1943 updated_window is not available here. */
1946 XTframe_up_to_date (f
)
1949 if (FRAME_MAC_P (f
))
1951 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1953 if (dpyinfo
->mouse_face_deferred_gc
1954 || f
== dpyinfo
->mouse_face_mouse_frame
)
1957 if (dpyinfo
->mouse_face_mouse_frame
)
1958 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1959 dpyinfo
->mouse_face_mouse_x
,
1960 dpyinfo
->mouse_face_mouse_y
);
1961 dpyinfo
->mouse_face_deferred_gc
= 0;
1968 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1969 arrow bitmaps, or clear the fringes if no bitmaps are required
1970 before DESIRED_ROW is made current. The window being updated is
1971 found in updated_window. This function is called from
1972 update_window_line only if it is known that there are differences
1973 between bitmaps to be drawn between current row and DESIRED_ROW. */
1976 x_after_update_window_line (desired_row
)
1977 struct glyph_row
*desired_row
;
1979 struct window
*w
= updated_window
;
1985 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1986 desired_row
->redraw_fringe_bitmaps_p
= 1;
1988 /* When a window has disappeared, make sure that no rest of
1989 full-width rows stays visible in the internal border. Could
1990 check here if updated_window is the leftmost/rightmost window,
1991 but I guess it's not worth doing since vertically split windows
1992 are almost never used, internal border is rarely set, and the
1993 overhead is very small. */
1994 if (windows_or_buffers_changed
1995 && desired_row
->full_width_p
1996 && (f
= XFRAME (w
->frame
),
1997 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1999 && (height
= desired_row
->visible_height
,
2002 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2004 /* Internal border is drawn below the tool bar. */
2005 if (WINDOWP (f
->tool_bar_window
)
2006 && w
== XWINDOW (f
->tool_bar_window
))
2010 mac_clear_area (f
, 0, y
, width
, height
);
2011 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2017 /* Draw the bitmap WHICH in one of the left or right fringes of
2018 window W. ROW is the glyph row for which to display the bitmap; it
2019 determines the vertical position at which the bitmap has to be
2023 x_draw_fringe_bitmap (w
, row
, p
)
2025 struct glyph_row
*row
;
2026 struct draw_fringe_bitmap_params
*p
;
2028 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2029 Display
*display
= FRAME_MAC_DISPLAY (f
);
2030 struct face
*face
= p
->face
;
2033 /* Must clip because of partially visible lines. */
2034 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2037 /* Adjust position of "bottom aligned" bitmap on partially
2038 visible last row. */
2040 int oldVH
= row
->visible_height
;
2041 row
->visible_height
= p
->h
;
2042 row
->y
-= rowY
- p
->y
;
2043 x_clip_to_row (w
, row
, -1, face
->gc
);
2045 row
->visible_height
= oldVH
;
2048 x_clip_to_row (w
, row
, -1, face
->gc
);
2050 if (p
->bx
>= 0 && !p
->overlay_p
)
2052 #if 0 /* MAC_TODO: stipple */
2053 /* In case the same realized face is used for fringes and
2054 for something displayed in the text (e.g. face `region' on
2055 mono-displays, the fill style may have been changed to
2056 FillSolid in x_draw_glyph_string_background. */
2058 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2060 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2063 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2065 #if 0 /* MAC_TODO: stipple */
2067 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2073 && p
->which
< max_fringe_bmp
2079 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2080 XSetForeground (display
, face
->gc
,
2082 ? (p
->overlay_p
? face
->background
2083 : f
->output_data
.mac
->cursor_pixel
)
2084 : face
->foreground
));
2086 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2087 p
->wd
, p
->h
, p
->x
, p
->y
, p
->overlay_p
);
2089 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2090 p
->wd
, p
->h
, p
->bits
+ p
->dh
, p
->overlay_p
);
2092 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2095 mac_reset_clip_rectangles (display
, face
->gc
);
2100 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2102 unsigned short *bits
;
2106 CGDataProviderRef provider
;
2108 if (which
>= max_fringe_bmp
)
2111 max_fringe_bmp
= which
+ 20;
2112 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2113 while (i
< max_fringe_bmp
)
2114 fringe_bmp
[i
++] = 0;
2117 for (i
= 0; i
< h
; i
++)
2119 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2120 sizeof (unsigned short) * h
, NULL
);
2123 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2124 sizeof (unsigned short),
2126 CGDataProviderRelease (provider
);
2131 mac_destroy_fringe_bitmap (which
)
2134 if (which
>= max_fringe_bmp
)
2137 if (fringe_bmp
[which
])
2138 CGImageRelease (fringe_bmp
[which
]);
2139 fringe_bmp
[which
] = 0;
2144 /* This is called when starting Emacs and when restarting after
2145 suspend. When starting Emacs, no window is mapped. And nothing
2146 must be done to Emacs's own window if it is suspended (though that
2150 XTset_terminal_modes ()
2154 /* This is called when exiting or suspending Emacs. Exiting will make
2155 the windows go away, and suspending requires no action. */
2158 XTreset_terminal_modes ()
2164 /***********************************************************************
2166 ***********************************************************************/
2168 /* Function prototypes of this page. */
2170 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2171 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2175 pcm_init (pcm
, count
)
2179 bzero (pcm
, sizeof (XCharStruct
) * count
);
2180 while (--count
>= 0)
2182 pcm
->descent
= PCM_INVALID
;
2187 static enum pcm_status
2188 pcm_get_status (pcm
)
2191 int height
= pcm
->ascent
+ pcm
->descent
;
2193 /* Negative height means some special status. */
2194 return height
>= 0 ? PCM_VALID
: height
;
2197 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2198 is not contained in the font. */
2200 static INLINE XCharStruct
*
2201 x_per_char_metric (font
, char2b
)
2205 /* The result metric information. */
2206 XCharStruct
*pcm
= NULL
;
2208 xassert (font
&& char2b
);
2211 if (font
->mac_style
)
2213 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2217 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2218 pcm_init (*row
, 0x100);
2220 pcm
= *row
+ char2b
->byte2
;
2221 if (pcm_get_status (pcm
) != PCM_VALID
)
2224 mac_query_char_extents (font
->mac_style
,
2225 (char2b
->byte1
<< 8) + char2b
->byte2
,
2226 NULL
, NULL
, pcm
, NULL
);
2233 if (font
->bounds
.per_char
!= NULL
)
2235 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2237 /* min_char_or_byte2 specifies the linear character index
2238 corresponding to the first element of the per_char array,
2239 max_char_or_byte2 is the index of the last character. A
2240 character with non-zero CHAR2B->byte1 is not in the font.
2241 A character with byte2 less than min_char_or_byte2 or
2242 greater max_char_or_byte2 is not in the font. */
2243 if (char2b
->byte1
== 0
2244 && char2b
->byte2
>= font
->min_char_or_byte2
2245 && char2b
->byte2
<= font
->max_char_or_byte2
)
2246 pcm
= font
->bounds
.per_char
2247 + (char2b
->byte2
- font
->min_char_or_byte2
);
2251 /* If either min_byte1 or max_byte1 are nonzero, both
2252 min_char_or_byte2 and max_char_or_byte2 are less than
2253 256, and the 2-byte character index values corresponding
2254 to the per_char array element N (counting from 0) are:
2256 byte1 = N/D + min_byte1
2257 byte2 = N\D + min_char_or_byte2
2261 D = max_char_or_byte2 - min_char_or_byte2 + 1
2262 / = integer division
2263 \ = integer modulus */
2264 if (char2b
->byte1
>= font
->min_byte1
2265 && char2b
->byte1
<= font
->max_byte1
2266 && char2b
->byte2
>= font
->min_char_or_byte2
2267 && char2b
->byte2
<= font
->max_char_or_byte2
)
2269 pcm
= (font
->bounds
.per_char
2270 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2271 * (char2b
->byte1
- font
->min_byte1
))
2272 + (char2b
->byte2
- font
->min_char_or_byte2
));
2278 /* If the per_char pointer is null, all glyphs between the first
2279 and last character indexes inclusive have the same
2280 information, as given by both min_bounds and max_bounds. */
2281 if (char2b
->byte2
>= font
->min_char_or_byte2
2282 && char2b
->byte2
<= font
->max_char_or_byte2
)
2283 pcm
= &font
->max_bounds
;
2289 return ((pcm
== NULL
2291 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2292 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2301 static XCharStruct
*
2302 mac_per_char_metric (font
, char2b
, font_type
)
2307 return x_per_char_metric (font
, char2b
);
2311 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2312 the two-byte form of C. Encoding is returned in *CHAR2B. */
2315 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2318 struct font_info
*font_info
;
2321 int charset
= CHAR_CHARSET (c
);
2322 XFontStruct
*font
= font_info
->font
;
2324 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2325 This may be either a program in a special encoder language or a
2327 if (font_info
->font_encoder
)
2329 /* It's a program. */
2330 struct ccl_program
*ccl
= font_info
->font_encoder
;
2332 check_ccl_update (ccl
);
2333 if (CHARSET_DIMENSION (charset
) == 1)
2335 ccl
->reg
[0] = charset
;
2336 ccl
->reg
[1] = char2b
->byte2
;
2341 ccl
->reg
[0] = charset
;
2342 ccl
->reg
[1] = char2b
->byte1
;
2343 ccl
->reg
[2] = char2b
->byte2
;
2346 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2348 /* We assume that MSBs are appropriately set/reset by CCL
2350 if (font
->max_byte1
== 0) /* 1-byte font */
2351 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2353 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2355 else if (font_info
->encoding
[charset
])
2357 /* Fixed encoding scheme. See fontset.h for the meaning of the
2358 encoding numbers. */
2359 int enc
= font_info
->encoding
[charset
];
2361 if ((enc
== 1 || enc
== 2)
2362 && CHARSET_DIMENSION (charset
) == 2)
2363 char2b
->byte1
|= 0x80;
2365 if (enc
== 1 || enc
== 3)
2366 char2b
->byte2
|= 0x80;
2372 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2373 char2b
->byte1
= sjis1
;
2374 char2b
->byte2
= sjis2
;
2379 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2381 return FONT_TYPE_UNKNOWN
;
2386 /***********************************************************************
2388 ***********************************************************************/
2392 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2393 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2394 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2396 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2397 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2398 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2399 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2400 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2401 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2402 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2403 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2404 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2405 unsigned long *, double, int));*/
2406 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2407 double, int, unsigned long));
2408 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2409 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2410 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2411 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2412 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2414 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2415 int, int, int, int, int, int,
2417 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2418 int, int, int, Rect
*));
2421 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2425 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2430 struct glyph_string
*s
;
2432 if (s
->font
== FRAME_FONT (s
->f
)
2433 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2434 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2436 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2439 /* Cursor on non-default face: must merge. */
2443 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2444 xgcv
.foreground
= s
->face
->background
;
2446 /* If the glyph would be invisible, try a different foreground. */
2447 if (xgcv
.foreground
== xgcv
.background
)
2448 xgcv
.foreground
= s
->face
->foreground
;
2449 if (xgcv
.foreground
== xgcv
.background
)
2450 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2451 if (xgcv
.foreground
== xgcv
.background
)
2452 xgcv
.foreground
= s
->face
->foreground
;
2454 /* Make sure the cursor is distinct from text in this face. */
2455 if (xgcv
.background
== s
->face
->background
2456 && xgcv
.foreground
== s
->face
->foreground
)
2458 xgcv
.background
= s
->face
->foreground
;
2459 xgcv
.foreground
= s
->face
->background
;
2462 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2463 xgcv
.font
= s
->font
;
2464 mask
= GCForeground
| GCBackground
| GCFont
;
2466 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2467 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2470 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2471 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2473 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2478 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2481 x_set_mouse_face_gc (s
)
2482 struct glyph_string
*s
;
2487 /* What face has to be used last for the mouse face? */
2488 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2489 face
= FACE_FROM_ID (s
->f
, face_id
);
2491 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2493 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2494 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2496 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2497 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2498 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2500 /* If font in this face is same as S->font, use it. */
2501 if (s
->font
== s
->face
->font
)
2502 s
->gc
= s
->face
->gc
;
2505 /* Otherwise construct scratch_cursor_gc with values from FACE
2510 xgcv
.background
= s
->face
->background
;
2511 xgcv
.foreground
= s
->face
->foreground
;
2512 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2513 xgcv
.font
= s
->font
;
2514 mask
= GCForeground
| GCBackground
| GCFont
;
2516 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2517 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2520 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2521 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2523 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2526 xassert (s
->gc
!= 0);
2530 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2531 Faces to use in the mode line have already been computed when the
2532 matrix was built, so there isn't much to do, here. */
2535 x_set_mode_line_face_gc (s
)
2536 struct glyph_string
*s
;
2538 s
->gc
= s
->face
->gc
;
2542 /* Set S->gc of glyph string S for drawing that glyph string. Set
2543 S->stippled_p to a non-zero value if the face of S has a stipple
2547 x_set_glyph_string_gc (s
)
2548 struct glyph_string
*s
;
2550 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2552 if (s
->hl
== DRAW_NORMAL_TEXT
)
2554 s
->gc
= s
->face
->gc
;
2555 s
->stippled_p
= s
->face
->stipple
!= 0;
2557 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2559 x_set_mode_line_face_gc (s
);
2560 s
->stippled_p
= s
->face
->stipple
!= 0;
2562 else if (s
->hl
== DRAW_CURSOR
)
2564 x_set_cursor_gc (s
);
2567 else if (s
->hl
== DRAW_MOUSE_FACE
)
2569 x_set_mouse_face_gc (s
);
2570 s
->stippled_p
= s
->face
->stipple
!= 0;
2572 else if (s
->hl
== DRAW_IMAGE_RAISED
2573 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2575 s
->gc
= s
->face
->gc
;
2576 s
->stippled_p
= s
->face
->stipple
!= 0;
2580 s
->gc
= s
->face
->gc
;
2581 s
->stippled_p
= s
->face
->stipple
!= 0;
2584 /* GC must have been set. */
2585 xassert (s
->gc
!= 0);
2589 /* Set clipping for output of glyph string S. S may be part of a mode
2590 line or menu if we don't have X toolkit support. */
2593 x_set_glyph_string_clipping (s
)
2594 struct glyph_string
*s
;
2596 Rect rects
[MAX_CLIP_RECTS
];
2599 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2600 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2605 Compute left and right overhang of glyph string S. If S is a glyph
2606 string for a composition, assume overhangs don't exist. */
2609 mac_compute_glyph_string_overhangs (s
)
2610 struct glyph_string
*s
;
2612 if (!(s
->cmp
== NULL
2613 && s
->first_glyph
->type
== CHAR_GLYPH
))
2618 || s
->font
->mac_style
2624 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2625 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2626 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2631 MacFontStruct
*font
= s
->font
;
2633 TextFont (font
->mac_fontnum
);
2634 TextSize (font
->mac_fontsize
);
2635 TextFace (font
->mac_fontface
);
2637 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2639 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2640 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2645 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2648 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2649 struct glyph_string
*s
;
2652 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2656 /* Draw the background of glyph_string S. If S->background_filled_p
2657 is non-zero don't draw it. FORCE_P non-zero means draw the
2658 background even if it wouldn't be drawn normally. This is used
2659 when a string preceding S draws into the background of S, or S
2660 contains the first component of a composition. */
2663 x_draw_glyph_string_background (s
, force_p
)
2664 struct glyph_string
*s
;
2667 /* Nothing to do if background has already been drawn or if it
2668 shouldn't be drawn in the first place. */
2669 if (!s
->background_filled_p
)
2671 int box_line_width
= max (s
->face
->box_line_width
, 0);
2673 #if 0 /* MAC_TODO: stipple */
2676 /* Fill background with a stipple pattern. */
2677 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2678 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2679 s
->y
+ box_line_width
,
2680 s
->background_width
,
2681 s
->height
- 2 * box_line_width
);
2682 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2683 s
->background_filled_p
= 1;
2687 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2688 || s
->font_not_found_p
2689 || s
->extends_to_end_of_line_p
2692 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2693 s
->background_width
,
2694 s
->height
- 2 * box_line_width
);
2695 s
->background_filled_p
= 1;
2701 /* Draw the foreground of glyph string S. */
2704 x_draw_glyph_string_foreground (s
)
2705 struct glyph_string
*s
;
2709 /* If first glyph of S has a left box line, start drawing the text
2710 of S to the right of that box line. */
2711 if (s
->face
->box
!= FACE_NO_BOX
2712 && s
->first_glyph
->left_box_line_p
)
2713 x
= s
->x
+ abs (s
->face
->box_line_width
);
2717 /* Draw characters of S as rectangles if S's font could not be
2719 if (s
->font_not_found_p
)
2721 for (i
= 0; i
< s
->nchars
; ++i
)
2723 struct glyph
*g
= s
->first_glyph
+ i
;
2724 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2725 g
->pixel_width
- 1, s
->height
- 1);
2726 x
+= g
->pixel_width
;
2731 char *char1b
= (char *) s
->char2b
;
2732 int boff
= s
->font_info
->baseline_offset
;
2734 if (s
->font_info
->vertical_centering
)
2735 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2737 /* If we can use 8-bit functions, condense S->char2b. */
2740 && GC_FONT (s
->gc
)->mac_style
== NULL
2743 for (i
= 0; i
< s
->nchars
; ++i
)
2744 char1b
[i
] = s
->char2b
[i
].byte2
;
2746 /* Draw text with XDrawString if background has already been
2747 filled. Otherwise, use XDrawImageString. (Note that
2748 XDrawImageString is usually faster than XDrawString.) Always
2749 use XDrawImageString when drawing the cursor so that there is
2750 no chance that characters under a box cursor are invisible. */
2752 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2753 bg_width
= 0; /* Corresponds to XDrawString. */
2755 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2759 || GC_FONT (s
->gc
)->mac_style
2762 #if USE_CG_TEXT_DRAWING
2764 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2765 s
->char2b
, s
->nchars
, bg_width
))
2769 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2770 s
->char2b
, s
->nchars
, bg_width
);
2772 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2773 char1b
, s
->nchars
, bg_width
);
2777 /* Draw the foreground of composite glyph string S. */
2780 x_draw_composite_glyph_string_foreground (s
)
2781 struct glyph_string
*s
;
2785 /* If first glyph of S has a left box line, start drawing the text
2786 of S to the right of that box line. */
2787 if (s
->face
->box
!= FACE_NO_BOX
2788 && s
->first_glyph
->left_box_line_p
)
2789 x
= s
->x
+ abs (s
->face
->box_line_width
);
2793 /* S is a glyph string for a composition. S->gidx is the index of
2794 the first character drawn for glyphs of this composition.
2795 S->gidx == 0 means we are drawing the very first character of
2796 this composition. */
2798 /* Draw a rectangle for the composition if the font for the very
2799 first character of the composition could not be loaded. */
2800 if (s
->font_not_found_p
)
2803 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2804 s
->width
- 1, s
->height
- 1);
2808 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2809 mac_draw_string_16 (s
->f
, s
->gc
,
2810 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2811 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2817 #ifdef USE_X_TOOLKIT
2819 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2822 /* Return the frame on which widget WIDGET is used.. Abort if frame
2823 cannot be determined. */
2825 static struct frame
*
2826 x_frame_of_widget (widget
)
2829 struct x_display_info
*dpyinfo
;
2833 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2835 /* Find the top-level shell of the widget. Note that this function
2836 can be called when the widget is not yet realized, so XtWindow
2837 (widget) == 0. That's the reason we can't simply use
2838 x_any_window_to_frame. */
2839 while (!XtIsTopLevelShell (widget
))
2840 widget
= XtParent (widget
);
2842 /* Look for a frame with that top-level widget. Allocate the color
2843 on that frame to get the right gamma correction value. */
2844 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2845 if (GC_FRAMEP (XCAR (tail
))
2846 && (f
= XFRAME (XCAR (tail
)),
2847 (f
->output_data
.nothing
!= 1
2848 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2849 && f
->output_data
.x
->widget
== widget
)
2856 /* Allocate the color COLOR->pixel on the screen and display of
2857 widget WIDGET in colormap CMAP. If an exact match cannot be
2858 allocated, try the nearest color available. Value is non-zero
2859 if successful. This is called from lwlib. */
2862 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2867 struct frame
*f
= x_frame_of_widget (widget
);
2868 return x_alloc_nearest_color (f
, cmap
, color
);
2872 #endif /* USE_X_TOOLKIT */
2874 #if 0 /* MAC_TODO */
2876 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2877 CMAP. If an exact match can't be allocated, try the nearest color
2878 available. Value is non-zero if successful. Set *COLOR to the
2882 x_alloc_nearest_color (f
, cmap
, color
)
2887 Display
*display
= FRAME_X_DISPLAY (f
);
2888 Screen
*screen
= FRAME_X_SCREEN (f
);
2891 gamma_correct (f
, color
);
2892 rc
= XAllocColor (display
, cmap
, color
);
2895 /* If we got to this point, the colormap is full, so we're going
2896 to try to get the next closest color. The algorithm used is
2897 a least-squares matching, which is what X uses for closest
2898 color matching with StaticColor visuals. */
2900 unsigned long nearest_delta
= ~0;
2901 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2902 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2904 for (i
= 0; i
< ncells
; ++i
)
2906 XQueryColors (display
, cmap
, cells
, ncells
);
2908 for (nearest
= i
= 0; i
< ncells
; ++i
)
2910 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2911 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2912 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2913 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2915 if (delta
< nearest_delta
)
2918 nearest_delta
= delta
;
2922 color
->red
= cells
[nearest
].red
;
2923 color
->green
= cells
[nearest
].green
;
2924 color
->blue
= cells
[nearest
].blue
;
2925 rc
= XAllocColor (display
, cmap
, color
);
2928 #ifdef DEBUG_X_COLORS
2930 register_color (color
->pixel
);
2931 #endif /* DEBUG_X_COLORS */
2937 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2938 It's necessary to do this instead of just using PIXEL directly to
2939 get color reference counts right. */
2942 x_copy_color (f
, pixel
)
2944 unsigned long pixel
;
2948 color
.pixel
= pixel
;
2950 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2951 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2953 #ifdef DEBUG_X_COLORS
2954 register_color (pixel
);
2960 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2961 It's necessary to do this instead of just using PIXEL directly to
2962 get color reference counts right. */
2965 x_copy_dpy_color (dpy
, cmap
, pixel
)
2968 unsigned long pixel
;
2972 color
.pixel
= pixel
;
2974 XQueryColor (dpy
, cmap
, &color
);
2975 XAllocColor (dpy
, cmap
, &color
);
2977 #ifdef DEBUG_X_COLORS
2978 register_color (pixel
);
2983 #endif /* MAC_TODO */
2986 /* Brightness beyond which a color won't have its highlight brightness
2989 Nominally, highlight colors for `3d' faces are calculated by
2990 brightening an object's color by a constant scale factor, but this
2991 doesn't yield good results for dark colors, so for colors who's
2992 brightness is less than this value (on a scale of 0-255) have to
2993 use an additional additive factor.
2995 The value here is set so that the default menu-bar/mode-line color
2996 (grey75) will not have its highlights changed at all. */
2997 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3000 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3001 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3002 If this produces the same color as COLOR, try a color where all RGB
3003 values have DELTA added. Return the allocated color in *COLOR.
3004 DISPLAY is the X display, CMAP is the colormap to operate on.
3005 Value is non-zero if successful. */
3008 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3010 unsigned long *color
;
3017 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3020 /* Change RGB values by specified FACTOR. Avoid overflow! */
3021 xassert (factor
>= 0);
3022 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3023 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3024 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3026 /* Calculate brightness of COLOR. */
3027 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3028 + BLUE_FROM_ULONG (*color
)) / 6;
3030 /* We only boost colors that are darker than
3031 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3032 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3033 /* Make an additive adjustment to NEW, because it's dark enough so
3034 that scaling by FACTOR alone isn't enough. */
3036 /* How far below the limit this color is (0 - 1, 1 being darker). */
3037 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3038 /* The additive adjustment. */
3039 int min_delta
= delta
* dimness
* factor
/ 2;
3042 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3043 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3044 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3046 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3047 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3048 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3052 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3053 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3054 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3056 /* MAC_TODO: Map to palette and retry with delta if same? */
3057 /* MAC_TODO: Free colors (if using palette)? */
3068 /* Set up the foreground color for drawing relief lines of glyph
3069 string S. RELIEF is a pointer to a struct relief containing the GC
3070 with which lines will be drawn. Use a color that is FACTOR or
3071 DELTA lighter or darker than the relief's background which is found
3072 in S->f->output_data.x->relief_background. If such a color cannot
3073 be allocated, use DEFAULT_PIXEL, instead. */
3076 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3078 struct relief
*relief
;
3081 unsigned long default_pixel
;
3084 struct mac_output
*di
= f
->output_data
.mac
;
3085 unsigned long mask
= GCForeground
;
3086 unsigned long pixel
;
3087 unsigned long background
= di
->relief_background
;
3088 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3090 /* MAC_TODO: Free colors (if using palette)? */
3092 /* Allocate new color. */
3093 xgcv
.foreground
= default_pixel
;
3095 if (dpyinfo
->n_planes
!= 1
3096 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3098 relief
->allocated_p
= 1;
3099 xgcv
.foreground
= relief
->pixel
= pixel
;
3102 if (relief
->gc
== 0)
3104 #if 0 /* MAC_TODO: stipple */
3105 xgcv
.stipple
= dpyinfo
->gray
;
3108 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3111 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3115 /* Set up colors for the relief lines around glyph string S. */
3118 x_setup_relief_colors (s
)
3119 struct glyph_string
*s
;
3121 struct mac_output
*di
= s
->f
->output_data
.mac
;
3122 unsigned long color
;
3124 if (s
->face
->use_box_color_for_shadows_p
)
3125 color
= s
->face
->box_color
;
3126 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3128 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3129 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3134 /* Get the background color of the face. */
3135 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3136 color
= xgcv
.background
;
3139 if (di
->white_relief
.gc
== 0
3140 || color
!= di
->relief_background
)
3142 di
->relief_background
= color
;
3143 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3144 WHITE_PIX_DEFAULT (s
->f
));
3145 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3146 BLACK_PIX_DEFAULT (s
->f
));
3151 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3152 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3153 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3154 relief. LEFT_P non-zero means draw a relief on the left side of
3155 the rectangle. RIGHT_P non-zero means draw a relief on the right
3156 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3160 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3161 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3163 int left_x
, top_y
, right_x
, bottom_y
, width
;
3164 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3167 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3172 gc
= f
->output_data
.mac
->white_relief
.gc
;
3174 gc
= f
->output_data
.mac
->black_relief
.gc
;
3175 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3179 for (i
= 0; i
< width
; ++i
)
3180 mac_draw_line (f
, gc
,
3181 left_x
+ i
* left_p
, top_y
+ i
,
3182 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3186 for (i
= 0; i
< width
; ++i
)
3187 mac_draw_line (f
, gc
,
3188 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3190 mac_reset_clip_rectangles (dpy
, gc
);
3192 gc
= f
->output_data
.mac
->black_relief
.gc
;
3194 gc
= f
->output_data
.mac
->white_relief
.gc
;
3195 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3199 for (i
= 0; i
< width
; ++i
)
3200 mac_draw_line (f
, gc
,
3201 left_x
+ i
* left_p
, bottom_y
- i
,
3202 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3206 for (i
= 0; i
< width
; ++i
)
3207 mac_draw_line (f
, gc
,
3208 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3210 mac_reset_clip_rectangles (dpy
, gc
);
3214 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3215 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3216 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3217 left side of the rectangle. RIGHT_P non-zero means draw a line
3218 on the right side of the rectangle. CLIP_RECT is the clipping
3219 rectangle to use when drawing. */
3222 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3223 left_p
, right_p
, clip_rect
)
3224 struct glyph_string
*s
;
3225 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3230 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3231 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3232 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3235 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3236 right_x
- left_x
+ 1, width
);
3240 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3241 width
, bottom_y
- top_y
+ 1);
3244 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3245 right_x
- left_x
+ 1, width
);
3249 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3250 top_y
, width
, bottom_y
- top_y
+ 1);
3252 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3253 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3257 /* Draw a box around glyph string S. */
3260 x_draw_glyph_string_box (s
)
3261 struct glyph_string
*s
;
3263 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3264 int left_p
, right_p
;
3265 struct glyph
*last_glyph
;
3268 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3269 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3270 : window_box_right (s
->w
, s
->area
));
3272 /* The glyph that may have a right box line. */
3273 last_glyph
= (s
->cmp
|| s
->img
3275 : s
->first_glyph
+ s
->nchars
- 1);
3277 width
= abs (s
->face
->box_line_width
);
3278 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3280 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3282 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3284 bottom_y
= top_y
+ s
->height
- 1;
3286 left_p
= (s
->first_glyph
->left_box_line_p
3287 || (s
->hl
== DRAW_MOUSE_FACE
3289 || s
->prev
->hl
!= s
->hl
)));
3290 right_p
= (last_glyph
->right_box_line_p
3291 || (s
->hl
== DRAW_MOUSE_FACE
3293 || s
->next
->hl
!= s
->hl
)));
3295 get_glyph_string_clip_rect (s
, &clip_rect
);
3297 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3298 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3299 left_p
, right_p
, &clip_rect
);
3302 x_setup_relief_colors (s
);
3303 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3304 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3309 /* Draw foreground of image glyph string S. */
3312 x_draw_image_foreground (s
)
3313 struct glyph_string
*s
;
3316 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3318 /* If first glyph of S has a left box line, start drawing it to the
3319 right of that line. */
3320 if (s
->face
->box
!= FACE_NO_BOX
3321 && s
->first_glyph
->left_box_line_p
3323 x
+= abs (s
->face
->box_line_width
);
3325 /* If there is a margin around the image, adjust x- and y-position
3327 if (s
->slice
.x
== 0)
3328 x
+= s
->img
->hmargin
;
3329 if (s
->slice
.y
== 0)
3330 y
+= s
->img
->vmargin
;
3334 x_set_glyph_string_clipping (s
);
3337 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3338 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3339 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3343 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3344 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3345 s
->slice
.width
, s
->slice
.height
, x
, y
);
3352 mac_copy_area (s
->img
->pixmap
,
3353 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3354 s
->slice
.width
, s
->slice
.height
, x
, y
);
3357 /* When the image has a mask, we can expect that at
3358 least part of a mouse highlight or a block cursor will
3359 be visible. If the image doesn't have a mask, make
3360 a block cursor visible by drawing a rectangle around
3361 the image. I believe it's looking better if we do
3362 nothing here for mouse-face. */
3363 if (s
->hl
== DRAW_CURSOR
)
3365 int r
= s
->img
->relief
;
3367 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3368 s
->slice
.width
+ r
*2 - 1,
3369 s
->slice
.height
+ r
*2 - 1);
3374 /* Draw a rectangle if image could not be loaded. */
3375 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3376 s
->slice
.width
- 1, s
->slice
.height
- 1);
3380 /* Draw a relief around the image glyph string S. */
3383 x_draw_image_relief (s
)
3384 struct glyph_string
*s
;
3386 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3389 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3391 /* If first glyph of S has a left box line, start drawing it to the
3392 right of that line. */
3393 if (s
->face
->box
!= FACE_NO_BOX
3394 && s
->first_glyph
->left_box_line_p
3396 x
+= abs (s
->face
->box_line_width
);
3398 /* If there is a margin around the image, adjust x- and y-position
3400 if (s
->slice
.x
== 0)
3401 x
+= s
->img
->hmargin
;
3402 if (s
->slice
.y
== 0)
3403 y
+= s
->img
->vmargin
;
3405 if (s
->hl
== DRAW_IMAGE_SUNKEN
3406 || s
->hl
== DRAW_IMAGE_RAISED
)
3408 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3409 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3413 thick
= abs (s
->img
->relief
);
3414 raised_p
= s
->img
->relief
> 0;
3419 x1
= x
+ s
->slice
.width
+ thick
- 1;
3420 y1
= y
+ s
->slice
.height
+ thick
- 1;
3422 x_setup_relief_colors (s
);
3423 get_glyph_string_clip_rect (s
, &r
);
3424 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3426 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3428 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3433 /* Draw part of the background of glyph string S. X, Y, W, and H
3434 give the rectangle to draw. */
3437 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3438 struct glyph_string
*s
;
3441 #if 0 /* MAC_TODO: stipple */
3444 /* Fill background with a stipple pattern. */
3445 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3446 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3447 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3450 #endif /* MAC_TODO */
3451 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3455 /* Draw image glyph string S.
3458 s->x +-------------------------
3461 | +-------------------------
3464 | | +-------------------
3470 x_draw_image_glyph_string (s
)
3471 struct glyph_string
*s
;
3474 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3475 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3478 height
= s
->height
- 2 * box_line_vwidth
;
3481 /* Fill background with face under the image. Do it only if row is
3482 taller than image or if image has a clip mask to reduce
3484 s
->stippled_p
= s
->face
->stipple
!= 0;
3485 if (height
> s
->slice
.height
3489 || s
->img
->pixmap
== 0
3490 || s
->width
!= s
->background_width
)
3493 if (s
->first_glyph
->left_box_line_p
3495 x
+= box_line_hwidth
;
3498 if (s
->slice
.y
== 0)
3499 y
+= box_line_vwidth
;
3501 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3503 s
->background_filled_p
= 1;
3506 /* Draw the foreground. */
3507 x_draw_image_foreground (s
);
3509 /* If we must draw a relief around the image, do it. */
3511 || s
->hl
== DRAW_IMAGE_RAISED
3512 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3513 x_draw_image_relief (s
);
3517 /* Draw stretch glyph string S. */
3520 x_draw_stretch_glyph_string (s
)
3521 struct glyph_string
*s
;
3523 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3524 s
->stippled_p
= s
->face
->stipple
!= 0;
3526 if (s
->hl
== DRAW_CURSOR
3527 && !x_stretch_cursor_p
)
3529 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3530 as wide as the stretch glyph. */
3531 int width
, background_width
= s
->background_width
;
3532 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3536 background_width
-= left_x
- x
;
3539 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3542 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3544 /* Clear rest using the GC of the original non-cursor face. */
3545 if (width
< background_width
)
3548 int w
= background_width
- width
, h
= s
->height
;
3553 if (s
->row
->mouse_face_p
3554 && cursor_in_mouse_face_p (s
->w
))
3556 x_set_mouse_face_gc (s
);
3562 get_glyph_string_clip_rect (s
, &r
);
3563 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3565 #if 0 /* MAC_TODO: stipple */
3566 if (s
->face
->stipple
)
3568 /* Fill background with a stipple pattern. */
3569 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3570 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3571 XSetFillStyle (s
->display
, gc
, FillSolid
);
3574 #endif /* MAC_TODO */
3575 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3578 else if (!s
->background_filled_p
)
3580 int background_width
= s
->background_width
;
3581 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3583 /* Don't draw into left margin, fringe or scrollbar area
3584 except for header line and mode line. */
3585 if (x
< left_x
&& !s
->row
->mode_line_p
)
3587 background_width
-= left_x
- x
;
3590 if (background_width
> 0)
3591 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3594 s
->background_filled_p
= 1;
3598 /* Draw glyph string S. */
3601 x_draw_glyph_string (s
)
3602 struct glyph_string
*s
;
3604 int relief_drawn_p
= 0;
3606 /* If S draws into the background of its successor that does not
3607 draw a cursor, draw the background of the successor first so that
3608 S can draw into it. This makes S->next use XDrawString instead
3609 of XDrawImageString. */
3610 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3611 && s
->next
->hl
!= DRAW_CURSOR
)
3613 xassert (s
->next
->img
== NULL
);
3614 x_set_glyph_string_gc (s
->next
);
3615 x_set_glyph_string_clipping (s
->next
);
3616 x_draw_glyph_string_background (s
->next
, 1);
3619 /* Set up S->gc, set clipping and draw S. */
3620 x_set_glyph_string_gc (s
);
3622 /* Draw relief (if any) in advance for char/composition so that the
3623 glyph string can be drawn over it. */
3624 if (!s
->for_overlaps
3625 && s
->face
->box
!= FACE_NO_BOX
3626 && (s
->first_glyph
->type
== CHAR_GLYPH
3627 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3630 x_set_glyph_string_clipping (s
);
3631 x_draw_glyph_string_background (s
, 1);
3632 x_draw_glyph_string_box (s
);
3633 x_set_glyph_string_clipping (s
);
3637 x_set_glyph_string_clipping (s
);
3639 switch (s
->first_glyph
->type
)
3642 x_draw_image_glyph_string (s
);
3646 x_draw_stretch_glyph_string (s
);
3650 if (s
->for_overlaps
)
3651 s
->background_filled_p
= 1;
3653 x_draw_glyph_string_background (s
, 0);
3654 x_draw_glyph_string_foreground (s
);
3657 case COMPOSITE_GLYPH
:
3658 if (s
->for_overlaps
|| s
->gidx
> 0)
3659 s
->background_filled_p
= 1;
3661 x_draw_glyph_string_background (s
, 1);
3662 x_draw_composite_glyph_string_foreground (s
);
3669 if (!s
->for_overlaps
)
3671 /* Draw underline. */
3672 if (s
->face
->underline_p
)
3674 unsigned long h
= 1;
3675 unsigned long dy
= s
->height
- h
;
3677 if (s
->face
->underline_defaulted_p
)
3678 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3679 s
->background_width
, h
);
3683 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3684 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3685 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3686 s
->background_width
, h
);
3687 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3691 /* Draw overline. */
3692 if (s
->face
->overline_p
)
3694 unsigned long dy
= 0, h
= 1;
3696 if (s
->face
->overline_color_defaulted_p
)
3697 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3698 s
->background_width
, h
);
3702 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3703 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3704 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3705 s
->background_width
, h
);
3706 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3710 /* Draw strike-through. */
3711 if (s
->face
->strike_through_p
)
3713 unsigned long h
= 1;
3714 unsigned long dy
= (s
->height
- h
) / 2;
3716 if (s
->face
->strike_through_color_defaulted_p
)
3717 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3722 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3723 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3724 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3726 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3730 /* Draw relief if not yet drawn. */
3731 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3732 x_draw_glyph_string_box (s
);
3735 /* Reset clipping. */
3736 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3739 /* Shift display to make room for inserted glyphs. */
3742 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3744 int x
, y
, width
, height
, shift_by
;
3746 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3747 x
, y
, width
, height
,
3751 /* Delete N glyphs at the nominal cursor position. Not implemented
3762 /* Clear entire frame. If updating_frame is non-null, clear that
3763 frame. Otherwise clear the selected frame. */
3773 f
= SELECTED_FRAME ();
3775 /* Clearing the frame will erase any cursor, so mark them all as no
3777 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3778 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3779 output_cursor
.x
= -1;
3781 /* We don't set the output cursor here because there will always
3782 follow an explicit cursor_to. */
3784 mac_clear_window (f
);
3786 /* We have to clear the scroll bars, too. If we have changed
3787 colors or something like that, then they should be notified. */
3788 x_scroll_bar_clear (f
);
3790 XFlush (FRAME_MAC_DISPLAY (f
));
3796 /* Invert the middle quarter of the frame for .15 sec. */
3798 /* We use the select system call to do the waiting, so we have to make
3799 sure it's available. If it isn't, we just won't do visual bells. */
3801 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3804 /* Subtract the `struct timeval' values X and Y, storing the result in
3805 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3808 timeval_subtract (result
, x
, y
)
3809 struct timeval
*result
, x
, y
;
3811 /* Perform the carry for the later subtraction by updating y. This
3812 is safer because on some systems the tv_sec member is unsigned. */
3813 if (x
.tv_usec
< y
.tv_usec
)
3815 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3816 y
.tv_usec
-= 1000000 * nsec
;
3820 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3822 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3823 y
.tv_usec
+= 1000000 * nsec
;
3827 /* Compute the time remaining to wait. tv_usec is certainly
3829 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3830 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3832 /* Return indication of whether the result should be considered
3834 return x
.tv_sec
< y
.tv_sec
;
3841 /* Get the height not including a menu bar widget. */
3842 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3843 /* Height of each line to flash. */
3844 int flash_height
= FRAME_LINE_HEIGHT (f
);
3845 /* These will be the left and right margins of the rectangles. */
3846 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3847 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3851 /* Don't flash the area between a scroll bar and the frame
3852 edge it is next to. */
3853 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3855 case vertical_scroll_bar_left
:
3856 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3859 case vertical_scroll_bar_right
:
3860 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3867 width
= flash_right
- flash_left
;
3871 /* If window is tall, flash top and bottom line. */
3872 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3874 mac_invert_rectangle (f
, flash_left
,
3875 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3876 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3877 width
, flash_height
);
3878 mac_invert_rectangle (f
, flash_left
,
3879 (height
- flash_height
3880 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3881 width
, flash_height
);
3884 /* If it is short, flash it all. */
3885 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3886 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3891 struct timeval wakeup
;
3893 EMACS_GET_TIME (wakeup
);
3895 /* Compute time to wait until, propagating carry from usecs. */
3896 wakeup
.tv_usec
+= 150000;
3897 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3898 wakeup
.tv_usec
%= 1000000;
3900 /* Keep waiting until past the time wakeup or any input gets
3902 while (! detect_input_pending ())
3904 struct timeval current
;
3905 struct timeval timeout
;
3907 EMACS_GET_TIME (current
);
3909 /* Break if result would be negative. */
3910 if (timeval_subtract (¤t
, wakeup
, current
))
3913 /* How long `select' should wait. */
3915 timeout
.tv_usec
= 10000;
3917 /* Try to wait that long--but we might wake up sooner. */
3918 select (0, NULL
, NULL
, NULL
, &timeout
);
3922 /* If window is tall, flash top and bottom line. */
3923 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3925 mac_invert_rectangle (f
, flash_left
,
3926 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3927 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3928 width
, flash_height
);
3929 mac_invert_rectangle (f
, flash_left
,
3930 (height
- flash_height
3931 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3932 width
, flash_height
);
3935 /* If it is short, flash it all. */
3936 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3937 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3944 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3947 /* Make audible bell. */
3952 struct frame
*f
= SELECTED_FRAME ();
3954 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3962 XFlush (FRAME_MAC_DISPLAY (f
));
3968 /* Specify how many text lines, from the top of the window,
3969 should be affected by insert-lines and delete-lines operations.
3970 This, and those operations, are used only within an update
3971 that is bounded by calls to x_update_begin and x_update_end. */
3974 XTset_terminal_window (n
)
3977 /* This function intentionally left blank. */
3982 /***********************************************************************
3984 ***********************************************************************/
3986 /* Perform an insert-lines or delete-lines operation, inserting N
3987 lines or deleting -N lines at vertical position VPOS. */
3990 x_ins_del_lines (vpos
, n
)
3997 /* Scroll part of the display as described by RUN. */
4000 x_scroll_run (w
, run
)
4004 struct frame
*f
= XFRAME (w
->frame
);
4005 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4007 /* Get frame-relative bounding box of the text display area of W,
4008 without mode lines. Include in this box the left and right
4010 window_box (w
, -1, &x
, &y
, &width
, &height
);
4012 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4013 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4014 bottom_y
= y
+ height
;
4018 /* Scrolling up. Make sure we don't copy part of the mode
4019 line at the bottom. */
4020 if (from_y
+ run
->height
> bottom_y
)
4021 height
= bottom_y
- from_y
;
4023 height
= run
->height
;
4027 /* Scolling down. Make sure we don't copy over the mode line.
4029 if (to_y
+ run
->height
> bottom_y
)
4030 height
= bottom_y
- to_y
;
4032 height
= run
->height
;
4037 /* Cursor off. Will be switched on again in x_update_window_end. */
4041 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4051 /***********************************************************************
4053 ***********************************************************************/
4061 ControlRef root_control
;
4064 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4066 ActivateControl (root_control
);
4068 x_update_cursor (f
, 1);
4072 frame_unhighlight (f
)
4076 ControlRef root_control
;
4079 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4081 DeactivateControl (root_control
);
4083 x_update_cursor (f
, 1);
4086 /* The focus has changed. Update the frames as necessary to reflect
4087 the new situation. Note that we can't change the selected frame
4088 here, because the Lisp code we are interrupting might become confused.
4089 Each event gets marked with the frame in which it occurred, so the
4090 Lisp code can tell when the switch took place by examining the events. */
4093 x_new_focus_frame (dpyinfo
, frame
)
4094 struct x_display_info
*dpyinfo
;
4095 struct frame
*frame
;
4097 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4099 if (frame
!= dpyinfo
->x_focus_frame
)
4101 /* Set this before calling other routines, so that they see
4102 the correct value of x_focus_frame. */
4103 dpyinfo
->x_focus_frame
= frame
;
4105 if (old_focus
&& old_focus
->auto_lower
)
4106 x_lower_frame (old_focus
);
4109 selected_frame
= frame
;
4110 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4112 Fselect_window (selected_frame
->selected_window
, Qnil
);
4113 choose_minibuf_frame ();
4116 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4117 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4119 pending_autoraise_frame
= 0;
4121 #if USE_MAC_FONT_PANEL
4123 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4127 x_frame_rehighlight (dpyinfo
);
4130 /* Handle FocusIn and FocusOut state changes for FRAME.
4131 If FRAME has focus and there exists more than one frame, puts
4132 a FOCUS_IN_EVENT into *BUFP. */
4135 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4137 struct mac_display_info
*dpyinfo
;
4138 struct frame
*frame
;
4139 struct input_event
*bufp
;
4141 if (type
== activeFlag
)
4143 if (dpyinfo
->x_focus_event_frame
!= frame
)
4145 x_new_focus_frame (dpyinfo
, frame
);
4146 dpyinfo
->x_focus_event_frame
= frame
;
4148 /* Don't stop displaying the initial startup message
4149 for a switch-frame event we don't need. */
4150 if (GC_NILP (Vterminal_frame
)
4151 && GC_CONSP (Vframe_list
)
4152 && !GC_NILP (XCDR (Vframe_list
)))
4154 bufp
->kind
= FOCUS_IN_EVENT
;
4155 XSETFRAME (bufp
->frame_or_window
, frame
);
4161 if (dpyinfo
->x_focus_event_frame
== frame
)
4163 dpyinfo
->x_focus_event_frame
= 0;
4164 x_new_focus_frame (dpyinfo
, 0);
4169 /* The focus may have changed. Figure out if it is a real focus change,
4170 by checking both FocusIn/Out and Enter/LeaveNotify events.
4172 Returns FOCUS_IN_EVENT event in *BUFP. */
4175 x_detect_focus_change (dpyinfo
, event
, bufp
)
4176 struct mac_display_info
*dpyinfo
;
4178 struct input_event
*bufp
;
4180 struct frame
*frame
;
4182 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4186 /* On Mac, this is only called from focus events, so no switch needed. */
4187 mac_focus_changed ((event
->modifiers
& activeFlag
),
4188 dpyinfo
, frame
, bufp
);
4192 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4195 x_mouse_leave (dpyinfo
)
4196 struct x_display_info
*dpyinfo
;
4198 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4201 /* The focus has changed, or we have redirected a frame's focus to
4202 another frame (this happens when a frame uses a surrogate
4203 mini-buffer frame). Shift the highlight as appropriate.
4205 The FRAME argument doesn't necessarily have anything to do with which
4206 frame is being highlighted or un-highlighted; we only use it to find
4207 the appropriate X display info. */
4210 XTframe_rehighlight (frame
)
4211 struct frame
*frame
;
4213 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4217 x_frame_rehighlight (dpyinfo
)
4218 struct x_display_info
*dpyinfo
;
4220 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4222 if (dpyinfo
->x_focus_frame
)
4224 dpyinfo
->x_highlight_frame
4225 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4226 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4227 : dpyinfo
->x_focus_frame
);
4228 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4230 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4231 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4235 dpyinfo
->x_highlight_frame
= 0;
4237 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4240 frame_unhighlight (old_highlight
);
4241 if (dpyinfo
->x_highlight_frame
)
4242 frame_highlight (dpyinfo
->x_highlight_frame
);
4248 /* Convert a keysym to its name. */
4251 x_get_keysym_name (keysym
)
4258 value
= XKeysymToString (keysym
);
4269 /* Function to report a mouse movement to the mainstream Emacs code.
4270 The input handler calls this.
4272 We have received a mouse movement event, which is given in *event.
4273 If the mouse is over a different glyph than it was last time, tell
4274 the mainstream emacs code by setting mouse_moved. If not, ask for
4275 another motion event, so we can check again the next time it moves. */
4277 static Point last_mouse_motion_position
;
4278 static Lisp_Object last_mouse_motion_frame
;
4281 note_mouse_movement (frame
, pos
)
4285 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4286 #if TARGET_API_MAC_CARBON
4290 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4291 last_mouse_motion_position
= *pos
;
4292 XSETFRAME (last_mouse_motion_frame
, frame
);
4294 #if TARGET_API_MAC_CARBON
4295 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4297 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4300 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4301 /* This case corresponds to LeaveNotify in X11. */
4303 /* If we move outside the frame, then we're certainly no
4304 longer on any text in the frame. */
4305 clear_mouse_face (dpyinfo
);
4306 dpyinfo
->mouse_face_mouse_frame
= 0;
4307 if (!dpyinfo
->grabbed
)
4308 rif
->define_frame_cursor (frame
,
4309 frame
->output_data
.mac
->nontext_cursor
);
4313 /* Has the mouse moved off the glyph it was on at the last sighting? */
4314 if (frame
!= last_mouse_glyph_frame
4315 || !PtInRect (*pos
, &last_mouse_glyph
))
4317 frame
->mouse_moved
= 1;
4318 last_mouse_scroll_bar
= Qnil
;
4319 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4320 /* Remember which glyph we're now on. */
4321 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4322 last_mouse_glyph_frame
= frame
;
4330 /************************************************************************
4332 ************************************************************************/
4334 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4337 redo_mouse_highlight ()
4339 if (!NILP (last_mouse_motion_frame
)
4340 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4341 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4342 last_mouse_motion_position
.h
,
4343 last_mouse_motion_position
.v
);
4347 static struct frame
*
4348 mac_focus_frame (dpyinfo
)
4349 struct mac_display_info
*dpyinfo
;
4351 if (dpyinfo
->x_focus_frame
)
4352 return dpyinfo
->x_focus_frame
;
4354 /* Mac version may get events, such as a menu bar click, even when
4355 all the frames are invisible. In this case, we regard the
4356 event came to the selected frame. */
4357 return SELECTED_FRAME ();
4361 /* Return the current position of the mouse.
4362 *FP should be a frame which indicates which display to ask about.
4364 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4365 and *PART to the frame, window, and scroll bar part that the mouse
4366 is over. Set *X and *Y to the portion and whole of the mouse's
4367 position on the scroll bar.
4369 If the mouse movement started elsewhere, set *FP to the frame the
4370 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4373 Set *TIME to the server time-stamp for the time at which the mouse
4374 was at this position.
4376 Don't store anything if we don't have a valid set of values to report.
4378 This clears the mouse_moved flag, so we can wait for the next mouse
4382 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4385 Lisp_Object
*bar_window
;
4386 enum scroll_bar_part
*part
;
4388 unsigned long *time
;
4394 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4395 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4398 Lisp_Object frame
, tail
;
4400 /* Clear the mouse-moved flag for every frame on this display. */
4401 FOR_EACH_FRAME (tail
, frame
)
4402 XFRAME (frame
)->mouse_moved
= 0;
4404 last_mouse_scroll_bar
= Qnil
;
4406 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4407 && FRAME_LIVE_P (last_mouse_frame
))
4408 f1
= last_mouse_frame
;
4410 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4414 /* Ok, we found a frame. Store all the values.
4415 last_mouse_glyph is a rectangle used to reduce the
4416 generation of mouse events. To not miss any motion
4417 events, we must divide the frame into rectangles of the
4418 size of the smallest character that could be displayed
4419 on it, i.e. into the same rectangles that matrices on
4420 the frame are divided into. */
4423 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4424 GetMouse (&mouse_pos
);
4425 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4427 last_mouse_glyph_frame
= f1
;
4432 XSETINT (*x
, mouse_pos
.h
);
4433 XSETINT (*y
, mouse_pos
.v
);
4434 *time
= last_mouse_movement_time
;
4442 /************************************************************************
4444 ************************************************************************/
4446 #ifdef USE_TOOLKIT_SCROLL_BARS
4448 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4449 static OSStatus install_scroll_bar_timer
P_ ((void));
4450 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4451 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4452 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4453 struct input_event
*));
4454 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4456 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4458 struct input_event
*));
4459 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4460 struct input_event
*));
4461 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4462 Point
, struct input_event
*));
4463 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4466 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4468 static int last_scroll_bar_part
;
4470 static EventLoopTimerRef scroll_bar_timer
;
4472 static int scroll_bar_timer_event_posted_p
;
4474 #define SCROLL_BAR_FIRST_DELAY 0.5
4475 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4478 scroll_bar_timer_callback (timer
, data
)
4479 EventLoopTimerRef timer
;
4484 err
= mac_post_mouse_moved_event ();
4486 scroll_bar_timer_event_posted_p
= 1;
4490 install_scroll_bar_timer ()
4492 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4494 if (scroll_bar_timer_callbackUPP
== NULL
)
4495 scroll_bar_timer_callbackUPP
=
4496 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4498 if (scroll_bar_timer
== NULL
)
4499 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4500 kEventDurationForever as delays. */
4502 InstallEventLoopTimer (GetCurrentEventLoop (),
4503 kEventDurationForever
, kEventDurationForever
,
4504 scroll_bar_timer_callbackUPP
, NULL
,
4509 set_scroll_bar_timer (delay
)
4510 EventTimerInterval delay
;
4512 if (scroll_bar_timer
== NULL
)
4513 install_scroll_bar_timer ();
4515 scroll_bar_timer_event_posted_p
= 0;
4517 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4521 control_part_code_to_scroll_bar_part (part_code
)
4522 ControlPartCode part_code
;
4526 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4527 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4528 case kControlPageUpPart
: return scroll_bar_above_handle
;
4529 case kControlPageDownPart
: return scroll_bar_below_handle
;
4530 case kControlIndicatorPart
: return scroll_bar_handle
;
4537 construct_scroll_bar_click (bar
, part
, bufp
)
4538 struct scroll_bar
*bar
;
4540 struct input_event
*bufp
;
4542 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4543 bufp
->frame_or_window
= bar
->window
;
4547 XSETINT (bufp
->x
, 0);
4548 XSETINT (bufp
->y
, 0);
4549 bufp
->modifiers
= 0;
4553 get_control_part_bounds (ch
, part_code
, rect
)
4555 ControlPartCode part_code
;
4558 RgnHandle region
= NewRgn ();
4561 err
= GetControlRegion (ch
, part_code
, region
);
4563 GetRegionBounds (region
, rect
);
4564 DisposeRgn (region
);
4570 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4571 struct scroll_bar
*bar
;
4572 ControlPartCode part_code
;
4573 struct input_event
*bufp
;
4575 int part
= control_part_code_to_scroll_bar_part (part_code
);
4580 if (part
!= scroll_bar_handle
)
4582 construct_scroll_bar_click (bar
, part
, bufp
);
4583 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4584 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4587 last_scroll_bar_part
= part
;
4588 bar
->dragging
= Qnil
;
4589 tracked_scroll_bar
= bar
;
4593 x_scroll_bar_handle_release (bar
, bufp
)
4594 struct scroll_bar
*bar
;
4595 struct input_event
*bufp
;
4597 if (last_scroll_bar_part
!= scroll_bar_handle
4598 || !GC_NILP (bar
->dragging
))
4599 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4601 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4602 set_scroll_bar_timer (kEventDurationForever
);
4604 last_scroll_bar_part
= -1;
4605 bar
->dragging
= Qnil
;
4606 tracked_scroll_bar
= NULL
;
4610 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4612 struct scroll_bar
*bar
;
4614 struct input_event
*bufp
;
4616 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4618 if (last_scroll_bar_part
== scroll_bar_handle
)
4623 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4624 kControlIndicatorPart
, &r
);
4626 if (GC_NILP (bar
->dragging
))
4627 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4629 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4630 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4631 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4636 if (top
> top_range
)
4639 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4640 XSETINT (bufp
->x
, top
);
4641 XSETINT (bufp
->y
, top_range
);
4645 ControlPartCode part_code
;
4646 int unhilite_p
= 0, part
;
4648 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4652 part
= control_part_code_to_scroll_bar_part (part_code
);
4654 switch (last_scroll_bar_part
)
4656 case scroll_bar_above_handle
:
4657 case scroll_bar_below_handle
:
4658 if (part
!= scroll_bar_above_handle
4659 && part
!= scroll_bar_below_handle
)
4663 case scroll_bar_up_arrow
:
4664 case scroll_bar_down_arrow
:
4665 if (part
!= scroll_bar_up_arrow
4666 && part
!= scroll_bar_down_arrow
)
4673 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4674 else if (part
!= last_scroll_bar_part
4675 || scroll_bar_timer_event_posted_p
)
4677 construct_scroll_bar_click (bar
, part
, bufp
);
4678 last_scroll_bar_part
= part
;
4679 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4680 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4685 /* Set the thumb size and position of scroll bar BAR. We are currently
4686 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4689 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4690 struct scroll_bar
*bar
;
4691 int portion
, position
, whole
;
4693 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4694 int value
, viewsize
, maximum
;
4696 if (XINT (bar
->track_height
) == 0)
4700 value
= 0, viewsize
= 1, maximum
= 0;
4705 maximum
= max (0, whole
- portion
);
4710 if (GetControlViewSize (ch
) != viewsize
4711 || GetControl32BitValue (ch
) != value
4712 || GetControl32BitMaximum (ch
) != maximum
)
4714 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4715 SetControlVisibility (ch
, false, false);
4717 SetControl32BitMaximum (ch
, maximum
);
4718 SetControl32BitValue (ch
, value
);
4719 SetControlViewSize (ch
, viewsize
);
4721 SetControlVisibility (ch
, true, true);
4727 #endif /* USE_TOOLKIT_SCROLL_BARS */
4731 /************************************************************************
4732 Scroll bars, general
4733 ************************************************************************/
4735 /* Create a scroll bar and return the scroll bar vector for it. W is
4736 the Emacs window on which to create the scroll bar. TOP, LEFT,
4737 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4740 static struct scroll_bar
*
4741 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4743 int top
, left
, width
, height
, disp_top
, disp_height
;
4745 struct frame
*f
= XFRAME (w
->frame
);
4746 struct scroll_bar
*bar
4747 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4755 r
.right
= left
+ width
;
4756 r
.bottom
= disp_top
+ disp_height
;
4759 mac_prepare_for_quickdraw (f
);
4761 #if TARGET_API_MAC_CARBON
4762 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4763 #if USE_TOOLKIT_SCROLL_BARS
4766 width
< disp_height
,
4768 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4770 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4771 0, 0, 0, scrollBarProc
, (long) bar
);
4773 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4775 XSETWINDOW (bar
->window
, w
);
4776 XSETINT (bar
->top
, top
);
4777 XSETINT (bar
->left
, left
);
4778 XSETINT (bar
->width
, width
);
4779 XSETINT (bar
->height
, height
);
4780 XSETINT (bar
->start
, 0);
4781 XSETINT (bar
->end
, 0);
4782 bar
->dragging
= Qnil
;
4783 #ifdef USE_TOOLKIT_SCROLL_BARS
4784 bar
->track_top
= Qnil
;
4785 bar
->track_height
= Qnil
;
4788 /* Add bar to its frame's list of scroll bars. */
4789 bar
->next
= FRAME_SCROLL_BARS (f
);
4791 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4792 if (!NILP (bar
->next
))
4793 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4800 /* Draw BAR's handle in the proper position.
4802 If the handle is already drawn from START to END, don't bother
4803 redrawing it, unless REBUILD is non-zero; in that case, always
4804 redraw it. (REBUILD is handy for drawing the handle after expose
4807 Normally, we want to constrain the start and end of the handle to
4808 fit inside its rectangle, but if the user is dragging the scroll
4809 bar handle, we want to let them drag it down all the way, so that
4810 the bar's top is as far down as it goes; otherwise, there's no way
4811 to move to the very end of the buffer. */
4813 #ifndef USE_TOOLKIT_SCROLL_BARS
4816 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4817 struct scroll_bar
*bar
;
4821 int dragging
= ! NILP (bar
->dragging
);
4822 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4823 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4824 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4825 int length
= end
- start
;
4827 /* If the display is already accurate, do nothing. */
4829 && start
== XINT (bar
->start
)
4830 && end
== XINT (bar
->end
))
4835 /* Make sure the values are reasonable, and try to preserve the
4836 distance between start and end. */
4839 else if (start
> top_range
)
4841 end
= start
+ length
;
4845 else if (end
> top_range
&& ! dragging
)
4848 /* Store the adjusted setting in the scroll bar. */
4849 XSETINT (bar
->start
, start
);
4850 XSETINT (bar
->end
, end
);
4852 /* Clip the end position, just for display. */
4853 if (end
> top_range
)
4856 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4857 top positions, to make sure the handle is always at least that
4858 many pixels tall. */
4859 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4861 SetControlMinimum (ch
, 0);
4862 /* Don't inadvertently activate deactivated scroll bars */
4863 if (GetControlMaximum (ch
) != -1)
4864 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4866 SetControlValue (ch
, start
);
4867 #if TARGET_API_MAC_CARBON
4868 SetControlViewSize (ch
, end
- start
);
4874 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4876 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4880 x_scroll_bar_remove (bar
)
4881 struct scroll_bar
*bar
;
4883 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4888 mac_prepare_for_quickdraw (f
);
4890 /* Destroy the Mac scroll bar control */
4891 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4893 /* Disassociate this scroll bar from its window. */
4894 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4900 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4901 that we are displaying PORTION characters out of a total of WHOLE
4902 characters, starting at POSITION. If WINDOW has no scroll bar,
4906 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4908 int portion
, whole
, position
;
4910 struct frame
*f
= XFRAME (w
->frame
);
4911 struct scroll_bar
*bar
;
4912 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4913 int window_y
, window_height
;
4915 /* Get window dimensions. */
4916 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4918 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4919 height
= window_height
;
4921 /* Compute the left edge of the scroll bar area. */
4922 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4924 /* Compute the width of the scroll bar which might be less than
4925 the width of the area reserved for the scroll bar. */
4926 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4927 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4931 /* Compute the left edge of the scroll bar. */
4932 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4935 sb_left
= left
+ width
- sb_width
;
4937 /* Adjustments according to Inside Macintosh to make it look nice */
4939 disp_height
= height
;
4946 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4952 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4956 /* Does the scroll bar exist yet? */
4957 if (NILP (w
->vertical_scroll_bar
))
4960 mac_clear_area (f
, left
, top
, width
, height
);
4962 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4964 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4968 /* It may just need to be moved and resized. */
4971 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4972 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4976 /* If already correctly positioned, do nothing. */
4977 if (!(XINT (bar
->left
) == sb_left
4978 && XINT (bar
->top
) == top
4979 && XINT (bar
->width
) == sb_width
4980 && XINT (bar
->height
) == height
))
4982 /* Since toolkit scroll bars are smaller than the space reserved
4983 for them on the frame, we have to clear "under" them. */
4984 mac_clear_area (f
, left
, top
, width
, height
);
4987 mac_prepare_for_quickdraw (f
);
4990 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4991 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4993 #ifndef USE_TOOLKIT_SCROLL_BARS
4994 if (sb_width
< disp_height
)
4998 /* Remember new settings. */
4999 XSETINT (bar
->left
, sb_left
);
5000 XSETINT (bar
->top
, top
);
5001 XSETINT (bar
->width
, sb_width
);
5002 XSETINT (bar
->height
, height
);
5003 #ifdef USE_TOOLKIT_SCROLL_BARS
5004 bar
->track_top
= Qnil
;
5005 bar
->track_height
= Qnil
;
5012 #ifdef USE_TOOLKIT_SCROLL_BARS
5013 if (NILP (bar
->track_top
))
5015 if (sb_width
>= disp_height
)
5017 XSETINT (bar
->track_top
, 0);
5018 XSETINT (bar
->track_height
, 0);
5022 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5027 SetControl32BitMinimum (ch
, 0);
5028 SetControl32BitMaximum (ch
, 1);
5029 SetControlViewSize (ch
, 1);
5031 /* Move the scroll bar thumb to the top. */
5032 SetControl32BitValue (ch
, 0);
5033 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5035 /* Move the scroll bar thumb to the bottom. */
5036 SetControl32BitValue (ch
, 1);
5037 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5039 UnionRect (&r0
, &r1
, &r0
);
5040 XSETINT (bar
->track_top
, r0
.top
);
5041 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5043 /* Don't show the scroll bar if its height is not enough to
5044 display the scroll bar thumb. */
5045 if (r0
.bottom
- r0
.top
> 0)
5052 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5053 #else /* not USE_TOOLKIT_SCROLL_BARS */
5054 /* Set the scroll bar's current state, unless we're currently being
5056 if (NILP (bar
->dragging
))
5058 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5061 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5064 int start
= ((double) position
* top_range
) / whole
;
5065 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5066 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5069 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5073 /* The following three hooks are used when we're doing a thorough
5074 redisplay of the frame. We don't explicitly know which scroll bars
5075 are going to be deleted, because keeping track of when windows go
5076 away is a real pain - "Can you say set-window-configuration, boys
5077 and girls?" Instead, we just assert at the beginning of redisplay
5078 that *all* scroll bars are to be removed, and then save a scroll bar
5079 from the fiery pit when we actually redisplay its window. */
5081 /* Arrange for all scroll bars on FRAME to be removed at the next call
5082 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5083 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5086 XTcondemn_scroll_bars (frame
)
5089 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5090 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5093 bar
= FRAME_SCROLL_BARS (frame
);
5094 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5095 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5096 XSCROLL_BAR (bar
)->prev
= Qnil
;
5097 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5098 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5099 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5104 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5105 Note that WINDOW isn't necessarily condemned at all. */
5108 XTredeem_scroll_bar (window
)
5109 struct window
*window
;
5111 struct scroll_bar
*bar
;
5114 /* We can't redeem this window's scroll bar if it doesn't have one. */
5115 if (NILP (window
->vertical_scroll_bar
))
5118 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5120 /* Unlink it from the condemned list. */
5121 f
= XFRAME (WINDOW_FRAME (window
));
5122 if (NILP (bar
->prev
))
5124 /* If the prev pointer is nil, it must be the first in one of
5126 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5127 /* It's not condemned. Everything's fine. */
5129 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5130 window
->vertical_scroll_bar
))
5131 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5133 /* If its prev pointer is nil, it must be at the front of
5134 one or the other! */
5138 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5140 if (! NILP (bar
->next
))
5141 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5143 bar
->next
= FRAME_SCROLL_BARS (f
);
5145 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5146 if (! NILP (bar
->next
))
5147 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5150 /* Remove all scroll bars on FRAME that haven't been saved since the
5151 last call to `*condemn_scroll_bars_hook'. */
5154 XTjudge_scroll_bars (f
)
5157 Lisp_Object bar
, next
;
5159 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5161 /* Clear out the condemned list now so we won't try to process any
5162 more events on the hapless scroll bars. */
5163 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5165 for (; ! NILP (bar
); bar
= next
)
5167 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5169 x_scroll_bar_remove (b
);
5172 b
->next
= b
->prev
= Qnil
;
5175 /* Now there should be no references to the condemned scroll bars,
5176 and they should get garbage-collected. */
5180 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5181 is set to something other than NO_EVENT, it is enqueued.
5183 This may be called from a signal handler, so we have to ignore GC
5187 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5188 struct scroll_bar
*bar
;
5189 ControlPartCode part_code
;
5191 struct input_event
*bufp
;
5193 int win_y
, top_range
;
5195 if (! GC_WINDOWP (bar
->window
))
5198 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5199 bufp
->frame_or_window
= bar
->window
;
5202 bar
->dragging
= Qnil
;
5206 case kControlUpButtonPart
:
5207 bufp
->part
= scroll_bar_up_arrow
;
5209 case kControlDownButtonPart
:
5210 bufp
->part
= scroll_bar_down_arrow
;
5212 case kControlPageUpPart
:
5213 bufp
->part
= scroll_bar_above_handle
;
5215 case kControlPageDownPart
:
5216 bufp
->part
= scroll_bar_below_handle
;
5218 #if TARGET_API_MAC_CARBON
5221 case kControlIndicatorPart
:
5223 if (er
->what
== mouseDown
)
5224 bar
->dragging
= make_number (0);
5225 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5226 bufp
->part
= scroll_bar_handle
;
5230 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5231 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5233 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5237 if (! NILP (bar
->dragging
))
5238 win_y
-= XINT (bar
->dragging
);
5242 if (win_y
> top_range
)
5245 XSETINT (bufp
->x
, win_y
);
5246 XSETINT (bufp
->y
, top_range
);
5249 #ifndef USE_TOOLKIT_SCROLL_BARS
5251 /* Handle some mouse motion while someone is dragging the scroll bar.
5253 This may be called from a signal handler, so we have to ignore GC
5257 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5258 struct scroll_bar
*bar
;
5262 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5264 last_mouse_movement_time
= t
;
5267 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5269 /* If we're dragging the bar, display it. */
5270 if (! GC_NILP (bar
->dragging
))
5272 /* Where should the handle be now? */
5273 int new_start
= y_pos
- 24;
5275 if (new_start
!= XINT (bar
->start
))
5277 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5279 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5284 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5286 /* Return information to the user about the current position of the mouse
5287 on the scroll bar. */
5290 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5292 Lisp_Object
*bar_window
;
5293 enum scroll_bar_part
*part
;
5295 unsigned long *time
;
5297 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5298 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5299 #if TARGET_API_MAC_CARBON
5300 WindowPtr wp
= GetControlOwner (ch
);
5302 WindowPtr wp
= (*ch
)->contrlOwner
;
5305 struct frame
*f
= mac_window_to_frame (wp
);
5306 int win_y
, top_range
;
5308 SetPortWindowPort (wp
);
5310 GetMouse (&mouse_pos
);
5312 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5313 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5315 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5319 if (! NILP (bar
->dragging
))
5320 win_y
-= XINT (bar
->dragging
);
5324 if (win_y
> top_range
)
5328 *bar_window
= bar
->window
;
5330 if (! NILP (bar
->dragging
))
5331 *part
= scroll_bar_handle
;
5332 else if (win_y
< XINT (bar
->start
))
5333 *part
= scroll_bar_above_handle
;
5334 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5335 *part
= scroll_bar_handle
;
5337 *part
= scroll_bar_below_handle
;
5339 XSETINT (*x
, win_y
);
5340 XSETINT (*y
, top_range
);
5343 last_mouse_scroll_bar
= Qnil
;
5345 *time
= last_mouse_movement_time
;
5349 /* The screen has been cleared so we may have changed foreground or
5350 background colors, and the scroll bars may need to be redrawn.
5351 Clear out the scroll bars, and ask for expose events, so we can
5355 x_scroll_bar_clear (f
)
5358 XTcondemn_scroll_bars (f
);
5359 XTjudge_scroll_bars (f
);
5363 /***********************************************************************
5365 ***********************************************************************/
5367 /* Set clipping for output in glyph row ROW. W is the window in which
5368 we operate. GC is the graphics context to set clipping in.
5370 ROW may be a text row or, e.g., a mode line. Text rows must be
5371 clipped to the interior of the window dedicated to text display,
5372 mode lines must be clipped to the whole window. */
5375 x_clip_to_row (w
, row
, area
, gc
)
5377 struct glyph_row
*row
;
5381 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5383 int window_x
, window_y
, window_width
;
5385 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5387 clip_rect
.left
= window_x
;
5388 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5389 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5390 clip_rect
.right
= clip_rect
.left
+ window_width
;
5391 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5393 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5397 /* Draw a hollow box cursor on window W in glyph row ROW. */
5400 x_draw_hollow_cursor (w
, row
)
5402 struct glyph_row
*row
;
5404 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5405 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5406 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5409 struct glyph
*cursor_glyph
;
5412 /* Get the glyph the cursor is on. If we can't tell because
5413 the current matrix is invalid or such, give up. */
5414 cursor_glyph
= get_phys_cursor_glyph (w
);
5415 if (cursor_glyph
== NULL
)
5418 /* Compute frame-relative coordinates for phys cursor. */
5419 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5420 wd
= w
->phys_cursor_width
;
5422 /* The foreground of cursor_gc is typically the same as the normal
5423 background color, which can cause the cursor box to be invisible. */
5424 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5425 if (dpyinfo
->scratch_cursor_gc
)
5426 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5428 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5429 GCForeground
, &xgcv
);
5430 gc
= dpyinfo
->scratch_cursor_gc
;
5432 /* Set clipping, draw the rectangle, and reset clipping again. */
5433 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5434 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5435 mac_reset_clip_rectangles (dpy
, gc
);
5439 /* Draw a bar cursor on window W in glyph row ROW.
5441 Implementation note: One would like to draw a bar cursor with an
5442 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5443 Unfortunately, I didn't find a font yet that has this property set.
5447 x_draw_bar_cursor (w
, row
, width
, kind
)
5449 struct glyph_row
*row
;
5451 enum text_cursor_kinds kind
;
5453 struct frame
*f
= XFRAME (w
->frame
);
5454 struct glyph
*cursor_glyph
;
5456 /* If cursor is out of bounds, don't draw garbage. This can happen
5457 in mini-buffer windows when switching between echo area glyphs
5459 cursor_glyph
= get_phys_cursor_glyph (w
);
5460 if (cursor_glyph
== NULL
)
5463 /* If on an image, draw like a normal cursor. That's usually better
5464 visible than drawing a bar, esp. if the image is large so that
5465 the bar might not be in the window. */
5466 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5468 struct glyph_row
*row
;
5469 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5470 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5474 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5475 Window window
= FRAME_MAC_WINDOW (f
);
5476 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5477 unsigned long mask
= GCForeground
| GCBackground
;
5478 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5481 /* If the glyph's background equals the color we normally draw
5482 the bar cursor in, the bar cursor in its normal color is
5483 invisible. Use the glyph's foreground color instead in this
5484 case, on the assumption that the glyph's colors are chosen so
5485 that the glyph is legible. */
5486 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5487 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5489 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5492 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5495 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5496 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5500 width
= FRAME_CURSOR_WIDTH (f
);
5501 width
= min (cursor_glyph
->pixel_width
, width
);
5503 w
->phys_cursor_width
= width
;
5504 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5506 if (kind
== BAR_CURSOR
)
5507 mac_fill_rectangle (f
, gc
,
5508 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5509 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5510 width
, row
->height
);
5512 mac_fill_rectangle (f
, gc
,
5513 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5514 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5515 row
->height
- width
),
5516 cursor_glyph
->pixel_width
,
5519 mac_reset_clip_rectangles (dpy
, gc
);
5524 /* RIF: Define cursor CURSOR on frame F. */
5527 mac_define_frame_cursor (f
, cursor
)
5531 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5533 if (dpyinfo
->x_focus_frame
== f
)
5534 SetThemeCursor (cursor
);
5538 /* RIF: Clear area on frame F. */
5541 mac_clear_frame_area (f
, x
, y
, width
, height
)
5543 int x
, y
, width
, height
;
5545 mac_clear_area (f
, x
, y
, width
, height
);
5549 /* RIF: Draw cursor on window W. */
5552 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5554 struct glyph_row
*glyph_row
;
5556 int cursor_type
, cursor_width
;
5561 w
->phys_cursor_type
= cursor_type
;
5562 w
->phys_cursor_on_p
= 1;
5564 if (glyph_row
->exact_window_width_line_p
5565 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5567 glyph_row
->cursor_in_fringe_p
= 1;
5568 draw_fringe_bitmap (w
, glyph_row
, 0);
5571 switch (cursor_type
)
5573 case HOLLOW_BOX_CURSOR
:
5574 x_draw_hollow_cursor (w
, glyph_row
);
5577 case FILLED_BOX_CURSOR
:
5578 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5582 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5586 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5590 w
->phys_cursor_width
= 0;
5602 #if 0 /* MAC_TODO: no icon support yet. */
5604 x_bitmap_icon (f
, icon
)
5610 if (FRAME_W32_WINDOW (f
) == 0)
5614 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5615 else if (STRINGP (icon
))
5616 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5617 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5618 else if (SYMBOLP (icon
))
5622 if (EQ (icon
, intern ("application")))
5623 name
= (LPCTSTR
) IDI_APPLICATION
;
5624 else if (EQ (icon
, intern ("hand")))
5625 name
= (LPCTSTR
) IDI_HAND
;
5626 else if (EQ (icon
, intern ("question")))
5627 name
= (LPCTSTR
) IDI_QUESTION
;
5628 else if (EQ (icon
, intern ("exclamation")))
5629 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5630 else if (EQ (icon
, intern ("asterisk")))
5631 name
= (LPCTSTR
) IDI_ASTERISK
;
5632 else if (EQ (icon
, intern ("winlogo")))
5633 name
= (LPCTSTR
) IDI_WINLOGO
;
5637 hicon
= LoadIcon (NULL
, name
);
5645 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5650 #endif /* MAC_TODO */
5652 /************************************************************************
5654 ************************************************************************/
5656 /* Display Error Handling functions not used on W32. Listing them here
5657 helps diff stay in step when comparing w32term.c with xterm.c.
5659 x_error_catcher (display, error)
5660 x_catch_errors (dpy)
5661 x_catch_errors_unwind (old_val)
5662 x_check_errors (dpy, format)
5663 x_had_errors_p (dpy)
5664 x_clear_errors (dpy)
5665 x_uncatch_errors (dpy, count)
5667 x_connection_signal (signalnum)
5668 x_connection_closed (dpy, error_message)
5669 x_error_quitter (display, error)
5670 x_error_handler (display, error)
5671 x_io_error_quitter (display)
5676 /* Changing the font of the frame. */
5678 /* Give frame F the font named FONTNAME as its default font, and
5679 return the full name of that font. FONTNAME may be a wildcard
5680 pattern; in that case, we choose some font that fits the pattern.
5681 The return value shows which font we chose. */
5684 x_new_font (f
, fontname
)
5686 register char *fontname
;
5688 struct font_info
*fontp
5689 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5694 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5695 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5696 FRAME_FONTSET (f
) = -1;
5698 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5699 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5700 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5702 compute_fringe_widths (f
, 1);
5704 /* Compute the scroll bar width in character columns. */
5705 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5707 int wid
= FRAME_COLUMN_WIDTH (f
);
5708 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5709 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5713 int wid
= FRAME_COLUMN_WIDTH (f
);
5714 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5717 /* Now make the frame display the given font. */
5718 if (FRAME_MAC_WINDOW (f
) != 0)
5720 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5722 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5724 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5727 /* Don't change the size of a tip frame; there's no point in
5728 doing it because it's done in Fx_show_tip, and it leads to
5729 problems because the tip frame has no widget. */
5730 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5731 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5734 return build_string (fontp
->full_name
);
5737 /* Give frame F the fontset named FONTSETNAME as its default font, and
5738 return the full name of that fontset. FONTSETNAME may be a wildcard
5739 pattern; in that case, we choose some fontset that fits the pattern.
5740 The return value shows which fontset we chose. */
5743 x_new_fontset (f
, fontsetname
)
5747 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5753 if (FRAME_FONTSET (f
) == fontset
)
5754 /* This fontset is already set in frame F. There's nothing more
5756 return fontset_name (fontset
);
5758 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5760 if (!STRINGP (result
))
5761 /* Can't load ASCII font. */
5764 /* Since x_new_font doesn't update any fontset information, do it now. */
5765 FRAME_FONTSET (f
) = fontset
;
5767 return build_string (fontsetname
);
5771 /***********************************************************************
5772 TODO: W32 Input Methods
5773 ***********************************************************************/
5774 /* Listing missing functions from xterm.c helps diff stay in step.
5776 xim_destroy_callback (xim, client_data, call_data)
5777 xim_open_dpy (dpyinfo, resource_name)
5779 xim_instantiate_callback (display, client_data, call_data)
5780 xim_initialize (dpyinfo, resource_name)
5781 xim_close_dpy (dpyinfo)
5787 mac_get_window_bounds (f
, inner
, outer
)
5789 Rect
*inner
, *outer
;
5791 #if TARGET_API_MAC_CARBON
5792 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5793 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5794 #else /* not TARGET_API_MAC_CARBON */
5795 RgnHandle region
= NewRgn ();
5797 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5798 *inner
= (*region
)->rgnBBox
;
5799 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5800 *outer
= (*region
)->rgnBBox
;
5801 DisposeRgn (region
);
5802 #endif /* not TARGET_API_MAC_CARBON */
5806 mac_handle_origin_change (f
)
5809 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5813 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
5815 int pixelwidth
, pixelheight
;
5819 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
5820 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
5822 if (cols
!= FRAME_COLS (f
)
5823 || rows
!= FRAME_LINES (f
)
5824 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
5825 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
5827 /* We pass 1 for DELAY since we can't run Lisp code inside of
5829 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5830 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5831 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5832 SET_FRAME_GARBAGED (f
);
5834 /* If cursor was outside the new size, mark it as off. */
5835 mark_window_cursors_off (XWINDOW (f
->root_window
));
5837 /* Clear out any recollection of where the mouse highlighting
5838 was, since it might be in a place that's outside the new
5839 frame size. Actually checking whether it is outside is a
5840 pain in the neck, so don't try--just let the highlighting be
5841 done afresh with new size. */
5842 cancel_mouse_face (f
);
5844 #if TARGET_API_MAC_CARBON
5845 if (f
->output_data
.mac
->hourglass_control
)
5848 mac_prepare_for_quickdraw (f
);
5850 MoveControl (f
->output_data
.mac
->hourglass_control
,
5851 pixelwidth
- HOURGLASS_WIDTH
, 0);
5858 /* Calculate the absolute position in frame F
5859 from its current recorded position values and gravity. */
5862 x_calc_absolute_position (f
)
5865 int width_diff
= 0, height_diff
= 0;
5866 int flags
= f
->size_hint_flags
;
5869 /* We have nothing to do if the current position
5870 is already for the top-left corner. */
5871 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5874 /* Find the offsets of the outside upper-left corner of
5875 the inner window, with respect to the outer window. */
5876 mac_get_window_bounds (f
, &inner
, &outer
);
5878 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5879 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5881 /* Treat negative positions as relative to the leftmost bottommost
5882 position that fits on the screen. */
5883 if (flags
& XNegative
)
5884 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5886 - FRAME_PIXEL_WIDTH (f
)
5889 if (flags
& YNegative
)
5890 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5892 - FRAME_PIXEL_HEIGHT (f
)
5895 /* The left_pos and top_pos
5896 are now relative to the top and left screen edges,
5897 so the flags should correspond. */
5898 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5901 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5902 to really change the position, and 0 when calling from
5903 x_make_frame_visible (in that case, XOFF and YOFF are the current
5904 position values). It is -1 when calling from x_set_frame_parameters,
5905 which means, do adjust for borders but don't change the gravity. */
5908 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5910 register int xoff
, yoff
;
5913 if (change_gravity
> 0)
5917 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5919 f
->size_hint_flags
|= XNegative
;
5921 f
->size_hint_flags
|= YNegative
;
5922 f
->win_gravity
= NorthWestGravity
;
5924 x_calc_absolute_position (f
);
5927 x_wm_set_size_hint (f
, (long) 0, 0);
5929 #if TARGET_API_MAC_CARBON
5930 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5931 /* If the title bar is completely outside the screen, adjust the
5933 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5934 kWindowConstrainMoveRegardlessOfFit
5935 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5936 #if USE_CARBON_EVENTS
5937 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
5939 mac_handle_origin_change (f
);
5942 Rect inner
, outer
, screen_rect
, dummy
;
5943 RgnHandle region
= NewRgn ();
5945 mac_get_window_bounds (f
, &inner
, &outer
);
5946 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5947 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5948 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5949 f
->top_pos
+ f
->y_pixels_diff
, false);
5951 /* If the title bar is completely outside the screen, adjust the
5952 position. The variable `outer' holds the title bar rectangle.
5953 The variable `inner' holds slightly smaller one than `outer',
5954 so that the calculation of overlapping may not become too
5956 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5957 outer
= (*region
)->rgnBBox
;
5958 DisposeRgn (region
);
5960 InsetRect (&inner
, 8, 8);
5961 screen_rect
= qd
.screenBits
.bounds
;
5962 screen_rect
.top
+= GetMBarHeight ();
5964 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5966 if (inner
.right
<= screen_rect
.left
)
5967 f
->left_pos
= screen_rect
.left
;
5968 else if (inner
.left
>= screen_rect
.right
)
5969 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5971 if (inner
.bottom
<= screen_rect
.top
)
5972 f
->top_pos
= screen_rect
.top
;
5973 else if (inner
.top
>= screen_rect
.bottom
)
5974 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5976 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5977 f
->top_pos
+ f
->y_pixels_diff
, false);
5985 /* Call this to change the size of frame F's x-window.
5986 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5987 for this size change and subsequent size changes.
5988 Otherwise we leave the window gravity unchanged. */
5991 x_set_window_size (f
, change_gravity
, cols
, rows
)
5996 int pixelwidth
, pixelheight
;
6000 check_frame_size (f
, &rows
, &cols
);
6001 f
->scroll_bar_actual_width
6002 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6004 compute_fringe_widths (f
, 0);
6006 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6007 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6009 f
->win_gravity
= NorthWestGravity
;
6010 x_wm_set_size_hint (f
, (long) 0, 0);
6012 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6014 #if USE_CARBON_EVENTS
6015 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6017 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6022 /* Mouse warping. */
6024 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6027 x_set_mouse_position (f
, x
, y
)
6033 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6034 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6036 if (pix_x
< 0) pix_x
= 0;
6037 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6039 if (pix_y
< 0) pix_y
= 0;
6040 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6042 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6046 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6055 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
6061 CGWarpMouseCursorPosition (point
);
6064 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6067 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6068 0, 0, 0, 0, pix_x
, pix_y
);
6074 /* focus shifting, raising and lowering. */
6077 x_focus_on_frame (f
)
6080 #if 0 /* This proves to be unpleasant. */
6084 /* I don't think that the ICCCM allows programs to do things like this
6085 without the interaction of the window manager. Whatever you end up
6086 doing with this code, do it to x_unfocus_frame too. */
6087 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6088 RevertToPointerRoot
, CurrentTime
);
6098 /* Raise frame F. */
6104 if (f
->async_visible
)
6107 BringToFront (FRAME_MAC_WINDOW (f
));
6112 /* Lower frame F. */
6118 if (f
->async_visible
)
6121 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6127 XTframe_raise_lower (f
, raise_flag
)
6137 /* Change of visibility. */
6140 mac_handle_visibility_change (f
)
6143 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6144 int visible
= 0, iconified
= 0;
6145 struct input_event buf
;
6147 if (IsWindowVisible (wp
))
6149 if (IsWindowCollapsed (wp
))
6155 if (!f
->async_visible
&& visible
)
6159 /* wait_reading_process_output will notice this and update
6160 the frame's display structures. If we were made
6161 invisible, we should not set garbaged, because that stops
6162 redrawing on Update events. */
6163 SET_FRAME_GARBAGED (f
);
6166 buf
.kind
= DEICONIFY_EVENT
;
6167 XSETFRAME (buf
.frame_or_window
, f
);
6169 kbd_buffer_store_event (&buf
);
6171 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6172 /* Force a redisplay sooner or later to update the
6173 frame titles in case this is the second frame. */
6174 record_asynch_buffer_change ();
6176 else if (f
->async_visible
&& !visible
)
6180 buf
.kind
= ICONIFY_EVENT
;
6181 XSETFRAME (buf
.frame_or_window
, f
);
6183 kbd_buffer_store_event (&buf
);
6186 f
->async_visible
= visible
;
6187 f
->async_iconified
= iconified
;
6190 /* This tries to wait until the frame is really visible.
6191 However, if the window manager asks the user where to position
6192 the frame, this will return before the user finishes doing that.
6193 The frame will not actually be visible at that time,
6194 but it will become visible later when the window manager
6195 finishes with it. */
6198 x_make_frame_visible (f
)
6203 if (! FRAME_VISIBLE_P (f
))
6205 /* We test FRAME_GARBAGED_P here to make sure we don't
6206 call x_set_offset a second time
6207 if we get to x_make_frame_visible a second time
6208 before the window gets really visible. */
6209 if (! FRAME_ICONIFIED_P (f
)
6210 && ! f
->output_data
.mac
->asked_for_visible
)
6212 #if TARGET_API_MAC_CARBON
6213 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6215 struct frame
*sf
= SELECTED_FRAME ();
6216 if (!FRAME_MAC_P (sf
))
6217 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6218 kWindowCenterOnMainScreen
);
6220 RepositionWindow (FRAME_MAC_WINDOW (f
),
6221 FRAME_MAC_WINDOW (sf
),
6222 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6223 kWindowCascadeStartAtParentWindowScreen
6225 kWindowCascadeOnParentWindowScreen
6228 #if USE_CARBON_EVENTS
6229 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6231 mac_handle_origin_change (f
);
6235 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6238 f
->output_data
.mac
->asked_for_visible
= 1;
6240 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6241 ShowWindow (FRAME_MAC_WINDOW (f
));
6244 XFlush (FRAME_MAC_DISPLAY (f
));
6246 /* Synchronize to ensure Emacs knows the frame is visible
6247 before we do anything else. We do this loop with input not blocked
6248 so that incoming events are handled. */
6253 /* This must come after we set COUNT. */
6256 XSETFRAME (frame
, f
);
6258 /* Wait until the frame is visible. Process X events until a
6259 MapNotify event has been seen, or until we think we won't get a
6260 MapNotify at all.. */
6261 for (count
= input_signal_count
+ 10;
6262 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6264 /* Force processing of queued events. */
6267 /* Machines that do polling rather than SIGIO have been
6268 observed to go into a busy-wait here. So we'll fake an
6269 alarm signal to let the handler know that there's something
6270 to be read. We used to raise a real alarm, but it seems
6271 that the handler isn't always enabled here. This is
6273 if (input_polling_used ())
6275 /* It could be confusing if a real alarm arrives while
6276 processing the fake one. Turn it off and let the
6277 handler reset it. */
6278 extern void poll_for_input_1
P_ ((void));
6279 int old_poll_suppress_count
= poll_suppress_count
;
6280 poll_suppress_count
= 1;
6281 poll_for_input_1 ();
6282 poll_suppress_count
= old_poll_suppress_count
;
6285 /* See if a MapNotify event has been processed. */
6286 FRAME_SAMPLE_VISIBILITY (f
);
6291 /* Change from mapped state to withdrawn state. */
6293 /* Make the frame visible (mapped and not iconified). */
6296 x_make_frame_invisible (f
)
6299 /* A deactivate event does not occur when the last visible frame is
6300 made invisible. So if we clear the highlight here, it will not
6301 be rehighlighted when it is made visible. */
6303 /* Don't keep the highlight on an invisible frame. */
6304 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6305 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6310 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6311 that the current position of the window is user-specified, rather than
6312 program-specified, so that when the window is mapped again, it will be
6313 placed at the same location, without forcing the user to position it
6314 by hand again (they have already done that once for this window.) */
6315 x_wm_set_size_hint (f
, (long) 0, 1);
6317 HideWindow (FRAME_MAC_WINDOW (f
));
6321 #if !USE_CARBON_EVENTS
6322 mac_handle_visibility_change (f
);
6326 /* Change window state from mapped to iconified. */
6334 /* A deactivate event does not occur when the last visible frame is
6335 iconified. So if we clear the highlight here, it will not be
6336 rehighlighted when it is deiconified. */
6338 /* Don't keep the highlight on an invisible frame. */
6339 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6340 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6343 if (f
->async_iconified
)
6348 FRAME_SAMPLE_VISIBILITY (f
);
6350 if (! FRAME_VISIBLE_P (f
))
6351 ShowWindow (FRAME_MAC_WINDOW (f
));
6353 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6358 error ("Can't notify window manager of iconification");
6360 #if !USE_CARBON_EVENTS
6361 mac_handle_visibility_change (f
);
6366 /* Free X resources of frame F. */
6369 x_free_frame_resources (f
)
6372 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6373 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6377 if (wp
!= tip_window
)
6378 remove_window_handler (wp
);
6381 if (wp
== tip_window
)
6382 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6383 closed' event. So we reset tip_window here. */
6386 free_frame_menubar (f
);
6388 if (FRAME_FACE_CACHE (f
))
6389 free_frame_faces (f
);
6393 if (FRAME_SIZE_HINTS (f
))
6394 xfree (FRAME_SIZE_HINTS (f
));
6396 xfree (f
->output_data
.mac
);
6397 f
->output_data
.mac
= NULL
;
6399 if (f
== dpyinfo
->x_focus_frame
)
6401 dpyinfo
->x_focus_frame
= 0;
6402 #if USE_MAC_FONT_PANEL
6403 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
6406 if (f
== dpyinfo
->x_focus_event_frame
)
6407 dpyinfo
->x_focus_event_frame
= 0;
6408 if (f
== dpyinfo
->x_highlight_frame
)
6409 dpyinfo
->x_highlight_frame
= 0;
6411 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6413 dpyinfo
->mouse_face_beg_row
6414 = dpyinfo
->mouse_face_beg_col
= -1;
6415 dpyinfo
->mouse_face_end_row
6416 = dpyinfo
->mouse_face_end_col
= -1;
6417 dpyinfo
->mouse_face_window
= Qnil
;
6418 dpyinfo
->mouse_face_deferred_gc
= 0;
6419 dpyinfo
->mouse_face_mouse_frame
= 0;
6426 /* Destroy the X window of frame F. */
6429 x_destroy_window (f
)
6432 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6434 x_free_frame_resources (f
);
6436 dpyinfo
->reference_count
--;
6440 /* Setting window manager hints. */
6442 /* Set the normal size hints for the window manager, for frame F.
6443 FLAGS is the flags word to use--or 0 meaning preserve the flags
6444 that the window now has.
6445 If USER_POSITION is nonzero, we set the USPosition
6446 flag (this is useful when FLAGS is 0). */
6448 x_wm_set_size_hint (f
, flags
, user_position
)
6453 int base_width
, base_height
, width_inc
, height_inc
;
6454 int min_rows
= 0, min_cols
= 0;
6455 XSizeHints
*size_hints
;
6457 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6458 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6459 width_inc
= FRAME_COLUMN_WIDTH (f
);
6460 height_inc
= FRAME_LINE_HEIGHT (f
);
6462 check_frame_size (f
, &min_rows
, &min_cols
);
6464 size_hints
= FRAME_SIZE_HINTS (f
);
6465 if (size_hints
== NULL
)
6467 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6468 bzero (size_hints
, sizeof (XSizeHints
));
6471 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6472 size_hints
->width_inc
= width_inc
;
6473 size_hints
->height_inc
= height_inc
;
6474 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6475 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6476 size_hints
->base_width
= base_width
;
6477 size_hints
->base_height
= base_height
;
6480 size_hints
->flags
= flags
;
6481 else if (user_position
)
6483 size_hints
->flags
&= ~ PPosition
;
6484 size_hints
->flags
|= USPosition
;
6488 #if 0 /* MAC_TODO: hide application instead of iconify? */
6489 /* Used for IconicState or NormalState */
6492 x_wm_set_window_state (f
, state
)
6496 #ifdef USE_X_TOOLKIT
6499 XtSetArg (al
[0], XtNinitialState
, state
);
6500 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6501 #else /* not USE_X_TOOLKIT */
6502 Window window
= FRAME_X_WINDOW (f
);
6504 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6505 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6507 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6508 #endif /* not USE_X_TOOLKIT */
6512 x_wm_set_icon_pixmap (f
, pixmap_id
)
6518 #ifndef USE_X_TOOLKIT
6519 Window window
= FRAME_X_WINDOW (f
);
6524 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6525 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6529 /* It seems there is no way to turn off use of an icon pixmap.
6530 The following line does it, only if no icon has yet been created,
6531 for some window managers. But with mwm it crashes.
6532 Some people say it should clear the IconPixmapHint bit in this case,
6533 but that doesn't work, and the X consortium said it isn't the
6534 right thing at all. Since there is no way to win,
6535 best to explicitly give up. */
6537 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6543 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6547 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6548 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6551 #else /* not USE_X_TOOLKIT */
6553 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6554 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6556 #endif /* not USE_X_TOOLKIT */
6559 #endif /* MAC_TODO */
6562 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6566 #if 0 /* MAC_TODO: no icons on Mac */
6567 #ifdef USE_X_TOOLKIT
6568 Window window
= XtWindow (f
->output_data
.x
->widget
);
6570 Window window
= FRAME_X_WINDOW (f
);
6573 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6574 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6575 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6577 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6578 #endif /* MAC_TODO */
6582 /***********************************************************************
6584 ***********************************************************************/
6586 /* An XLFD pattern is divided into blocks delimited by '*'. This
6587 structure holds information for each block. */
6588 struct xlfdpat_block
6590 /* Length of the pattern string in this block. Non-zero except for
6591 the first and the last blocks. */
6594 /* Pattern string except the last character in this block. The last
6595 character is replaced with NUL in order to use it as a
6597 unsigned char *pattern
;
6599 /* Last character of the pattern string. Must not be '?'. */
6600 unsigned char last_char
;
6602 /* One of the tables for the Boyer-Moore string search. It
6603 specifies the number of positions to proceed for each character
6604 with which the match fails. */
6607 /* The skip value for the last character in the above `skip' is
6608 assigned to `infinity' in order to simplify a loop condition.
6609 The original value is saved here. */
6615 /* Normalized pattern string. "Normalized" means that capital
6616 letters are lowered, blocks are not empty except the first and
6617 the last ones, and trailing '?'s in a block that is not the last
6618 one are moved to the next one. The last character in each block
6619 is replaced with NUL. */
6622 /* Number of characters except '*'s and trailing '?'s in the
6623 normalized pattern string. */
6626 /* Number of trailing '?'s in the normalized pattern string. */
6627 int trailing_anychars
;
6629 /* Number of blocks and information for each block. The latter is
6630 NULL if the pattern is exact (no '*' or '?' in it). */
6632 struct xlfdpat_block
*blocks
;
6636 xlfdpat_destroy (pat
)
6637 struct xlfdpat
*pat
;
6644 xfree (pat
->blocks
);
6651 static struct xlfdpat
*
6652 xlfdpat_create (pattern
)
6655 struct xlfdpat
*pat
;
6656 int nblocks
, i
, skip
;
6657 unsigned char last_char
, *p
, *q
, *anychar_head
;
6658 struct xlfdpat_block
*blk
;
6660 pat
= xmalloc (sizeof (struct xlfdpat
));
6661 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6663 /* Normalize the pattern string and store it to `pat->buf'. */
6665 anychar_head
= NULL
;
6668 for (p
= pattern
; *p
; p
++)
6670 unsigned char c
= *p
;
6673 if (last_char
== '*')
6674 /* ...a** -> ...a* */
6678 if (last_char
== '?')
6680 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6681 /* ...*??* -> ...*?? */
6684 /* ...a??* -> ...a*?? */
6686 *anychar_head
++ = '*';
6694 if (last_char
!= '?')
6698 /* On Mac OS X 10.3, tolower also converts non-ASCII
6699 characters for some locales. */
6703 *q
++ = last_char
= c
;
6707 pat
->nblocks
= nblocks
;
6708 if (last_char
!= '?')
6709 pat
->trailing_anychars
= 0;
6712 pat
->trailing_anychars
= q
- anychar_head
;
6715 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6717 if (anychar_head
== NULL
&& nblocks
== 1)
6719 /* The pattern is exact. */
6724 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6726 /* Divide the normalized pattern into blocks. */
6728 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6733 blk
->len
= p
- blk
->pattern
;
6737 blk
->len
= q
- blk
->pattern
;
6739 /* Setup a table for the Boyer-Moore string search. */
6740 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6743 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6744 blk
->pattern
[blk
->len
- 1] = '\0';
6746 for (skip
= 1; skip
< blk
->len
; skip
++)
6747 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6750 for (i
= 0; i
< 256; i
++)
6751 blk
->skip
[i
] = skip
;
6753 p
= blk
->pattern
+ (blk
->len
- skip
);
6755 blk
->skip
[*p
++] = skip
;
6757 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6764 xlfdpat_exact_p (pat
)
6765 struct xlfdpat
*pat
;
6767 return pat
->blocks
== NULL
;
6770 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6771 that the pattern in *BLK matches with its prefix. Return NULL
6772 there is no such strings. STRING must be lowered in advance. */
6775 xlfdpat_block_match_1 (blk
, string
, start_max
)
6776 struct xlfdpat_block
*blk
;
6777 unsigned char *string
;
6780 int start
, infinity
;
6781 unsigned char *p
, *s
;
6783 xassert (blk
->len
> 0);
6784 xassert (start_max
+ blk
->len
<= strlen (string
));
6785 xassert (blk
->last_char
!= '?');
6787 /* See the comments in the function `boyer_moore' (search.c) for the
6788 use of `infinity'. */
6789 infinity
= start_max
+ blk
->len
+ 1;
6790 blk
->skip
[blk
->last_char
] = infinity
;
6795 /* Check the last character of the pattern. */
6796 s
= string
+ blk
->len
- 1;
6799 start
+= blk
->skip
[*(s
+ start
)];
6801 while (start
<= start_max
);
6803 if (start
< infinity
)
6804 /* Couldn't find the last character. */
6807 /* No less than `infinity' means we could find the last
6808 character at `s[start - infinity]'. */
6811 /* Check the remaining characters. We prefer making no-'?'
6812 cases faster because the use of '?' is really rare. */
6817 while (*p
++ == *s
++)
6820 while (*(p
- 1) == '?');
6822 if (*(p
- 1) == '\0')
6824 return string
+ start
;
6827 start
+= blk
->last_char_skip
;
6829 while (start
<= start_max
);
6834 #define xlfdpat_block_match(b, s, m) \
6835 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6836 : xlfdpat_block_match_1 (b, s, m))
6838 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6839 matches with STRING. STRING must be lowered in advance. */
6842 xlfdpat_match (pat
, string
)
6843 struct xlfdpat
*pat
;
6844 unsigned char *string
;
6846 int str_len
, nblocks
, i
, start_max
;
6847 struct xlfdpat_block
*blk
;
6850 xassert (pat
->nblocks
> 0);
6852 if (xlfdpat_exact_p (pat
))
6853 return strcmp (pat
->buf
, string
) == 0;
6855 /* The number of the characters in the string must not be smaller
6856 than that in the pattern. */
6857 str_len
= strlen (string
);
6858 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6861 /* Chop off the trailing '?'s. */
6862 str_len
-= pat
->trailing_anychars
;
6864 /* The last block. When it is non-empty, it must match at the end
6866 nblocks
= pat
->nblocks
;
6867 blk
= pat
->blocks
+ (nblocks
- 1);
6869 /* The last block is also the first one. */
6870 return (str_len
== blk
->len
6871 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6872 else if (blk
->len
!= 0)
6873 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6876 /* The first block. When it is non-empty, it must match at the
6877 beginning of the string. */
6881 s
= xlfdpat_block_match (blk
, string
, 0);
6884 string
= s
+ blk
->len
;
6887 /* The rest of the blocks. */
6888 start_max
= str_len
- pat
->nchars
;
6889 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6891 s
= xlfdpat_block_match (blk
, string
, start_max
);
6894 start_max
-= s
- string
;
6895 string
= s
+ blk
->len
;
6902 /***********************************************************************
6904 ***********************************************************************/
6906 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6909 x_get_font_info (f
, font_idx
)
6913 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6916 /* the global font name table */
6917 static char **font_name_table
= NULL
;
6918 static int font_name_table_size
= 0;
6919 static int font_name_count
= 0;
6921 /* Alist linking font family names to Font Manager font family
6922 references (which can also be used as QuickDraw font IDs). We use
6923 an alist because hash tables are not ready when the terminal frame
6924 for Mac OS Classic is created. */
6925 static Lisp_Object fm_font_family_alist
;
6927 /* Hash table linking font family names to ATSU font IDs. */
6928 static Lisp_Object atsu_font_id_hash
;
6929 /* Alist linking Font Manager style to face attributes. */
6930 static Lisp_Object fm_style_face_attributes_alist
;
6931 static Lisp_Object Vmac_atsu_font_table
;
6932 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
6935 /* Alist linking character set strings to Mac text encoding and Emacs
6937 static Lisp_Object Vmac_charset_info_alist
;
6940 create_text_encoding_info_alist ()
6942 Lisp_Object result
= Qnil
, rest
;
6944 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6946 Lisp_Object charset_info
= XCAR (rest
);
6947 Lisp_Object charset
, coding_system
, text_encoding
;
6948 Lisp_Object existing_info
;
6950 if (!(CONSP (charset_info
)
6951 && STRINGP (charset
= XCAR (charset_info
))
6952 && CONSP (XCDR (charset_info
))
6953 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6954 && CONSP (XCDR (XCDR (charset_info
)))
6955 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6958 existing_info
= assq_no_quit (text_encoding
, result
);
6959 if (NILP (existing_info
))
6960 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6963 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6964 XSETCDR (XCDR (existing_info
),
6965 Fcons (charset
, XCDR (XCDR (existing_info
))));
6973 decode_mac_font_name (name
, size
, coding_system
)
6976 Lisp_Object coding_system
;
6978 struct coding_system coding
;
6981 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6983 for (p
= name
; *p
; p
++)
6984 if (!isascii (*p
) || iscntrl (*p
))
6989 setup_coding_system (coding_system
, &coding
);
6990 coding
.src_multibyte
= 0;
6991 coding
.dst_multibyte
= 1;
6992 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6993 coding
.composing
= COMPOSITION_DISABLED
;
6994 buf
= (char *) alloca (size
);
6996 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6997 bcopy (buf
, name
, coding
.produced
);
6998 name
[coding
.produced
] = '\0';
7002 /* If there's just one occurrence of '-' in the family name, it is
7003 replaced with '_'. (More than one occurrence of '-' means a
7004 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7005 p
= strchr (name
, '-');
7006 if (p
&& strchr (p
+ 1, '-') == NULL
)
7009 for (p
= name
; *p
; p
++)
7010 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7011 for some locales. */
7018 mac_to_x_fontname (name
, size
, style
, charset
)
7026 char xf
[256], *result
;
7029 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7033 strcpy(foundry
, "Apple");
7034 strcpy(family
, name
);
7037 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7038 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7039 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7041 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7042 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7043 for (p
= result
; *p
; p
++)
7044 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7045 for some locales. */
7052 /* Parse fully-specified and instantiated X11 font spec XF, and store
7053 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7054 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7055 caller must allocate at least 256 and 32 bytes respectively. For
7056 ordinary Mac fonts, the value stored to FAMILY should just be their
7057 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7058 intlfonts collection contain their charset designation in their
7059 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7060 types of font names are handled accordingly. */
7062 const int kDefaultFontSize
= 12;
7065 parse_x_font_name (xf
, family
, size
, style
, charset
)
7071 Str31 foundry
, weight
;
7072 int point_size
, avgwidth
;
7075 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7076 foundry
, family
, weight
, slant
, size
,
7077 &point_size
, &avgwidth
, charset
) != 8
7078 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7079 foundry
, family
, weight
, slant
, size
,
7080 &point_size
, &avgwidth
, charset
) != 8)
7086 *size
= point_size
/ 10;
7087 else if (avgwidth
> 0)
7088 *size
= avgwidth
/ 10;
7091 *size
= kDefaultFontSize
;
7094 if (strcmp (weight
, "bold") == 0)
7099 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7101 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7103 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7105 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7106 but take overlap into account. */
7107 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7108 memcpy (family
, foundry
, foundry_len
);
7109 family
[foundry_len
] = '-';
7110 family
[foundry_len
+ 1 + family_len
] = '-';
7111 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7117 for (p
= family
; *p
; p
++)
7118 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7119 for some locales. */
7128 add_font_name_table_entry (char *font_name
)
7130 if (font_name_table_size
== 0)
7132 font_name_table_size
= 256;
7133 font_name_table
= (char **)
7134 xmalloc (font_name_table_size
* sizeof (char *));
7136 else if (font_name_count
+ 1 >= font_name_table_size
)
7138 font_name_table_size
*= 2;
7139 font_name_table
= (char **)
7140 xrealloc (font_name_table
,
7141 font_name_table_size
* sizeof (char *));
7144 font_name_table
[font_name_count
++] = font_name
;
7148 add_mac_font_name (name
, size
, style
, charset
)
7155 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7158 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7159 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
7160 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
7161 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
7168 fm_style_to_face_attributes (fm_style
)
7169 FMFontStyle fm_style
;
7173 fm_style
&= (bold
| italic
);
7174 tem
= assq_no_quit (make_number (fm_style
),
7175 fm_style_face_attributes_alist
);
7179 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
7180 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
7181 fm_style_face_attributes_alist
=
7182 Fcons (Fcons (make_number (fm_style
), tem
),
7183 fm_style_face_attributes_alist
);
7189 /* Sets up the table font_name_table to contain the list of all fonts
7190 in the system the first time the table is used so that the Resource
7191 Manager need not be accessed every time this information is
7195 init_font_name_table ()
7197 #if TARGET_API_MAC_CARBON
7198 FMFontFamilyIterator ffi
;
7199 FMFontFamilyInstanceIterator ffii
;
7201 Lisp_Object text_encoding_info_alist
;
7202 struct gcpro gcpro1
;
7204 text_encoding_info_alist
= create_text_encoding_info_alist ();
7207 #if USE_CG_TEXT_DRAWING
7208 init_cg_text_anti_aliasing_threshold ();
7210 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7211 text_encoding_info_alist
)))
7214 struct Lisp_Hash_Table
*h
;
7216 ItemCount nfonts
, i
;
7217 ATSUFontID
*font_ids
= NULL
;
7223 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7224 make_float (DEFAULT_REHASH_SIZE
),
7225 make_float (DEFAULT_REHASH_THRESHOLD
),
7227 h
= XHASH_TABLE (atsu_font_id_hash
);
7229 err
= ATSUFontCount (&nfonts
);
7232 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7233 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7236 for (i
= 0; i
< nfonts
; i
++)
7238 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7239 kFontMacintoshPlatform
, kFontNoScript
,
7240 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
7243 name
= xmalloc (name_len
+ 1);
7244 name
[name_len
] = '\0';
7245 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7246 kFontMacintoshPlatform
, kFontNoScript
,
7247 kFontNoLanguage
, name_len
, name
,
7252 FMFontStyle style
= normal
;
7254 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
7255 family
= make_unibyte_string (name
, name_len
);
7256 FMGetFontFamilyInstanceFromFont (font_ids
[i
], &ff
, &style
);
7257 Fputhash ((font_ids
[i
] > MOST_POSITIVE_FIXNUM
7258 ? make_float (font_ids
[i
])
7259 : make_number (font_ids
[i
])),
7262 fm_style_to_face_attributes (style
))),
7263 Vmac_atsu_font_table
);
7265 && hash_lookup (h
, family
, &hash_code
) < 0)
7267 add_mac_font_name (name
, 0, normal
, "iso10646-1");
7268 hash_put (h
, family
, long_to_cons (font_ids
[i
]),
7279 /* Create a dummy instance iterator here to avoid creating and
7280 destroying it in the loop. */
7281 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7283 /* Create an iterator to enumerate the font families. */
7284 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7287 FMDisposeFontFamilyInstanceIterator (&ffii
);
7291 GCPRO1 (text_encoding_info_alist
);
7293 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7299 TextEncoding encoding
;
7300 TextEncodingBase sc
;
7301 Lisp_Object text_encoding_info
, family
;
7303 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7309 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7311 sc
= GetTextEncodingBase (encoding
);
7312 text_encoding_info
= assq_no_quit (make_number (sc
),
7313 text_encoding_info_alist
);
7314 if (NILP (text_encoding_info
))
7315 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7316 text_encoding_info_alist
);
7317 decode_mac_font_name (name
, sizeof (name
),
7318 XCAR (XCDR (text_encoding_info
)));
7319 family
= build_string (name
);
7320 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7322 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7323 fm_font_family_alist
);
7325 /* Point the instance iterator at the current font family. */
7326 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7329 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7332 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7334 if (size
> 0 || style
== normal
)
7335 for (; !NILP (rest
); rest
= XCDR (rest
))
7336 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7342 /* Dispose of the iterators. */
7343 FMDisposeFontFamilyIterator (&ffi
);
7344 FMDisposeFontFamilyInstanceIterator (&ffii
);
7345 #else /* !TARGET_API_MAC_CARBON */
7347 SInt16 fontnum
, old_fontnum
;
7348 int num_mac_fonts
= CountResources('FOND');
7350 Handle font_handle
, font_handle_2
;
7351 short id
, scriptcode
;
7354 struct FontAssoc
*fat
;
7355 struct AsscEntry
*assc_entry
;
7356 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7357 struct gcpro gcpro1
;
7359 GetPort (&port
); /* save the current font number used */
7360 old_fontnum
= port
->txFont
;
7362 text_encoding_info_alist
= create_text_encoding_info_alist ();
7364 GCPRO1 (text_encoding_info_alist
);
7366 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7368 font_handle
= GetIndResource ('FOND', i
);
7372 GetResInfo (font_handle
, &id
, &type
, name
);
7373 GetFNum (name
, &fontnum
);
7375 if (fontnum
== 0 || *name
== '.')
7379 scriptcode
= FontToScript (fontnum
);
7380 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7381 text_encoding_info_alist
);
7382 if (NILP (text_encoding_info
))
7383 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7384 text_encoding_info_alist
);
7385 decode_mac_font_name (name
, sizeof (name
),
7386 XCAR (XCDR (text_encoding_info
)));
7387 family
= build_string (name
);
7388 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7390 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7391 fm_font_family_alist
);
7394 HLock (font_handle
);
7396 if (GetResourceSizeOnDisk (font_handle
)
7397 >= sizeof (struct FamRec
))
7399 fat
= (struct FontAssoc
*) (*font_handle
7400 + sizeof (struct FamRec
));
7402 = (struct AsscEntry
*) (*font_handle
7403 + sizeof (struct FamRec
)
7404 + sizeof (struct FontAssoc
));
7406 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7408 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7410 for (; !NILP (rest
); rest
= XCDR (rest
))
7411 add_mac_font_name (name
, assc_entry
->fontSize
,
7412 assc_entry
->fontStyle
,
7413 SDATA (XCAR (rest
)));
7417 HUnlock (font_handle
);
7418 font_handle_2
= GetNextFOND (font_handle
);
7419 ReleaseResource (font_handle
);
7420 font_handle
= font_handle_2
;
7422 while (ResError () == noErr
&& font_handle
);
7427 TextFont (old_fontnum
);
7428 #endif /* !TARGET_API_MAC_CARBON */
7433 mac_clear_font_name_table ()
7437 for (i
= 0; i
< font_name_count
; i
++)
7438 xfree (font_name_table
[i
]);
7439 xfree (font_name_table
);
7440 font_name_table
= NULL
;
7441 font_name_table_size
= font_name_count
= 0;
7442 fm_font_family_alist
= Qnil
;
7446 enum xlfd_scalable_field_index
7448 XLFD_SCL_PIXEL_SIZE
,
7449 XLFD_SCL_POINT_SIZE
,
7454 static int xlfd_scalable_fields
[] =
7463 mac_do_list_fonts (pattern
, maxnames
)
7468 Lisp_Object font_list
= Qnil
;
7469 struct xlfdpat
*pat
;
7471 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7474 if (font_name_table
== NULL
) /* Initialize when first used. */
7475 init_font_name_table ();
7477 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7480 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7481 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7482 fonts are scaled according to the specified size. */
7485 field
= xlfd_scalable_fields
;
7493 if ('0' <= *ptr
&& *ptr
<= '9')
7495 *val
= *ptr
++ - '0';
7496 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7497 *val
= *val
* 10 + *ptr
++ - '0';
7504 ptr
= strchr (ptr
, '-');
7507 while (ptr
&& i
< 14);
7509 if (i
== 14 && ptr
== NULL
)
7511 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7512 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7513 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7514 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7516 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7517 scl_val
[XLFD_SCL_POINT_SIZE
] =
7518 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7519 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7521 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7522 scl_val
[XLFD_SCL_AVGWIDTH
] =
7523 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7524 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7528 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7530 pat
= xlfdpat_create (pattern
);
7534 exact
= xlfdpat_exact_p (pat
);
7536 for (i
= 0; i
< font_name_count
; i
++)
7538 if (xlfdpat_match (pat
, font_name_table
[i
]))
7540 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7541 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7544 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7545 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7547 int former_len
= ptr
- font_name_table
[i
];
7549 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7550 memcpy (scaled
, font_name_table
[i
], former_len
);
7551 sprintf (scaled
+ former_len
,
7552 "-%d-%d-72-72-m-%d-%s",
7553 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7554 scl_val
[XLFD_SCL_POINT_SIZE
],
7555 scl_val
[XLFD_SCL_AVGWIDTH
],
7556 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7558 if (xlfdpat_match (pat
, scaled
))
7560 font_list
= Fcons (build_string (scaled
), font_list
);
7562 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7570 xlfdpat_destroy (pat
);
7575 /* Return a list of names of available fonts matching PATTERN on frame F.
7577 Frame F null means we have not yet created any frame on Mac, and
7578 consult the first display in x_display_list. MAXNAMES sets a limit
7579 on how many fonts to match. */
7582 x_list_fonts (f
, pattern
, size
, maxnames
)
7584 Lisp_Object pattern
;
7587 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7588 struct mac_display_info
*dpyinfo
7589 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7591 xassert (size
<= 0);
7593 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7594 if (NILP (patterns
))
7595 patterns
= Fcons (pattern
, Qnil
);
7597 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7599 pattern
= XCAR (patterns
);
7601 if (!STRINGP (pattern
))
7604 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7605 key
= Fcons (pattern
, make_number (maxnames
));
7607 list
= Fassoc (key
, tem
);
7610 list
= Fcdr_safe (list
);
7611 /* We have a cashed list. Don't have to get the list again. */
7616 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7619 /* MAC_TODO: add code for matching outline fonts here */
7621 /* Now store the result in the cache. */
7622 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7623 Fcons (Fcons (key
, list
),
7624 XCAR (XCDR (dpyinfo
->name_list_element
))));
7627 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7636 /* Check that FONT is valid on frame F. It is if it can be found in F's
7640 x_check_font (f
, font
)
7645 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7647 xassert (font
!= NULL
);
7649 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7650 if (dpyinfo
->font_table
[i
].name
7651 && font
== dpyinfo
->font_table
[i
].font
)
7654 xassert (i
< dpyinfo
->n_fonts
);
7657 #endif /* GLYPH_DEBUG != 0 */
7659 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7660 Note: There are (broken) X fonts out there with invalid XFontStruct
7661 min_bounds contents. For example, handa@etl.go.jp reports that
7662 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7663 have font->min_bounds.width == 0. */
7666 x_font_min_bounds (font
, w
, h
)
7667 MacFontStruct
*font
;
7670 *h
= FONT_HEIGHT (font
);
7671 *w
= font
->min_bounds
.width
;
7675 /* Compute the smallest character width and smallest font height over
7676 all fonts available on frame F. Set the members smallest_char_width
7677 and smallest_font_height in F's x_display_info structure to
7678 the values computed. Value is non-zero if smallest_font_height or
7679 smallest_char_width become smaller than they were before. */
7682 x_compute_min_glyph_bounds (f
)
7686 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7687 MacFontStruct
*font
;
7688 int old_width
= dpyinfo
->smallest_char_width
;
7689 int old_height
= dpyinfo
->smallest_font_height
;
7691 dpyinfo
->smallest_font_height
= 100000;
7692 dpyinfo
->smallest_char_width
= 100000;
7694 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7695 if (dpyinfo
->font_table
[i
].name
)
7697 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7700 font
= (MacFontStruct
*) fontp
->font
;
7701 xassert (font
!= (MacFontStruct
*) ~0);
7702 x_font_min_bounds (font
, &w
, &h
);
7704 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7705 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7708 xassert (dpyinfo
->smallest_char_width
> 0
7709 && dpyinfo
->smallest_font_height
> 0);
7711 return (dpyinfo
->n_fonts
== 1
7712 || dpyinfo
->smallest_char_width
< old_width
7713 || dpyinfo
->smallest_font_height
< old_height
);
7717 /* Determine whether given string is a fully-specified XLFD: all 14
7718 fields are present, none is '*'. */
7721 is_fully_specified_xlfd (char *p
)
7729 for (i
= 0; i
< 13; i
++)
7731 q
= strchr (p
+ 1, '-');
7734 if (q
- p
== 2 && *(p
+ 1) == '*')
7739 if (strchr (p
+ 1, '-') != NULL
)
7742 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7749 /* XLoadQueryFont creates and returns an internal representation for a
7750 font in a MacFontStruct struct. There is really no concept
7751 corresponding to "loading" a font on the Mac. But we check its
7752 existence and find the font number and all other information for it
7753 and store them in the returned MacFontStruct. */
7755 static MacFontStruct
*
7756 XLoadQueryFont (Display
*dpy
, char *fontname
)
7764 static ATSUFontID font_id
;
7765 ATSUStyle mac_style
= NULL
;
7768 #if TARGET_API_MAC_CARBON
7769 TextEncoding encoding
;
7774 MacFontStruct
*font
;
7775 XCharStruct
*space_bounds
= NULL
, *pcm
;
7777 if (is_fully_specified_xlfd (fontname
))
7781 Lisp_Object matched_fonts
;
7783 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7784 if (NILP (matched_fonts
))
7786 name
= SDATA (XCAR (matched_fonts
));
7789 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7793 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7796 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7797 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7798 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7799 sizeof (Boolean
), sizeof (Boolean
)};
7800 static Fixed size_fixed
;
7801 static Boolean bold_p
, italic_p
;
7802 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7803 &bold_p
, &italic_p
};
7804 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
,
7806 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
,
7807 kDecomposeDiacriticsSelector
};
7808 Lisp_Object font_id_cons
;
7811 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7812 atsu_font_id_hash
, Qnil
);
7813 if (NILP (font_id_cons
))
7815 font_id
= cons_to_long (font_id_cons
);
7816 size_fixed
= Long2Fix (size
);
7817 bold_p
= (fontface
& bold
) != 0;
7818 italic_p
= (fontface
& italic
) != 0;
7819 err
= ATSUCreateStyle (&mac_style
);
7822 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7826 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7827 tags
, sizes
, values
);
7830 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
7833 scriptcode
= kTextEncodingMacUnicode
;
7838 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7842 fontnum
= XINT (XCDR (tmp
));
7843 #if TARGET_API_MAC_CARBON
7844 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7846 scriptcode
= GetTextEncodingBase (encoding
);
7848 scriptcode
= FontToScript (fontnum
);
7852 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7854 font
->mac_fontnum
= fontnum
;
7855 font
->mac_fontsize
= size
;
7856 font
->mac_fontface
= fontface
;
7857 font
->mac_scriptcode
= scriptcode
;
7859 font
->mac_style
= mac_style
;
7860 #if USE_CG_TEXT_DRAWING
7861 font
->cg_font
= NULL
;
7862 font
->cg_glyphs
= NULL
;
7866 /* Apple Japanese (SJIS) font is listed as both
7867 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7868 (Roman script) in init_font_name_table (). The latter should be
7869 treated as a one-byte font. */
7870 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7871 font
->mac_scriptcode
= smRoman
;
7873 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7876 if (font
->mac_style
)
7881 font
->min_byte1
= 0;
7882 font
->max_byte1
= 0xff;
7883 font
->min_char_or_byte2
= 0;
7884 font
->max_char_or_byte2
= 0xff;
7886 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
7887 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
7888 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
7889 pcm_init (font
->bounds
.rows
[0], 0x100);
7891 #if USE_CG_TEXT_DRAWING
7895 ATSFontRef ats_font
;
7897 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
7899 /* Use CG text drawing if italic/bold is not synthesized. */
7900 if (err
== noErr
&& style
== fontface
)
7902 ats_font
= FMGetATSFontRefFromFont (font_id
);
7903 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7909 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7910 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7913 space_bounds
= font
->bounds
.rows
[0] + 0x20;
7914 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7915 &font
->ascent
, &font
->descent
,
7917 #if USE_CG_TEXT_DRAWING
7918 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7926 mac_unload_font (&one_mac_display_info
, font
);
7930 pcm
= font
->bounds
.rows
[0];
7931 for (c
= 0x21; c
<= 0xff; c
++)
7934 /* Soft hyphen is not supported in ATSUI. */
7942 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
7943 #if USE_CG_TEXT_DRAWING
7944 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7951 #if USE_CG_TEXT_DRAWING
7952 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7954 /* Don't use CG text drawing if font substitution occurs in
7955 ASCII or Latin-1 characters. */
7956 CGFontRelease (font
->cg_font
);
7957 font
->cg_font
= NULL
;
7958 xfree (font
->cg_glyphs
);
7959 font
->cg_glyphs
= NULL
;
7968 SInt16 old_fontnum
, old_fontsize
;
7970 FontInfo the_fontinfo
;
7971 int is_two_byte_font
;
7973 /* Save the current font number used. */
7975 #if TARGET_API_MAC_CARBON
7976 old_fontnum
= GetPortTextFont (port
);
7977 old_fontsize
= GetPortTextSize (port
);
7978 old_fontface
= GetPortTextFace (port
);
7980 old_fontnum
= port
->txFont
;
7981 old_fontsize
= port
->txSize
;
7982 old_fontface
= port
->txFace
;
7987 TextFace (fontface
);
7989 GetFontInfo (&the_fontinfo
);
7991 font
->ascent
= the_fontinfo
.ascent
;
7992 font
->descent
= the_fontinfo
.descent
;
7994 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7995 || font
->mac_scriptcode
== smTradChinese
7996 || font
->mac_scriptcode
== smSimpChinese
7997 || font
->mac_scriptcode
== smKorean
);
7999 if (is_two_byte_font
)
8003 font
->min_byte1
= 0xa1;
8004 font
->max_byte1
= 0xfe;
8005 font
->min_char_or_byte2
= 0xa1;
8006 font
->max_char_or_byte2
= 0xfe;
8008 /* Use the width of an "ideographic space" of that font
8009 because the_fontinfo.widMax returns the wrong width for
8011 switch (font
->mac_scriptcode
)
8014 font
->min_byte1
= 0x81;
8015 font
->max_byte1
= 0xfc;
8016 font
->min_char_or_byte2
= 0x40;
8017 font
->max_char_or_byte2
= 0xfc;
8018 char_width
= StringWidth("\p\x81\x40");
8021 font
->min_char_or_byte2
= 0x40;
8022 char_width
= StringWidth("\p\xa1\x40");
8025 char_width
= StringWidth("\p\xa1\xa1");
8028 char_width
= StringWidth("\p\xa1\xa1");
8032 font
->bounds
.per_char
= NULL
;
8034 if (fontface
& italic
)
8035 font
->max_bounds
.rbearing
= char_width
+ 1;
8037 font
->max_bounds
.rbearing
= char_width
;
8038 font
->max_bounds
.lbearing
= 0;
8039 font
->max_bounds
.width
= char_width
;
8040 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8041 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8043 font
->min_bounds
= font
->max_bounds
;
8049 font
->min_byte1
= font
->max_byte1
= 0;
8050 font
->min_char_or_byte2
= 0x20;
8051 font
->max_char_or_byte2
= 0xff;
8053 font
->bounds
.per_char
=
8054 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8055 bzero (font
->bounds
.per_char
,
8056 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8058 space_bounds
= font
->bounds
.per_char
;
8059 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
8060 space_bounds
, NULL
);
8062 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8063 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8066 /* Restore previous font number, size and face. */
8067 TextFont (old_fontnum
);
8068 TextSize (old_fontsize
);
8069 TextFace (old_fontface
);
8076 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8077 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8080 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8082 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8084 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8086 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8089 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8091 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8093 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8095 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8100 font
->mac_style
== NULL
&&
8102 font
->max_bounds
.width
== font
->min_bounds
.width
8103 && font
->min_bounds
.lbearing
>= 0
8104 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8106 /* Fixed width and no overhangs. */
8107 xfree (font
->bounds
.per_char
);
8108 font
->bounds
.per_char
= NULL
;
8112 #if !defined (MAC_OS8) || USE_ATSUI
8113 /* AppKit and WebKit do some adjustment to the heights of Courier,
8114 Helvetica, and Times. This only works on the environments where
8115 srcCopy text transfer mode is never used. */
8117 #ifdef MAC_OS8 /* implies USE_ATSUI */
8120 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8121 || strcmp (family
, "times") == 0))
8122 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8130 mac_unload_font (dpyinfo
, font
)
8131 struct mac_display_info
*dpyinfo
;
8134 xfree (font
->full_name
);
8136 if (font
->mac_style
)
8140 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8141 if (font
->bounds
.rows
[i
])
8142 xfree (font
->bounds
.rows
[i
]);
8143 xfree (font
->bounds
.rows
);
8144 ATSUDisposeStyle (font
->mac_style
);
8148 if (font
->bounds
.per_char
)
8149 xfree (font
->bounds
.per_char
);
8150 #if USE_CG_TEXT_DRAWING
8152 CGFontRelease (font
->cg_font
);
8153 if (font
->cg_glyphs
)
8154 xfree (font
->cg_glyphs
);
8160 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8161 pointer to the structure font_info while allocating it dynamically.
8162 If SIZE is 0, load any size of font.
8163 If loading is failed, return NULL. */
8166 x_load_font (f
, fontname
, size
)
8168 register char *fontname
;
8171 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8172 Lisp_Object font_names
;
8174 /* Get a list of all the fonts that match this name. Once we
8175 have a list of matching fonts, we compare them against the fonts
8176 we already have by comparing names. */
8177 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8179 if (!NILP (font_names
))
8184 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8185 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8186 if (dpyinfo
->font_table
[i
].name
8187 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8188 SDATA (XCAR (tail
)))
8189 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8190 SDATA (XCAR (tail
)))))
8191 return (dpyinfo
->font_table
+ i
);
8196 /* Load the font and add it to the table. */
8198 struct MacFontStruct
*font
;
8199 struct font_info
*fontp
;
8202 fontname
= (char *) SDATA (XCAR (font_names
));
8205 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
8210 /* Find a free slot in the font table. */
8211 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8212 if (dpyinfo
->font_table
[i
].name
== NULL
)
8215 /* If no free slot found, maybe enlarge the font table. */
8216 if (i
== dpyinfo
->n_fonts
8217 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8220 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8221 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8223 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8226 fontp
= dpyinfo
->font_table
+ i
;
8227 if (i
== dpyinfo
->n_fonts
)
8230 /* Now fill in the slots of *FONTP. */
8232 bzero (fontp
, sizeof (*fontp
));
8234 fontp
->font_idx
= i
;
8235 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8236 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8238 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8240 /* Fixed width font. */
8241 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8248 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8249 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8251 fontp
->space_width
= pcm
->width
;
8253 fontp
->space_width
= FONT_WIDTH (font
);
8257 int width
= pcm
->width
;
8258 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8259 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8260 width
+= pcm
->width
;
8261 fontp
->average_width
= width
/ 95;
8264 fontp
->average_width
= FONT_WIDTH (font
);
8267 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8268 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8270 fontp
->size
= font
->max_bounds
.width
;
8271 fontp
->height
= FONT_HEIGHT (font
);
8273 /* For some font, ascent and descent in max_bounds field is
8274 larger than the above value. */
8275 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8276 if (max_height
> fontp
->height
)
8277 fontp
->height
= max_height
;
8280 /* The slot `encoding' specifies how to map a character
8281 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8282 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8283 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8284 2:0xA020..0xFF7F). For the moment, we don't know which charset
8285 uses this font. So, we set information in fontp->encoding[1]
8286 which is never used by any charset. If mapping can't be
8287 decided, set FONT_ENCODING_NOT_DECIDED. */
8288 if (font
->mac_scriptcode
== smJapanese
)
8289 fontp
->encoding
[1] = 4;
8293 = (font
->max_byte1
== 0
8295 ? (font
->min_char_or_byte2
< 0x80
8296 ? (font
->max_char_or_byte2
< 0x80
8297 ? 0 /* 0x20..0x7F */
8298 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8299 : 1) /* 0xA0..0xFF */
8301 : (font
->min_byte1
< 0x80
8302 ? (font
->max_byte1
< 0x80
8303 ? (font
->min_char_or_byte2
< 0x80
8304 ? (font
->max_char_or_byte2
< 0x80
8305 ? 0 /* 0x2020..0x7F7F */
8306 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8307 : 3) /* 0x20A0..0x7FFF */
8308 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8309 : (font
->min_char_or_byte2
< 0x80
8310 ? (font
->max_char_or_byte2
< 0x80
8311 ? 2 /* 0xA020..0xFF7F */
8312 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8313 : 1))); /* 0xA0A0..0xFFFF */
8316 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8317 fontp
->baseline_offset
8318 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8319 ? (long) value
: 0);
8320 fontp
->relative_compose
8321 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8322 ? (long) value
: 0);
8323 fontp
->default_ascent
8324 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8325 ? (long) value
: 0);
8327 fontp
->baseline_offset
= 0;
8328 fontp
->relative_compose
= 0;
8329 fontp
->default_ascent
= 0;
8332 /* Set global flag fonts_changed_p to non-zero if the font loaded
8333 has a character with a smaller width than any other character
8334 before, or if the font loaded has a smaller height than any
8335 other font loaded before. If this happens, it will make a
8336 glyph matrix reallocation necessary. */
8337 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8344 /* Return a pointer to struct font_info of a font named FONTNAME for
8345 frame F. If no such font is loaded, return NULL. */
8348 x_query_font (f
, fontname
)
8350 register char *fontname
;
8352 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8355 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8356 if (dpyinfo
->font_table
[i
].name
8357 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
8358 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8359 return (dpyinfo
->font_table
+ i
);
8364 /* Find a CCL program for a font specified by FONTP, and set the member
8365 `encoder' of the structure. */
8368 x_find_ccl_program (fontp
)
8369 struct font_info
*fontp
;
8371 Lisp_Object list
, elt
;
8373 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8377 && STRINGP (XCAR (elt
))
8378 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8384 struct ccl_program
*ccl
8385 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8387 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8390 fontp
->font_encoder
= ccl
;
8394 #if USE_MAC_FONT_PANEL
8395 /* Whether Font Panel has been shown before. The first call to font
8396 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8397 slow. This variable is used for deferring such a call as much as
8399 static int font_panel_shown_p
= 0;
8402 mac_font_panel_visible_p ()
8404 return font_panel_shown_p
&& FPIsFontPanelVisible ();
8408 mac_show_hide_font_panel ()
8410 font_panel_shown_p
= 1;
8412 return FPShowHideFontPanel ();
8416 mac_set_font_info_for_selection (f
, face_id
, c
)
8421 EventTargetRef target
= NULL
;
8422 XFontStruct
*font
= NULL
;
8424 if (!mac_font_panel_visible_p ())
8429 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
8431 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
8435 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
8436 face
= FACE_FROM_ID (f
, face_id
);
8442 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
8445 if (font
->mac_fontnum
!= -1)
8447 FontSelectionQDStyle qd_style
;
8449 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
8450 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
8451 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
8452 qd_style
.size
= font
->mac_fontsize
;
8453 qd_style
.hasColor
= false;
8455 err
= SetFontInfoForSelection (kFontSelectionQDType
,
8456 1, &qd_style
, target
);
8459 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
8460 1, &font
->mac_style
, target
);
8468 /* The Mac Event loop code */
8470 #if !TARGET_API_MAC_CARBON
8472 #include <Quickdraw.h>
8473 #include <Balloons.h>
8474 #include <Devices.h>
8476 #include <Gestalt.h>
8478 #include <Processes.h>
8480 #include <ToolUtils.h>
8481 #include <TextUtils.h>
8482 #include <Dialogs.h>
8485 #include <Resources.h>
8490 #endif /* ! TARGET_API_MAC_CARBON */
8495 #define WINDOW_RESOURCE 128
8496 #define TERM_WINDOW_RESOURCE 129
8498 #define DEFAULT_NUM_COLS 80
8500 #define MIN_DOC_SIZE 64
8501 #define MAX_DOC_SIZE 32767
8503 #define EXTRA_STACK_ALLOC (256 * 1024)
8505 #define ARGV_STRING_LIST_ID 129
8506 #define ABOUT_ALERT_ID 128
8507 #define RAM_TOO_LARGE_ALERT_ID 129
8509 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8510 Lisp_Object Qreverse
;
8513 /* Modifier associated with the control key, or nil to ignore. */
8514 Lisp_Object Vmac_control_modifier
;
8516 /* Modifier associated with the option key, or nil to ignore. */
8517 Lisp_Object Vmac_option_modifier
;
8519 /* Modifier associated with the command key, or nil to ignore. */
8520 Lisp_Object Vmac_command_modifier
;
8522 /* Modifier associated with the function key, or nil to ignore. */
8523 Lisp_Object Vmac_function_modifier
;
8525 /* True if the option and command modifiers should be used to emulate
8526 a three button mouse */
8527 Lisp_Object Vmac_emulate_three_button_mouse
;
8529 #if USE_CARBON_EVENTS
8530 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8531 mouse-2, instead of mouse-3. */
8532 int mac_wheel_button_is_mouse_2
;
8534 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8535 for processing before Emacs sees it. */
8536 int mac_pass_command_to_system
;
8538 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8539 for processing before Emacs sees it. */
8540 int mac_pass_control_to_system
;
8543 /* Points to the variable `inev' in the function XTread_socket. It is
8544 used for passing an input event to the function back from
8545 Carbon/Apple event handlers. */
8546 static struct input_event
*read_socket_inev
= NULL
;
8548 Point saved_menu_event_location
;
8551 #if USE_CARBON_EVENTS
8552 static Lisp_Object Qhi_command
;
8554 extern Lisp_Object Qwindow
;
8555 static Lisp_Object Qtoolbar_switch_mode
;
8557 #if USE_MAC_FONT_PANEL
8558 extern Lisp_Object Qfont
;
8559 static Lisp_Object Qpanel_closed
, Qselection
;
8562 static TSMDocumentID tsm_document_id
;
8563 static Lisp_Object Qtext_input
;
8564 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8565 static Lisp_Object Vmac_ts_active_input_overlay
;
8566 extern Lisp_Object Qbefore_string
;
8567 static Lisp_Object Vmac_ts_script_language_on_focus
;
8568 static Lisp_Object saved_ts_script_language_on_focus
;
8569 static ScriptLanguageRecord saved_ts_language
;
8570 static Component saved_ts_component
;
8573 extern int mac_ready_for_apple_events
;
8574 extern Lisp_Object Qundefined
;
8575 extern void init_apple_event_handler
P_ ((void));
8576 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8577 Lisp_Object
*, Lisp_Object
*,
8579 extern OSErr init_coercion_handler
P_ ((void));
8582 OSErr install_drag_handler
P_ ((WindowRef
));
8583 void remove_drag_handler
P_ ((WindowRef
));
8585 #if USE_CARBON_EVENTS
8587 extern void init_service_handler ();
8588 static Lisp_Object Qservice
, Qpaste
, Qperform
;
8590 /* Window Event Handler */
8591 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8594 OSStatus
install_window_handler (WindowPtr
);
8596 extern void init_emacs_passwd_dir ();
8597 extern int emacs_main (int, char **, char **);
8599 extern void initialize_applescript();
8600 extern void terminate_applescript();
8602 /* Table for translating Mac keycode to X keysym values. Contributed
8604 Mapping for special keys is now identical to that in Apple X11
8605 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8606 on the right of the Cmd key on laptops, and fn + `enter' (->
8608 static unsigned char keycode_to_xkeysym_table
[] = {
8609 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8610 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8611 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8613 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8614 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8615 /*0x38*/ 0, 0, 0, 0,
8616 /*0x3C*/ 0, 0, 0, 0,
8618 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8619 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8620 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8621 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8623 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8624 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8625 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8626 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8628 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8629 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8630 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8631 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8633 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8634 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8635 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8636 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8640 /* Table for translating Mac keycode with the laptop `fn' key to that
8641 without it. Destination symbols in comments are keys on US
8642 keyboard, and they may not be the same on other types of keyboards.
8643 If the destination is identical to the source (f1 ... f12), it
8644 doesn't map `fn' key to a modifier. */
8645 static unsigned char fn_keycode_to_keycode_table
[] = {
8646 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8647 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8648 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8650 /*0x30*/ 0, 0, 0, 0,
8651 /*0x34*/ 0, 0, 0, 0,
8652 /*0x38*/ 0, 0, 0, 0,
8653 /*0x3C*/ 0, 0, 0, 0,
8655 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8656 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8657 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8658 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8660 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8661 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8662 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8663 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8665 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8666 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8667 /*0x68*/ 0, 0, 0, 0,
8668 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8670 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
8671 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8672 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
8675 #endif /* MAC_OSX */
8678 #if USE_CARBON_EVENTS
8679 mac_to_emacs_modifiers (UInt32 mods
)
8681 mac_to_emacs_modifiers (EventModifiers mods
)
8684 unsigned int result
= 0;
8685 if (mods
& shiftKey
)
8686 result
|= shift_modifier
;
8688 /* Deactivated to simplify configuration:
8689 if Vmac_option_modifier is non-NIL, we fully process the Option
8690 key. Otherwise, we only process it if an additional Ctrl or Command
8691 is pressed. That way the system may convert the character to a
8693 if ((mods & optionKey) &&
8694 (( !NILP(Vmac_option_modifier) ||
8695 ((mods & cmdKey) || (mods & controlKey))))) */
8697 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8698 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8700 result
|= XUINT(val
);
8702 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8703 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8705 result
|= XUINT(val
);
8707 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8708 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8710 result
|= XUINT(val
);
8714 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8715 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8717 result
|= XUINT(val
);
8725 mac_get_emulated_btn ( UInt32 modifiers
)
8728 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8729 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8730 if (modifiers
& cmdKey
)
8731 result
= cmdIs3
? 2 : 1;
8732 else if (modifiers
& optionKey
)
8733 result
= cmdIs3
? 1 : 2;
8738 #if USE_CARBON_EVENTS
8739 /* Obtains the event modifiers from the event ref and then calls
8740 mac_to_emacs_modifiers. */
8742 mac_event_to_emacs_modifiers (EventRef eventRef
)
8745 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8746 sizeof (UInt32
), NULL
, &mods
);
8747 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8748 GetEventClass(eventRef
) == kEventClassMouse
)
8750 mods
&= ~(optionKey
| cmdKey
);
8752 return mac_to_emacs_modifiers (mods
);
8755 /* Given an event ref, return the code to use for the mouse button
8756 code in the emacs input_event. */
8758 mac_get_mouse_btn (EventRef ref
)
8760 EventMouseButton result
= kEventMouseButtonPrimary
;
8761 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8762 sizeof (EventMouseButton
), NULL
, &result
);
8765 case kEventMouseButtonPrimary
:
8766 if (NILP (Vmac_emulate_three_button_mouse
))
8770 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8771 sizeof (UInt32
), NULL
, &mods
);
8772 return mac_get_emulated_btn(mods
);
8774 case kEventMouseButtonSecondary
:
8775 return mac_wheel_button_is_mouse_2
? 2 : 1;
8776 case kEventMouseButtonTertiary
:
8777 case 4: /* 4 is the number for the mouse wheel button */
8778 return mac_wheel_button_is_mouse_2
? 1 : 2;
8784 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8785 events. However the click of the mouse wheel is not converted to a
8786 mouseDown or mouseUp event. Likewise for dead key down events.
8787 This calls ConvertEventRef, but then checks to see if it is a mouse
8788 up/down, or a dead key down carbon event that has not been
8789 converted, and if so, converts it by hand (to be picked up in the
8790 XTread_socket loop). */
8791 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8794 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8799 switch (GetEventClass (eventRef
))
8801 case kEventClassMouse
:
8802 switch (GetEventKind (eventRef
))
8804 case kEventMouseDown
:
8805 eventRec
->what
= mouseDown
;
8810 eventRec
->what
= mouseUp
;
8819 case kEventClassKeyboard
:
8820 switch (GetEventKind (eventRef
))
8822 case kEventRawKeyDown
:
8824 unsigned char char_codes
;
8827 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
8828 typeChar
, NULL
, sizeof (char),
8831 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
8832 typeUInt32
, NULL
, sizeof (UInt32
),
8836 eventRec
->what
= keyDown
;
8837 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8854 /* Need where and when. */
8857 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8858 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8859 /* Use two step process because new event modifiers are 32-bit
8860 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8861 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8862 NULL
, sizeof (UInt32
), NULL
, &mods
);
8863 eventRec
->modifiers
= mods
;
8865 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8877 Handle menubar_handle
;
8878 MenuHandle menu_handle
;
8880 menubar_handle
= GetNewMBar (128);
8881 if(menubar_handle
== NULL
)
8883 SetMenuBar (menubar_handle
);
8886 #if !TARGET_API_MAC_CARBON
8887 menu_handle
= GetMenuHandle (M_APPLE
);
8888 if(menu_handle
!= NULL
)
8889 AppendResMenu (menu_handle
,'DRVR');
8897 do_init_managers (void)
8899 #if !TARGET_API_MAC_CARBON
8900 InitGraf (&qd
.thePort
);
8902 FlushEvents (everyEvent
, 0);
8907 #endif /* !TARGET_API_MAC_CARBON */
8910 #if !TARGET_API_MAC_CARBON
8911 /* set up some extra stack space for use by emacs */
8912 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8914 /* MaxApplZone must be called for AppleScript to execute more
8915 complicated scripts */
8918 #endif /* !TARGET_API_MAC_CARBON */
8922 do_check_ram_size (void)
8924 SInt32 physical_ram_size
, logical_ram_size
;
8926 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8927 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8928 || physical_ram_size
> (1 << VALBITS
)
8929 || logical_ram_size
> (1 << VALBITS
))
8931 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8935 #endif /* MAC_OS8 */
8938 do_window_update (WindowPtr win
)
8940 struct frame
*f
= mac_window_to_frame (win
);
8944 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8946 if (win
!= tip_window
)
8948 if (f
->async_visible
== 0)
8950 /* Update events may occur when a frame gets iconified. */
8952 f
->async_visible
= 1;
8953 f
->async_iconified
= 0;
8954 SET_FRAME_GARBAGED (f
);
8960 #if TARGET_API_MAC_CARBON
8961 RgnHandle region
= NewRgn ();
8963 GetPortVisibleRegion (GetWindowPort (win
), region
);
8964 GetRegionBounds (region
, &r
);
8965 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8966 UpdateControls (win
, region
);
8967 DisposeRgn (region
);
8969 r
= (*win
->visRgn
)->rgnBBox
;
8970 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8971 UpdateControls (win
, win
->visRgn
);
8980 is_emacs_window (WindowPtr win
)
8982 Lisp_Object tail
, frame
;
8987 FOR_EACH_FRAME (tail
, frame
)
8988 if (FRAME_MAC_P (XFRAME (frame
)))
8989 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
9000 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9002 err
= ActivateTSMDocument (tsm_document_id
);
9006 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
9007 && EQ (saved_ts_script_language_on_focus
, Qt
))
9008 slptr
= &saved_ts_language
;
9009 else if (CONSP (Vmac_ts_script_language_on_focus
)
9010 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9011 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
9012 && CONSP (saved_ts_script_language_on_focus
)
9013 && EQ (XCAR (saved_ts_script_language_on_focus
),
9014 XCAR (Vmac_ts_script_language_on_focus
))
9015 && EQ (XCDR (saved_ts_script_language_on_focus
),
9016 XCDR (Vmac_ts_script_language_on_focus
)))
9018 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9019 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9026 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9027 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
9028 kKeyboardInputMethodClass
);
9030 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
9033 err
= SetTextServiceLanguage (slptr
);
9035 /* Seems to be needed on Mac OS X 10.2. */
9037 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
9047 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9049 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
9051 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
9053 err
= GetTextServiceLanguage (&saved_ts_language
);
9055 slptr
= &saved_ts_language
;
9057 else if (CONSP (Vmac_ts_script_language_on_focus
)
9058 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9059 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
9061 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9062 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9068 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9069 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
9070 kKeyboardInputMethodClass
);
9072 GetDefaultInputMethod (&saved_ts_component
, slptr
);
9076 err
= DeactivateTSMDocument (tsm_document_id
);
9082 #if !TARGET_API_MAC_CARBON
9084 do_apple_menu (SInt16 menu_item
)
9087 SInt16 da_driver_refnum
;
9089 if (menu_item
== I_ABOUT
)
9090 NoteAlert (ABOUT_ALERT_ID
, NULL
);
9093 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
9094 da_driver_refnum
= OpenDeskAcc (item_name
);
9097 #endif /* !TARGET_API_MAC_CARBON */
9099 /* Handle drags in size box. Based on code contributed by Ben
9100 Mesander and IM - Window Manager A. */
9103 do_grow_window (WindowPtr w
, EventRecord
*e
)
9106 int rows
, columns
, width
, height
;
9107 struct frame
*f
= mac_window_to_frame (w
);
9108 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
9109 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
9110 #if TARGET_API_MAC_CARBON
9116 if (size_hints
->flags
& PMinSize
)
9118 min_width
= size_hints
->min_width
;
9119 min_height
= size_hints
->min_height
;
9121 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
9123 #if TARGET_API_MAC_CARBON
9124 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
9126 height
= new_rect
.bottom
- new_rect
.top
;
9127 width
= new_rect
.right
- new_rect
.left
;
9129 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
9130 /* see if it really changed size */
9133 height
= HiWord (grow_size
);
9134 width
= LoWord (grow_size
);
9137 if (width
!= FRAME_PIXEL_WIDTH (f
)
9138 || height
!= FRAME_PIXEL_HEIGHT (f
))
9140 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9141 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9143 x_set_window_size (f
, 0, columns
, rows
);
9148 #if TARGET_API_MAC_CARBON
9150 mac_get_ideal_size (f
)
9153 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9154 WindowPtr w
= FRAME_MAC_WINDOW (f
);
9157 int height
, width
, columns
, rows
;
9159 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9160 ideal_size
.v
= dpyinfo
->height
;
9161 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
9162 /* Adjust the standard size according to character boundaries. */
9163 width
= standard_rect
.right
- standard_rect
.left
;
9164 height
= standard_rect
.bottom
- standard_rect
.top
;
9165 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9166 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9167 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
9168 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9174 /* Handle clicks in zoom box. Calculation of "standard state" based
9175 on code in IM - Window Manager A and code contributed by Ben
9176 Mesander. The standard state of an Emacs window is 80-characters
9177 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9180 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
9182 Rect zoom_rect
, port_rect
;
9184 struct frame
*f
= mac_window_to_frame (w
);
9185 #if TARGET_API_MAC_CARBON
9186 Point ideal_size
= mac_get_ideal_size (f
);
9188 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
9189 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
9190 && port_rect
.left
== zoom_rect
.left
9191 && port_rect
.top
== zoom_rect
.top
)
9192 zoom_in_or_out
= inZoomIn
;
9194 zoom_in_or_out
= inZoomOut
;
9197 mac_clear_window (f
);
9199 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
9200 #else /* not TARGET_API_MAC_CARBON */
9203 int w_title_height
, rows
;
9204 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9206 GetPort (&save_port
);
9208 SetPortWindowPort (w
);
9210 /* Clear window to avoid flicker. */
9211 EraseRect (&(w
->portRect
));
9212 if (zoom_in_or_out
== inZoomOut
)
9214 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9215 LocalToGlobal (&top_left
);
9217 /* calculate height of window's title bar */
9218 w_title_height
= top_left
.v
- 1
9219 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9221 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9222 zoom_rect
= qd
.screenBits
.bounds
;
9223 zoom_rect
.top
+= w_title_height
;
9224 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9226 zoom_rect
.right
= zoom_rect
.left
9227 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9229 /* Adjust the standard size according to character boundaries. */
9230 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9232 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9234 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9238 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
9240 SetPort (save_port
);
9241 #endif /* not TARGET_API_MAC_CARBON */
9243 #if !USE_CARBON_EVENTS
9244 /* retrieve window size and update application values */
9245 #if TARGET_API_MAC_CARBON
9246 GetWindowPortBounds (w
, &port_rect
);
9248 port_rect
= w
->portRect
;
9250 height
= port_rect
.bottom
- port_rect
.top
;
9251 width
= port_rect
.right
- port_rect
.left
;
9253 mac_handle_size_change (f
, width
, height
);
9254 mac_handle_origin_change (f
);
9259 mac_store_apple_event (class, id
, desc
)
9260 Lisp_Object
class, id
;
9263 struct input_event buf
;
9267 buf
.kind
= MAC_APPLE_EVENT
;
9270 XSETFRAME (buf
.frame_or_window
,
9271 mac_focus_frame (&one_mac_display_info
));
9272 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9273 is safe to use them during read_socket_hook. */
9274 buf
.arg
= mac_aedesc_to_lisp (desc
);
9275 kbd_buffer_store_event (&buf
);
9278 #if TARGET_API_MAC_CARBON
9280 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
9281 event
, num_params
, names
, types
)
9284 Lisp_Object class_key
, id_key
;
9287 EventParamName
*names
;
9288 EventParamType
*types
;
9290 OSStatus err
= eventNotHandledErr
;
9291 Lisp_Object binding
;
9293 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
9294 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9296 if (INTEGERP (binding
))
9297 err
= XINT (binding
);
9300 AppleEvent apple_event
;
9301 err
= create_apple_event_from_event_ref (event
, num_params
,
9306 mac_store_apple_event (class_key
, id_key
, &apple_event
);
9307 AEDisposeDesc (&apple_event
);
9308 /* Post a harmless event so as to wake up from
9309 ReceiveNextEvent. */
9310 mac_post_mouse_moved_event ();
9319 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
9325 struct input_event buf
;
9329 buf
.kind
= DRAG_N_DROP_EVENT
;
9330 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9331 buf
.timestamp
= TickCount () * (1000 / 60);
9332 XSETINT (buf
.x
, mouse_pos
.h
);
9333 XSETINT (buf
.y
, mouse_pos
.v
);
9334 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
9335 buf
.arg
= mac_aedesc_to_lisp (desc
);
9336 kbd_buffer_store_event (&buf
);
9340 #if USE_CARBON_EVENTS
9341 static pascal OSStatus
9342 mac_handle_command_event (next_handler
, event
, data
)
9343 EventHandlerCallRef next_handler
;
9347 OSStatus result
, err
;
9349 static EventParamName names
[] = {kEventParamDirectObject
,
9350 kEventParamKeyModifiers
};
9351 static EventParamType types
[] = {typeHICommand
,
9353 int num_params
= sizeof (names
) / sizeof (names
[0]);
9355 result
= CallNextEventHandler (next_handler
, event
);
9356 if (result
!= eventNotHandledErr
)
9359 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9360 NULL
, sizeof (HICommand
), NULL
, &command
);
9362 if (err
!= noErr
|| command
.commandID
== 0)
9363 return eventNotHandledErr
;
9365 /* A HI command event is mapped to an Apple event whose event class
9366 symbol is `hi-command' and event ID is its command ID. */
9367 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
9369 event
, num_params
, names
, types
);
9370 return err
== noErr
? noErr
: eventNotHandledErr
;
9374 init_command_handler ()
9376 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
9377 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9379 if (handle_command_eventUPP
== NULL
)
9380 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9381 return InstallApplicationEventHandler (handle_command_eventUPP
,
9382 GetEventTypeCount (specs
), specs
,
9386 static pascal OSStatus
9387 mac_handle_window_event (next_handler
, event
, data
)
9388 EventHandlerCallRef next_handler
;
9393 OSStatus result
, err
;
9396 XSizeHints
*size_hints
;
9398 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9399 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9401 return eventNotHandledErr
;
9403 f
= mac_window_to_frame (wp
);
9404 switch (GetEventKind (event
))
9406 case kEventWindowUpdate
:
9407 result
= CallNextEventHandler (next_handler
, event
);
9408 if (result
!= eventNotHandledErr
)
9411 do_window_update (wp
);
9414 case kEventWindowGetIdealSize
:
9415 result
= CallNextEventHandler (next_handler
, event
);
9416 if (result
!= eventNotHandledErr
)
9420 Point ideal_size
= mac_get_ideal_size (f
);
9422 err
= SetEventParameter (event
, kEventParamDimensions
,
9423 typeQDPoint
, sizeof (Point
), &ideal_size
);
9429 case kEventWindowBoundsChanging
:
9430 result
= CallNextEventHandler (next_handler
, event
);
9431 if (result
!= eventNotHandledErr
)
9434 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9435 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9439 size_hints
= FRAME_SIZE_HINTS (f
);
9440 if ((attributes
& kWindowBoundsChangeUserResize
)
9441 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9442 == (PResizeInc
| PBaseSize
| PMinSize
)))
9447 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9448 typeQDRectangle
, NULL
, sizeof (Rect
),
9453 width
= bounds
.right
- bounds
.left
;
9454 height
= bounds
.bottom
- bounds
.top
;
9456 if (width
< size_hints
->min_width
)
9457 width
= size_hints
->min_width
;
9459 width
= size_hints
->base_width
9460 + (int) ((width
- size_hints
->base_width
)
9461 / (float) size_hints
->width_inc
+ .5)
9462 * size_hints
->width_inc
;
9464 if (height
< size_hints
->min_height
)
9465 height
= size_hints
->min_height
;
9467 height
= size_hints
->base_height
9468 + (int) ((height
- size_hints
->base_height
)
9469 / (float) size_hints
->height_inc
+ .5)
9470 * size_hints
->height_inc
;
9472 bounds
.right
= bounds
.left
+ width
;
9473 bounds
.bottom
= bounds
.top
+ height
;
9474 SetEventParameter (event
, kEventParamCurrentBounds
,
9475 typeQDRectangle
, sizeof (Rect
), &bounds
);
9480 case kEventWindowBoundsChanged
:
9481 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9482 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9486 if (attributes
& kWindowBoundsChangeSizeChanged
)
9490 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9491 typeQDRectangle
, NULL
, sizeof (Rect
),
9497 width
= bounds
.right
- bounds
.left
;
9498 height
= bounds
.bottom
- bounds
.top
;
9499 mac_handle_size_change (f
, width
, height
);
9503 if (attributes
& kWindowBoundsChangeOriginChanged
)
9504 mac_handle_origin_change (f
);
9508 case kEventWindowShown
:
9509 case kEventWindowHidden
:
9510 case kEventWindowExpanded
:
9511 case kEventWindowCollapsed
:
9512 result
= CallNextEventHandler (next_handler
, event
);
9514 mac_handle_visibility_change (f
);
9519 case kEventWindowClose
:
9520 result
= CallNextEventHandler (next_handler
, event
);
9522 struct input_event buf
;
9525 buf
.kind
= DELETE_WINDOW_EVENT
;
9526 XSETFRAME (buf
.frame_or_window
, f
);
9528 kbd_buffer_store_event (&buf
);
9533 case kEventWindowToolbarSwitchMode
:
9534 result
= CallNextEventHandler (next_handler
, event
);
9536 static EventParamName names
[] = {kEventParamDirectObject
,
9537 kEventParamWindowMouseLocation
,
9538 kEventParamKeyModifiers
,
9539 kEventParamMouseButton
,
9540 kEventParamClickCount
,
9541 kEventParamMouseChord
};
9542 static EventParamType types
[] = {typeWindowRef
,
9548 int num_params
= sizeof (names
) / sizeof (names
[0]);
9550 err
= mac_store_event_ref_as_apple_event (0, 0,
9552 Qtoolbar_switch_mode
,
9556 return err
== noErr
? noErr
: result
;
9560 case kEventWindowFocusAcquired
:
9561 result
= CallNextEventHandler (next_handler
, event
);
9562 err
= mac_tsm_resume ();
9563 return err
== noErr
? noErr
: result
;
9565 case kEventWindowFocusRelinquish
:
9566 result
= CallNextEventHandler (next_handler
, event
);
9567 err
= mac_tsm_suspend ();
9568 return err
== noErr
? noErr
: result
;
9572 return eventNotHandledErr
;
9575 static pascal OSStatus
9576 mac_handle_mouse_event (next_handler
, event
, data
)
9577 EventHandlerCallRef next_handler
;
9581 OSStatus result
, err
;
9583 switch (GetEventKind (event
))
9585 case kEventMouseWheelMoved
:
9589 EventMouseWheelAxis axis
;
9593 result
= CallNextEventHandler (next_handler
, event
);
9594 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9597 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9598 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9602 f
= mac_window_to_frame (wp
);
9603 if (f
!= mac_focus_frame (&one_mac_display_info
))
9606 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
9607 typeMouseWheelAxis
, NULL
,
9608 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9609 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
9612 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
9613 typeSInt32
, NULL
, sizeof (SInt32
),
9617 err
= GetEventParameter (event
, kEventParamMouseLocation
,
9618 typeQDPoint
, NULL
, sizeof (Point
),
9622 read_socket_inev
->kind
= WHEEL_EVENT
;
9623 read_socket_inev
->code
= 0;
9624 read_socket_inev
->modifiers
=
9625 (mac_event_to_emacs_modifiers (event
)
9626 | ((delta
< 0) ? down_modifier
: up_modifier
));
9627 SetPortWindowPort (wp
);
9628 GlobalToLocal (&point
);
9629 XSETINT (read_socket_inev
->x
, point
.h
);
9630 XSETINT (read_socket_inev
->y
, point
.v
);
9631 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9641 return eventNotHandledErr
;
9644 #if USE_MAC_FONT_PANEL
9645 static pascal OSStatus
9646 mac_handle_font_event (next_handler
, event
, data
)
9647 EventHandlerCallRef next_handler
;
9651 OSStatus result
, err
;
9654 EventParamName
*names
;
9655 EventParamType
*types
;
9656 static EventParamName names_sel
[] = {kEventParamATSUFontID
,
9657 kEventParamATSUFontSize
,
9658 kEventParamFMFontFamily
,
9659 kEventParamFMFontSize
,
9660 kEventParamFontColor
};
9661 static EventParamType types_sel
[] = {typeATSUFontID
,
9667 result
= CallNextEventHandler (next_handler
, event
);
9668 if (result
!= eventNotHandledErr
)
9671 switch (GetEventKind (event
))
9673 case kEventFontPanelClosed
:
9674 id_key
= Qpanel_closed
;
9680 case kEventFontSelection
:
9681 id_key
= Qselection
;
9682 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9688 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9692 return err
== noErr
? noErr
: eventNotHandledErr
;
9697 static pascal OSStatus
9698 mac_handle_text_input_event (next_handler
, event
, data
)
9699 EventHandlerCallRef next_handler
;
9703 OSStatus result
, err
= noErr
;
9704 Lisp_Object id_key
= Qnil
;
9706 EventParamName
*names
;
9707 EventParamType
*types
;
9708 static UInt32 seqno_uaia
= 0;
9709 static EventParamName names_uaia
[] =
9710 {kEventParamTextInputSendComponentInstance
,
9711 kEventParamTextInputSendRefCon
,
9712 kEventParamTextInputSendSLRec
,
9713 kEventParamTextInputSendFixLen
,
9714 kEventParamTextInputSendText
,
9715 kEventParamTextInputSendUpdateRng
,
9716 kEventParamTextInputSendHiliteRng
,
9717 kEventParamTextInputSendClauseRng
,
9718 kEventParamTextInputSendPinRng
,
9719 kEventParamTextInputSendTextServiceEncoding
,
9720 kEventParamTextInputSendTextServiceMacEncoding
,
9721 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
9722 static EventParamType types_uaia
[] =
9723 {typeComponentInstance
,
9725 typeIntlWritingCode
,
9739 static EventParamName names_ufke
[] =
9740 {kEventParamTextInputSendComponentInstance
,
9741 kEventParamTextInputSendRefCon
,
9742 kEventParamTextInputSendSLRec
,
9743 kEventParamTextInputSendText
};
9744 static EventParamType types_ufke
[] =
9745 {typeComponentInstance
,
9747 typeIntlWritingCode
,
9750 result
= CallNextEventHandler (next_handler
, event
);
9752 switch (GetEventKind (event
))
9754 case kEventTextInputUpdateActiveInputArea
:
9755 id_key
= Qupdate_active_input_area
;
9756 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
9759 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
9760 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
9764 case kEventTextInputUnicodeForKeyEvent
:
9767 UInt32 actual_size
, modifiers
, mapped_modifiers
;
9769 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
9770 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
9773 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
9775 sizeof (UInt32
), NULL
, &modifiers
);
9779 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9780 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9781 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9784 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9786 if (modifiers
& mapped_modifiers
)
9787 /* There're mapped modifier keys. Process it in
9789 return eventNotHandledErr
;
9792 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
9793 typeUnicodeText
, NULL
, 0, &actual_size
,
9795 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
9799 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
9800 typeUnicodeText
, NULL
,
9801 sizeof (UniChar
), NULL
, &code
);
9802 if (err
== noErr
&& code
< 0x80)
9804 /* ASCII character. Process it in XTread_socket. */
9805 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
9809 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
9810 typeUInt32
, NULL
, sizeof (UInt32
),
9812 if (!(err
== noErr
&& key_code
<= 0x7f
9813 && keycode_to_xkeysym_table
[key_code
]))
9816 mac_focus_frame (&one_mac_display_info
);
9818 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
9819 read_socket_inev
->code
= code
;
9820 read_socket_inev
->modifiers
=
9821 mac_to_emacs_modifiers (modifiers
);
9822 read_socket_inev
->modifiers
|=
9823 (extra_keyboard_modifiers
9824 & (meta_modifier
| alt_modifier
9825 | hyper_modifier
| super_modifier
));
9826 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9829 return eventNotHandledErr
;
9833 /* Non-ASCII keystrokes without mapped modifiers are processed
9834 at the Lisp level. */
9835 id_key
= Qunicode_for_key_event
;
9836 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
9841 case kEventTextInputOffsetToPos
:
9847 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
9848 return eventNotHandledErr
;
9850 /* Strictly speaking, this is not always correct because
9851 previous events may change some states about display. */
9852 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
9854 /* Active input area is displayed in the echo area. */
9855 w
= XWINDOW (echo_area_window
);
9856 f
= WINDOW_XFRAME (w
);
9860 /* Active input area is displayed around the current point. */
9861 f
= SELECTED_FRAME ();
9862 w
= XWINDOW (f
->selected_window
);
9865 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
9866 + WINDOW_LEFT_FRINGE_WIDTH (w
));
9867 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
9868 + FONT_BASE (FRAME_FONT (f
)));
9869 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
9871 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
9872 typeQDPoint
, sizeof (typeQDPoint
), &p
);
9881 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
9885 return err
== noErr
? noErr
: result
;
9891 mac_store_service_event (event
)
9897 EventParamName
*names
;
9898 EventParamType
*types
;
9899 static EventParamName names_pfm
[] = {kEventParamServiceMessageName
,
9900 kEventParamServiceUserData
};
9901 static EventParamType types_pfm
[] = {typeCFStringRef
,
9904 switch (GetEventKind (event
))
9906 case kEventServicePaste
:
9913 case kEventServicePerform
:
9915 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
9924 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
9930 #endif /* MAC_OSX */
9931 #endif /* USE_CARBON_EVENTS */
9935 install_window_handler (window
)
9938 OSStatus err
= noErr
;
9939 #if USE_CARBON_EVENTS
9940 EventTypeSpec specs_window
[] =
9941 {{kEventClassWindow
, kEventWindowUpdate
},
9942 {kEventClassWindow
, kEventWindowGetIdealSize
},
9943 {kEventClassWindow
, kEventWindowBoundsChanging
},
9944 {kEventClassWindow
, kEventWindowBoundsChanged
},
9945 {kEventClassWindow
, kEventWindowShown
},
9946 {kEventClassWindow
, kEventWindowHidden
},
9947 {kEventClassWindow
, kEventWindowExpanded
},
9948 {kEventClassWindow
, kEventWindowCollapsed
},
9949 {kEventClassWindow
, kEventWindowClose
},
9951 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
9954 {kEventClassWindow
, kEventWindowFocusAcquired
},
9955 {kEventClassWindow
, kEventWindowFocusRelinquish
},
9958 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9959 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9960 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9961 #if USE_MAC_FONT_PANEL
9962 EventTypeSpec specs_font
[] = {{kEventClassFont
, kEventFontPanelClosed
},
9963 {kEventClassFont
, kEventFontSelection
}};
9964 static EventHandlerUPP handle_font_eventUPP
= NULL
;
9967 EventTypeSpec specs_text_input
[] =
9968 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
9969 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
9970 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
9971 static EventHandlerUPP handle_text_input_eventUPP
= NULL
;
9974 if (handle_window_eventUPP
== NULL
)
9975 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9976 if (handle_mouse_eventUPP
== NULL
)
9977 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9978 #if USE_MAC_FONT_PANEL
9979 if (handle_font_eventUPP
== NULL
)
9980 handle_font_eventUPP
= NewEventHandlerUPP (mac_handle_font_event
);
9983 if (handle_text_input_eventUPP
== NULL
)
9984 handle_text_input_eventUPP
=
9985 NewEventHandlerUPP (mac_handle_text_input_event
);
9987 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9988 GetEventTypeCount (specs_window
),
9989 specs_window
, NULL
, NULL
);
9991 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9992 GetEventTypeCount (specs_mouse
),
9993 specs_mouse
, NULL
, NULL
);
9994 #if USE_MAC_FONT_PANEL
9996 err
= InstallWindowEventHandler (window
, handle_font_eventUPP
,
9997 GetEventTypeCount (specs_font
),
9998 specs_font
, NULL
, NULL
);
10002 err
= InstallWindowEventHandler (window
, handle_text_input_eventUPP
,
10003 GetEventTypeCount (specs_text_input
),
10004 specs_text_input
, window
, NULL
);
10008 err
= install_drag_handler (window
);
10014 remove_window_handler (window
)
10017 remove_drag_handler (window
);
10023 profiler_exit_proc ()
10025 ProfilerDump ("\pEmacs.prof");
10030 /* These few functions implement Emacs as a normal Mac application
10031 (almost): set up the heap and the Toolbox, handle necessary system
10032 events plus a few simple menu events. They also set up Emacs's
10033 access to functions defined in the rest of this file. Emacs uses
10034 function hooks to perform all its terminal I/O. A complete list of
10035 these functions appear in termhooks.h. For what they do, read the
10036 comments there and see also w32term.c and xterm.c. What's
10037 noticeably missing here is the event loop, which is normally
10038 present in most Mac application. After performing the necessary
10039 Mac initializations, main passes off control to emacs_main
10040 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10041 (defined further below) to read input. This is where
10042 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10049 #if __profile__ /* is the profiler on? */
10050 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
10055 /* set creator and type for files created by MSL */
10056 _fcreator
= 'EMAx';
10060 do_init_managers ();
10064 #ifndef USE_LSB_TAG
10065 do_check_ram_size ();
10068 init_emacs_passwd_dir ();
10072 init_coercion_handler ();
10074 initialize_applescript ();
10076 init_apple_event_handler ();
10082 /* set up argv array from STR# resource */
10083 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
10087 /* free up AppleScript resources on exit */
10088 atexit (terminate_applescript
);
10090 #if __profile__ /* is the profiler on? */
10091 atexit (profiler_exit_proc
);
10094 /* 3rd param "envp" never used in emacs_main */
10095 (void) emacs_main (argc
, argv
, 0);
10098 /* Never reached - real exit in Fkill_emacs */
10103 #if !USE_CARBON_EVENTS
10104 static RgnHandle mouse_region
= NULL
;
10107 mac_wait_next_event (er
, sleep_time
, dequeue
)
10112 static EventRecord er_buf
= {nullEvent
};
10113 UInt32 target_tick
, current_tick
;
10114 EventMask event_mask
;
10116 if (mouse_region
== NULL
)
10117 mouse_region
= NewRgn ();
10119 event_mask
= everyEvent
;
10120 if (!mac_ready_for_apple_events
)
10121 event_mask
-= highLevelEventMask
;
10123 current_tick
= TickCount ();
10124 target_tick
= current_tick
+ sleep_time
;
10126 if (er_buf
.what
== nullEvent
)
10127 while (!WaitNextEvent (event_mask
, &er_buf
,
10128 target_tick
- current_tick
, mouse_region
))
10130 current_tick
= TickCount ();
10131 if (target_tick
<= current_tick
)
10137 er_buf
.what
= nullEvent
;
10140 #endif /* not USE_CARBON_EVENTS */
10142 #if TARGET_API_MAC_CARBON
10144 mac_post_mouse_moved_event ()
10146 EventRef event
= NULL
;
10149 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
10150 kEventAttributeNone
, &event
);
10155 GetMouse (&mouse_pos
);
10156 LocalToGlobal (&mouse_pos
);
10157 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
10158 sizeof (Point
), &mouse_pos
);
10162 UInt32 modifiers
= GetCurrentKeyModifiers ();
10164 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
10165 sizeof (UInt32
), &modifiers
);
10168 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
10169 kEventPriorityStandard
);
10171 ReleaseEvent (event
);
10177 mac_set_unicode_keystroke_event (code
, buf
)
10179 struct input_event
*buf
;
10181 int charset_id
, c1
, c2
;
10185 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10188 else if (code
< 0x100)
10191 charset_id
= CHARSET_8_BIT_CONTROL
;
10193 charset_id
= charset_latin_iso8859_1
;
10194 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10195 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10200 charset_id
= charset_mule_unicode_0100_24ff
,
10202 else if (code
< 0x33FF)
10203 charset_id
= charset_mule_unicode_2500_33ff
,
10205 else if (code
>= 0xE000)
10206 charset_id
= charset_mule_unicode_e000_ffff
,
10208 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10209 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10210 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10215 /* Emacs calls this whenever it wants to read an input event from the
10218 XTread_socket (sd
, expected
, hold_quit
)
10220 struct input_event
*hold_quit
;
10222 struct input_event inev
;
10224 #if USE_CARBON_EVENTS
10226 EventTargetRef toolbox_dispatcher
;
10229 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10231 if (interrupt_input_blocked
)
10233 interrupt_input_pending
= 1;
10237 interrupt_input_pending
= 0;
10240 /* So people can tell when we have read the available input. */
10241 input_signal_count
++;
10245 #if USE_CARBON_EVENTS
10246 toolbox_dispatcher
= GetEventDispatcherTarget ();
10250 mac_prepare_for_quickdraw (NULL
),
10252 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
10253 kEventRemoveFromQueue
, &eventRef
))
10254 #else /* !USE_CARBON_EVENTS */
10255 while (mac_wait_next_event (&er
, 0, true))
10256 #endif /* !USE_CARBON_EVENTS */
10260 unsigned long timestamp
;
10263 inev
.kind
= NO_EVENT
;
10266 #if USE_CARBON_EVENTS
10267 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
10269 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10272 #if USE_CARBON_EVENTS
10273 /* Handle new events */
10274 if (!mac_convert_event_ref (eventRef
, &er
))
10276 /* There used to be a handler for the kEventMouseWheelMoved
10277 event here. But as of Mac OS X 10.4, this kind of event
10278 is not directly posted to the main event queue by
10279 two-finger scrolling on the trackpad. Instead, some
10280 private event is posted and it is converted to a wheel
10281 event by the default handler for the application target.
10282 The converted one can be received by a Carbon event
10283 handler installed on a window target. */
10284 read_socket_inev
= &inev
;
10285 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10286 read_socket_inev
= NULL
;
10289 #endif /* USE_CARBON_EVENTS */
10295 WindowPtr window_ptr
;
10296 ControlPartCode part_code
;
10297 int tool_bar_p
= 0;
10299 #if USE_CARBON_EVENTS
10300 /* This is needed to send mouse events like aqua window
10301 buttons to the correct handler. */
10302 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10303 != eventNotHandledErr
)
10306 last_mouse_glyph_frame
= 0;
10308 if (dpyinfo
->grabbed
&& last_mouse_frame
10309 && FRAME_LIVE_P (last_mouse_frame
))
10311 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
10312 part_code
= inContent
;
10316 part_code
= FindWindow (er
.where
, &window_ptr
);
10317 if (tip_window
&& window_ptr
== tip_window
)
10319 HideWindow (tip_window
);
10320 part_code
= FindWindow (er
.where
, &window_ptr
);
10324 if (er
.what
!= mouseDown
&&
10325 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
10331 f
= mac_focus_frame (dpyinfo
);
10332 saved_menu_event_location
= er
.where
;
10333 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
10334 XSETFRAME (inev
.frame_or_window
, f
);
10339 #if TARGET_API_MAC_CARBON
10340 FrontNonFloatingWindow ()
10345 SelectWindow (window_ptr
);
10348 ControlPartCode control_part_code
;
10350 Point mouse_loc
= er
.where
;
10352 ControlKind control_kind
;
10355 f
= mac_window_to_frame (window_ptr
);
10356 /* convert to local coordinates of new window */
10357 SetPortWindowPort (window_ptr
);
10359 GlobalToLocal (&mouse_loc
);
10360 #if TARGET_API_MAC_CARBON
10361 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10362 &control_part_code
);
10365 GetControlKind (ch
, &control_kind
);
10368 control_part_code
= FindControl (mouse_loc
, window_ptr
,
10372 #if USE_CARBON_EVENTS
10373 inev
.code
= mac_get_mouse_btn (eventRef
);
10374 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10376 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
10377 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10379 XSETINT (inev
.x
, mouse_loc
.h
);
10380 XSETINT (inev
.y
, mouse_loc
.v
);
10382 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
10384 #ifndef USE_TOOLKIT_SCROLL_BARS
10385 /* control_part_code becomes kControlNoPart if
10386 a progress indicator is clicked. */
10387 && control_part_code
!= kControlNoPart
10388 #else /* USE_TOOLKIT_SCROLL_BARS */
10390 && control_kind
.kind
== kControlKindScrollBar
10391 #endif /* MAC_OSX */
10392 #endif /* USE_TOOLKIT_SCROLL_BARS */
10395 struct scroll_bar
*bar
;
10397 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10399 bar
= tracked_scroll_bar
;
10400 #ifndef USE_TOOLKIT_SCROLL_BARS
10401 control_part_code
= kControlIndicatorPart
;
10405 bar
= (struct scroll_bar
*) GetControlReference (ch
);
10406 #ifdef USE_TOOLKIT_SCROLL_BARS
10407 /* Make the "Ctrl-Mouse-2 splits window" work
10408 for toolkit scroll bars. */
10409 if (er
.modifiers
& controlKey
)
10410 x_scroll_bar_handle_click (bar
, control_part_code
,
10412 else if (er
.what
== mouseDown
)
10413 x_scroll_bar_handle_press (bar
, control_part_code
,
10416 x_scroll_bar_handle_release (bar
, &inev
);
10417 #else /* not USE_TOOLKIT_SCROLL_BARS */
10418 x_scroll_bar_handle_click (bar
, control_part_code
,
10420 if (er
.what
== mouseDown
10421 && control_part_code
== kControlIndicatorPart
)
10422 tracked_scroll_bar
= bar
;
10424 tracked_scroll_bar
= NULL
;
10425 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10429 Lisp_Object window
;
10430 int x
= mouse_loc
.h
;
10431 int y
= mouse_loc
.v
;
10433 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10434 if (EQ (window
, f
->tool_bar_window
))
10436 if (er
.what
== mouseDown
)
10437 handle_tool_bar_click (f
, x
, y
, 1, 0);
10439 handle_tool_bar_click (f
, x
, y
, 0,
10445 XSETFRAME (inev
.frame_or_window
, f
);
10446 inev
.kind
= MOUSE_CLICK_EVENT
;
10450 if (er
.what
== mouseDown
)
10452 dpyinfo
->grabbed
|= (1 << inev
.code
);
10453 last_mouse_frame
= f
;
10456 last_tool_bar_item
= -1;
10460 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10461 /* If a button is released though it was not
10462 previously pressed, that would be because
10463 of multi-button emulation. */
10464 dpyinfo
->grabbed
= 0;
10466 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10469 /* Ignore any mouse motion that happened before
10470 this event; any subsequent mouse-movement Emacs
10471 events should reflect only motion after the
10474 f
->mouse_moved
= 0;
10476 #ifdef USE_TOOLKIT_SCROLL_BARS
10477 if (inev
.kind
== MOUSE_CLICK_EVENT
)
10482 inev
.modifiers
|= down_modifier
;
10485 inev
.modifiers
|= up_modifier
;
10492 #if TARGET_API_MAC_CARBON
10494 if (IsWindowPathSelectClick (window_ptr
, &er
))
10496 WindowPathSelect (window_ptr
, NULL
, NULL
);
10499 if (part_code
== inProxyIcon
10500 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
10501 != errUserWantsToDragWindow
))
10503 DragWindow (window_ptr
, er
.where
, NULL
);
10504 #else /* not TARGET_API_MAC_CARBON */
10505 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10506 #endif /* not TARGET_API_MAC_CARBON */
10507 /* Update the frame parameters. */
10508 #if !USE_CARBON_EVENTS
10510 struct frame
*f
= mac_window_to_frame (window_ptr
);
10512 if (f
&& !f
->async_iconified
)
10513 mac_handle_origin_change (f
);
10519 if (TrackGoAway (window_ptr
, er
.where
))
10521 inev
.kind
= DELETE_WINDOW_EVENT
;
10522 XSETFRAME (inev
.frame_or_window
,
10523 mac_window_to_frame (window_ptr
));
10527 /* window resize handling added --ben */
10529 do_grow_window (window_ptr
, &er
);
10532 /* window zoom handling added --ben */
10535 if (TrackBox (window_ptr
, er
.where
, part_code
))
10536 do_zoom_window (window_ptr
, part_code
);
10546 #if USE_CARBON_EVENTS
10547 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10548 != eventNotHandledErr
)
10551 do_window_update ((WindowPtr
) er
.message
);
10556 #if USE_CARBON_EVENTS
10557 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10558 != eventNotHandledErr
)
10561 switch ((er
.message
>> 24) & 0x000000FF)
10563 case suspendResumeMessage
:
10565 if (er
.message
& resumeFlag
)
10568 mac_tsm_suspend ();
10572 case mouseMovedMessage
:
10573 #if !USE_CARBON_EVENTS
10574 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
10575 er
.where
.h
+ 1, er
.where
.v
+ 1);
10577 previous_help_echo_string
= help_echo_string
;
10578 help_echo_string
= Qnil
;
10580 if (dpyinfo
->grabbed
&& last_mouse_frame
10581 && FRAME_LIVE_P (last_mouse_frame
))
10582 f
= last_mouse_frame
;
10584 f
= dpyinfo
->x_focus_frame
;
10586 if (dpyinfo
->mouse_face_hidden
)
10588 dpyinfo
->mouse_face_hidden
= 0;
10589 clear_mouse_face (dpyinfo
);
10594 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
10595 Point mouse_pos
= er
.where
;
10597 SetPortWindowPort (wp
);
10599 GlobalToLocal (&mouse_pos
);
10601 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10602 #ifdef USE_TOOLKIT_SCROLL_BARS
10603 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
10605 #else /* not USE_TOOLKIT_SCROLL_BARS */
10606 x_scroll_bar_note_movement (tracked_scroll_bar
,
10608 - XINT (tracked_scroll_bar
->top
),
10609 er
.when
* (1000 / 60));
10610 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10613 /* Generate SELECT_WINDOW_EVENTs when needed. */
10614 if (!NILP (Vmouse_autoselect_window
))
10616 Lisp_Object window
;
10618 window
= window_from_coordinates (f
,
10623 /* Window will be selected only when it is
10624 not selected now and last mouse movement
10625 event was not in it. Minibuffer window
10626 will be selected iff it is active. */
10627 if (WINDOWP (window
)
10628 && !EQ (window
, last_window
)
10629 && !EQ (window
, selected_window
))
10631 inev
.kind
= SELECT_WINDOW_EVENT
;
10632 inev
.frame_or_window
= window
;
10635 last_window
=window
;
10637 if (!note_mouse_movement (f
, &mouse_pos
))
10638 help_echo_string
= previous_help_echo_string
;
10642 /* If the contents of the global variable
10643 help_echo_string has changed, generate a
10645 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10653 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10655 #if USE_CARBON_EVENTS
10656 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10657 != eventNotHandledErr
)
10660 if (window_ptr
== tip_window
)
10662 HideWindow (tip_window
);
10666 if (!is_emacs_window (window_ptr
))
10669 if ((er
.modifiers
& activeFlag
) != 0)
10671 /* A window has been activated */
10672 Point mouse_loc
= er
.where
;
10674 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10676 SetPortWindowPort (window_ptr
);
10677 GlobalToLocal (&mouse_loc
);
10678 /* Window-activated event counts as mouse movement,
10679 so update things that depend on mouse position. */
10680 note_mouse_movement (mac_window_to_frame (window_ptr
),
10685 /* A window has been deactivated */
10686 #if USE_TOOLKIT_SCROLL_BARS
10687 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10689 struct input_event event
;
10691 EVENT_INIT (event
);
10692 event
.kind
= NO_EVENT
;
10693 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10694 if (event
.kind
!= NO_EVENT
)
10696 event
.timestamp
= timestamp
;
10697 kbd_buffer_store_event_hold (&event
, hold_quit
);
10702 dpyinfo
->grabbed
= 0;
10704 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10706 f
= mac_window_to_frame (window_ptr
);
10707 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10709 /* If we move outside the frame, then we're
10710 certainly no longer on any text in the
10712 clear_mouse_face (dpyinfo
);
10713 dpyinfo
->mouse_face_mouse_frame
= 0;
10716 /* Generate a nil HELP_EVENT to cancel a help-echo.
10717 Do it only if there's something to cancel.
10718 Otherwise, the startup message is cleared when the
10719 mouse leaves the frame. */
10720 if (any_help_event_p
)
10730 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10731 static SInt16 last_key_script
= -1;
10732 SInt16 current_key_script
;
10733 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
10736 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
10737 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
10738 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
10740 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10741 mapped_modifiers
|=
10742 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
10744 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
10746 sizeof (UInt32
), NULL
, &modifiers
);
10748 mapped_modifiers
&= modifiers
;
10750 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
10751 /* When using Carbon Events, we need to pass raw keyboard
10752 events to the TSM ourselves. If TSM handles it, it
10753 will pass back noErr, otherwise it will pass back
10754 "eventNotHandledErr" and we can process it
10756 if (!(mapped_modifiers
10757 & ~(mac_pass_command_to_system
? cmdKey
: 0)
10758 & ~(mac_pass_control_to_system
? controlKey
: 0)))
10762 read_socket_inev
= &inev
;
10763 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10764 read_socket_inev
= NULL
;
10765 if (err
!= eventNotHandledErr
)
10769 if (er
.what
== keyUp
)
10774 f
= mac_focus_frame (dpyinfo
);
10776 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
10777 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
10779 clear_mouse_face (dpyinfo
);
10780 dpyinfo
->mouse_face_hidden
= 1;
10783 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10784 if (last_key_script
!= current_key_script
)
10786 struct input_event event
;
10788 EVENT_INIT (event
);
10789 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10791 event
.code
= current_key_script
;
10792 event
.timestamp
= timestamp
;
10793 kbd_buffer_store_event (&event
);
10795 last_key_script
= current_key_script
;
10799 if (inev
.kind
!= NO_EVENT
)
10804 if (mapped_modifiers
& kEventKeyModifierFnMask
10806 && fn_keycode_to_keycode_table
[keycode
])
10807 keycode
= fn_keycode_to_keycode_table
[keycode
];
10809 if (keycode
<= 0x7f && keycode_to_xkeysym_table
[keycode
])
10811 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10812 inev
.code
= 0xff00 | keycode_to_xkeysym_table
[keycode
];
10814 if (modifiers
& kEventKeyModifierFnMask
10816 && fn_keycode_to_keycode_table
[keycode
] == keycode
)
10817 modifiers
&= ~kEventKeyModifierFnMask
;
10820 else if (mapped_modifiers
)
10822 /* translate the keycode back to determine the
10825 static SInt16 last_key_layout_id
= 0;
10826 static Handle uchr_handle
= (Handle
)-1;
10827 SInt16 current_key_layout_id
=
10828 GetScriptVariable (current_key_script
, smScriptKeys
);
10830 if (uchr_handle
== (Handle
)-1
10831 || last_key_layout_id
!= current_key_layout_id
)
10833 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10834 last_key_layout_id
= current_key_layout_id
;
10840 UInt16 key_action
= er
.what
- keyDown
;
10841 UInt32 modifier_key_state
=
10842 (modifiers
& ~mapped_modifiers
) >> 8;
10843 UInt32 keyboard_type
= LMGetKbdType ();
10844 SInt32 dead_key_state
= 0;
10846 UniCharCount actual_length
;
10848 status
= UCKeyTranslate ((UCKeyboardLayout
*)*uchr_handle
,
10849 keycode
, key_action
,
10850 modifier_key_state
,
10852 kUCKeyTranslateNoDeadKeysMask
,
10854 1, &actual_length
, &code
);
10855 if (status
== noErr
&& actual_length
== 1)
10856 mac_set_unicode_keystroke_event (code
, &inev
);
10858 #endif /* MAC_OSX */
10860 if (inev
.kind
== NO_EVENT
)
10862 /* This code comes from Keyboard Resource,
10863 Appendix C of IM - Text. This is necessary
10864 since shift is ignored in KCHR table
10865 translation when option or command is pressed.
10866 It also does not translate correctly
10867 control-shift chars like C-% so mask off shift
10869 /* Mask off modifier keys that are mapped to some
10870 Emacs modifiers. */
10871 int new_modifiers
= er
.modifiers
& ~mapped_modifiers
;
10872 /* set high byte of keycode to modifier high byte*/
10873 int new_keycode
= keycode
| new_modifiers
;
10874 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10875 unsigned long some_state
= 0;
10876 UInt32 new_char_code
;
10878 new_char_code
= KeyTranslate (kchr_ptr
, new_keycode
,
10880 if (new_char_code
== 0)
10881 /* Seems like a dead key. Append up-stroke. */
10882 new_char_code
= KeyTranslate (kchr_ptr
,
10883 new_keycode
| 0x80,
10887 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10888 inev
.code
= new_char_code
& 0xff;
10893 if (inev
.kind
== NO_EVENT
)
10895 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10896 inev
.code
= er
.message
& charCodeMask
;
10899 inev
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10900 inev
.modifiers
|= (extra_keyboard_modifiers
10901 & (meta_modifier
| alt_modifier
10902 | hyper_modifier
| super_modifier
));
10903 XSETFRAME (inev
.frame_or_window
, f
);
10905 #if TARGET_API_MAC_CARBON
10906 if (inev
.kind
== ASCII_KEYSTROKE_EVENT
10907 && inev
.code
>= 0x80 && inev
.modifiers
)
10910 TextEncoding encoding
= kTextEncodingMacRoman
;
10911 TextToUnicodeInfo ttu_info
;
10913 UpgradeScriptInfoToTextEncoding (current_key_script
,
10914 kTextLanguageDontCare
,
10915 kTextRegionDontCare
,
10917 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10922 ByteCount unicode_len
;
10925 pstr
[1] = inev
.code
;
10926 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10928 &unicode_len
, &code
);
10929 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10930 mac_set_unicode_keystroke_event (code
, &inev
);
10931 DisposeTextToUnicodeInfo (&ttu_info
);
10938 case kHighLevelEvent
:
10939 AEProcessAppleEvent (&er
);
10945 #if USE_CARBON_EVENTS
10946 ReleaseEvent (eventRef
);
10949 if (inev
.kind
!= NO_EVENT
)
10951 inev
.timestamp
= timestamp
;
10952 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10957 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10962 XSETFRAME (frame
, f
);
10968 any_help_event_p
= 1;
10969 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10970 help_echo_object
, help_echo_pos
);
10974 help_echo_string
= Qnil
;
10975 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10982 /* If the focus was just given to an autoraising frame,
10984 /* ??? This ought to be able to handle more than one such frame. */
10985 if (pending_autoraise_frame
)
10987 x_raise_frame (pending_autoraise_frame
);
10988 pending_autoraise_frame
= 0;
10991 #if !USE_CARBON_EVENTS
10992 /* Check which frames are still visible. We do this here because
10993 there doesn't seem to be any direct notification from the Window
10994 Manager that the visibility of a window has changed (at least,
10995 not in all cases). */
10997 Lisp_Object tail
, frame
;
10999 FOR_EACH_FRAME (tail
, frame
)
11001 struct frame
*f
= XFRAME (frame
);
11003 /* The tooltip has been drawn already. Avoid the
11004 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11005 if (EQ (frame
, tip_frame
))
11008 if (FRAME_MAC_P (f
))
11009 mac_handle_visibility_change (f
);
11020 /* Need to override CodeWarrior's input function so no conversion is
11021 done on newlines Otherwise compiled functions in .elc files will be
11022 read incorrectly. Defined in ...:MSL C:MSL
11023 Common:Source:buffer_io.c. */
11026 __convert_to_newlines (unsigned char * p
, size_t * n
)
11028 #pragma unused(p,n)
11032 __convert_from_newlines (unsigned char * p
, size_t * n
)
11034 #pragma unused(p,n)
11040 make_mac_terminal_frame (struct frame
*f
)
11045 XSETFRAME (frame
, f
);
11047 f
->output_method
= output_mac
;
11048 f
->output_data
.mac
= (struct mac_output
*)
11049 xmalloc (sizeof (struct mac_output
));
11050 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
11052 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
11054 FRAME_COLS (f
) = 96;
11055 FRAME_LINES (f
) = 4;
11057 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
11058 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
11060 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
11062 f
->output_data
.mac
->cursor_pixel
= 0;
11063 f
->output_data
.mac
->border_pixel
= 0x00ff00;
11064 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
11065 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
11067 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
11068 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
11069 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
11070 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
11071 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
11072 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
11074 FRAME_FONTSET (f
) = -1;
11075 f
->output_data
.mac
->explicit_parent
= 0;
11078 f
->border_width
= 0;
11080 f
->internal_border_width
= 0;
11085 f
->new_text_cols
= 0;
11086 f
->new_text_lines
= 0;
11088 SetRect (&r
, f
->left_pos
, f
->top_pos
,
11089 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
11090 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
11094 if (!(FRAME_MAC_WINDOW (f
) =
11095 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
11096 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
11098 /* so that update events can find this mac_output struct */
11099 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
11105 /* Need to be initialized for unshow_buffer in window.c. */
11106 selected_window
= f
->selected_window
;
11108 Fmodify_frame_parameters (frame
,
11109 Fcons (Fcons (Qfont
,
11110 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
11111 Fmodify_frame_parameters (frame
,
11112 Fcons (Fcons (Qforeground_color
,
11113 build_string ("black")), Qnil
));
11114 Fmodify_frame_parameters (frame
,
11115 Fcons (Fcons (Qbackground_color
,
11116 build_string ("white")), Qnil
));
11121 /***********************************************************************
11123 ***********************************************************************/
11125 int mac_initialized
= 0;
11128 mac_initialize_display_info ()
11130 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11132 bzero (dpyinfo
, sizeof (*dpyinfo
));
11135 dpyinfo
->mac_id_name
11136 = (char *) xmalloc (SCHARS (Vinvocation_name
)
11137 + SCHARS (Vsystem_name
)
11139 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
11140 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
11142 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
11143 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
11146 dpyinfo
->reference_count
= 0;
11147 dpyinfo
->resx
= 72.0;
11148 dpyinfo
->resy
= 72.0;
11150 /* HasDepth returns true if it is possible to have a 32 bit display,
11151 but this may not be what is actually used. Mac OSX can do better. */
11152 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11153 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11154 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11155 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11158 GDHandle main_device_handle
= LMGetMainDevice();
11160 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
11161 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11162 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
11163 gdDevType
, dpyinfo
->color_p
))
11165 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
11166 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
11169 dpyinfo
->grabbed
= 0;
11170 dpyinfo
->root_window
= NULL
;
11171 dpyinfo
->image_cache
= make_image_cache ();
11173 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11174 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11175 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11176 dpyinfo
->mouse_face_window
= Qnil
;
11177 dpyinfo
->mouse_face_overlay
= Qnil
;
11178 dpyinfo
->mouse_face_hidden
= 0;
11183 mac_make_rdb (xrm_option
)
11186 XrmDatabase database
;
11188 database
= xrm_get_preference_database (NULL
);
11190 xrm_merge_string_database (database
, xrm_option
);
11195 struct mac_display_info
*
11196 mac_term_init (display_name
, xrm_option
, resource_name
)
11197 Lisp_Object display_name
;
11199 char *resource_name
;
11201 struct mac_display_info
*dpyinfo
;
11205 if (!mac_initialized
)
11208 mac_initialized
= 1;
11211 if (x_display_list
)
11212 error ("Sorry, this version can only handle one display");
11214 mac_initialize_display_info ();
11216 dpyinfo
= &one_mac_display_info
;
11218 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
11220 /* Put this display on the chain. */
11221 dpyinfo
->next
= x_display_list
;
11222 x_display_list
= dpyinfo
;
11224 /* Put it on x_display_name_list. */
11225 x_display_name_list
= Fcons (Fcons (display_name
,
11226 Fcons (Qnil
, dpyinfo
->xrdb
)),
11227 x_display_name_list
);
11228 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11234 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11237 x_delete_display (dpyinfo
)
11238 struct mac_display_info
*dpyinfo
;
11242 /* Discard this display from x_display_name_list and x_display_list.
11243 We can't use Fdelq because that can quit. */
11244 if (! NILP (x_display_name_list
)
11245 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11246 x_display_name_list
= XCDR (x_display_name_list
);
11251 tail
= x_display_name_list
;
11252 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11254 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11256 XSETCDR (tail
, XCDR (XCDR (tail
)));
11259 tail
= XCDR (tail
);
11263 if (x_display_list
== dpyinfo
)
11264 x_display_list
= dpyinfo
->next
;
11267 struct x_display_info
*tail
;
11269 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11270 if (tail
->next
== dpyinfo
)
11271 tail
->next
= tail
->next
->next
;
11274 /* Free the font names in the font table. */
11275 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11276 if (dpyinfo
->font_table
[i
].name
)
11278 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11279 xfree (dpyinfo
->font_table
[i
].full_name
);
11280 xfree (dpyinfo
->font_table
[i
].name
);
11283 if (dpyinfo
->font_table
)
11285 if (dpyinfo
->font_table
->font_encoder
)
11286 xfree (dpyinfo
->font_table
->font_encoder
);
11287 xfree (dpyinfo
->font_table
);
11289 if (dpyinfo
->mac_id_name
)
11290 xfree (dpyinfo
->mac_id_name
);
11292 if (x_display_list
== 0)
11294 mac_clear_font_name_table ();
11295 bzero (dpyinfo
, sizeof (*dpyinfo
));
11304 extern int inhibit_window_system
;
11305 extern int noninteractive
;
11306 CFBundleRef appsBundle
;
11308 /* No need to test if already -nw*/
11309 if (inhibit_window_system
|| noninteractive
)
11312 appsBundle
= CFBundleGetMainBundle();
11313 if (appsBundle
!= NULL
)
11315 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
11316 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
11317 /* We found the bundle identifier, now we know we are valid. */
11324 /* MAC_TODO: Have this start the bundled executable */
11326 /* For now, prevent the fatal error by bringing it up in the terminal */
11327 inhibit_window_system
= 1;
11331 MakeMeTheFrontProcess ()
11333 ProcessSerialNumber psn
;
11336 err
= GetCurrentProcess (&psn
);
11338 (void) SetFrontProcess (&psn
);
11341 /***** Code to handle C-g testing *****/
11343 /* Contains the Mac modifier formed from quit_char */
11344 int mac_quit_char_modifiers
= 0;
11345 int mac_quit_char_keycode
;
11346 extern int quit_char
;
11349 mac_determine_quit_char_modifiers()
11351 /* Todo: Determine modifiers from quit_char. */
11352 UInt32 qc_modifiers
= ctrl_modifier
;
11354 /* Map modifiers */
11355 mac_quit_char_modifiers
= 0;
11356 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
11357 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
11358 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
11362 init_quit_char_handler ()
11364 /* TODO: Let this support keys other the 'g' */
11365 mac_quit_char_keycode
= 5;
11366 /* Look at <architecture/adb_kb_map.h> for details */
11367 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
11369 mac_determine_quit_char_modifiers();
11371 #endif /* MAC_OSX */
11379 MenuItemIndex menu_index
;
11381 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
11382 &menu
, &menu_index
);
11384 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11385 #if USE_CARBON_EVENTS
11386 EnableMenuCommand (NULL
, kHICommandPreferences
);
11387 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
11388 &menu
, &menu_index
);
11391 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11392 InsertMenuItemTextWithCFString (menu
, NULL
,
11393 0, kMenuItemAttrSeparator
, 0);
11394 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
11395 0, 0, kHICommandAbout
);
11397 #endif /* USE_CARBON_EVENTS */
11398 #else /* !MAC_OSX */
11399 #if USE_CARBON_EVENTS
11400 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
11410 static InterfaceTypeList types
= {kUnicodeDocument
};
11412 static InterfaceTypeList types
= {kTextService
};
11415 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
11416 &tsm_document_id
, 0);
11420 /* Set up use of X before we make the first connection. */
11422 extern frame_parm_handler mac_frame_parm_handlers
[];
11424 static struct redisplay_interface x_redisplay_interface
=
11426 mac_frame_parm_handlers
,
11430 x_clear_end_of_line
,
11432 x_after_update_window_line
,
11433 x_update_window_begin
,
11434 x_update_window_end
,
11437 0, /* flush_display_optional */
11438 x_clear_window_mouse_face
,
11439 x_get_glyph_overhangs
,
11440 x_fix_overlapping_area
,
11441 x_draw_fringe_bitmap
,
11443 mac_define_fringe_bitmap
,
11444 mac_destroy_fringe_bitmap
,
11446 0, /* define_fringe_bitmap */
11447 0, /* destroy_fringe_bitmap */
11449 mac_per_char_metric
,
11451 mac_compute_glyph_string_overhangs
,
11452 x_draw_glyph_string
,
11453 mac_define_frame_cursor
,
11454 mac_clear_frame_area
,
11455 mac_draw_window_cursor
,
11456 mac_draw_vertical_window_border
,
11457 mac_shift_glyphs_for_insert
11463 rif
= &x_redisplay_interface
;
11465 clear_frame_hook
= x_clear_frame
;
11466 ins_del_lines_hook
= x_ins_del_lines
;
11467 delete_glyphs_hook
= x_delete_glyphs
;
11468 ring_bell_hook
= XTring_bell
;
11469 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11470 set_terminal_modes_hook
= XTset_terminal_modes
;
11471 update_begin_hook
= x_update_begin
;
11472 update_end_hook
= x_update_end
;
11473 set_terminal_window_hook
= XTset_terminal_window
;
11474 read_socket_hook
= XTread_socket
;
11475 frame_up_to_date_hook
= XTframe_up_to_date
;
11476 mouse_position_hook
= XTmouse_position
;
11477 frame_rehighlight_hook
= XTframe_rehighlight
;
11478 frame_raise_lower_hook
= XTframe_raise_lower
;
11480 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11481 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11482 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11483 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11485 scroll_region_ok
= 1; /* we'll scroll partial frames */
11486 char_ins_del_ok
= 1;
11487 line_ins_del_ok
= 1; /* we'll just blt 'em */
11488 fast_clear_end_of_line
= 1; /* X does this well */
11489 memory_below_frame
= 0; /* we don't remember what scrolls
11493 last_tool_bar_item
= -1;
11494 any_help_event_p
= 0;
11496 /* Try to use interrupt input; if we can't, then start polling. */
11497 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
11501 #if TARGET_API_MAC_CARBON
11503 #if USE_CARBON_EVENTS
11505 init_service_handler ();
11507 init_quit_char_handler ();
11508 #endif /* MAC_OSX */
11510 init_command_handler ();
11517 #endif /* USE_CARBON_EVENTS */
11520 init_coercion_handler ();
11522 init_apple_event_handler ();
11524 if (!inhibit_window_system
)
11525 MakeMeTheFrontProcess ();
11530 mac_init_fringe ();
11541 staticpro (&x_error_message_string
);
11542 x_error_message_string
= Qnil
;
11545 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
11546 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
11547 Qalt
= intern ("alt"); staticpro (&Qalt
);
11548 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
11549 Qsuper
= intern ("super"); staticpro (&Qsuper
);
11550 Qmodifier_value
= intern ("modifier-value");
11551 staticpro (&Qmodifier_value
);
11553 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
11554 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11555 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11556 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11557 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11559 #if USE_CARBON_EVENTS
11560 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
11562 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
11563 staticpro (&Qtoolbar_switch_mode
);
11564 #if USE_MAC_FONT_PANEL
11565 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
11566 Qselection
= intern ("selection"); staticpro (&Qselection
);
11569 Qservice
= intern ("service"); staticpro (&Qservice
);
11570 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
11571 Qperform
= intern ("perform"); staticpro (&Qperform
);
11574 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
11575 Qupdate_active_input_area
= intern ("update-active-input-area");
11576 staticpro (&Qupdate_active_input_area
);
11577 Qunicode_for_key_event
= intern ("unicode-for-key-event");
11578 staticpro (&Qunicode_for_key_event
);
11583 Fprovide (intern ("mac-carbon"), Qnil
);
11586 staticpro (&Qreverse
);
11587 Qreverse
= intern ("reverse");
11589 staticpro (&x_display_name_list
);
11590 x_display_name_list
= Qnil
;
11592 staticpro (&last_mouse_scroll_bar
);
11593 last_mouse_scroll_bar
= Qnil
;
11595 staticpro (&fm_font_family_alist
);
11596 fm_font_family_alist
= Qnil
;
11599 staticpro (&atsu_font_id_hash
);
11600 atsu_font_id_hash
= Qnil
;
11602 staticpro (&fm_style_face_attributes_alist
);
11603 fm_style_face_attributes_alist
= Qnil
;
11607 staticpro (&saved_ts_script_language_on_focus
);
11608 saved_ts_script_language_on_focus
= Qnil
;
11611 /* We don't yet support this, but defining this here avoids whining
11612 from cus-start.el and other places, like "M-x set-variable". */
11613 DEFVAR_BOOL ("x-use-underline-position-properties",
11614 &x_use_underline_position_properties
,
11615 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11616 nil means ignore them. If you encounter fonts with bogus
11617 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11618 to 4.1, set this to nil.
11620 NOTE: Not supported on Mac yet. */);
11621 x_use_underline_position_properties
= 0;
11623 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
11624 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
11625 #ifdef USE_TOOLKIT_SCROLL_BARS
11626 Vx_toolkit_scroll_bars
= Qt
;
11628 Vx_toolkit_scroll_bars
= Qnil
;
11631 staticpro (&last_mouse_motion_frame
);
11632 last_mouse_motion_frame
= Qnil
;
11634 /* Variables to configure modifier key assignment. */
11636 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
11637 doc
: /* *Modifier key assumed when the Mac control key is pressed.
11638 The value can be `control', `meta', `alt', `hyper', or `super' for the
11639 respective modifier. The default is `control'. */);
11640 Vmac_control_modifier
= Qcontrol
;
11642 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
11643 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
11644 The value can be `control', `meta', `alt', `hyper', or `super' for the
11645 respective modifier. If the value is nil then the key will act as the
11646 normal Mac control modifier, and the option key can be used to compose
11647 characters depending on the chosen Mac keyboard setting. */);
11648 Vmac_option_modifier
= Qnil
;
11650 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
11651 doc
: /* *Modifier key assumed when the Mac command key is pressed.
11652 The value can be `control', `meta', `alt', `hyper', or `super' for the
11653 respective modifier. The default is `meta'. */);
11654 Vmac_command_modifier
= Qmeta
;
11656 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
11657 doc
: /* *Modifier key assumed when the Mac function key is pressed.
11658 The value can be `control', `meta', `alt', `hyper', or `super' for the
11659 respective modifier. Note that remapping the function key may lead to
11660 unexpected results for some keys on non-US/GB keyboards. */);
11661 Vmac_function_modifier
= Qnil
;
11663 DEFVAR_LISP ("mac-emulate-three-button-mouse",
11664 &Vmac_emulate_three_button_mouse
,
11665 doc
: /* *Specify a way of three button mouse emulation.
11666 The value can be nil, t, or the symbol `reverse'.
11667 nil means that no emulation should be done and the modifiers should be
11668 placed on the mouse-1 event.
11669 t means that when the option-key is held down while pressing the mouse
11670 button, the click will register as mouse-2 and while the command-key
11671 is held down, the click will register as mouse-3.
11672 The symbol `reverse' means that the option-key will register for
11673 mouse-3 and the command-key will register for mouse-2. */);
11674 Vmac_emulate_three_button_mouse
= Qnil
;
11676 #if USE_CARBON_EVENTS
11677 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
11678 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
11679 Otherwise, the right click will be treated as mouse-2 and the wheel
11680 button will be mouse-3. */);
11681 mac_wheel_button_is_mouse_2
= 1;
11683 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
11684 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
11685 mac_pass_command_to_system
= 1;
11687 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
11688 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
11689 mac_pass_control_to_system
= 1;
11693 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
11694 doc
: /* *If non-nil, allow anti-aliasing.
11695 The text will be rendered using Core Graphics text rendering which
11696 may anti-alias the text. */);
11698 mac_use_core_graphics
= 1;
11700 mac_use_core_graphics
= 0;
11703 /* Register an entry for `mac-roman' so that it can be used when
11704 creating the terminal frame on Mac OS 9 before loading
11705 term/mac-win.elc. */
11706 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
11707 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
11708 Each entry should be of the form:
11710 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
11712 where CHARSET-NAME is a string used in font names to identify the
11713 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
11714 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
11715 Vmac_charset_info_alist
=
11716 Fcons (list3 (build_string ("mac-roman"),
11717 make_number (smRoman
), Qnil
), Qnil
);
11720 DEFVAR_LISP ("mac-atsu-font-table", &Vmac_atsu_font_table
,
11721 doc
: /* Hash table of ATSU font IDs vs plist of attributes and values. */);
11722 Vmac_atsu_font_table
=
11723 make_hash_table (Qeql
, make_number (DEFAULT_HASH_SIZE
),
11724 make_float (DEFAULT_REHASH_SIZE
),
11725 make_float (DEFAULT_REHASH_THRESHOLD
),
11729 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
11730 doc
: /* Overlay used to display Mac TSM active input area. */);
11731 Vmac_ts_active_input_overlay
= Qnil
;
11733 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
11734 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
11735 If the value is t, the input script and language are restored to those
11736 used in the last focus frame. If the value is a pair of integers, the
11737 input script and language codes, which are defined in the Script
11738 Manager, are set to its car and cdr parts, respectively. Otherwise,
11739 Emacs doesn't set them and thus follows the system default behavior. */);
11740 Vmac_ts_script_language_on_focus
= Qnil
;
11744 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
11745 (do not change this comment) */