1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
49 #include <Resources.h>
51 #include <TextUtils.h>
55 #if defined (__MRC__) || (__MSL__ >= 0x6000)
56 #include <ControlDefinitions.h>
62 #endif /* not TARGET_API_MAC_CARBON */
75 #include "dispextern.h"
77 #include "termhooks.h"
85 #include "intervals.h"
88 #include "character.h"
93 /* Non-nil means Emacs uses toolkit scroll bars. */
95 Lisp_Object Vx_toolkit_scroll_bars
;
97 /* If non-zero, the text will be rendered using Core Graphics text
98 rendering which may anti-alias the text. */
99 int mac_use_core_graphics
;
102 /* Non-zero means that a HELP_EVENT has been generated since Emacs
105 static int any_help_event_p
;
107 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
108 static Lisp_Object last_window
;
110 /* Non-zero means make use of UNDERLINE_POSITION font properties.
111 (Not yet supported.) */
112 int x_use_underline_position_properties
;
114 /* This is a chain of structures for all the X displays currently in
117 struct x_display_info
*x_display_list
;
119 /* This is a list of cons cells, each of the form (NAME
120 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
121 x_display_list and in the same order. NAME is the name of the
122 frame. FONT-LIST-CACHE records previous values returned by
123 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
124 equivalent, which is implemented with a Lisp object, for the
127 Lisp_Object x_display_name_list
;
129 /* This is display since Mac does not support multiple ones. */
130 struct mac_display_info one_mac_display_info
;
132 /* Frame being updated by update_frame. This is declared in term.c.
133 This is set by update_begin and looked at by all the XT functions.
134 It is zero while not inside an update. In that case, the XT
135 functions assume that `selected_frame' is the frame to apply to. */
137 extern struct frame
*updating_frame
;
139 /* This is a frame waiting to be auto-raised, within XTread_socket. */
141 struct frame
*pending_autoraise_frame
;
145 Formerly, we used PointerMotionHintMask (in standard_event_mask)
146 so that we would have to call XQueryPointer after each MotionNotify
147 event to ask for another such event. However, this made mouse tracking
148 slow, and there was a bug that made it eventually stop.
150 Simply asking for MotionNotify all the time seems to work better.
152 In order to avoid asking for motion events and then throwing most
153 of them away or busy-polling the server for mouse positions, we ask
154 the server for pointer motion hints. This means that we get only
155 one event per group of mouse movements. "Groups" are delimited by
156 other kinds of events (focus changes and button clicks, for
157 example), or by XQueryPointer calls; when one of these happens, we
158 get another MotionNotify event the next time the mouse moves. This
159 is at least as efficient as getting motion events when mouse
160 tracking is on, and I suspect only negligibly worse when tracking
163 /* Where the mouse was last time we reported a mouse event. */
165 static Rect last_mouse_glyph
;
166 static FRAME_PTR last_mouse_glyph_frame
;
168 /* The scroll bar in which the last X motion event occurred.
170 If the last X motion event occurred in a scroll bar, we set this so
171 XTmouse_position can know whether to report a scroll bar motion or
174 If the last X motion event didn't occur in a scroll bar, we set
175 this to Qnil, to tell XTmouse_position to return an ordinary motion
178 static Lisp_Object last_mouse_scroll_bar
;
180 /* This is a hack. We would really prefer that XTmouse_position would
181 return the time associated with the position it returns, but there
182 doesn't seem to be any way to wrest the time-stamp from the server
183 along with the position query. So, we just keep track of the time
184 of the last movement we received, and return that in hopes that
185 it's somewhat accurate. */
187 static Time last_mouse_movement_time
;
189 struct scroll_bar
*tracked_scroll_bar
= NULL
;
191 /* Incremented by XTread_socket whenever it really tries to read
195 static int volatile input_signal_count
;
197 static int input_signal_count
;
200 extern Lisp_Object Vsystem_name
;
202 /* A mask of extra modifier bits to put into every keyboard char. */
204 extern EMACS_INT extra_keyboard_modifiers
;
206 /* The keysyms to use for the various modifiers. */
208 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
210 extern int inhibit_window_system
;
212 #if __MRC__ && !TARGET_API_MAC_CARBON
213 QDGlobals qd
; /* QuickDraw global information structure. */
216 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
218 struct mac_display_info
*mac_display_info_for_display (Display
*);
219 static void x_update_window_end
P_ ((struct window
*, int, int));
220 static int x_io_error_quitter
P_ ((Display
*));
221 int x_catch_errors
P_ ((Display
*));
222 void x_uncatch_errors
P_ ((Display
*, int));
223 void x_lower_frame
P_ ((struct frame
*));
224 void x_scroll_bar_clear
P_ ((struct frame
*));
225 int x_had_errors_p
P_ ((Display
*));
226 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
227 void x_raise_frame
P_ ((struct frame
*));
228 void x_set_window_size
P_ ((struct frame
*, int, int, int));
229 void x_wm_set_window_state
P_ ((struct frame
*, int));
230 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
231 void mac_initialize
P_ ((void));
232 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
233 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
234 static void x_update_end
P_ ((struct frame
*));
235 static void XTframe_up_to_date
P_ ((struct frame
*));
236 static void XTset_terminal_modes
P_ ((void));
237 static void XTreset_terminal_modes
P_ ((void));
238 static void x_clear_frame
P_ ((void));
239 static void frame_highlight
P_ ((struct frame
*));
240 static void frame_unhighlight
P_ ((struct frame
*));
241 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
242 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
243 struct frame
*, struct input_event
*));
244 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
245 EventRecord
*, struct input_event
*));
246 static void XTframe_rehighlight
P_ ((struct frame
*));
247 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
248 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
249 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
250 enum text_cursor_kinds
));
252 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
253 static void x_flush
P_ ((struct frame
*f
));
254 static void x_update_begin
P_ ((struct frame
*));
255 static void x_update_window_begin
P_ ((struct window
*));
256 static void x_after_update_window_line
P_ ((struct glyph_row
*));
257 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
258 enum scroll_bar_part
*,
259 Lisp_Object
*, Lisp_Object
*,
262 static int is_emacs_window
P_ ((WindowPtr
));
263 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
264 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
266 /* Defined in macmenu.h. */
267 extern void menubar_selection_callback (FRAME_PTR
, int);
269 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
270 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
271 #define GC_FONT(gc) ((gc)->xgcv.font)
272 #define GC_CLIP_REGION(gc) ((gc)->clip_region)
273 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
275 static RgnHandle saved_port_clip_region
= NULL
;
278 mac_begin_clip (region
)
281 static RgnHandle new_region
= NULL
;
283 if (saved_port_clip_region
== NULL
)
284 saved_port_clip_region
= NewRgn ();
285 if (new_region
== NULL
)
286 new_region
= NewRgn ();
290 GetClip (saved_port_clip_region
);
291 SectRgn (saved_port_clip_region
, region
, new_region
);
292 SetClip (new_region
);
297 mac_end_clip (region
)
301 SetClip (saved_port_clip_region
);
305 /* X display function emulation */
308 XFreePixmap (display
, pixmap
)
309 Display
*display
; /* not used */
312 DisposeGWorld (pixmap
);
316 /* Mac version of XDrawLine. */
319 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
324 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
326 RGBForeColor (GC_FORE_COLOR (gc
));
328 mac_begin_clip (GC_CLIP_REGION (gc
));
331 mac_end_clip (GC_CLIP_REGION (gc
));
335 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
344 GetGWorld (&old_port
, &old_gdh
);
347 RGBForeColor (GC_FORE_COLOR (gc
));
349 LockPixels (GetGWorldPixMap (p
));
352 UnlockPixels (GetGWorldPixMap (p
));
354 SetGWorld (old_port
, old_gdh
);
359 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
363 unsigned int width
, height
;
367 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
369 RGBBackColor (GC_BACK_COLOR (gc
));
370 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
372 mac_begin_clip (GC_CLIP_REGION (gc
));
374 mac_end_clip (GC_CLIP_REGION (gc
));
376 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
380 /* Mac version of XClearArea. */
383 mac_clear_area (f
, x
, y
, width
, height
)
386 unsigned int width
, height
;
388 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
391 /* Mac version of XClearWindow. */
397 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
399 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
401 #if TARGET_API_MAC_CARBON
405 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
408 #else /* not TARGET_API_MAC_CARBON */
409 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
410 #endif /* not TARGET_API_MAC_CARBON */
414 /* Mac replacement for XCopyArea. */
417 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
420 int x
, y
, width
, height
;
421 unsigned short *bits
;
427 bitmap
.rowBytes
= sizeof(unsigned short);
428 bitmap
.baseAddr
= (char *)bits
;
429 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
431 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
433 RGBForeColor (GC_FORE_COLOR (gc
));
434 RGBBackColor (GC_BACK_COLOR (gc
));
435 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
437 mac_begin_clip (GC_CLIP_REGION (gc
));
438 #if TARGET_API_MAC_CARBON
444 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
445 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
446 UnlockPortBits (port
);
448 #else /* not TARGET_API_MAC_CARBON */
449 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
450 overlay_p
? srcOr
: srcCopy
, 0);
451 #endif /* not TARGET_API_MAC_CARBON */
452 mac_end_clip (GC_CLIP_REGION (gc
));
454 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
458 /* Mac replacement for XCreateBitmapFromBitmapData. */
461 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
466 static unsigned char swap_nibble
[16]
467 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
468 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
469 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
470 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
474 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
475 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
476 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
477 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
478 for (i
= 0; i
< h
; i
++)
480 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
481 for (j
= 0; j
< w1
; j
++)
483 /* Bitswap XBM bytes to match how Mac does things. */
484 unsigned char c
= *bits
++;
485 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
486 | (swap_nibble
[(c
>>4) & 0xf]));;
490 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
495 mac_free_bitmap (bitmap
)
498 xfree (bitmap
->baseAddr
);
503 XCreatePixmap (display
, w
, width
, height
, depth
)
504 Display
*display
; /* not used */
506 unsigned int width
, height
;
513 SetPortWindowPort (w
);
515 SetRect (&r
, 0, 0, width
, height
);
516 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
524 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
525 Display
*display
; /* not used */
528 unsigned int width
, height
;
529 unsigned long fg
, bg
;
536 static GC gc
= NULL
; /* not reentrant */
539 gc
= XCreateGC (display
, w
, 0, NULL
);
541 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
545 GetGWorld (&old_port
, &old_gdh
);
546 SetGWorld (pixmap
, NULL
);
547 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
548 XSetForeground (display
, gc
, fg
);
549 XSetBackground (display
, gc
, bg
);
550 RGBForeColor (GC_FORE_COLOR (gc
));
551 RGBBackColor (GC_BACK_COLOR (gc
));
552 LockPixels (GetGWorldPixMap (pixmap
));
553 #if TARGET_API_MAC_CARBON
554 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
555 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
556 #else /* not TARGET_API_MAC_CARBON */
557 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
558 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
559 #endif /* not TARGET_API_MAC_CARBON */
560 UnlockPixels (GetGWorldPixMap (pixmap
));
561 SetGWorld (old_port
, old_gdh
);
562 mac_free_bitmap (&bitmap
);
568 /* Mac replacement for XFillRectangle. */
571 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
575 unsigned int width
, height
;
579 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
581 RGBForeColor (GC_FORE_COLOR (gc
));
582 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
584 mac_begin_clip (GC_CLIP_REGION (gc
));
585 PaintRect (&r
); /* using foreground color of gc */
586 mac_end_clip (GC_CLIP_REGION (gc
));
590 /* Mac replacement for XDrawRectangle: dest is a window. */
593 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
597 unsigned int width
, height
;
601 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
603 RGBForeColor (GC_FORE_COLOR (gc
));
604 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
606 mac_begin_clip (GC_CLIP_REGION (gc
));
607 FrameRect (&r
); /* using foreground color of gc */
608 mac_end_clip (GC_CLIP_REGION (gc
));
614 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
615 ConstUniCharArrayPtr text
;
616 UniCharCount text_length
;
618 ATSUTextLayout
*text_layout
;
621 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
623 if (saved_text_layout
== NULL
)
625 UniCharCount lengths
[] = {kATSUToTextEnd
};
626 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
627 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
628 static ATSLineLayoutOptions line_layout
=
629 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
630 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
631 | kATSLineUseQDRendering
633 kATSLineIsDisplayOnly
| kATSLineFractDisable
636 ATSUAttributeValuePtr values
[] = {&line_layout
};
638 err
= ATSUCreateTextLayoutWithTextPtr (text
,
639 kATSUFromTextBeginning
,
645 err
= ATSUSetLayoutControls (saved_text_layout
,
646 sizeof (tags
) / sizeof (tags
[0]),
647 tags
, sizes
, values
);
648 /* XXX: Should we do this? */
650 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
654 err
= ATSUSetRunStyle (saved_text_layout
, style
,
655 kATSUFromTextBeginning
, kATSUToTextEnd
);
657 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
658 kATSUFromTextBeginning
,
664 *text_layout
= saved_text_layout
;
671 mac_invert_rectangle (f
, x
, y
, width
, height
)
674 unsigned int width
, height
;
678 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
680 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
687 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, mode
, bytes_per_char
)
692 int nchars
, mode
, bytes_per_char
;
694 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
695 UInt32 textFlags
, savedFlags
;
696 if (mac_use_core_graphics
) {
697 textFlags
= kQDUseCGTextRendering
;
698 savedFlags
= SwapQDTextFlags(textFlags
);
702 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
704 RGBForeColor (GC_FORE_COLOR (gc
));
706 RGBBackColor (GC_BACK_COLOR (gc
));
709 if (GC_FONT (gc
)->mac_style
)
712 ATSUTextLayout text_layout
;
714 xassert (bytes_per_char
== 2);
716 #ifndef WORDS_BIG_ENDIAN
719 UniChar
*text
= (UniChar
*)buf
;
721 for (i
= 0; i
< nchars
; i
++)
722 text
[i
] = EndianU16_BtoN (text
[i
]);
725 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
727 GC_FONT (gc
)->mac_style
,
732 if (!mac_use_core_graphics
)
735 mac_begin_clip (GC_CLIP_REGION (gc
));
737 ATSUDrawText (text_layout
,
738 kATSUFromTextBeginning
, kATSUToTextEnd
,
739 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
740 mac_end_clip (GC_CLIP_REGION (gc
));
746 CGContextRef context
;
747 float port_height
= FRAME_PIXEL_HEIGHT (f
);
748 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
749 ByteCount sizes
[] = {sizeof (CGContextRef
)};
750 ATSUAttributeValuePtr values
[] = {&context
};
753 QDBeginCGContext (port
, &context
);
754 if (gc
->n_clip_rects
)
756 CGContextTranslateCTM (context
, 0, port_height
);
757 CGContextScaleCTM (context
, 1, -1);
758 CGContextClipToRects (context
, gc
->clip_rects
,
760 CGContextScaleCTM (context
, 1, -1);
761 CGContextTranslateCTM (context
, 0, -port_height
);
763 CGContextSetRGBFillColor
765 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
766 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
767 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
769 err
= ATSUSetLayoutControls (text_layout
,
770 sizeof (tags
) / sizeof (tags
[0]),
771 tags
, sizes
, values
);
773 ATSUDrawText (text_layout
,
774 kATSUFromTextBeginning
, kATSUToTextEnd
,
775 Long2Fix (x
), Long2Fix (port_height
- y
));
776 CGContextSynchronize (context
);
777 QDEndCGContext (port
, &context
);
779 /* This doesn't work on Mac OS X 10.1. */
780 ATSUClearLayoutControls (text_layout
,
781 sizeof (tags
) / sizeof (tags
[0]),
784 ATSUSetLayoutControls (text_layout
,
785 sizeof (tags
) / sizeof (tags
[0]),
786 tags
, sizes
, values
);
795 TextFont (GC_FONT (gc
)->mac_fontnum
);
796 TextSize (GC_FONT (gc
)->mac_fontsize
);
797 TextFace (GC_FONT (gc
)->mac_fontface
);
800 mac_begin_clip (GC_CLIP_REGION (gc
));
802 DrawText (buf
, 0, nchars
* bytes_per_char
);
803 mac_end_clip (GC_CLIP_REGION (gc
));
809 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
810 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
811 if (mac_use_core_graphics
)
812 SwapQDTextFlags(savedFlags
);
817 /* Mac replacement for XDrawString. */
820 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
827 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
831 /* Mac replacement for XDrawString16. */
834 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
841 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
, 2);
845 /* Mac replacement for XDrawImageString. */
848 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
)
855 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
859 /* Mac replacement for XDrawString16. */
862 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
)
869 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
, 2);
873 /* Mac replacement for XQueryTextExtents, but takes a character. If
874 STYLE is NULL, measurement is done by QuickDraw Text routines for
875 the font of the current graphics port. If CG_GLYPH is not NULL,
876 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
879 mac_query_char_extents (style
, c
,
880 font_ascent_return
, font_descent_return
,
881 overall_return
, cg_glyph
)
888 int *font_ascent_return
, *font_descent_return
;
889 XCharStruct
*overall_return
;
890 #if USE_CG_TEXT_DRAWING
903 ATSUTextLayout text_layout
;
906 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
909 ATSTrapezoid glyph_bounds
;
911 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
912 kATSUFromTextBeginning
, kATSUToTextEnd
,
913 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
914 kATSUseFractionalOrigins
,
916 kATSUseDeviceOrigins
,
918 1, &glyph_bounds
, NULL
);
921 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
922 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
924 width
= Fix2Long (glyph_bounds
.upperRight
.x
925 - glyph_bounds
.upperLeft
.x
);
926 if (font_ascent_return
)
927 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
928 if (font_descent_return
)
929 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
932 if (err
== noErr
&& overall_return
)
934 err
= ATSUMeasureTextImage (text_layout
,
935 kATSUFromTextBeginning
, kATSUToTextEnd
,
938 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
939 #if USE_CG_TEXT_DRAWING
940 if (err
== noErr
&& cg_glyph
)
943 ATSUGlyphInfoArray glyph_info_array
;
944 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
946 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
947 kATSUToTextEnd
, NULL
, NULL
, NULL
);
949 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
950 kATSUToTextEnd
, &count
,
954 xassert (glyph_info_array
.glyphs
[0].glyphID
);
955 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
966 if (font_ascent_return
|| font_descent_return
)
970 GetFontInfo (&font_info
);
971 if (font_ascent_return
)
972 *font_ascent_return
= font_info
.ascent
;
973 if (font_descent_return
)
974 *font_descent_return
= font_info
.descent
;
980 width
= CharWidth (ch
);
981 QDTextBounds (1, &ch
, &char_bounds
);
982 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
990 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
993 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
994 XFontStruct
*font_struct
;
997 XCharStruct
*overall_return
;
1000 short width
= 0, lbearing
= 0, rbearing
= 0;
1003 for (i
= 0; i
< nchars
; i
++)
1005 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1007 width
+= FONT_WIDTH (font_struct
);
1010 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1011 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1012 width
+= pcm
->width
;
1017 overall_return
->lbearing
= lbearing
;
1018 overall_return
->rbearing
= rbearing
;
1019 overall_return
->width
= width
;
1021 /* What's the meaning of the return value of XTextExtents16? */
1025 #if USE_CG_TEXT_DRAWING
1026 static int cg_text_anti_aliasing_threshold
= 8;
1029 init_cg_text_anti_aliasing_threshold ()
1032 Fmac_get_preference (build_string ("AppleAntiAliasingThreshold"),
1036 cg_text_anti_aliasing_threshold
= XINT (val
);
1040 mac_draw_string_cg (f
, gc
, x
, y
, buf
, nchars
)
1048 float port_height
, gx
, gy
;
1050 CGContextRef context
;
1054 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1057 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1058 port_height
= FRAME_PIXEL_HEIGHT (f
);
1060 gy
= port_height
- y
;
1061 glyphs
= (CGGlyph
*)buf
;
1062 advances
= xmalloc (sizeof (CGSize
) * nchars
);
1063 for (i
= 0; i
< nchars
; i
++)
1065 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1067 advances
[i
].width
= pcm
->width
;
1068 advances
[i
].height
= 0;
1069 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1073 QDBeginCGContext (port
, &context
);
1074 if (gc
->n_clip_rects
)
1076 CGContextTranslateCTM (context
, 0, port_height
);
1077 CGContextScaleCTM (context
, 1, -1);
1078 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1079 CGContextScaleCTM (context
, 1, -1);
1080 CGContextTranslateCTM (context
, 0, -port_height
);
1082 CGContextSetRGBFillColor (context
,
1083 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
1084 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
1085 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
1087 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1088 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1089 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1090 CGContextSetShouldAntialias (context
, false);
1091 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1092 CGContextSetTextPosition (context
, gx
, gy
);
1093 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1095 for (i
= 0; i
< nchars
; i
++)
1097 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1098 gx
+= advances
[i
].width
;
1101 CGContextSynchronize (context
);
1102 QDEndCGContext (port
, &context
);
1111 /* Mac replacement for XCopyArea: dest must be window. */
1114 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1119 unsigned int width
, height
;
1124 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1126 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1127 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1129 ForeColor (blackColor
);
1130 BackColor (whiteColor
);
1132 mac_begin_clip (GC_CLIP_REGION (gc
));
1133 LockPixels (GetGWorldPixMap (src
));
1134 #if TARGET_API_MAC_CARBON
1139 LockPortBits (port
);
1140 CopyBits (GetPortBitMapForCopyBits (src
),
1141 GetPortBitMapForCopyBits (port
),
1142 &src_r
, &dest_r
, srcCopy
, 0);
1143 UnlockPortBits (port
);
1145 #else /* not TARGET_API_MAC_CARBON */
1146 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1147 &src_r
, &dest_r
, srcCopy
, 0);
1148 #endif /* not TARGET_API_MAC_CARBON */
1149 UnlockPixels (GetGWorldPixMap (src
));
1150 mac_end_clip (GC_CLIP_REGION (gc
));
1152 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1157 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1158 width
, height
, dest_x
, dest_y
)
1163 unsigned int width
, height
;
1168 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1170 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1171 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1173 ForeColor (blackColor
);
1174 BackColor (whiteColor
);
1176 mac_begin_clip (GC_CLIP_REGION (gc
));
1177 LockPixels (GetGWorldPixMap (src
));
1178 LockPixels (GetGWorldPixMap (mask
));
1179 #if TARGET_API_MAC_CARBON
1184 LockPortBits (port
);
1185 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1186 GetPortBitMapForCopyBits (port
),
1187 &src_r
, &src_r
, &dest_r
);
1188 UnlockPortBits (port
);
1190 #else /* not TARGET_API_MAC_CARBON */
1191 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1192 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1193 #endif /* not TARGET_API_MAC_CARBON */
1194 UnlockPixels (GetGWorldPixMap (mask
));
1195 UnlockPixels (GetGWorldPixMap (src
));
1196 mac_end_clip (GC_CLIP_REGION (gc
));
1198 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1202 /* Mac replacement for XCopyArea: used only for scrolling. */
1205 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1209 unsigned int width
, height
;
1212 #if TARGET_API_MAC_CARBON
1214 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1216 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1217 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1218 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1219 kScrollWindowNoOptions
, dummy
);
1221 #else /* not TARGET_API_MAC_CARBON */
1223 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1227 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1228 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1230 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1231 color mapping in CopyBits. Otherwise, it will be slow. */
1232 ForeColor (blackColor
);
1233 BackColor (whiteColor
);
1234 mac_begin_clip (GC_CLIP_REGION (gc
));
1235 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1236 mac_end_clip (GC_CLIP_REGION (gc
));
1238 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1239 #endif /* not TARGET_API_MAC_CARBON */
1243 /* Mac replacement for XChangeGC. */
1246 XChangeGC (display
, gc
, mask
, xgcv
)
1252 if (mask
& GCForeground
)
1253 XSetForeground (display
, gc
, xgcv
->foreground
);
1254 if (mask
& GCBackground
)
1255 XSetBackground (display
, gc
, xgcv
->background
);
1257 XSetFont (display
, gc
, xgcv
->font
);
1261 /* Mac replacement for XCreateGC. */
1264 XCreateGC (display
, window
, mask
, xgcv
)
1270 GC gc
= xmalloc (sizeof (*gc
));
1274 bzero (gc
, sizeof (*gc
));
1275 XChangeGC (display
, gc
, mask
, xgcv
);
1282 /* Used in xfaces.c. */
1285 XFreeGC (display
, gc
)
1289 if (gc
->clip_region
)
1290 DisposeRgn (gc
->clip_region
);
1295 /* Mac replacement for XGetGCValues. */
1298 XGetGCValues (display
, gc
, mask
, xgcv
)
1304 if (mask
& GCForeground
)
1305 xgcv
->foreground
= gc
->xgcv
.foreground
;
1306 if (mask
& GCBackground
)
1307 xgcv
->background
= gc
->xgcv
.background
;
1309 xgcv
->font
= gc
->xgcv
.font
;
1313 /* Mac replacement for XSetForeground. */
1316 XSetForeground (display
, gc
, color
)
1319 unsigned long color
;
1321 if (gc
->xgcv
.foreground
!= color
)
1323 gc
->xgcv
.foreground
= color
;
1324 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1325 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1326 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1331 /* Mac replacement for XSetBackground. */
1334 XSetBackground (display
, gc
, color
)
1337 unsigned long color
;
1339 if (gc
->xgcv
.background
!= color
)
1341 gc
->xgcv
.background
= color
;
1342 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1343 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1344 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1349 /* Mac replacement for XSetFont. */
1352 XSetFont (display
, gc
, font
)
1357 gc
->xgcv
.font
= font
;
1361 /* Mac replacement for XSetClipRectangles. */
1364 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1372 if (n
< 0 || n
> MAX_CLIP_RECTS
)
1376 if (gc
->clip_region
)
1378 DisposeRgn (gc
->clip_region
);
1379 gc
->clip_region
= NULL
;
1384 if (gc
->clip_region
== NULL
)
1385 gc
->clip_region
= NewRgn ();
1386 RectRgn (gc
->clip_region
, rectangles
);
1389 RgnHandle region
= NewRgn ();
1391 for (i
= 1; i
< n
; i
++)
1393 RectRgn (region
, rectangles
+ i
);
1394 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1396 DisposeRgn (region
);
1399 #if defined (MAC_OSX) && USE_ATSUI
1400 gc
->n_clip_rects
= n
;
1402 for (i
= 0; i
< n
; i
++)
1404 Rect
*rect
= rectangles
+ i
;
1406 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1407 rect
->right
- rect
->left
,
1408 rect
->bottom
- rect
->top
);
1414 /* Mac replacement for XSetClipMask. */
1417 mac_reset_clip_rectangles (display
, gc
)
1421 mac_set_clip_rectangles (display
, gc
, NULL
, 0);
1425 /* Mac replacement for XSetWindowBackground. */
1428 XSetWindowBackground (display
, w
, color
)
1431 unsigned long color
;
1433 #if !TARGET_API_MAC_CARBON
1434 AuxWinHandle aw_handle
;
1435 CTabHandle ctab_handle
;
1436 ColorSpecPtr ct_table
;
1441 bg_color
.red
= RED16_FROM_ULONG (color
);
1442 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1443 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1445 #if TARGET_API_MAC_CARBON
1446 SetWindowContentColor (w
, &bg_color
);
1448 if (GetAuxWin (w
, &aw_handle
))
1450 ctab_handle
= (*aw_handle
)->awCTable
;
1451 HandToHand ((Handle
*) &ctab_handle
);
1452 ct_table
= (*ctab_handle
)->ctTable
;
1453 ct_size
= (*ctab_handle
)->ctSize
;
1454 while (ct_size
> -1)
1456 if (ct_table
->value
== 0)
1458 ct_table
->rgb
= bg_color
;
1459 CTabChanged (ctab_handle
);
1460 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1468 /* x_sync is a no-op on Mac. */
1476 /* Flush display of frame F, or of all frames if F is null. */
1482 #if TARGET_API_MAC_CARBON
1485 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1487 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1493 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1494 Calls to XFlush should be unnecessary because the X output buffer
1495 is flushed automatically as needed by calls to XPending,
1496 XNextEvent, or XWindowEvent according to the XFlush man page.
1497 XTread_socket calls XPending. Removing XFlush improves
1500 #define XFlush(DISPLAY) (void) 0
1503 /* Return the struct mac_display_info corresponding to DPY. There's
1506 struct mac_display_info
*
1507 mac_display_info_for_display (dpy
)
1510 return &one_mac_display_info
;
1515 /***********************************************************************
1516 Starting and ending an update
1517 ***********************************************************************/
1519 /* Start an update of frame F. This function is installed as a hook
1520 for update_begin, i.e. it is called when update_begin is called.
1521 This function is called prior to calls to x_update_window_begin for
1522 each window being updated. */
1528 #if TARGET_API_MAC_CARBON
1529 /* During update of a frame, availability of input events is
1530 periodically checked with ReceiveNextEvent if
1531 redisplay-dont-pause is nil. That normally flushes window buffer
1532 changes for every check, and thus screen update looks waving even
1533 if no input is available. So we disable screen updates during
1534 update of a frame. */
1536 DisableScreenUpdates ();
1542 /* Start update of window W. Set the global variable updated_window
1543 to the window being updated and set output_cursor to the cursor
1547 x_update_window_begin (w
)
1550 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1551 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1554 set_output_cursor (&w
->cursor
);
1558 if (f
== display_info
->mouse_face_mouse_frame
)
1560 /* Don't do highlighting for mouse motion during the update. */
1561 display_info
->mouse_face_defer
= 1;
1563 /* If F needs to be redrawn, simply forget about any prior mouse
1565 if (FRAME_GARBAGED_P (f
))
1566 display_info
->mouse_face_window
= Qnil
;
1568 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1569 their mouse_face_p flag set, which means that they are always
1570 unequal to rows in a desired matrix which never have that
1571 flag set. So, rows containing mouse-face glyphs are never
1572 scrolled, and we don't have to switch the mouse highlight off
1573 here to prevent it from being scrolled. */
1575 /* Can we tell that this update does not affect the window
1576 where the mouse highlight is? If so, no need to turn off.
1577 Likewise, don't do anything if the frame is garbaged;
1578 in that case, the frame's current matrix that we would use
1579 is all wrong, and we will redisplay that line anyway. */
1580 if (!NILP (display_info
->mouse_face_window
)
1581 && w
== XWINDOW (display_info
->mouse_face_window
))
1585 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1586 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1589 if (i
< w
->desired_matrix
->nrows
)
1590 clear_mouse_face (display_info
);
1599 /* Draw a vertical window border from (x,y0) to (x,y1) */
1602 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1606 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1609 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1611 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1614 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1617 /* End update of window W (which is equal to updated_window).
1619 Draw vertical borders between horizontally adjacent windows, and
1620 display W's cursor if CURSOR_ON_P is non-zero.
1622 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1623 glyphs in mouse-face were overwritten. In that case we have to
1624 make sure that the mouse-highlight is properly redrawn.
1626 W may be a menu bar pseudo-window in case we don't have X toolkit
1627 support. Such windows don't have a cursor, so don't display it
1631 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1633 int cursor_on_p
, mouse_face_overwritten_p
;
1635 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1637 if (!w
->pseudo_window_p
)
1642 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1644 output_cursor
.x
, output_cursor
.y
);
1646 if (draw_window_fringes (w
, 1))
1647 x_draw_vertical_border (w
);
1652 /* If a row with mouse-face was overwritten, arrange for
1653 XTframe_up_to_date to redisplay the mouse highlight. */
1654 if (mouse_face_overwritten_p
)
1656 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1657 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1658 dpyinfo
->mouse_face_window
= Qnil
;
1661 updated_window
= NULL
;
1665 /* End update of frame F. This function is installed as a hook in
1672 /* Mouse highlight may be displayed again. */
1673 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1676 #if TARGET_API_MAC_CARBON
1677 EnableScreenUpdates ();
1679 XFlush (FRAME_MAC_DISPLAY (f
));
1684 /* This function is called from various places in xdisp.c whenever a
1685 complete update has been performed. The global variable
1686 updated_window is not available here. */
1689 XTframe_up_to_date (f
)
1692 if (FRAME_MAC_P (f
))
1694 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1696 if (dpyinfo
->mouse_face_deferred_gc
1697 || f
== dpyinfo
->mouse_face_mouse_frame
)
1700 if (dpyinfo
->mouse_face_mouse_frame
)
1701 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1702 dpyinfo
->mouse_face_mouse_x
,
1703 dpyinfo
->mouse_face_mouse_y
);
1704 dpyinfo
->mouse_face_deferred_gc
= 0;
1711 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1712 arrow bitmaps, or clear the fringes if no bitmaps are required
1713 before DESIRED_ROW is made current. The window being updated is
1714 found in updated_window. This function is called from
1715 update_window_line only if it is known that there are differences
1716 between bitmaps to be drawn between current row and DESIRED_ROW. */
1719 x_after_update_window_line (desired_row
)
1720 struct glyph_row
*desired_row
;
1722 struct window
*w
= updated_window
;
1728 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1729 desired_row
->redraw_fringe_bitmaps_p
= 1;
1731 /* When a window has disappeared, make sure that no rest of
1732 full-width rows stays visible in the internal border. Could
1733 check here if updated_window is the leftmost/rightmost window,
1734 but I guess it's not worth doing since vertically split windows
1735 are almost never used, internal border is rarely set, and the
1736 overhead is very small. */
1737 if (windows_or_buffers_changed
1738 && desired_row
->full_width_p
1739 && (f
= XFRAME (w
->frame
),
1740 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1742 && (height
= desired_row
->visible_height
,
1745 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1747 /* Internal border is drawn below the tool bar. */
1748 if (WINDOWP (f
->tool_bar_window
)
1749 && w
== XWINDOW (f
->tool_bar_window
))
1753 mac_clear_area (f
, 0, y
, width
, height
);
1754 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
1760 /* Draw the bitmap WHICH in one of the left or right fringes of
1761 window W. ROW is the glyph row for which to display the bitmap; it
1762 determines the vertical position at which the bitmap has to be
1766 x_draw_fringe_bitmap (w
, row
, p
)
1768 struct glyph_row
*row
;
1769 struct draw_fringe_bitmap_params
*p
;
1771 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1772 Display
*display
= FRAME_MAC_DISPLAY (f
);
1773 struct face
*face
= p
->face
;
1776 /* Must clip because of partially visible lines. */
1777 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1780 /* Adjust position of "bottom aligned" bitmap on partially
1781 visible last row. */
1783 int oldVH
= row
->visible_height
;
1784 row
->visible_height
= p
->h
;
1785 row
->y
-= rowY
- p
->y
;
1786 x_clip_to_row (w
, row
, -1, face
->gc
);
1788 row
->visible_height
= oldVH
;
1791 x_clip_to_row (w
, row
, -1, face
->gc
);
1793 if (p
->bx
>= 0 && !p
->overlay_p
)
1795 #if 0 /* MAC_TODO: stipple */
1796 /* In case the same realized face is used for fringes and
1797 for something displayed in the text (e.g. face `region' on
1798 mono-displays, the fill style may have been changed to
1799 FillSolid in x_draw_glyph_string_background. */
1801 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1803 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1806 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1808 #if 0 /* MAC_TODO: stipple */
1810 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1816 unsigned short *bits
= p
->bits
+ p
->dh
;
1819 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
1820 XSetForeground (display
, face
->gc
,
1822 ? (p
->overlay_p
? face
->background
1823 : f
->output_data
.mac
->cursor_pixel
)
1824 : face
->foreground
));
1825 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
1826 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1827 XSetForeground (display
, face
->gc
, gcv
.foreground
);
1830 mac_reset_clip_rectangles (display
, face
->gc
);
1835 /* This is called when starting Emacs and when restarting after
1836 suspend. When starting Emacs, no window is mapped. And nothing
1837 must be done to Emacs's own window if it is suspended (though that
1841 XTset_terminal_modes ()
1845 /* This is called when exiting or suspending Emacs. Exiting will make
1846 the windows go away, and suspending requires no action. */
1849 XTreset_terminal_modes ()
1855 /***********************************************************************
1857 ***********************************************************************/
1859 /* Function prototypes of this page. */
1861 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1862 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
1863 struct charset
*, int *));
1866 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1867 is not contained in the font. */
1869 static INLINE XCharStruct
*
1870 x_per_char_metric (font
, char2b
)
1874 /* The result metric information. */
1875 XCharStruct
*pcm
= NULL
;
1877 xassert (font
&& char2b
);
1880 if (font
->mac_style
)
1882 XCharStructRow
**row
= font
->bounds
.rows
+ char2b
->byte1
;
1886 *row
= xmalloc (sizeof (XCharStructRow
));
1888 bzero (*row
, sizeof (XCharStructRow
));
1892 pcm
= (*row
)->per_char
+ char2b
->byte2
;
1893 if (!XCHARSTRUCTROW_CHAR_VALID_P (*row
, char2b
->byte2
))
1896 mac_query_char_extents (font
->mac_style
,
1897 (char2b
->byte1
<< 8) + char2b
->byte2
,
1898 NULL
, NULL
, pcm
, NULL
);
1900 XCHARSTRUCTROW_SET_CHAR_VALID (*row
, char2b
->byte2
);
1907 if (font
->bounds
.per_char
!= NULL
)
1909 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1911 /* min_char_or_byte2 specifies the linear character index
1912 corresponding to the first element of the per_char array,
1913 max_char_or_byte2 is the index of the last character. A
1914 character with non-zero CHAR2B->byte1 is not in the font.
1915 A character with byte2 less than min_char_or_byte2 or
1916 greater max_char_or_byte2 is not in the font. */
1917 if (char2b
->byte1
== 0
1918 && char2b
->byte2
>= font
->min_char_or_byte2
1919 && char2b
->byte2
<= font
->max_char_or_byte2
)
1920 pcm
= font
->bounds
.per_char
1921 + (char2b
->byte2
- font
->min_char_or_byte2
);
1925 /* If either min_byte1 or max_byte1 are nonzero, both
1926 min_char_or_byte2 and max_char_or_byte2 are less than
1927 256, and the 2-byte character index values corresponding
1928 to the per_char array element N (counting from 0) are:
1930 byte1 = N/D + min_byte1
1931 byte2 = N\D + min_char_or_byte2
1935 D = max_char_or_byte2 - min_char_or_byte2 + 1
1936 / = integer division
1937 \ = integer modulus */
1938 if (char2b
->byte1
>= font
->min_byte1
1939 && char2b
->byte1
<= font
->max_byte1
1940 && char2b
->byte2
>= font
->min_char_or_byte2
1941 && char2b
->byte2
<= font
->max_char_or_byte2
)
1943 pcm
= (font
->bounds
.per_char
1944 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1945 * (char2b
->byte1
- font
->min_byte1
))
1946 + (char2b
->byte2
- font
->min_char_or_byte2
));
1952 /* If the per_char pointer is null, all glyphs between the first
1953 and last character indexes inclusive have the same
1954 information, as given by both min_bounds and max_bounds. */
1955 if (char2b
->byte2
>= font
->min_char_or_byte2
1956 && char2b
->byte2
<= font
->max_char_or_byte2
)
1957 pcm
= &font
->max_bounds
;
1963 return ((pcm
== NULL
1964 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1971 static XCharStruct
*
1972 mac_per_char_metric (font
, char2b
, font_type
)
1977 return x_per_char_metric (font
, char2b
);
1981 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1982 the two-byte form of C. Encoding is returned in *CHAR2B. */
1985 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
1988 struct font_info
*font_info
;
1989 struct charset
*charset
;
1992 XFontStruct
*font
= font_info
->font
;
1994 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1995 This may be either a program in a special encoder language or a
1997 if (font_info
->font_encoder
)
1999 /* It's a program. */
2000 struct ccl_program
*ccl
= font_info
->font_encoder
;
2002 check_ccl_update (ccl
);
2003 if (CHARSET_DIMENSION (charset
) == 1)
2005 ccl
->reg
[0] = CHARSET_ID (charset
);
2006 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
2011 ccl
->reg
[0] = CHARSET_ID (charset
);
2012 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
2013 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
2016 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
2018 /* We assume that MSBs are appropriately set/reset by CCL
2020 if (font
->max_byte1
== 0) /* 1-byte font */
2021 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
2023 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
2025 else if (font_info
->encoding_type
)
2027 /* Fixed encoding scheme. See fontset.h for the meaning of the
2028 encoding numbers. */
2029 unsigned char enc
= font_info
->encoding_type
;
2031 if ((enc
== 1 || enc
== 2)
2032 && CHARSET_DIMENSION (charset
) == 2)
2033 char2b
->byte1
|= 0x80;
2035 if (enc
== 1 || enc
== 3)
2036 char2b
->byte2
|= 0x80;
2040 int code
= (char2b
->byte1
<< 8) | char2b
->byte2
;
2043 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
2048 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2050 return FONT_TYPE_UNKNOWN
;
2055 /***********************************************************************
2057 ***********************************************************************/
2061 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2062 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2063 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2065 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2066 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2067 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2068 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2069 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2070 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2071 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2072 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2073 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2074 unsigned long *, double, int));*/
2075 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2076 double, int, unsigned long));
2077 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2078 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2079 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2080 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2081 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2082 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2084 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2085 int, int, int, int, int, int,
2087 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2088 int, int, int, Rect
*));
2091 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2095 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2100 struct glyph_string
*s
;
2102 if (s
->font
== FRAME_FONT (s
->f
)
2103 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2104 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2106 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2109 /* Cursor on non-default face: must merge. */
2113 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2114 xgcv
.foreground
= s
->face
->background
;
2116 /* If the glyph would be invisible, try a different foreground. */
2117 if (xgcv
.foreground
== xgcv
.background
)
2118 xgcv
.foreground
= s
->face
->foreground
;
2119 if (xgcv
.foreground
== xgcv
.background
)
2120 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2121 if (xgcv
.foreground
== xgcv
.background
)
2122 xgcv
.foreground
= s
->face
->foreground
;
2124 /* Make sure the cursor is distinct from text in this face. */
2125 if (xgcv
.background
== s
->face
->background
2126 && xgcv
.foreground
== s
->face
->foreground
)
2128 xgcv
.background
= s
->face
->foreground
;
2129 xgcv
.foreground
= s
->face
->background
;
2132 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2133 xgcv
.font
= s
->font
;
2134 mask
= GCForeground
| GCBackground
| GCFont
;
2136 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2137 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2140 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2141 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2143 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2148 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2151 x_set_mouse_face_gc (s
)
2152 struct glyph_string
*s
;
2157 /* What face has to be used last for the mouse face? */
2158 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2159 face
= FACE_FROM_ID (s
->f
, face_id
);
2161 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2163 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2164 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
2166 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
2167 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2168 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2170 /* If font in this face is same as S->font, use it. */
2171 if (s
->font
== s
->face
->font
)
2172 s
->gc
= s
->face
->gc
;
2175 /* Otherwise construct scratch_cursor_gc with values from FACE
2180 xgcv
.background
= s
->face
->background
;
2181 xgcv
.foreground
= s
->face
->foreground
;
2182 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2183 xgcv
.font
= s
->font
;
2184 mask
= GCForeground
| GCBackground
| GCFont
;
2186 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2187 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2190 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2191 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2193 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2196 xassert (s
->gc
!= 0);
2200 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2201 Faces to use in the mode line have already been computed when the
2202 matrix was built, so there isn't much to do, here. */
2205 x_set_mode_line_face_gc (s
)
2206 struct glyph_string
*s
;
2208 s
->gc
= s
->face
->gc
;
2212 /* Set S->gc of glyph string S for drawing that glyph string. Set
2213 S->stippled_p to a non-zero value if the face of S has a stipple
2217 x_set_glyph_string_gc (s
)
2218 struct glyph_string
*s
;
2220 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2222 if (s
->hl
== DRAW_NORMAL_TEXT
)
2224 s
->gc
= s
->face
->gc
;
2225 s
->stippled_p
= s
->face
->stipple
!= 0;
2227 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2229 x_set_mode_line_face_gc (s
);
2230 s
->stippled_p
= s
->face
->stipple
!= 0;
2232 else if (s
->hl
== DRAW_CURSOR
)
2234 x_set_cursor_gc (s
);
2237 else if (s
->hl
== DRAW_MOUSE_FACE
)
2239 x_set_mouse_face_gc (s
);
2240 s
->stippled_p
= s
->face
->stipple
!= 0;
2242 else if (s
->hl
== DRAW_IMAGE_RAISED
2243 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2245 s
->gc
= s
->face
->gc
;
2246 s
->stippled_p
= s
->face
->stipple
!= 0;
2250 s
->gc
= s
->face
->gc
;
2251 s
->stippled_p
= s
->face
->stipple
!= 0;
2254 /* GC must have been set. */
2255 xassert (s
->gc
!= 0);
2259 /* Set clipping for output of glyph string S. S may be part of a mode
2260 line or menu if we don't have X toolkit support. */
2263 x_set_glyph_string_clipping (s
)
2264 struct glyph_string
*s
;
2266 Rect rects
[MAX_CLIP_RECTS
];
2269 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2270 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2275 Compute left and right overhang of glyph string S. If S is a glyph
2276 string for a composition, assume overhangs don't exist. */
2279 mac_compute_glyph_string_overhangs (s
)
2280 struct glyph_string
*s
;
2283 && s
->first_glyph
->type
== CHAR_GLYPH
)
2286 || s
->font
->mac_style
2292 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2293 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2294 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2299 MacFontStruct
*font
= s
->font
;
2301 TextFont (font
->mac_fontnum
);
2302 TextSize (font
->mac_fontsize
);
2303 TextFace (font
->mac_fontface
);
2305 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2307 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2308 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2313 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2316 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2317 struct glyph_string
*s
;
2320 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2324 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2325 on Mac OS X because:
2326 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2327 into an offscreen graphics world first. So performance gain
2328 cannot be expected.)
2329 - It lowers rendering quality.
2330 - Some fonts leave garbage on cursor movement. */
2332 /* Draw the background of glyph_string S. If S->background_filled_p
2333 is non-zero don't draw it. FORCE_P non-zero means draw the
2334 background even if it wouldn't be drawn normally. This is used
2335 when a string preceding S draws into the background of S, or S
2336 contains the first component of a composition. */
2339 x_draw_glyph_string_background (s
, force_p
)
2340 struct glyph_string
*s
;
2343 /* Nothing to do if background has already been drawn or if it
2344 shouldn't be drawn in the first place. */
2345 if (!s
->background_filled_p
)
2347 int box_line_width
= max (s
->face
->box_line_width
, 0);
2349 #if 0 /* MAC_TODO: stipple */
2352 /* Fill background with a stipple pattern. */
2353 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2354 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2355 s
->y
+ box_line_width
,
2356 s
->background_width
,
2357 s
->height
- 2 * box_line_width
);
2358 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2359 s
->background_filled_p
= 1;
2363 #if defined (MAC_OS8) && !USE_ATSUI
2364 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2365 || s
->font_not_found_p
2366 || s
->extends_to_end_of_line_p
2370 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2371 s
->background_width
,
2372 s
->height
- 2 * box_line_width
);
2373 s
->background_filled_p
= 1;
2379 /* Draw the foreground of glyph string S. */
2382 x_draw_glyph_string_foreground (s
)
2383 struct glyph_string
*s
;
2387 /* If first glyph of S has a left box line, start drawing the text
2388 of S to the right of that box line. */
2389 if (s
->face
->box
!= FACE_NO_BOX
2390 && s
->first_glyph
->left_box_line_p
)
2391 x
= s
->x
+ abs (s
->face
->box_line_width
);
2395 /* Draw characters of S as rectangles if S's font could not be
2397 if (s
->font_not_found_p
)
2399 for (i
= 0; i
< s
->nchars
; ++i
)
2401 struct glyph
*g
= s
->first_glyph
+ i
;
2402 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2403 g
->pixel_width
- 1, s
->height
- 1);
2404 x
+= g
->pixel_width
;
2409 char *char1b
= (char *) s
->char2b
;
2410 int boff
= s
->font_info
->baseline_offset
;
2412 if (s
->font_info
->vertical_centering
)
2413 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2415 /* If we can use 8-bit functions, condense S->char2b. */
2418 && GC_FONT (s
->gc
)->mac_style
== NULL
2421 for (i
= 0; i
< s
->nchars
; ++i
)
2422 char1b
[i
] = s
->char2b
[i
].byte2
;
2424 #if defined (MAC_OS8) && !USE_ATSUI
2425 /* Draw text with XDrawString if background has already been
2426 filled. Otherwise, use XDrawImageString. (Note that
2427 XDrawImageString is usually faster than XDrawString.) Always
2428 use XDrawImageString when drawing the cursor so that there is
2429 no chance that characters under a box cursor are invisible. */
2431 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2434 /* Draw characters with 16-bit or 8-bit functions. */
2437 || GC_FONT (s
->gc
)->mac_style
2440 #if USE_CG_TEXT_DRAWING
2442 && mac_draw_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2443 s
->char2b
, s
->nchars
))
2447 mac_draw_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2448 s
->char2b
, s
->nchars
);
2450 mac_draw_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2453 #if defined (MAC_OS8) && !USE_ATSUI
2457 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2458 s
->char2b
, s
->nchars
);
2460 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2467 /* Draw the foreground of composite glyph string S. */
2470 x_draw_composite_glyph_string_foreground (s
)
2471 struct glyph_string
*s
;
2475 /* If first glyph of S has a left box line, start drawing the text
2476 of S to the right of that box line. */
2477 if (s
->face
->box
!= FACE_NO_BOX
2478 && s
->first_glyph
->left_box_line_p
)
2479 x
= s
->x
+ abs (s
->face
->box_line_width
);
2483 /* S is a glyph string for a composition. S->gidx is the index of
2484 the first character drawn for glyphs of this composition.
2485 S->gidx == 0 means we are drawing the very first character of
2486 this composition. */
2488 /* Draw a rectangle for the composition if the font for the very
2489 first character of the composition could not be loaded. */
2490 if (s
->font_not_found_p
)
2493 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2494 s
->width
- 1, s
->height
- 1);
2498 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2499 mac_draw_string_16 (s
->f
, s
->gc
,
2500 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2501 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2507 #ifdef USE_X_TOOLKIT
2509 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2512 /* Return the frame on which widget WIDGET is used.. Abort if frame
2513 cannot be determined. */
2515 static struct frame
*
2516 x_frame_of_widget (widget
)
2519 struct x_display_info
*dpyinfo
;
2523 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2525 /* Find the top-level shell of the widget. Note that this function
2526 can be called when the widget is not yet realized, so XtWindow
2527 (widget) == 0. That's the reason we can't simply use
2528 x_any_window_to_frame. */
2529 while (!XtIsTopLevelShell (widget
))
2530 widget
= XtParent (widget
);
2532 /* Look for a frame with that top-level widget. Allocate the color
2533 on that frame to get the right gamma correction value. */
2534 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2535 if (GC_FRAMEP (XCAR (tail
))
2536 && (f
= XFRAME (XCAR (tail
)),
2537 (f
->output_data
.nothing
!= 1
2538 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2539 && f
->output_data
.x
->widget
== widget
)
2546 /* Allocate the color COLOR->pixel on the screen and display of
2547 widget WIDGET in colormap CMAP. If an exact match cannot be
2548 allocated, try the nearest color available. Value is non-zero
2549 if successful. This is called from lwlib. */
2552 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2557 struct frame
*f
= x_frame_of_widget (widget
);
2558 return x_alloc_nearest_color (f
, cmap
, color
);
2562 #endif /* USE_X_TOOLKIT */
2564 #if 0 /* MAC_TODO */
2566 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2567 CMAP. If an exact match can't be allocated, try the nearest color
2568 available. Value is non-zero if successful. Set *COLOR to the
2572 x_alloc_nearest_color (f
, cmap
, color
)
2577 Display
*display
= FRAME_X_DISPLAY (f
);
2578 Screen
*screen
= FRAME_X_SCREEN (f
);
2581 gamma_correct (f
, color
);
2582 rc
= XAllocColor (display
, cmap
, color
);
2585 /* If we got to this point, the colormap is full, so we're going
2586 to try to get the next closest color. The algorithm used is
2587 a least-squares matching, which is what X uses for closest
2588 color matching with StaticColor visuals. */
2590 unsigned long nearest_delta
= ~0;
2591 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2592 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2594 for (i
= 0; i
< ncells
; ++i
)
2596 XQueryColors (display
, cmap
, cells
, ncells
);
2598 for (nearest
= i
= 0; i
< ncells
; ++i
)
2600 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2601 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2602 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2603 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2605 if (delta
< nearest_delta
)
2608 nearest_delta
= delta
;
2612 color
->red
= cells
[nearest
].red
;
2613 color
->green
= cells
[nearest
].green
;
2614 color
->blue
= cells
[nearest
].blue
;
2615 rc
= XAllocColor (display
, cmap
, color
);
2618 #ifdef DEBUG_X_COLORS
2620 register_color (color
->pixel
);
2621 #endif /* DEBUG_X_COLORS */
2627 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2628 It's necessary to do this instead of just using PIXEL directly to
2629 get color reference counts right. */
2632 x_copy_color (f
, pixel
)
2634 unsigned long pixel
;
2638 color
.pixel
= pixel
;
2640 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2641 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2643 #ifdef DEBUG_X_COLORS
2644 register_color (pixel
);
2650 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2651 It's necessary to do this instead of just using PIXEL directly to
2652 get color reference counts right. */
2655 x_copy_dpy_color (dpy
, cmap
, pixel
)
2658 unsigned long pixel
;
2662 color
.pixel
= pixel
;
2664 XQueryColor (dpy
, cmap
, &color
);
2665 XAllocColor (dpy
, cmap
, &color
);
2667 #ifdef DEBUG_X_COLORS
2668 register_color (pixel
);
2673 #endif /* MAC_TODO */
2676 /* Brightness beyond which a color won't have its highlight brightness
2679 Nominally, highlight colors for `3d' faces are calculated by
2680 brightening an object's color by a constant scale factor, but this
2681 doesn't yield good results for dark colors, so for colors who's
2682 brightness is less than this value (on a scale of 0-255) have to
2683 use an additional additive factor.
2685 The value here is set so that the default menu-bar/mode-line color
2686 (grey75) will not have its highlights changed at all. */
2687 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2690 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2691 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2692 If this produces the same color as COLOR, try a color where all RGB
2693 values have DELTA added. Return the allocated color in *COLOR.
2694 DISPLAY is the X display, CMAP is the colormap to operate on.
2695 Value is non-zero if successful. */
2698 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2700 unsigned long *color
;
2707 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2710 /* Change RGB values by specified FACTOR. Avoid overflow! */
2711 xassert (factor
>= 0);
2712 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2713 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2714 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2716 /* Calculate brightness of COLOR. */
2717 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2718 + BLUE_FROM_ULONG (*color
)) / 6;
2720 /* We only boost colors that are darker than
2721 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2722 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2723 /* Make an additive adjustment to NEW, because it's dark enough so
2724 that scaling by FACTOR alone isn't enough. */
2726 /* How far below the limit this color is (0 - 1, 1 being darker). */
2727 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2728 /* The additive adjustment. */
2729 int min_delta
= delta
* dimness
* factor
/ 2;
2732 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2733 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2734 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2736 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2737 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2738 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2742 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2743 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2744 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2746 /* MAC_TODO: Map to palette and retry with delta if same? */
2747 /* MAC_TODO: Free colors (if using palette)? */
2758 /* Set up the foreground color for drawing relief lines of glyph
2759 string S. RELIEF is a pointer to a struct relief containing the GC
2760 with which lines will be drawn. Use a color that is FACTOR or
2761 DELTA lighter or darker than the relief's background which is found
2762 in S->f->output_data.x->relief_background. If such a color cannot
2763 be allocated, use DEFAULT_PIXEL, instead. */
2766 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2768 struct relief
*relief
;
2771 unsigned long default_pixel
;
2774 struct mac_output
*di
= f
->output_data
.mac
;
2775 unsigned long mask
= GCForeground
;
2776 unsigned long pixel
;
2777 unsigned long background
= di
->relief_background
;
2778 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2780 /* MAC_TODO: Free colors (if using palette)? */
2782 /* Allocate new color. */
2783 xgcv
.foreground
= default_pixel
;
2785 if (dpyinfo
->n_planes
!= 1
2786 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2788 relief
->allocated_p
= 1;
2789 xgcv
.foreground
= relief
->pixel
= pixel
;
2792 if (relief
->gc
== 0)
2794 #if 0 /* MAC_TODO: stipple */
2795 xgcv
.stipple
= dpyinfo
->gray
;
2798 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2801 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2805 /* Set up colors for the relief lines around glyph string S. */
2808 x_setup_relief_colors (s
)
2809 struct glyph_string
*s
;
2811 struct mac_output
*di
= s
->f
->output_data
.mac
;
2812 unsigned long color
;
2814 if (s
->face
->use_box_color_for_shadows_p
)
2815 color
= s
->face
->box_color
;
2816 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2818 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2819 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2824 /* Get the background color of the face. */
2825 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2826 color
= xgcv
.background
;
2829 if (di
->white_relief
.gc
== 0
2830 || color
!= di
->relief_background
)
2832 di
->relief_background
= color
;
2833 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2834 WHITE_PIX_DEFAULT (s
->f
));
2835 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2836 BLACK_PIX_DEFAULT (s
->f
));
2841 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2842 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2843 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2844 relief. LEFT_P non-zero means draw a relief on the left side of
2845 the rectangle. RIGHT_P non-zero means draw a relief on the right
2846 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2850 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2851 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2853 int left_x
, top_y
, right_x
, bottom_y
, width
;
2854 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2857 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2862 gc
= f
->output_data
.mac
->white_relief
.gc
;
2864 gc
= f
->output_data
.mac
->black_relief
.gc
;
2865 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2869 for (i
= 0; i
< width
; ++i
)
2870 mac_draw_line (f
, gc
,
2871 left_x
+ i
* left_p
, top_y
+ i
,
2872 right_x
- i
* right_p
, top_y
+ i
);
2876 for (i
= 0; i
< width
; ++i
)
2877 mac_draw_line (f
, gc
,
2878 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2880 mac_reset_clip_rectangles (dpy
, gc
);
2882 gc
= f
->output_data
.mac
->black_relief
.gc
;
2884 gc
= f
->output_data
.mac
->white_relief
.gc
;
2885 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2889 for (i
= 0; i
< width
; ++i
)
2890 mac_draw_line (f
, gc
,
2891 left_x
+ i
* left_p
, bottom_y
- i
,
2892 right_x
- i
* right_p
, bottom_y
- i
);
2896 for (i
= 0; i
< width
; ++i
)
2897 mac_draw_line (f
, gc
,
2898 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2900 mac_reset_clip_rectangles (dpy
, gc
);
2904 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2905 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2906 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2907 left side of the rectangle. RIGHT_P non-zero means draw a line
2908 on the right side of the rectangle. CLIP_RECT is the clipping
2909 rectangle to use when drawing. */
2912 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2913 left_p
, right_p
, clip_rect
)
2914 struct glyph_string
*s
;
2915 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2920 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2921 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2922 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
2925 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2926 right_x
- left_x
+ 1, width
);
2930 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2931 width
, bottom_y
- top_y
+ 1);
2934 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
2935 right_x
- left_x
+ 1, width
);
2939 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
2940 top_y
, width
, bottom_y
- top_y
+ 1);
2942 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2943 mac_reset_clip_rectangles (s
->display
, s
->gc
);
2947 /* Draw a box around glyph string S. */
2950 x_draw_glyph_string_box (s
)
2951 struct glyph_string
*s
;
2953 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2954 int left_p
, right_p
;
2955 struct glyph
*last_glyph
;
2958 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2959 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2960 : window_box_right (s
->w
, s
->area
));
2962 /* The glyph that may have a right box line. */
2963 last_glyph
= (s
->cmp
|| s
->img
2965 : s
->first_glyph
+ s
->nchars
- 1);
2967 width
= abs (s
->face
->box_line_width
);
2968 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2970 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2972 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2974 bottom_y
= top_y
+ s
->height
- 1;
2976 left_p
= (s
->first_glyph
->left_box_line_p
2977 || (s
->hl
== DRAW_MOUSE_FACE
2979 || s
->prev
->hl
!= s
->hl
)));
2980 right_p
= (last_glyph
->right_box_line_p
2981 || (s
->hl
== DRAW_MOUSE_FACE
2983 || s
->next
->hl
!= s
->hl
)));
2985 get_glyph_string_clip_rect (s
, &clip_rect
);
2987 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2988 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2989 left_p
, right_p
, &clip_rect
);
2992 x_setup_relief_colors (s
);
2993 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2994 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2999 /* Draw foreground of image glyph string S. */
3002 x_draw_image_foreground (s
)
3003 struct glyph_string
*s
;
3006 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3008 /* If first glyph of S has a left box line, start drawing it to the
3009 right of that line. */
3010 if (s
->face
->box
!= FACE_NO_BOX
3011 && s
->first_glyph
->left_box_line_p
3013 x
+= abs (s
->face
->box_line_width
);
3015 /* If there is a margin around the image, adjust x- and y-position
3017 if (s
->slice
.x
== 0)
3018 x
+= s
->img
->hmargin
;
3019 if (s
->slice
.y
== 0)
3020 y
+= s
->img
->vmargin
;
3024 x_set_glyph_string_clipping (s
);
3027 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3028 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3029 s
->slice
.width
, s
->slice
.height
, x
, y
);
3032 mac_copy_area (s
->img
->pixmap
,
3033 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3034 s
->slice
.width
, s
->slice
.height
, x
, y
);
3036 /* When the image has a mask, we can expect that at
3037 least part of a mouse highlight or a block cursor will
3038 be visible. If the image doesn't have a mask, make
3039 a block cursor visible by drawing a rectangle around
3040 the image. I believe it's looking better if we do
3041 nothing here for mouse-face. */
3042 if (s
->hl
== DRAW_CURSOR
)
3044 int r
= s
->img
->relief
;
3046 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3047 s
->slice
.width
+ r
*2 - 1,
3048 s
->slice
.height
+ r
*2 - 1);
3053 /* Draw a rectangle if image could not be loaded. */
3054 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3055 s
->slice
.width
- 1, s
->slice
.height
- 1);
3059 /* Draw a relief around the image glyph string S. */
3062 x_draw_image_relief (s
)
3063 struct glyph_string
*s
;
3065 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3068 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3070 /* If first glyph of S has a left box line, start drawing it to the
3071 right of that line. */
3072 if (s
->face
->box
!= FACE_NO_BOX
3073 && s
->first_glyph
->left_box_line_p
3075 x
+= abs (s
->face
->box_line_width
);
3077 /* If there is a margin around the image, adjust x- and y-position
3079 if (s
->slice
.x
== 0)
3080 x
+= s
->img
->hmargin
;
3081 if (s
->slice
.y
== 0)
3082 y
+= s
->img
->vmargin
;
3084 if (s
->hl
== DRAW_IMAGE_SUNKEN
3085 || s
->hl
== DRAW_IMAGE_RAISED
)
3087 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3088 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3092 thick
= abs (s
->img
->relief
);
3093 raised_p
= s
->img
->relief
> 0;
3098 x1
= x
+ s
->slice
.width
+ thick
- 1;
3099 y1
= y
+ s
->slice
.height
+ thick
- 1;
3101 x_setup_relief_colors (s
);
3102 get_glyph_string_clip_rect (s
, &r
);
3103 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3105 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3107 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3112 /* Draw part of the background of glyph string S. X, Y, W, and H
3113 give the rectangle to draw. */
3116 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3117 struct glyph_string
*s
;
3120 #if 0 /* MAC_TODO: stipple */
3123 /* Fill background with a stipple pattern. */
3124 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3125 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3126 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3129 #endif /* MAC_TODO */
3130 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3134 /* Draw image glyph string S.
3137 s->x +-------------------------
3140 | +-------------------------
3143 | | +-------------------
3149 x_draw_image_glyph_string (s
)
3150 struct glyph_string
*s
;
3153 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3154 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3158 height
= s
->height
- 2 * box_line_vwidth
;
3161 /* Fill background with face under the image. Do it only if row is
3162 taller than image or if image has a clip mask to reduce
3164 s
->stippled_p
= s
->face
->stipple
!= 0;
3165 if (height
> s
->slice
.height
3169 || s
->img
->pixmap
== 0
3170 || s
->width
!= s
->background_width
)
3173 if (s
->first_glyph
->left_box_line_p
3175 x
+= box_line_hwidth
;
3178 if (s
->slice
.y
== 0)
3179 y
+= box_line_vwidth
;
3181 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3183 s
->background_filled_p
= 1;
3186 /* Draw the foreground. */
3187 x_draw_image_foreground (s
);
3189 /* If we must draw a relief around the image, do it. */
3191 || s
->hl
== DRAW_IMAGE_RAISED
3192 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3193 x_draw_image_relief (s
);
3197 /* Draw stretch glyph string S. */
3200 x_draw_stretch_glyph_string (s
)
3201 struct glyph_string
*s
;
3203 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3204 s
->stippled_p
= s
->face
->stipple
!= 0;
3206 if (s
->hl
== DRAW_CURSOR
3207 && !x_stretch_cursor_p
)
3209 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3210 as wide as the stretch glyph. */
3211 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3214 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3216 /* Clear rest using the GC of the original non-cursor face. */
3217 if (width
< s
->background_width
)
3219 int x
= s
->x
+ width
, y
= s
->y
;
3220 int w
= s
->background_width
- width
, h
= s
->height
;
3224 if (s
->row
->mouse_face_p
3225 && cursor_in_mouse_face_p (s
->w
))
3227 x_set_mouse_face_gc (s
);
3233 get_glyph_string_clip_rect (s
, &r
);
3234 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3236 #if 0 /* MAC_TODO: stipple */
3237 if (s
->face
->stipple
)
3239 /* Fill background with a stipple pattern. */
3240 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3241 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3242 XSetFillStyle (s
->display
, gc
, FillSolid
);
3245 #endif /* MAC_TODO */
3246 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3249 else if (!s
->background_filled_p
)
3250 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3253 s
->background_filled_p
= 1;
3257 /* Draw glyph string S. */
3260 x_draw_glyph_string (s
)
3261 struct glyph_string
*s
;
3263 int relief_drawn_p
= 0;
3265 /* If S draws into the background of its successor that does not
3266 draw a cursor, draw the background of the successor first so that
3267 S can draw into it. This makes S->next use XDrawString instead
3268 of XDrawImageString. */
3269 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3270 && s
->next
->hl
!= DRAW_CURSOR
)
3272 xassert (s
->next
->img
== NULL
);
3273 x_set_glyph_string_gc (s
->next
);
3274 x_set_glyph_string_clipping (s
->next
);
3275 x_draw_glyph_string_background (s
->next
, 1);
3278 /* Set up S->gc, set clipping and draw S. */
3279 x_set_glyph_string_gc (s
);
3281 /* Draw relief (if any) in advance for char/composition so that the
3282 glyph string can be drawn over it. */
3283 if (!s
->for_overlaps
3284 && s
->face
->box
!= FACE_NO_BOX
3285 && (s
->first_glyph
->type
== CHAR_GLYPH
3286 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3289 x_set_glyph_string_clipping (s
);
3290 x_draw_glyph_string_background (s
, 1);
3291 x_draw_glyph_string_box (s
);
3292 x_set_glyph_string_clipping (s
);
3296 x_set_glyph_string_clipping (s
);
3298 switch (s
->first_glyph
->type
)
3301 x_draw_image_glyph_string (s
);
3305 x_draw_stretch_glyph_string (s
);
3309 if (s
->for_overlaps
)
3310 s
->background_filled_p
= 1;
3312 x_draw_glyph_string_background (s
, 0);
3313 x_draw_glyph_string_foreground (s
);
3316 case COMPOSITE_GLYPH
:
3317 if (s
->for_overlaps
|| s
->gidx
> 0)
3318 s
->background_filled_p
= 1;
3320 x_draw_glyph_string_background (s
, 1);
3321 x_draw_composite_glyph_string_foreground (s
);
3328 if (!s
->for_overlaps
)
3330 /* Draw underline. */
3331 if (s
->face
->underline_p
)
3333 unsigned long h
= 1;
3334 unsigned long dy
= s
->height
- h
;
3336 if (s
->face
->underline_defaulted_p
)
3337 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3342 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3343 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3344 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3346 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3350 /* Draw overline. */
3351 if (s
->face
->overline_p
)
3353 unsigned long dy
= 0, h
= 1;
3355 if (s
->face
->overline_color_defaulted_p
)
3356 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3361 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3362 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3363 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3365 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3369 /* Draw strike-through. */
3370 if (s
->face
->strike_through_p
)
3372 unsigned long h
= 1;
3373 unsigned long dy
= (s
->height
- h
) / 2;
3375 if (s
->face
->strike_through_color_defaulted_p
)
3376 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3381 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3382 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3383 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3385 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3389 /* Draw relief if not yet drawn. */
3390 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3391 x_draw_glyph_string_box (s
);
3394 /* Reset clipping. */
3395 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3398 /* Shift display to make room for inserted glyphs. */
3401 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3403 int x
, y
, width
, height
, shift_by
;
3405 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3406 x
, y
, width
, height
,
3410 /* Delete N glyphs at the nominal cursor position. Not implemented
3421 /* Clear entire frame. If updating_frame is non-null, clear that
3422 frame. Otherwise clear the selected frame. */
3432 f
= SELECTED_FRAME ();
3434 /* Clearing the frame will erase any cursor, so mark them all as no
3436 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3437 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3438 output_cursor
.x
= -1;
3440 /* We don't set the output cursor here because there will always
3441 follow an explicit cursor_to. */
3443 mac_clear_window (f
);
3445 /* We have to clear the scroll bars, too. If we have changed
3446 colors or something like that, then they should be notified. */
3447 x_scroll_bar_clear (f
);
3449 XFlush (FRAME_MAC_DISPLAY (f
));
3455 /* Invert the middle quarter of the frame for .15 sec. */
3457 /* We use the select system call to do the waiting, so we have to make
3458 sure it's available. If it isn't, we just won't do visual bells. */
3460 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3463 /* Subtract the `struct timeval' values X and Y, storing the result in
3464 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3467 timeval_subtract (result
, x
, y
)
3468 struct timeval
*result
, x
, y
;
3470 /* Perform the carry for the later subtraction by updating y. This
3471 is safer because on some systems the tv_sec member is unsigned. */
3472 if (x
.tv_usec
< y
.tv_usec
)
3474 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3475 y
.tv_usec
-= 1000000 * nsec
;
3479 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3481 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3482 y
.tv_usec
+= 1000000 * nsec
;
3486 /* Compute the time remaining to wait. tv_usec is certainly
3488 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3489 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3491 /* Return indication of whether the result should be considered
3493 return x
.tv_sec
< y
.tv_sec
;
3500 /* Get the height not including a menu bar widget. */
3501 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3502 /* Height of each line to flash. */
3503 int flash_height
= FRAME_LINE_HEIGHT (f
);
3504 /* These will be the left and right margins of the rectangles. */
3505 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3506 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3510 /* Don't flash the area between a scroll bar and the frame
3511 edge it is next to. */
3512 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3514 case vertical_scroll_bar_left
:
3515 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3518 case vertical_scroll_bar_right
:
3519 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3526 width
= flash_right
- flash_left
;
3530 /* If window is tall, flash top and bottom line. */
3531 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3533 mac_invert_rectangle (f
, flash_left
,
3534 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3535 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3536 width
, flash_height
);
3537 mac_invert_rectangle (f
, flash_left
,
3538 (height
- flash_height
3539 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3540 width
, flash_height
);
3543 /* If it is short, flash it all. */
3544 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3545 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3550 struct timeval wakeup
;
3552 EMACS_GET_TIME (wakeup
);
3554 /* Compute time to wait until, propagating carry from usecs. */
3555 wakeup
.tv_usec
+= 150000;
3556 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3557 wakeup
.tv_usec
%= 1000000;
3559 /* Keep waiting until past the time wakeup or any input gets
3561 while (! detect_input_pending ())
3563 struct timeval current
;
3564 struct timeval timeout
;
3566 EMACS_GET_TIME (current
);
3568 /* Break if result would be negative. */
3569 if (timeval_subtract (¤t
, wakeup
, current
))
3572 /* How long `select' should wait. */
3574 timeout
.tv_usec
= 10000;
3576 /* Try to wait that long--but we might wake up sooner. */
3577 select (0, NULL
, NULL
, NULL
, &timeout
);
3581 /* If window is tall, flash top and bottom line. */
3582 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3584 mac_invert_rectangle (f
, flash_left
,
3585 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3586 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3587 width
, flash_height
);
3588 mac_invert_rectangle (f
, flash_left
,
3589 (height
- flash_height
3590 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3591 width
, flash_height
);
3594 /* If it is short, flash it all. */
3595 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3596 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3603 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3606 /* Make audible bell. */
3611 struct frame
*f
= SELECTED_FRAME ();
3613 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3621 XFlush (FRAME_MAC_DISPLAY (f
));
3627 /* Specify how many text lines, from the top of the window,
3628 should be affected by insert-lines and delete-lines operations.
3629 This, and those operations, are used only within an update
3630 that is bounded by calls to x_update_begin and x_update_end. */
3633 XTset_terminal_window (n
)
3636 /* This function intentionally left blank. */
3641 /***********************************************************************
3643 ***********************************************************************/
3645 /* Perform an insert-lines or delete-lines operation, inserting N
3646 lines or deleting -N lines at vertical position VPOS. */
3649 x_ins_del_lines (vpos
, n
)
3656 /* Scroll part of the display as described by RUN. */
3659 x_scroll_run (w
, run
)
3663 struct frame
*f
= XFRAME (w
->frame
);
3664 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3666 /* Get frame-relative bounding box of the text display area of W,
3667 without mode lines. Include in this box the left and right
3669 window_box (w
, -1, &x
, &y
, &width
, &height
);
3671 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3672 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3673 bottom_y
= y
+ height
;
3677 /* Scrolling up. Make sure we don't copy part of the mode
3678 line at the bottom. */
3679 if (from_y
+ run
->height
> bottom_y
)
3680 height
= bottom_y
- from_y
;
3682 height
= run
->height
;
3686 /* Scolling down. Make sure we don't copy over the mode line.
3688 if (to_y
+ run
->height
> bottom_y
)
3689 height
= bottom_y
- to_y
;
3691 height
= run
->height
;
3696 /* Cursor off. Will be switched on again in x_update_window_end. */
3700 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3710 /***********************************************************************
3712 ***********************************************************************/
3720 ControlRef root_control
;
3723 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3725 ActivateControl (root_control
);
3727 x_update_cursor (f
, 1);
3731 frame_unhighlight (f
)
3735 ControlRef root_control
;
3738 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3740 DeactivateControl (root_control
);
3742 x_update_cursor (f
, 1);
3745 /* The focus has changed. Update the frames as necessary to reflect
3746 the new situation. Note that we can't change the selected frame
3747 here, because the Lisp code we are interrupting might become confused.
3748 Each event gets marked with the frame in which it occurred, so the
3749 Lisp code can tell when the switch took place by examining the events. */
3752 x_new_focus_frame (dpyinfo
, frame
)
3753 struct x_display_info
*dpyinfo
;
3754 struct frame
*frame
;
3756 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3758 if (frame
!= dpyinfo
->x_focus_frame
)
3760 /* Set this before calling other routines, so that they see
3761 the correct value of x_focus_frame. */
3762 dpyinfo
->x_focus_frame
= frame
;
3764 if (old_focus
&& old_focus
->auto_lower
)
3765 x_lower_frame (old_focus
);
3768 selected_frame
= frame
;
3769 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3771 Fselect_window (selected_frame
->selected_window
, Qnil
);
3772 choose_minibuf_frame ();
3775 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3776 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3778 pending_autoraise_frame
= 0;
3781 x_frame_rehighlight (dpyinfo
);
3784 /* Handle FocusIn and FocusOut state changes for FRAME.
3785 If FRAME has focus and there exists more than one frame, puts
3786 a FOCUS_IN_EVENT into *BUFP. */
3789 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3791 struct mac_display_info
*dpyinfo
;
3792 struct frame
*frame
;
3793 struct input_event
*bufp
;
3795 if (type
== activeFlag
)
3797 if (dpyinfo
->x_focus_event_frame
!= frame
)
3799 x_new_focus_frame (dpyinfo
, frame
);
3800 dpyinfo
->x_focus_event_frame
= frame
;
3802 /* Don't stop displaying the initial startup message
3803 for a switch-frame event we don't need. */
3804 if (GC_NILP (Vterminal_frame
)
3805 && GC_CONSP (Vframe_list
)
3806 && !GC_NILP (XCDR (Vframe_list
)))
3808 bufp
->kind
= FOCUS_IN_EVENT
;
3809 XSETFRAME (bufp
->frame_or_window
, frame
);
3815 if (dpyinfo
->x_focus_event_frame
== frame
)
3817 dpyinfo
->x_focus_event_frame
= 0;
3818 x_new_focus_frame (dpyinfo
, 0);
3823 /* The focus may have changed. Figure out if it is a real focus change,
3824 by checking both FocusIn/Out and Enter/LeaveNotify events.
3826 Returns FOCUS_IN_EVENT event in *BUFP. */
3829 x_detect_focus_change (dpyinfo
, event
, bufp
)
3830 struct mac_display_info
*dpyinfo
;
3832 struct input_event
*bufp
;
3834 struct frame
*frame
;
3836 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3840 /* On Mac, this is only called from focus events, so no switch needed. */
3841 mac_focus_changed ((event
->modifiers
& activeFlag
),
3842 dpyinfo
, frame
, bufp
);
3846 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3849 x_mouse_leave (dpyinfo
)
3850 struct x_display_info
*dpyinfo
;
3852 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3855 /* The focus has changed, or we have redirected a frame's focus to
3856 another frame (this happens when a frame uses a surrogate
3857 mini-buffer frame). Shift the highlight as appropriate.
3859 The FRAME argument doesn't necessarily have anything to do with which
3860 frame is being highlighted or un-highlighted; we only use it to find
3861 the appropriate X display info. */
3864 XTframe_rehighlight (frame
)
3865 struct frame
*frame
;
3867 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3871 x_frame_rehighlight (dpyinfo
)
3872 struct x_display_info
*dpyinfo
;
3874 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3876 if (dpyinfo
->x_focus_frame
)
3878 dpyinfo
->x_highlight_frame
3879 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3880 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3881 : dpyinfo
->x_focus_frame
);
3882 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3884 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3885 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3889 dpyinfo
->x_highlight_frame
= 0;
3891 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3894 frame_unhighlight (old_highlight
);
3895 if (dpyinfo
->x_highlight_frame
)
3896 frame_highlight (dpyinfo
->x_highlight_frame
);
3902 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3904 #if 0 /* MAC_TODO */
3905 /* Initialize mode_switch_bit and modifier_meaning. */
3907 x_find_modifier_meanings (dpyinfo
)
3908 struct x_display_info
*dpyinfo
;
3910 int min_code
, max_code
;
3913 XModifierKeymap
*mods
;
3915 dpyinfo
->meta_mod_mask
= 0;
3916 dpyinfo
->shift_lock_mask
= 0;
3917 dpyinfo
->alt_mod_mask
= 0;
3918 dpyinfo
->super_mod_mask
= 0;
3919 dpyinfo
->hyper_mod_mask
= 0;
3922 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3924 min_code
= dpyinfo
->display
->min_keycode
;
3925 max_code
= dpyinfo
->display
->max_keycode
;
3928 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3929 min_code
, max_code
- min_code
+ 1,
3931 mods
= XGetModifierMapping (dpyinfo
->display
);
3933 /* Scan the modifier table to see which modifier bits the Meta and
3934 Alt keysyms are on. */
3936 int row
, col
; /* The row and column in the modifier table. */
3938 for (row
= 3; row
< 8; row
++)
3939 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3942 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3944 /* Zeroes are used for filler. Skip them. */
3948 /* Are any of this keycode's keysyms a meta key? */
3952 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3954 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3960 dpyinfo
->meta_mod_mask
|= (1 << row
);
3965 dpyinfo
->alt_mod_mask
|= (1 << row
);
3970 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3975 dpyinfo
->super_mod_mask
|= (1 << row
);
3979 /* Ignore this if it's not on the lock modifier. */
3980 if ((1 << row
) == LockMask
)
3981 dpyinfo
->shift_lock_mask
= LockMask
;
3989 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3990 if (! dpyinfo
->meta_mod_mask
)
3992 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3993 dpyinfo
->alt_mod_mask
= 0;
3996 /* If some keys are both alt and meta,
3997 make them just meta, not alt. */
3998 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
4000 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
4003 XFree ((char *) syms
);
4004 XFreeModifiermap (mods
);
4007 #endif /* MAC_TODO */
4009 /* Convert between the modifier bits X uses and the modifier bits
4013 x_mac_to_emacs_modifiers (dpyinfo
, state
)
4014 struct x_display_info
*dpyinfo
;
4015 unsigned short state
;
4017 return (((state
& shiftKey
) ? shift_modifier
: 0)
4018 | ((state
& controlKey
) ? ctrl_modifier
: 0)
4019 | ((state
& cmdKey
) ? meta_modifier
: 0)
4020 | ((state
& optionKey
) ? alt_modifier
: 0));
4023 #if 0 /* MAC_TODO */
4024 static unsigned short
4025 x_emacs_to_x_modifiers (dpyinfo
, state
)
4026 struct x_display_info
*dpyinfo
;
4029 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
4030 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
4031 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
4032 | ((state
& shift_modifier
) ? ShiftMask
: 0)
4033 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
4034 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
4036 #endif /* MAC_TODO */
4038 /* Convert a keysym to its name. */
4041 x_get_keysym_name (keysym
)
4048 value
= XKeysymToString (keysym
);
4059 /* Function to report a mouse movement to the mainstream Emacs code.
4060 The input handler calls this.
4062 We have received a mouse movement event, which is given in *event.
4063 If the mouse is over a different glyph than it was last time, tell
4064 the mainstream emacs code by setting mouse_moved. If not, ask for
4065 another motion event, so we can check again the next time it moves. */
4067 static Point last_mouse_motion_position
;
4068 static Lisp_Object last_mouse_motion_frame
;
4071 note_mouse_movement (frame
, pos
)
4075 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4076 #if TARGET_API_MAC_CARBON
4080 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4081 last_mouse_motion_position
= *pos
;
4082 XSETFRAME (last_mouse_motion_frame
, frame
);
4084 #if TARGET_API_MAC_CARBON
4085 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4087 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4090 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4091 /* This case corresponds to LeaveNotify in X11. */
4093 /* If we move outside the frame, then we're certainly no
4094 longer on any text in the frame. */
4095 clear_mouse_face (dpyinfo
);
4096 dpyinfo
->mouse_face_mouse_frame
= 0;
4097 if (!dpyinfo
->grabbed
)
4098 rif
->define_frame_cursor (frame
,
4099 frame
->output_data
.mac
->nontext_cursor
);
4103 /* Has the mouse moved off the glyph it was on at the last sighting? */
4104 if (frame
!= last_mouse_glyph_frame
4105 || !PtInRect (*pos
, &last_mouse_glyph
))
4107 frame
->mouse_moved
= 1;
4108 last_mouse_scroll_bar
= Qnil
;
4109 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4110 /* Remember which glyph we're now on. */
4111 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4112 last_mouse_glyph_frame
= frame
;
4120 /************************************************************************
4122 ************************************************************************/
4124 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4127 redo_mouse_highlight ()
4129 if (!NILP (last_mouse_motion_frame
)
4130 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4131 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4132 last_mouse_motion_position
.h
,
4133 last_mouse_motion_position
.v
);
4137 static struct frame
*
4138 mac_focus_frame (dpyinfo
)
4139 struct mac_display_info
*dpyinfo
;
4141 if (dpyinfo
->x_focus_frame
)
4142 return dpyinfo
->x_focus_frame
;
4144 /* Mac version may get events, such as a menu bar click, even when
4145 all the frames are invisible. In this case, we regard the
4146 event came to the selected frame. */
4147 return SELECTED_FRAME ();
4151 /* Return the current position of the mouse.
4152 *FP should be a frame which indicates which display to ask about.
4154 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4155 and *PART to the frame, window, and scroll bar part that the mouse
4156 is over. Set *X and *Y to the portion and whole of the mouse's
4157 position on the scroll bar.
4159 If the mouse movement started elsewhere, set *FP to the frame the
4160 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4163 Set *TIME to the server time-stamp for the time at which the mouse
4164 was at this position.
4166 Don't store anything if we don't have a valid set of values to report.
4168 This clears the mouse_moved flag, so we can wait for the next mouse
4172 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4175 Lisp_Object
*bar_window
;
4176 enum scroll_bar_part
*part
;
4178 unsigned long *time
;
4184 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4185 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4188 Lisp_Object frame
, tail
;
4190 /* Clear the mouse-moved flag for every frame on this display. */
4191 FOR_EACH_FRAME (tail
, frame
)
4192 XFRAME (frame
)->mouse_moved
= 0;
4194 last_mouse_scroll_bar
= Qnil
;
4196 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4197 && FRAME_LIVE_P (last_mouse_frame
))
4198 f1
= last_mouse_frame
;
4200 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4204 /* Ok, we found a frame. Store all the values.
4205 last_mouse_glyph is a rectangle used to reduce the
4206 generation of mouse events. To not miss any motion
4207 events, we must divide the frame into rectangles of the
4208 size of the smallest character that could be displayed
4209 on it, i.e. into the same rectangles that matrices on
4210 the frame are divided into. */
4213 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4214 GetMouse (&mouse_pos
);
4215 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4217 last_mouse_glyph_frame
= f1
;
4222 XSETINT (*x
, mouse_pos
.h
);
4223 XSETINT (*y
, mouse_pos
.v
);
4224 *time
= last_mouse_movement_time
;
4232 /************************************************************************
4234 ************************************************************************/
4236 #ifdef USE_TOOLKIT_SCROLL_BARS
4238 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4239 static OSStatus install_scroll_bar_timer
P_ ((void));
4240 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4241 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4242 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4243 struct input_event
*));
4244 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4246 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4248 struct input_event
*));
4249 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4250 struct input_event
*));
4251 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4252 Point
, struct input_event
*));
4253 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4256 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4258 static int last_scroll_bar_part
;
4260 static EventLoopTimerRef scroll_bar_timer
;
4262 static int scroll_bar_timer_event_posted_p
;
4264 #define SCROLL_BAR_FIRST_DELAY 0.5
4265 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4268 scroll_bar_timer_callback (timer
, data
)
4269 EventLoopTimerRef timer
;
4272 EventRef event
= NULL
;
4275 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4276 kEventAttributeNone
, &event
);
4281 GetMouse (&mouse_pos
);
4282 LocalToGlobal (&mouse_pos
);
4283 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4284 sizeof (Point
), &mouse_pos
);
4288 UInt32 modifiers
= GetCurrentKeyModifiers ();
4290 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4291 sizeof (UInt32
), &modifiers
);
4294 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4295 kEventPriorityStandard
);
4297 scroll_bar_timer_event_posted_p
= 1;
4300 ReleaseEvent (event
);
4304 install_scroll_bar_timer ()
4306 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4308 if (scroll_bar_timer_callbackUPP
== NULL
)
4309 scroll_bar_timer_callbackUPP
=
4310 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4312 if (scroll_bar_timer
== NULL
)
4313 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4314 kEventDurationForever as delays. */
4316 InstallEventLoopTimer (GetCurrentEventLoop (),
4317 kEventDurationForever
, kEventDurationForever
,
4318 scroll_bar_timer_callbackUPP
, NULL
,
4323 set_scroll_bar_timer (delay
)
4324 EventTimerInterval delay
;
4326 if (scroll_bar_timer
== NULL
)
4327 install_scroll_bar_timer ();
4329 scroll_bar_timer_event_posted_p
= 0;
4331 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4335 control_part_code_to_scroll_bar_part (part_code
)
4336 ControlPartCode part_code
;
4340 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4341 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4342 case kControlPageUpPart
: return scroll_bar_above_handle
;
4343 case kControlPageDownPart
: return scroll_bar_below_handle
;
4344 case kControlIndicatorPart
: return scroll_bar_handle
;
4351 construct_scroll_bar_click (bar
, part
, bufp
)
4352 struct scroll_bar
*bar
;
4354 struct input_event
*bufp
;
4356 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4357 bufp
->frame_or_window
= bar
->window
;
4361 XSETINT (bufp
->x
, 0);
4362 XSETINT (bufp
->y
, 0);
4363 bufp
->modifiers
= 0;
4367 get_control_part_bounds (ch
, part_code
, rect
)
4369 ControlPartCode part_code
;
4372 RgnHandle region
= NewRgn ();
4375 err
= GetControlRegion (ch
, part_code
, region
);
4377 GetRegionBounds (region
, rect
);
4378 DisposeRgn (region
);
4384 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4385 struct scroll_bar
*bar
;
4386 ControlPartCode part_code
;
4387 struct input_event
*bufp
;
4389 int part
= control_part_code_to_scroll_bar_part (part_code
);
4394 if (part
!= scroll_bar_handle
)
4396 construct_scroll_bar_click (bar
, part
, bufp
);
4397 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4398 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4401 last_scroll_bar_part
= part
;
4402 bar
->dragging
= Qnil
;
4403 tracked_scroll_bar
= bar
;
4407 x_scroll_bar_handle_release (bar
, bufp
)
4408 struct scroll_bar
*bar
;
4409 struct input_event
*bufp
;
4411 if (last_scroll_bar_part
!= scroll_bar_handle
4412 || !GC_NILP (bar
->dragging
))
4413 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4415 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4416 set_scroll_bar_timer (kEventDurationForever
);
4418 last_scroll_bar_part
= -1;
4419 bar
->dragging
= Qnil
;
4420 tracked_scroll_bar
= NULL
;
4424 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4426 struct scroll_bar
*bar
;
4428 struct input_event
*bufp
;
4430 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4432 if (last_scroll_bar_part
== scroll_bar_handle
)
4437 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4438 kControlIndicatorPart
, &r
);
4440 if (GC_NILP (bar
->dragging
))
4441 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4443 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4444 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4445 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4450 if (top
> top_range
)
4453 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4454 XSETINT (bufp
->x
, top
);
4455 XSETINT (bufp
->y
, top_range
);
4459 ControlPartCode part_code
;
4460 int unhilite_p
= 0, part
;
4462 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4466 part
= control_part_code_to_scroll_bar_part (part_code
);
4468 switch (last_scroll_bar_part
)
4470 case scroll_bar_above_handle
:
4471 case scroll_bar_below_handle
:
4472 if (part
!= scroll_bar_above_handle
4473 && part
!= scroll_bar_below_handle
)
4477 case scroll_bar_up_arrow
:
4478 case scroll_bar_down_arrow
:
4479 if (part
!= scroll_bar_up_arrow
4480 && part
!= scroll_bar_down_arrow
)
4487 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4488 else if (part
!= last_scroll_bar_part
4489 || scroll_bar_timer_event_posted_p
)
4491 construct_scroll_bar_click (bar
, part
, bufp
);
4492 last_scroll_bar_part
= part
;
4493 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4494 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4499 /* Set the thumb size and position of scroll bar BAR. We are currently
4500 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4503 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4504 struct scroll_bar
*bar
;
4505 int portion
, position
, whole
;
4507 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4509 int value
, viewsize
, maximum
;
4511 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4512 value
= 0, viewsize
= 1, maximum
= 0;
4517 maximum
= max (0, whole
- portion
);
4522 SetControl32BitMinimum (ch
, 0);
4523 SetControl32BitMaximum (ch
, maximum
);
4524 SetControl32BitValue (ch
, value
);
4525 SetControlViewSize (ch
, viewsize
);
4530 #endif /* USE_TOOLKIT_SCROLL_BARS */
4534 /************************************************************************
4535 Scroll bars, general
4536 ************************************************************************/
4538 /* Create a scroll bar and return the scroll bar vector for it. W is
4539 the Emacs window on which to create the scroll bar. TOP, LEFT,
4540 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4543 static struct scroll_bar
*
4544 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4546 int top
, left
, width
, height
, disp_top
, disp_height
;
4548 struct frame
*f
= XFRAME (w
->frame
);
4549 struct scroll_bar
*bar
4550 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4558 r
.right
= left
+ width
;
4559 r
.bottom
= disp_top
+ disp_height
;
4561 #if TARGET_API_MAC_CARBON
4562 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4563 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4565 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4566 0, 0, 0, scrollBarProc
, (long) bar
);
4568 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4570 XSETWINDOW (bar
->window
, w
);
4571 XSETINT (bar
->top
, top
);
4572 XSETINT (bar
->left
, left
);
4573 XSETINT (bar
->width
, width
);
4574 XSETINT (bar
->height
, height
);
4575 XSETINT (bar
->start
, 0);
4576 XSETINT (bar
->end
, 0);
4577 bar
->dragging
= Qnil
;
4578 #ifdef USE_TOOLKIT_SCROLL_BARS
4579 bar
->track_top
= Qnil
;
4580 bar
->track_height
= Qnil
;
4583 /* Add bar to its frame's list of scroll bars. */
4584 bar
->next
= FRAME_SCROLL_BARS (f
);
4586 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4587 if (!NILP (bar
->next
))
4588 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4595 /* Draw BAR's handle in the proper position.
4597 If the handle is already drawn from START to END, don't bother
4598 redrawing it, unless REBUILD is non-zero; in that case, always
4599 redraw it. (REBUILD is handy for drawing the handle after expose
4602 Normally, we want to constrain the start and end of the handle to
4603 fit inside its rectangle, but if the user is dragging the scroll
4604 bar handle, we want to let them drag it down all the way, so that
4605 the bar's top is as far down as it goes; otherwise, there's no way
4606 to move to the very end of the buffer. */
4608 #ifndef USE_TOOLKIT_SCROLL_BARS
4611 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4612 struct scroll_bar
*bar
;
4616 int dragging
= ! NILP (bar
->dragging
);
4617 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4618 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4619 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4620 int length
= end
- start
;
4622 /* If the display is already accurate, do nothing. */
4624 && start
== XINT (bar
->start
)
4625 && end
== XINT (bar
->end
))
4630 /* Make sure the values are reasonable, and try to preserve the
4631 distance between start and end. */
4634 else if (start
> top_range
)
4636 end
= start
+ length
;
4640 else if (end
> top_range
&& ! dragging
)
4643 /* Store the adjusted setting in the scroll bar. */
4644 XSETINT (bar
->start
, start
);
4645 XSETINT (bar
->end
, end
);
4647 /* Clip the end position, just for display. */
4648 if (end
> top_range
)
4651 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4652 top positions, to make sure the handle is always at least that
4653 many pixels tall. */
4654 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4656 SetControlMinimum (ch
, 0);
4657 /* Don't inadvertently activate deactivated scroll bars */
4658 if (GetControlMaximum (ch
) != -1)
4659 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4661 SetControlValue (ch
, start
);
4662 #if TARGET_API_MAC_CARBON
4663 SetControlViewSize (ch
, end
- start
);
4669 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4671 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4675 x_scroll_bar_remove (bar
)
4676 struct scroll_bar
*bar
;
4678 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4682 /* Destroy the Mac scroll bar control */
4683 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4685 /* Disassociate this scroll bar from its window. */
4686 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4692 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4693 that we are displaying PORTION characters out of a total of WHOLE
4694 characters, starting at POSITION. If WINDOW has no scroll bar,
4698 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4700 int portion
, whole
, position
;
4702 struct frame
*f
= XFRAME (w
->frame
);
4703 struct scroll_bar
*bar
;
4704 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4705 int window_y
, window_height
;
4707 /* Get window dimensions. */
4708 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4710 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4711 height
= window_height
;
4713 /* Compute the left edge of the scroll bar area. */
4714 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4716 /* Compute the width of the scroll bar which might be less than
4717 the width of the area reserved for the scroll bar. */
4718 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4719 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4723 /* Compute the left edge of the scroll bar. */
4724 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4727 sb_left
= left
+ width
- sb_width
;
4729 /* Adjustments according to Inside Macintosh to make it look nice */
4731 disp_height
= height
;
4737 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4743 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4746 /* Does the scroll bar exist yet? */
4747 if (NILP (w
->vertical_scroll_bar
))
4750 mac_clear_area (f
, left
, top
, width
, height
);
4752 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4754 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4758 /* It may just need to be moved and resized. */
4761 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4762 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4766 /* If already correctly positioned, do nothing. */
4767 if (!(XINT (bar
->left
) == sb_left
4768 && XINT (bar
->top
) == top
4769 && XINT (bar
->width
) == sb_width
4770 && XINT (bar
->height
) == height
))
4772 /* Since toolkit scroll bars are smaller than the space reserved
4773 for them on the frame, we have to clear "under" them. */
4774 mac_clear_area (f
, left
, top
, width
, height
);
4777 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4778 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4780 if (sb_width
< disp_height
)
4783 /* Remember new settings. */
4784 XSETINT (bar
->left
, sb_left
);
4785 XSETINT (bar
->top
, top
);
4786 XSETINT (bar
->width
, sb_width
);
4787 XSETINT (bar
->height
, height
);
4788 #ifdef USE_TOOLKIT_SCROLL_BARS
4789 bar
->track_top
= Qnil
;
4790 bar
->track_height
= Qnil
;
4797 #ifdef USE_TOOLKIT_SCROLL_BARS
4798 if (NILP (bar
->track_top
))
4800 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4805 SetControl32BitMinimum (ch
, 0);
4806 SetControl32BitMaximum (ch
, 1);
4807 SetControlViewSize (ch
, 1);
4809 /* Move the scroll bar thumb to the top. */
4810 SetControl32BitValue (ch
, 0);
4811 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4813 /* Move the scroll bar thumb to the bottom. */
4814 SetControl32BitValue (ch
, 1);
4815 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4817 UnionRect (&r0
, &r1
, &r0
);
4818 XSETINT (bar
->track_top
, r0
.top
);
4819 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4824 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4825 #else /* not USE_TOOLKIT_SCROLL_BARS */
4826 /* Set the scroll bar's current state, unless we're currently being
4828 if (NILP (bar
->dragging
))
4830 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4833 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4836 int start
= ((double) position
* top_range
) / whole
;
4837 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4838 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4841 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4845 /* The following three hooks are used when we're doing a thorough
4846 redisplay of the frame. We don't explicitly know which scroll bars
4847 are going to be deleted, because keeping track of when windows go
4848 away is a real pain - "Can you say set-window-configuration, boys
4849 and girls?" Instead, we just assert at the beginning of redisplay
4850 that *all* scroll bars are to be removed, and then save a scroll bar
4851 from the fiery pit when we actually redisplay its window. */
4853 /* Arrange for all scroll bars on FRAME to be removed at the next call
4854 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4855 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4858 XTcondemn_scroll_bars (frame
)
4861 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4862 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4865 bar
= FRAME_SCROLL_BARS (frame
);
4866 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4867 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4868 XSCROLL_BAR (bar
)->prev
= Qnil
;
4869 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4870 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4871 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4876 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4877 Note that WINDOW isn't necessarily condemned at all. */
4880 XTredeem_scroll_bar (window
)
4881 struct window
*window
;
4883 struct scroll_bar
*bar
;
4886 /* We can't redeem this window's scroll bar if it doesn't have one. */
4887 if (NILP (window
->vertical_scroll_bar
))
4890 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4892 /* Unlink it from the condemned list. */
4893 f
= XFRAME (WINDOW_FRAME (window
));
4894 if (NILP (bar
->prev
))
4896 /* If the prev pointer is nil, it must be the first in one of
4898 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4899 /* It's not condemned. Everything's fine. */
4901 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4902 window
->vertical_scroll_bar
))
4903 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4905 /* If its prev pointer is nil, it must be at the front of
4906 one or the other! */
4910 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4912 if (! NILP (bar
->next
))
4913 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4915 bar
->next
= FRAME_SCROLL_BARS (f
);
4917 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4918 if (! NILP (bar
->next
))
4919 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4922 /* Remove all scroll bars on FRAME that haven't been saved since the
4923 last call to `*condemn_scroll_bars_hook'. */
4926 XTjudge_scroll_bars (f
)
4929 Lisp_Object bar
, next
;
4931 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4933 /* Clear out the condemned list now so we won't try to process any
4934 more events on the hapless scroll bars. */
4935 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4937 for (; ! NILP (bar
); bar
= next
)
4939 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4941 x_scroll_bar_remove (b
);
4944 b
->next
= b
->prev
= Qnil
;
4947 /* Now there should be no references to the condemned scroll bars,
4948 and they should get garbage-collected. */
4952 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4953 is set to something other than NO_EVENT, it is enqueued.
4955 This may be called from a signal handler, so we have to ignore GC
4959 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4960 struct scroll_bar
*bar
;
4961 ControlPartCode part_code
;
4963 struct input_event
*bufp
;
4965 int win_y
, top_range
;
4967 if (! GC_WINDOWP (bar
->window
))
4970 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4971 bufp
->frame_or_window
= bar
->window
;
4974 bar
->dragging
= Qnil
;
4978 case kControlUpButtonPart
:
4979 bufp
->part
= scroll_bar_up_arrow
;
4981 case kControlDownButtonPart
:
4982 bufp
->part
= scroll_bar_down_arrow
;
4984 case kControlPageUpPart
:
4985 bufp
->part
= scroll_bar_above_handle
;
4987 case kControlPageDownPart
:
4988 bufp
->part
= scroll_bar_below_handle
;
4990 #if TARGET_API_MAC_CARBON
4993 case kControlIndicatorPart
:
4995 if (er
->what
== mouseDown
)
4996 bar
->dragging
= make_number (0);
4997 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4998 bufp
->part
= scroll_bar_handle
;
5002 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5003 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5005 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5009 if (! NILP (bar
->dragging
))
5010 win_y
-= XINT (bar
->dragging
);
5014 if (win_y
> top_range
)
5017 XSETINT (bufp
->x
, win_y
);
5018 XSETINT (bufp
->y
, top_range
);
5021 #ifndef USE_TOOLKIT_SCROLL_BARS
5023 /* Handle some mouse motion while someone is dragging the scroll bar.
5025 This may be called from a signal handler, so we have to ignore GC
5029 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5030 struct scroll_bar
*bar
;
5034 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5036 last_mouse_movement_time
= t
;
5039 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5041 /* If we're dragging the bar, display it. */
5042 if (! GC_NILP (bar
->dragging
))
5044 /* Where should the handle be now? */
5045 int new_start
= y_pos
- 24;
5047 if (new_start
!= XINT (bar
->start
))
5049 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5051 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5056 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5058 /* Return information to the user about the current position of the mouse
5059 on the scroll bar. */
5062 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5064 Lisp_Object
*bar_window
;
5065 enum scroll_bar_part
*part
;
5067 unsigned long *time
;
5069 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5070 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5071 #if TARGET_API_MAC_CARBON
5072 WindowPtr wp
= GetControlOwner (ch
);
5074 WindowPtr wp
= (*ch
)->contrlOwner
;
5077 struct frame
*f
= mac_window_to_frame (wp
);
5078 int win_y
, top_range
;
5080 SetPortWindowPort (wp
);
5082 GetMouse (&mouse_pos
);
5084 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5085 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5087 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5091 if (! NILP (bar
->dragging
))
5092 win_y
-= XINT (bar
->dragging
);
5096 if (win_y
> top_range
)
5100 *bar_window
= bar
->window
;
5102 if (! NILP (bar
->dragging
))
5103 *part
= scroll_bar_handle
;
5104 else if (win_y
< XINT (bar
->start
))
5105 *part
= scroll_bar_above_handle
;
5106 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5107 *part
= scroll_bar_handle
;
5109 *part
= scroll_bar_below_handle
;
5111 XSETINT (*x
, win_y
);
5112 XSETINT (*y
, top_range
);
5115 last_mouse_scroll_bar
= Qnil
;
5117 *time
= last_mouse_movement_time
;
5121 /* The screen has been cleared so we may have changed foreground or
5122 background colors, and the scroll bars may need to be redrawn.
5123 Clear out the scroll bars, and ask for expose events, so we can
5127 x_scroll_bar_clear (f
)
5130 XTcondemn_scroll_bars (f
);
5131 XTjudge_scroll_bars (f
);
5135 /***********************************************************************
5137 ***********************************************************************/
5139 /* Set clipping for output in glyph row ROW. W is the window in which
5140 we operate. GC is the graphics context to set clipping in.
5142 ROW may be a text row or, e.g., a mode line. Text rows must be
5143 clipped to the interior of the window dedicated to text display,
5144 mode lines must be clipped to the whole window. */
5147 x_clip_to_row (w
, row
, area
, gc
)
5149 struct glyph_row
*row
;
5153 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5155 int window_x
, window_y
, window_width
;
5157 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5159 clip_rect
.left
= window_x
;
5160 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5161 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5162 clip_rect
.right
= clip_rect
.left
+ window_width
;
5163 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5165 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5169 /* Draw a hollow box cursor on window W in glyph row ROW. */
5172 x_draw_hollow_cursor (w
, row
)
5174 struct glyph_row
*row
;
5176 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5177 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5178 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5181 struct glyph
*cursor_glyph
;
5184 /* Get the glyph the cursor is on. If we can't tell because
5185 the current matrix is invalid or such, give up. */
5186 cursor_glyph
= get_phys_cursor_glyph (w
);
5187 if (cursor_glyph
== NULL
)
5190 /* Compute frame-relative coordinates for phys cursor. */
5191 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5192 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5193 wd
= w
->phys_cursor_width
;
5195 /* The foreground of cursor_gc is typically the same as the normal
5196 background color, which can cause the cursor box to be invisible. */
5197 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5198 if (dpyinfo
->scratch_cursor_gc
)
5199 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5201 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5202 GCForeground
, &xgcv
);
5203 gc
= dpyinfo
->scratch_cursor_gc
;
5205 /* Set clipping, draw the rectangle, and reset clipping again. */
5206 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5207 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
);
5208 mac_reset_clip_rectangles (dpy
, gc
);
5212 /* Draw a bar cursor on window W in glyph row ROW.
5214 Implementation note: One would like to draw a bar cursor with an
5215 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5216 Unfortunately, I didn't find a font yet that has this property set.
5220 x_draw_bar_cursor (w
, row
, width
, kind
)
5222 struct glyph_row
*row
;
5224 enum text_cursor_kinds kind
;
5226 struct frame
*f
= XFRAME (w
->frame
);
5227 struct glyph
*cursor_glyph
;
5229 /* If cursor is out of bounds, don't draw garbage. This can happen
5230 in mini-buffer windows when switching between echo area glyphs
5232 cursor_glyph
= get_phys_cursor_glyph (w
);
5233 if (cursor_glyph
== NULL
)
5236 /* If on an image, draw like a normal cursor. That's usually better
5237 visible than drawing a bar, esp. if the image is large so that
5238 the bar might not be in the window. */
5239 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5241 struct glyph_row
*row
;
5242 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5243 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5247 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5248 Window window
= FRAME_MAC_WINDOW (f
);
5249 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5250 unsigned long mask
= GCForeground
| GCBackground
;
5251 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5254 /* If the glyph's background equals the color we normally draw
5255 the bar cursor in, the bar cursor in its normal color is
5256 invisible. Use the glyph's foreground color instead in this
5257 case, on the assumption that the glyph's colors are chosen so
5258 that the glyph is legible. */
5259 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5260 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5262 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5265 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5268 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5269 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5273 width
= FRAME_CURSOR_WIDTH (f
);
5274 width
= min (cursor_glyph
->pixel_width
, width
);
5276 w
->phys_cursor_width
= width
;
5277 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5279 if (kind
== BAR_CURSOR
)
5280 mac_fill_rectangle (f
, gc
,
5281 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5282 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5283 width
, row
->height
);
5285 mac_fill_rectangle (f
, gc
,
5286 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5287 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5288 row
->height
- width
),
5289 cursor_glyph
->pixel_width
,
5292 mac_reset_clip_rectangles (dpy
, gc
);
5297 /* RIF: Define cursor CURSOR on frame F. */
5300 mac_define_frame_cursor (f
, cursor
)
5304 SetThemeCursor (cursor
);
5308 /* RIF: Clear area on frame F. */
5311 mac_clear_frame_area (f
, x
, y
, width
, height
)
5313 int x
, y
, width
, height
;
5315 mac_clear_area (f
, x
, y
, width
, height
);
5319 /* RIF: Draw cursor on window W. */
5322 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5324 struct glyph_row
*glyph_row
;
5326 int cursor_type
, cursor_width
;
5331 w
->phys_cursor_type
= cursor_type
;
5332 w
->phys_cursor_on_p
= 1;
5334 if (glyph_row
->exact_window_width_line_p
5335 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5337 glyph_row
->cursor_in_fringe_p
= 1;
5338 draw_fringe_bitmap (w
, glyph_row
, 0);
5341 switch (cursor_type
)
5343 case HOLLOW_BOX_CURSOR
:
5344 x_draw_hollow_cursor (w
, glyph_row
);
5347 case FILLED_BOX_CURSOR
:
5348 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5352 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5356 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5360 w
->phys_cursor_width
= 0;
5372 #if 0 /* MAC_TODO: no icon support yet. */
5374 x_bitmap_icon (f
, icon
)
5380 if (FRAME_W32_WINDOW (f
) == 0)
5384 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5385 else if (STRINGP (icon
))
5386 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5387 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5388 else if (SYMBOLP (icon
))
5392 if (EQ (icon
, intern ("application")))
5393 name
= (LPCTSTR
) IDI_APPLICATION
;
5394 else if (EQ (icon
, intern ("hand")))
5395 name
= (LPCTSTR
) IDI_HAND
;
5396 else if (EQ (icon
, intern ("question")))
5397 name
= (LPCTSTR
) IDI_QUESTION
;
5398 else if (EQ (icon
, intern ("exclamation")))
5399 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5400 else if (EQ (icon
, intern ("asterisk")))
5401 name
= (LPCTSTR
) IDI_ASTERISK
;
5402 else if (EQ (icon
, intern ("winlogo")))
5403 name
= (LPCTSTR
) IDI_WINLOGO
;
5407 hicon
= LoadIcon (NULL
, name
);
5415 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5420 #endif /* MAC_TODO */
5422 /************************************************************************
5424 ************************************************************************/
5426 /* Display Error Handling functions not used on W32. Listing them here
5427 helps diff stay in step when comparing w32term.c with xterm.c.
5429 x_error_catcher (display, error)
5430 x_catch_errors (dpy)
5431 x_catch_errors_unwind (old_val)
5432 x_check_errors (dpy, format)
5433 x_had_errors_p (dpy)
5434 x_clear_errors (dpy)
5435 x_uncatch_errors (dpy, count)
5437 x_connection_signal (signalnum)
5438 x_connection_closed (dpy, error_message)
5439 x_error_quitter (display, error)
5440 x_error_handler (display, error)
5441 x_io_error_quitter (display)
5446 /* Changing the font of the frame. */
5448 /* Give frame F the font named FONTNAME as its default font, and
5449 return the full name of that font. FONTNAME may be a wildcard
5450 pattern; in that case, we choose some font that fits the pattern.
5451 The return value shows which font we chose. */
5454 x_new_font (f
, fontname
)
5456 register char *fontname
;
5458 struct font_info
*fontp
5459 = FS_LOAD_FONT (f
, fontname
);
5464 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
5465 /* This font is already set in frame F. There's nothing more to
5467 return build_string (fontp
->full_name
);
5469 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5470 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5471 FRAME_FONTSET (f
) = -1;
5473 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5474 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5475 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5477 compute_fringe_widths (f
, 1);
5479 /* Compute the scroll bar width in character columns. */
5480 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5482 int wid
= FRAME_COLUMN_WIDTH (f
);
5483 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5484 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5488 int wid
= FRAME_COLUMN_WIDTH (f
);
5489 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5492 /* Now make the frame display the given font. */
5493 if (FRAME_MAC_WINDOW (f
) != 0)
5495 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5497 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5499 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5502 /* Don't change the size of a tip frame; there's no point in
5503 doing it because it's done in Fx_show_tip, and it leads to
5504 problems because the tip frame has no widget. */
5505 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5506 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5509 return build_string (fontp
->full_name
);
5512 /* Give frame F the fontset named FONTSETNAME as its default fontset,
5513 and return the full name of that fontset. FONTSETNAME may be a
5514 wildcard pattern; in that case, we choose some fontset that fits
5515 the pattern. FONTSETNAME may be a font name for ASCII characters;
5516 in that case, we create a fontset from that font name.
5518 The return value shows which fontset we chose.
5519 If FONTSETNAME specifies the default fontset, return Qt.
5520 If an ASCII font in the specified fontset can't be loaded, return
5524 x_new_fontset (f
, fontsetname
)
5526 Lisp_Object fontsetname
;
5528 int fontset
= fs_query_fontset (fontsetname
, 0);
5531 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
5532 /* This fontset is already set in frame F. There's nothing more
5534 return fontset_name (fontset
);
5535 else if (fontset
== 0)
5536 /* The default fontset can't be the default font. */
5540 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5542 result
= x_new_font (f
, SDATA (fontsetname
));
5544 if (!STRINGP (result
))
5545 /* Can't load ASCII font. */
5549 fontset
= new_fontset_from_font_name (result
);
5551 /* Since x_new_font doesn't update any fontset information, do it now. */
5552 FRAME_FONTSET (f
) = fontset
;
5554 return fontset_name (fontset
);
5558 /***********************************************************************
5559 TODO: W32 Input Methods
5560 ***********************************************************************/
5561 /* Listing missing functions from xterm.c helps diff stay in step.
5563 xim_destroy_callback (xim, client_data, call_data)
5564 xim_open_dpy (dpyinfo, resource_name)
5566 xim_instantiate_callback (display, client_data, call_data)
5567 xim_initialize (dpyinfo, resource_name)
5568 xim_close_dpy (dpyinfo)
5574 mac_get_window_bounds (f
, inner
, outer
)
5576 Rect
*inner
, *outer
;
5578 #if TARGET_API_MAC_CARBON
5579 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5580 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5581 #else /* not TARGET_API_MAC_CARBON */
5582 RgnHandle region
= NewRgn ();
5584 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5585 *inner
= (*region
)->rgnBBox
;
5586 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5587 *outer
= (*region
)->rgnBBox
;
5588 DisposeRgn (region
);
5589 #endif /* not TARGET_API_MAC_CARBON */
5594 /* Calculate the absolute position in frame F
5595 from its current recorded position values and gravity. */
5598 x_calc_absolute_position (f
)
5601 int width_diff
= 0, height_diff
= 0;
5602 int flags
= f
->size_hint_flags
;
5605 /* We have nothing to do if the current position
5606 is already for the top-left corner. */
5607 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5610 /* Find the offsets of the outside upper-left corner of
5611 the inner window, with respect to the outer window. */
5612 mac_get_window_bounds (f
, &inner
, &outer
);
5614 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5615 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5617 /* Treat negative positions as relative to the leftmost bottommost
5618 position that fits on the screen. */
5619 if (flags
& XNegative
)
5620 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5622 - FRAME_PIXEL_WIDTH (f
)
5625 if (flags
& YNegative
)
5626 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5628 - FRAME_PIXEL_HEIGHT (f
)
5631 /* The left_pos and top_pos
5632 are now relative to the top and left screen edges,
5633 so the flags should correspond. */
5634 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5637 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5638 to really change the position, and 0 when calling from
5639 x_make_frame_visible (in that case, XOFF and YOFF are the current
5640 position values). It is -1 when calling from x_set_frame_parameters,
5641 which means, do adjust for borders but don't change the gravity. */
5644 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5646 register int xoff
, yoff
;
5649 if (change_gravity
> 0)
5653 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5655 f
->size_hint_flags
|= XNegative
;
5657 f
->size_hint_flags
|= YNegative
;
5658 f
->win_gravity
= NorthWestGravity
;
5660 x_calc_absolute_position (f
);
5663 x_wm_set_size_hint (f
, (long) 0, 0);
5665 #if TARGET_API_MAC_CARBON
5666 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5667 /* If the title bar is completely outside the screen, adjust the
5669 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5670 kWindowConstrainMoveRegardlessOfFit
5671 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5672 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5675 Rect inner
, outer
, screen_rect
, dummy
;
5676 RgnHandle region
= NewRgn ();
5678 mac_get_window_bounds (f
, &inner
, &outer
);
5679 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5680 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5681 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5682 f
->top_pos
+ f
->y_pixels_diff
, false);
5684 /* If the title bar is completely outside the screen, adjust the
5685 position. The variable `outer' holds the title bar rectangle.
5686 The variable `inner' holds slightly smaller one than `outer',
5687 so that the calculation of overlapping may not become too
5689 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5690 outer
= (*region
)->rgnBBox
;
5691 DisposeRgn (region
);
5693 InsetRect (&inner
, 8, 8);
5694 screen_rect
= qd
.screenBits
.bounds
;
5695 screen_rect
.top
+= GetMBarHeight ();
5697 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5699 if (inner
.right
<= screen_rect
.left
)
5700 f
->left_pos
= screen_rect
.left
;
5701 else if (inner
.left
>= screen_rect
.right
)
5702 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5704 if (inner
.bottom
<= screen_rect
.top
)
5705 f
->top_pos
= screen_rect
.top
;
5706 else if (inner
.top
>= screen_rect
.bottom
)
5707 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5709 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5710 f
->top_pos
+ f
->y_pixels_diff
, false);
5718 /* Call this to change the size of frame F's x-window.
5719 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5720 for this size change and subsequent size changes.
5721 Otherwise we leave the window gravity unchanged. */
5724 x_set_window_size (f
, change_gravity
, cols
, rows
)
5729 int pixelwidth
, pixelheight
;
5733 check_frame_size (f
, &rows
, &cols
);
5734 f
->scroll_bar_actual_width
5735 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5737 compute_fringe_widths (f
, 0);
5739 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5740 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5742 f
->win_gravity
= NorthWestGravity
;
5743 x_wm_set_size_hint (f
, (long) 0, 0);
5745 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5746 #if TARGET_API_MAC_CARBON
5747 if (f
->output_data
.mac
->hourglass_control
)
5748 MoveControl (f
->output_data
.mac
->hourglass_control
,
5749 pixelwidth
- HOURGLASS_WIDTH
, 0);
5752 /* Now, strictly speaking, we can't be sure that this is accurate,
5753 but the window manager will get around to dealing with the size
5754 change request eventually, and we'll hear how it went when the
5755 ConfigureNotify event gets here.
5757 We could just not bother storing any of this information here,
5758 and let the ConfigureNotify event set everything up, but that
5759 might be kind of confusing to the Lisp code, since size changes
5760 wouldn't be reported in the frame parameters until some random
5761 point in the future when the ConfigureNotify event arrives.
5763 We pass 1 for DELAY since we can't run Lisp code inside of
5765 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5766 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5767 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5769 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5770 receive in the ConfigureNotify event; if we get what we asked
5771 for, then the event won't cause the screen to become garbaged, so
5772 we have to make sure to do it here. */
5773 SET_FRAME_GARBAGED (f
);
5775 XFlush (FRAME_X_DISPLAY (f
));
5777 /* If cursor was outside the new size, mark it as off. */
5778 mark_window_cursors_off (XWINDOW (f
->root_window
));
5780 /* Clear out any recollection of where the mouse highlighting was,
5781 since it might be in a place that's outside the new frame size.
5782 Actually checking whether it is outside is a pain in the neck,
5783 so don't try--just let the highlighting be done afresh with new size. */
5784 cancel_mouse_face (f
);
5789 /* Mouse warping. */
5791 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5794 x_set_mouse_position (f
, x
, y
)
5800 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5801 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5803 if (pix_x
< 0) pix_x
= 0;
5804 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5806 if (pix_y
< 0) pix_y
= 0;
5807 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5809 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5813 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5817 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5820 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5821 0, 0, 0, 0, pix_x
, pix_y
);
5826 /* focus shifting, raising and lowering. */
5829 x_focus_on_frame (f
)
5832 #if 0 /* This proves to be unpleasant. */
5836 /* I don't think that the ICCCM allows programs to do things like this
5837 without the interaction of the window manager. Whatever you end up
5838 doing with this code, do it to x_unfocus_frame too. */
5839 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5840 RevertToPointerRoot
, CurrentTime
);
5850 /* Raise frame F. */
5856 if (f
->async_visible
)
5859 SelectWindow (FRAME_MAC_WINDOW (f
));
5864 /* Lower frame F. */
5870 if (f
->async_visible
)
5873 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5879 XTframe_raise_lower (f
, raise_flag
)
5889 /* Change of visibility. */
5892 mac_handle_visibility_change (f
)
5895 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5896 int visible
= 0, iconified
= 0;
5897 struct input_event buf
;
5899 if (IsWindowVisible (wp
))
5900 if (IsWindowCollapsed (wp
))
5905 if (!f
->async_visible
&& visible
)
5909 /* wait_reading_process_output will notice this and update
5910 the frame's display structures. If we were made
5911 invisible, we should not set garbaged, because that stops
5912 redrawing on Update events. */
5913 SET_FRAME_GARBAGED (f
);
5916 buf
.kind
= DEICONIFY_EVENT
;
5917 XSETFRAME (buf
.frame_or_window
, f
);
5918 kbd_buffer_store_event (&buf
);
5920 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
5921 /* Force a redisplay sooner or later to update the
5922 frame titles in case this is the second frame. */
5923 record_asynch_buffer_change ();
5925 else if (f
->async_visible
&& !visible
)
5929 buf
.kind
= ICONIFY_EVENT
;
5930 XSETFRAME (buf
.frame_or_window
, f
);
5931 kbd_buffer_store_event (&buf
);
5934 f
->async_visible
= visible
;
5935 f
->async_iconified
= iconified
;
5938 /* This tries to wait until the frame is really visible.
5939 However, if the window manager asks the user where to position
5940 the frame, this will return before the user finishes doing that.
5941 The frame will not actually be visible at that time,
5942 but it will become visible later when the window manager
5943 finishes with it. */
5946 x_make_frame_visible (f
)
5950 int original_top
, original_left
;
5954 if (! FRAME_VISIBLE_P (f
))
5956 /* We test FRAME_GARBAGED_P here to make sure we don't
5957 call x_set_offset a second time
5958 if we get to x_make_frame_visible a second time
5959 before the window gets really visible. */
5960 if (! FRAME_ICONIFIED_P (f
)
5961 && ! f
->output_data
.mac
->asked_for_visible
)
5962 #if TARGET_API_MAC_CARBON
5963 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5965 struct frame
*sf
= SELECTED_FRAME ();
5966 if (!FRAME_MAC_P (sf
))
5967 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5968 kWindowCenterOnMainScreen
);
5970 RepositionWindow (FRAME_MAC_WINDOW (f
),
5971 FRAME_MAC_WINDOW (sf
),
5972 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5973 kWindowCascadeStartAtParentWindowScreen
5975 kWindowCascadeOnParentWindowScreen
5978 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5982 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5984 f
->output_data
.mac
->asked_for_visible
= 1;
5986 SelectWindow (FRAME_MAC_WINDOW (f
));
5987 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
5988 ShowWindow (FRAME_MAC_WINDOW (f
));
5991 XFlush (FRAME_MAC_DISPLAY (f
));
5993 /* Synchronize to ensure Emacs knows the frame is visible
5994 before we do anything else. We do this loop with input not blocked
5995 so that incoming events are handled. */
6000 /* This must come after we set COUNT. */
6003 XSETFRAME (frame
, f
);
6005 /* Wait until the frame is visible. Process X events until a
6006 MapNotify event has been seen, or until we think we won't get a
6007 MapNotify at all.. */
6008 for (count
= input_signal_count
+ 10;
6009 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6011 /* Force processing of queued events. */
6014 /* Machines that do polling rather than SIGIO have been
6015 observed to go into a busy-wait here. So we'll fake an
6016 alarm signal to let the handler know that there's something
6017 to be read. We used to raise a real alarm, but it seems
6018 that the handler isn't always enabled here. This is
6020 if (input_polling_used ())
6022 /* It could be confusing if a real alarm arrives while
6023 processing the fake one. Turn it off and let the
6024 handler reset it. */
6025 extern void poll_for_input_1
P_ ((void));
6026 int old_poll_suppress_count
= poll_suppress_count
;
6027 poll_suppress_count
= 1;
6028 poll_for_input_1 ();
6029 poll_suppress_count
= old_poll_suppress_count
;
6032 /* See if a MapNotify event has been processed. */
6033 FRAME_SAMPLE_VISIBILITY (f
);
6038 /* Change from mapped state to withdrawn state. */
6040 /* Make the frame visible (mapped and not iconified). */
6043 x_make_frame_invisible (f
)
6046 /* A deactivate event does not occur when the last visible frame is
6047 made invisible. So if we clear the highlight here, it will not
6048 be rehighlighted when it is made visible. */
6050 /* Don't keep the highlight on an invisible frame. */
6051 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6052 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6057 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6058 that the current position of the window is user-specified, rather than
6059 program-specified, so that when the window is mapped again, it will be
6060 placed at the same location, without forcing the user to position it
6061 by hand again (they have already done that once for this window.) */
6062 x_wm_set_size_hint (f
, (long) 0, 1);
6064 HideWindow (FRAME_MAC_WINDOW (f
));
6068 #if !USE_CARBON_EVENTS
6069 mac_handle_visibility_change (f
);
6073 /* Change window state from mapped to iconified. */
6081 /* A deactivate event does not occur when the last visible frame is
6082 iconified. So if we clear the highlight here, it will not be
6083 rehighlighted when it is deiconified. */
6085 /* Don't keep the highlight on an invisible frame. */
6086 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6087 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6090 if (f
->async_iconified
)
6095 FRAME_SAMPLE_VISIBILITY (f
);
6097 if (! FRAME_VISIBLE_P (f
))
6098 ShowWindow (FRAME_MAC_WINDOW (f
));
6100 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6105 error ("Can't notify window manager of iconification");
6107 #if !USE_CARBON_EVENTS
6108 mac_handle_visibility_change (f
);
6113 /* Free X resources of frame F. */
6116 x_free_frame_resources (f
)
6119 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6120 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6124 if (wp
!= tip_window
)
6125 remove_window_handler (wp
);
6128 if (wp
== tip_window
)
6129 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6130 closed' event. So we reset tip_window here. */
6133 free_frame_menubar (f
);
6135 if (FRAME_FACE_CACHE (f
))
6136 free_frame_faces (f
);
6140 if (FRAME_SIZE_HINTS (f
))
6141 xfree (FRAME_SIZE_HINTS (f
));
6143 xfree (f
->output_data
.mac
);
6144 f
->output_data
.mac
= NULL
;
6146 if (f
== dpyinfo
->x_focus_frame
)
6147 dpyinfo
->x_focus_frame
= 0;
6148 if (f
== dpyinfo
->x_focus_event_frame
)
6149 dpyinfo
->x_focus_event_frame
= 0;
6150 if (f
== dpyinfo
->x_highlight_frame
)
6151 dpyinfo
->x_highlight_frame
= 0;
6153 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6155 dpyinfo
->mouse_face_beg_row
6156 = dpyinfo
->mouse_face_beg_col
= -1;
6157 dpyinfo
->mouse_face_end_row
6158 = dpyinfo
->mouse_face_end_col
= -1;
6159 dpyinfo
->mouse_face_window
= Qnil
;
6160 dpyinfo
->mouse_face_deferred_gc
= 0;
6161 dpyinfo
->mouse_face_mouse_frame
= 0;
6168 /* Destroy the X window of frame F. */
6171 x_destroy_window (f
)
6174 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6176 x_free_frame_resources (f
);
6178 dpyinfo
->reference_count
--;
6182 /* Setting window manager hints. */
6184 /* Set the normal size hints for the window manager, for frame F.
6185 FLAGS is the flags word to use--or 0 meaning preserve the flags
6186 that the window now has.
6187 If USER_POSITION is nonzero, we set the USPosition
6188 flag (this is useful when FLAGS is 0). */
6190 x_wm_set_size_hint (f
, flags
, user_position
)
6195 int base_width
, base_height
, width_inc
, height_inc
;
6196 int min_rows
= 0, min_cols
= 0;
6197 XSizeHints
*size_hints
;
6199 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6200 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6201 width_inc
= FRAME_COLUMN_WIDTH (f
);
6202 height_inc
= FRAME_LINE_HEIGHT (f
);
6204 check_frame_size (f
, &min_rows
, &min_cols
);
6206 size_hints
= FRAME_SIZE_HINTS (f
);
6207 if (size_hints
== NULL
)
6209 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6210 bzero (size_hints
, sizeof (XSizeHints
));
6213 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6214 size_hints
->width_inc
= width_inc
;
6215 size_hints
->height_inc
= height_inc
;
6216 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6217 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6218 size_hints
->base_width
= base_width
;
6219 size_hints
->base_height
= base_height
;
6222 size_hints
->flags
= flags
;
6223 else if (user_position
)
6225 size_hints
->flags
&= ~ PPosition
;
6226 size_hints
->flags
|= USPosition
;
6230 #if 0 /* MAC_TODO: hide application instead of iconify? */
6231 /* Used for IconicState or NormalState */
6234 x_wm_set_window_state (f
, state
)
6238 #ifdef USE_X_TOOLKIT
6241 XtSetArg (al
[0], XtNinitialState
, state
);
6242 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6243 #else /* not USE_X_TOOLKIT */
6244 Window window
= FRAME_X_WINDOW (f
);
6246 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6247 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6249 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6250 #endif /* not USE_X_TOOLKIT */
6254 x_wm_set_icon_pixmap (f
, pixmap_id
)
6260 #ifndef USE_X_TOOLKIT
6261 Window window
= FRAME_X_WINDOW (f
);
6266 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6267 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6271 /* It seems there is no way to turn off use of an icon pixmap.
6272 The following line does it, only if no icon has yet been created,
6273 for some window managers. But with mwm it crashes.
6274 Some people say it should clear the IconPixmapHint bit in this case,
6275 but that doesn't work, and the X consortium said it isn't the
6276 right thing at all. Since there is no way to win,
6277 best to explicitly give up. */
6279 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6285 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6289 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6290 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6293 #else /* not USE_X_TOOLKIT */
6295 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6296 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6298 #endif /* not USE_X_TOOLKIT */
6301 #endif /* MAC_TODO */
6304 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6308 #if 0 /* MAC_TODO: no icons on Mac */
6309 #ifdef USE_X_TOOLKIT
6310 Window window
= XtWindow (f
->output_data
.x
->widget
);
6312 Window window
= FRAME_X_WINDOW (f
);
6315 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6316 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6317 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6319 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6320 #endif /* MAC_TODO */
6324 /***********************************************************************
6326 ***********************************************************************/
6328 /* An XLFD pattern is divided into blocks delimited by '*'. This
6329 structure holds information for each block. */
6330 struct xlfdpat_block
6332 /* Length of the pattern string in this block. Non-zero except for
6333 the first and the last blocks. */
6336 /* Pattern string except the last character in this block. The last
6337 character is replaced with NUL in order to use it as a
6339 unsigned char *pattern
;
6341 /* Last character of the pattern string. Must not be '?'. */
6342 unsigned char last_char
;
6344 /* One of the tables for the Boyer-Moore string search. It
6345 specifies the number of positions to proceed for each character
6346 with which the match fails. */
6349 /* The skip value for the last character in the above `skip' is
6350 assigned to `infinity' in order to simplify a loop condition.
6351 The original value is saved here. */
6357 /* Normalized pattern string. "Normalized" means that capital
6358 letters are lowered, blocks are not empty except the first and
6359 the last ones, and trailing '?'s in a block that is not the last
6360 one are moved to the next one. The last character in each block
6361 is replaced with NUL. */
6364 /* Number of characters except '*'s and trailing '?'s in the
6365 normalized pattern string. */
6368 /* Number of trailing '?'s in the normalized pattern string. */
6369 int trailing_anychars
;
6371 /* Number of blocks and information for each block. The latter is
6372 NULL if the pattern is exact (no '*' or '?' in it). */
6374 struct xlfdpat_block
*blocks
;
6378 xlfdpat_destroy (pat
)
6379 struct xlfdpat
*pat
;
6386 xfree (pat
->blocks
);
6393 static struct xlfdpat
*
6394 xlfdpat_create (pattern
)
6397 struct xlfdpat
*pat
;
6398 int nblocks
, i
, skip
;
6399 unsigned char last_char
, *p
, *q
, *anychar_head
;
6400 struct xlfdpat_block
*blk
;
6402 pat
= xmalloc (sizeof (struct xlfdpat
));
6406 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6407 if (pat
->buf
== NULL
)
6410 /* Normalize the pattern string and store it to `pat->buf'. */
6412 anychar_head
= NULL
;
6415 for (p
= pattern
; *p
; p
++)
6417 unsigned char c
= *p
;
6420 if (last_char
== '*')
6421 /* ...a** -> ...a* */
6425 if (last_char
== '?')
6426 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6427 /* ...*??* -> ...*?? */
6430 /* ...a??* -> ...a*?? */
6432 *anychar_head
++ = '*';
6439 if (last_char
!= '?')
6443 /* On Mac OS X 10.3, tolower also converts non-ASCII
6444 characters for some locales. */
6448 *q
++ = last_char
= c
;
6452 pat
->nblocks
= nblocks
;
6453 if (last_char
!= '?')
6454 pat
->trailing_anychars
= 0;
6457 pat
->trailing_anychars
= q
- anychar_head
;
6460 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6462 if (anychar_head
== NULL
&& nblocks
== 1)
6464 /* The pattern is exact. */
6469 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6470 if (pat
->blocks
== NULL
)
6473 /* Divide the normalized pattern into blocks. */
6475 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6480 blk
->len
= p
- blk
->pattern
;
6484 blk
->len
= q
- blk
->pattern
;
6486 /* Setup a table for the Boyer-Moore string search. */
6487 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6490 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6491 blk
->pattern
[blk
->len
- 1] = '\0';
6493 for (skip
= 1; skip
< blk
->len
; skip
++)
6494 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6497 for (i
= 0; i
< 256; i
++)
6498 blk
->skip
[i
] = skip
;
6500 p
= blk
->pattern
+ (blk
->len
- skip
);
6502 blk
->skip
[*p
++] = skip
;
6504 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6510 xlfdpat_destroy (pat
);
6515 xlfdpat_exact_p (pat
)
6516 struct xlfdpat
*pat
;
6518 return pat
->blocks
== NULL
;
6521 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6522 that the pattern in *BLK matches with its prefix. Return NULL
6523 there is no such strings. STRING must be lowered in advance. */
6526 xlfdpat_block_match_1 (blk
, string
, start_max
)
6527 struct xlfdpat_block
*blk
;
6528 unsigned char *string
;
6531 int start
, infinity
;
6532 unsigned char *p
, *s
;
6534 xassert (blk
->len
> 0);
6535 xassert (start_max
+ blk
->len
<= strlen (string
));
6536 xassert (blk
->last_char
!= '?');
6538 /* See the comments in the function `boyer_moore' (search.c) for the
6539 use of `infinity'. */
6540 infinity
= start_max
+ blk
->len
+ 1;
6541 blk
->skip
[blk
->last_char
] = infinity
;
6546 /* Check the last character of the pattern. */
6547 s
= string
+ blk
->len
- 1;
6550 start
+= blk
->skip
[*(s
+ start
)];
6552 while (start
<= start_max
);
6554 if (start
< infinity
)
6555 /* Couldn't find the last character. */
6558 /* No less than `infinity' means we could find the last
6559 character at `s[start - infinity]'. */
6562 /* Check the remaining characters. We prefer making no-'?'
6563 cases faster because the use of '?' is really rare. */
6568 while (*p
++ == *s
++)
6571 while (*(p
- 1) == '?');
6573 if (*(p
- 1) == '\0')
6575 return string
+ start
;
6578 start
+= blk
->last_char_skip
;
6580 while (start
<= start_max
);
6585 #define xlfdpat_block_match(b, s, m) \
6586 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6587 : xlfdpat_block_match_1 (b, s, m))
6589 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6590 matches with STRING. STRING must be lowered in advance. */
6593 xlfdpat_match (pat
, string
)
6594 struct xlfdpat
*pat
;
6595 unsigned char *string
;
6597 int str_len
, nblocks
, i
, start_max
;
6598 struct xlfdpat_block
*blk
;
6601 xassert (pat
->nblocks
> 0);
6603 if (xlfdpat_exact_p (pat
))
6604 return strcmp (pat
->buf
, string
) == 0;
6606 /* The number of the characters in the string must not be smaller
6607 than that in the pattern. */
6608 str_len
= strlen (string
);
6609 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6612 /* Chop off the trailing '?'s. */
6613 str_len
-= pat
->trailing_anychars
;
6615 /* The last block. When it is non-empty, it must match at the end
6617 nblocks
= pat
->nblocks
;
6618 blk
= pat
->blocks
+ (nblocks
- 1);
6620 /* The last block is also the first one. */
6621 return (str_len
== blk
->len
6622 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6623 else if (blk
->len
!= 0)
6624 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6627 /* The first block. When it is non-empty, it must match at the
6628 beginning of the string. */
6632 s
= xlfdpat_block_match (blk
, string
, 0);
6635 string
= s
+ blk
->len
;
6638 /* The rest of the blocks. */
6639 start_max
= str_len
- pat
->nchars
;
6640 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6642 s
= xlfdpat_block_match (blk
, string
, start_max
);
6645 start_max
-= s
- string
;
6646 string
= s
+ blk
->len
;
6653 /***********************************************************************
6655 ***********************************************************************/
6657 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6660 x_get_font_info (f
, font_idx
)
6664 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6667 /* the global font name table */
6668 static char **font_name_table
= NULL
;
6669 static int font_name_table_size
= 0;
6670 static int font_name_count
= 0;
6672 /* Alist linking font family names to Font Manager font family
6673 references (which can also be used as QuickDraw font IDs). We use
6674 an alist because hash tables are not ready when the terminal frame
6675 for Mac OS Classic is created. */
6676 static Lisp_Object fm_font_family_alist
;
6678 /* Hash table linking font family names to ATSU font IDs. */
6679 static Lisp_Object atsu_font_id_hash
;
6682 /* Alist linking character set strings to Mac text encoding and Emacs
6684 static Lisp_Object Vmac_charset_info_alist
;
6687 create_text_encoding_info_alist ()
6689 Lisp_Object result
= Qnil
, rest
;
6691 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6693 Lisp_Object charset_info
= XCAR (rest
);
6694 Lisp_Object charset
, coding_system
, text_encoding
;
6695 Lisp_Object existing_info
;
6697 if (!(CONSP (charset_info
)
6698 && STRINGP (charset
= XCAR (charset_info
))
6699 && CONSP (XCDR (charset_info
))
6700 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6701 && CONSP (XCDR (XCDR (charset_info
)))
6702 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6705 existing_info
= assq_no_quit (text_encoding
, result
);
6706 if (NILP (existing_info
))
6707 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6710 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6711 XSETCDR (XCDR (existing_info
),
6712 Fcons (charset
, XCDR (XCDR (existing_info
))));
6720 decode_mac_font_name (name
, size
, coding_system
)
6723 Lisp_Object coding_system
;
6725 struct coding_system coding
;
6728 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6730 for (p
= name
; *p
; p
++)
6731 if (!isascii (*p
) || iscntrl (*p
))
6736 setup_coding_system (coding_system
, &coding
);
6737 coding
.src_multibyte
= 0;
6738 coding
.dst_multibyte
= 1;
6739 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6740 coding
.dst_bytes
= size
;
6741 coding
.destination
= (unsigned char *) alloca (coding
.dst_bytes
);
6743 decode_coding_c_string (&coding
, name
, strlen (name
), Qnil
);
6744 bcopy (coding
.destination
, name
, min (coding
.produced
, size
));
6745 name
[min (coding
.produced
, size
)] = '\0';
6749 /* If there's just one occurrence of '-' in the family name, it is
6750 replaced with '_'. (More than one occurrence of '-' means a
6751 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6752 p
= strchr (name
, '-');
6753 if (p
&& strchr (p
+ 1, '-') == NULL
)
6756 for (p
= name
; *p
; p
++)
6757 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6758 for some locales. */
6765 mac_to_x_fontname (name
, size
, style
, charset
)
6773 char xf
[256], *result
;
6776 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6780 strcpy(foundry
, "Apple");
6781 strcpy(family
, name
);
6784 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6785 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6786 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
6788 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6789 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6790 for (p
= result
; *p
; p
++)
6791 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6792 for some locales. */
6799 /* Parse fully-specified and instantiated X11 font spec XF, and store
6800 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6801 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6802 caller must allocate at least 256 and 32 bytes respectively. For
6803 ordinary Mac fonts, the value stored to FAMILY should just be their
6804 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6805 intlfonts collection contain their charset designation in their
6806 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6807 types of font names are handled accordingly. */
6809 const int kDefaultFontSize
= 12;
6812 parse_x_font_name (xf
, family
, size
, style
, charset
)
6818 Str31 foundry
, weight
;
6819 int point_size
, avgwidth
;
6822 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6823 foundry
, family
, weight
, slant
, size
,
6824 &point_size
, &avgwidth
, charset
) != 8
6825 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6826 foundry
, family
, weight
, slant
, size
,
6827 &point_size
, &avgwidth
, charset
) != 8)
6833 *size
= point_size
/ 10;
6834 else if (avgwidth
> 0)
6835 *size
= avgwidth
/ 10;
6838 *size
= kDefaultFontSize
;
6841 if (strcmp (weight
, "bold") == 0)
6846 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
6848 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
6850 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
6852 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6853 but take overlap into account. */
6854 memmove (family
+ foundry_len
+ 1, family
, family_len
);
6855 memcpy (family
, foundry
, foundry_len
);
6856 family
[foundry_len
] = '-';
6857 family
[foundry_len
+ 1 + family_len
] = '-';
6858 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
6864 for (p
= family
; *p
; p
++)
6865 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6866 for some locales. */
6875 add_font_name_table_entry (char *font_name
)
6877 if (font_name_table_size
== 0)
6879 font_name_table_size
= 256;
6880 font_name_table
= (char **)
6881 xmalloc (font_name_table_size
* sizeof (char *));
6883 else if (font_name_count
+ 1 >= font_name_table_size
)
6885 font_name_table_size
*= 2;
6886 font_name_table
= (char **)
6887 xrealloc (font_name_table
,
6888 font_name_table_size
* sizeof (char *));
6891 font_name_table
[font_name_count
++] = font_name
;
6894 /* Sets up the table font_name_table to contain the list of all fonts
6895 in the system the first time the table is used so that the Resource
6896 Manager need not be accessed every time this information is
6900 init_font_name_table ()
6902 #if TARGET_API_MAC_CARBON
6903 FMFontFamilyIterator ffi
;
6904 FMFontFamilyInstanceIterator ffii
;
6906 Lisp_Object text_encoding_info_alist
;
6907 struct gcpro gcpro1
;
6909 text_encoding_info_alist
= create_text_encoding_info_alist ();
6912 #if USE_CG_TEXT_DRAWING
6913 init_cg_text_anti_aliasing_threshold ();
6915 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
6916 text_encoding_info_alist
)))
6919 ItemCount nfonts
, i
;
6920 ATSUFontID
*font_ids
= NULL
;
6921 Ptr name
, prev_name
= NULL
;
6925 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
6926 make_float (DEFAULT_REHASH_SIZE
),
6927 make_float (DEFAULT_REHASH_THRESHOLD
),
6929 err
= ATSUFontCount (&nfonts
);
6931 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
6933 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
6935 for (i
= 0; i
< nfonts
; i
++)
6937 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6938 kFontMacintoshPlatform
, kFontNoScript
,
6939 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
6942 name
= xmalloc (name_len
+ 1);
6945 name
[name_len
] = '\0';
6946 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6947 kFontMacintoshPlatform
, kFontNoScript
,
6948 kFontNoLanguage
, name_len
, name
,
6951 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
6954 && (prev_name
== NULL
6955 || strcmp (name
, prev_name
) != 0))
6957 static char *cs
= "iso10646-1";
6959 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6961 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6963 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6965 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6966 italic
| bold
, cs
));
6967 Fputhash (make_unibyte_string (name
, name_len
),
6968 long_to_cons (font_ids
[i
]), atsu_font_id_hash
);
6982 /* Create a dummy instance iterator here to avoid creating and
6983 destroying it in the loop. */
6984 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6986 /* Create an iterator to enumerate the font families. */
6987 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6990 FMDisposeFontFamilyInstanceIterator (&ffii
);
6994 GCPRO1 (text_encoding_info_alist
);
6996 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7002 TextEncoding encoding
;
7003 TextEncodingBase sc
;
7004 Lisp_Object text_encoding_info
;
7006 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7012 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7014 sc
= GetTextEncodingBase (encoding
);
7015 text_encoding_info
= assq_no_quit (make_number (sc
),
7016 text_encoding_info_alist
);
7017 if (NILP (text_encoding_info
))
7018 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7019 text_encoding_info_alist
);
7020 decode_mac_font_name (name
, sizeof (name
),
7021 XCAR (XCDR (text_encoding_info
)));
7022 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7024 fm_font_family_alist
);
7026 /* Point the instance iterator at the current font family. */
7027 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7030 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7033 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7035 if (size
> 0 || style
== normal
)
7036 for (; !NILP (rest
); rest
= XCDR (rest
))
7038 char *cs
= SDATA (XCAR (rest
));
7042 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7044 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7046 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7048 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7054 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7063 /* Dispose of the iterators. */
7064 FMDisposeFontFamilyIterator (&ffi
);
7065 FMDisposeFontFamilyInstanceIterator (&ffii
);
7066 #else /* !TARGET_API_MAC_CARBON */
7068 SInt16 fontnum
, old_fontnum
;
7069 int num_mac_fonts
= CountResources('FOND');
7071 Handle font_handle
, font_handle_2
;
7072 short id
, scriptcode
;
7075 struct FontAssoc
*fat
;
7076 struct AsscEntry
*assc_entry
;
7077 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
7078 struct gcpro gcpro1
;
7080 GetPort (&port
); /* save the current font number used */
7081 old_fontnum
= port
->txFont
;
7083 text_encoding_info_alist
= create_text_encoding_info_alist ();
7085 GCPRO1 (text_encoding_info_alist
);
7087 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7089 font_handle
= GetIndResource ('FOND', i
);
7093 GetResInfo (font_handle
, &id
, &type
, name
);
7094 GetFNum (name
, &fontnum
);
7100 scriptcode
= FontToScript (fontnum
);
7101 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7102 text_encoding_info_alist
);
7103 if (NILP (text_encoding_info
))
7104 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7105 text_encoding_info_alist
);
7106 decode_mac_font_name (name
, sizeof (name
),
7107 XCAR (XCDR (text_encoding_info
)));
7108 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7109 make_number (fontnum
)),
7110 fm_font_family_alist
);
7113 HLock (font_handle
);
7115 if (GetResourceSizeOnDisk (font_handle
)
7116 >= sizeof (struct FamRec
))
7118 fat
= (struct FontAssoc
*) (*font_handle
7119 + sizeof (struct FamRec
));
7121 = (struct AsscEntry
*) (*font_handle
7122 + sizeof (struct FamRec
)
7123 + sizeof (struct FontAssoc
));
7125 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7127 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7129 for (; !NILP (rest
); rest
= XCDR (rest
))
7131 char *cs
= SDATA (XCAR (rest
));
7133 add_font_name_table_entry (mac_to_x_fontname (name
,
7134 assc_entry
->fontSize
,
7135 assc_entry
->fontStyle
,
7141 HUnlock (font_handle
);
7142 font_handle_2
= GetNextFOND (font_handle
);
7143 ReleaseResource (font_handle
);
7144 font_handle
= font_handle_2
;
7146 while (ResError () == noErr
&& font_handle
);
7151 TextFont (old_fontnum
);
7152 #endif /* !TARGET_API_MAC_CARBON */
7157 mac_clear_font_name_table ()
7161 for (i
= 0; i
< font_name_count
; i
++)
7162 xfree (font_name_table
[i
]);
7163 xfree (font_name_table
);
7164 font_name_table
= NULL
;
7165 font_name_table_size
= font_name_count
= 0;
7166 fm_font_family_alist
= Qnil
;
7170 enum xlfd_scalable_field_index
7172 XLFD_SCL_PIXEL_SIZE
,
7173 XLFD_SCL_POINT_SIZE
,
7178 static int xlfd_scalable_fields
[] =
7187 mac_do_list_fonts (pattern
, maxnames
)
7192 Lisp_Object font_list
= Qnil
;
7193 struct xlfdpat
*pat
;
7195 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7198 if (font_name_table
== NULL
) /* Initialize when first used. */
7199 init_font_name_table ();
7201 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7204 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7205 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7206 fonts are scaled according to the specified size. */
7209 field
= xlfd_scalable_fields
;
7217 if ('0' <= *ptr
&& *ptr
<= '9')
7219 *val
= *ptr
++ - '0';
7220 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7221 *val
= *val
* 10 + *ptr
++ - '0';
7228 ptr
= strchr (ptr
, '-');
7231 while (ptr
&& i
< 14);
7233 if (i
== 14 && ptr
== NULL
)
7235 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7236 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7237 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7238 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7240 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7241 scl_val
[XLFD_SCL_POINT_SIZE
] =
7242 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7243 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7245 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7246 scl_val
[XLFD_SCL_AVGWIDTH
] =
7247 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7248 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7252 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7254 pat
= xlfdpat_create (pattern
);
7258 exact
= xlfdpat_exact_p (pat
);
7260 for (i
= 0; i
< font_name_count
; i
++)
7262 if (xlfdpat_match (pat
, font_name_table
[i
]))
7264 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7265 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7268 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7269 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7271 int former_len
= ptr
- font_name_table
[i
];
7273 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7276 memcpy (scaled
, font_name_table
[i
], former_len
);
7277 sprintf (scaled
+ former_len
,
7278 "-%d-%d-72-72-m-%d-%s",
7279 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7280 scl_val
[XLFD_SCL_POINT_SIZE
],
7281 scl_val
[XLFD_SCL_AVGWIDTH
],
7282 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7284 if (xlfdpat_match (pat
, scaled
))
7286 font_list
= Fcons (build_string (scaled
), font_list
);
7288 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7296 xlfdpat_destroy (pat
);
7301 /* Return a list of names of available fonts matching PATTERN on frame F.
7303 Frame F null means we have not yet created any frame on Mac, and
7304 consult the first display in x_display_list. MAXNAMES sets a limit
7305 on how many fonts to match. */
7308 x_list_fonts (f
, pattern
, size
, maxnames
)
7310 Lisp_Object pattern
;
7313 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7314 struct mac_display_info
*dpyinfo
7315 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7317 xassert (size
<= 0);
7319 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7320 if (NILP (patterns
))
7321 patterns
= Fcons (pattern
, Qnil
);
7323 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7325 pattern
= XCAR (patterns
);
7327 if (!STRINGP (pattern
))
7330 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7331 key
= Fcons (pattern
, make_number (maxnames
));
7333 list
= Fassoc (key
, tem
);
7336 list
= Fcdr_safe (list
);
7337 /* We have a cashed list. Don't have to get the list again. */
7342 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7345 /* MAC_TODO: add code for matching outline fonts here */
7347 /* Now store the result in the cache. */
7348 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7349 Fcons (Fcons (key
, list
),
7350 XCAR (XCDR (dpyinfo
->name_list_element
))));
7353 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7362 /* Check that FONT is valid on frame F. It is if it can be found in F's
7366 x_check_font (f
, font
)
7371 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7373 xassert (font
!= NULL
);
7375 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7376 if (dpyinfo
->font_table
[i
].name
7377 && font
== dpyinfo
->font_table
[i
].font
)
7380 xassert (i
< dpyinfo
->n_fonts
);
7383 #endif /* GLYPH_DEBUG != 0 */
7385 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7386 Note: There are (broken) X fonts out there with invalid XFontStruct
7387 min_bounds contents. For example, handa@etl.go.jp reports that
7388 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7389 have font->min_bounds.width == 0. */
7392 x_font_min_bounds (font
, w
, h
)
7393 MacFontStruct
*font
;
7396 *h
= FONT_HEIGHT (font
);
7397 *w
= font
->min_bounds
.width
;
7401 /* Compute the smallest character width and smallest font height over
7402 all fonts available on frame F. Set the members smallest_char_width
7403 and smallest_font_height in F's x_display_info structure to
7404 the values computed. Value is non-zero if smallest_font_height or
7405 smallest_char_width become smaller than they were before. */
7408 x_compute_min_glyph_bounds (f
)
7412 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7413 MacFontStruct
*font
;
7414 int old_width
= dpyinfo
->smallest_char_width
;
7415 int old_height
= dpyinfo
->smallest_font_height
;
7417 dpyinfo
->smallest_font_height
= 100000;
7418 dpyinfo
->smallest_char_width
= 100000;
7420 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7421 if (dpyinfo
->font_table
[i
].name
)
7423 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7426 font
= (MacFontStruct
*) fontp
->font
;
7427 xassert (font
!= (MacFontStruct
*) ~0);
7428 x_font_min_bounds (font
, &w
, &h
);
7430 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7431 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7434 xassert (dpyinfo
->smallest_char_width
> 0
7435 && dpyinfo
->smallest_font_height
> 0);
7437 return (dpyinfo
->n_fonts
== 1
7438 || dpyinfo
->smallest_char_width
< old_width
7439 || dpyinfo
->smallest_font_height
< old_height
);
7443 /* Determine whether given string is a fully-specified XLFD: all 14
7444 fields are present, none is '*'. */
7447 is_fully_specified_xlfd (char *p
)
7455 for (i
= 0; i
< 13; i
++)
7457 q
= strchr (p
+ 1, '-');
7460 if (q
- p
== 2 && *(p
+ 1) == '*')
7465 if (strchr (p
+ 1, '-') != NULL
)
7468 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7475 /* XLoadQueryFont creates and returns an internal representation for a
7476 font in a MacFontStruct struct. There is really no concept
7477 corresponding to "loading" a font on the Mac. But we check its
7478 existence and find the font number and all other information for it
7479 and store them in the returned MacFontStruct. */
7481 static MacFontStruct
*
7482 XLoadQueryFont (Display
*dpy
, char *fontname
)
7490 static ATSUFontID font_id
;
7491 ATSUStyle mac_style
= NULL
;
7494 #if TARGET_API_MAC_CARBON
7495 TextEncoding encoding
;
7500 MacFontStruct
*font
;
7501 XCharStruct
*space_bounds
= NULL
, *pcm
;
7503 if (is_fully_specified_xlfd (fontname
))
7507 Lisp_Object matched_fonts
;
7509 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7510 if (NILP (matched_fonts
))
7512 name
= SDATA (XCAR (matched_fonts
));
7515 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7519 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7522 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7523 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7524 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7525 sizeof (Boolean
), sizeof (Boolean
)};
7526 static Fixed size_fixed
;
7527 static Boolean bold_p
, italic_p
;
7528 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7529 &bold_p
, &italic_p
};
7530 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
,
7532 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
,
7533 kDecomposeDiacriticsSelector
};
7534 Lisp_Object font_id_cons
;
7536 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7537 atsu_font_id_hash
, Qnil
);
7538 if (NILP (font_id_cons
))
7540 font_id
= cons_to_long (font_id_cons
);
7541 size_fixed
= Long2Fix (size
);
7542 bold_p
= (fontface
& bold
) != 0;
7543 italic_p
= (fontface
& italic
) != 0;
7544 err
= ATSUCreateStyle (&mac_style
);
7547 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7551 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7552 tags
, sizes
, values
);
7554 scriptcode
= kTextEncodingMacUnicode
;
7559 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7563 fontnum
= XINT (XCDR (tmp
));
7564 #if TARGET_API_MAC_CARBON
7565 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7567 scriptcode
= GetTextEncodingBase (encoding
);
7569 scriptcode
= FontToScript (fontnum
);
7573 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7575 font
->mac_fontnum
= fontnum
;
7576 font
->mac_fontsize
= size
;
7577 font
->mac_fontface
= fontface
;
7578 font
->mac_scriptcode
= scriptcode
;
7580 font
->mac_style
= mac_style
;
7581 #if USE_CG_TEXT_DRAWING
7582 font
->cg_font
= NULL
;
7583 font
->cg_glyphs
= NULL
;
7587 /* Apple Japanese (SJIS) font is listed as both
7588 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7589 (Roman script) in init_font_name_table (). The latter should be
7590 treated as a one-byte font. */
7591 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7592 font
->mac_scriptcode
= smRoman
;
7594 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7597 if (font
->mac_style
)
7602 font
->min_byte1
= 0;
7603 font
->max_byte1
= 0xff;
7604 font
->min_char_or_byte2
= 0;
7605 font
->max_char_or_byte2
= 0xff;
7607 font
->bounds
.rows
= xmalloc (sizeof (XCharStructRow
*) * 0x100);
7608 if (font
->bounds
.rows
== NULL
)
7610 mac_unload_font (&one_mac_display_info
, font
);
7613 bzero (font
->bounds
.rows
, sizeof (XCharStructRow
*) * 0x100);
7614 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStructRow
));
7615 if (font
->bounds
.rows
[0] == NULL
)
7617 mac_unload_font (&one_mac_display_info
, font
);
7620 bzero (font
->bounds
.rows
[0], sizeof (XCharStructRow
));
7622 #if USE_CG_TEXT_DRAWING
7624 FMFontFamily font_family
;
7626 ATSFontRef ats_font
;
7628 err
= FMGetFontFamilyInstanceFromFont (font_id
, &font_family
, &style
);
7630 err
= FMGetFontFromFontFamilyInstance (font_family
, fontface
,
7632 /* Use CG text drawing if italic/bold is not synthesized. */
7633 if (err
== noErr
&& style
== fontface
)
7635 ats_font
= FMGetATSFontRefFromFont (font_id
);
7636 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7641 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7642 if (font
->cg_glyphs
)
7643 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7645 space_bounds
= font
->bounds
.rows
[0]->per_char
+ 0x20;
7646 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7647 &font
->ascent
, &font
->descent
,
7649 #if USE_CG_TEXT_DRAWING
7650 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7658 mac_unload_font (&one_mac_display_info
, font
);
7661 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], 0x20);
7663 pcm
= font
->bounds
.rows
[0]->per_char
;
7664 for (c
= 0x21; c
<= 0xff; c
++)
7667 /* Soft hyphen is not supported in ATSUI. */
7675 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
7676 #if USE_CG_TEXT_DRAWING
7677 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7683 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], c
);
7685 #if USE_CG_TEXT_DRAWING
7686 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7688 /* Don't use CG text drawing if font substitution occurs in
7689 ASCII or Latin-1 characters. */
7690 CGFontRelease (font
->cg_font
);
7691 font
->cg_font
= NULL
;
7692 xfree (font
->cg_glyphs
);
7693 font
->cg_glyphs
= NULL
;
7702 SInt16 old_fontnum
, old_fontsize
;
7704 FontInfo the_fontinfo
;
7705 int is_two_byte_font
;
7707 /* Save the current font number used. */
7709 #if TARGET_API_MAC_CARBON
7710 old_fontnum
= GetPortTextFont (port
);
7711 old_fontsize
= GetPortTextSize (port
);
7712 old_fontface
= GetPortTextFace (port
);
7714 old_fontnum
= port
->txFont
;
7715 old_fontsize
= port
->txSize
;
7716 old_fontface
= port
->txFace
;
7721 TextFace (fontface
);
7723 GetFontInfo (&the_fontinfo
);
7725 font
->ascent
= the_fontinfo
.ascent
;
7726 font
->descent
= the_fontinfo
.descent
;
7728 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7729 || font
->mac_scriptcode
== smTradChinese
7730 || font
->mac_scriptcode
== smSimpChinese
7731 || font
->mac_scriptcode
== smKorean
);
7733 if (is_two_byte_font
)
7737 font
->min_byte1
= 0xa1;
7738 font
->max_byte1
= 0xfe;
7739 font
->min_char_or_byte2
= 0xa1;
7740 font
->max_char_or_byte2
= 0xfe;
7742 /* Use the width of an "ideographic space" of that font
7743 because the_fontinfo.widMax returns the wrong width for
7745 switch (font
->mac_scriptcode
)
7748 font
->min_byte1
= 0x81;
7749 font
->max_byte1
= 0xfc;
7750 font
->min_char_or_byte2
= 0x40;
7751 font
->max_char_or_byte2
= 0xfc;
7752 char_width
= StringWidth("\p\x81\x40");
7755 font
->min_char_or_byte2
= 0x40;
7756 char_width
= StringWidth("\p\xa1\x40");
7759 char_width
= StringWidth("\p\xa1\xa1");
7762 char_width
= StringWidth("\p\xa1\xa1");
7766 font
->bounds
.per_char
= NULL
;
7768 if (fontface
& italic
)
7769 font
->max_bounds
.rbearing
= char_width
+ 1;
7771 font
->max_bounds
.rbearing
= char_width
;
7772 font
->max_bounds
.lbearing
= 0;
7773 font
->max_bounds
.width
= char_width
;
7774 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7775 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7777 font
->min_bounds
= font
->max_bounds
;
7783 font
->min_byte1
= font
->max_byte1
= 0;
7784 font
->min_char_or_byte2
= 0x20;
7785 font
->max_char_or_byte2
= 0xff;
7787 font
->bounds
.per_char
=
7788 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7789 if (font
->bounds
.per_char
== NULL
)
7791 mac_unload_font (&one_mac_display_info
, font
);
7794 bzero (font
->bounds
.per_char
,
7795 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7797 space_bounds
= font
->bounds
.per_char
;
7798 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
7799 space_bounds
, NULL
);
7801 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
7802 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
7805 /* Restore previous font number, size and face. */
7806 TextFont (old_fontnum
);
7807 TextSize (old_fontsize
);
7808 TextFace (old_fontface
);
7815 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
7816 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
7819 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
7821 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
7823 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
7825 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
7828 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
7830 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
7832 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
7834 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
7839 font
->mac_style
== NULL
&&
7841 font
->max_bounds
.width
== font
->min_bounds
.width
7842 && font
->min_bounds
.lbearing
>= 0
7843 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
7845 /* Fixed width and no overhangs. */
7846 xfree (font
->bounds
.per_char
);
7847 font
->bounds
.per_char
= NULL
;
7851 #if !defined (MAC_OS8) || USE_ATSUI
7852 /* AppKit and WebKit do some adjustment to the heights of Courier,
7853 Helvetica, and Times. This only works on the environments where
7854 the XDrawImageString counterpart is never used. */
7855 if (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
7856 || strcmp (family
, "times") == 0)
7857 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
7865 mac_unload_font (dpyinfo
, font
)
7866 struct mac_display_info
*dpyinfo
;
7869 xfree (font
->full_name
);
7871 if (font
->mac_style
)
7875 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
7876 if (font
->bounds
.rows
[i
])
7877 xfree (font
->bounds
.rows
[i
]);
7878 xfree (font
->bounds
.rows
);
7879 ATSUDisposeStyle (font
->mac_style
);
7883 if (font
->bounds
.per_char
)
7884 xfree (font
->bounds
.per_char
);
7885 #if USE_CG_TEXT_DRAWING
7887 CGFontRelease (font
->cg_font
);
7888 if (font
->cg_glyphs
)
7889 xfree (font
->cg_glyphs
);
7895 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7896 pointer to the structure font_info while allocating it dynamically.
7897 If SIZE is 0, load any size of font.
7898 If loading is failed, return NULL. */
7901 x_load_font (f
, fontname
, size
)
7903 register char *fontname
;
7906 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7907 Lisp_Object font_names
;
7909 /* Get a list of all the fonts that match this name. Once we
7910 have a list of matching fonts, we compare them against the fonts
7911 we already have by comparing names. */
7912 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7914 if (!NILP (font_names
))
7919 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7920 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7921 if (dpyinfo
->font_table
[i
].name
7922 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7923 SDATA (XCAR (tail
)))
7924 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7925 SDATA (XCAR (tail
)))))
7926 return (dpyinfo
->font_table
+ i
);
7931 /* Load the font and add it to the table. */
7934 struct MacFontStruct
*font
;
7935 struct font_info
*fontp
;
7936 unsigned long value
;
7939 fontname
= (char *) SDATA (XCAR (font_names
));
7942 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7947 /* Find a free slot in the font table. */
7948 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7949 if (dpyinfo
->font_table
[i
].name
== NULL
)
7952 /* If no free slot found, maybe enlarge the font table. */
7953 if (i
== dpyinfo
->n_fonts
7954 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7957 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7958 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7960 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7963 fontp
= dpyinfo
->font_table
+ i
;
7964 if (i
== dpyinfo
->n_fonts
)
7967 /* Now fill in the slots of *FONTP. */
7969 bzero (fontp
, sizeof (*fontp
));
7971 fontp
->font_idx
= i
;
7972 fontp
->charset
= -1; /* fs_load_font sets it. */
7973 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7974 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7976 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7978 /* Fixed width font. */
7979 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7986 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7987 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7989 fontp
->space_width
= pcm
->width
;
7991 fontp
->space_width
= FONT_WIDTH (font
);
7995 int width
= pcm
->width
;
7996 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7997 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7998 width
+= pcm
->width
;
7999 fontp
->average_width
= width
/ 95;
8002 fontp
->average_width
= FONT_WIDTH (font
);
8005 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8006 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8008 fontp
->size
= font
->max_bounds
.width
;
8009 fontp
->height
= FONT_HEIGHT (font
);
8011 /* For some font, ascent and descent in max_bounds field is
8012 larger than the above value. */
8013 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8014 if (max_height
> fontp
->height
)
8015 fontp
->height
= max_height
;
8018 /* MAC_TODO: The script encoding is irrelevant in unicode? */
8019 /* The slot `encoding' specifies how to map a character
8020 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8021 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8022 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8023 2:0xA020..0xFF7F). For the moment, we don't know which charset
8024 uses this font. So, we set information in fontp->encoding_type
8025 which is never used by any charset. If mapping can't be
8026 decided, set FONT_ENCODING_NOT_DECIDED. */
8027 if (font
->mac_scriptcode
== smJapanese
)
8028 fontp
->encoding_type
= 4;
8031 fontp
->encoding_type
8032 = (font
->max_byte1
== 0
8034 ? (font
->min_char_or_byte2
< 0x80
8035 ? (font
->max_char_or_byte2
< 0x80
8036 ? 0 /* 0x20..0x7F */
8037 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8038 : 1) /* 0xA0..0xFF */
8040 : (font
->min_byte1
< 0x80
8041 ? (font
->max_byte1
< 0x80
8042 ? (font
->min_char_or_byte2
< 0x80
8043 ? (font
->max_char_or_byte2
< 0x80
8044 ? 0 /* 0x2020..0x7F7F */
8045 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8046 : 3) /* 0x20A0..0x7FFF */
8047 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8048 : (font
->min_char_or_byte2
< 0x80
8049 ? (font
->max_char_or_byte2
< 0x80
8050 ? 2 /* 0xA020..0xFF7F */
8051 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8052 : 1))); /* 0xA0A0..0xFFFF */
8055 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8056 fontp
->baseline_offset
8057 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8058 ? (long) value
: 0);
8059 fontp
->relative_compose
8060 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8061 ? (long) value
: 0);
8062 fontp
->default_ascent
8063 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8064 ? (long) value
: 0);
8066 fontp
->baseline_offset
= 0;
8067 fontp
->relative_compose
= 0;
8068 fontp
->default_ascent
= 0;
8071 /* Set global flag fonts_changed_p to non-zero if the font loaded
8072 has a character with a smaller width than any other character
8073 before, or if the font loaded has a smaller height than any
8074 other font loaded before. If this happens, it will make a
8075 glyph matrix reallocation necessary. */
8076 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8083 /* Return a pointer to struct font_info of a font named FONTNAME for
8084 frame F. If no such font is loaded, return NULL. */
8087 x_query_font (f
, fontname
)
8089 register char *fontname
;
8091 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8094 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8095 if (dpyinfo
->font_table
[i
].name
8096 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8097 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8098 return (dpyinfo
->font_table
+ i
);
8103 /* Find a CCL program for a font specified by FONTP, and set the member
8104 `encoder' of the structure. */
8107 x_find_ccl_program (fontp
)
8108 struct font_info
*fontp
;
8110 Lisp_Object list
, elt
;
8112 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8116 && STRINGP (XCAR (elt
))
8117 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8123 struct ccl_program
*ccl
8124 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8126 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8129 fontp
->font_encoder
= ccl
;
8135 /* The Mac Event loop code */
8137 #if !TARGET_API_MAC_CARBON
8139 #include <Quickdraw.h>
8140 #include <Balloons.h>
8141 #include <Devices.h>
8143 #include <Gestalt.h>
8145 #include <Processes.h>
8147 #include <ToolUtils.h>
8148 #include <TextUtils.h>
8149 #include <Dialogs.h>
8152 #include <Resources.h>
8157 #endif /* ! TARGET_API_MAC_CARBON */
8162 #define WINDOW_RESOURCE 128
8163 #define TERM_WINDOW_RESOURCE 129
8165 #define DEFAULT_NUM_COLS 80
8167 #define MIN_DOC_SIZE 64
8168 #define MAX_DOC_SIZE 32767
8170 #define EXTRA_STACK_ALLOC (256 * 1024)
8172 #define ARGV_STRING_LIST_ID 129
8173 #define ABOUT_ALERT_ID 128
8174 #define RAM_TOO_LARGE_ALERT_ID 129
8176 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8177 Lisp_Object Qreverse
;
8180 /* Modifier associated with the control key, or nil to ignore. */
8181 Lisp_Object Vmac_control_modifier
;
8183 /* Modifier associated with the option key, or nil to ignore. */
8184 Lisp_Object Vmac_option_modifier
;
8186 /* Modifier associated with the command key, or nil to ignore. */
8187 Lisp_Object Vmac_command_modifier
;
8189 /* Modifier associated with the function key, or nil to ignore. */
8190 Lisp_Object Vmac_function_modifier
;
8192 /* True if the option and command modifiers should be used to emulate
8193 a three button mouse */
8194 Lisp_Object Vmac_emulate_three_button_mouse
;
8196 #if USE_CARBON_EVENTS
8197 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8198 mouse-2, instead of mouse-3. */
8199 int mac_wheel_button_is_mouse_2
;
8201 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8202 for processing before Emacs sees it. */
8203 int mac_pass_command_to_system
;
8205 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8206 for processing before Emacs sees it. */
8207 int mac_pass_control_to_system
;
8210 /* Points to the variable `inev' in the function XTread_socket. It is
8211 used for passing an input event to the function back from
8212 Carbon/Apple event handlers. */
8213 static struct input_event
*read_socket_inev
= NULL
;
8215 Point saved_menu_event_location
;
8218 #if USE_CARBON_EVENTS
8219 static Lisp_Object Qhicommand
;
8221 extern int mac_ready_for_apple_events
;
8222 extern Lisp_Object Qundefined
;
8223 extern void init_apple_event_handler
P_ ((void));
8224 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8225 Lisp_Object
*, Lisp_Object
*,
8227 extern OSErr init_coercion_handler
P_ ((void));
8229 #if TARGET_API_MAC_CARBON
8231 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
8232 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
8233 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
8234 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
8237 #if USE_CARBON_EVENTS
8239 extern void init_service_handler ();
8240 static Lisp_Object Qservices
, Qpaste
, Qperform
;
8242 /* Window Event Handler */
8243 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8246 OSErr
install_window_handler (WindowPtr
);
8248 extern void init_emacs_passwd_dir ();
8249 extern int emacs_main (int, char **, char **);
8251 extern void initialize_applescript();
8252 extern void terminate_applescript();
8255 #if USE_CARBON_EVENTS
8256 mac_to_emacs_modifiers (UInt32 mods
)
8258 mac_to_emacs_modifiers (EventModifiers mods
)
8261 unsigned int result
= 0;
8262 if (mods
& shiftKey
)
8263 result
|= shift_modifier
;
8265 /* Deactivated to simplify configuration:
8266 if Vmac_option_modifier is non-NIL, we fully process the Option
8267 key. Otherwise, we only process it if an additional Ctrl or Command
8268 is pressed. That way the system may convert the character to a
8270 if ((mods & optionKey) &&
8271 (( !NILP(Vmac_option_modifier) ||
8272 ((mods & cmdKey) || (mods & controlKey))))) */
8274 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8275 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8277 result
|= XUINT(val
);
8279 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8280 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8282 result
|= XUINT(val
);
8284 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8285 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8287 result
|= XUINT(val
);
8291 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8292 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8294 result
|= XUINT(val
);
8302 mac_get_emulated_btn ( UInt32 modifiers
)
8305 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8306 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8307 if (modifiers
& cmdKey
)
8308 result
= cmdIs3
? 2 : 1;
8309 else if (modifiers
& optionKey
)
8310 result
= cmdIs3
? 1 : 2;
8315 #if USE_CARBON_EVENTS
8316 /* Obtains the event modifiers from the event ref and then calls
8317 mac_to_emacs_modifiers. */
8319 mac_event_to_emacs_modifiers (EventRef eventRef
)
8322 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8323 sizeof (UInt32
), NULL
, &mods
);
8324 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8325 GetEventClass(eventRef
) == kEventClassMouse
)
8327 mods
&= ~(optionKey
| cmdKey
);
8329 return mac_to_emacs_modifiers (mods
);
8332 /* Given an event ref, return the code to use for the mouse button
8333 code in the emacs input_event. */
8335 mac_get_mouse_btn (EventRef ref
)
8337 EventMouseButton result
= kEventMouseButtonPrimary
;
8338 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8339 sizeof (EventMouseButton
), NULL
, &result
);
8342 case kEventMouseButtonPrimary
:
8343 if (NILP (Vmac_emulate_three_button_mouse
))
8347 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8348 sizeof (UInt32
), NULL
, &mods
);
8349 return mac_get_emulated_btn(mods
);
8351 case kEventMouseButtonSecondary
:
8352 return mac_wheel_button_is_mouse_2
? 2 : 1;
8353 case kEventMouseButtonTertiary
:
8354 case 4: /* 4 is the number for the mouse wheel button */
8355 return mac_wheel_button_is_mouse_2
? 1 : 2;
8361 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8362 events. However the click of the mouse wheel is not converted to a
8363 mouseDown or mouseUp event. Likewise for dead key down events.
8364 This calls ConvertEventRef, but then checks to see if it is a mouse
8365 up/down, or a dead key down carbon event that has not been
8366 converted, and if so, converts it by hand (to be picked up in the
8367 XTread_socket loop). */
8368 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8370 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8375 switch (GetEventClass (eventRef
))
8377 case kEventClassMouse
:
8378 switch (GetEventKind (eventRef
))
8380 case kEventMouseDown
:
8381 eventRec
->what
= mouseDown
;
8386 eventRec
->what
= mouseUp
;
8395 case kEventClassKeyboard
:
8396 switch (GetEventKind (eventRef
))
8398 case kEventRawKeyDown
:
8400 unsigned char char_codes
;
8403 eventRec
->what
= keyDown
;
8404 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
8405 NULL
, sizeof (char), NULL
, &char_codes
);
8406 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
8407 NULL
, sizeof (UInt32
), NULL
, &key_code
);
8408 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8424 /* Need where and when. */
8427 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8428 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8429 /* Use two step process because new event modifiers are 32-bit
8430 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8431 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8432 NULL
, sizeof (UInt32
), NULL
, &mods
);
8433 eventRec
->modifiers
= mods
;
8435 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8446 Handle menubar_handle
;
8447 MenuHandle menu_handle
;
8449 menubar_handle
= GetNewMBar (128);
8450 if(menubar_handle
== NULL
)
8452 SetMenuBar (menubar_handle
);
8455 #if !TARGET_API_MAC_CARBON
8456 menu_handle
= GetMenuHandle (M_APPLE
);
8457 if(menu_handle
!= NULL
)
8458 AppendResMenu (menu_handle
,'DRVR');
8466 do_init_managers (void)
8468 #if !TARGET_API_MAC_CARBON
8469 InitGraf (&qd
.thePort
);
8471 FlushEvents (everyEvent
, 0);
8476 #endif /* !TARGET_API_MAC_CARBON */
8479 #if !TARGET_API_MAC_CARBON
8480 /* set up some extra stack space for use by emacs */
8481 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8483 /* MaxApplZone must be called for AppleScript to execute more
8484 complicated scripts */
8487 #endif /* !TARGET_API_MAC_CARBON */
8491 do_check_ram_size (void)
8493 SInt32 physical_ram_size
, logical_ram_size
;
8495 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8496 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8497 || physical_ram_size
> (1 << VALBITS
)
8498 || logical_ram_size
> (1 << VALBITS
))
8500 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8506 do_window_update (WindowPtr win
)
8508 struct frame
*f
= mac_window_to_frame (win
);
8512 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8514 if (win
!= tip_window
)
8516 if (f
->async_visible
== 0)
8518 /* Update events may occur when a frame gets iconified. */
8520 f
->async_visible
= 1;
8521 f
->async_iconified
= 0;
8522 SET_FRAME_GARBAGED (f
);
8528 #if TARGET_API_MAC_CARBON
8529 RgnHandle region
= NewRgn ();
8531 GetPortVisibleRegion (GetWindowPort (win
), region
);
8532 GetRegionBounds (region
, &r
);
8533 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8534 UpdateControls (win
, region
);
8535 DisposeRgn (region
);
8537 r
= (*win
->visRgn
)->rgnBBox
;
8538 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8539 UpdateControls (win
, win
->visRgn
);
8548 is_emacs_window (WindowPtr win
)
8550 Lisp_Object tail
, frame
;
8555 FOR_EACH_FRAME (tail
, frame
)
8556 if (FRAME_MAC_P (XFRAME (frame
)))
8557 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8566 /* Window-activate events will do the job. */
8572 /* Window-deactivate events will do the job. */
8577 do_apple_menu (SInt16 menu_item
)
8579 #if !TARGET_API_MAC_CARBON
8581 SInt16 da_driver_refnum
;
8583 if (menu_item
== I_ABOUT
)
8584 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8587 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8588 da_driver_refnum
= OpenDeskAcc (item_name
);
8590 #endif /* !TARGET_API_MAC_CARBON */
8594 do_menu_choice (SInt32 menu_choice
)
8596 SInt16 menu_id
, menu_item
;
8598 menu_id
= HiWord (menu_choice
);
8599 menu_item
= LoWord (menu_choice
);
8607 do_apple_menu (menu_item
);
8612 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8613 MenuHandle menu
= GetMenuHandle (menu_id
);
8618 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8619 menubar_selection_callback (f
, refcon
);
8628 /* Handle drags in size box. Based on code contributed by Ben
8629 Mesander and IM - Window Manager A. */
8632 do_grow_window (WindowPtr w
, EventRecord
*e
)
8635 int rows
, columns
, width
, height
;
8636 struct frame
*f
= mac_window_to_frame (w
);
8637 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8638 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8639 #if TARGET_API_MAC_CARBON
8645 if (size_hints
->flags
& PMinSize
)
8647 min_width
= size_hints
->min_width
;
8648 min_height
= size_hints
->min_height
;
8650 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8652 #if TARGET_API_MAC_CARBON
8653 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8655 height
= new_rect
.bottom
- new_rect
.top
;
8656 width
= new_rect
.right
- new_rect
.left
;
8658 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8659 /* see if it really changed size */
8662 height
= HiWord (grow_size
);
8663 width
= LoWord (grow_size
);
8666 if (width
!= FRAME_PIXEL_WIDTH (f
)
8667 || height
!= FRAME_PIXEL_HEIGHT (f
))
8669 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8670 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8672 x_set_window_size (f
, 0, columns
, rows
);
8677 /* Handle clicks in zoom box. Calculation of "standard state" based
8678 on code in IM - Window Manager A and code contributed by Ben
8679 Mesander. The standard state of an Emacs window is 80-characters
8680 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8683 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8686 Rect zoom_rect
, port_rect
;
8688 int w_title_height
, columns
, rows
, width
, height
;
8689 struct frame
*f
= mac_window_to_frame (w
);
8690 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8692 #if TARGET_API_MAC_CARBON
8694 Point standard_size
;
8696 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8697 standard_size
.v
= dpyinfo
->height
;
8699 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8700 zoom_in_or_out
= inZoomIn
;
8703 /* Adjust the standard size according to character boundaries. */
8705 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8706 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8707 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8708 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8709 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8710 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8711 && port_rect
.left
== zoom_rect
.left
8712 && port_rect
.top
== zoom_rect
.top
)
8713 zoom_in_or_out
= inZoomIn
;
8715 zoom_in_or_out
= inZoomOut
;
8718 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8720 #else /* not TARGET_API_MAC_CARBON */
8721 GetPort (&save_port
);
8723 SetPortWindowPort (w
);
8725 /* Clear window to avoid flicker. */
8726 EraseRect (&(w
->portRect
));
8727 if (zoom_in_or_out
== inZoomOut
)
8729 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8730 LocalToGlobal (&top_left
);
8732 /* calculate height of window's title bar */
8733 w_title_height
= top_left
.v
- 1
8734 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8736 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8737 zoom_rect
= qd
.screenBits
.bounds
;
8738 zoom_rect
.top
+= w_title_height
;
8739 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8741 zoom_rect
.right
= zoom_rect
.left
8742 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8744 /* Adjust the standard size according to character boundaries. */
8745 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8747 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8749 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8753 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8755 SetPort (save_port
);
8756 #endif /* not TARGET_API_MAC_CARBON */
8758 /* retrieve window size and update application values */
8759 #if TARGET_API_MAC_CARBON
8760 GetWindowPortBounds (w
, &port_rect
);
8762 port_rect
= w
->portRect
;
8764 height
= port_rect
.bottom
- port_rect
.top
;
8765 width
= port_rect
.right
- port_rect
.left
;
8767 if (width
!= FRAME_PIXEL_WIDTH (f
)
8768 || height
!= FRAME_PIXEL_HEIGHT (f
))
8770 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8771 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8773 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8774 SET_FRAME_GARBAGED (f
);
8775 cancel_mouse_face (f
);
8777 FRAME_PIXEL_WIDTH (f
) = width
;
8778 FRAME_PIXEL_HEIGHT (f
) = height
;
8780 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8784 mac_store_apple_event (class, id
, desc
)
8785 Lisp_Object
class, id
;
8789 struct input_event buf
;
8792 desc_copy
= xmalloc (sizeof (AEDesc
));
8793 if (desc_copy
== NULL
)
8796 err
= AEDuplicateDesc (desc
, desc_copy
);
8801 buf
.kind
= MAC_APPLE_EVENT
;
8804 buf
.code
= (int)desc_copy
;
8805 XSETFRAME (buf
.frame_or_window
,
8806 mac_focus_frame (&one_mac_display_info
));
8808 kbd_buffer_store_event (&buf
);
8815 mac_make_lispy_event_code (code
)
8818 AEDesc
*desc
= (AEDesc
*)code
;
8821 obj
= mac_aedesc_to_lisp (desc
);
8822 AEDisposeDesc (desc
);
8828 #if USE_CARBON_EVENTS
8829 static pascal OSStatus
8830 mac_handle_command_event (next_handler
, event
, data
)
8831 EventHandlerCallRef next_handler
;
8838 Lisp_Object class_key
, id_key
, binding
;
8840 result
= CallNextEventHandler (next_handler
, event
);
8841 if (result
!= eventNotHandledErr
)
8844 GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8845 sizeof (HICommand
), NULL
, &command
);
8847 if (command
.commandID
== 0)
8848 return eventNotHandledErr
;
8850 /* A HICommand event is mapped to an Apple event whose event class
8851 symbol is `hicommand' and event ID is its command ID. */
8852 class_key
= Qhicommand
;
8853 mac_find_apple_event_spec (0, command
.commandID
,
8854 &class_key
, &id_key
, &binding
);
8855 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
8856 if (INTEGERP (binding
))
8857 return XINT (binding
);
8860 AppleEvent apple_event
;
8862 static EventParamName names
[] = {kEventParamDirectObject
,
8863 kEventParamKeyModifiers
};
8864 static EventParamType types
[] = {typeHICommand
,
8866 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
8870 err
= mac_store_apple_event (class_key
, id_key
, &apple_event
);
8871 AEDisposeDesc (&apple_event
);
8877 return eventNotHandledErr
;
8881 init_command_handler ()
8884 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8885 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8887 if (handle_command_eventUPP
== NULL
)
8888 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8889 return InstallApplicationEventHandler (handle_command_eventUPP
,
8890 GetEventTypeCount (specs
), specs
,
8894 static pascal OSStatus
8895 mac_handle_window_event (next_handler
, event
, data
)
8896 EventHandlerCallRef next_handler
;
8903 XSizeHints
*size_hints
;
8905 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8906 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8908 switch (GetEventKind (event
))
8910 case kEventWindowUpdate
:
8911 result
= CallNextEventHandler (next_handler
, event
);
8912 if (result
!= eventNotHandledErr
)
8915 do_window_update (wp
);
8918 case kEventWindowBoundsChanging
:
8919 result
= CallNextEventHandler (next_handler
, event
);
8920 if (result
!= eventNotHandledErr
)
8923 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8924 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8925 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8926 if ((attributes
& kWindowBoundsChangeUserResize
)
8927 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8928 == (PResizeInc
| PBaseSize
| PMinSize
)))
8933 GetEventParameter (event
, kEventParamCurrentBounds
,
8935 NULL
, sizeof (Rect
), NULL
, &bounds
);
8936 width
= bounds
.right
- bounds
.left
;
8937 height
= bounds
.bottom
- bounds
.top
;
8939 if (width
< size_hints
->min_width
)
8940 width
= size_hints
->min_width
;
8942 width
= size_hints
->base_width
8943 + (int) ((width
- size_hints
->base_width
)
8944 / (float) size_hints
->width_inc
+ .5)
8945 * size_hints
->width_inc
;
8947 if (height
< size_hints
->min_height
)
8948 height
= size_hints
->min_height
;
8950 height
= size_hints
->base_height
8951 + (int) ((height
- size_hints
->base_height
)
8952 / (float) size_hints
->height_inc
+ .5)
8953 * size_hints
->height_inc
;
8955 bounds
.right
= bounds
.left
+ width
;
8956 bounds
.bottom
= bounds
.top
+ height
;
8957 SetEventParameter (event
, kEventParamCurrentBounds
,
8958 typeQDRectangle
, sizeof (Rect
), &bounds
);
8963 case kEventWindowShown
:
8964 case kEventWindowHidden
:
8965 case kEventWindowExpanded
:
8966 case kEventWindowCollapsed
:
8967 result
= CallNextEventHandler (next_handler
, event
);
8969 mac_handle_visibility_change (mac_window_to_frame (wp
));
8975 return eventNotHandledErr
;
8978 static pascal OSStatus
8979 mac_handle_mouse_event (next_handler
, event
, data
)
8980 EventHandlerCallRef next_handler
;
8986 switch (GetEventKind (event
))
8988 case kEventMouseWheelMoved
:
8992 EventMouseWheelAxis axis
;
8996 result
= CallNextEventHandler (next_handler
, event
);
8997 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9000 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9001 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9002 f
= mac_window_to_frame (wp
);
9003 if (f
!= mac_focus_frame (&one_mac_display_info
))
9006 GetEventParameter (event
, kEventParamMouseWheelAxis
,
9007 typeMouseWheelAxis
, NULL
,
9008 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9009 if (axis
!= kEventMouseWheelAxisY
)
9012 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
9013 NULL
, sizeof (SInt32
), NULL
, &delta
);
9014 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
9015 NULL
, sizeof (Point
), NULL
, &point
);
9016 read_socket_inev
->kind
= WHEEL_EVENT
;
9017 read_socket_inev
->code
= 0;
9018 read_socket_inev
->modifiers
=
9019 (mac_event_to_emacs_modifiers (event
)
9020 | ((delta
< 0) ? down_modifier
: up_modifier
));
9021 SetPortWindowPort (wp
);
9022 GlobalToLocal (&point
);
9023 XSETINT (read_socket_inev
->x
, point
.h
);
9024 XSETINT (read_socket_inev
->y
, point
.v
);
9025 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9035 return eventNotHandledErr
;
9040 mac_store_services_event (event
)
9044 AppleEvent apple_event
;
9047 switch (GetEventKind (event
))
9049 case kEventServicePaste
:
9051 err
= create_apple_event_from_event_ref (event
, 0, NULL
, NULL
,
9055 case kEventServicePerform
:
9057 static EventParamName names
[] = {kEventParamServiceMessageName
,
9058 kEventParamServiceUserData
};
9059 static EventParamType types
[] = {typeCFStringRef
,
9063 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
9074 err
= mac_store_apple_event (Qservices
, id_key
, &apple_event
);
9075 AEDisposeDesc (&apple_event
);
9080 #endif /* MAC_OSX */
9081 #endif /* USE_CARBON_EVENTS */
9085 install_window_handler (window
)
9089 #if USE_CARBON_EVENTS
9090 EventTypeSpec specs_window
[] =
9091 {{kEventClassWindow
, kEventWindowUpdate
},
9092 {kEventClassWindow
, kEventWindowBoundsChanging
},
9093 {kEventClassWindow
, kEventWindowShown
},
9094 {kEventClassWindow
, kEventWindowHidden
},
9095 {kEventClassWindow
, kEventWindowExpanded
},
9096 {kEventClassWindow
, kEventWindowCollapsed
}};
9097 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9098 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9099 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9101 if (handle_window_eventUPP
== NULL
)
9102 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9103 if (handle_mouse_eventUPP
== NULL
)
9104 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9105 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9106 GetEventTypeCount (specs_window
),
9107 specs_window
, NULL
, NULL
);
9109 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9110 GetEventTypeCount (specs_mouse
),
9111 specs_mouse
, NULL
, NULL
);
9113 #if TARGET_API_MAC_CARBON
9114 if (mac_do_track_dragUPP
== NULL
)
9115 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
9116 if (mac_do_receive_dragUPP
== NULL
)
9117 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
9120 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
9122 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
9128 remove_window_handler (window
)
9131 #if TARGET_API_MAC_CARBON
9132 if (mac_do_track_dragUPP
)
9133 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
9134 if (mac_do_receive_dragUPP
)
9135 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
9139 #if TARGET_API_MAC_CARBON
9141 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
9142 void *handlerRefCon
, DragReference theDrag
)
9144 static int can_accept
;
9147 ItemReference theItem
;
9148 FlavorFlags theFlags
;
9151 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9152 return dragNotAcceptedErr
;
9156 case kDragTrackingEnterHandler
:
9157 CountDragItems (theDrag
, &items
);
9159 for (index
= 1; index
<= items
; index
++)
9161 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9162 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9163 if (result
== noErr
)
9171 case kDragTrackingEnterWindow
:
9174 RgnHandle hilite_rgn
= NewRgn ();
9176 struct frame
*f
= mac_window_to_frame (window
);
9178 GetWindowPortBounds (window
, &r
);
9179 OffsetRect (&r
, -r
.left
, -r
.top
);
9180 RectRgn (hilite_rgn
, &r
);
9181 ShowDragHilite (theDrag
, hilite_rgn
, true);
9182 DisposeRgn (hilite_rgn
);
9183 SetThemeCursor (kThemeCopyArrowCursor
);
9187 case kDragTrackingInWindow
:
9190 case kDragTrackingLeaveWindow
:
9193 struct frame
*f
= mac_window_to_frame (window
);
9195 HideDragHilite (theDrag
);
9196 SetThemeCursor (kThemeArrowCursor
);
9200 case kDragTrackingLeaveHandler
:
9208 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9209 DragReference theDrag
)
9213 FlavorFlags theFlags
;
9216 ItemReference theItem
;
9218 Size size
= sizeof (HFSFlavor
);
9219 Lisp_Object file_list
;
9221 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9222 return dragNotAcceptedErr
;
9225 GetDragMouse (theDrag
, &mouse
, 0L);
9226 CountDragItems (theDrag
, &items
);
9227 for (index
= 1; index
<= items
; index
++)
9229 /* Only handle file references. */
9230 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9231 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9232 if (result
== noErr
)
9237 err
= GetFlavorData (theDrag
, theItem
, flavorTypeHFS
,
9240 err
= AECoercePtr (typeFSS
, &data
.fileSpec
, sizeof (FSSpec
),
9241 TYPE_FILE_NAME
, &desc
);
9246 /* x-dnd functions expect undecoded filenames. */
9247 file
= make_uninit_string (AEGetDescDataSize (&desc
));
9248 err
= AEGetDescData (&desc
, SDATA (file
), SBYTES (file
));
9250 file_list
= Fcons (file
, file_list
);
9251 AEDisposeDesc (&desc
);
9255 /* If there are items in the list, construct an event and post it to
9256 the queue like an interrupt using kbd_buffer_store_event. */
9257 if (!NILP (file_list
))
9259 struct input_event event
;
9261 struct frame
*f
= mac_window_to_frame (window
);
9264 GlobalToLocal (&mouse
);
9265 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
9267 event
.kind
= DRAG_N_DROP_EVENT
;
9269 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9270 event
.timestamp
= TickCount () * (1000 / 60);
9271 XSETINT (event
.x
, mouse
.h
);
9272 XSETINT (event
.y
, mouse
.v
);
9273 XSETFRAME (frame
, f
);
9274 event
.frame_or_window
= frame
;
9275 event
.arg
= file_list
;
9276 /* Post to the interrupt queue */
9277 kbd_buffer_store_event (&event
);
9278 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9280 ProcessSerialNumber psn
;
9281 GetCurrentProcess (&psn
);
9282 SetFrontProcess (&psn
);
9288 return dragNotAcceptedErr
;
9295 profiler_exit_proc ()
9297 ProfilerDump ("\pEmacs.prof");
9302 /* These few functions implement Emacs as a normal Mac application
9303 (almost): set up the heap and the Toolbox, handle necessary system
9304 events plus a few simple menu events. They also set up Emacs's
9305 access to functions defined in the rest of this file. Emacs uses
9306 function hooks to perform all its terminal I/O. A complete list of
9307 these functions appear in termhooks.h. For what they do, read the
9308 comments there and see also w32term.c and xterm.c. What's
9309 noticeably missing here is the event loop, which is normally
9310 present in most Mac application. After performing the necessary
9311 Mac initializations, main passes off control to emacs_main
9312 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9313 (defined further below) to read input. This is where
9314 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9321 #if __profile__ /* is the profiler on? */
9322 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9327 /* set creator and type for files created by MSL */
9332 do_init_managers ();
9337 do_check_ram_size ();
9340 init_emacs_passwd_dir ();
9344 init_coercion_handler ();
9346 initialize_applescript ();
9348 init_apple_event_handler ();
9354 /* set up argv array from STR# resource */
9355 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9359 /* free up AppleScript resources on exit */
9360 atexit (terminate_applescript
);
9362 #if __profile__ /* is the profiler on? */
9363 atexit (profiler_exit_proc
);
9366 /* 3rd param "envp" never used in emacs_main */
9367 (void) emacs_main (argc
, argv
, 0);
9370 /* Never reached - real exit in Fkill_emacs */
9375 /* Table for translating Mac keycode to X keysym values. Contributed
9377 Mapping for special keys is now identical to that in Apple X11
9378 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9379 on the right of the Cmd key on laptops, and fn + `enter' (->
9381 static unsigned char keycode_to_xkeysym_table
[] = {
9382 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9383 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9384 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9386 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9387 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9388 /*0x38*/ 0, 0, 0, 0,
9389 /*0x3C*/ 0, 0, 0, 0,
9391 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9392 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9393 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9394 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9396 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9397 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9398 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9399 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9401 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9402 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9403 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9404 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9406 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9407 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9408 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9409 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9414 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9416 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9417 return *xKeySym
!= 0;
9420 static unsigned char fn_keycode_to_xkeysym_table
[] = {
9421 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9422 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9423 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9425 /*0x30*/ 0, 0, 0, 0,
9426 /*0x34*/ 0, 0, 0, 0,
9427 /*0x38*/ 0, 0, 0, 0,
9428 /*0x3C*/ 0, 0, 0, 0,
9430 /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
9431 /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
9432 /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
9433 /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
9435 /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
9436 /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
9437 /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
9438 /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
9440 /*0x60*/ 0, 0, 0, 0,
9441 /*0x64*/ 0, 0, 0, 0,
9442 /*0x68*/ 0, 0, 0, 0,
9443 /*0x6C*/ 0, 0, 0, 0,
9445 /*0x70*/ 0, 0, 0, 0,
9446 /*0x74*/ 0, 0, 0, 0,
9447 /*0x78*/ 0, 0, 0, 0,
9451 convert_fn_keycode (EventRef eventRef
, int keyCode
, int *newCode
)
9454 /* Use the special map to translate keys when function modifier is
9455 to be caught. KeyTranslate can't be used in that case.
9456 We can't detect the function key using the input_event.modifiers,
9457 because this uses the high word of an UInt32. Therefore,
9458 we'll just read it out of the original eventRef.
9462 /* TODO / known issues
9464 - Fn-Shift-j is regonized as Fn-j and not Fn-J.
9465 The above table always translates to lower characters. We need to use
9466 the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
9468 - The table is meant for English language keyboards, and it will work
9469 for many others with the exception of key combinations like Fn-ö on
9470 a German keyboard, which is currently mapped to Fn-;.
9471 How to solve this without keeping separate tables for all keyboards
9472 around? KeyTranslate isn't of much help here, as it only takes a 16-bit
9473 value for keycode with the modifiers in he high byte, i.e. no room for the
9474 Fn modifier. That's why we need the table.
9479 if (!NILP(Vmac_function_modifier
))
9481 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9482 sizeof (UInt32
), NULL
, &mods
);
9483 if (mods
& kEventKeyModifierFnMask
)
9484 { *newCode
= fn_keycode_to_xkeysym_table
[keyCode
& 0x7f];
9486 return (*newCode
!= 0);
9494 backtranslate_modified_keycode(int mods
, int keycode
, int def
)
9496 EventModifiers mapped_modifiers
=
9497 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9498 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9499 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9501 if (mods
& mapped_modifiers
)
9503 /* This code comes from Keyboard Resource,
9504 Appendix C of IM - Text. This is necessary
9505 since shift is ignored in KCHR table
9506 translation when option or command is pressed.
9507 It also does not translate correctly
9508 control-shift chars like C-% so mask off shift
9511 Not done for combinations with the option key (alt)
9512 unless it is to be caught by Emacs: this is
9513 to preserve key combinations translated by the OS
9516 /* Mask off modifier keys that are mapped to some Emacs
9518 int new_modifiers
= mods
& ~mapped_modifiers
;
9519 /* set high byte of keycode to modifier high byte*/
9520 int new_keycode
= keycode
| new_modifiers
;
9521 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9522 unsigned long some_state
= 0;
9523 return (int) KeyTranslate (kchr_ptr
, new_keycode
,
9524 &some_state
) & 0xff;
9525 /* TO DO: Recognize two separate resulting characters, "for
9526 example, when the user presses Option-E followed by N, you
9527 can map this through the KeyTranslate function using the
9528 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
9529 returns as two characters in the bytes labeled Character code
9530 1 and Character code 2." (from Carbon API doc) */
9538 #if !USE_CARBON_EVENTS
9539 static RgnHandle mouse_region
= NULL
;
9542 mac_wait_next_event (er
, sleep_time
, dequeue
)
9547 static EventRecord er_buf
= {nullEvent
};
9548 UInt32 target_tick
, current_tick
;
9549 EventMask event_mask
;
9551 if (mouse_region
== NULL
)
9552 mouse_region
= NewRgn ();
9554 event_mask
= everyEvent
;
9555 if (!mac_ready_for_apple_events
)
9556 event_mask
-= highLevelEventMask
;
9558 current_tick
= TickCount ();
9559 target_tick
= current_tick
+ sleep_time
;
9561 if (er_buf
.what
== nullEvent
)
9562 while (!WaitNextEvent (event_mask
, &er_buf
,
9563 target_tick
- current_tick
, mouse_region
))
9565 current_tick
= TickCount ();
9566 if (target_tick
<= current_tick
)
9572 er_buf
.what
= nullEvent
;
9575 #endif /* not USE_CARBON_EVENTS */
9577 /* Emacs calls this whenever it wants to read an input event from the
9580 XTread_socket (sd
, expected
, hold_quit
)
9582 struct input_event
*hold_quit
;
9584 struct input_event inev
;
9586 #if USE_CARBON_EVENTS
9588 EventTargetRef toolbox_dispatcher
;
9591 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9593 if (interrupt_input_blocked
)
9595 interrupt_input_pending
= 1;
9599 interrupt_input_pending
= 0;
9602 /* So people can tell when we have read the available input. */
9603 input_signal_count
++;
9605 #if USE_CARBON_EVENTS
9606 toolbox_dispatcher
= GetEventDispatcherTarget ();
9608 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9609 kEventRemoveFromQueue
, &eventRef
))
9610 #else /* !USE_CARBON_EVENTS */
9611 while (mac_wait_next_event (&er
, 0, true))
9612 #endif /* !USE_CARBON_EVENTS */
9616 unsigned long timestamp
;
9618 /* It is necessary to set this (additional) argument slot of an
9619 event to nil because keyboard.c protects incompletely
9620 processed event from being garbage collected by placing them
9621 in the kbd_buffer_gcpro vector. */
9623 inev
.kind
= NO_EVENT
;
9626 #if USE_CARBON_EVENTS
9627 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9629 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9632 #if USE_CARBON_EVENTS
9633 /* Handle new events */
9634 if (!mac_convert_event_ref (eventRef
, &er
))
9636 /* There used to be a handler for the kEventMouseWheelMoved
9637 event here. But as of Mac OS X 10.4, this kind of event
9638 is not directly posted to the main event queue by
9639 two-finger scrolling on the trackpad. Instead, some
9640 private event is posted and it is converted to a wheel
9641 event by the default handler for the application target.
9642 The converted one can be received by a Carbon event
9643 handler installed on a window target. */
9644 read_socket_inev
= &inev
;
9645 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9646 read_socket_inev
= NULL
;
9649 #endif /* USE_CARBON_EVENTS */
9655 WindowPtr window_ptr
;
9656 ControlPartCode part_code
;
9659 #if USE_CARBON_EVENTS
9660 /* This is needed to send mouse events like aqua window
9661 buttons to the correct handler. */
9662 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9663 != eventNotHandledErr
)
9666 last_mouse_glyph_frame
= 0;
9668 if (dpyinfo
->grabbed
&& last_mouse_frame
9669 && FRAME_LIVE_P (last_mouse_frame
))
9671 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9672 part_code
= inContent
;
9676 part_code
= FindWindow (er
.where
, &window_ptr
);
9677 if (tip_window
&& window_ptr
== tip_window
)
9679 HideWindow (tip_window
);
9680 part_code
= FindWindow (er
.where
, &window_ptr
);
9684 if (er
.what
!= mouseDown
&&
9685 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
9691 f
= mac_focus_frame (dpyinfo
);
9692 saved_menu_event_location
= er
.where
;
9693 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9694 XSETFRAME (inev
.frame_or_window
, f
);
9698 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9699 SelectWindow (window_ptr
);
9702 ControlPartCode control_part_code
;
9704 Point mouse_loc
= er
.where
;
9706 ControlKind control_kind
;
9709 f
= mac_window_to_frame (window_ptr
);
9710 /* convert to local coordinates of new window */
9711 SetPortWindowPort (window_ptr
);
9713 GlobalToLocal (&mouse_loc
);
9714 #if TARGET_API_MAC_CARBON
9715 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9716 &control_part_code
);
9719 GetControlKind (ch
, &control_kind
);
9722 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9726 #if USE_CARBON_EVENTS
9727 inev
.code
= mac_get_mouse_btn (eventRef
);
9728 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9730 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9731 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9733 XSETINT (inev
.x
, mouse_loc
.h
);
9734 XSETINT (inev
.y
, mouse_loc
.v
);
9736 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9738 #ifndef USE_TOOLKIT_SCROLL_BARS
9739 /* control_part_code becomes kControlNoPart if
9740 a progress indicator is clicked. */
9741 && control_part_code
!= kControlNoPart
9742 #else /* USE_TOOLKIT_SCROLL_BARS */
9744 && control_kind
.kind
== kControlKindScrollBar
9745 #endif /* MAC_OSX */
9746 #endif /* USE_TOOLKIT_SCROLL_BARS */
9749 struct scroll_bar
*bar
;
9751 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9753 bar
= tracked_scroll_bar
;
9754 #ifndef USE_TOOLKIT_SCROLL_BARS
9755 control_part_code
= kControlIndicatorPart
;
9759 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9760 #ifdef USE_TOOLKIT_SCROLL_BARS
9761 /* Make the "Ctrl-Mouse-2 splits window" work
9762 for toolkit scroll bars. */
9763 if (er
.modifiers
& controlKey
)
9764 x_scroll_bar_handle_click (bar
, control_part_code
,
9766 else if (er
.what
== mouseDown
)
9767 x_scroll_bar_handle_press (bar
, control_part_code
,
9770 x_scroll_bar_handle_release (bar
, &inev
);
9771 #else /* not USE_TOOLKIT_SCROLL_BARS */
9772 x_scroll_bar_handle_click (bar
, control_part_code
,
9774 if (er
.what
== mouseDown
9775 && control_part_code
== kControlIndicatorPart
)
9776 tracked_scroll_bar
= bar
;
9778 tracked_scroll_bar
= NULL
;
9779 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9784 int x
= mouse_loc
.h
;
9785 int y
= mouse_loc
.v
;
9787 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9788 if (EQ (window
, f
->tool_bar_window
))
9790 if (er
.what
== mouseDown
)
9791 handle_tool_bar_click (f
, x
, y
, 1, 0);
9793 handle_tool_bar_click (f
, x
, y
, 0,
9799 XSETFRAME (inev
.frame_or_window
, f
);
9800 inev
.kind
= MOUSE_CLICK_EVENT
;
9804 if (er
.what
== mouseDown
)
9806 dpyinfo
->grabbed
|= (1 << inev
.code
);
9807 last_mouse_frame
= f
;
9810 last_tool_bar_item
= -1;
9814 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9815 /* If a button is released though it was not
9816 previously pressed, that would be because
9817 of multi-button emulation. */
9818 dpyinfo
->grabbed
= 0;
9820 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9823 /* Ignore any mouse motion that happened before
9824 this event; any subsequent mouse-movement Emacs
9825 events should reflect only motion after the
9830 #ifdef USE_TOOLKIT_SCROLL_BARS
9831 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9836 inev
.modifiers
|= down_modifier
;
9839 inev
.modifiers
|= up_modifier
;
9846 #if TARGET_API_MAC_CARBON
9847 DragWindow (window_ptr
, er
.where
, NULL
);
9848 #else /* not TARGET_API_MAC_CARBON */
9849 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9850 #endif /* not TARGET_API_MAC_CARBON */
9851 /* Update the frame parameters. */
9853 struct frame
*f
= mac_window_to_frame (window_ptr
);
9855 if (f
&& !f
->async_iconified
)
9856 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9861 if (TrackGoAway (window_ptr
, er
.where
))
9863 inev
.kind
= DELETE_WINDOW_EVENT
;
9864 XSETFRAME (inev
.frame_or_window
,
9865 mac_window_to_frame (window_ptr
));
9869 /* window resize handling added --ben */
9871 do_grow_window (window_ptr
, &er
);
9874 /* window zoom handling added --ben */
9877 if (TrackBox (window_ptr
, er
.where
, part_code
))
9878 do_zoom_window (window_ptr
, part_code
);
9888 #if USE_CARBON_EVENTS
9889 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9890 != eventNotHandledErr
)
9893 do_window_update ((WindowPtr
) er
.message
);
9898 #if USE_CARBON_EVENTS
9899 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9900 != eventNotHandledErr
)
9903 switch ((er
.message
>> 24) & 0x000000FF)
9905 case suspendResumeMessage
:
9906 if ((er
.message
& resumeFlag
) == 1)
9912 case mouseMovedMessage
:
9913 #if !USE_CARBON_EVENTS
9914 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9915 er
.where
.h
+ 1, er
.where
.v
+ 1);
9917 previous_help_echo_string
= help_echo_string
;
9918 help_echo_string
= Qnil
;
9920 if (dpyinfo
->grabbed
&& last_mouse_frame
9921 && FRAME_LIVE_P (last_mouse_frame
))
9922 f
= last_mouse_frame
;
9924 f
= dpyinfo
->x_focus_frame
;
9926 if (dpyinfo
->mouse_face_hidden
)
9928 dpyinfo
->mouse_face_hidden
= 0;
9929 clear_mouse_face (dpyinfo
);
9934 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9935 Point mouse_pos
= er
.where
;
9937 SetPortWindowPort (wp
);
9939 GlobalToLocal (&mouse_pos
);
9941 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9942 #ifdef USE_TOOLKIT_SCROLL_BARS
9943 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9945 #else /* not USE_TOOLKIT_SCROLL_BARS */
9946 x_scroll_bar_note_movement (tracked_scroll_bar
,
9948 - XINT (tracked_scroll_bar
->top
),
9949 er
.when
* (1000 / 60));
9950 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9953 /* Generate SELECT_WINDOW_EVENTs when needed. */
9954 if (mouse_autoselect_window
)
9958 window
= window_from_coordinates (f
,
9963 /* Window will be selected only when it is
9964 not selected now and last mouse movement
9965 event was not in it. Minibuffer window
9966 will be selected iff it is active. */
9967 if (WINDOWP (window
)
9968 && !EQ (window
, last_window
)
9969 && !EQ (window
, selected_window
))
9971 inev
.kind
= SELECT_WINDOW_EVENT
;
9972 inev
.frame_or_window
= window
;
9977 if (!note_mouse_movement (f
, &mouse_pos
))
9978 help_echo_string
= previous_help_echo_string
;
9982 /* If the contents of the global variable
9983 help_echo_string has changed, generate a
9985 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
9993 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
9995 #if USE_CARBON_EVENTS
9996 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9997 != eventNotHandledErr
)
10000 if (window_ptr
== tip_window
)
10002 HideWindow (tip_window
);
10006 if (!is_emacs_window (window_ptr
))
10009 if ((er
.modifiers
& activeFlag
) != 0)
10011 /* A window has been activated */
10012 Point mouse_loc
= er
.where
;
10014 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10016 SetPortWindowPort (window_ptr
);
10017 GlobalToLocal (&mouse_loc
);
10018 /* Window-activated event counts as mouse movement,
10019 so update things that depend on mouse position. */
10020 note_mouse_movement (mac_window_to_frame (window_ptr
),
10025 /* A window has been deactivated */
10026 #if USE_TOOLKIT_SCROLL_BARS
10027 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10029 struct input_event event
;
10031 EVENT_INIT (event
);
10032 event
.kind
= NO_EVENT
;
10033 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10034 if (event
.kind
!= NO_EVENT
)
10036 event
.timestamp
= timestamp
;
10037 kbd_buffer_store_event_hold (&event
, hold_quit
);
10042 dpyinfo
->grabbed
= 0;
10044 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10046 f
= mac_window_to_frame (window_ptr
);
10047 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10049 /* If we move outside the frame, then we're
10050 certainly no longer on any text in the
10052 clear_mouse_face (dpyinfo
);
10053 dpyinfo
->mouse_face_mouse_frame
= 0;
10056 /* Generate a nil HELP_EVENT to cancel a help-echo.
10057 Do it only if there's something to cancel.
10058 Otherwise, the startup message is cleared when the
10059 mouse leaves the frame. */
10060 if (any_help_event_p
)
10069 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10072 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10073 /* When using Carbon Events, we need to pass raw keyboard
10074 events to the TSM ourselves. If TSM handles it, it
10075 will pass back noErr, otherwise it will pass back
10076 "eventNotHandledErr" and we can process it
10078 if ((mac_pass_command_to_system
10079 || !(er
.modifiers
& cmdKey
))
10080 && (mac_pass_control_to_system
10081 || !(er
.modifiers
& controlKey
))
10082 && (NILP (Vmac_option_modifier
)
10083 || !(er
.modifiers
& optionKey
)))
10084 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10085 != eventNotHandledErr
)
10090 if (dpyinfo
->x_focus_frame
== NULL
)
10092 /* Beep if keyboard input occurs when all the frames
10100 static SInt16 last_key_script
= -1;
10101 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10103 if (last_key_script
!= current_key_script
)
10105 struct input_event event
;
10107 EVENT_INIT (event
);
10108 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10110 event
.code
= current_key_script
;
10111 event
.timestamp
= timestamp
;
10112 kbd_buffer_store_event (&event
);
10115 last_key_script
= current_key_script
;
10120 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10122 clear_mouse_face (dpyinfo
);
10123 dpyinfo
->mouse_face_hidden
= 1;
10126 /* translate the keycode back to determine the original key */
10127 /* Convert key code if function key is pressed.
10128 Otherwise, if non-ASCII-event, take care of that
10129 without re-translating the key code. */
10130 #if USE_CARBON_EVENTS
10131 if (convert_fn_keycode (eventRef
, keycode
, &xkeysym
))
10133 inev
.code
= xkeysym
;
10134 /* this doesn't work - tried to add shift modifiers */
10136 backtranslate_modified_keycode(er
.modifiers
& (~0x2200),
10137 xkeysym
| 0x80, xkeysym
);
10138 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10142 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10144 inev
.code
= 0xff00 | xkeysym
;
10145 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10150 backtranslate_modified_keycode(er
.modifiers
, keycode
,
10151 er
.message
& charCodeMask
);
10152 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10156 #if USE_CARBON_EVENTS
10157 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10159 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10161 inev
.modifiers
|= (extra_keyboard_modifiers
10162 & (meta_modifier
| alt_modifier
10163 | hyper_modifier
| super_modifier
));
10164 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
10167 case kHighLevelEvent
:
10168 read_socket_inev
= &inev
;
10169 AEProcessAppleEvent (&er
);
10170 read_socket_inev
= NULL
;
10176 #if USE_CARBON_EVENTS
10177 ReleaseEvent (eventRef
);
10180 if (inev
.kind
!= NO_EVENT
)
10182 inev
.timestamp
= timestamp
;
10183 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10188 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10193 XSETFRAME (frame
, f
);
10199 any_help_event_p
= 1;
10200 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10201 help_echo_object
, help_echo_pos
);
10205 help_echo_string
= Qnil
;
10206 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10213 /* If the focus was just given to an autoraising frame,
10215 /* ??? This ought to be able to handle more than one such frame. */
10216 if (pending_autoraise_frame
)
10218 x_raise_frame (pending_autoraise_frame
);
10219 pending_autoraise_frame
= 0;
10222 #if !USE_CARBON_EVENTS
10223 /* Check which frames are still visible. We do this here because
10224 there doesn't seem to be any direct notification from the Window
10225 Manager that the visibility of a window has changed (at least,
10226 not in all cases). */
10228 Lisp_Object tail
, frame
;
10230 FOR_EACH_FRAME (tail
, frame
)
10232 struct frame
*f
= XFRAME (frame
);
10234 /* The tooltip has been drawn already. Avoid the
10235 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10236 if (EQ (frame
, tip_frame
))
10239 if (FRAME_MAC_P (f
))
10240 mac_handle_visibility_change (f
);
10250 /* Need to override CodeWarrior's input function so no conversion is
10251 done on newlines Otherwise compiled functions in .elc files will be
10252 read incorrectly. Defined in ...:MSL C:MSL
10253 Common:Source:buffer_io.c. */
10256 __convert_to_newlines (unsigned char * p
, size_t * n
)
10258 #pragma unused(p,n)
10262 __convert_from_newlines (unsigned char * p
, size_t * n
)
10264 #pragma unused(p,n)
10270 make_mac_terminal_frame (struct frame
*f
)
10275 XSETFRAME (frame
, f
);
10277 f
->output_method
= output_mac
;
10278 f
->output_data
.mac
= (struct mac_output
*)
10279 xmalloc (sizeof (struct mac_output
));
10280 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10282 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10284 FRAME_COLS (f
) = 96;
10285 FRAME_LINES (f
) = 4;
10287 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10288 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10290 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10292 f
->output_data
.mac
->cursor_pixel
= 0;
10293 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10294 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10295 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10297 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10298 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10299 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10300 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10301 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10302 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10304 FRAME_FONTSET (f
) = -1;
10305 f
->output_data
.mac
->explicit_parent
= 0;
10308 f
->border_width
= 0;
10310 f
->internal_border_width
= 0;
10315 f
->new_text_cols
= 0;
10316 f
->new_text_lines
= 0;
10318 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10319 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10320 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10324 if (!(FRAME_MAC_WINDOW (f
) =
10325 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10326 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10328 /* so that update events can find this mac_output struct */
10329 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10335 /* Need to be initialized for unshow_buffer in window.c. */
10336 selected_window
= f
->selected_window
;
10338 Fmodify_frame_parameters (frame
,
10339 Fcons (Fcons (Qfont
,
10340 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10341 Fmodify_frame_parameters (frame
,
10342 Fcons (Fcons (Qforeground_color
,
10343 build_string ("black")), Qnil
));
10344 Fmodify_frame_parameters (frame
,
10345 Fcons (Fcons (Qbackground_color
,
10346 build_string ("white")), Qnil
));
10351 /***********************************************************************
10353 ***********************************************************************/
10355 int mac_initialized
= 0;
10358 mac_initialize_display_info ()
10360 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10361 GDHandle main_device_handle
;
10363 bzero (dpyinfo
, sizeof (*dpyinfo
));
10366 dpyinfo
->mac_id_name
10367 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10368 + SCHARS (Vsystem_name
)
10370 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10371 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10373 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10374 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10377 main_device_handle
= LMGetMainDevice();
10379 dpyinfo
->reference_count
= 0;
10380 dpyinfo
->resx
= 72.0;
10381 dpyinfo
->resy
= 72.0;
10382 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10384 /* HasDepth returns true if it is possible to have a 32 bit display,
10385 but this may not be what is actually used. Mac OSX can do better.
10386 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10387 header for CGGetActiveDisplayList says that the first display returned
10388 is the active one, so we use that. */
10390 CGDirectDisplayID disp_id
[1];
10391 CGDisplayCount disp_count
;
10392 CGDisplayErr error_code
;
10394 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10395 if (error_code
!= 0)
10396 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10398 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10401 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10402 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10403 gdDevType
, dpyinfo
->color_p
))
10406 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10407 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10408 dpyinfo
->grabbed
= 0;
10409 dpyinfo
->root_window
= NULL
;
10410 dpyinfo
->image_cache
= make_image_cache ();
10412 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10413 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10414 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10415 dpyinfo
->mouse_face_window
= Qnil
;
10416 dpyinfo
->mouse_face_overlay
= Qnil
;
10417 dpyinfo
->mouse_face_hidden
= 0;
10422 mac_make_rdb (xrm_option
)
10425 XrmDatabase database
;
10427 database
= xrm_get_preference_database (NULL
);
10429 xrm_merge_string_database (database
, xrm_option
);
10434 struct mac_display_info
*
10435 mac_term_init (display_name
, xrm_option
, resource_name
)
10436 Lisp_Object display_name
;
10438 char *resource_name
;
10440 struct mac_display_info
*dpyinfo
;
10444 if (!mac_initialized
)
10447 mac_initialized
= 1;
10450 if (x_display_list
)
10451 error ("Sorry, this version can only handle one display");
10453 mac_initialize_display_info ();
10455 dpyinfo
= &one_mac_display_info
;
10457 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10459 /* Put this display on the chain. */
10460 dpyinfo
->next
= x_display_list
;
10461 x_display_list
= dpyinfo
;
10463 /* Put it on x_display_name_list. */
10464 x_display_name_list
= Fcons (Fcons (display_name
,
10465 Fcons (Qnil
, dpyinfo
->xrdb
)),
10466 x_display_name_list
);
10467 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10473 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10476 x_delete_display (dpyinfo
)
10477 struct mac_display_info
*dpyinfo
;
10481 /* Discard this display from x_display_name_list and x_display_list.
10482 We can't use Fdelq because that can quit. */
10483 if (! NILP (x_display_name_list
)
10484 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10485 x_display_name_list
= XCDR (x_display_name_list
);
10490 tail
= x_display_name_list
;
10491 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10493 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10495 XSETCDR (tail
, XCDR (XCDR (tail
)));
10498 tail
= XCDR (tail
);
10502 if (x_display_list
== dpyinfo
)
10503 x_display_list
= dpyinfo
->next
;
10506 struct x_display_info
*tail
;
10508 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10509 if (tail
->next
== dpyinfo
)
10510 tail
->next
= tail
->next
->next
;
10513 /* Free the font names in the font table. */
10514 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10515 if (dpyinfo
->font_table
[i
].name
)
10517 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10518 xfree (dpyinfo
->font_table
[i
].full_name
);
10519 xfree (dpyinfo
->font_table
[i
].name
);
10522 if (dpyinfo
->font_table
->font_encoder
)
10523 xfree (dpyinfo
->font_table
->font_encoder
);
10525 xfree (dpyinfo
->font_table
);
10526 xfree (dpyinfo
->mac_id_name
);
10528 if (x_display_list
== 0)
10530 mac_clear_font_name_table ();
10531 bzero (dpyinfo
, sizeof (*dpyinfo
));
10540 extern int inhibit_window_system
;
10541 extern int noninteractive
;
10542 CFBundleRef appsBundle
;
10545 /* No need to test if already -nw*/
10546 if (inhibit_window_system
|| noninteractive
)
10549 appsBundle
= CFBundleGetMainBundle();
10550 if (appsBundle
!= NULL
)
10552 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10553 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10554 /* We found the bundle identifier, now we know we are valid. */
10561 /* MAC_TODO: Have this start the bundled executable */
10563 /* For now, prevent the fatal error by bringing it up in the terminal */
10564 inhibit_window_system
= 1;
10568 MakeMeTheFrontProcess ()
10570 ProcessSerialNumber psn
;
10573 err
= GetCurrentProcess (&psn
);
10575 (void) SetFrontProcess (&psn
);
10578 /***** Code to handle C-g testing *****/
10580 /* Contains the Mac modifier formed from quit_char */
10581 int mac_quit_char_modifiers
= 0;
10582 int mac_quit_char_keycode
;
10583 extern int quit_char
;
10586 mac_determine_quit_char_modifiers()
10588 /* Todo: Determine modifiers from quit_char. */
10589 UInt32 qc_modifiers
= ctrl_modifier
;
10591 /* Map modifiers */
10592 mac_quit_char_modifiers
= 0;
10593 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
10594 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
10595 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
10599 init_quit_char_handler ()
10601 /* TODO: Let this support keys other the 'g' */
10602 mac_quit_char_keycode
= 5;
10603 /* Look at <architecture/adb_kb_map.h> for details */
10604 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10606 mac_determine_quit_char_modifiers();
10608 #endif /* MAC_OSX */
10616 MenuItemIndex menu_index
;
10618 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10619 &menu
, &menu_index
);
10621 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10622 #if USE_CARBON_EVENTS
10623 EnableMenuCommand (NULL
, kHICommandPreferences
);
10624 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10625 &menu
, &menu_index
);
10628 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10629 InsertMenuItemTextWithCFString (menu
, NULL
,
10630 0, kMenuItemAttrSeparator
, 0);
10631 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10632 0, 0, kHICommandAbout
);
10634 #endif /* USE_CARBON_EVENTS */
10635 #else /* !MAC_OSX */
10636 #if USE_CARBON_EVENTS
10637 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10643 /* Set up use of X before we make the first connection. */
10645 extern frame_parm_handler mac_frame_parm_handlers
[];
10647 static struct redisplay_interface x_redisplay_interface
=
10649 mac_frame_parm_handlers
,
10653 x_clear_end_of_line
,
10655 x_after_update_window_line
,
10656 x_update_window_begin
,
10657 x_update_window_end
,
10660 0, /* flush_display_optional */
10661 x_clear_window_mouse_face
,
10662 x_get_glyph_overhangs
,
10663 x_fix_overlapping_area
,
10664 x_draw_fringe_bitmap
,
10665 0, /* define_fringe_bitmap */
10666 0, /* destroy_fringe_bitmap */
10667 mac_per_char_metric
,
10669 mac_compute_glyph_string_overhangs
,
10670 x_draw_glyph_string
,
10671 mac_define_frame_cursor
,
10672 mac_clear_frame_area
,
10673 mac_draw_window_cursor
,
10674 mac_draw_vertical_window_border
,
10675 mac_shift_glyphs_for_insert
10681 rif
= &x_redisplay_interface
;
10683 clear_frame_hook
= x_clear_frame
;
10684 ins_del_lines_hook
= x_ins_del_lines
;
10685 delete_glyphs_hook
= x_delete_glyphs
;
10686 ring_bell_hook
= XTring_bell
;
10687 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10688 set_terminal_modes_hook
= XTset_terminal_modes
;
10689 update_begin_hook
= x_update_begin
;
10690 update_end_hook
= x_update_end
;
10691 set_terminal_window_hook
= XTset_terminal_window
;
10692 read_socket_hook
= XTread_socket
;
10693 frame_up_to_date_hook
= XTframe_up_to_date
;
10694 mouse_position_hook
= XTmouse_position
;
10695 frame_rehighlight_hook
= XTframe_rehighlight
;
10696 frame_raise_lower_hook
= XTframe_raise_lower
;
10698 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10699 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10700 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10701 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10703 scroll_region_ok
= 1; /* we'll scroll partial frames */
10704 char_ins_del_ok
= 1;
10705 line_ins_del_ok
= 1; /* we'll just blt 'em */
10706 fast_clear_end_of_line
= 1; /* X does this well */
10707 memory_below_frame
= 0; /* we don't remember what scrolls
10711 last_tool_bar_item
= -1;
10712 any_help_event_p
= 0;
10714 /* Try to use interrupt input; if we can't, then start polling. */
10715 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10719 #if TARGET_API_MAC_CARBON
10721 #if USE_CARBON_EVENTS
10723 init_service_handler ();
10725 init_quit_char_handler ();
10726 #endif /* MAC_OSX */
10728 init_command_handler ();
10731 #endif /* USE_CARBON_EVENTS */
10734 init_coercion_handler ();
10736 init_apple_event_handler ();
10738 if (!inhibit_window_system
)
10739 MakeMeTheFrontProcess ();
10750 staticpro (&x_error_message_string
);
10751 x_error_message_string
= Qnil
;
10754 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
10755 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
10756 Qalt
= intern ("alt"); staticpro (&Qalt
);
10757 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
10758 Qsuper
= intern ("super"); staticpro (&Qsuper
);
10759 Qmodifier_value
= intern ("modifier-value");
10760 staticpro (&Qmodifier_value
);
10762 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
10763 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10764 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10765 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10766 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10768 #if USE_CARBON_EVENTS
10769 Qhicommand
= intern ("hicommand"); staticpro (&Qhicommand
);
10771 Qservices
= intern ("services"); staticpro (&Qservices
);
10772 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10773 Qperform
= intern ("perform"); staticpro (&Qperform
);
10778 Fprovide (intern ("mac-carbon"), Qnil
);
10781 staticpro (&Qreverse
);
10782 Qreverse
= intern ("reverse");
10784 staticpro (&x_display_name_list
);
10785 x_display_name_list
= Qnil
;
10787 staticpro (&last_mouse_scroll_bar
);
10788 last_mouse_scroll_bar
= Qnil
;
10790 staticpro (&fm_font_family_alist
);
10791 fm_font_family_alist
= Qnil
;
10794 staticpro (&atsu_font_id_hash
);
10795 atsu_font_id_hash
= Qnil
;
10798 /* We don't yet support this, but defining this here avoids whining
10799 from cus-start.el and other places, like "M-x set-variable". */
10800 DEFVAR_BOOL ("x-use-underline-position-properties",
10801 &x_use_underline_position_properties
,
10802 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10803 nil means ignore them. If you encounter fonts with bogus
10804 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10805 to 4.1, set this to nil.
10807 NOTE: Not supported on Mac yet. */);
10808 x_use_underline_position_properties
= 0;
10810 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10811 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10812 #ifdef USE_TOOLKIT_SCROLL_BARS
10813 Vx_toolkit_scroll_bars
= Qt
;
10815 Vx_toolkit_scroll_bars
= Qnil
;
10818 staticpro (&last_mouse_motion_frame
);
10819 last_mouse_motion_frame
= Qnil
;
10821 /* Variables to configure modifier key assignment. */
10823 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
10824 doc
: /* *Modifier key assumed when the Mac control key is pressed.
10825 The value can be `control', `meta', `alt', `hyper', or `super' for the
10826 respective modifier. The default is `control'. */);
10827 Vmac_control_modifier
= Qcontrol
;
10829 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10830 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
10831 The value can be `control', `meta', `alt', `hyper', or `super' for the
10832 respective modifier. If the value is nil then the key will act as the
10833 normal Mac control modifier, and the option key can be used to compose
10834 characters depending on the chosen Mac keyboard setting. */);
10835 Vmac_option_modifier
= Qnil
;
10837 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
10838 doc
: /* *Modifier key assumed when the Mac command key is pressed.
10839 The value can be `control', `meta', `alt', `hyper', or `super' for the
10840 respective modifier. The default is `meta'. */);
10841 Vmac_command_modifier
= Qmeta
;
10843 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
10844 doc
: /* *Modifier key assumed when the Mac function key is pressed.
10845 The value can be `control', `meta', `alt', `hyper', or `super' for the
10846 respective modifier. Note that remapping the function key may lead to
10847 unexpected results for some keys on non-US/GB keyboards. */);
10848 Vmac_function_modifier
= Qnil
;
10850 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10851 &Vmac_emulate_three_button_mouse
,
10852 doc
: /* *Specify a way of three button mouse emulation.
10853 The value can be nil, t, or the symbol `reverse'.
10854 nil means that no emulation should be done and the modifiers should be
10855 placed on the mouse-1 event.
10856 t means that when the option-key is held down while pressing the mouse
10857 button, the click will register as mouse-2 and while the command-key
10858 is held down, the click will register as mouse-3.
10859 The symbol `reverse' means that the option-key will register for
10860 mouse-3 and the command-key will register for mouse-2. */);
10861 Vmac_emulate_three_button_mouse
= Qnil
;
10863 #if USE_CARBON_EVENTS
10864 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
10865 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
10866 Otherwise, the right click will be treated as mouse-2 and the wheel
10867 button will be mouse-3. */);
10868 mac_wheel_button_is_mouse_2
= 1;
10870 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
10871 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
10872 mac_pass_command_to_system
= 1;
10874 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
10875 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
10876 mac_pass_control_to_system
= 1;
10880 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
10881 doc
: /* *If non-nil, allow anti-aliasing.
10882 The text will be rendered using Core Graphics text rendering which
10883 may anti-alias the text. */);
10884 mac_use_core_graphics
= 0;
10886 /* Register an entry for `mac-roman' so that it can be used when
10887 creating the terminal frame on Mac OS 9 before loading
10888 term/mac-win.elc. */
10889 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10890 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
10891 Each entry should be of the form:
10893 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10895 where CHARSET-NAME is a string used in font names to identify the
10896 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
10897 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
10898 Vmac_charset_info_alist
=
10899 Fcons (list3 (build_string ("mac-roman"),
10900 make_number (smRoman
), Qnil
), Qnil
);
10903 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10904 (do not change this comment) */