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 /* A mask of extra modifier bits to put into every keyboard char. */
201 extern EMACS_INT extra_keyboard_modifiers
;
203 /* The keysyms to use for the various modifiers. */
205 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
207 extern int inhibit_window_system
;
209 #if __MRC__ && !TARGET_API_MAC_CARBON
210 QDGlobals qd
; /* QuickDraw global information structure. */
213 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
215 struct mac_display_info
*mac_display_info_for_display (Display
*);
216 static void x_update_window_end
P_ ((struct window
*, int, int));
217 int x_catch_errors
P_ ((Display
*));
218 void x_uncatch_errors
P_ ((Display
*, int));
219 void x_lower_frame
P_ ((struct frame
*));
220 void x_scroll_bar_clear
P_ ((struct frame
*));
221 int x_had_errors_p
P_ ((Display
*));
222 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
223 void x_raise_frame
P_ ((struct frame
*));
224 void x_set_window_size
P_ ((struct frame
*, int, int, int));
225 void x_wm_set_window_state
P_ ((struct frame
*, int));
226 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
227 void mac_initialize
P_ ((void));
228 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
229 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
230 static void x_update_end
P_ ((struct frame
*));
231 static void XTframe_up_to_date
P_ ((struct frame
*));
232 static void XTset_terminal_modes
P_ ((void));
233 static void XTreset_terminal_modes
P_ ((void));
234 static void x_clear_frame
P_ ((void));
235 static void frame_highlight
P_ ((struct frame
*));
236 static void frame_unhighlight
P_ ((struct frame
*));
237 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
238 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
239 struct frame
*, struct input_event
*));
240 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
241 EventRecord
*, struct input_event
*));
242 static void XTframe_rehighlight
P_ ((struct frame
*));
243 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
244 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
245 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
246 enum text_cursor_kinds
));
248 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
249 static void x_flush
P_ ((struct frame
*f
));
250 static void x_update_begin
P_ ((struct frame
*));
251 static void x_update_window_begin
P_ ((struct window
*));
252 static void x_after_update_window_line
P_ ((struct glyph_row
*));
253 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
254 enum scroll_bar_part
*,
255 Lisp_Object
*, Lisp_Object
*,
258 static int is_emacs_window
P_ ((WindowPtr
));
259 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
260 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
262 /* Defined in macmenu.h. */
263 extern void menubar_selection_callback (FRAME_PTR
, int);
265 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
266 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
267 #define GC_FONT(gc) ((gc)->xgcv.font)
268 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
269 #define CG_SET_FILL_COLOR(context, color) \
270 CGContextSetRGBFillColor (context, \
271 RED_FROM_ULONG (color) / 255.0f, \
272 GREEN_FROM_ULONG (color) / 255.0f, \
273 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
274 #define CG_SET_STROKE_COLOR(context, color) \
275 CGContextSetRGBStrokeColor (context, \
276 RED_FROM_ULONG (color) / 255.0f, \
277 GREEN_FROM_ULONG (color) / 255.0f, \
278 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
280 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
282 /* Fringe bitmaps. */
284 static int max_fringe_bmp
= 0;
285 static CGImageRef
*fringe_bmp
= 0;
288 mac_begin_cg_clip (f
, gc
)
292 CGContextRef context
= FRAME_CG_CONTEXT (f
);
296 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
297 FRAME_CG_CONTEXT (f
) = context
;
300 CGContextSaveGState (context
);
301 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
302 CGContextScaleCTM (context
, 1, -1);
303 if (gc
&& gc
->n_clip_rects
)
304 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
313 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
317 mac_prepare_for_quickdraw (f
)
322 Lisp_Object rest
, frame
;
323 FOR_EACH_FRAME (rest
, frame
)
324 if (FRAME_MAC_P (XFRAME (frame
)))
325 mac_prepare_for_quickdraw (XFRAME (frame
));
329 CGContextRef context
= FRAME_CG_CONTEXT (f
);
333 CGContextSynchronize (context
);
334 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
335 &FRAME_CG_CONTEXT (f
));
341 static RgnHandle saved_port_clip_region
= NULL
;
347 static RgnHandle new_region
= NULL
;
349 if (saved_port_clip_region
== NULL
)
350 saved_port_clip_region
= NewRgn ();
351 if (new_region
== NULL
)
352 new_region
= NewRgn ();
354 if (gc
->n_clip_rects
)
356 GetClip (saved_port_clip_region
);
357 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
358 SetClip (new_region
);
366 if (gc
->n_clip_rects
)
367 SetClip (saved_port_clip_region
);
371 /* X display function emulation */
374 XFreePixmap (display
, pixmap
)
375 Display
*display
; /* not used */
378 DisposeGWorld (pixmap
);
382 /* Mac version of XDrawLine. */
385 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
391 CGContextRef context
;
392 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
395 gx1
+= 0.5f
, gx2
+= 0.5f
;
397 gy1
+= 0.5f
, gy2
+= 0.5f
;
399 context
= mac_begin_cg_clip (f
, gc
);
400 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
401 CGContextBeginPath (context
);
402 CGContextMoveToPoint (context
, gx1
, gy1
);
403 CGContextAddLineToPoint (context
, gx2
, gy2
);
404 CGContextClosePath (context
);
405 CGContextStrokePath (context
);
423 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
425 RGBForeColor (GC_FORE_COLOR (gc
));
435 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
459 GetGWorld (&old_port
, &old_gdh
);
462 RGBForeColor (GC_FORE_COLOR (gc
));
464 LockPixels (GetGWorldPixMap (p
));
467 UnlockPixels (GetGWorldPixMap (p
));
469 SetGWorld (old_port
, old_gdh
);
474 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
478 unsigned int width
, height
;
481 CGContextRef context
;
483 context
= mac_begin_cg_clip (f
, gc
);
484 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
485 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
490 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
492 RGBBackColor (GC_BACK_COLOR (gc
));
493 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
499 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
504 /* Mac version of XClearArea. */
507 mac_clear_area (f
, x
, y
, width
, height
)
510 unsigned int width
, height
;
512 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
515 /* Mac version of XClearWindow. */
522 CGContextRef context
;
523 GC gc
= FRAME_NORMAL_GC (f
);
525 context
= mac_begin_cg_clip (f
, NULL
);
526 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
527 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
528 FRAME_PIXEL_HEIGHT (f
)));
531 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
533 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
535 #if TARGET_API_MAC_CARBON
539 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
542 #else /* not TARGET_API_MAC_CARBON */
543 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
544 #endif /* not TARGET_API_MAC_CARBON */
549 /* Mac replacement for XCopyArea. */
553 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
554 dest_x
, dest_y
, overlay_p
)
559 unsigned int width
, height
;
560 int dest_x
, dest_y
, overlay_p
;
562 CGContextRef context
;
563 float port_height
= FRAME_PIXEL_HEIGHT (f
);
564 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
566 context
= mac_begin_cg_clip (f
, gc
);
569 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
570 CGContextFillRect (context
, dest_rect
);
572 CGContextClipToRect (context
, dest_rect
);
573 CGContextScaleCTM (context
, 1, -1);
574 CGContextTranslateCTM (context
, 0, -port_height
);
575 if (CGImageIsMask (image
))
576 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
577 CGContextDrawImage (context
,
578 CGRectMake (dest_x
- src_x
,
579 port_height
- (dest_y
- src_y
580 + CGImageGetHeight (image
)),
581 CGImageGetWidth (image
),
582 CGImageGetHeight (image
)),
587 #else /* !USE_CG_DRAWING */
590 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
593 int x
, y
, width
, height
;
594 unsigned short *bits
;
600 bitmap
.rowBytes
= sizeof(unsigned short);
601 bitmap
.baseAddr
= (char *)bits
;
602 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
604 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
606 RGBForeColor (GC_FORE_COLOR (gc
));
607 RGBBackColor (GC_BACK_COLOR (gc
));
608 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
611 #if TARGET_API_MAC_CARBON
617 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
618 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
619 UnlockPortBits (port
);
621 #else /* not TARGET_API_MAC_CARBON */
622 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
623 overlay_p
? srcOr
: srcCopy
, 0);
624 #endif /* not TARGET_API_MAC_CARBON */
627 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
629 #endif /* !USE_CG_DRAWING */
632 /* Mac replacement for XCreateBitmapFromBitmapData. */
635 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
640 static unsigned char swap_nibble
[16]
641 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
642 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
643 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
644 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
648 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
649 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
650 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
651 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
652 for (i
= 0; i
< h
; i
++)
654 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
655 for (j
= 0; j
< w1
; j
++)
657 /* Bitswap XBM bytes to match how Mac does things. */
658 unsigned char c
= *bits
++;
659 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
660 | (swap_nibble
[(c
>>4) & 0xf]));;
664 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
669 mac_free_bitmap (bitmap
)
672 xfree (bitmap
->baseAddr
);
677 XCreatePixmap (display
, w
, width
, height
, depth
)
678 Display
*display
; /* not used */
680 unsigned int width
, height
;
687 SetPortWindowPort (w
);
689 SetRect (&r
, 0, 0, width
, height
);
690 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
693 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
694 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
696 /* CreateCGImageFromPixMaps requires ARGB format. */
697 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
706 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
707 Display
*display
; /* not used */
710 unsigned int width
, height
;
711 unsigned long fg
, bg
;
718 static GC gc
= NULL
; /* not reentrant */
721 gc
= XCreateGC (display
, w
, 0, NULL
);
723 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
727 GetGWorld (&old_port
, &old_gdh
);
728 SetGWorld (pixmap
, NULL
);
729 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
730 XSetForeground (display
, gc
, fg
);
731 XSetBackground (display
, gc
, bg
);
732 RGBForeColor (GC_FORE_COLOR (gc
));
733 RGBBackColor (GC_BACK_COLOR (gc
));
734 LockPixels (GetGWorldPixMap (pixmap
));
735 #if TARGET_API_MAC_CARBON
736 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
737 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
738 #else /* not TARGET_API_MAC_CARBON */
739 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
740 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
741 #endif /* not TARGET_API_MAC_CARBON */
742 UnlockPixels (GetGWorldPixMap (pixmap
));
743 SetGWorld (old_port
, old_gdh
);
744 mac_free_bitmap (&bitmap
);
750 /* Mac replacement for XFillRectangle. */
753 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
757 unsigned int width
, height
;
760 CGContextRef context
;
762 context
= mac_begin_cg_clip (f
, gc
);
763 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
764 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
769 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
771 RGBForeColor (GC_FORE_COLOR (gc
));
772 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
775 PaintRect (&r
); /* using foreground color of gc */
781 /* Mac replacement for XDrawRectangle: dest is a window. */
784 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
788 unsigned int width
, height
;
791 CGContextRef context
;
793 context
= mac_begin_cg_clip (f
, gc
);
794 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
795 CGContextStrokeRect (context
,
796 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
801 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
803 RGBForeColor (GC_FORE_COLOR (gc
));
804 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
807 FrameRect (&r
); /* using foreground color of gc */
815 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
816 ConstUniCharArrayPtr text
;
817 UniCharCount text_length
;
819 ATSUTextLayout
*text_layout
;
822 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
824 if (saved_text_layout
== NULL
)
826 UniCharCount lengths
[] = {kATSUToTextEnd
};
827 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
828 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
829 static ATSLineLayoutOptions line_layout
=
830 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
831 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
832 | kATSLineUseQDRendering
834 kATSLineIsDisplayOnly
| kATSLineFractDisable
837 ATSUAttributeValuePtr values
[] = {&line_layout
};
839 err
= ATSUCreateTextLayoutWithTextPtr (text
,
840 kATSUFromTextBeginning
,
846 err
= ATSUSetLayoutControls (saved_text_layout
,
847 sizeof (tags
) / sizeof (tags
[0]),
848 tags
, sizes
, values
);
849 /* XXX: Should we do this? */
851 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
855 err
= ATSUSetRunStyle (saved_text_layout
, style
,
856 kATSUFromTextBeginning
, kATSUToTextEnd
);
858 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
859 kATSUFromTextBeginning
,
865 *text_layout
= saved_text_layout
;
872 mac_invert_rectangle (f
, x
, y
, width
, height
)
875 unsigned int width
, height
;
880 mac_prepare_for_quickdraw (f
);
882 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
884 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
891 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, bytes_per_char
)
896 int nchars
, bg_width
, bytes_per_char
;
898 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
901 if (GC_FONT (gc
)->mac_style
)
904 ATSUTextLayout text_layout
;
906 xassert (bytes_per_char
== 2);
908 #ifndef WORDS_BIG_ENDIAN
911 UniChar
*text
= (UniChar
*)buf
;
913 for (i
= 0; i
< nchars
; i
++)
914 text
[i
] = EndianU16_BtoN (text
[i
]);
917 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
919 GC_FONT (gc
)->mac_style
,
924 if (!mac_use_core_graphics
)
928 mac_prepare_for_quickdraw (f
);
931 RGBForeColor (GC_FORE_COLOR (gc
));
936 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
937 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
938 RGBBackColor (GC_BACK_COLOR (gc
));
940 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
943 ATSUDrawText (text_layout
,
944 kATSUFromTextBeginning
, kATSUToTextEnd
,
945 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
952 CGContextRef context
;
953 float port_height
= FRAME_PIXEL_HEIGHT (f
);
954 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
955 ByteCount sizes
[] = {sizeof (CGContextRef
)};
956 ATSUAttributeValuePtr values
[] = {&context
};
959 context
= mac_begin_cg_clip (f
, gc
);
962 QDBeginCGContext (port
, &context
);
963 if (gc
->n_clip_rects
|| bg_width
)
965 CGContextTranslateCTM (context
, 0, port_height
);
966 CGContextScaleCTM (context
, 1, -1);
967 if (gc
->n_clip_rects
)
968 CGContextClipToRects (context
, gc
->clip_rects
,
973 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
976 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
977 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
979 CGContextScaleCTM (context
, 1, -1);
980 CGContextTranslateCTM (context
, 0, -port_height
);
984 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
985 err
= ATSUSetLayoutControls (text_layout
,
986 sizeof (tags
) / sizeof (tags
[0]),
987 tags
, sizes
, values
);
989 ATSUDrawText (text_layout
,
990 kATSUFromTextBeginning
, kATSUToTextEnd
,
991 Long2Fix (x
), Long2Fix (port_height
- y
));
996 CGContextSynchronize (context
);
997 QDEndCGContext (port
, &context
);
1000 /* This doesn't work on Mac OS X 10.1. */
1001 ATSUClearLayoutControls (text_layout
,
1002 sizeof (tags
) / sizeof (tags
[0]), tags
);
1004 ATSUSetLayoutControls (text_layout
,
1005 sizeof (tags
) / sizeof (tags
[0]),
1006 tags
, sizes
, values
);
1009 #endif /* MAC_OSX */
1012 #endif /* USE_ATSUI */
1014 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1017 if (mac_use_core_graphics
)
1018 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1021 mac_prepare_for_quickdraw (f
);
1023 mac_begin_clip (gc
);
1024 RGBForeColor (GC_FORE_COLOR (gc
));
1028 RGBBackColor (GC_BACK_COLOR (gc
));
1034 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1036 - Screen is double-buffered. (In srcCopy mode, a text is
1037 drawn into an offscreen graphics world first. So
1038 performance gain cannot be expected.)
1039 - It lowers rendering quality.
1040 - Some fonts leave garbage on cursor movement. */
1045 RGBBackColor (GC_BACK_COLOR (gc
));
1046 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1047 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1052 TextFont (GC_FONT (gc
)->mac_fontnum
);
1053 TextSize (GC_FONT (gc
)->mac_fontsize
);
1054 TextFace (GC_FONT (gc
)->mac_fontface
);
1056 DrawText (buf
, 0, nchars
* bytes_per_char
);
1058 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1061 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1062 if (mac_use_core_graphics
)
1063 SwapQDTextFlags(savedFlags
);
1069 /* Mac replacement for XDrawString. */
1072 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
1079 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, 0, 1);
1083 /* Mac replacement for XDrawString16. */
1086 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
1093 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, 0, 2);
1097 /* Mac replacement for XDrawImageString. */
1100 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1105 int nchars
, bg_width
;
1107 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, 1);
1111 /* Mac replacement for XDrawString16. */
1114 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1119 int nchars
, bg_width
;
1121 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
, 2);
1125 /* Mac replacement for XQueryTextExtents, but takes a character. If
1126 STYLE is NULL, measurement is done by QuickDraw Text routines for
1127 the font of the current graphics port. If CG_GLYPH is not NULL,
1128 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1131 mac_query_char_extents (style
, c
,
1132 font_ascent_return
, font_descent_return
,
1133 overall_return
, cg_glyph
)
1140 int *font_ascent_return
, *font_descent_return
;
1141 XCharStruct
*overall_return
;
1142 #if USE_CG_TEXT_DRAWING
1155 ATSUTextLayout text_layout
;
1158 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1161 ATSTrapezoid glyph_bounds
;
1163 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1164 kATSUFromTextBeginning
, kATSUToTextEnd
,
1165 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1166 kATSUseFractionalOrigins
,
1168 kATSUseDeviceOrigins
,
1170 1, &glyph_bounds
, NULL
);
1173 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1174 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1176 width
= Fix2Long (glyph_bounds
.upperRight
.x
1177 - glyph_bounds
.upperLeft
.x
);
1178 if (font_ascent_return
)
1179 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1180 if (font_descent_return
)
1181 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1184 if (err
== noErr
&& overall_return
)
1186 err
= ATSUMeasureTextImage (text_layout
,
1187 kATSUFromTextBeginning
, kATSUToTextEnd
,
1188 0, 0, &char_bounds
);
1190 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1191 #if USE_CG_TEXT_DRAWING
1192 if (err
== noErr
&& cg_glyph
)
1195 ATSUGlyphInfoArray glyph_info_array
;
1196 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1198 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1199 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1201 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1202 kATSUToTextEnd
, &count
,
1206 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1207 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1218 if (font_ascent_return
|| font_descent_return
)
1222 GetFontInfo (&font_info
);
1223 if (font_ascent_return
)
1224 *font_ascent_return
= font_info
.ascent
;
1225 if (font_descent_return
)
1226 *font_descent_return
= font_info
.descent
;
1232 width
= CharWidth (ch
);
1233 QDTextBounds (1, &ch
, &char_bounds
);
1234 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1242 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1245 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1246 XFontStruct
*font_struct
;
1249 XCharStruct
*overall_return
;
1252 short width
= 0, lbearing
= 0, rbearing
= 0;
1255 for (i
= 0; i
< nchars
; i
++)
1257 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1259 width
+= FONT_WIDTH (font_struct
);
1262 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1263 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1264 width
+= pcm
->width
;
1269 overall_return
->lbearing
= lbearing
;
1270 overall_return
->rbearing
= rbearing
;
1271 overall_return
->width
= width
;
1273 /* What's the meaning of the return value of XTextExtents16? */
1277 #if USE_CG_TEXT_DRAWING
1278 static int cg_text_anti_aliasing_threshold
= 8;
1281 init_cg_text_anti_aliasing_threshold ()
1287 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1288 kCFPreferencesCurrentApplication
,
1291 cg_text_anti_aliasing_threshold
= threshold
;
1295 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1300 int nchars
, bg_width
;
1303 float port_height
, gx
, gy
;
1305 CGContextRef context
;
1309 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1312 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1313 port_height
= FRAME_PIXEL_HEIGHT (f
);
1315 gy
= port_height
- y
;
1316 glyphs
= (CGGlyph
*)buf
;
1317 advances
= alloca (sizeof (CGSize
) * nchars
);
1318 if (advances
== NULL
)
1320 for (i
= 0; i
< nchars
; i
++)
1322 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1324 advances
[i
].width
= pcm
->width
;
1325 advances
[i
].height
= 0;
1326 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1331 context
= mac_begin_cg_clip (f
, gc
);
1333 QDBeginCGContext (port
, &context
);
1334 if (gc
->n_clip_rects
|| bg_width
)
1336 CGContextTranslateCTM (context
, 0, port_height
);
1337 CGContextScaleCTM (context
, 1, -1);
1338 if (gc
->n_clip_rects
)
1339 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1343 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
1346 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1347 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1349 CGContextScaleCTM (context
, 1, -1);
1350 CGContextTranslateCTM (context
, 0, -port_height
);
1354 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
1355 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1356 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1357 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1358 CGContextSetShouldAntialias (context
, false);
1359 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1360 CGContextSetTextPosition (context
, gx
, gy
);
1361 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1363 for (i
= 0; i
< nchars
; i
++)
1365 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1366 gx
+= advances
[i
].width
;
1370 mac_end_cg_clip (f
);
1372 CGContextSynchronize (context
);
1373 QDEndCGContext (port
, &context
);
1382 /* Mac replacement for XCopyArea: dest must be window. */
1385 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1390 unsigned int width
, height
;
1395 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1397 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1398 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1400 ForeColor (blackColor
);
1401 BackColor (whiteColor
);
1403 mac_begin_clip (gc
);
1404 LockPixels (GetGWorldPixMap (src
));
1405 #if TARGET_API_MAC_CARBON
1410 LockPortBits (port
);
1411 CopyBits (GetPortBitMapForCopyBits (src
),
1412 GetPortBitMapForCopyBits (port
),
1413 &src_r
, &dest_r
, srcCopy
, 0);
1414 UnlockPortBits (port
);
1416 #else /* not TARGET_API_MAC_CARBON */
1417 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1418 &src_r
, &dest_r
, srcCopy
, 0);
1419 #endif /* not TARGET_API_MAC_CARBON */
1420 UnlockPixels (GetGWorldPixMap (src
));
1423 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1428 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1429 width
, height
, dest_x
, dest_y
)
1434 unsigned int width
, height
;
1439 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1441 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1442 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1444 ForeColor (blackColor
);
1445 BackColor (whiteColor
);
1447 mac_begin_clip (gc
);
1448 LockPixels (GetGWorldPixMap (src
));
1449 LockPixels (GetGWorldPixMap (mask
));
1450 #if TARGET_API_MAC_CARBON
1455 LockPortBits (port
);
1456 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1457 GetPortBitMapForCopyBits (port
),
1458 &src_r
, &src_r
, &dest_r
);
1459 UnlockPortBits (port
);
1461 #else /* not TARGET_API_MAC_CARBON */
1462 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1463 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1464 #endif /* not TARGET_API_MAC_CARBON */
1465 UnlockPixels (GetGWorldPixMap (mask
));
1466 UnlockPixels (GetGWorldPixMap (src
));
1469 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1471 #endif /* !USE_CG_DRAWING */
1474 /* Mac replacement for XCopyArea: used only for scrolling. */
1477 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1481 unsigned int width
, height
;
1484 #if TARGET_API_MAC_CARBON
1486 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1488 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1490 mac_prepare_for_quickdraw (f
);
1492 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1493 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1494 kScrollWindowNoOptions
, dummy
);
1496 #else /* not TARGET_API_MAC_CARBON */
1498 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1502 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1503 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1505 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1506 color mapping in CopyBits. Otherwise, it will be slow. */
1507 ForeColor (blackColor
);
1508 BackColor (whiteColor
);
1509 mac_begin_clip (gc
);
1510 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1513 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1514 #endif /* not TARGET_API_MAC_CARBON */
1518 /* Mac replacement for XChangeGC. */
1521 XChangeGC (display
, gc
, mask
, xgcv
)
1527 if (mask
& GCForeground
)
1528 XSetForeground (display
, gc
, xgcv
->foreground
);
1529 if (mask
& GCBackground
)
1530 XSetBackground (display
, gc
, xgcv
->background
);
1532 XSetFont (display
, gc
, xgcv
->font
);
1536 /* Mac replacement for XCreateGC. */
1539 XCreateGC (display
, window
, mask
, xgcv
)
1545 GC gc
= xmalloc (sizeof (*gc
));
1547 bzero (gc
, sizeof (*gc
));
1548 XChangeGC (display
, gc
, mask
, xgcv
);
1554 /* Used in xfaces.c. */
1557 XFreeGC (display
, gc
)
1561 if (gc
->clip_region
)
1562 DisposeRgn (gc
->clip_region
);
1567 /* Mac replacement for XGetGCValues. */
1570 XGetGCValues (display
, gc
, mask
, xgcv
)
1576 if (mask
& GCForeground
)
1577 xgcv
->foreground
= gc
->xgcv
.foreground
;
1578 if (mask
& GCBackground
)
1579 xgcv
->background
= gc
->xgcv
.background
;
1581 xgcv
->font
= gc
->xgcv
.font
;
1585 /* Mac replacement for XSetForeground. */
1588 XSetForeground (display
, gc
, color
)
1591 unsigned long color
;
1593 if (gc
->xgcv
.foreground
!= color
)
1595 gc
->xgcv
.foreground
= color
;
1596 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1597 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1598 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1603 /* Mac replacement for XSetBackground. */
1606 XSetBackground (display
, gc
, color
)
1609 unsigned long color
;
1611 if (gc
->xgcv
.background
!= color
)
1613 gc
->xgcv
.background
= color
;
1614 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1615 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1616 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1621 /* Mac replacement for XSetFont. */
1624 XSetFont (display
, gc
, font
)
1629 gc
->xgcv
.font
= font
;
1633 /* Mac replacement for XSetClipRectangles. */
1636 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1644 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1646 gc
->n_clip_rects
= n
;
1649 if (gc
->clip_region
== NULL
)
1650 gc
->clip_region
= NewRgn ();
1651 RectRgn (gc
->clip_region
, rectangles
);
1654 RgnHandle region
= NewRgn ();
1656 for (i
= 1; i
< n
; i
++)
1658 RectRgn (region
, rectangles
+ i
);
1659 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1661 DisposeRgn (region
);
1664 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1665 for (i
= 0; i
< n
; i
++)
1667 Rect
*rect
= rectangles
+ i
;
1669 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1670 rect
->right
- rect
->left
,
1671 rect
->bottom
- rect
->top
);
1677 /* Mac replacement for XSetClipMask. */
1680 mac_reset_clip_rectangles (display
, gc
)
1684 gc
->n_clip_rects
= 0;
1688 /* Mac replacement for XSetWindowBackground. */
1691 XSetWindowBackground (display
, w
, color
)
1694 unsigned long color
;
1696 #if !TARGET_API_MAC_CARBON
1697 AuxWinHandle aw_handle
;
1698 CTabHandle ctab_handle
;
1699 ColorSpecPtr ct_table
;
1704 bg_color
.red
= RED16_FROM_ULONG (color
);
1705 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1706 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1708 #if TARGET_API_MAC_CARBON
1709 SetWindowContentColor (w
, &bg_color
);
1711 if (GetAuxWin (w
, &aw_handle
))
1713 ctab_handle
= (*aw_handle
)->awCTable
;
1714 HandToHand ((Handle
*) &ctab_handle
);
1715 ct_table
= (*ctab_handle
)->ctTable
;
1716 ct_size
= (*ctab_handle
)->ctSize
;
1717 while (ct_size
> -1)
1719 if (ct_table
->value
== 0)
1721 ct_table
->rgb
= bg_color
;
1722 CTabChanged (ctab_handle
);
1723 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1731 /* Flush display of frame F, or of all frames if F is null. */
1737 #if TARGET_API_MAC_CARBON
1740 mac_prepare_for_quickdraw (f
);
1743 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1745 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1751 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1752 Calls to XFlush should be unnecessary because the X output buffer
1753 is flushed automatically as needed by calls to XPending,
1754 XNextEvent, or XWindowEvent according to the XFlush man page.
1755 XTread_socket calls XPending. Removing XFlush improves
1758 #define XFlush(DISPLAY) (void) 0
1761 /* Return the struct mac_display_info corresponding to DPY. There's
1764 struct mac_display_info
*
1765 mac_display_info_for_display (dpy
)
1768 return &one_mac_display_info
;
1773 /***********************************************************************
1774 Starting and ending an update
1775 ***********************************************************************/
1777 /* Start an update of frame F. This function is installed as a hook
1778 for update_begin, i.e. it is called when update_begin is called.
1779 This function is called prior to calls to x_update_window_begin for
1780 each window being updated. */
1786 #if TARGET_API_MAC_CARBON
1787 /* During update of a frame, availability of input events is
1788 periodically checked with ReceiveNextEvent if
1789 redisplay-dont-pause is nil. That normally flushes window buffer
1790 changes for every check, and thus screen update looks waving even
1791 if no input is available. So we disable screen updates during
1792 update of a frame. */
1794 DisableScreenUpdates ();
1800 /* Start update of window W. Set the global variable updated_window
1801 to the window being updated and set output_cursor to the cursor
1805 x_update_window_begin (w
)
1808 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1809 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1812 set_output_cursor (&w
->cursor
);
1816 if (f
== display_info
->mouse_face_mouse_frame
)
1818 /* Don't do highlighting for mouse motion during the update. */
1819 display_info
->mouse_face_defer
= 1;
1821 /* If F needs to be redrawn, simply forget about any prior mouse
1823 if (FRAME_GARBAGED_P (f
))
1824 display_info
->mouse_face_window
= Qnil
;
1826 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1827 their mouse_face_p flag set, which means that they are always
1828 unequal to rows in a desired matrix which never have that
1829 flag set. So, rows containing mouse-face glyphs are never
1830 scrolled, and we don't have to switch the mouse highlight off
1831 here to prevent it from being scrolled. */
1833 /* Can we tell that this update does not affect the window
1834 where the mouse highlight is? If so, no need to turn off.
1835 Likewise, don't do anything if the frame is garbaged;
1836 in that case, the frame's current matrix that we would use
1837 is all wrong, and we will redisplay that line anyway. */
1838 if (!NILP (display_info
->mouse_face_window
)
1839 && w
== XWINDOW (display_info
->mouse_face_window
))
1843 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1844 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1847 if (i
< w
->desired_matrix
->nrows
)
1848 clear_mouse_face (display_info
);
1857 /* Draw a vertical window border from (x,y0) to (x,y1) */
1860 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1864 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1867 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1869 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1872 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1875 /* End update of window W (which is equal to updated_window).
1877 Draw vertical borders between horizontally adjacent windows, and
1878 display W's cursor if CURSOR_ON_P is non-zero.
1880 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1881 glyphs in mouse-face were overwritten. In that case we have to
1882 make sure that the mouse-highlight is properly redrawn.
1884 W may be a menu bar pseudo-window in case we don't have X toolkit
1885 support. Such windows don't have a cursor, so don't display it
1889 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1891 int cursor_on_p
, mouse_face_overwritten_p
;
1893 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1895 if (!w
->pseudo_window_p
)
1900 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1902 output_cursor
.x
, output_cursor
.y
);
1904 if (draw_window_fringes (w
, 1))
1905 x_draw_vertical_border (w
);
1910 /* If a row with mouse-face was overwritten, arrange for
1911 XTframe_up_to_date to redisplay the mouse highlight. */
1912 if (mouse_face_overwritten_p
)
1914 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1915 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1916 dpyinfo
->mouse_face_window
= Qnil
;
1919 updated_window
= NULL
;
1923 /* End update of frame F. This function is installed as a hook in
1930 /* Mouse highlight may be displayed again. */
1931 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1934 #if TARGET_API_MAC_CARBON
1935 EnableScreenUpdates ();
1937 XFlush (FRAME_MAC_DISPLAY (f
));
1942 /* This function is called from various places in xdisp.c whenever a
1943 complete update has been performed. The global variable
1944 updated_window is not available here. */
1947 XTframe_up_to_date (f
)
1950 if (FRAME_MAC_P (f
))
1952 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1954 if (dpyinfo
->mouse_face_deferred_gc
1955 || f
== dpyinfo
->mouse_face_mouse_frame
)
1958 if (dpyinfo
->mouse_face_mouse_frame
)
1959 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1960 dpyinfo
->mouse_face_mouse_x
,
1961 dpyinfo
->mouse_face_mouse_y
);
1962 dpyinfo
->mouse_face_deferred_gc
= 0;
1969 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1970 arrow bitmaps, or clear the fringes if no bitmaps are required
1971 before DESIRED_ROW is made current. The window being updated is
1972 found in updated_window. This function is called from
1973 update_window_line only if it is known that there are differences
1974 between bitmaps to be drawn between current row and DESIRED_ROW. */
1977 x_after_update_window_line (desired_row
)
1978 struct glyph_row
*desired_row
;
1980 struct window
*w
= updated_window
;
1986 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1987 desired_row
->redraw_fringe_bitmaps_p
= 1;
1989 /* When a window has disappeared, make sure that no rest of
1990 full-width rows stays visible in the internal border. Could
1991 check here if updated_window is the leftmost/rightmost window,
1992 but I guess it's not worth doing since vertically split windows
1993 are almost never used, internal border is rarely set, and the
1994 overhead is very small. */
1995 if (windows_or_buffers_changed
1996 && desired_row
->full_width_p
1997 && (f
= XFRAME (w
->frame
),
1998 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2000 && (height
= desired_row
->visible_height
,
2003 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2005 /* Internal border is drawn below the tool bar. */
2006 if (WINDOWP (f
->tool_bar_window
)
2007 && w
== XWINDOW (f
->tool_bar_window
))
2011 mac_clear_area (f
, 0, y
, width
, height
);
2012 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2018 /* Draw the bitmap WHICH in one of the left or right fringes of
2019 window W. ROW is the glyph row for which to display the bitmap; it
2020 determines the vertical position at which the bitmap has to be
2024 x_draw_fringe_bitmap (w
, row
, p
)
2026 struct glyph_row
*row
;
2027 struct draw_fringe_bitmap_params
*p
;
2029 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2030 Display
*display
= FRAME_MAC_DISPLAY (f
);
2031 struct face
*face
= p
->face
;
2034 /* Must clip because of partially visible lines. */
2035 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2038 /* Adjust position of "bottom aligned" bitmap on partially
2039 visible last row. */
2041 int oldVH
= row
->visible_height
;
2042 row
->visible_height
= p
->h
;
2043 row
->y
-= rowY
- p
->y
;
2044 x_clip_to_row (w
, row
, -1, face
->gc
);
2046 row
->visible_height
= oldVH
;
2049 x_clip_to_row (w
, row
, -1, face
->gc
);
2051 if (p
->bx
>= 0 && !p
->overlay_p
)
2053 #if 0 /* MAC_TODO: stipple */
2054 /* In case the same realized face is used for fringes and
2055 for something displayed in the text (e.g. face `region' on
2056 mono-displays, the fill style may have been changed to
2057 FillSolid in x_draw_glyph_string_background. */
2059 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2061 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2064 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2066 #if 0 /* MAC_TODO: stipple */
2068 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2074 && p
->which
< max_fringe_bmp
2080 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2081 XSetForeground (display
, face
->gc
,
2083 ? (p
->overlay_p
? face
->background
2084 : f
->output_data
.mac
->cursor_pixel
)
2085 : face
->foreground
));
2087 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2088 p
->wd
, p
->h
, p
->x
, p
->y
, p
->overlay_p
);
2090 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2091 p
->wd
, p
->h
, p
->bits
+ p
->dh
, p
->overlay_p
);
2093 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2096 mac_reset_clip_rectangles (display
, face
->gc
);
2101 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2103 unsigned short *bits
;
2107 CGDataProviderRef provider
;
2109 if (which
>= max_fringe_bmp
)
2112 max_fringe_bmp
= which
+ 20;
2113 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2114 while (i
< max_fringe_bmp
)
2115 fringe_bmp
[i
++] = 0;
2118 for (i
= 0; i
< h
; i
++)
2120 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2121 sizeof (unsigned short) * h
, NULL
);
2124 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2125 sizeof (unsigned short),
2127 CGDataProviderRelease (provider
);
2132 mac_destroy_fringe_bitmap (which
)
2135 if (which
>= max_fringe_bmp
)
2138 if (fringe_bmp
[which
])
2139 CGImageRelease (fringe_bmp
[which
]);
2140 fringe_bmp
[which
] = 0;
2145 /* This is called when starting Emacs and when restarting after
2146 suspend. When starting Emacs, no window is mapped. And nothing
2147 must be done to Emacs's own window if it is suspended (though that
2151 XTset_terminal_modes ()
2155 /* This is called when exiting or suspending Emacs. Exiting will make
2156 the windows go away, and suspending requires no action. */
2159 XTreset_terminal_modes ()
2165 /***********************************************************************
2167 ***********************************************************************/
2169 /* Function prototypes of this page. */
2171 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2172 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2176 pcm_init (pcm
, count
)
2180 bzero (pcm
, sizeof (XCharStruct
) * count
);
2181 while (--count
>= 0)
2183 pcm
->descent
= PCM_INVALID
;
2188 static enum pcm_status
2189 pcm_get_status (pcm
)
2192 int height
= pcm
->ascent
+ pcm
->descent
;
2194 /* Negative height means some special status. */
2195 return height
>= 0 ? PCM_VALID
: height
;
2198 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2199 is not contained in the font. */
2201 static INLINE XCharStruct
*
2202 x_per_char_metric (font
, char2b
)
2206 /* The result metric information. */
2207 XCharStruct
*pcm
= NULL
;
2209 xassert (font
&& char2b
);
2212 if (font
->mac_style
)
2214 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2218 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2219 pcm_init (*row
, 0x100);
2221 pcm
= *row
+ char2b
->byte2
;
2222 if (pcm_get_status (pcm
) != PCM_VALID
)
2225 mac_query_char_extents (font
->mac_style
,
2226 (char2b
->byte1
<< 8) + char2b
->byte2
,
2227 NULL
, NULL
, pcm
, NULL
);
2234 if (font
->bounds
.per_char
!= NULL
)
2236 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2238 /* min_char_or_byte2 specifies the linear character index
2239 corresponding to the first element of the per_char array,
2240 max_char_or_byte2 is the index of the last character. A
2241 character with non-zero CHAR2B->byte1 is not in the font.
2242 A character with byte2 less than min_char_or_byte2 or
2243 greater max_char_or_byte2 is not in the font. */
2244 if (char2b
->byte1
== 0
2245 && char2b
->byte2
>= font
->min_char_or_byte2
2246 && char2b
->byte2
<= font
->max_char_or_byte2
)
2247 pcm
= font
->bounds
.per_char
2248 + (char2b
->byte2
- font
->min_char_or_byte2
);
2252 /* If either min_byte1 or max_byte1 are nonzero, both
2253 min_char_or_byte2 and max_char_or_byte2 are less than
2254 256, and the 2-byte character index values corresponding
2255 to the per_char array element N (counting from 0) are:
2257 byte1 = N/D + min_byte1
2258 byte2 = N\D + min_char_or_byte2
2262 D = max_char_or_byte2 - min_char_or_byte2 + 1
2263 / = integer division
2264 \ = integer modulus */
2265 if (char2b
->byte1
>= font
->min_byte1
2266 && char2b
->byte1
<= font
->max_byte1
2267 && char2b
->byte2
>= font
->min_char_or_byte2
2268 && char2b
->byte2
<= font
->max_char_or_byte2
)
2270 pcm
= (font
->bounds
.per_char
2271 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2272 * (char2b
->byte1
- font
->min_byte1
))
2273 + (char2b
->byte2
- font
->min_char_or_byte2
));
2279 /* If the per_char pointer is null, all glyphs between the first
2280 and last character indexes inclusive have the same
2281 information, as given by both min_bounds and max_bounds. */
2282 if (char2b
->byte2
>= font
->min_char_or_byte2
2283 && char2b
->byte2
<= font
->max_char_or_byte2
)
2284 pcm
= &font
->max_bounds
;
2290 return ((pcm
== NULL
2292 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2293 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2302 static XCharStruct
*
2303 mac_per_char_metric (font
, char2b
, font_type
)
2308 return x_per_char_metric (font
, char2b
);
2312 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2313 the two-byte form of C. Encoding is returned in *CHAR2B. */
2316 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2319 struct font_info
*font_info
;
2322 int charset
= CHAR_CHARSET (c
);
2323 XFontStruct
*font
= font_info
->font
;
2325 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2326 This may be either a program in a special encoder language or a
2328 if (font_info
->font_encoder
)
2330 /* It's a program. */
2331 struct ccl_program
*ccl
= font_info
->font_encoder
;
2333 check_ccl_update (ccl
);
2334 if (CHARSET_DIMENSION (charset
) == 1)
2336 ccl
->reg
[0] = charset
;
2337 ccl
->reg
[1] = char2b
->byte2
;
2342 ccl
->reg
[0] = charset
;
2343 ccl
->reg
[1] = char2b
->byte1
;
2344 ccl
->reg
[2] = char2b
->byte2
;
2347 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2349 /* We assume that MSBs are appropriately set/reset by CCL
2351 if (font
->max_byte1
== 0) /* 1-byte font */
2352 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2354 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2356 else if (font_info
->encoding
[charset
])
2358 /* Fixed encoding scheme. See fontset.h for the meaning of the
2359 encoding numbers. */
2360 int enc
= font_info
->encoding
[charset
];
2362 if ((enc
== 1 || enc
== 2)
2363 && CHARSET_DIMENSION (charset
) == 2)
2364 char2b
->byte1
|= 0x80;
2366 if (enc
== 1 || enc
== 3)
2367 char2b
->byte2
|= 0x80;
2373 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2374 char2b
->byte1
= sjis1
;
2375 char2b
->byte2
= sjis2
;
2380 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2382 return FONT_TYPE_UNKNOWN
;
2387 /***********************************************************************
2389 ***********************************************************************/
2393 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2394 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2395 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2397 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2398 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2399 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2400 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2401 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2402 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2403 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2404 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2405 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2406 unsigned long *, double, int));*/
2407 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2408 double, int, unsigned long));
2409 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2410 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2411 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2412 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2413 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2415 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2416 int, int, int, int, int, int,
2418 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2419 int, int, int, Rect
*));
2422 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2426 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2431 struct glyph_string
*s
;
2433 if (s
->font
== FRAME_FONT (s
->f
)
2434 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2435 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2437 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2440 /* Cursor on non-default face: must merge. */
2444 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2445 xgcv
.foreground
= s
->face
->background
;
2447 /* If the glyph would be invisible, try a different foreground. */
2448 if (xgcv
.foreground
== xgcv
.background
)
2449 xgcv
.foreground
= s
->face
->foreground
;
2450 if (xgcv
.foreground
== xgcv
.background
)
2451 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2452 if (xgcv
.foreground
== xgcv
.background
)
2453 xgcv
.foreground
= s
->face
->foreground
;
2455 /* Make sure the cursor is distinct from text in this face. */
2456 if (xgcv
.background
== s
->face
->background
2457 && xgcv
.foreground
== s
->face
->foreground
)
2459 xgcv
.background
= s
->face
->foreground
;
2460 xgcv
.foreground
= s
->face
->background
;
2463 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2464 xgcv
.font
= s
->font
;
2465 mask
= GCForeground
| GCBackground
| GCFont
;
2467 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2468 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2471 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2472 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2474 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2479 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2482 x_set_mouse_face_gc (s
)
2483 struct glyph_string
*s
;
2488 /* What face has to be used last for the mouse face? */
2489 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2490 face
= FACE_FROM_ID (s
->f
, face_id
);
2492 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2494 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2495 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2497 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2498 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2499 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2501 /* If font in this face is same as S->font, use it. */
2502 if (s
->font
== s
->face
->font
)
2503 s
->gc
= s
->face
->gc
;
2506 /* Otherwise construct scratch_cursor_gc with values from FACE
2511 xgcv
.background
= s
->face
->background
;
2512 xgcv
.foreground
= s
->face
->foreground
;
2513 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2514 xgcv
.font
= s
->font
;
2515 mask
= GCForeground
| GCBackground
| GCFont
;
2517 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2518 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2521 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2522 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2524 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2527 xassert (s
->gc
!= 0);
2531 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2532 Faces to use in the mode line have already been computed when the
2533 matrix was built, so there isn't much to do, here. */
2536 x_set_mode_line_face_gc (s
)
2537 struct glyph_string
*s
;
2539 s
->gc
= s
->face
->gc
;
2543 /* Set S->gc of glyph string S for drawing that glyph string. Set
2544 S->stippled_p to a non-zero value if the face of S has a stipple
2548 x_set_glyph_string_gc (s
)
2549 struct glyph_string
*s
;
2551 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2553 if (s
->hl
== DRAW_NORMAL_TEXT
)
2555 s
->gc
= s
->face
->gc
;
2556 s
->stippled_p
= s
->face
->stipple
!= 0;
2558 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2560 x_set_mode_line_face_gc (s
);
2561 s
->stippled_p
= s
->face
->stipple
!= 0;
2563 else if (s
->hl
== DRAW_CURSOR
)
2565 x_set_cursor_gc (s
);
2568 else if (s
->hl
== DRAW_MOUSE_FACE
)
2570 x_set_mouse_face_gc (s
);
2571 s
->stippled_p
= s
->face
->stipple
!= 0;
2573 else if (s
->hl
== DRAW_IMAGE_RAISED
2574 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2576 s
->gc
= s
->face
->gc
;
2577 s
->stippled_p
= s
->face
->stipple
!= 0;
2581 s
->gc
= s
->face
->gc
;
2582 s
->stippled_p
= s
->face
->stipple
!= 0;
2585 /* GC must have been set. */
2586 xassert (s
->gc
!= 0);
2590 /* Set clipping for output of glyph string S. S may be part of a mode
2591 line or menu if we don't have X toolkit support. */
2594 x_set_glyph_string_clipping (s
)
2595 struct glyph_string
*s
;
2597 Rect rects
[MAX_CLIP_RECTS
];
2600 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2601 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2606 Compute left and right overhang of glyph string S. If S is a glyph
2607 string for a composition, assume overhangs don't exist. */
2610 mac_compute_glyph_string_overhangs (s
)
2611 struct glyph_string
*s
;
2613 if (!(s
->cmp
== NULL
2614 && s
->first_glyph
->type
== CHAR_GLYPH
))
2619 || s
->font
->mac_style
2625 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2626 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2627 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2632 MacFontStruct
*font
= s
->font
;
2634 TextFont (font
->mac_fontnum
);
2635 TextSize (font
->mac_fontsize
);
2636 TextFace (font
->mac_fontface
);
2638 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2640 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2641 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2646 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2649 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2650 struct glyph_string
*s
;
2653 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2657 /* Draw the background of glyph_string S. If S->background_filled_p
2658 is non-zero don't draw it. FORCE_P non-zero means draw the
2659 background even if it wouldn't be drawn normally. This is used
2660 when a string preceding S draws into the background of S, or S
2661 contains the first component of a composition. */
2664 x_draw_glyph_string_background (s
, force_p
)
2665 struct glyph_string
*s
;
2668 /* Nothing to do if background has already been drawn or if it
2669 shouldn't be drawn in the first place. */
2670 if (!s
->background_filled_p
)
2672 int box_line_width
= max (s
->face
->box_line_width
, 0);
2674 #if 0 /* MAC_TODO: stipple */
2677 /* Fill background with a stipple pattern. */
2678 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2679 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2680 s
->y
+ box_line_width
,
2681 s
->background_width
,
2682 s
->height
- 2 * box_line_width
);
2683 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2684 s
->background_filled_p
= 1;
2688 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2689 || s
->font_not_found_p
2690 || s
->extends_to_end_of_line_p
2693 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2694 s
->background_width
,
2695 s
->height
- 2 * box_line_width
);
2696 s
->background_filled_p
= 1;
2702 /* Draw the foreground of glyph string S. */
2705 x_draw_glyph_string_foreground (s
)
2706 struct glyph_string
*s
;
2710 /* If first glyph of S has a left box line, start drawing the text
2711 of S to the right of that box line. */
2712 if (s
->face
->box
!= FACE_NO_BOX
2713 && s
->first_glyph
->left_box_line_p
)
2714 x
= s
->x
+ abs (s
->face
->box_line_width
);
2718 /* Draw characters of S as rectangles if S's font could not be
2720 if (s
->font_not_found_p
)
2722 for (i
= 0; i
< s
->nchars
; ++i
)
2724 struct glyph
*g
= s
->first_glyph
+ i
;
2725 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2726 g
->pixel_width
- 1, s
->height
- 1);
2727 x
+= g
->pixel_width
;
2732 char *char1b
= (char *) s
->char2b
;
2733 int boff
= s
->font_info
->baseline_offset
;
2735 if (s
->font_info
->vertical_centering
)
2736 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2738 /* If we can use 8-bit functions, condense S->char2b. */
2741 && GC_FONT (s
->gc
)->mac_style
== NULL
2744 for (i
= 0; i
< s
->nchars
; ++i
)
2745 char1b
[i
] = s
->char2b
[i
].byte2
;
2747 /* Draw text with XDrawString if background has already been
2748 filled. Otherwise, use XDrawImageString. (Note that
2749 XDrawImageString is usually faster than XDrawString.) Always
2750 use XDrawImageString when drawing the cursor so that there is
2751 no chance that characters under a box cursor are invisible. */
2753 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2754 bg_width
= 0; /* Corresponds to XDrawString. */
2756 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2760 || GC_FONT (s
->gc
)->mac_style
2763 #if USE_CG_TEXT_DRAWING
2765 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2766 s
->char2b
, s
->nchars
, bg_width
))
2770 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2771 s
->char2b
, s
->nchars
, bg_width
);
2773 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2774 char1b
, s
->nchars
, bg_width
);
2778 /* Draw the foreground of composite glyph string S. */
2781 x_draw_composite_glyph_string_foreground (s
)
2782 struct glyph_string
*s
;
2786 /* If first glyph of S has a left box line, start drawing the text
2787 of S to the right of that box line. */
2788 if (s
->face
->box
!= FACE_NO_BOX
2789 && s
->first_glyph
->left_box_line_p
)
2790 x
= s
->x
+ abs (s
->face
->box_line_width
);
2794 /* S is a glyph string for a composition. S->gidx is the index of
2795 the first character drawn for glyphs of this composition.
2796 S->gidx == 0 means we are drawing the very first character of
2797 this composition. */
2799 /* Draw a rectangle for the composition if the font for the very
2800 first character of the composition could not be loaded. */
2801 if (s
->font_not_found_p
)
2804 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2805 s
->width
- 1, s
->height
- 1);
2809 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2810 mac_draw_string_16 (s
->f
, s
->gc
,
2811 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2812 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2818 #ifdef USE_X_TOOLKIT
2820 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2823 /* Return the frame on which widget WIDGET is used.. Abort if frame
2824 cannot be determined. */
2826 static struct frame
*
2827 x_frame_of_widget (widget
)
2830 struct x_display_info
*dpyinfo
;
2834 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2836 /* Find the top-level shell of the widget. Note that this function
2837 can be called when the widget is not yet realized, so XtWindow
2838 (widget) == 0. That's the reason we can't simply use
2839 x_any_window_to_frame. */
2840 while (!XtIsTopLevelShell (widget
))
2841 widget
= XtParent (widget
);
2843 /* Look for a frame with that top-level widget. Allocate the color
2844 on that frame to get the right gamma correction value. */
2845 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2846 if (GC_FRAMEP (XCAR (tail
))
2847 && (f
= XFRAME (XCAR (tail
)),
2848 (f
->output_data
.nothing
!= 1
2849 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2850 && f
->output_data
.x
->widget
== widget
)
2857 /* Allocate the color COLOR->pixel on the screen and display of
2858 widget WIDGET in colormap CMAP. If an exact match cannot be
2859 allocated, try the nearest color available. Value is non-zero
2860 if successful. This is called from lwlib. */
2863 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2868 struct frame
*f
= x_frame_of_widget (widget
);
2869 return x_alloc_nearest_color (f
, cmap
, color
);
2873 #endif /* USE_X_TOOLKIT */
2875 #if 0 /* MAC_TODO */
2877 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2878 CMAP. If an exact match can't be allocated, try the nearest color
2879 available. Value is non-zero if successful. Set *COLOR to the
2883 x_alloc_nearest_color (f
, cmap
, color
)
2888 Display
*display
= FRAME_X_DISPLAY (f
);
2889 Screen
*screen
= FRAME_X_SCREEN (f
);
2892 gamma_correct (f
, color
);
2893 rc
= XAllocColor (display
, cmap
, color
);
2896 /* If we got to this point, the colormap is full, so we're going
2897 to try to get the next closest color. The algorithm used is
2898 a least-squares matching, which is what X uses for closest
2899 color matching with StaticColor visuals. */
2901 unsigned long nearest_delta
= ~0;
2902 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2903 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2905 for (i
= 0; i
< ncells
; ++i
)
2907 XQueryColors (display
, cmap
, cells
, ncells
);
2909 for (nearest
= i
= 0; i
< ncells
; ++i
)
2911 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2912 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2913 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2914 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2916 if (delta
< nearest_delta
)
2919 nearest_delta
= delta
;
2923 color
->red
= cells
[nearest
].red
;
2924 color
->green
= cells
[nearest
].green
;
2925 color
->blue
= cells
[nearest
].blue
;
2926 rc
= XAllocColor (display
, cmap
, color
);
2929 #ifdef DEBUG_X_COLORS
2931 register_color (color
->pixel
);
2932 #endif /* DEBUG_X_COLORS */
2938 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2939 It's necessary to do this instead of just using PIXEL directly to
2940 get color reference counts right. */
2943 x_copy_color (f
, pixel
)
2945 unsigned long pixel
;
2949 color
.pixel
= pixel
;
2951 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2952 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2954 #ifdef DEBUG_X_COLORS
2955 register_color (pixel
);
2961 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2962 It's necessary to do this instead of just using PIXEL directly to
2963 get color reference counts right. */
2966 x_copy_dpy_color (dpy
, cmap
, pixel
)
2969 unsigned long pixel
;
2973 color
.pixel
= pixel
;
2975 XQueryColor (dpy
, cmap
, &color
);
2976 XAllocColor (dpy
, cmap
, &color
);
2978 #ifdef DEBUG_X_COLORS
2979 register_color (pixel
);
2984 #endif /* MAC_TODO */
2987 /* Brightness beyond which a color won't have its highlight brightness
2990 Nominally, highlight colors for `3d' faces are calculated by
2991 brightening an object's color by a constant scale factor, but this
2992 doesn't yield good results for dark colors, so for colors who's
2993 brightness is less than this value (on a scale of 0-255) have to
2994 use an additional additive factor.
2996 The value here is set so that the default menu-bar/mode-line color
2997 (grey75) will not have its highlights changed at all. */
2998 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3001 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3002 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3003 If this produces the same color as COLOR, try a color where all RGB
3004 values have DELTA added. Return the allocated color in *COLOR.
3005 DISPLAY is the X display, CMAP is the colormap to operate on.
3006 Value is non-zero if successful. */
3009 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3011 unsigned long *color
;
3018 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3021 /* Change RGB values by specified FACTOR. Avoid overflow! */
3022 xassert (factor
>= 0);
3023 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3024 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3025 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3027 /* Calculate brightness of COLOR. */
3028 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3029 + BLUE_FROM_ULONG (*color
)) / 6;
3031 /* We only boost colors that are darker than
3032 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3033 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3034 /* Make an additive adjustment to NEW, because it's dark enough so
3035 that scaling by FACTOR alone isn't enough. */
3037 /* How far below the limit this color is (0 - 1, 1 being darker). */
3038 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3039 /* The additive adjustment. */
3040 int min_delta
= delta
* dimness
* factor
/ 2;
3043 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3044 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3045 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3047 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3048 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3049 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3053 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3054 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3055 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3057 /* MAC_TODO: Map to palette and retry with delta if same? */
3058 /* MAC_TODO: Free colors (if using palette)? */
3069 /* Set up the foreground color for drawing relief lines of glyph
3070 string S. RELIEF is a pointer to a struct relief containing the GC
3071 with which lines will be drawn. Use a color that is FACTOR or
3072 DELTA lighter or darker than the relief's background which is found
3073 in S->f->output_data.x->relief_background. If such a color cannot
3074 be allocated, use DEFAULT_PIXEL, instead. */
3077 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3079 struct relief
*relief
;
3082 unsigned long default_pixel
;
3085 struct mac_output
*di
= f
->output_data
.mac
;
3086 unsigned long mask
= GCForeground
;
3087 unsigned long pixel
;
3088 unsigned long background
= di
->relief_background
;
3089 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3091 /* MAC_TODO: Free colors (if using palette)? */
3093 /* Allocate new color. */
3094 xgcv
.foreground
= default_pixel
;
3096 if (dpyinfo
->n_planes
!= 1
3097 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3099 relief
->allocated_p
= 1;
3100 xgcv
.foreground
= relief
->pixel
= pixel
;
3103 if (relief
->gc
== 0)
3105 #if 0 /* MAC_TODO: stipple */
3106 xgcv
.stipple
= dpyinfo
->gray
;
3109 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3112 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3116 /* Set up colors for the relief lines around glyph string S. */
3119 x_setup_relief_colors (s
)
3120 struct glyph_string
*s
;
3122 struct mac_output
*di
= s
->f
->output_data
.mac
;
3123 unsigned long color
;
3125 if (s
->face
->use_box_color_for_shadows_p
)
3126 color
= s
->face
->box_color
;
3127 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3129 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3130 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3135 /* Get the background color of the face. */
3136 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3137 color
= xgcv
.background
;
3140 if (di
->white_relief
.gc
== 0
3141 || color
!= di
->relief_background
)
3143 di
->relief_background
= color
;
3144 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3145 WHITE_PIX_DEFAULT (s
->f
));
3146 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3147 BLACK_PIX_DEFAULT (s
->f
));
3152 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3153 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3154 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3155 relief. LEFT_P non-zero means draw a relief on the left side of
3156 the rectangle. RIGHT_P non-zero means draw a relief on the right
3157 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3161 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3162 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3164 int left_x
, top_y
, right_x
, bottom_y
, width
;
3165 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3168 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3173 gc
= f
->output_data
.mac
->white_relief
.gc
;
3175 gc
= f
->output_data
.mac
->black_relief
.gc
;
3176 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3180 for (i
= 0; i
< width
; ++i
)
3181 mac_draw_line (f
, gc
,
3182 left_x
+ i
* left_p
, top_y
+ i
,
3183 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3187 for (i
= 0; i
< width
; ++i
)
3188 mac_draw_line (f
, gc
,
3189 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3191 mac_reset_clip_rectangles (dpy
, gc
);
3193 gc
= f
->output_data
.mac
->black_relief
.gc
;
3195 gc
= f
->output_data
.mac
->white_relief
.gc
;
3196 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3200 for (i
= 0; i
< width
; ++i
)
3201 mac_draw_line (f
, gc
,
3202 left_x
+ i
* left_p
, bottom_y
- i
,
3203 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3207 for (i
= 0; i
< width
; ++i
)
3208 mac_draw_line (f
, gc
,
3209 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3211 mac_reset_clip_rectangles (dpy
, gc
);
3215 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3216 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3217 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3218 left side of the rectangle. RIGHT_P non-zero means draw a line
3219 on the right side of the rectangle. CLIP_RECT is the clipping
3220 rectangle to use when drawing. */
3223 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3224 left_p
, right_p
, clip_rect
)
3225 struct glyph_string
*s
;
3226 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3231 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3232 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3233 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3236 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3237 right_x
- left_x
+ 1, width
);
3241 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3242 width
, bottom_y
- top_y
+ 1);
3245 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3246 right_x
- left_x
+ 1, width
);
3250 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3251 top_y
, width
, bottom_y
- top_y
+ 1);
3253 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3254 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3258 /* Draw a box around glyph string S. */
3261 x_draw_glyph_string_box (s
)
3262 struct glyph_string
*s
;
3264 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3265 int left_p
, right_p
;
3266 struct glyph
*last_glyph
;
3269 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3270 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3271 : window_box_right (s
->w
, s
->area
));
3273 /* The glyph that may have a right box line. */
3274 last_glyph
= (s
->cmp
|| s
->img
3276 : s
->first_glyph
+ s
->nchars
- 1);
3278 width
= abs (s
->face
->box_line_width
);
3279 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3281 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3283 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3285 bottom_y
= top_y
+ s
->height
- 1;
3287 left_p
= (s
->first_glyph
->left_box_line_p
3288 || (s
->hl
== DRAW_MOUSE_FACE
3290 || s
->prev
->hl
!= s
->hl
)));
3291 right_p
= (last_glyph
->right_box_line_p
3292 || (s
->hl
== DRAW_MOUSE_FACE
3294 || s
->next
->hl
!= s
->hl
)));
3296 get_glyph_string_clip_rect (s
, &clip_rect
);
3298 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3299 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3300 left_p
, right_p
, &clip_rect
);
3303 x_setup_relief_colors (s
);
3304 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3305 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3310 /* Draw foreground of image glyph string S. */
3313 x_draw_image_foreground (s
)
3314 struct glyph_string
*s
;
3317 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3319 /* If first glyph of S has a left box line, start drawing it to the
3320 right of that line. */
3321 if (s
->face
->box
!= FACE_NO_BOX
3322 && s
->first_glyph
->left_box_line_p
3324 x
+= abs (s
->face
->box_line_width
);
3326 /* If there is a margin around the image, adjust x- and y-position
3328 if (s
->slice
.x
== 0)
3329 x
+= s
->img
->hmargin
;
3330 if (s
->slice
.y
== 0)
3331 y
+= s
->img
->vmargin
;
3335 x_set_glyph_string_clipping (s
);
3338 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3339 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3340 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3344 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3345 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3346 s
->slice
.width
, s
->slice
.height
, x
, y
);
3353 mac_copy_area (s
->img
->pixmap
,
3354 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3355 s
->slice
.width
, s
->slice
.height
, x
, y
);
3358 /* When the image has a mask, we can expect that at
3359 least part of a mouse highlight or a block cursor will
3360 be visible. If the image doesn't have a mask, make
3361 a block cursor visible by drawing a rectangle around
3362 the image. I believe it's looking better if we do
3363 nothing here for mouse-face. */
3364 if (s
->hl
== DRAW_CURSOR
)
3366 int r
= s
->img
->relief
;
3368 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3369 s
->slice
.width
+ r
*2 - 1,
3370 s
->slice
.height
+ r
*2 - 1);
3375 /* Draw a rectangle if image could not be loaded. */
3376 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3377 s
->slice
.width
- 1, s
->slice
.height
- 1);
3381 /* Draw a relief around the image glyph string S. */
3384 x_draw_image_relief (s
)
3385 struct glyph_string
*s
;
3387 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3390 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3392 /* If first glyph of S has a left box line, start drawing it to the
3393 right of that line. */
3394 if (s
->face
->box
!= FACE_NO_BOX
3395 && s
->first_glyph
->left_box_line_p
3397 x
+= abs (s
->face
->box_line_width
);
3399 /* If there is a margin around the image, adjust x- and y-position
3401 if (s
->slice
.x
== 0)
3402 x
+= s
->img
->hmargin
;
3403 if (s
->slice
.y
== 0)
3404 y
+= s
->img
->vmargin
;
3406 if (s
->hl
== DRAW_IMAGE_SUNKEN
3407 || s
->hl
== DRAW_IMAGE_RAISED
)
3409 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3410 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3414 thick
= abs (s
->img
->relief
);
3415 raised_p
= s
->img
->relief
> 0;
3420 x1
= x
+ s
->slice
.width
+ thick
- 1;
3421 y1
= y
+ s
->slice
.height
+ thick
- 1;
3423 x_setup_relief_colors (s
);
3424 get_glyph_string_clip_rect (s
, &r
);
3425 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3427 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3429 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3434 /* Draw part of the background of glyph string S. X, Y, W, and H
3435 give the rectangle to draw. */
3438 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3439 struct glyph_string
*s
;
3442 #if 0 /* MAC_TODO: stipple */
3445 /* Fill background with a stipple pattern. */
3446 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3447 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3448 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3451 #endif /* MAC_TODO */
3452 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3456 /* Draw image glyph string S.
3459 s->x +-------------------------
3462 | +-------------------------
3465 | | +-------------------
3471 x_draw_image_glyph_string (s
)
3472 struct glyph_string
*s
;
3475 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3476 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3479 height
= s
->height
- 2 * box_line_vwidth
;
3482 /* Fill background with face under the image. Do it only if row is
3483 taller than image or if image has a clip mask to reduce
3485 s
->stippled_p
= s
->face
->stipple
!= 0;
3486 if (height
> s
->slice
.height
3490 || s
->img
->pixmap
== 0
3491 || s
->width
!= s
->background_width
)
3494 if (s
->first_glyph
->left_box_line_p
3496 x
+= box_line_hwidth
;
3499 if (s
->slice
.y
== 0)
3500 y
+= box_line_vwidth
;
3502 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3504 s
->background_filled_p
= 1;
3507 /* Draw the foreground. */
3508 x_draw_image_foreground (s
);
3510 /* If we must draw a relief around the image, do it. */
3512 || s
->hl
== DRAW_IMAGE_RAISED
3513 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3514 x_draw_image_relief (s
);
3518 /* Draw stretch glyph string S. */
3521 x_draw_stretch_glyph_string (s
)
3522 struct glyph_string
*s
;
3524 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3525 s
->stippled_p
= s
->face
->stipple
!= 0;
3527 if (s
->hl
== DRAW_CURSOR
3528 && !x_stretch_cursor_p
)
3530 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3531 as wide as the stretch glyph. */
3532 int width
, background_width
= s
->background_width
;
3533 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3537 background_width
-= left_x
- x
;
3540 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3543 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3545 /* Clear rest using the GC of the original non-cursor face. */
3546 if (width
< background_width
)
3549 int w
= background_width
- width
, h
= s
->height
;
3554 if (s
->row
->mouse_face_p
3555 && cursor_in_mouse_face_p (s
->w
))
3557 x_set_mouse_face_gc (s
);
3563 get_glyph_string_clip_rect (s
, &r
);
3564 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3566 #if 0 /* MAC_TODO: stipple */
3567 if (s
->face
->stipple
)
3569 /* Fill background with a stipple pattern. */
3570 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3571 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3572 XSetFillStyle (s
->display
, gc
, FillSolid
);
3575 #endif /* MAC_TODO */
3576 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3579 else if (!s
->background_filled_p
)
3581 int background_width
= s
->background_width
;
3582 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3586 background_width
-= left_x
- x
;
3589 if (background_width
> 0)
3590 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3593 s
->background_filled_p
= 1;
3597 /* Draw glyph string S. */
3600 x_draw_glyph_string (s
)
3601 struct glyph_string
*s
;
3603 int relief_drawn_p
= 0;
3605 /* If S draws into the background of its successor that does not
3606 draw a cursor, draw the background of the successor first so that
3607 S can draw into it. This makes S->next use XDrawString instead
3608 of XDrawImageString. */
3609 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3610 && s
->next
->hl
!= DRAW_CURSOR
)
3612 xassert (s
->next
->img
== NULL
);
3613 x_set_glyph_string_gc (s
->next
);
3614 x_set_glyph_string_clipping (s
->next
);
3615 x_draw_glyph_string_background (s
->next
, 1);
3618 /* Set up S->gc, set clipping and draw S. */
3619 x_set_glyph_string_gc (s
);
3621 /* Draw relief (if any) in advance for char/composition so that the
3622 glyph string can be drawn over it. */
3623 if (!s
->for_overlaps
3624 && s
->face
->box
!= FACE_NO_BOX
3625 && (s
->first_glyph
->type
== CHAR_GLYPH
3626 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3629 x_set_glyph_string_clipping (s
);
3630 x_draw_glyph_string_background (s
, 1);
3631 x_draw_glyph_string_box (s
);
3632 x_set_glyph_string_clipping (s
);
3636 x_set_glyph_string_clipping (s
);
3638 switch (s
->first_glyph
->type
)
3641 x_draw_image_glyph_string (s
);
3645 x_draw_stretch_glyph_string (s
);
3649 if (s
->for_overlaps
)
3650 s
->background_filled_p
= 1;
3652 x_draw_glyph_string_background (s
, 0);
3653 x_draw_glyph_string_foreground (s
);
3656 case COMPOSITE_GLYPH
:
3657 if (s
->for_overlaps
|| s
->gidx
> 0)
3658 s
->background_filled_p
= 1;
3660 x_draw_glyph_string_background (s
, 1);
3661 x_draw_composite_glyph_string_foreground (s
);
3668 if (!s
->for_overlaps
)
3670 /* Draw underline. */
3671 if (s
->face
->underline_p
)
3673 unsigned long h
= 1;
3674 unsigned long dy
= s
->height
- h
;
3676 if (s
->face
->underline_defaulted_p
)
3677 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3682 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3683 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3684 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3686 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3690 /* Draw overline. */
3691 if (s
->face
->overline_p
)
3693 unsigned long dy
= 0, h
= 1;
3695 if (s
->face
->overline_color_defaulted_p
)
3696 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3701 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3702 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3703 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3705 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3709 /* Draw strike-through. */
3710 if (s
->face
->strike_through_p
)
3712 unsigned long h
= 1;
3713 unsigned long dy
= (s
->height
- h
) / 2;
3715 if (s
->face
->strike_through_color_defaulted_p
)
3716 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3721 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3722 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3723 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3725 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3729 /* Draw relief if not yet drawn. */
3730 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3731 x_draw_glyph_string_box (s
);
3734 /* Reset clipping. */
3735 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3738 /* Shift display to make room for inserted glyphs. */
3741 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3743 int x
, y
, width
, height
, shift_by
;
3745 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3746 x
, y
, width
, height
,
3750 /* Delete N glyphs at the nominal cursor position. Not implemented
3761 /* Clear entire frame. If updating_frame is non-null, clear that
3762 frame. Otherwise clear the selected frame. */
3772 f
= SELECTED_FRAME ();
3774 /* Clearing the frame will erase any cursor, so mark them all as no
3776 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3777 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3778 output_cursor
.x
= -1;
3780 /* We don't set the output cursor here because there will always
3781 follow an explicit cursor_to. */
3783 mac_clear_window (f
);
3785 /* We have to clear the scroll bars, too. If we have changed
3786 colors or something like that, then they should be notified. */
3787 x_scroll_bar_clear (f
);
3789 XFlush (FRAME_MAC_DISPLAY (f
));
3795 /* Invert the middle quarter of the frame for .15 sec. */
3797 /* We use the select system call to do the waiting, so we have to make
3798 sure it's available. If it isn't, we just won't do visual bells. */
3800 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3803 /* Subtract the `struct timeval' values X and Y, storing the result in
3804 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3807 timeval_subtract (result
, x
, y
)
3808 struct timeval
*result
, x
, y
;
3810 /* Perform the carry for the later subtraction by updating y. This
3811 is safer because on some systems the tv_sec member is unsigned. */
3812 if (x
.tv_usec
< y
.tv_usec
)
3814 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3815 y
.tv_usec
-= 1000000 * nsec
;
3819 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3821 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3822 y
.tv_usec
+= 1000000 * nsec
;
3826 /* Compute the time remaining to wait. tv_usec is certainly
3828 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3829 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3831 /* Return indication of whether the result should be considered
3833 return x
.tv_sec
< y
.tv_sec
;
3840 /* Get the height not including a menu bar widget. */
3841 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3842 /* Height of each line to flash. */
3843 int flash_height
= FRAME_LINE_HEIGHT (f
);
3844 /* These will be the left and right margins of the rectangles. */
3845 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3846 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3850 /* Don't flash the area between a scroll bar and the frame
3851 edge it is next to. */
3852 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3854 case vertical_scroll_bar_left
:
3855 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3858 case vertical_scroll_bar_right
:
3859 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3866 width
= flash_right
- flash_left
;
3870 /* If window is tall, flash top and bottom line. */
3871 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3873 mac_invert_rectangle (f
, flash_left
,
3874 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3875 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3876 width
, flash_height
);
3877 mac_invert_rectangle (f
, flash_left
,
3878 (height
- flash_height
3879 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3880 width
, flash_height
);
3883 /* If it is short, flash it all. */
3884 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3885 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3890 struct timeval wakeup
;
3892 EMACS_GET_TIME (wakeup
);
3894 /* Compute time to wait until, propagating carry from usecs. */
3895 wakeup
.tv_usec
+= 150000;
3896 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3897 wakeup
.tv_usec
%= 1000000;
3899 /* Keep waiting until past the time wakeup or any input gets
3901 while (! detect_input_pending ())
3903 struct timeval current
;
3904 struct timeval timeout
;
3906 EMACS_GET_TIME (current
);
3908 /* Break if result would be negative. */
3909 if (timeval_subtract (¤t
, wakeup
, current
))
3912 /* How long `select' should wait. */
3914 timeout
.tv_usec
= 10000;
3916 /* Try to wait that long--but we might wake up sooner. */
3917 select (0, NULL
, NULL
, NULL
, &timeout
);
3921 /* If window is tall, flash top and bottom line. */
3922 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3924 mac_invert_rectangle (f
, flash_left
,
3925 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3926 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3927 width
, flash_height
);
3928 mac_invert_rectangle (f
, flash_left
,
3929 (height
- flash_height
3930 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3931 width
, flash_height
);
3934 /* If it is short, flash it all. */
3935 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3936 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3943 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3946 /* Make audible bell. */
3951 struct frame
*f
= SELECTED_FRAME ();
3953 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3961 XFlush (FRAME_MAC_DISPLAY (f
));
3967 /* Specify how many text lines, from the top of the window,
3968 should be affected by insert-lines and delete-lines operations.
3969 This, and those operations, are used only within an update
3970 that is bounded by calls to x_update_begin and x_update_end. */
3973 XTset_terminal_window (n
)
3976 /* This function intentionally left blank. */
3981 /***********************************************************************
3983 ***********************************************************************/
3985 /* Perform an insert-lines or delete-lines operation, inserting N
3986 lines or deleting -N lines at vertical position VPOS. */
3989 x_ins_del_lines (vpos
, n
)
3996 /* Scroll part of the display as described by RUN. */
3999 x_scroll_run (w
, run
)
4003 struct frame
*f
= XFRAME (w
->frame
);
4004 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4006 /* Get frame-relative bounding box of the text display area of W,
4007 without mode lines. Include in this box the left and right
4009 window_box (w
, -1, &x
, &y
, &width
, &height
);
4011 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4012 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4013 bottom_y
= y
+ height
;
4017 /* Scrolling up. Make sure we don't copy part of the mode
4018 line at the bottom. */
4019 if (from_y
+ run
->height
> bottom_y
)
4020 height
= bottom_y
- from_y
;
4022 height
= run
->height
;
4026 /* Scolling down. Make sure we don't copy over the mode line.
4028 if (to_y
+ run
->height
> bottom_y
)
4029 height
= bottom_y
- to_y
;
4031 height
= run
->height
;
4036 /* Cursor off. Will be switched on again in x_update_window_end. */
4040 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4050 /***********************************************************************
4052 ***********************************************************************/
4060 ControlRef root_control
;
4063 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4065 ActivateControl (root_control
);
4067 x_update_cursor (f
, 1);
4071 frame_unhighlight (f
)
4075 ControlRef root_control
;
4078 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4080 DeactivateControl (root_control
);
4082 x_update_cursor (f
, 1);
4085 /* The focus has changed. Update the frames as necessary to reflect
4086 the new situation. Note that we can't change the selected frame
4087 here, because the Lisp code we are interrupting might become confused.
4088 Each event gets marked with the frame in which it occurred, so the
4089 Lisp code can tell when the switch took place by examining the events. */
4092 x_new_focus_frame (dpyinfo
, frame
)
4093 struct x_display_info
*dpyinfo
;
4094 struct frame
*frame
;
4096 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4098 if (frame
!= dpyinfo
->x_focus_frame
)
4100 /* Set this before calling other routines, so that they see
4101 the correct value of x_focus_frame. */
4102 dpyinfo
->x_focus_frame
= frame
;
4104 if (old_focus
&& old_focus
->auto_lower
)
4105 x_lower_frame (old_focus
);
4108 selected_frame
= frame
;
4109 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4111 Fselect_window (selected_frame
->selected_window
, Qnil
);
4112 choose_minibuf_frame ();
4115 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4116 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4118 pending_autoraise_frame
= 0;
4120 #if USE_MAC_FONT_PANEL
4122 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4126 x_frame_rehighlight (dpyinfo
);
4129 /* Handle FocusIn and FocusOut state changes for FRAME.
4130 If FRAME has focus and there exists more than one frame, puts
4131 a FOCUS_IN_EVENT into *BUFP. */
4134 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4136 struct mac_display_info
*dpyinfo
;
4137 struct frame
*frame
;
4138 struct input_event
*bufp
;
4140 if (type
== activeFlag
)
4142 if (dpyinfo
->x_focus_event_frame
!= frame
)
4144 x_new_focus_frame (dpyinfo
, frame
);
4145 dpyinfo
->x_focus_event_frame
= frame
;
4147 /* Don't stop displaying the initial startup message
4148 for a switch-frame event we don't need. */
4149 if (GC_NILP (Vterminal_frame
)
4150 && GC_CONSP (Vframe_list
)
4151 && !GC_NILP (XCDR (Vframe_list
)))
4153 bufp
->kind
= FOCUS_IN_EVENT
;
4154 XSETFRAME (bufp
->frame_or_window
, frame
);
4160 if (dpyinfo
->x_focus_event_frame
== frame
)
4162 dpyinfo
->x_focus_event_frame
= 0;
4163 x_new_focus_frame (dpyinfo
, 0);
4168 /* The focus may have changed. Figure out if it is a real focus change,
4169 by checking both FocusIn/Out and Enter/LeaveNotify events.
4171 Returns FOCUS_IN_EVENT event in *BUFP. */
4174 x_detect_focus_change (dpyinfo
, event
, bufp
)
4175 struct mac_display_info
*dpyinfo
;
4177 struct input_event
*bufp
;
4179 struct frame
*frame
;
4181 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4185 /* On Mac, this is only called from focus events, so no switch needed. */
4186 mac_focus_changed ((event
->modifiers
& activeFlag
),
4187 dpyinfo
, frame
, bufp
);
4191 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4194 x_mouse_leave (dpyinfo
)
4195 struct x_display_info
*dpyinfo
;
4197 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4200 /* The focus has changed, or we have redirected a frame's focus to
4201 another frame (this happens when a frame uses a surrogate
4202 mini-buffer frame). Shift the highlight as appropriate.
4204 The FRAME argument doesn't necessarily have anything to do with which
4205 frame is being highlighted or un-highlighted; we only use it to find
4206 the appropriate X display info. */
4209 XTframe_rehighlight (frame
)
4210 struct frame
*frame
;
4212 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4216 x_frame_rehighlight (dpyinfo
)
4217 struct x_display_info
*dpyinfo
;
4219 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4221 if (dpyinfo
->x_focus_frame
)
4223 dpyinfo
->x_highlight_frame
4224 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4225 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4226 : dpyinfo
->x_focus_frame
);
4227 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4229 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4230 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4234 dpyinfo
->x_highlight_frame
= 0;
4236 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4239 frame_unhighlight (old_highlight
);
4240 if (dpyinfo
->x_highlight_frame
)
4241 frame_highlight (dpyinfo
->x_highlight_frame
);
4247 /* Convert a keysym to its name. */
4250 x_get_keysym_name (keysym
)
4257 value
= XKeysymToString (keysym
);
4268 /* Function to report a mouse movement to the mainstream Emacs code.
4269 The input handler calls this.
4271 We have received a mouse movement event, which is given in *event.
4272 If the mouse is over a different glyph than it was last time, tell
4273 the mainstream emacs code by setting mouse_moved. If not, ask for
4274 another motion event, so we can check again the next time it moves. */
4276 static Point last_mouse_motion_position
;
4277 static Lisp_Object last_mouse_motion_frame
;
4280 note_mouse_movement (frame
, pos
)
4284 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4285 #if TARGET_API_MAC_CARBON
4289 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4290 last_mouse_motion_position
= *pos
;
4291 XSETFRAME (last_mouse_motion_frame
, frame
);
4293 #if TARGET_API_MAC_CARBON
4294 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4296 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4299 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4300 /* This case corresponds to LeaveNotify in X11. */
4302 /* If we move outside the frame, then we're certainly no
4303 longer on any text in the frame. */
4304 clear_mouse_face (dpyinfo
);
4305 dpyinfo
->mouse_face_mouse_frame
= 0;
4306 if (!dpyinfo
->grabbed
)
4307 rif
->define_frame_cursor (frame
,
4308 frame
->output_data
.mac
->nontext_cursor
);
4312 /* Has the mouse moved off the glyph it was on at the last sighting? */
4313 if (frame
!= last_mouse_glyph_frame
4314 || !PtInRect (*pos
, &last_mouse_glyph
))
4316 frame
->mouse_moved
= 1;
4317 last_mouse_scroll_bar
= Qnil
;
4318 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4319 /* Remember which glyph we're now on. */
4320 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4321 last_mouse_glyph_frame
= frame
;
4329 /************************************************************************
4331 ************************************************************************/
4333 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4336 redo_mouse_highlight ()
4338 if (!NILP (last_mouse_motion_frame
)
4339 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4340 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4341 last_mouse_motion_position
.h
,
4342 last_mouse_motion_position
.v
);
4346 static struct frame
*
4347 mac_focus_frame (dpyinfo
)
4348 struct mac_display_info
*dpyinfo
;
4350 if (dpyinfo
->x_focus_frame
)
4351 return dpyinfo
->x_focus_frame
;
4353 /* Mac version may get events, such as a menu bar click, even when
4354 all the frames are invisible. In this case, we regard the
4355 event came to the selected frame. */
4356 return SELECTED_FRAME ();
4360 /* Return the current position of the mouse.
4361 *FP should be a frame which indicates which display to ask about.
4363 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4364 and *PART to the frame, window, and scroll bar part that the mouse
4365 is over. Set *X and *Y to the portion and whole of the mouse's
4366 position on the scroll bar.
4368 If the mouse movement started elsewhere, set *FP to the frame the
4369 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4372 Set *TIME to the server time-stamp for the time at which the mouse
4373 was at this position.
4375 Don't store anything if we don't have a valid set of values to report.
4377 This clears the mouse_moved flag, so we can wait for the next mouse
4381 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4384 Lisp_Object
*bar_window
;
4385 enum scroll_bar_part
*part
;
4387 unsigned long *time
;
4393 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4394 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4397 Lisp_Object frame
, tail
;
4399 /* Clear the mouse-moved flag for every frame on this display. */
4400 FOR_EACH_FRAME (tail
, frame
)
4401 XFRAME (frame
)->mouse_moved
= 0;
4403 last_mouse_scroll_bar
= Qnil
;
4405 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4406 && FRAME_LIVE_P (last_mouse_frame
))
4407 f1
= last_mouse_frame
;
4409 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4413 /* Ok, we found a frame. Store all the values.
4414 last_mouse_glyph is a rectangle used to reduce the
4415 generation of mouse events. To not miss any motion
4416 events, we must divide the frame into rectangles of the
4417 size of the smallest character that could be displayed
4418 on it, i.e. into the same rectangles that matrices on
4419 the frame are divided into. */
4422 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4423 GetMouse (&mouse_pos
);
4424 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4426 last_mouse_glyph_frame
= f1
;
4431 XSETINT (*x
, mouse_pos
.h
);
4432 XSETINT (*y
, mouse_pos
.v
);
4433 *time
= last_mouse_movement_time
;
4441 /************************************************************************
4443 ************************************************************************/
4445 #ifdef USE_TOOLKIT_SCROLL_BARS
4447 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4448 static OSStatus install_scroll_bar_timer
P_ ((void));
4449 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4450 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4451 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4452 struct input_event
*));
4453 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4455 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4457 struct input_event
*));
4458 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4459 struct input_event
*));
4460 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4461 Point
, struct input_event
*));
4462 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4465 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4467 static int last_scroll_bar_part
;
4469 static EventLoopTimerRef scroll_bar_timer
;
4471 static int scroll_bar_timer_event_posted_p
;
4473 #define SCROLL_BAR_FIRST_DELAY 0.5
4474 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4477 scroll_bar_timer_callback (timer
, data
)
4478 EventLoopTimerRef timer
;
4483 err
= mac_post_mouse_moved_event ();
4485 scroll_bar_timer_event_posted_p
= 1;
4489 install_scroll_bar_timer ()
4491 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4493 if (scroll_bar_timer_callbackUPP
== NULL
)
4494 scroll_bar_timer_callbackUPP
=
4495 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4497 if (scroll_bar_timer
== NULL
)
4498 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4499 kEventDurationForever as delays. */
4501 InstallEventLoopTimer (GetCurrentEventLoop (),
4502 kEventDurationForever
, kEventDurationForever
,
4503 scroll_bar_timer_callbackUPP
, NULL
,
4508 set_scroll_bar_timer (delay
)
4509 EventTimerInterval delay
;
4511 if (scroll_bar_timer
== NULL
)
4512 install_scroll_bar_timer ();
4514 scroll_bar_timer_event_posted_p
= 0;
4516 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4520 control_part_code_to_scroll_bar_part (part_code
)
4521 ControlPartCode part_code
;
4525 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4526 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4527 case kControlPageUpPart
: return scroll_bar_above_handle
;
4528 case kControlPageDownPart
: return scroll_bar_below_handle
;
4529 case kControlIndicatorPart
: return scroll_bar_handle
;
4536 construct_scroll_bar_click (bar
, part
, bufp
)
4537 struct scroll_bar
*bar
;
4539 struct input_event
*bufp
;
4541 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4542 bufp
->frame_or_window
= bar
->window
;
4546 XSETINT (bufp
->x
, 0);
4547 XSETINT (bufp
->y
, 0);
4548 bufp
->modifiers
= 0;
4552 get_control_part_bounds (ch
, part_code
, rect
)
4554 ControlPartCode part_code
;
4557 RgnHandle region
= NewRgn ();
4560 err
= GetControlRegion (ch
, part_code
, region
);
4562 GetRegionBounds (region
, rect
);
4563 DisposeRgn (region
);
4569 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4570 struct scroll_bar
*bar
;
4571 ControlPartCode part_code
;
4572 struct input_event
*bufp
;
4574 int part
= control_part_code_to_scroll_bar_part (part_code
);
4579 if (part
!= scroll_bar_handle
)
4581 construct_scroll_bar_click (bar
, part
, bufp
);
4582 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4583 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4586 last_scroll_bar_part
= part
;
4587 bar
->dragging
= Qnil
;
4588 tracked_scroll_bar
= bar
;
4592 x_scroll_bar_handle_release (bar
, bufp
)
4593 struct scroll_bar
*bar
;
4594 struct input_event
*bufp
;
4596 if (last_scroll_bar_part
!= scroll_bar_handle
4597 || !GC_NILP (bar
->dragging
))
4598 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4600 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4601 set_scroll_bar_timer (kEventDurationForever
);
4603 last_scroll_bar_part
= -1;
4604 bar
->dragging
= Qnil
;
4605 tracked_scroll_bar
= NULL
;
4609 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4611 struct scroll_bar
*bar
;
4613 struct input_event
*bufp
;
4615 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4617 if (last_scroll_bar_part
== scroll_bar_handle
)
4622 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4623 kControlIndicatorPart
, &r
);
4625 if (GC_NILP (bar
->dragging
))
4626 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4628 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4629 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4630 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4635 if (top
> top_range
)
4638 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4639 XSETINT (bufp
->x
, top
);
4640 XSETINT (bufp
->y
, top_range
);
4644 ControlPartCode part_code
;
4645 int unhilite_p
= 0, part
;
4647 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4651 part
= control_part_code_to_scroll_bar_part (part_code
);
4653 switch (last_scroll_bar_part
)
4655 case scroll_bar_above_handle
:
4656 case scroll_bar_below_handle
:
4657 if (part
!= scroll_bar_above_handle
4658 && part
!= scroll_bar_below_handle
)
4662 case scroll_bar_up_arrow
:
4663 case scroll_bar_down_arrow
:
4664 if (part
!= scroll_bar_up_arrow
4665 && part
!= scroll_bar_down_arrow
)
4672 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4673 else if (part
!= last_scroll_bar_part
4674 || scroll_bar_timer_event_posted_p
)
4676 construct_scroll_bar_click (bar
, part
, bufp
);
4677 last_scroll_bar_part
= part
;
4678 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4679 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4684 /* Set the thumb size and position of scroll bar BAR. We are currently
4685 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4688 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4689 struct scroll_bar
*bar
;
4690 int portion
, position
, whole
;
4692 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4693 int value
, viewsize
, maximum
;
4695 if (XINT (bar
->track_height
) == 0)
4699 value
= 0, viewsize
= 1, maximum
= 0;
4704 maximum
= max (0, whole
- portion
);
4709 if (GetControlViewSize (ch
) != viewsize
4710 || GetControl32BitValue (ch
) != value
4711 || GetControl32BitMaximum (ch
) != maximum
)
4713 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4714 SetControlVisibility (ch
, false, false);
4716 SetControl32BitMaximum (ch
, maximum
);
4717 SetControl32BitValue (ch
, value
);
4718 SetControlViewSize (ch
, viewsize
);
4720 SetControlVisibility (ch
, true, true);
4726 #endif /* USE_TOOLKIT_SCROLL_BARS */
4730 /************************************************************************
4731 Scroll bars, general
4732 ************************************************************************/
4734 /* Create a scroll bar and return the scroll bar vector for it. W is
4735 the Emacs window on which to create the scroll bar. TOP, LEFT,
4736 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4739 static struct scroll_bar
*
4740 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4742 int top
, left
, width
, height
, disp_top
, disp_height
;
4744 struct frame
*f
= XFRAME (w
->frame
);
4745 struct scroll_bar
*bar
4746 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4754 r
.right
= left
+ width
;
4755 r
.bottom
= disp_top
+ disp_height
;
4758 mac_prepare_for_quickdraw (f
);
4760 #if TARGET_API_MAC_CARBON
4761 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4762 #if USE_TOOLKIT_SCROLL_BARS
4765 width
< disp_height
,
4767 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4769 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4770 0, 0, 0, scrollBarProc
, (long) bar
);
4772 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4774 XSETWINDOW (bar
->window
, w
);
4775 XSETINT (bar
->top
, top
);
4776 XSETINT (bar
->left
, left
);
4777 XSETINT (bar
->width
, width
);
4778 XSETINT (bar
->height
, height
);
4779 XSETINT (bar
->start
, 0);
4780 XSETINT (bar
->end
, 0);
4781 bar
->dragging
= Qnil
;
4782 #ifdef USE_TOOLKIT_SCROLL_BARS
4783 bar
->track_top
= Qnil
;
4784 bar
->track_height
= Qnil
;
4787 /* Add bar to its frame's list of scroll bars. */
4788 bar
->next
= FRAME_SCROLL_BARS (f
);
4790 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4791 if (!NILP (bar
->next
))
4792 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4799 /* Draw BAR's handle in the proper position.
4801 If the handle is already drawn from START to END, don't bother
4802 redrawing it, unless REBUILD is non-zero; in that case, always
4803 redraw it. (REBUILD is handy for drawing the handle after expose
4806 Normally, we want to constrain the start and end of the handle to
4807 fit inside its rectangle, but if the user is dragging the scroll
4808 bar handle, we want to let them drag it down all the way, so that
4809 the bar's top is as far down as it goes; otherwise, there's no way
4810 to move to the very end of the buffer. */
4812 #ifndef USE_TOOLKIT_SCROLL_BARS
4815 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4816 struct scroll_bar
*bar
;
4820 int dragging
= ! NILP (bar
->dragging
);
4821 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4822 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4823 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4824 int length
= end
- start
;
4826 /* If the display is already accurate, do nothing. */
4828 && start
== XINT (bar
->start
)
4829 && end
== XINT (bar
->end
))
4834 /* Make sure the values are reasonable, and try to preserve the
4835 distance between start and end. */
4838 else if (start
> top_range
)
4840 end
= start
+ length
;
4844 else if (end
> top_range
&& ! dragging
)
4847 /* Store the adjusted setting in the scroll bar. */
4848 XSETINT (bar
->start
, start
);
4849 XSETINT (bar
->end
, end
);
4851 /* Clip the end position, just for display. */
4852 if (end
> top_range
)
4855 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4856 top positions, to make sure the handle is always at least that
4857 many pixels tall. */
4858 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4860 SetControlMinimum (ch
, 0);
4861 /* Don't inadvertently activate deactivated scroll bars */
4862 if (GetControlMaximum (ch
) != -1)
4863 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4865 SetControlValue (ch
, start
);
4866 #if TARGET_API_MAC_CARBON
4867 SetControlViewSize (ch
, end
- start
);
4873 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4875 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4879 x_scroll_bar_remove (bar
)
4880 struct scroll_bar
*bar
;
4882 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4887 mac_prepare_for_quickdraw (f
);
4889 /* Destroy the Mac scroll bar control */
4890 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4892 /* Disassociate this scroll bar from its window. */
4893 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4899 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4900 that we are displaying PORTION characters out of a total of WHOLE
4901 characters, starting at POSITION. If WINDOW has no scroll bar,
4905 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4907 int portion
, whole
, position
;
4909 struct frame
*f
= XFRAME (w
->frame
);
4910 struct scroll_bar
*bar
;
4911 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4912 int window_y
, window_height
;
4914 /* Get window dimensions. */
4915 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4917 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4918 height
= window_height
;
4920 /* Compute the left edge of the scroll bar area. */
4921 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4923 /* Compute the width of the scroll bar which might be less than
4924 the width of the area reserved for the scroll bar. */
4925 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4926 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4930 /* Compute the left edge of the scroll bar. */
4931 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4934 sb_left
= left
+ width
- sb_width
;
4936 /* Adjustments according to Inside Macintosh to make it look nice */
4938 disp_height
= height
;
4945 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4951 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4955 /* Does the scroll bar exist yet? */
4956 if (NILP (w
->vertical_scroll_bar
))
4959 mac_clear_area (f
, left
, top
, width
, height
);
4961 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4963 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4967 /* It may just need to be moved and resized. */
4970 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4971 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4975 /* If already correctly positioned, do nothing. */
4976 if (!(XINT (bar
->left
) == sb_left
4977 && XINT (bar
->top
) == top
4978 && XINT (bar
->width
) == sb_width
4979 && XINT (bar
->height
) == height
))
4981 /* Since toolkit scroll bars are smaller than the space reserved
4982 for them on the frame, we have to clear "under" them. */
4983 mac_clear_area (f
, left
, top
, width
, height
);
4986 mac_prepare_for_quickdraw (f
);
4989 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4990 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4992 #ifndef USE_TOOLKIT_SCROLL_BARS
4993 if (sb_width
< disp_height
)
4997 /* Remember new settings. */
4998 XSETINT (bar
->left
, sb_left
);
4999 XSETINT (bar
->top
, top
);
5000 XSETINT (bar
->width
, sb_width
);
5001 XSETINT (bar
->height
, height
);
5002 #ifdef USE_TOOLKIT_SCROLL_BARS
5003 bar
->track_top
= Qnil
;
5004 bar
->track_height
= Qnil
;
5011 #ifdef USE_TOOLKIT_SCROLL_BARS
5012 if (NILP (bar
->track_top
))
5014 if (sb_width
>= disp_height
)
5016 XSETINT (bar
->track_top
, 0);
5017 XSETINT (bar
->track_height
, 0);
5021 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5026 SetControl32BitMinimum (ch
, 0);
5027 SetControl32BitMaximum (ch
, 1);
5028 SetControlViewSize (ch
, 1);
5030 /* Move the scroll bar thumb to the top. */
5031 SetControl32BitValue (ch
, 0);
5032 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5034 /* Move the scroll bar thumb to the bottom. */
5035 SetControl32BitValue (ch
, 1);
5036 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5038 UnionRect (&r0
, &r1
, &r0
);
5039 XSETINT (bar
->track_top
, r0
.top
);
5040 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5042 /* Don't show the scroll bar if its height is not enough to
5043 display the scroll bar thumb. */
5044 if (r0
.bottom
- r0
.top
> 0)
5051 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5052 #else /* not USE_TOOLKIT_SCROLL_BARS */
5053 /* Set the scroll bar's current state, unless we're currently being
5055 if (NILP (bar
->dragging
))
5057 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5060 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5063 int start
= ((double) position
* top_range
) / whole
;
5064 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5065 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5068 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5072 /* The following three hooks are used when we're doing a thorough
5073 redisplay of the frame. We don't explicitly know which scroll bars
5074 are going to be deleted, because keeping track of when windows go
5075 away is a real pain - "Can you say set-window-configuration, boys
5076 and girls?" Instead, we just assert at the beginning of redisplay
5077 that *all* scroll bars are to be removed, and then save a scroll bar
5078 from the fiery pit when we actually redisplay its window. */
5080 /* Arrange for all scroll bars on FRAME to be removed at the next call
5081 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5082 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5085 XTcondemn_scroll_bars (frame
)
5088 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5089 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5092 bar
= FRAME_SCROLL_BARS (frame
);
5093 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5094 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5095 XSCROLL_BAR (bar
)->prev
= Qnil
;
5096 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5097 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5098 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5103 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5104 Note that WINDOW isn't necessarily condemned at all. */
5107 XTredeem_scroll_bar (window
)
5108 struct window
*window
;
5110 struct scroll_bar
*bar
;
5113 /* We can't redeem this window's scroll bar if it doesn't have one. */
5114 if (NILP (window
->vertical_scroll_bar
))
5117 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5119 /* Unlink it from the condemned list. */
5120 f
= XFRAME (WINDOW_FRAME (window
));
5121 if (NILP (bar
->prev
))
5123 /* If the prev pointer is nil, it must be the first in one of
5125 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5126 /* It's not condemned. Everything's fine. */
5128 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5129 window
->vertical_scroll_bar
))
5130 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5132 /* If its prev pointer is nil, it must be at the front of
5133 one or the other! */
5137 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5139 if (! NILP (bar
->next
))
5140 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5142 bar
->next
= FRAME_SCROLL_BARS (f
);
5144 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5145 if (! NILP (bar
->next
))
5146 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5149 /* Remove all scroll bars on FRAME that haven't been saved since the
5150 last call to `*condemn_scroll_bars_hook'. */
5153 XTjudge_scroll_bars (f
)
5156 Lisp_Object bar
, next
;
5158 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5160 /* Clear out the condemned list now so we won't try to process any
5161 more events on the hapless scroll bars. */
5162 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5164 for (; ! NILP (bar
); bar
= next
)
5166 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5168 x_scroll_bar_remove (b
);
5171 b
->next
= b
->prev
= Qnil
;
5174 /* Now there should be no references to the condemned scroll bars,
5175 and they should get garbage-collected. */
5179 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5180 is set to something other than NO_EVENT, it is enqueued.
5182 This may be called from a signal handler, so we have to ignore GC
5186 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5187 struct scroll_bar
*bar
;
5188 ControlPartCode part_code
;
5190 struct input_event
*bufp
;
5192 int win_y
, top_range
;
5194 if (! GC_WINDOWP (bar
->window
))
5197 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5198 bufp
->frame_or_window
= bar
->window
;
5201 bar
->dragging
= Qnil
;
5205 case kControlUpButtonPart
:
5206 bufp
->part
= scroll_bar_up_arrow
;
5208 case kControlDownButtonPart
:
5209 bufp
->part
= scroll_bar_down_arrow
;
5211 case kControlPageUpPart
:
5212 bufp
->part
= scroll_bar_above_handle
;
5214 case kControlPageDownPart
:
5215 bufp
->part
= scroll_bar_below_handle
;
5217 #if TARGET_API_MAC_CARBON
5220 case kControlIndicatorPart
:
5222 if (er
->what
== mouseDown
)
5223 bar
->dragging
= make_number (0);
5224 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5225 bufp
->part
= scroll_bar_handle
;
5229 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5230 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5232 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5236 if (! NILP (bar
->dragging
))
5237 win_y
-= XINT (bar
->dragging
);
5241 if (win_y
> top_range
)
5244 XSETINT (bufp
->x
, win_y
);
5245 XSETINT (bufp
->y
, top_range
);
5248 #ifndef USE_TOOLKIT_SCROLL_BARS
5250 /* Handle some mouse motion while someone is dragging the scroll bar.
5252 This may be called from a signal handler, so we have to ignore GC
5256 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5257 struct scroll_bar
*bar
;
5261 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5263 last_mouse_movement_time
= t
;
5266 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5268 /* If we're dragging the bar, display it. */
5269 if (! GC_NILP (bar
->dragging
))
5271 /* Where should the handle be now? */
5272 int new_start
= y_pos
- 24;
5274 if (new_start
!= XINT (bar
->start
))
5276 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5278 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5283 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5285 /* Return information to the user about the current position of the mouse
5286 on the scroll bar. */
5289 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5291 Lisp_Object
*bar_window
;
5292 enum scroll_bar_part
*part
;
5294 unsigned long *time
;
5296 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5297 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5298 #if TARGET_API_MAC_CARBON
5299 WindowPtr wp
= GetControlOwner (ch
);
5301 WindowPtr wp
= (*ch
)->contrlOwner
;
5304 struct frame
*f
= mac_window_to_frame (wp
);
5305 int win_y
, top_range
;
5307 SetPortWindowPort (wp
);
5309 GetMouse (&mouse_pos
);
5311 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5312 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5314 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5318 if (! NILP (bar
->dragging
))
5319 win_y
-= XINT (bar
->dragging
);
5323 if (win_y
> top_range
)
5327 *bar_window
= bar
->window
;
5329 if (! NILP (bar
->dragging
))
5330 *part
= scroll_bar_handle
;
5331 else if (win_y
< XINT (bar
->start
))
5332 *part
= scroll_bar_above_handle
;
5333 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5334 *part
= scroll_bar_handle
;
5336 *part
= scroll_bar_below_handle
;
5338 XSETINT (*x
, win_y
);
5339 XSETINT (*y
, top_range
);
5342 last_mouse_scroll_bar
= Qnil
;
5344 *time
= last_mouse_movement_time
;
5348 /* The screen has been cleared so we may have changed foreground or
5349 background colors, and the scroll bars may need to be redrawn.
5350 Clear out the scroll bars, and ask for expose events, so we can
5354 x_scroll_bar_clear (f
)
5357 XTcondemn_scroll_bars (f
);
5358 XTjudge_scroll_bars (f
);
5362 /***********************************************************************
5364 ***********************************************************************/
5366 /* Set clipping for output in glyph row ROW. W is the window in which
5367 we operate. GC is the graphics context to set clipping in.
5369 ROW may be a text row or, e.g., a mode line. Text rows must be
5370 clipped to the interior of the window dedicated to text display,
5371 mode lines must be clipped to the whole window. */
5374 x_clip_to_row (w
, row
, area
, gc
)
5376 struct glyph_row
*row
;
5380 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5382 int window_x
, window_y
, window_width
;
5384 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5386 clip_rect
.left
= window_x
;
5387 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5388 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5389 clip_rect
.right
= clip_rect
.left
+ window_width
;
5390 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5392 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5396 /* Draw a hollow box cursor on window W in glyph row ROW. */
5399 x_draw_hollow_cursor (w
, row
)
5401 struct glyph_row
*row
;
5403 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5404 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5405 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5408 struct glyph
*cursor_glyph
;
5411 /* Get the glyph the cursor is on. If we can't tell because
5412 the current matrix is invalid or such, give up. */
5413 cursor_glyph
= get_phys_cursor_glyph (w
);
5414 if (cursor_glyph
== NULL
)
5417 /* Compute frame-relative coordinates for phys cursor. */
5418 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5419 wd
= w
->phys_cursor_width
;
5421 /* The foreground of cursor_gc is typically the same as the normal
5422 background color, which can cause the cursor box to be invisible. */
5423 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5424 if (dpyinfo
->scratch_cursor_gc
)
5425 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5427 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5428 GCForeground
, &xgcv
);
5429 gc
= dpyinfo
->scratch_cursor_gc
;
5431 /* Set clipping, draw the rectangle, and reset clipping again. */
5432 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5433 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5434 mac_reset_clip_rectangles (dpy
, gc
);
5438 /* Draw a bar cursor on window W in glyph row ROW.
5440 Implementation note: One would like to draw a bar cursor with an
5441 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5442 Unfortunately, I didn't find a font yet that has this property set.
5446 x_draw_bar_cursor (w
, row
, width
, kind
)
5448 struct glyph_row
*row
;
5450 enum text_cursor_kinds kind
;
5452 struct frame
*f
= XFRAME (w
->frame
);
5453 struct glyph
*cursor_glyph
;
5455 /* If cursor is out of bounds, don't draw garbage. This can happen
5456 in mini-buffer windows when switching between echo area glyphs
5458 cursor_glyph
= get_phys_cursor_glyph (w
);
5459 if (cursor_glyph
== NULL
)
5462 /* If on an image, draw like a normal cursor. That's usually better
5463 visible than drawing a bar, esp. if the image is large so that
5464 the bar might not be in the window. */
5465 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5467 struct glyph_row
*row
;
5468 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5469 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5473 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5474 Window window
= FRAME_MAC_WINDOW (f
);
5475 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5476 unsigned long mask
= GCForeground
| GCBackground
;
5477 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5480 /* If the glyph's background equals the color we normally draw
5481 the bar cursor in, the bar cursor in its normal color is
5482 invisible. Use the glyph's foreground color instead in this
5483 case, on the assumption that the glyph's colors are chosen so
5484 that the glyph is legible. */
5485 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5486 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5488 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5491 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5494 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5495 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5499 width
= FRAME_CURSOR_WIDTH (f
);
5500 width
= min (cursor_glyph
->pixel_width
, width
);
5502 w
->phys_cursor_width
= width
;
5503 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5505 if (kind
== BAR_CURSOR
)
5506 mac_fill_rectangle (f
, gc
,
5507 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5508 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5509 width
, row
->height
);
5511 mac_fill_rectangle (f
, gc
,
5512 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5513 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5514 row
->height
- width
),
5515 cursor_glyph
->pixel_width
,
5518 mac_reset_clip_rectangles (dpy
, gc
);
5523 /* RIF: Define cursor CURSOR on frame F. */
5526 mac_define_frame_cursor (f
, cursor
)
5530 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5532 if (dpyinfo
->x_focus_frame
== f
)
5533 SetThemeCursor (cursor
);
5537 /* RIF: Clear area on frame F. */
5540 mac_clear_frame_area (f
, x
, y
, width
, height
)
5542 int x
, y
, width
, height
;
5544 mac_clear_area (f
, x
, y
, width
, height
);
5548 /* RIF: Draw cursor on window W. */
5551 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5553 struct glyph_row
*glyph_row
;
5555 int cursor_type
, cursor_width
;
5560 w
->phys_cursor_type
= cursor_type
;
5561 w
->phys_cursor_on_p
= 1;
5563 if (glyph_row
->exact_window_width_line_p
5564 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5566 glyph_row
->cursor_in_fringe_p
= 1;
5567 draw_fringe_bitmap (w
, glyph_row
, 0);
5570 switch (cursor_type
)
5572 case HOLLOW_BOX_CURSOR
:
5573 x_draw_hollow_cursor (w
, glyph_row
);
5576 case FILLED_BOX_CURSOR
:
5577 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5581 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5585 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5589 w
->phys_cursor_width
= 0;
5601 #if 0 /* MAC_TODO: no icon support yet. */
5603 x_bitmap_icon (f
, icon
)
5609 if (FRAME_W32_WINDOW (f
) == 0)
5613 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5614 else if (STRINGP (icon
))
5615 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5616 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5617 else if (SYMBOLP (icon
))
5621 if (EQ (icon
, intern ("application")))
5622 name
= (LPCTSTR
) IDI_APPLICATION
;
5623 else if (EQ (icon
, intern ("hand")))
5624 name
= (LPCTSTR
) IDI_HAND
;
5625 else if (EQ (icon
, intern ("question")))
5626 name
= (LPCTSTR
) IDI_QUESTION
;
5627 else if (EQ (icon
, intern ("exclamation")))
5628 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5629 else if (EQ (icon
, intern ("asterisk")))
5630 name
= (LPCTSTR
) IDI_ASTERISK
;
5631 else if (EQ (icon
, intern ("winlogo")))
5632 name
= (LPCTSTR
) IDI_WINLOGO
;
5636 hicon
= LoadIcon (NULL
, name
);
5644 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5649 #endif /* MAC_TODO */
5651 /************************************************************************
5653 ************************************************************************/
5655 /* Display Error Handling functions not used on W32. Listing them here
5656 helps diff stay in step when comparing w32term.c with xterm.c.
5658 x_error_catcher (display, error)
5659 x_catch_errors (dpy)
5660 x_catch_errors_unwind (old_val)
5661 x_check_errors (dpy, format)
5662 x_had_errors_p (dpy)
5663 x_clear_errors (dpy)
5664 x_uncatch_errors (dpy, count)
5666 x_connection_signal (signalnum)
5667 x_connection_closed (dpy, error_message)
5668 x_error_quitter (display, error)
5669 x_error_handler (display, error)
5670 x_io_error_quitter (display)
5675 /* Changing the font of the frame. */
5677 /* Give frame F the font named FONTNAME as its default font, and
5678 return the full name of that font. FONTNAME may be a wildcard
5679 pattern; in that case, we choose some font that fits the pattern.
5680 The return value shows which font we chose. */
5683 x_new_font (f
, fontname
)
5685 register char *fontname
;
5687 struct font_info
*fontp
5688 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5693 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5694 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5695 FRAME_FONTSET (f
) = -1;
5697 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5698 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5699 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5701 compute_fringe_widths (f
, 1);
5703 /* Compute the scroll bar width in character columns. */
5704 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5706 int wid
= FRAME_COLUMN_WIDTH (f
);
5707 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5708 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5712 int wid
= FRAME_COLUMN_WIDTH (f
);
5713 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5716 /* Now make the frame display the given font. */
5717 if (FRAME_MAC_WINDOW (f
) != 0)
5719 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5721 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5723 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5726 /* Don't change the size of a tip frame; there's no point in
5727 doing it because it's done in Fx_show_tip, and it leads to
5728 problems because the tip frame has no widget. */
5729 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5730 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5733 return build_string (fontp
->full_name
);
5736 /* Give frame F the fontset named FONTSETNAME as its default font, and
5737 return the full name of that fontset. FONTSETNAME may be a wildcard
5738 pattern; in that case, we choose some fontset that fits the pattern.
5739 The return value shows which fontset we chose. */
5742 x_new_fontset (f
, fontsetname
)
5746 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5752 if (FRAME_FONTSET (f
) == fontset
)
5753 /* This fontset is already set in frame F. There's nothing more
5755 return fontset_name (fontset
);
5757 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5759 if (!STRINGP (result
))
5760 /* Can't load ASCII font. */
5763 /* Since x_new_font doesn't update any fontset information, do it now. */
5764 FRAME_FONTSET (f
) = fontset
;
5766 return build_string (fontsetname
);
5770 /***********************************************************************
5771 TODO: W32 Input Methods
5772 ***********************************************************************/
5773 /* Listing missing functions from xterm.c helps diff stay in step.
5775 xim_destroy_callback (xim, client_data, call_data)
5776 xim_open_dpy (dpyinfo, resource_name)
5778 xim_instantiate_callback (display, client_data, call_data)
5779 xim_initialize (dpyinfo, resource_name)
5780 xim_close_dpy (dpyinfo)
5786 mac_get_window_bounds (f
, inner
, outer
)
5788 Rect
*inner
, *outer
;
5790 #if TARGET_API_MAC_CARBON
5791 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5792 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5793 #else /* not TARGET_API_MAC_CARBON */
5794 RgnHandle region
= NewRgn ();
5796 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5797 *inner
= (*region
)->rgnBBox
;
5798 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5799 *outer
= (*region
)->rgnBBox
;
5800 DisposeRgn (region
);
5801 #endif /* not TARGET_API_MAC_CARBON */
5806 /* Calculate the absolute position in frame F
5807 from its current recorded position values and gravity. */
5810 x_calc_absolute_position (f
)
5813 int width_diff
= 0, height_diff
= 0;
5814 int flags
= f
->size_hint_flags
;
5817 /* We have nothing to do if the current position
5818 is already for the top-left corner. */
5819 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5822 /* Find the offsets of the outside upper-left corner of
5823 the inner window, with respect to the outer window. */
5824 mac_get_window_bounds (f
, &inner
, &outer
);
5826 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5827 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5829 /* Treat negative positions as relative to the leftmost bottommost
5830 position that fits on the screen. */
5831 if (flags
& XNegative
)
5832 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5834 - FRAME_PIXEL_WIDTH (f
)
5837 if (flags
& YNegative
)
5838 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5840 - FRAME_PIXEL_HEIGHT (f
)
5843 /* The left_pos and top_pos
5844 are now relative to the top and left screen edges,
5845 so the flags should correspond. */
5846 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5849 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5850 to really change the position, and 0 when calling from
5851 x_make_frame_visible (in that case, XOFF and YOFF are the current
5852 position values). It is -1 when calling from x_set_frame_parameters,
5853 which means, do adjust for borders but don't change the gravity. */
5856 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5858 register int xoff
, yoff
;
5861 if (change_gravity
> 0)
5865 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5867 f
->size_hint_flags
|= XNegative
;
5869 f
->size_hint_flags
|= YNegative
;
5870 f
->win_gravity
= NorthWestGravity
;
5872 x_calc_absolute_position (f
);
5875 x_wm_set_size_hint (f
, (long) 0, 0);
5877 #if TARGET_API_MAC_CARBON
5878 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5879 /* If the title bar is completely outside the screen, adjust the
5881 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5882 kWindowConstrainMoveRegardlessOfFit
5883 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5884 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5887 Rect inner
, outer
, screen_rect
, dummy
;
5888 RgnHandle region
= NewRgn ();
5890 mac_get_window_bounds (f
, &inner
, &outer
);
5891 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5892 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5893 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5894 f
->top_pos
+ f
->y_pixels_diff
, false);
5896 /* If the title bar is completely outside the screen, adjust the
5897 position. The variable `outer' holds the title bar rectangle.
5898 The variable `inner' holds slightly smaller one than `outer',
5899 so that the calculation of overlapping may not become too
5901 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5902 outer
= (*region
)->rgnBBox
;
5903 DisposeRgn (region
);
5905 InsetRect (&inner
, 8, 8);
5906 screen_rect
= qd
.screenBits
.bounds
;
5907 screen_rect
.top
+= GetMBarHeight ();
5909 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5911 if (inner
.right
<= screen_rect
.left
)
5912 f
->left_pos
= screen_rect
.left
;
5913 else if (inner
.left
>= screen_rect
.right
)
5914 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5916 if (inner
.bottom
<= screen_rect
.top
)
5917 f
->top_pos
= screen_rect
.top
;
5918 else if (inner
.top
>= screen_rect
.bottom
)
5919 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5921 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5922 f
->top_pos
+ f
->y_pixels_diff
, false);
5930 /* Call this to change the size of frame F's x-window.
5931 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5932 for this size change and subsequent size changes.
5933 Otherwise we leave the window gravity unchanged. */
5936 x_set_window_size (f
, change_gravity
, cols
, rows
)
5941 int pixelwidth
, pixelheight
;
5945 check_frame_size (f
, &rows
, &cols
);
5946 f
->scroll_bar_actual_width
5947 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5949 compute_fringe_widths (f
, 0);
5951 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5952 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5954 f
->win_gravity
= NorthWestGravity
;
5955 x_wm_set_size_hint (f
, (long) 0, 0);
5957 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5958 #if TARGET_API_MAC_CARBON
5959 if (f
->output_data
.mac
->hourglass_control
)
5962 mac_prepare_for_quickdraw (f
);
5964 MoveControl (f
->output_data
.mac
->hourglass_control
,
5965 pixelwidth
- HOURGLASS_WIDTH
, 0);
5969 /* Now, strictly speaking, we can't be sure that this is accurate,
5970 but the window manager will get around to dealing with the size
5971 change request eventually, and we'll hear how it went when the
5972 ConfigureNotify event gets here.
5974 We could just not bother storing any of this information here,
5975 and let the ConfigureNotify event set everything up, but that
5976 might be kind of confusing to the Lisp code, since size changes
5977 wouldn't be reported in the frame parameters until some random
5978 point in the future when the ConfigureNotify event arrives.
5980 We pass 1 for DELAY since we can't run Lisp code inside of
5982 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5983 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5984 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5986 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5987 receive in the ConfigureNotify event; if we get what we asked
5988 for, then the event won't cause the screen to become garbaged, so
5989 we have to make sure to do it here. */
5990 SET_FRAME_GARBAGED (f
);
5992 XFlush (FRAME_X_DISPLAY (f
));
5994 /* If cursor was outside the new size, mark it as off. */
5995 mark_window_cursors_off (XWINDOW (f
->root_window
));
5997 /* Clear out any recollection of where the mouse highlighting was,
5998 since it might be in a place that's outside the new frame size.
5999 Actually checking whether it is outside is a pain in the neck,
6000 so don't try--just let the highlighting be done afresh with new size. */
6001 cancel_mouse_face (f
);
6006 /* Mouse warping. */
6008 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6011 x_set_mouse_position (f
, x
, y
)
6017 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6018 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6020 if (pix_x
< 0) pix_x
= 0;
6021 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6023 if (pix_y
< 0) pix_y
= 0;
6024 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6026 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6030 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6034 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
6037 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6038 0, 0, 0, 0, pix_x
, pix_y
);
6043 /* focus shifting, raising and lowering. */
6046 x_focus_on_frame (f
)
6049 #if 0 /* This proves to be unpleasant. */
6053 /* I don't think that the ICCCM allows programs to do things like this
6054 without the interaction of the window manager. Whatever you end up
6055 doing with this code, do it to x_unfocus_frame too. */
6056 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6057 RevertToPointerRoot
, CurrentTime
);
6067 /* Raise frame F. */
6073 if (f
->async_visible
)
6076 BringToFront (FRAME_MAC_WINDOW (f
));
6081 /* Lower frame F. */
6087 if (f
->async_visible
)
6090 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6096 XTframe_raise_lower (f
, raise_flag
)
6106 /* Change of visibility. */
6109 mac_handle_visibility_change (f
)
6112 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6113 int visible
= 0, iconified
= 0;
6114 struct input_event buf
;
6116 if (IsWindowVisible (wp
))
6118 if (IsWindowCollapsed (wp
))
6124 if (!f
->async_visible
&& visible
)
6128 /* wait_reading_process_output will notice this and update
6129 the frame's display structures. If we were made
6130 invisible, we should not set garbaged, because that stops
6131 redrawing on Update events. */
6132 SET_FRAME_GARBAGED (f
);
6135 buf
.kind
= DEICONIFY_EVENT
;
6136 XSETFRAME (buf
.frame_or_window
, f
);
6138 kbd_buffer_store_event (&buf
);
6140 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6141 /* Force a redisplay sooner or later to update the
6142 frame titles in case this is the second frame. */
6143 record_asynch_buffer_change ();
6145 else if (f
->async_visible
&& !visible
)
6149 buf
.kind
= ICONIFY_EVENT
;
6150 XSETFRAME (buf
.frame_or_window
, f
);
6152 kbd_buffer_store_event (&buf
);
6155 f
->async_visible
= visible
;
6156 f
->async_iconified
= iconified
;
6159 /* This tries to wait until the frame is really visible.
6160 However, if the window manager asks the user where to position
6161 the frame, this will return before the user finishes doing that.
6162 The frame will not actually be visible at that time,
6163 but it will become visible later when the window manager
6164 finishes with it. */
6167 x_make_frame_visible (f
)
6172 if (! FRAME_VISIBLE_P (f
))
6174 /* We test FRAME_GARBAGED_P here to make sure we don't
6175 call x_set_offset a second time
6176 if we get to x_make_frame_visible a second time
6177 before the window gets really visible. */
6178 if (! FRAME_ICONIFIED_P (f
)
6179 && ! f
->output_data
.mac
->asked_for_visible
)
6181 #if TARGET_API_MAC_CARBON
6182 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6184 struct frame
*sf
= SELECTED_FRAME ();
6185 if (!FRAME_MAC_P (sf
))
6186 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6187 kWindowCenterOnMainScreen
);
6189 RepositionWindow (FRAME_MAC_WINDOW (f
),
6190 FRAME_MAC_WINDOW (sf
),
6191 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6192 kWindowCascadeStartAtParentWindowScreen
6194 kWindowCascadeOnParentWindowScreen
6197 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6201 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6204 f
->output_data
.mac
->asked_for_visible
= 1;
6206 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6207 ShowWindow (FRAME_MAC_WINDOW (f
));
6210 XFlush (FRAME_MAC_DISPLAY (f
));
6212 /* Synchronize to ensure Emacs knows the frame is visible
6213 before we do anything else. We do this loop with input not blocked
6214 so that incoming events are handled. */
6219 /* This must come after we set COUNT. */
6222 XSETFRAME (frame
, f
);
6224 /* Wait until the frame is visible. Process X events until a
6225 MapNotify event has been seen, or until we think we won't get a
6226 MapNotify at all.. */
6227 for (count
= input_signal_count
+ 10;
6228 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6230 /* Force processing of queued events. */
6233 /* Machines that do polling rather than SIGIO have been
6234 observed to go into a busy-wait here. So we'll fake an
6235 alarm signal to let the handler know that there's something
6236 to be read. We used to raise a real alarm, but it seems
6237 that the handler isn't always enabled here. This is
6239 if (input_polling_used ())
6241 /* It could be confusing if a real alarm arrives while
6242 processing the fake one. Turn it off and let the
6243 handler reset it. */
6244 extern void poll_for_input_1
P_ ((void));
6245 int old_poll_suppress_count
= poll_suppress_count
;
6246 poll_suppress_count
= 1;
6247 poll_for_input_1 ();
6248 poll_suppress_count
= old_poll_suppress_count
;
6251 /* See if a MapNotify event has been processed. */
6252 FRAME_SAMPLE_VISIBILITY (f
);
6257 /* Change from mapped state to withdrawn state. */
6259 /* Make the frame visible (mapped and not iconified). */
6262 x_make_frame_invisible (f
)
6265 /* A deactivate event does not occur when the last visible frame is
6266 made invisible. So if we clear the highlight here, it will not
6267 be rehighlighted when it is made visible. */
6269 /* Don't keep the highlight on an invisible frame. */
6270 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6271 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6276 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6277 that the current position of the window is user-specified, rather than
6278 program-specified, so that when the window is mapped again, it will be
6279 placed at the same location, without forcing the user to position it
6280 by hand again (they have already done that once for this window.) */
6281 x_wm_set_size_hint (f
, (long) 0, 1);
6283 HideWindow (FRAME_MAC_WINDOW (f
));
6287 #if !USE_CARBON_EVENTS
6288 mac_handle_visibility_change (f
);
6292 /* Change window state from mapped to iconified. */
6300 /* A deactivate event does not occur when the last visible frame is
6301 iconified. So if we clear the highlight here, it will not be
6302 rehighlighted when it is deiconified. */
6304 /* Don't keep the highlight on an invisible frame. */
6305 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6306 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6309 if (f
->async_iconified
)
6314 FRAME_SAMPLE_VISIBILITY (f
);
6316 if (! FRAME_VISIBLE_P (f
))
6317 ShowWindow (FRAME_MAC_WINDOW (f
));
6319 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6324 error ("Can't notify window manager of iconification");
6326 #if !USE_CARBON_EVENTS
6327 mac_handle_visibility_change (f
);
6332 /* Free X resources of frame F. */
6335 x_free_frame_resources (f
)
6338 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6339 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6343 if (wp
!= tip_window
)
6344 remove_window_handler (wp
);
6347 if (wp
== tip_window
)
6348 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6349 closed' event. So we reset tip_window here. */
6352 free_frame_menubar (f
);
6354 if (FRAME_FACE_CACHE (f
))
6355 free_frame_faces (f
);
6359 if (FRAME_SIZE_HINTS (f
))
6360 xfree (FRAME_SIZE_HINTS (f
));
6362 #if TARGET_API_MAC_CARBON
6363 if (FRAME_FILE_NAME (f
))
6364 xfree (FRAME_FILE_NAME (f
));
6367 xfree (f
->output_data
.mac
);
6368 f
->output_data
.mac
= NULL
;
6370 if (f
== dpyinfo
->x_focus_frame
)
6372 dpyinfo
->x_focus_frame
= 0;
6373 #if USE_MAC_FONT_PANEL
6374 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
6377 if (f
== dpyinfo
->x_focus_event_frame
)
6378 dpyinfo
->x_focus_event_frame
= 0;
6379 if (f
== dpyinfo
->x_highlight_frame
)
6380 dpyinfo
->x_highlight_frame
= 0;
6382 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6384 dpyinfo
->mouse_face_beg_row
6385 = dpyinfo
->mouse_face_beg_col
= -1;
6386 dpyinfo
->mouse_face_end_row
6387 = dpyinfo
->mouse_face_end_col
= -1;
6388 dpyinfo
->mouse_face_window
= Qnil
;
6389 dpyinfo
->mouse_face_deferred_gc
= 0;
6390 dpyinfo
->mouse_face_mouse_frame
= 0;
6397 /* Destroy the X window of frame F. */
6400 x_destroy_window (f
)
6403 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6405 x_free_frame_resources (f
);
6407 dpyinfo
->reference_count
--;
6411 /* Setting window manager hints. */
6413 /* Set the normal size hints for the window manager, for frame F.
6414 FLAGS is the flags word to use--or 0 meaning preserve the flags
6415 that the window now has.
6416 If USER_POSITION is nonzero, we set the USPosition
6417 flag (this is useful when FLAGS is 0). */
6419 x_wm_set_size_hint (f
, flags
, user_position
)
6424 int base_width
, base_height
, width_inc
, height_inc
;
6425 int min_rows
= 0, min_cols
= 0;
6426 XSizeHints
*size_hints
;
6428 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6429 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6430 width_inc
= FRAME_COLUMN_WIDTH (f
);
6431 height_inc
= FRAME_LINE_HEIGHT (f
);
6433 check_frame_size (f
, &min_rows
, &min_cols
);
6435 size_hints
= FRAME_SIZE_HINTS (f
);
6436 if (size_hints
== NULL
)
6438 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6439 bzero (size_hints
, sizeof (XSizeHints
));
6442 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6443 size_hints
->width_inc
= width_inc
;
6444 size_hints
->height_inc
= height_inc
;
6445 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6446 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6447 size_hints
->base_width
= base_width
;
6448 size_hints
->base_height
= base_height
;
6451 size_hints
->flags
= flags
;
6452 else if (user_position
)
6454 size_hints
->flags
&= ~ PPosition
;
6455 size_hints
->flags
|= USPosition
;
6459 #if 0 /* MAC_TODO: hide application instead of iconify? */
6460 /* Used for IconicState or NormalState */
6463 x_wm_set_window_state (f
, state
)
6467 #ifdef USE_X_TOOLKIT
6470 XtSetArg (al
[0], XtNinitialState
, state
);
6471 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6472 #else /* not USE_X_TOOLKIT */
6473 Window window
= FRAME_X_WINDOW (f
);
6475 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6476 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6478 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6479 #endif /* not USE_X_TOOLKIT */
6483 x_wm_set_icon_pixmap (f
, pixmap_id
)
6489 #ifndef USE_X_TOOLKIT
6490 Window window
= FRAME_X_WINDOW (f
);
6495 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6496 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6500 /* It seems there is no way to turn off use of an icon pixmap.
6501 The following line does it, only if no icon has yet been created,
6502 for some window managers. But with mwm it crashes.
6503 Some people say it should clear the IconPixmapHint bit in this case,
6504 but that doesn't work, and the X consortium said it isn't the
6505 right thing at all. Since there is no way to win,
6506 best to explicitly give up. */
6508 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6514 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6518 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6519 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6522 #else /* not USE_X_TOOLKIT */
6524 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6525 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6527 #endif /* not USE_X_TOOLKIT */
6530 #endif /* MAC_TODO */
6533 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6537 #if 0 /* MAC_TODO: no icons on Mac */
6538 #ifdef USE_X_TOOLKIT
6539 Window window
= XtWindow (f
->output_data
.x
->widget
);
6541 Window window
= FRAME_X_WINDOW (f
);
6544 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6545 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6546 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6548 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6549 #endif /* MAC_TODO */
6553 /***********************************************************************
6555 ***********************************************************************/
6557 /* An XLFD pattern is divided into blocks delimited by '*'. This
6558 structure holds information for each block. */
6559 struct xlfdpat_block
6561 /* Length of the pattern string in this block. Non-zero except for
6562 the first and the last blocks. */
6565 /* Pattern string except the last character in this block. The last
6566 character is replaced with NUL in order to use it as a
6568 unsigned char *pattern
;
6570 /* Last character of the pattern string. Must not be '?'. */
6571 unsigned char last_char
;
6573 /* One of the tables for the Boyer-Moore string search. It
6574 specifies the number of positions to proceed for each character
6575 with which the match fails. */
6578 /* The skip value for the last character in the above `skip' is
6579 assigned to `infinity' in order to simplify a loop condition.
6580 The original value is saved here. */
6586 /* Normalized pattern string. "Normalized" means that capital
6587 letters are lowered, blocks are not empty except the first and
6588 the last ones, and trailing '?'s in a block that is not the last
6589 one are moved to the next one. The last character in each block
6590 is replaced with NUL. */
6593 /* Number of characters except '*'s and trailing '?'s in the
6594 normalized pattern string. */
6597 /* Number of trailing '?'s in the normalized pattern string. */
6598 int trailing_anychars
;
6600 /* Number of blocks and information for each block. The latter is
6601 NULL if the pattern is exact (no '*' or '?' in it). */
6603 struct xlfdpat_block
*blocks
;
6607 xlfdpat_destroy (pat
)
6608 struct xlfdpat
*pat
;
6615 xfree (pat
->blocks
);
6622 static struct xlfdpat
*
6623 xlfdpat_create (pattern
)
6626 struct xlfdpat
*pat
;
6627 int nblocks
, i
, skip
;
6628 unsigned char last_char
, *p
, *q
, *anychar_head
;
6629 struct xlfdpat_block
*blk
;
6631 pat
= xmalloc (sizeof (struct xlfdpat
));
6632 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6634 /* Normalize the pattern string and store it to `pat->buf'. */
6636 anychar_head
= NULL
;
6639 for (p
= pattern
; *p
; p
++)
6641 unsigned char c
= *p
;
6644 if (last_char
== '*')
6645 /* ...a** -> ...a* */
6649 if (last_char
== '?')
6651 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6652 /* ...*??* -> ...*?? */
6655 /* ...a??* -> ...a*?? */
6657 *anychar_head
++ = '*';
6665 if (last_char
!= '?')
6669 /* On Mac OS X 10.3, tolower also converts non-ASCII
6670 characters for some locales. */
6674 *q
++ = last_char
= c
;
6678 pat
->nblocks
= nblocks
;
6679 if (last_char
!= '?')
6680 pat
->trailing_anychars
= 0;
6683 pat
->trailing_anychars
= q
- anychar_head
;
6686 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6688 if (anychar_head
== NULL
&& nblocks
== 1)
6690 /* The pattern is exact. */
6695 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6697 /* Divide the normalized pattern into blocks. */
6699 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6704 blk
->len
= p
- blk
->pattern
;
6708 blk
->len
= q
- blk
->pattern
;
6710 /* Setup a table for the Boyer-Moore string search. */
6711 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6714 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6715 blk
->pattern
[blk
->len
- 1] = '\0';
6717 for (skip
= 1; skip
< blk
->len
; skip
++)
6718 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6721 for (i
= 0; i
< 256; i
++)
6722 blk
->skip
[i
] = skip
;
6724 p
= blk
->pattern
+ (blk
->len
- skip
);
6726 blk
->skip
[*p
++] = skip
;
6728 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6735 xlfdpat_exact_p (pat
)
6736 struct xlfdpat
*pat
;
6738 return pat
->blocks
== NULL
;
6741 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6742 that the pattern in *BLK matches with its prefix. Return NULL
6743 there is no such strings. STRING must be lowered in advance. */
6746 xlfdpat_block_match_1 (blk
, string
, start_max
)
6747 struct xlfdpat_block
*blk
;
6748 unsigned char *string
;
6751 int start
, infinity
;
6752 unsigned char *p
, *s
;
6754 xassert (blk
->len
> 0);
6755 xassert (start_max
+ blk
->len
<= strlen (string
));
6756 xassert (blk
->last_char
!= '?');
6758 /* See the comments in the function `boyer_moore' (search.c) for the
6759 use of `infinity'. */
6760 infinity
= start_max
+ blk
->len
+ 1;
6761 blk
->skip
[blk
->last_char
] = infinity
;
6766 /* Check the last character of the pattern. */
6767 s
= string
+ blk
->len
- 1;
6770 start
+= blk
->skip
[*(s
+ start
)];
6772 while (start
<= start_max
);
6774 if (start
< infinity
)
6775 /* Couldn't find the last character. */
6778 /* No less than `infinity' means we could find the last
6779 character at `s[start - infinity]'. */
6782 /* Check the remaining characters. We prefer making no-'?'
6783 cases faster because the use of '?' is really rare. */
6788 while (*p
++ == *s
++)
6791 while (*(p
- 1) == '?');
6793 if (*(p
- 1) == '\0')
6795 return string
+ start
;
6798 start
+= blk
->last_char_skip
;
6800 while (start
<= start_max
);
6805 #define xlfdpat_block_match(b, s, m) \
6806 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6807 : xlfdpat_block_match_1 (b, s, m))
6809 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6810 matches with STRING. STRING must be lowered in advance. */
6813 xlfdpat_match (pat
, string
)
6814 struct xlfdpat
*pat
;
6815 unsigned char *string
;
6817 int str_len
, nblocks
, i
, start_max
;
6818 struct xlfdpat_block
*blk
;
6821 xassert (pat
->nblocks
> 0);
6823 if (xlfdpat_exact_p (pat
))
6824 return strcmp (pat
->buf
, string
) == 0;
6826 /* The number of the characters in the string must not be smaller
6827 than that in the pattern. */
6828 str_len
= strlen (string
);
6829 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6832 /* Chop off the trailing '?'s. */
6833 str_len
-= pat
->trailing_anychars
;
6835 /* The last block. When it is non-empty, it must match at the end
6837 nblocks
= pat
->nblocks
;
6838 blk
= pat
->blocks
+ (nblocks
- 1);
6840 /* The last block is also the first one. */
6841 return (str_len
== blk
->len
6842 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6843 else if (blk
->len
!= 0)
6844 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6847 /* The first block. When it is non-empty, it must match at the
6848 beginning of the string. */
6852 s
= xlfdpat_block_match (blk
, string
, 0);
6855 string
= s
+ blk
->len
;
6858 /* The rest of the blocks. */
6859 start_max
= str_len
- pat
->nchars
;
6860 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6862 s
= xlfdpat_block_match (blk
, string
, start_max
);
6865 start_max
-= s
- string
;
6866 string
= s
+ blk
->len
;
6873 /***********************************************************************
6875 ***********************************************************************/
6877 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6880 x_get_font_info (f
, font_idx
)
6884 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6887 /* the global font name table */
6888 static char **font_name_table
= NULL
;
6889 static int font_name_table_size
= 0;
6890 static int font_name_count
= 0;
6892 /* Alist linking font family names to Font Manager font family
6893 references (which can also be used as QuickDraw font IDs). We use
6894 an alist because hash tables are not ready when the terminal frame
6895 for Mac OS Classic is created. */
6896 static Lisp_Object fm_font_family_alist
;
6898 /* Hash table linking font family names to ATSU font IDs. */
6899 static Lisp_Object atsu_font_id_hash
;
6900 static Lisp_Object Vmac_atsu_font_table
;
6901 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
6904 /* Alist linking character set strings to Mac text encoding and Emacs
6906 static Lisp_Object Vmac_charset_info_alist
;
6909 create_text_encoding_info_alist ()
6911 Lisp_Object result
= Qnil
, rest
;
6913 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6915 Lisp_Object charset_info
= XCAR (rest
);
6916 Lisp_Object charset
, coding_system
, text_encoding
;
6917 Lisp_Object existing_info
;
6919 if (!(CONSP (charset_info
)
6920 && STRINGP (charset
= XCAR (charset_info
))
6921 && CONSP (XCDR (charset_info
))
6922 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6923 && CONSP (XCDR (XCDR (charset_info
)))
6924 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6927 existing_info
= assq_no_quit (text_encoding
, result
);
6928 if (NILP (existing_info
))
6929 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6932 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6933 XSETCDR (XCDR (existing_info
),
6934 Fcons (charset
, XCDR (XCDR (existing_info
))));
6942 decode_mac_font_name (name
, size
, coding_system
)
6945 Lisp_Object coding_system
;
6947 struct coding_system coding
;
6950 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6952 for (p
= name
; *p
; p
++)
6953 if (!isascii (*p
) || iscntrl (*p
))
6958 setup_coding_system (coding_system
, &coding
);
6959 coding
.src_multibyte
= 0;
6960 coding
.dst_multibyte
= 1;
6961 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6962 coding
.composing
= COMPOSITION_DISABLED
;
6963 buf
= (char *) alloca (size
);
6965 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6966 bcopy (buf
, name
, coding
.produced
);
6967 name
[coding
.produced
] = '\0';
6971 /* If there's just one occurrence of '-' in the family name, it is
6972 replaced with '_'. (More than one occurrence of '-' means a
6973 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6974 p
= strchr (name
, '-');
6975 if (p
&& strchr (p
+ 1, '-') == NULL
)
6978 for (p
= name
; *p
; p
++)
6979 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6980 for some locales. */
6987 mac_to_x_fontname (name
, size
, style
, charset
)
6995 char xf
[256], *result
;
6998 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7002 strcpy(foundry
, "Apple");
7003 strcpy(family
, name
);
7006 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7007 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7008 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7010 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7011 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7012 for (p
= result
; *p
; p
++)
7013 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7014 for some locales. */
7021 /* Parse fully-specified and instantiated X11 font spec XF, and store
7022 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7023 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7024 caller must allocate at least 256 and 32 bytes respectively. For
7025 ordinary Mac fonts, the value stored to FAMILY should just be their
7026 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7027 intlfonts collection contain their charset designation in their
7028 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7029 types of font names are handled accordingly. */
7031 const int kDefaultFontSize
= 12;
7034 parse_x_font_name (xf
, family
, size
, style
, charset
)
7040 Str31 foundry
, weight
;
7041 int point_size
, avgwidth
;
7044 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7045 foundry
, family
, weight
, slant
, size
,
7046 &point_size
, &avgwidth
, charset
) != 8
7047 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7048 foundry
, family
, weight
, slant
, size
,
7049 &point_size
, &avgwidth
, charset
) != 8)
7055 *size
= point_size
/ 10;
7056 else if (avgwidth
> 0)
7057 *size
= avgwidth
/ 10;
7060 *size
= kDefaultFontSize
;
7063 if (strcmp (weight
, "bold") == 0)
7068 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7070 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7072 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7074 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7075 but take overlap into account. */
7076 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7077 memcpy (family
, foundry
, foundry_len
);
7078 family
[foundry_len
] = '-';
7079 family
[foundry_len
+ 1 + family_len
] = '-';
7080 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7086 for (p
= family
; *p
; p
++)
7087 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7088 for some locales. */
7097 add_font_name_table_entry (char *font_name
)
7099 if (font_name_table_size
== 0)
7101 font_name_table_size
= 256;
7102 font_name_table
= (char **)
7103 xmalloc (font_name_table_size
* sizeof (char *));
7105 else if (font_name_count
+ 1 >= font_name_table_size
)
7107 font_name_table_size
*= 2;
7108 font_name_table
= (char **)
7109 xrealloc (font_name_table
,
7110 font_name_table_size
* sizeof (char *));
7113 font_name_table
[font_name_count
++] = font_name
;
7117 add_mac_font_name (name
, size
, style
, charset
)
7124 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7127 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7128 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
7129 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
7130 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
7135 /* Sets up the table font_name_table to contain the list of all fonts
7136 in the system the first time the table is used so that the Resource
7137 Manager need not be accessed every time this information is
7141 init_font_name_table ()
7143 #if TARGET_API_MAC_CARBON
7144 FMFontFamilyIterator ffi
;
7145 FMFontFamilyInstanceIterator ffii
;
7147 Lisp_Object text_encoding_info_alist
;
7148 struct gcpro gcpro1
;
7150 text_encoding_info_alist
= create_text_encoding_info_alist ();
7153 #if USE_CG_TEXT_DRAWING
7154 init_cg_text_anti_aliasing_threshold ();
7156 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7157 text_encoding_info_alist
)))
7160 struct Lisp_Hash_Table
*h
;
7162 ItemCount nfonts
, i
;
7163 ATSUFontID
*font_ids
= NULL
;
7169 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7170 make_float (DEFAULT_REHASH_SIZE
),
7171 make_float (DEFAULT_REHASH_THRESHOLD
),
7173 h
= XHASH_TABLE (atsu_font_id_hash
);
7175 err
= ATSUFontCount (&nfonts
);
7178 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7179 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7182 for (i
= 0; i
< nfonts
; i
++)
7184 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7185 kFontMacintoshPlatform
, kFontNoScript
,
7186 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
7189 name
= xmalloc (name_len
+ 1);
7190 name
[name_len
] = '\0';
7191 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7192 kFontMacintoshPlatform
, kFontNoScript
,
7193 kFontNoLanguage
, name_len
, name
,
7198 FMFontStyle style
= normal
;
7200 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
7201 family
= make_unibyte_string (name
, name_len
);
7202 FMGetFontFamilyInstanceFromFont (font_ids
[i
], &ff
, &style
);
7203 Fputhash (make_unibyte_string ((char *)(font_ids
+ i
),
7204 sizeof (ATSUFontID
)),
7208 style
& bold
? Qbold
: Qnormal
,
7210 style
& italic
? Qitalic
: Qnormal
)),
7211 Vmac_atsu_font_table
);
7213 && hash_lookup (h
, family
, &hash_code
) < 0)
7215 add_mac_font_name (name
, 0, normal
, "iso10646-1");
7216 hash_put (h
, family
, long_to_cons (font_ids
[i
]),
7227 /* Create a dummy instance iterator here to avoid creating and
7228 destroying it in the loop. */
7229 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7231 /* Create an iterator to enumerate the font families. */
7232 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7235 FMDisposeFontFamilyInstanceIterator (&ffii
);
7239 GCPRO1 (text_encoding_info_alist
);
7241 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7247 TextEncoding encoding
;
7248 TextEncodingBase sc
;
7249 Lisp_Object text_encoding_info
, family
;
7251 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7257 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7259 sc
= GetTextEncodingBase (encoding
);
7260 text_encoding_info
= assq_no_quit (make_number (sc
),
7261 text_encoding_info_alist
);
7262 if (NILP (text_encoding_info
))
7263 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7264 text_encoding_info_alist
);
7265 decode_mac_font_name (name
, sizeof (name
),
7266 XCAR (XCDR (text_encoding_info
)));
7267 family
= build_string (name
);
7268 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7270 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7271 fm_font_family_alist
);
7273 /* Point the instance iterator at the current font family. */
7274 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7277 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7280 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7282 if (size
> 0 || style
== normal
)
7283 for (; !NILP (rest
); rest
= XCDR (rest
))
7284 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7290 /* Dispose of the iterators. */
7291 FMDisposeFontFamilyIterator (&ffi
);
7292 FMDisposeFontFamilyInstanceIterator (&ffii
);
7293 #else /* !TARGET_API_MAC_CARBON */
7295 SInt16 fontnum
, old_fontnum
;
7296 int num_mac_fonts
= CountResources('FOND');
7298 Handle font_handle
, font_handle_2
;
7299 short id
, scriptcode
;
7302 struct FontAssoc
*fat
;
7303 struct AsscEntry
*assc_entry
;
7304 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7305 struct gcpro gcpro1
;
7307 GetPort (&port
); /* save the current font number used */
7308 old_fontnum
= port
->txFont
;
7310 text_encoding_info_alist
= create_text_encoding_info_alist ();
7312 GCPRO1 (text_encoding_info_alist
);
7314 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7316 font_handle
= GetIndResource ('FOND', i
);
7320 GetResInfo (font_handle
, &id
, &type
, name
);
7321 GetFNum (name
, &fontnum
);
7323 if (fontnum
== 0 || *name
== '.')
7327 scriptcode
= FontToScript (fontnum
);
7328 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7329 text_encoding_info_alist
);
7330 if (NILP (text_encoding_info
))
7331 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7332 text_encoding_info_alist
);
7333 decode_mac_font_name (name
, sizeof (name
),
7334 XCAR (XCDR (text_encoding_info
)));
7335 family
= build_string (name
);
7336 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7338 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7339 fm_font_family_alist
);
7342 HLock (font_handle
);
7344 if (GetResourceSizeOnDisk (font_handle
)
7345 >= sizeof (struct FamRec
))
7347 fat
= (struct FontAssoc
*) (*font_handle
7348 + sizeof (struct FamRec
));
7350 = (struct AsscEntry
*) (*font_handle
7351 + sizeof (struct FamRec
)
7352 + sizeof (struct FontAssoc
));
7354 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7356 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7358 for (; !NILP (rest
); rest
= XCDR (rest
))
7359 add_mac_font_name (name
, assc_entry
->fontSize
,
7360 assc_entry
->fontStyle
,
7361 SDATA (XCAR (rest
)));
7365 HUnlock (font_handle
);
7366 font_handle_2
= GetNextFOND (font_handle
);
7367 ReleaseResource (font_handle
);
7368 font_handle
= font_handle_2
;
7370 while (ResError () == noErr
&& font_handle
);
7375 TextFont (old_fontnum
);
7376 #endif /* !TARGET_API_MAC_CARBON */
7381 mac_clear_font_name_table ()
7385 for (i
= 0; i
< font_name_count
; i
++)
7386 xfree (font_name_table
[i
]);
7387 xfree (font_name_table
);
7388 font_name_table
= NULL
;
7389 font_name_table_size
= font_name_count
= 0;
7390 fm_font_family_alist
= Qnil
;
7394 enum xlfd_scalable_field_index
7396 XLFD_SCL_PIXEL_SIZE
,
7397 XLFD_SCL_POINT_SIZE
,
7402 static int xlfd_scalable_fields
[] =
7411 mac_do_list_fonts (pattern
, maxnames
)
7416 Lisp_Object font_list
= Qnil
;
7417 struct xlfdpat
*pat
;
7419 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7422 if (font_name_table
== NULL
) /* Initialize when first used. */
7423 init_font_name_table ();
7425 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7428 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7429 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7430 fonts are scaled according to the specified size. */
7433 field
= xlfd_scalable_fields
;
7441 if ('0' <= *ptr
&& *ptr
<= '9')
7443 *val
= *ptr
++ - '0';
7444 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7445 *val
= *val
* 10 + *ptr
++ - '0';
7452 ptr
= strchr (ptr
, '-');
7455 while (ptr
&& i
< 14);
7457 if (i
== 14 && ptr
== NULL
)
7459 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7460 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7461 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7462 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7464 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7465 scl_val
[XLFD_SCL_POINT_SIZE
] =
7466 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7467 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7469 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7470 scl_val
[XLFD_SCL_AVGWIDTH
] =
7471 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7472 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7476 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7478 pat
= xlfdpat_create (pattern
);
7482 exact
= xlfdpat_exact_p (pat
);
7484 for (i
= 0; i
< font_name_count
; i
++)
7486 if (xlfdpat_match (pat
, font_name_table
[i
]))
7488 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7489 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7492 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7493 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7495 int former_len
= ptr
- font_name_table
[i
];
7497 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7498 memcpy (scaled
, font_name_table
[i
], former_len
);
7499 sprintf (scaled
+ former_len
,
7500 "-%d-%d-72-72-m-%d-%s",
7501 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7502 scl_val
[XLFD_SCL_POINT_SIZE
],
7503 scl_val
[XLFD_SCL_AVGWIDTH
],
7504 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7506 if (xlfdpat_match (pat
, scaled
))
7508 font_list
= Fcons (build_string (scaled
), font_list
);
7510 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7518 xlfdpat_destroy (pat
);
7523 /* Return a list of names of available fonts matching PATTERN on frame F.
7525 Frame F null means we have not yet created any frame on Mac, and
7526 consult the first display in x_display_list. MAXNAMES sets a limit
7527 on how many fonts to match. */
7530 x_list_fonts (f
, pattern
, size
, maxnames
)
7532 Lisp_Object pattern
;
7535 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7536 struct mac_display_info
*dpyinfo
7537 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7539 xassert (size
<= 0);
7541 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7542 if (NILP (patterns
))
7543 patterns
= Fcons (pattern
, Qnil
);
7545 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7547 pattern
= XCAR (patterns
);
7549 if (!STRINGP (pattern
))
7552 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7553 key
= Fcons (pattern
, make_number (maxnames
));
7555 list
= Fassoc (key
, tem
);
7558 list
= Fcdr_safe (list
);
7559 /* We have a cashed list. Don't have to get the list again. */
7564 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7567 /* MAC_TODO: add code for matching outline fonts here */
7569 /* Now store the result in the cache. */
7570 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7571 Fcons (Fcons (key
, list
),
7572 XCAR (XCDR (dpyinfo
->name_list_element
))));
7575 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7584 /* Check that FONT is valid on frame F. It is if it can be found in F's
7588 x_check_font (f
, font
)
7593 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7595 xassert (font
!= NULL
);
7597 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7598 if (dpyinfo
->font_table
[i
].name
7599 && font
== dpyinfo
->font_table
[i
].font
)
7602 xassert (i
< dpyinfo
->n_fonts
);
7605 #endif /* GLYPH_DEBUG != 0 */
7607 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7608 Note: There are (broken) X fonts out there with invalid XFontStruct
7609 min_bounds contents. For example, handa@etl.go.jp reports that
7610 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7611 have font->min_bounds.width == 0. */
7614 x_font_min_bounds (font
, w
, h
)
7615 MacFontStruct
*font
;
7618 *h
= FONT_HEIGHT (font
);
7619 *w
= font
->min_bounds
.width
;
7623 /* Compute the smallest character width and smallest font height over
7624 all fonts available on frame F. Set the members smallest_char_width
7625 and smallest_font_height in F's x_display_info structure to
7626 the values computed. Value is non-zero if smallest_font_height or
7627 smallest_char_width become smaller than they were before. */
7630 x_compute_min_glyph_bounds (f
)
7634 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7635 MacFontStruct
*font
;
7636 int old_width
= dpyinfo
->smallest_char_width
;
7637 int old_height
= dpyinfo
->smallest_font_height
;
7639 dpyinfo
->smallest_font_height
= 100000;
7640 dpyinfo
->smallest_char_width
= 100000;
7642 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7643 if (dpyinfo
->font_table
[i
].name
)
7645 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7648 font
= (MacFontStruct
*) fontp
->font
;
7649 xassert (font
!= (MacFontStruct
*) ~0);
7650 x_font_min_bounds (font
, &w
, &h
);
7652 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7653 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7656 xassert (dpyinfo
->smallest_char_width
> 0
7657 && dpyinfo
->smallest_font_height
> 0);
7659 return (dpyinfo
->n_fonts
== 1
7660 || dpyinfo
->smallest_char_width
< old_width
7661 || dpyinfo
->smallest_font_height
< old_height
);
7665 /* Determine whether given string is a fully-specified XLFD: all 14
7666 fields are present, none is '*'. */
7669 is_fully_specified_xlfd (char *p
)
7677 for (i
= 0; i
< 13; i
++)
7679 q
= strchr (p
+ 1, '-');
7682 if (q
- p
== 2 && *(p
+ 1) == '*')
7687 if (strchr (p
+ 1, '-') != NULL
)
7690 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7697 /* XLoadQueryFont creates and returns an internal representation for a
7698 font in a MacFontStruct struct. There is really no concept
7699 corresponding to "loading" a font on the Mac. But we check its
7700 existence and find the font number and all other information for it
7701 and store them in the returned MacFontStruct. */
7703 static MacFontStruct
*
7704 XLoadQueryFont (Display
*dpy
, char *fontname
)
7712 static ATSUFontID font_id
;
7713 ATSUStyle mac_style
= NULL
;
7716 #if TARGET_API_MAC_CARBON
7717 TextEncoding encoding
;
7722 MacFontStruct
*font
;
7723 XCharStruct
*space_bounds
= NULL
, *pcm
;
7725 if (is_fully_specified_xlfd (fontname
))
7729 Lisp_Object matched_fonts
;
7731 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7732 if (NILP (matched_fonts
))
7734 name
= SDATA (XCAR (matched_fonts
));
7737 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7741 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7744 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7745 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7746 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7747 sizeof (Boolean
), sizeof (Boolean
)};
7748 static Fixed size_fixed
;
7749 static Boolean bold_p
, italic_p
;
7750 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7751 &bold_p
, &italic_p
};
7752 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
,
7754 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
,
7755 kDecomposeDiacriticsSelector
};
7756 Lisp_Object font_id_cons
;
7759 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7760 atsu_font_id_hash
, Qnil
);
7761 if (NILP (font_id_cons
))
7763 font_id
= cons_to_long (font_id_cons
);
7764 size_fixed
= Long2Fix (size
);
7765 bold_p
= (fontface
& bold
) != 0;
7766 italic_p
= (fontface
& italic
) != 0;
7767 err
= ATSUCreateStyle (&mac_style
);
7770 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7774 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7775 tags
, sizes
, values
);
7778 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
7781 scriptcode
= kTextEncodingMacUnicode
;
7786 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7790 fontnum
= XINT (XCDR (tmp
));
7791 #if TARGET_API_MAC_CARBON
7792 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7794 scriptcode
= GetTextEncodingBase (encoding
);
7796 scriptcode
= FontToScript (fontnum
);
7800 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7802 font
->mac_fontnum
= fontnum
;
7803 font
->mac_fontsize
= size
;
7804 font
->mac_fontface
= fontface
;
7805 font
->mac_scriptcode
= scriptcode
;
7807 font
->mac_style
= mac_style
;
7808 #if USE_CG_TEXT_DRAWING
7809 font
->cg_font
= NULL
;
7810 font
->cg_glyphs
= NULL
;
7814 /* Apple Japanese (SJIS) font is listed as both
7815 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7816 (Roman script) in init_font_name_table (). The latter should be
7817 treated as a one-byte font. */
7818 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7819 font
->mac_scriptcode
= smRoman
;
7821 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7824 if (font
->mac_style
)
7829 font
->min_byte1
= 0;
7830 font
->max_byte1
= 0xff;
7831 font
->min_char_or_byte2
= 0;
7832 font
->max_char_or_byte2
= 0xff;
7834 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
7835 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
7836 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
7837 pcm_init (font
->bounds
.rows
[0], 0x100);
7839 #if USE_CG_TEXT_DRAWING
7843 ATSFontRef ats_font
;
7845 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
7847 /* Use CG text drawing if italic/bold is not synthesized. */
7848 if (err
== noErr
&& style
== fontface
)
7850 ats_font
= FMGetATSFontRefFromFont (font_id
);
7851 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7857 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7858 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7861 space_bounds
= font
->bounds
.rows
[0] + 0x20;
7862 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7863 &font
->ascent
, &font
->descent
,
7865 #if USE_CG_TEXT_DRAWING
7866 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7874 mac_unload_font (&one_mac_display_info
, font
);
7878 pcm
= font
->bounds
.rows
[0];
7879 for (c
= 0x21; c
<= 0xff; c
++)
7882 /* Soft hyphen is not supported in ATSUI. */
7890 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
7891 #if USE_CG_TEXT_DRAWING
7892 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7899 #if USE_CG_TEXT_DRAWING
7900 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7902 /* Don't use CG text drawing if font substitution occurs in
7903 ASCII or Latin-1 characters. */
7904 CGFontRelease (font
->cg_font
);
7905 font
->cg_font
= NULL
;
7906 xfree (font
->cg_glyphs
);
7907 font
->cg_glyphs
= NULL
;
7916 SInt16 old_fontnum
, old_fontsize
;
7918 FontInfo the_fontinfo
;
7919 int is_two_byte_font
;
7921 /* Save the current font number used. */
7923 #if TARGET_API_MAC_CARBON
7924 old_fontnum
= GetPortTextFont (port
);
7925 old_fontsize
= GetPortTextSize (port
);
7926 old_fontface
= GetPortTextFace (port
);
7928 old_fontnum
= port
->txFont
;
7929 old_fontsize
= port
->txSize
;
7930 old_fontface
= port
->txFace
;
7935 TextFace (fontface
);
7937 GetFontInfo (&the_fontinfo
);
7939 font
->ascent
= the_fontinfo
.ascent
;
7940 font
->descent
= the_fontinfo
.descent
;
7942 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7943 || font
->mac_scriptcode
== smTradChinese
7944 || font
->mac_scriptcode
== smSimpChinese
7945 || font
->mac_scriptcode
== smKorean
);
7947 if (is_two_byte_font
)
7951 font
->min_byte1
= 0xa1;
7952 font
->max_byte1
= 0xfe;
7953 font
->min_char_or_byte2
= 0xa1;
7954 font
->max_char_or_byte2
= 0xfe;
7956 /* Use the width of an "ideographic space" of that font
7957 because the_fontinfo.widMax returns the wrong width for
7959 switch (font
->mac_scriptcode
)
7962 font
->min_byte1
= 0x81;
7963 font
->max_byte1
= 0xfc;
7964 font
->min_char_or_byte2
= 0x40;
7965 font
->max_char_or_byte2
= 0xfc;
7966 char_width
= StringWidth("\p\x81\x40");
7969 font
->min_char_or_byte2
= 0x40;
7970 char_width
= StringWidth("\p\xa1\x40");
7973 char_width
= StringWidth("\p\xa1\xa1");
7976 char_width
= StringWidth("\p\xa1\xa1");
7980 font
->bounds
.per_char
= NULL
;
7982 if (fontface
& italic
)
7983 font
->max_bounds
.rbearing
= char_width
+ 1;
7985 font
->max_bounds
.rbearing
= char_width
;
7986 font
->max_bounds
.lbearing
= 0;
7987 font
->max_bounds
.width
= char_width
;
7988 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7989 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7991 font
->min_bounds
= font
->max_bounds
;
7997 font
->min_byte1
= font
->max_byte1
= 0;
7998 font
->min_char_or_byte2
= 0x20;
7999 font
->max_char_or_byte2
= 0xff;
8001 font
->bounds
.per_char
=
8002 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8003 bzero (font
->bounds
.per_char
,
8004 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8006 space_bounds
= font
->bounds
.per_char
;
8007 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
8008 space_bounds
, NULL
);
8010 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8011 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8014 /* Restore previous font number, size and face. */
8015 TextFont (old_fontnum
);
8016 TextSize (old_fontsize
);
8017 TextFace (old_fontface
);
8024 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8025 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8028 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8030 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8032 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8034 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8037 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8039 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8041 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8043 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8048 font
->mac_style
== NULL
&&
8050 font
->max_bounds
.width
== font
->min_bounds
.width
8051 && font
->min_bounds
.lbearing
>= 0
8052 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8054 /* Fixed width and no overhangs. */
8055 xfree (font
->bounds
.per_char
);
8056 font
->bounds
.per_char
= NULL
;
8060 #if !defined (MAC_OS8) || USE_ATSUI
8061 /* AppKit and WebKit do some adjustment to the heights of Courier,
8062 Helvetica, and Times. This only works on the environments where
8063 srcCopy text transfer mode is never used. */
8065 #ifdef MAC_OS8 /* implies USE_ATSUI */
8068 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8069 || strcmp (family
, "times") == 0))
8070 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8078 mac_unload_font (dpyinfo
, font
)
8079 struct mac_display_info
*dpyinfo
;
8082 xfree (font
->full_name
);
8084 if (font
->mac_style
)
8088 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8089 if (font
->bounds
.rows
[i
])
8090 xfree (font
->bounds
.rows
[i
]);
8091 xfree (font
->bounds
.rows
);
8092 ATSUDisposeStyle (font
->mac_style
);
8096 if (font
->bounds
.per_char
)
8097 xfree (font
->bounds
.per_char
);
8098 #if USE_CG_TEXT_DRAWING
8100 CGFontRelease (font
->cg_font
);
8101 if (font
->cg_glyphs
)
8102 xfree (font
->cg_glyphs
);
8108 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8109 pointer to the structure font_info while allocating it dynamically.
8110 If SIZE is 0, load any size of font.
8111 If loading is failed, return NULL. */
8114 x_load_font (f
, fontname
, size
)
8116 register char *fontname
;
8119 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8120 Lisp_Object font_names
;
8122 /* Get a list of all the fonts that match this name. Once we
8123 have a list of matching fonts, we compare them against the fonts
8124 we already have by comparing names. */
8125 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8127 if (!NILP (font_names
))
8132 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8133 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8134 if (dpyinfo
->font_table
[i
].name
8135 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8136 SDATA (XCAR (tail
)))
8137 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8138 SDATA (XCAR (tail
)))))
8139 return (dpyinfo
->font_table
+ i
);
8144 /* Load the font and add it to the table. */
8146 struct MacFontStruct
*font
;
8147 struct font_info
*fontp
;
8150 fontname
= (char *) SDATA (XCAR (font_names
));
8153 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
8158 /* Find a free slot in the font table. */
8159 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8160 if (dpyinfo
->font_table
[i
].name
== NULL
)
8163 /* If no free slot found, maybe enlarge the font table. */
8164 if (i
== dpyinfo
->n_fonts
8165 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8168 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8169 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8171 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8174 fontp
= dpyinfo
->font_table
+ i
;
8175 if (i
== dpyinfo
->n_fonts
)
8178 /* Now fill in the slots of *FONTP. */
8180 bzero (fontp
, sizeof (*fontp
));
8182 fontp
->font_idx
= i
;
8183 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8184 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8186 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8188 /* Fixed width font. */
8189 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8196 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8197 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8199 fontp
->space_width
= pcm
->width
;
8201 fontp
->space_width
= FONT_WIDTH (font
);
8205 int width
= pcm
->width
;
8206 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8207 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8208 width
+= pcm
->width
;
8209 fontp
->average_width
= width
/ 95;
8212 fontp
->average_width
= FONT_WIDTH (font
);
8215 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8216 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8218 fontp
->size
= font
->max_bounds
.width
;
8219 fontp
->height
= FONT_HEIGHT (font
);
8221 /* For some font, ascent and descent in max_bounds field is
8222 larger than the above value. */
8223 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8224 if (max_height
> fontp
->height
)
8225 fontp
->height
= max_height
;
8228 /* The slot `encoding' specifies how to map a character
8229 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8230 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8231 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8232 2:0xA020..0xFF7F). For the moment, we don't know which charset
8233 uses this font. So, we set information in fontp->encoding[1]
8234 which is never used by any charset. If mapping can't be
8235 decided, set FONT_ENCODING_NOT_DECIDED. */
8236 if (font
->mac_scriptcode
== smJapanese
)
8237 fontp
->encoding
[1] = 4;
8241 = (font
->max_byte1
== 0
8243 ? (font
->min_char_or_byte2
< 0x80
8244 ? (font
->max_char_or_byte2
< 0x80
8245 ? 0 /* 0x20..0x7F */
8246 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8247 : 1) /* 0xA0..0xFF */
8249 : (font
->min_byte1
< 0x80
8250 ? (font
->max_byte1
< 0x80
8251 ? (font
->min_char_or_byte2
< 0x80
8252 ? (font
->max_char_or_byte2
< 0x80
8253 ? 0 /* 0x2020..0x7F7F */
8254 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8255 : 3) /* 0x20A0..0x7FFF */
8256 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8257 : (font
->min_char_or_byte2
< 0x80
8258 ? (font
->max_char_or_byte2
< 0x80
8259 ? 2 /* 0xA020..0xFF7F */
8260 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8261 : 1))); /* 0xA0A0..0xFFFF */
8264 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8265 fontp
->baseline_offset
8266 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8267 ? (long) value
: 0);
8268 fontp
->relative_compose
8269 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8270 ? (long) value
: 0);
8271 fontp
->default_ascent
8272 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8273 ? (long) value
: 0);
8275 fontp
->baseline_offset
= 0;
8276 fontp
->relative_compose
= 0;
8277 fontp
->default_ascent
= 0;
8280 /* Set global flag fonts_changed_p to non-zero if the font loaded
8281 has a character with a smaller width than any other character
8282 before, or if the font loaded has a smaller height than any
8283 other font loaded before. If this happens, it will make a
8284 glyph matrix reallocation necessary. */
8285 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8292 /* Return a pointer to struct font_info of a font named FONTNAME for
8293 frame F. If no such font is loaded, return NULL. */
8296 x_query_font (f
, fontname
)
8298 register char *fontname
;
8300 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8303 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8304 if (dpyinfo
->font_table
[i
].name
8305 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8306 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8307 return (dpyinfo
->font_table
+ i
);
8312 /* Find a CCL program for a font specified by FONTP, and set the member
8313 `encoder' of the structure. */
8316 x_find_ccl_program (fontp
)
8317 struct font_info
*fontp
;
8319 Lisp_Object list
, elt
;
8321 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8325 && STRINGP (XCAR (elt
))
8326 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8332 struct ccl_program
*ccl
8333 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8335 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8338 fontp
->font_encoder
= ccl
;
8342 #if USE_MAC_FONT_PANEL
8343 /* Whether Font Panel has been shown before. The first call to font
8344 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8345 slow. This variable is used for deferring such a call as much as
8347 static int font_panel_shown_p
= 0;
8350 mac_font_panel_visible_p ()
8352 return font_panel_shown_p
&& FPIsFontPanelVisible ();
8356 mac_show_hide_font_panel ()
8358 font_panel_shown_p
= 1;
8360 return FPShowHideFontPanel ();
8364 mac_set_font_info_for_selection (f
, face_id
, c
)
8369 EventTargetRef target
= NULL
;
8370 XFontStruct
*font
= NULL
;
8372 if (!mac_font_panel_visible_p ())
8377 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
8379 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
8383 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
8384 face
= FACE_FROM_ID (f
, face_id
);
8390 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
8393 if (font
->mac_fontnum
!= -1)
8395 FontSelectionQDStyle qd_style
;
8397 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
8398 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
8399 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
8400 qd_style
.size
= font
->mac_fontsize
;
8401 qd_style
.hasColor
= false;
8403 err
= SetFontInfoForSelection (kFontSelectionQDType
,
8404 1, &qd_style
, target
);
8407 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
8408 1, &font
->mac_style
, target
);
8416 /* The Mac Event loop code */
8418 #if !TARGET_API_MAC_CARBON
8420 #include <Quickdraw.h>
8421 #include <Balloons.h>
8422 #include <Devices.h>
8424 #include <Gestalt.h>
8426 #include <Processes.h>
8428 #include <ToolUtils.h>
8429 #include <TextUtils.h>
8430 #include <Dialogs.h>
8433 #include <Resources.h>
8438 #endif /* ! TARGET_API_MAC_CARBON */
8443 #define WINDOW_RESOURCE 128
8444 #define TERM_WINDOW_RESOURCE 129
8446 #define DEFAULT_NUM_COLS 80
8448 #define MIN_DOC_SIZE 64
8449 #define MAX_DOC_SIZE 32767
8451 #define EXTRA_STACK_ALLOC (256 * 1024)
8453 #define ARGV_STRING_LIST_ID 129
8454 #define ABOUT_ALERT_ID 128
8455 #define RAM_TOO_LARGE_ALERT_ID 129
8457 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8458 Lisp_Object Qreverse
;
8461 /* Modifier associated with the control key, or nil to ignore. */
8462 Lisp_Object Vmac_control_modifier
;
8464 /* Modifier associated with the option key, or nil to ignore. */
8465 Lisp_Object Vmac_option_modifier
;
8467 /* Modifier associated with the command key, or nil to ignore. */
8468 Lisp_Object Vmac_command_modifier
;
8470 /* Modifier associated with the function key, or nil to ignore. */
8471 Lisp_Object Vmac_function_modifier
;
8473 /* True if the option and command modifiers should be used to emulate
8474 a three button mouse */
8475 Lisp_Object Vmac_emulate_three_button_mouse
;
8477 #if USE_CARBON_EVENTS
8478 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8479 mouse-2, instead of mouse-3. */
8480 int mac_wheel_button_is_mouse_2
;
8482 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8483 for processing before Emacs sees it. */
8484 int mac_pass_command_to_system
;
8486 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8487 for processing before Emacs sees it. */
8488 int mac_pass_control_to_system
;
8491 /* Points to the variable `inev' in the function XTread_socket. It is
8492 used for passing an input event to the function back from
8493 Carbon/Apple event handlers. */
8494 static struct input_event
*read_socket_inev
= NULL
;
8496 Point saved_menu_event_location
;
8499 #if USE_CARBON_EVENTS
8500 static Lisp_Object Qhicommand
;
8502 extern Lisp_Object Qwindow
;
8503 static Lisp_Object Qtoolbar_switch_mode
;
8505 #if USE_MAC_FONT_PANEL
8506 extern Lisp_Object Qfont
;
8507 static Lisp_Object Qpanel_closed
, Qselection
;
8510 static TSMDocumentID tsm_document_id
;
8511 static Lisp_Object Qtext_input
;
8512 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8513 static Lisp_Object Vmac_ts_active_input_overlay
;
8514 extern Lisp_Object Qbefore_string
;
8517 extern int mac_ready_for_apple_events
;
8518 extern Lisp_Object Qundefined
;
8519 extern void init_apple_event_handler
P_ ((void));
8520 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8521 Lisp_Object
*, Lisp_Object
*,
8523 extern OSErr init_coercion_handler
P_ ((void));
8526 OSErr install_drag_handler
P_ ((WindowRef
));
8527 void remove_drag_handler
P_ ((WindowRef
));
8529 #if USE_CARBON_EVENTS
8531 extern void init_service_handler ();
8532 static Lisp_Object Qservice
, Qpaste
, Qperform
;
8534 /* Window Event Handler */
8535 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8538 OSErr
install_window_handler (WindowPtr
);
8540 extern void init_emacs_passwd_dir ();
8541 extern int emacs_main (int, char **, char **);
8543 extern void initialize_applescript();
8544 extern void terminate_applescript();
8547 #if USE_CARBON_EVENTS
8548 mac_to_emacs_modifiers (UInt32 mods
)
8550 mac_to_emacs_modifiers (EventModifiers mods
)
8553 unsigned int result
= 0;
8554 if (mods
& shiftKey
)
8555 result
|= shift_modifier
;
8557 /* Deactivated to simplify configuration:
8558 if Vmac_option_modifier is non-NIL, we fully process the Option
8559 key. Otherwise, we only process it if an additional Ctrl or Command
8560 is pressed. That way the system may convert the character to a
8562 if ((mods & optionKey) &&
8563 (( !NILP(Vmac_option_modifier) ||
8564 ((mods & cmdKey) || (mods & controlKey))))) */
8566 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8567 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8569 result
|= XUINT(val
);
8571 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8572 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8574 result
|= XUINT(val
);
8576 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8577 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8579 result
|= XUINT(val
);
8583 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8584 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8586 result
|= XUINT(val
);
8594 mac_get_emulated_btn ( UInt32 modifiers
)
8597 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8598 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8599 if (modifiers
& cmdKey
)
8600 result
= cmdIs3
? 2 : 1;
8601 else if (modifiers
& optionKey
)
8602 result
= cmdIs3
? 1 : 2;
8607 #if USE_CARBON_EVENTS
8608 /* Obtains the event modifiers from the event ref and then calls
8609 mac_to_emacs_modifiers. */
8611 mac_event_to_emacs_modifiers (EventRef eventRef
)
8614 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8615 sizeof (UInt32
), NULL
, &mods
);
8616 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8617 GetEventClass(eventRef
) == kEventClassMouse
)
8619 mods
&= ~(optionKey
| cmdKey
);
8621 return mac_to_emacs_modifiers (mods
);
8624 /* Given an event ref, return the code to use for the mouse button
8625 code in the emacs input_event. */
8627 mac_get_mouse_btn (EventRef ref
)
8629 EventMouseButton result
= kEventMouseButtonPrimary
;
8630 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8631 sizeof (EventMouseButton
), NULL
, &result
);
8634 case kEventMouseButtonPrimary
:
8635 if (NILP (Vmac_emulate_three_button_mouse
))
8639 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8640 sizeof (UInt32
), NULL
, &mods
);
8641 return mac_get_emulated_btn(mods
);
8643 case kEventMouseButtonSecondary
:
8644 return mac_wheel_button_is_mouse_2
? 2 : 1;
8645 case kEventMouseButtonTertiary
:
8646 case 4: /* 4 is the number for the mouse wheel button */
8647 return mac_wheel_button_is_mouse_2
? 1 : 2;
8653 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8654 events. However the click of the mouse wheel is not converted to a
8655 mouseDown or mouseUp event. Likewise for dead key down events.
8656 This calls ConvertEventRef, but then checks to see if it is a mouse
8657 up/down, or a dead key down carbon event that has not been
8658 converted, and if so, converts it by hand (to be picked up in the
8659 XTread_socket loop). */
8660 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8663 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8668 switch (GetEventClass (eventRef
))
8670 case kEventClassMouse
:
8671 switch (GetEventKind (eventRef
))
8673 case kEventMouseDown
:
8674 eventRec
->what
= mouseDown
;
8679 eventRec
->what
= mouseUp
;
8688 case kEventClassKeyboard
:
8689 switch (GetEventKind (eventRef
))
8691 case kEventRawKeyDown
:
8693 unsigned char char_codes
;
8696 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
8697 typeChar
, NULL
, sizeof (char),
8700 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
8701 typeUInt32
, NULL
, sizeof (UInt32
),
8705 eventRec
->what
= keyDown
;
8706 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8723 /* Need where and when. */
8726 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8727 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8728 /* Use two step process because new event modifiers are 32-bit
8729 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8730 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8731 NULL
, sizeof (UInt32
), NULL
, &mods
);
8732 eventRec
->modifiers
= mods
;
8734 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8746 Handle menubar_handle
;
8747 MenuHandle menu_handle
;
8749 menubar_handle
= GetNewMBar (128);
8750 if(menubar_handle
== NULL
)
8752 SetMenuBar (menubar_handle
);
8755 #if !TARGET_API_MAC_CARBON
8756 menu_handle
= GetMenuHandle (M_APPLE
);
8757 if(menu_handle
!= NULL
)
8758 AppendResMenu (menu_handle
,'DRVR');
8766 do_init_managers (void)
8768 #if !TARGET_API_MAC_CARBON
8769 InitGraf (&qd
.thePort
);
8771 FlushEvents (everyEvent
, 0);
8776 #endif /* !TARGET_API_MAC_CARBON */
8779 #if !TARGET_API_MAC_CARBON
8780 /* set up some extra stack space for use by emacs */
8781 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8783 /* MaxApplZone must be called for AppleScript to execute more
8784 complicated scripts */
8787 #endif /* !TARGET_API_MAC_CARBON */
8791 do_check_ram_size (void)
8793 SInt32 physical_ram_size
, logical_ram_size
;
8795 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8796 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8797 || physical_ram_size
> (1 << VALBITS
)
8798 || logical_ram_size
> (1 << VALBITS
))
8800 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8804 #endif /* MAC_OS8 */
8807 do_window_update (WindowPtr win
)
8809 struct frame
*f
= mac_window_to_frame (win
);
8813 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8815 if (win
!= tip_window
)
8817 if (f
->async_visible
== 0)
8819 /* Update events may occur when a frame gets iconified. */
8821 f
->async_visible
= 1;
8822 f
->async_iconified
= 0;
8823 SET_FRAME_GARBAGED (f
);
8829 #if TARGET_API_MAC_CARBON
8830 RgnHandle region
= NewRgn ();
8832 GetPortVisibleRegion (GetWindowPort (win
), region
);
8833 GetRegionBounds (region
, &r
);
8834 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8835 UpdateControls (win
, region
);
8836 DisposeRgn (region
);
8838 r
= (*win
->visRgn
)->rgnBBox
;
8839 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8840 UpdateControls (win
, win
->visRgn
);
8849 is_emacs_window (WindowPtr win
)
8851 Lisp_Object tail
, frame
;
8856 FOR_EACH_FRAME (tail
, frame
)
8857 if (FRAME_MAC_P (XFRAME (frame
)))
8858 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8868 ActivateTSMDocument (tsm_document_id
);
8876 DeactivateTSMDocument (tsm_document_id
);
8882 do_apple_menu (SInt16 menu_item
)
8884 #if !TARGET_API_MAC_CARBON
8886 SInt16 da_driver_refnum
;
8888 if (menu_item
== I_ABOUT
)
8889 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8892 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8893 da_driver_refnum
= OpenDeskAcc (item_name
);
8895 #endif /* !TARGET_API_MAC_CARBON */
8899 do_menu_choice (SInt32 menu_choice
)
8901 SInt16 menu_id
, menu_item
;
8903 menu_id
= HiWord (menu_choice
);
8904 menu_item
= LoWord (menu_choice
);
8912 do_apple_menu (menu_item
);
8917 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8918 MenuHandle menu
= GetMenuHandle (menu_id
);
8923 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8924 menubar_selection_callback (f
, refcon
);
8933 /* Handle drags in size box. Based on code contributed by Ben
8934 Mesander and IM - Window Manager A. */
8937 do_grow_window (WindowPtr w
, EventRecord
*e
)
8940 int rows
, columns
, width
, height
;
8941 struct frame
*f
= mac_window_to_frame (w
);
8942 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8943 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8944 #if TARGET_API_MAC_CARBON
8950 if (size_hints
->flags
& PMinSize
)
8952 min_width
= size_hints
->min_width
;
8953 min_height
= size_hints
->min_height
;
8955 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8957 #if TARGET_API_MAC_CARBON
8958 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8960 height
= new_rect
.bottom
- new_rect
.top
;
8961 width
= new_rect
.right
- new_rect
.left
;
8963 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8964 /* see if it really changed size */
8967 height
= HiWord (grow_size
);
8968 width
= LoWord (grow_size
);
8971 if (width
!= FRAME_PIXEL_WIDTH (f
)
8972 || height
!= FRAME_PIXEL_HEIGHT (f
))
8974 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8975 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8977 x_set_window_size (f
, 0, columns
, rows
);
8982 /* Handle clicks in zoom box. Calculation of "standard state" based
8983 on code in IM - Window Manager A and code contributed by Ben
8984 Mesander. The standard state of an Emacs window is 80-characters
8985 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8988 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8990 Rect zoom_rect
, port_rect
;
8991 int columns
, rows
, width
, height
;
8992 struct frame
*f
= mac_window_to_frame (w
);
8993 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8994 #if TARGET_API_MAC_CARBON
8995 Point standard_size
;
8997 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8998 standard_size
.v
= dpyinfo
->height
;
9000 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
9001 zoom_in_or_out
= inZoomIn
;
9004 /* Adjust the standard size according to character boundaries. */
9006 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
9007 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9008 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
9009 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9010 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
9011 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
9012 && port_rect
.left
== zoom_rect
.left
9013 && port_rect
.top
== zoom_rect
.top
)
9014 zoom_in_or_out
= inZoomIn
;
9016 zoom_in_or_out
= inZoomOut
;
9019 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
9020 #else /* not TARGET_API_MAC_CARBON */
9025 GetPort (&save_port
);
9027 SetPortWindowPort (w
);
9029 /* Clear window to avoid flicker. */
9030 EraseRect (&(w
->portRect
));
9031 if (zoom_in_or_out
== inZoomOut
)
9033 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9034 LocalToGlobal (&top_left
);
9036 /* calculate height of window's title bar */
9037 w_title_height
= top_left
.v
- 1
9038 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9040 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9041 zoom_rect
= qd
.screenBits
.bounds
;
9042 zoom_rect
.top
+= w_title_height
;
9043 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9045 zoom_rect
.right
= zoom_rect
.left
9046 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9048 /* Adjust the standard size according to character boundaries. */
9049 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9051 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9053 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9057 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
9059 SetPort (save_port
);
9060 #endif /* not TARGET_API_MAC_CARBON */
9062 /* retrieve window size and update application values */
9063 #if TARGET_API_MAC_CARBON
9064 GetWindowPortBounds (w
, &port_rect
);
9066 port_rect
= w
->portRect
;
9068 height
= port_rect
.bottom
- port_rect
.top
;
9069 width
= port_rect
.right
- port_rect
.left
;
9071 if (width
!= FRAME_PIXEL_WIDTH (f
)
9072 || height
!= FRAME_PIXEL_HEIGHT (f
))
9074 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9075 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9077 change_frame_size (f
, rows
, columns
, 0, 1, 0);
9078 SET_FRAME_GARBAGED (f
);
9079 cancel_mouse_face (f
);
9081 FRAME_PIXEL_WIDTH (f
) = width
;
9082 FRAME_PIXEL_HEIGHT (f
) = height
;
9084 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9088 mac_store_apple_event (class, id
, desc
)
9089 Lisp_Object
class, id
;
9092 struct input_event buf
;
9096 buf
.kind
= MAC_APPLE_EVENT
;
9099 XSETFRAME (buf
.frame_or_window
,
9100 mac_focus_frame (&one_mac_display_info
));
9101 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9102 is safe to use them during read_socket_hook. */
9103 buf
.arg
= mac_aedesc_to_lisp (desc
);
9104 kbd_buffer_store_event (&buf
);
9107 #if TARGET_API_MAC_CARBON
9109 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
9110 event
, num_params
, names
, types
)
9113 Lisp_Object class_key
, id_key
;
9116 EventParamName
*names
;
9117 EventParamType
*types
;
9119 OSStatus err
= eventNotHandledErr
;
9120 Lisp_Object binding
;
9122 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
9123 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9125 if (INTEGERP (binding
))
9126 err
= XINT (binding
);
9129 AppleEvent apple_event
;
9130 err
= create_apple_event_from_event_ref (event
, num_params
,
9135 mac_store_apple_event (class_key
, id_key
, &apple_event
);
9136 AEDisposeDesc (&apple_event
);
9137 /* Post a harmless event so as to wake up from
9138 ReceiveNextEvent. */
9139 mac_post_mouse_moved_event ();
9148 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
9154 struct input_event buf
;
9158 buf
.kind
= DRAG_N_DROP_EVENT
;
9159 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9160 buf
.timestamp
= TickCount () * (1000 / 60);
9161 XSETINT (buf
.x
, mouse_pos
.h
);
9162 XSETINT (buf
.y
, mouse_pos
.v
);
9163 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
9164 buf
.arg
= mac_aedesc_to_lisp (desc
);
9165 kbd_buffer_store_event (&buf
);
9169 #if USE_CARBON_EVENTS
9170 static pascal OSStatus
9171 mac_handle_command_event (next_handler
, event
, data
)
9172 EventHandlerCallRef next_handler
;
9176 OSStatus result
, err
;
9178 static EventParamName names
[] = {kEventParamDirectObject
,
9179 kEventParamKeyModifiers
};
9180 static EventParamType types
[] = {typeHICommand
,
9182 int num_params
= sizeof (names
) / sizeof (names
[0]);
9184 result
= CallNextEventHandler (next_handler
, event
);
9185 if (result
!= eventNotHandledErr
)
9188 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9189 NULL
, sizeof (HICommand
), NULL
, &command
);
9191 if (err
!= noErr
|| command
.commandID
== 0)
9192 return eventNotHandledErr
;
9194 /* A HICommand event is mapped to an Apple event whose event class
9195 symbol is `hicommand' and event ID is its command ID. */
9196 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
9198 event
, num_params
, names
, types
);
9199 return err
== noErr
? noErr
: eventNotHandledErr
;
9203 init_command_handler ()
9205 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
9206 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9208 if (handle_command_eventUPP
== NULL
)
9209 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9210 return InstallApplicationEventHandler (handle_command_eventUPP
,
9211 GetEventTypeCount (specs
), specs
,
9215 static pascal OSStatus
9216 mac_handle_window_event (next_handler
, event
, data
)
9217 EventHandlerCallRef next_handler
;
9222 OSStatus result
, err
;
9224 XSizeHints
*size_hints
;
9226 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9227 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9229 return eventNotHandledErr
;
9231 switch (GetEventKind (event
))
9233 case kEventWindowUpdate
:
9234 result
= CallNextEventHandler (next_handler
, event
);
9235 if (result
!= eventNotHandledErr
)
9238 do_window_update (wp
);
9241 case kEventWindowBoundsChanging
:
9242 result
= CallNextEventHandler (next_handler
, event
);
9243 if (result
!= eventNotHandledErr
)
9246 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9247 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9251 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
9252 if ((attributes
& kWindowBoundsChangeUserResize
)
9253 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9254 == (PResizeInc
| PBaseSize
| PMinSize
)))
9259 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9260 typeQDRectangle
, NULL
, sizeof (Rect
),
9265 width
= bounds
.right
- bounds
.left
;
9266 height
= bounds
.bottom
- bounds
.top
;
9268 if (width
< size_hints
->min_width
)
9269 width
= size_hints
->min_width
;
9271 width
= size_hints
->base_width
9272 + (int) ((width
- size_hints
->base_width
)
9273 / (float) size_hints
->width_inc
+ .5)
9274 * size_hints
->width_inc
;
9276 if (height
< size_hints
->min_height
)
9277 height
= size_hints
->min_height
;
9279 height
= size_hints
->base_height
9280 + (int) ((height
- size_hints
->base_height
)
9281 / (float) size_hints
->height_inc
+ .5)
9282 * size_hints
->height_inc
;
9284 bounds
.right
= bounds
.left
+ width
;
9285 bounds
.bottom
= bounds
.top
+ height
;
9286 SetEventParameter (event
, kEventParamCurrentBounds
,
9287 typeQDRectangle
, sizeof (Rect
), &bounds
);
9292 case kEventWindowShown
:
9293 case kEventWindowHidden
:
9294 case kEventWindowExpanded
:
9295 case kEventWindowCollapsed
:
9296 result
= CallNextEventHandler (next_handler
, event
);
9298 mac_handle_visibility_change (mac_window_to_frame (wp
));
9304 case kEventWindowToolbarSwitchMode
:
9305 result
= CallNextEventHandler (next_handler
, event
);
9307 static EventParamName names
[] = {kEventParamDirectObject
,
9308 kEventParamWindowMouseLocation
,
9309 kEventParamKeyModifiers
,
9310 kEventParamMouseButton
,
9311 kEventParamClickCount
,
9312 kEventParamMouseChord
};
9313 static EventParamType types
[] = {typeWindowRef
,
9319 int num_params
= sizeof (names
) / sizeof (names
[0]);
9321 err
= mac_store_event_ref_as_apple_event (0, 0,
9323 Qtoolbar_switch_mode
,
9327 return err
== noErr
? noErr
: result
;
9331 case kEventWindowFocusAcquired
:
9332 result
= CallNextEventHandler (next_handler
, event
);
9333 err
= ActivateTSMDocument (tsm_document_id
);
9334 return err
== noErr
? noErr
: result
;
9336 case kEventWindowFocusRelinquish
:
9337 result
= CallNextEventHandler (next_handler
, event
);
9338 err
= DeactivateTSMDocument (tsm_document_id
);
9339 return err
== noErr
? noErr
: result
;
9343 return eventNotHandledErr
;
9346 static pascal OSStatus
9347 mac_handle_mouse_event (next_handler
, event
, data
)
9348 EventHandlerCallRef next_handler
;
9352 OSStatus result
, err
;
9354 switch (GetEventKind (event
))
9356 case kEventMouseWheelMoved
:
9360 EventMouseWheelAxis axis
;
9364 result
= CallNextEventHandler (next_handler
, event
);
9365 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9368 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9369 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9373 f
= mac_window_to_frame (wp
);
9374 if (f
!= mac_focus_frame (&one_mac_display_info
))
9377 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
9378 typeMouseWheelAxis
, NULL
,
9379 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9380 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
9383 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
9384 typeSInt32
, NULL
, sizeof (SInt32
),
9388 err
= GetEventParameter (event
, kEventParamMouseLocation
,
9389 typeQDPoint
, NULL
, sizeof (Point
),
9393 read_socket_inev
->kind
= WHEEL_EVENT
;
9394 read_socket_inev
->code
= 0;
9395 read_socket_inev
->modifiers
=
9396 (mac_event_to_emacs_modifiers (event
)
9397 | ((delta
< 0) ? down_modifier
: up_modifier
));
9398 SetPortWindowPort (wp
);
9399 GlobalToLocal (&point
);
9400 XSETINT (read_socket_inev
->x
, point
.h
);
9401 XSETINT (read_socket_inev
->y
, point
.v
);
9402 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9412 return eventNotHandledErr
;
9415 #if USE_MAC_FONT_PANEL
9416 static pascal OSStatus
9417 mac_handle_font_event (next_handler
, event
, data
)
9418 EventHandlerCallRef next_handler
;
9422 OSStatus result
, err
;
9425 EventParamName
*names
;
9426 EventParamType
*types
;
9427 static EventParamName names_sel
[] = {kEventParamATSUFontID
,
9428 kEventParamATSUFontSize
,
9429 kEventParamFMFontFamily
,
9430 kEventParamFMFontSize
,
9431 kEventParamFontColor
};
9432 static EventParamType types_sel
[] = {typeATSUFontID
,
9438 result
= CallNextEventHandler (next_handler
, event
);
9439 if (result
!= eventNotHandledErr
)
9442 switch (GetEventKind (event
))
9444 case kEventFontPanelClosed
:
9445 id_key
= Qpanel_closed
;
9451 case kEventFontSelection
:
9452 id_key
= Qselection
;
9453 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9459 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9463 return err
== noErr
? noErr
: eventNotHandledErr
;
9468 static pascal OSStatus
9469 mac_handle_text_input_event (next_handler
, event
, data
)
9470 EventHandlerCallRef next_handler
;
9474 OSStatus result
, err
= noErr
;
9475 Lisp_Object id_key
= Qnil
;
9477 EventParamName
*names
;
9478 EventParamType
*types
;
9479 static UInt32 seqno_uaia
= 0;
9480 static EventParamName names_uaia
[] =
9481 {kEventParamTextInputSendComponentInstance
,
9482 kEventParamTextInputSendRefCon
,
9483 kEventParamTextInputSendSLRec
,
9484 kEventParamTextInputSendFixLen
,
9485 kEventParamTextInputSendText
,
9486 kEventParamTextInputSendUpdateRng
,
9487 kEventParamTextInputSendHiliteRng
,
9488 kEventParamTextInputSendClauseRng
,
9489 kEventParamTextInputSendPinRng
,
9490 kEventParamTextInputSendTextServiceEncoding
,
9491 kEventParamTextInputSendTextServiceMacEncoding
,
9492 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
9493 static EventParamType types_uaia
[] =
9494 {typeComponentInstance
,
9496 typeIntlWritingCode
,
9506 static EventParamName names_ufke
[] =
9507 {kEventParamTextInputSendComponentInstance
,
9508 kEventParamTextInputSendRefCon
,
9509 kEventParamTextInputSendSLRec
,
9510 kEventParamTextInputSendText
};
9511 static EventParamType types_ufke
[] =
9512 {typeComponentInstance
,
9514 typeIntlWritingCode
,
9517 result
= CallNextEventHandler (next_handler
, event
);
9519 switch (GetEventKind (event
))
9521 case kEventTextInputUpdateActiveInputArea
:
9522 id_key
= Qupdate_active_input_area
;
9523 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
9526 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
9527 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
9531 case kEventTextInputUnicodeForKeyEvent
:
9534 UInt32 actual_size
, modifiers
, mapped_modifiers
;
9537 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
9538 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
9541 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
9543 sizeof (UInt32
), NULL
, &modifiers
);
9547 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9548 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9549 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9552 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9554 if (modifiers
& mapped_modifiers
)
9555 /* There're mapped modifier keys. Process it in
9557 return eventNotHandledErr
;
9560 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
9561 typeUnicodeText
, NULL
, 0, &actual_size
,
9565 if (actual_size
== sizeof (UniChar
))
9566 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
9567 typeUnicodeText
, NULL
,
9568 sizeof (UniChar
), NULL
, &code
);
9569 if (err
== noErr
&& code
< 0x80)
9571 /* ASCII character. Process it in XTread_socket. */
9572 if (read_socket_inev
&& code
>= 0x20)
9574 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
9576 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
9577 read_socket_inev
->code
= code
;
9578 read_socket_inev
->modifiers
=
9579 (extra_keyboard_modifiers
9580 & (meta_modifier
| alt_modifier
9581 | hyper_modifier
| super_modifier
));
9582 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9584 return eventNotHandledErr
;
9588 /* Non-ASCII keystrokes without mapped modifiers are processed
9589 at the Lisp level. */
9590 id_key
= Qunicode_for_key_event
;
9591 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
9596 case kEventTextInputOffsetToPos
:
9602 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
9603 return eventNotHandledErr
;
9605 /* Strictly speaking, this is not always correct because
9606 previous events may change some states about display. */
9607 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
9609 /* Active input area is displayed in the echo area. */
9610 w
= XWINDOW (echo_area_window
);
9611 f
= WINDOW_XFRAME (w
);
9615 /* Active input area is displayed around the current point. */
9616 f
= SELECTED_FRAME ();
9617 w
= XWINDOW (f
->selected_window
);
9620 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
9621 + WINDOW_LEFT_FRINGE_WIDTH (w
));
9622 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
9623 + FONT_BASE (FRAME_FONT (f
)));
9624 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
9626 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
9627 typeQDPoint
, sizeof (typeQDPoint
), &p
);
9636 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
9640 return err
== noErr
? noErr
: result
;
9646 mac_store_service_event (event
)
9652 EventParamName
*names
;
9653 EventParamType
*types
;
9654 static EventParamName names_pfm
[] = {kEventParamServiceMessageName
,
9655 kEventParamServiceUserData
};
9656 static EventParamType types_pfm
[] = {typeCFStringRef
,
9659 switch (GetEventKind (event
))
9661 case kEventServicePaste
:
9668 case kEventServicePerform
:
9670 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
9679 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
9685 #endif /* MAC_OSX */
9686 #endif /* USE_CARBON_EVENTS */
9690 install_window_handler (window
)
9694 #if USE_CARBON_EVENTS
9695 EventTypeSpec specs_window
[] =
9696 {{kEventClassWindow
, kEventWindowUpdate
},
9697 {kEventClassWindow
, kEventWindowBoundsChanging
},
9698 {kEventClassWindow
, kEventWindowShown
},
9699 {kEventClassWindow
, kEventWindowHidden
},
9700 {kEventClassWindow
, kEventWindowExpanded
},
9701 {kEventClassWindow
, kEventWindowCollapsed
},
9703 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
9706 {kEventClassWindow
, kEventWindowFocusAcquired
},
9707 {kEventClassWindow
, kEventWindowFocusRelinquish
},
9710 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9711 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9712 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9713 #if USE_MAC_FONT_PANEL
9714 EventTypeSpec specs_font
[] = {{kEventClassFont
, kEventFontPanelClosed
},
9715 {kEventClassFont
, kEventFontSelection
}};
9716 static EventHandlerUPP handle_font_eventUPP
= NULL
;
9719 EventTypeSpec specs_text_input
[] =
9720 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
9721 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
9722 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
9723 static EventHandlerUPP handle_text_input_eventUPP
= NULL
;
9726 if (handle_window_eventUPP
== NULL
)
9727 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9728 if (handle_mouse_eventUPP
== NULL
)
9729 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9730 #if USE_MAC_FONT_PANEL
9731 if (handle_font_eventUPP
== NULL
)
9732 handle_font_eventUPP
= NewEventHandlerUPP (mac_handle_font_event
);
9735 if (handle_text_input_eventUPP
== NULL
)
9736 handle_text_input_eventUPP
=
9737 NewEventHandlerUPP (mac_handle_text_input_event
);
9739 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9740 GetEventTypeCount (specs_window
),
9741 specs_window
, NULL
, NULL
);
9743 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9744 GetEventTypeCount (specs_mouse
),
9745 specs_mouse
, NULL
, NULL
);
9746 #if USE_MAC_FONT_PANEL
9748 err
= InstallWindowEventHandler (window
, handle_font_eventUPP
,
9749 GetEventTypeCount (specs_font
),
9750 specs_font
, NULL
, NULL
);
9754 err
= InstallWindowEventHandler (window
, handle_text_input_eventUPP
,
9755 GetEventTypeCount (specs_text_input
),
9756 specs_text_input
, window
, NULL
);
9760 err
= install_drag_handler (window
);
9766 remove_window_handler (window
)
9769 remove_drag_handler (window
);
9775 profiler_exit_proc ()
9777 ProfilerDump ("\pEmacs.prof");
9782 /* These few functions implement Emacs as a normal Mac application
9783 (almost): set up the heap and the Toolbox, handle necessary system
9784 events plus a few simple menu events. They also set up Emacs's
9785 access to functions defined in the rest of this file. Emacs uses
9786 function hooks to perform all its terminal I/O. A complete list of
9787 these functions appear in termhooks.h. For what they do, read the
9788 comments there and see also w32term.c and xterm.c. What's
9789 noticeably missing here is the event loop, which is normally
9790 present in most Mac application. After performing the necessary
9791 Mac initializations, main passes off control to emacs_main
9792 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9793 (defined further below) to read input. This is where
9794 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9801 #if __profile__ /* is the profiler on? */
9802 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9807 /* set creator and type for files created by MSL */
9812 do_init_managers ();
9817 do_check_ram_size ();
9820 init_emacs_passwd_dir ();
9824 init_coercion_handler ();
9826 initialize_applescript ();
9828 init_apple_event_handler ();
9834 /* set up argv array from STR# resource */
9835 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9839 /* free up AppleScript resources on exit */
9840 atexit (terminate_applescript
);
9842 #if __profile__ /* is the profiler on? */
9843 atexit (profiler_exit_proc
);
9846 /* 3rd param "envp" never used in emacs_main */
9847 (void) emacs_main (argc
, argv
, 0);
9850 /* Never reached - real exit in Fkill_emacs */
9855 /* Table for translating Mac keycode to X keysym values. Contributed
9857 Mapping for special keys is now identical to that in Apple X11
9858 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9859 on the right of the Cmd key on laptops, and fn + `enter' (->
9861 static unsigned char keycode_to_xkeysym_table
[] = {
9862 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9863 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9864 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9866 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9867 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9868 /*0x38*/ 0, 0, 0, 0,
9869 /*0x3C*/ 0, 0, 0, 0,
9871 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9872 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9873 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9874 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9876 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9877 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9878 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9879 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9881 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9882 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9883 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9884 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9886 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9887 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9888 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9889 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9894 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9896 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9897 return *xKeySym
!= 0;
9901 /* Table for translating Mac keycode with the laptop `fn' key to that
9902 without it. Destination symbols in comments are keys on US
9903 keyboard, and they may not be the same on other types of keyboards.
9904 If the destination is identical to the source (f1 ... f12), it
9905 doesn't map `fn' key to a modifier. */
9906 static unsigned char fn_keycode_to_keycode_table
[] = {
9907 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9908 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9909 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9911 /*0x30*/ 0, 0, 0, 0,
9912 /*0x34*/ 0, 0, 0, 0,
9913 /*0x38*/ 0, 0, 0, 0,
9914 /*0x3C*/ 0, 0, 0, 0,
9916 /*0x40*/ 0, 0x2f /*kp-. -> '.'*/, 0, 0x23 /*kp-* -> 'p'*/,
9917 /*0x44*/ 0, 0x2c /*kp-+ -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9918 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9919 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-- -> ';'*/, 0,
9921 /*0x50*/ 0, 0x1b /*kp-= -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9922 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9923 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9924 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9926 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9927 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9928 /*0x68*/ 0, 0, 0, 0,
9929 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9931 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9932 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9933 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9936 #endif /* MAC_OSX */
9938 #if !USE_CARBON_EVENTS
9939 static RgnHandle mouse_region
= NULL
;
9942 mac_wait_next_event (er
, sleep_time
, dequeue
)
9947 static EventRecord er_buf
= {nullEvent
};
9948 UInt32 target_tick
, current_tick
;
9949 EventMask event_mask
;
9951 if (mouse_region
== NULL
)
9952 mouse_region
= NewRgn ();
9954 event_mask
= everyEvent
;
9955 if (!mac_ready_for_apple_events
)
9956 event_mask
-= highLevelEventMask
;
9958 current_tick
= TickCount ();
9959 target_tick
= current_tick
+ sleep_time
;
9961 if (er_buf
.what
== nullEvent
)
9962 while (!WaitNextEvent (event_mask
, &er_buf
,
9963 target_tick
- current_tick
, mouse_region
))
9965 current_tick
= TickCount ();
9966 if (target_tick
<= current_tick
)
9972 er_buf
.what
= nullEvent
;
9975 #endif /* not USE_CARBON_EVENTS */
9977 #if TARGET_API_MAC_CARBON
9979 mac_post_mouse_moved_event ()
9981 EventRef event
= NULL
;
9984 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
9985 kEventAttributeNone
, &event
);
9990 GetMouse (&mouse_pos
);
9991 LocalToGlobal (&mouse_pos
);
9992 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
9993 sizeof (Point
), &mouse_pos
);
9997 UInt32 modifiers
= GetCurrentKeyModifiers ();
9999 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
10000 sizeof (UInt32
), &modifiers
);
10003 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
10004 kEventPriorityStandard
);
10006 ReleaseEvent (event
);
10012 mac_set_unicode_keystroke_event (code
, buf
)
10014 struct input_event
*buf
;
10016 int charset_id
, c1
, c2
;
10020 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10023 else if (code
< 0x100)
10026 charset_id
= CHARSET_8_BIT_CONTROL
;
10028 charset_id
= charset_latin_iso8859_1
;
10029 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10030 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10035 charset_id
= charset_mule_unicode_0100_24ff
,
10037 else if (code
< 0x33FF)
10038 charset_id
= charset_mule_unicode_2500_33ff
,
10040 else if (code
>= 0xE000)
10041 charset_id
= charset_mule_unicode_e000_ffff
,
10043 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10044 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10045 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10050 /* Emacs calls this whenever it wants to read an input event from the
10053 XTread_socket (sd
, expected
, hold_quit
)
10055 struct input_event
*hold_quit
;
10057 struct input_event inev
;
10059 #if USE_CARBON_EVENTS
10061 EventTargetRef toolbox_dispatcher
;
10064 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10066 if (interrupt_input_blocked
)
10068 interrupt_input_pending
= 1;
10072 interrupt_input_pending
= 0;
10075 /* So people can tell when we have read the available input. */
10076 input_signal_count
++;
10080 #if USE_CARBON_EVENTS
10081 toolbox_dispatcher
= GetEventDispatcherTarget ();
10085 mac_prepare_for_quickdraw (NULL
),
10087 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
10088 kEventRemoveFromQueue
, &eventRef
))
10089 #else /* !USE_CARBON_EVENTS */
10090 while (mac_wait_next_event (&er
, 0, true))
10091 #endif /* !USE_CARBON_EVENTS */
10095 unsigned long timestamp
;
10098 inev
.kind
= NO_EVENT
;
10101 #if USE_CARBON_EVENTS
10102 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
10104 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10107 #if USE_CARBON_EVENTS
10108 /* Handle new events */
10109 if (!mac_convert_event_ref (eventRef
, &er
))
10111 /* There used to be a handler for the kEventMouseWheelMoved
10112 event here. But as of Mac OS X 10.4, this kind of event
10113 is not directly posted to the main event queue by
10114 two-finger scrolling on the trackpad. Instead, some
10115 private event is posted and it is converted to a wheel
10116 event by the default handler for the application target.
10117 The converted one can be received by a Carbon event
10118 handler installed on a window target. */
10119 read_socket_inev
= &inev
;
10120 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10121 read_socket_inev
= NULL
;
10124 #endif /* USE_CARBON_EVENTS */
10130 WindowPtr window_ptr
;
10131 ControlPartCode part_code
;
10132 int tool_bar_p
= 0;
10134 #if USE_CARBON_EVENTS
10135 /* This is needed to send mouse events like aqua window
10136 buttons to the correct handler. */
10137 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10138 != eventNotHandledErr
)
10141 last_mouse_glyph_frame
= 0;
10143 if (dpyinfo
->grabbed
&& last_mouse_frame
10144 && FRAME_LIVE_P (last_mouse_frame
))
10146 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
10147 part_code
= inContent
;
10151 part_code
= FindWindow (er
.where
, &window_ptr
);
10152 if (tip_window
&& window_ptr
== tip_window
)
10154 HideWindow (tip_window
);
10155 part_code
= FindWindow (er
.where
, &window_ptr
);
10159 if (er
.what
!= mouseDown
&&
10160 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
10166 f
= mac_focus_frame (dpyinfo
);
10167 saved_menu_event_location
= er
.where
;
10168 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
10169 XSETFRAME (inev
.frame_or_window
, f
);
10174 #if TARGET_API_MAC_CARBON
10175 FrontNonFloatingWindow ()
10180 SelectWindow (window_ptr
);
10183 ControlPartCode control_part_code
;
10185 Point mouse_loc
= er
.where
;
10187 ControlKind control_kind
;
10190 f
= mac_window_to_frame (window_ptr
);
10191 /* convert to local coordinates of new window */
10192 SetPortWindowPort (window_ptr
);
10194 GlobalToLocal (&mouse_loc
);
10195 #if TARGET_API_MAC_CARBON
10196 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10197 &control_part_code
);
10200 GetControlKind (ch
, &control_kind
);
10203 control_part_code
= FindControl (mouse_loc
, window_ptr
,
10207 #if USE_CARBON_EVENTS
10208 inev
.code
= mac_get_mouse_btn (eventRef
);
10209 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10211 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
10212 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10214 XSETINT (inev
.x
, mouse_loc
.h
);
10215 XSETINT (inev
.y
, mouse_loc
.v
);
10217 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
10219 #ifndef USE_TOOLKIT_SCROLL_BARS
10220 /* control_part_code becomes kControlNoPart if
10221 a progress indicator is clicked. */
10222 && control_part_code
!= kControlNoPart
10223 #else /* USE_TOOLKIT_SCROLL_BARS */
10225 && control_kind
.kind
== kControlKindScrollBar
10226 #endif /* MAC_OSX */
10227 #endif /* USE_TOOLKIT_SCROLL_BARS */
10230 struct scroll_bar
*bar
;
10232 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10234 bar
= tracked_scroll_bar
;
10235 #ifndef USE_TOOLKIT_SCROLL_BARS
10236 control_part_code
= kControlIndicatorPart
;
10240 bar
= (struct scroll_bar
*) GetControlReference (ch
);
10241 #ifdef USE_TOOLKIT_SCROLL_BARS
10242 /* Make the "Ctrl-Mouse-2 splits window" work
10243 for toolkit scroll bars. */
10244 if (er
.modifiers
& controlKey
)
10245 x_scroll_bar_handle_click (bar
, control_part_code
,
10247 else if (er
.what
== mouseDown
)
10248 x_scroll_bar_handle_press (bar
, control_part_code
,
10251 x_scroll_bar_handle_release (bar
, &inev
);
10252 #else /* not USE_TOOLKIT_SCROLL_BARS */
10253 x_scroll_bar_handle_click (bar
, control_part_code
,
10255 if (er
.what
== mouseDown
10256 && control_part_code
== kControlIndicatorPart
)
10257 tracked_scroll_bar
= bar
;
10259 tracked_scroll_bar
= NULL
;
10260 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10264 Lisp_Object window
;
10265 int x
= mouse_loc
.h
;
10266 int y
= mouse_loc
.v
;
10268 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10269 if (EQ (window
, f
->tool_bar_window
))
10271 if (er
.what
== mouseDown
)
10272 handle_tool_bar_click (f
, x
, y
, 1, 0);
10274 handle_tool_bar_click (f
, x
, y
, 0,
10280 XSETFRAME (inev
.frame_or_window
, f
);
10281 inev
.kind
= MOUSE_CLICK_EVENT
;
10285 if (er
.what
== mouseDown
)
10287 dpyinfo
->grabbed
|= (1 << inev
.code
);
10288 last_mouse_frame
= f
;
10291 last_tool_bar_item
= -1;
10295 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10296 /* If a button is released though it was not
10297 previously pressed, that would be because
10298 of multi-button emulation. */
10299 dpyinfo
->grabbed
= 0;
10301 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10304 /* Ignore any mouse motion that happened before
10305 this event; any subsequent mouse-movement Emacs
10306 events should reflect only motion after the
10309 f
->mouse_moved
= 0;
10311 #ifdef USE_TOOLKIT_SCROLL_BARS
10312 if (inev
.kind
== MOUSE_CLICK_EVENT
)
10317 inev
.modifiers
|= down_modifier
;
10320 inev
.modifiers
|= up_modifier
;
10327 #if TARGET_API_MAC_CARBON
10329 if (IsWindowPathSelectClick (window_ptr
, &er
))
10331 WindowPathSelect (window_ptr
, NULL
, NULL
);
10334 if (part_code
== inProxyIcon
10335 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
10336 != errUserWantsToDragWindow
))
10338 DragWindow (window_ptr
, er
.where
, NULL
);
10339 #else /* not TARGET_API_MAC_CARBON */
10340 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10341 #endif /* not TARGET_API_MAC_CARBON */
10342 /* Update the frame parameters. */
10344 struct frame
*f
= mac_window_to_frame (window_ptr
);
10346 if (f
&& !f
->async_iconified
)
10347 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
10352 if (TrackGoAway (window_ptr
, er
.where
))
10354 inev
.kind
= DELETE_WINDOW_EVENT
;
10355 XSETFRAME (inev
.frame_or_window
,
10356 mac_window_to_frame (window_ptr
));
10360 /* window resize handling added --ben */
10362 do_grow_window (window_ptr
, &er
);
10365 /* window zoom handling added --ben */
10368 if (TrackBox (window_ptr
, er
.where
, part_code
))
10369 do_zoom_window (window_ptr
, part_code
);
10379 #if USE_CARBON_EVENTS
10380 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10381 != eventNotHandledErr
)
10384 do_window_update ((WindowPtr
) er
.message
);
10389 #if USE_CARBON_EVENTS
10390 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10391 != eventNotHandledErr
)
10394 switch ((er
.message
>> 24) & 0x000000FF)
10396 case suspendResumeMessage
:
10397 if ((er
.message
& resumeFlag
) == 1)
10403 case mouseMovedMessage
:
10404 #if !USE_CARBON_EVENTS
10405 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
10406 er
.where
.h
+ 1, er
.where
.v
+ 1);
10408 previous_help_echo_string
= help_echo_string
;
10409 help_echo_string
= Qnil
;
10411 if (dpyinfo
->grabbed
&& last_mouse_frame
10412 && FRAME_LIVE_P (last_mouse_frame
))
10413 f
= last_mouse_frame
;
10415 f
= dpyinfo
->x_focus_frame
;
10417 if (dpyinfo
->mouse_face_hidden
)
10419 dpyinfo
->mouse_face_hidden
= 0;
10420 clear_mouse_face (dpyinfo
);
10425 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
10426 Point mouse_pos
= er
.where
;
10428 SetPortWindowPort (wp
);
10430 GlobalToLocal (&mouse_pos
);
10432 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10433 #ifdef USE_TOOLKIT_SCROLL_BARS
10434 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
10436 #else /* not USE_TOOLKIT_SCROLL_BARS */
10437 x_scroll_bar_note_movement (tracked_scroll_bar
,
10439 - XINT (tracked_scroll_bar
->top
),
10440 er
.when
* (1000 / 60));
10441 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10444 /* Generate SELECT_WINDOW_EVENTs when needed. */
10445 if (mouse_autoselect_window
)
10447 Lisp_Object window
;
10449 window
= window_from_coordinates (f
,
10454 /* Window will be selected only when it is
10455 not selected now and last mouse movement
10456 event was not in it. Minibuffer window
10457 will be selected iff it is active. */
10458 if (WINDOWP (window
)
10459 && !EQ (window
, last_window
)
10460 && !EQ (window
, selected_window
))
10462 inev
.kind
= SELECT_WINDOW_EVENT
;
10463 inev
.frame_or_window
= window
;
10466 last_window
=window
;
10468 if (!note_mouse_movement (f
, &mouse_pos
))
10469 help_echo_string
= previous_help_echo_string
;
10473 /* If the contents of the global variable
10474 help_echo_string has changed, generate a
10476 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10484 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10486 #if USE_CARBON_EVENTS
10487 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10488 != eventNotHandledErr
)
10491 if (window_ptr
== tip_window
)
10493 HideWindow (tip_window
);
10497 if (!is_emacs_window (window_ptr
))
10500 if ((er
.modifiers
& activeFlag
) != 0)
10502 /* A window has been activated */
10503 Point mouse_loc
= er
.where
;
10505 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10507 SetPortWindowPort (window_ptr
);
10508 GlobalToLocal (&mouse_loc
);
10509 /* Window-activated event counts as mouse movement,
10510 so update things that depend on mouse position. */
10511 note_mouse_movement (mac_window_to_frame (window_ptr
),
10516 /* A window has been deactivated */
10517 #if USE_TOOLKIT_SCROLL_BARS
10518 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10520 struct input_event event
;
10522 EVENT_INIT (event
);
10523 event
.kind
= NO_EVENT
;
10524 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10525 if (event
.kind
!= NO_EVENT
)
10527 event
.timestamp
= timestamp
;
10528 kbd_buffer_store_event_hold (&event
, hold_quit
);
10533 dpyinfo
->grabbed
= 0;
10535 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10537 f
= mac_window_to_frame (window_ptr
);
10538 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10540 /* If we move outside the frame, then we're
10541 certainly no longer on any text in the
10543 clear_mouse_face (dpyinfo
);
10544 dpyinfo
->mouse_face_mouse_frame
= 0;
10547 /* Generate a nil HELP_EVENT to cancel a help-echo.
10548 Do it only if there's something to cancel.
10549 Otherwise, the startup message is cleared when the
10550 mouse leaves the frame. */
10551 if (any_help_event_p
)
10561 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10563 static SInt16 last_key_script
= -1;
10564 SInt16 current_key_script
;
10565 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
10568 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
10569 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
10570 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
10572 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10573 mapped_modifiers
|=
10574 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
10576 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
10578 sizeof (UInt32
), NULL
, &modifiers
);
10580 mapped_modifiers
&= modifiers
;
10582 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10583 /* When using Carbon Events, we need to pass raw keyboard
10584 events to the TSM ourselves. If TSM handles it, it
10585 will pass back noErr, otherwise it will pass back
10586 "eventNotHandledErr" and we can process it
10588 if (!(mapped_modifiers
10589 & ~(mac_pass_command_to_system
? cmdKey
: 0)
10590 & ~(mac_pass_control_to_system
? controlKey
: 0)))
10594 read_socket_inev
= &inev
;
10595 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10596 read_socket_inev
= NULL
;
10597 if (err
!= eventNotHandledErr
)
10601 if (er
.what
== keyUp
)
10606 f
= mac_focus_frame (dpyinfo
);
10608 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
10609 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
10611 clear_mouse_face (dpyinfo
);
10612 dpyinfo
->mouse_face_hidden
= 1;
10615 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10616 if (last_key_script
!= current_key_script
)
10618 struct input_event event
;
10620 EVENT_INIT (event
);
10621 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10623 event
.code
= current_key_script
;
10624 event
.timestamp
= timestamp
;
10625 kbd_buffer_store_event (&event
);
10627 last_key_script
= current_key_script
;
10631 if (inev
.kind
!= NO_EVENT
)
10636 if (mapped_modifiers
& kEventKeyModifierFnMask
10638 && fn_keycode_to_keycode_table
[keycode
])
10639 keycode
= fn_keycode_to_keycode_table
[keycode
];
10641 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10643 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10644 inev
.code
= 0xff00 | xkeysym
;
10646 if (modifiers
& kEventKeyModifierFnMask
10648 && fn_keycode_to_keycode_table
[keycode
] == keycode
)
10649 modifiers
&= ~kEventKeyModifierFnMask
;
10652 else if (mapped_modifiers
)
10654 /* translate the keycode back to determine the
10657 static SInt16 last_key_layout_id
= 0;
10658 static Handle uchr_handle
= (Handle
)-1;
10659 SInt16 current_key_layout_id
=
10660 GetScriptVariable (current_key_script
, smScriptKeys
);
10662 if (uchr_handle
== (Handle
)-1
10663 || last_key_layout_id
!= current_key_layout_id
)
10665 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10666 last_key_layout_id
= current_key_layout_id
;
10672 UInt16 key_action
= er
.what
- keyDown
;
10673 UInt32 modifier_key_state
=
10674 (modifiers
& ~mapped_modifiers
) >> 8;
10675 UInt32 keyboard_type
= LMGetKbdType ();
10676 SInt32 dead_key_state
= 0;
10678 UniCharCount actual_length
;
10680 status
= UCKeyTranslate ((UCKeyboardLayout
*)*uchr_handle
,
10681 keycode
, key_action
,
10682 modifier_key_state
,
10684 kUCKeyTranslateNoDeadKeysMask
,
10686 1, &actual_length
, &code
);
10687 if (status
== noErr
&& actual_length
== 1)
10688 mac_set_unicode_keystroke_event (code
, &inev
);
10690 #endif /* MAC_OSX */
10692 if (inev
.kind
== NO_EVENT
)
10694 /* This code comes from Keyboard Resource,
10695 Appendix C of IM - Text. This is necessary
10696 since shift is ignored in KCHR table
10697 translation when option or command is pressed.
10698 It also does not translate correctly
10699 control-shift chars like C-% so mask off shift
10701 /* Mask off modifier keys that are mapped to some
10702 Emacs modifiers. */
10703 int new_modifiers
= er
.modifiers
& ~mapped_modifiers
;
10704 /* set high byte of keycode to modifier high byte*/
10705 int new_keycode
= keycode
| new_modifiers
;
10706 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10707 unsigned long some_state
= 0;
10708 UInt32 new_char_code
;
10710 new_char_code
= KeyTranslate (kchr_ptr
, new_keycode
,
10712 if (new_char_code
== 0)
10713 /* Seems like a dead key. Append up-stroke. */
10714 new_char_code
= KeyTranslate (kchr_ptr
,
10715 new_keycode
| 0x80,
10719 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10720 inev
.code
= new_char_code
& 0xff;
10725 if (inev
.kind
== NO_EVENT
)
10727 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10728 inev
.code
= er
.message
& charCodeMask
;
10731 inev
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10732 inev
.modifiers
|= (extra_keyboard_modifiers
10733 & (meta_modifier
| alt_modifier
10734 | hyper_modifier
| super_modifier
));
10735 XSETFRAME (inev
.frame_or_window
, f
);
10737 #if TARGET_API_MAC_CARBON
10738 if (inev
.kind
== ASCII_KEYSTROKE_EVENT
10739 && inev
.code
>= 0x80 && inev
.modifiers
)
10742 TextEncoding encoding
= kTextEncodingMacRoman
;
10743 TextToUnicodeInfo ttu_info
;
10745 UpgradeScriptInfoToTextEncoding (current_key_script
,
10746 kTextLanguageDontCare
,
10747 kTextRegionDontCare
,
10749 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10754 ByteCount unicode_len
;
10757 pstr
[1] = inev
.code
;
10758 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10760 &unicode_len
, &code
);
10761 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10762 mac_set_unicode_keystroke_event (code
, &inev
);
10763 DisposeTextToUnicodeInfo (&ttu_info
);
10770 case kHighLevelEvent
:
10771 AEProcessAppleEvent (&er
);
10777 #if USE_CARBON_EVENTS
10778 ReleaseEvent (eventRef
);
10781 if (inev
.kind
!= NO_EVENT
)
10783 inev
.timestamp
= timestamp
;
10784 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10789 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10794 XSETFRAME (frame
, f
);
10800 any_help_event_p
= 1;
10801 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10802 help_echo_object
, help_echo_pos
);
10806 help_echo_string
= Qnil
;
10807 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10814 /* If the focus was just given to an autoraising frame,
10816 /* ??? This ought to be able to handle more than one such frame. */
10817 if (pending_autoraise_frame
)
10819 x_raise_frame (pending_autoraise_frame
);
10820 pending_autoraise_frame
= 0;
10823 #if !USE_CARBON_EVENTS
10824 /* Check which frames are still visible. We do this here because
10825 there doesn't seem to be any direct notification from the Window
10826 Manager that the visibility of a window has changed (at least,
10827 not in all cases). */
10829 Lisp_Object tail
, frame
;
10831 FOR_EACH_FRAME (tail
, frame
)
10833 struct frame
*f
= XFRAME (frame
);
10835 /* The tooltip has been drawn already. Avoid the
10836 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10837 if (EQ (frame
, tip_frame
))
10840 if (FRAME_MAC_P (f
))
10841 mac_handle_visibility_change (f
);
10852 /* Need to override CodeWarrior's input function so no conversion is
10853 done on newlines Otherwise compiled functions in .elc files will be
10854 read incorrectly. Defined in ...:MSL C:MSL
10855 Common:Source:buffer_io.c. */
10858 __convert_to_newlines (unsigned char * p
, size_t * n
)
10860 #pragma unused(p,n)
10864 __convert_from_newlines (unsigned char * p
, size_t * n
)
10866 #pragma unused(p,n)
10872 make_mac_terminal_frame (struct frame
*f
)
10877 XSETFRAME (frame
, f
);
10879 f
->output_method
= output_mac
;
10880 f
->output_data
.mac
= (struct mac_output
*)
10881 xmalloc (sizeof (struct mac_output
));
10882 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10884 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10886 FRAME_COLS (f
) = 96;
10887 FRAME_LINES (f
) = 4;
10889 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10890 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10892 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10894 f
->output_data
.mac
->cursor_pixel
= 0;
10895 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10896 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10897 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10899 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10900 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10901 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10902 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10903 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10904 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10906 FRAME_FONTSET (f
) = -1;
10907 f
->output_data
.mac
->explicit_parent
= 0;
10910 f
->border_width
= 0;
10912 f
->internal_border_width
= 0;
10917 f
->new_text_cols
= 0;
10918 f
->new_text_lines
= 0;
10920 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10921 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10922 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10926 if (!(FRAME_MAC_WINDOW (f
) =
10927 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10928 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10930 /* so that update events can find this mac_output struct */
10931 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10937 /* Need to be initialized for unshow_buffer in window.c. */
10938 selected_window
= f
->selected_window
;
10940 Fmodify_frame_parameters (frame
,
10941 Fcons (Fcons (Qfont
,
10942 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10943 Fmodify_frame_parameters (frame
,
10944 Fcons (Fcons (Qforeground_color
,
10945 build_string ("black")), Qnil
));
10946 Fmodify_frame_parameters (frame
,
10947 Fcons (Fcons (Qbackground_color
,
10948 build_string ("white")), Qnil
));
10953 /***********************************************************************
10955 ***********************************************************************/
10957 int mac_initialized
= 0;
10960 mac_initialize_display_info ()
10962 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10963 GDHandle main_device_handle
;
10965 bzero (dpyinfo
, sizeof (*dpyinfo
));
10968 dpyinfo
->mac_id_name
10969 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10970 + SCHARS (Vsystem_name
)
10972 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10973 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10975 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10976 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10979 main_device_handle
= LMGetMainDevice();
10981 dpyinfo
->reference_count
= 0;
10982 dpyinfo
->resx
= 72.0;
10983 dpyinfo
->resy
= 72.0;
10984 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10986 /* HasDepth returns true if it is possible to have a 32 bit display,
10987 but this may not be what is actually used. Mac OSX can do better.
10988 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10989 header for CGGetActiveDisplayList says that the first display returned
10990 is the active one, so we use that. */
10992 CGDirectDisplayID disp_id
[1];
10993 CGDisplayCount disp_count
;
10994 CGDisplayErr error_code
;
10996 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10997 if (error_code
!= 0)
10998 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
11000 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
11003 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11004 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
11005 gdDevType
, dpyinfo
->color_p
))
11008 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
11009 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
11010 dpyinfo
->grabbed
= 0;
11011 dpyinfo
->root_window
= NULL
;
11012 dpyinfo
->image_cache
= make_image_cache ();
11014 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11015 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11016 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11017 dpyinfo
->mouse_face_window
= Qnil
;
11018 dpyinfo
->mouse_face_overlay
= Qnil
;
11019 dpyinfo
->mouse_face_hidden
= 0;
11024 mac_make_rdb (xrm_option
)
11027 XrmDatabase database
;
11029 database
= xrm_get_preference_database (NULL
);
11031 xrm_merge_string_database (database
, xrm_option
);
11036 struct mac_display_info
*
11037 mac_term_init (display_name
, xrm_option
, resource_name
)
11038 Lisp_Object display_name
;
11040 char *resource_name
;
11042 struct mac_display_info
*dpyinfo
;
11046 if (!mac_initialized
)
11049 mac_initialized
= 1;
11052 if (x_display_list
)
11053 error ("Sorry, this version can only handle one display");
11055 mac_initialize_display_info ();
11057 dpyinfo
= &one_mac_display_info
;
11059 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
11061 /* Put this display on the chain. */
11062 dpyinfo
->next
= x_display_list
;
11063 x_display_list
= dpyinfo
;
11065 /* Put it on x_display_name_list. */
11066 x_display_name_list
= Fcons (Fcons (display_name
,
11067 Fcons (Qnil
, dpyinfo
->xrdb
)),
11068 x_display_name_list
);
11069 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11075 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11078 x_delete_display (dpyinfo
)
11079 struct mac_display_info
*dpyinfo
;
11083 /* Discard this display from x_display_name_list and x_display_list.
11084 We can't use Fdelq because that can quit. */
11085 if (! NILP (x_display_name_list
)
11086 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11087 x_display_name_list
= XCDR (x_display_name_list
);
11092 tail
= x_display_name_list
;
11093 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11095 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11097 XSETCDR (tail
, XCDR (XCDR (tail
)));
11100 tail
= XCDR (tail
);
11104 if (x_display_list
== dpyinfo
)
11105 x_display_list
= dpyinfo
->next
;
11108 struct x_display_info
*tail
;
11110 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11111 if (tail
->next
== dpyinfo
)
11112 tail
->next
= tail
->next
->next
;
11115 /* Free the font names in the font table. */
11116 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11117 if (dpyinfo
->font_table
[i
].name
)
11119 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11120 xfree (dpyinfo
->font_table
[i
].full_name
);
11121 xfree (dpyinfo
->font_table
[i
].name
);
11124 if (dpyinfo
->font_table
->font_encoder
)
11125 xfree (dpyinfo
->font_table
->font_encoder
);
11127 xfree (dpyinfo
->font_table
);
11128 xfree (dpyinfo
->mac_id_name
);
11130 if (x_display_list
== 0)
11132 mac_clear_font_name_table ();
11133 bzero (dpyinfo
, sizeof (*dpyinfo
));
11142 extern int inhibit_window_system
;
11143 extern int noninteractive
;
11144 CFBundleRef appsBundle
;
11146 /* No need to test if already -nw*/
11147 if (inhibit_window_system
|| noninteractive
)
11150 appsBundle
= CFBundleGetMainBundle();
11151 if (appsBundle
!= NULL
)
11153 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
11154 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
11155 /* We found the bundle identifier, now we know we are valid. */
11162 /* MAC_TODO: Have this start the bundled executable */
11164 /* For now, prevent the fatal error by bringing it up in the terminal */
11165 inhibit_window_system
= 1;
11169 MakeMeTheFrontProcess ()
11171 ProcessSerialNumber psn
;
11174 err
= GetCurrentProcess (&psn
);
11176 (void) SetFrontProcess (&psn
);
11179 /***** Code to handle C-g testing *****/
11181 /* Contains the Mac modifier formed from quit_char */
11182 int mac_quit_char_modifiers
= 0;
11183 int mac_quit_char_keycode
;
11184 extern int quit_char
;
11187 mac_determine_quit_char_modifiers()
11189 /* Todo: Determine modifiers from quit_char. */
11190 UInt32 qc_modifiers
= ctrl_modifier
;
11192 /* Map modifiers */
11193 mac_quit_char_modifiers
= 0;
11194 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
11195 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
11196 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
11200 init_quit_char_handler ()
11202 /* TODO: Let this support keys other the 'g' */
11203 mac_quit_char_keycode
= 5;
11204 /* Look at <architecture/adb_kb_map.h> for details */
11205 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
11207 mac_determine_quit_char_modifiers();
11209 #endif /* MAC_OSX */
11217 MenuItemIndex menu_index
;
11219 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
11220 &menu
, &menu_index
);
11222 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11223 #if USE_CARBON_EVENTS
11224 EnableMenuCommand (NULL
, kHICommandPreferences
);
11225 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
11226 &menu
, &menu_index
);
11229 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11230 InsertMenuItemTextWithCFString (menu
, NULL
,
11231 0, kMenuItemAttrSeparator
, 0);
11232 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
11233 0, 0, kHICommandAbout
);
11235 #endif /* USE_CARBON_EVENTS */
11236 #else /* !MAC_OSX */
11237 #if USE_CARBON_EVENTS
11238 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
11247 static InterfaceTypeList types
= {kUnicodeDocument
};
11249 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
11250 &tsm_document_id
, 0);
11254 /* Set up use of X before we make the first connection. */
11256 extern frame_parm_handler mac_frame_parm_handlers
[];
11258 static struct redisplay_interface x_redisplay_interface
=
11260 mac_frame_parm_handlers
,
11264 x_clear_end_of_line
,
11266 x_after_update_window_line
,
11267 x_update_window_begin
,
11268 x_update_window_end
,
11271 0, /* flush_display_optional */
11272 x_clear_window_mouse_face
,
11273 x_get_glyph_overhangs
,
11274 x_fix_overlapping_area
,
11275 x_draw_fringe_bitmap
,
11277 mac_define_fringe_bitmap
,
11278 mac_destroy_fringe_bitmap
,
11280 0, /* define_fringe_bitmap */
11281 0, /* destroy_fringe_bitmap */
11283 mac_per_char_metric
,
11285 mac_compute_glyph_string_overhangs
,
11286 x_draw_glyph_string
,
11287 mac_define_frame_cursor
,
11288 mac_clear_frame_area
,
11289 mac_draw_window_cursor
,
11290 mac_draw_vertical_window_border
,
11291 mac_shift_glyphs_for_insert
11297 rif
= &x_redisplay_interface
;
11299 clear_frame_hook
= x_clear_frame
;
11300 ins_del_lines_hook
= x_ins_del_lines
;
11301 delete_glyphs_hook
= x_delete_glyphs
;
11302 ring_bell_hook
= XTring_bell
;
11303 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11304 set_terminal_modes_hook
= XTset_terminal_modes
;
11305 update_begin_hook
= x_update_begin
;
11306 update_end_hook
= x_update_end
;
11307 set_terminal_window_hook
= XTset_terminal_window
;
11308 read_socket_hook
= XTread_socket
;
11309 frame_up_to_date_hook
= XTframe_up_to_date
;
11310 mouse_position_hook
= XTmouse_position
;
11311 frame_rehighlight_hook
= XTframe_rehighlight
;
11312 frame_raise_lower_hook
= XTframe_raise_lower
;
11314 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11315 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11316 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11317 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11319 scroll_region_ok
= 1; /* we'll scroll partial frames */
11320 char_ins_del_ok
= 1;
11321 line_ins_del_ok
= 1; /* we'll just blt 'em */
11322 fast_clear_end_of_line
= 1; /* X does this well */
11323 memory_below_frame
= 0; /* we don't remember what scrolls
11327 last_tool_bar_item
= -1;
11328 any_help_event_p
= 0;
11330 /* Try to use interrupt input; if we can't, then start polling. */
11331 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
11335 #if TARGET_API_MAC_CARBON
11337 #if USE_CARBON_EVENTS
11339 init_service_handler ();
11341 init_quit_char_handler ();
11342 #endif /* MAC_OSX */
11344 init_command_handler ();
11351 #endif /* USE_CARBON_EVENTS */
11354 init_coercion_handler ();
11356 init_apple_event_handler ();
11358 if (!inhibit_window_system
)
11359 MakeMeTheFrontProcess ();
11364 mac_init_fringe ();
11375 staticpro (&x_error_message_string
);
11376 x_error_message_string
= Qnil
;
11379 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
11380 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
11381 Qalt
= intern ("alt"); staticpro (&Qalt
);
11382 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
11383 Qsuper
= intern ("super"); staticpro (&Qsuper
);
11384 Qmodifier_value
= intern ("modifier-value");
11385 staticpro (&Qmodifier_value
);
11387 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
11388 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11389 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11390 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11391 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11393 #if USE_CARBON_EVENTS
11394 Qhicommand
= intern ("hicommand"); staticpro (&Qhicommand
);
11396 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
11397 staticpro (&Qtoolbar_switch_mode
);
11398 #if USE_MAC_FONT_PANEL
11399 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
11400 Qselection
= intern ("selection"); staticpro (&Qselection
);
11403 Qservice
= intern ("service"); staticpro (&Qservice
);
11404 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
11405 Qperform
= intern ("perform"); staticpro (&Qperform
);
11408 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
11409 Qupdate_active_input_area
= intern ("update-active-input-area");
11410 staticpro (&Qupdate_active_input_area
);
11411 Qunicode_for_key_event
= intern ("unicode-for-key-event");
11412 staticpro (&Qunicode_for_key_event
);
11417 Fprovide (intern ("mac-carbon"), Qnil
);
11420 staticpro (&Qreverse
);
11421 Qreverse
= intern ("reverse");
11423 staticpro (&x_display_name_list
);
11424 x_display_name_list
= Qnil
;
11426 staticpro (&last_mouse_scroll_bar
);
11427 last_mouse_scroll_bar
= Qnil
;
11429 staticpro (&fm_font_family_alist
);
11430 fm_font_family_alist
= Qnil
;
11433 staticpro (&atsu_font_id_hash
);
11434 atsu_font_id_hash
= Qnil
;
11437 /* We don't yet support this, but defining this here avoids whining
11438 from cus-start.el and other places, like "M-x set-variable". */
11439 DEFVAR_BOOL ("x-use-underline-position-properties",
11440 &x_use_underline_position_properties
,
11441 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11442 nil means ignore them. If you encounter fonts with bogus
11443 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11444 to 4.1, set this to nil.
11446 NOTE: Not supported on Mac yet. */);
11447 x_use_underline_position_properties
= 0;
11449 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
11450 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
11451 #ifdef USE_TOOLKIT_SCROLL_BARS
11452 Vx_toolkit_scroll_bars
= Qt
;
11454 Vx_toolkit_scroll_bars
= Qnil
;
11457 staticpro (&last_mouse_motion_frame
);
11458 last_mouse_motion_frame
= Qnil
;
11460 /* Variables to configure modifier key assignment. */
11462 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
11463 doc
: /* *Modifier key assumed when the Mac control key is pressed.
11464 The value can be `control', `meta', `alt', `hyper', or `super' for the
11465 respective modifier. The default is `control'. */);
11466 Vmac_control_modifier
= Qcontrol
;
11468 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
11469 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
11470 The value can be `control', `meta', `alt', `hyper', or `super' for the
11471 respective modifier. If the value is nil then the key will act as the
11472 normal Mac control modifier, and the option key can be used to compose
11473 characters depending on the chosen Mac keyboard setting. */);
11474 Vmac_option_modifier
= Qnil
;
11476 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
11477 doc
: /* *Modifier key assumed when the Mac command key is pressed.
11478 The value can be `control', `meta', `alt', `hyper', or `super' for the
11479 respective modifier. The default is `meta'. */);
11480 Vmac_command_modifier
= Qmeta
;
11482 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
11483 doc
: /* *Modifier key assumed when the Mac function key is pressed.
11484 The value can be `control', `meta', `alt', `hyper', or `super' for the
11485 respective modifier. Note that remapping the function key may lead to
11486 unexpected results for some keys on non-US/GB keyboards. */);
11487 Vmac_function_modifier
= Qnil
;
11489 DEFVAR_LISP ("mac-emulate-three-button-mouse",
11490 &Vmac_emulate_three_button_mouse
,
11491 doc
: /* *Specify a way of three button mouse emulation.
11492 The value can be nil, t, or the symbol `reverse'.
11493 nil means that no emulation should be done and the modifiers should be
11494 placed on the mouse-1 event.
11495 t means that when the option-key is held down while pressing the mouse
11496 button, the click will register as mouse-2 and while the command-key
11497 is held down, the click will register as mouse-3.
11498 The symbol `reverse' means that the option-key will register for
11499 mouse-3 and the command-key will register for mouse-2. */);
11500 Vmac_emulate_three_button_mouse
= Qnil
;
11502 #if USE_CARBON_EVENTS
11503 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
11504 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
11505 Otherwise, the right click will be treated as mouse-2 and the wheel
11506 button will be mouse-3. */);
11507 mac_wheel_button_is_mouse_2
= 1;
11509 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
11510 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
11511 mac_pass_command_to_system
= 1;
11513 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
11514 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
11515 mac_pass_control_to_system
= 1;
11519 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
11520 doc
: /* *If non-nil, allow anti-aliasing.
11521 The text will be rendered using Core Graphics text rendering which
11522 may anti-alias the text. */);
11524 mac_use_core_graphics
= 1;
11526 mac_use_core_graphics
= 0;
11529 /* Register an entry for `mac-roman' so that it can be used when
11530 creating the terminal frame on Mac OS 9 before loading
11531 term/mac-win.elc. */
11532 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
11533 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
11534 Each entry should be of the form:
11536 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
11538 where CHARSET-NAME is a string used in font names to identify the
11539 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
11540 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
11541 Vmac_charset_info_alist
=
11542 Fcons (list3 (build_string ("mac-roman"),
11543 make_number (smRoman
), Qnil
), Qnil
);
11546 DEFVAR_LISP ("mac-atsu-font-table", &Vmac_atsu_font_table
,
11547 doc
: /* Hash table of ATSU font IDs vs plist of attributes and values.
11548 Each font ID is represented as a four-byte string in native byte
11550 Vmac_atsu_font_table
=
11551 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
11552 make_float (DEFAULT_REHASH_SIZE
),
11553 make_float (DEFAULT_REHASH_THRESHOLD
),
11557 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
11558 doc
: /* Overlay used to display Mac TSM active input area. */);
11559 Vmac_ts_active_input_overlay
= Qnil
;
11563 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
11564 (do not change this comment) */