1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
49 #include <Resources.h>
51 #include <TextUtils.h>
55 #if defined (__MRC__) || (__MSL__ >= 0x6000)
56 #include <ControlDefinitions.h>
62 #endif /* not TARGET_API_MAC_CARBON */
75 #include "dispextern.h"
77 #include "termhooks.h"
85 #include "intervals.h"
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 ()
1035 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1036 kCFPreferencesCurrentApplication
,
1039 cg_text_anti_aliasing_threshold
= threshold
;
1043 mac_draw_string_cg (f
, gc
, x
, y
, buf
, nchars
)
1051 float port_height
, gx
, gy
;
1053 CGContextRef context
;
1057 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1060 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1061 port_height
= FRAME_PIXEL_HEIGHT (f
);
1063 gy
= port_height
- y
;
1064 glyphs
= (CGGlyph
*)buf
;
1065 advances
= xmalloc (sizeof (CGSize
) * nchars
);
1066 for (i
= 0; i
< nchars
; i
++)
1068 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1070 advances
[i
].width
= pcm
->width
;
1071 advances
[i
].height
= 0;
1072 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1076 QDBeginCGContext (port
, &context
);
1077 if (gc
->n_clip_rects
)
1079 CGContextTranslateCTM (context
, 0, port_height
);
1080 CGContextScaleCTM (context
, 1, -1);
1081 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1082 CGContextScaleCTM (context
, 1, -1);
1083 CGContextTranslateCTM (context
, 0, -port_height
);
1085 CGContextSetRGBFillColor (context
,
1086 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
1087 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
1088 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
1090 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1091 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1092 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1093 CGContextSetShouldAntialias (context
, false);
1094 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1095 CGContextSetTextPosition (context
, gx
, gy
);
1096 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1098 for (i
= 0; i
< nchars
; i
++)
1100 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1101 gx
+= advances
[i
].width
;
1104 CGContextSynchronize (context
);
1105 QDEndCGContext (port
, &context
);
1114 /* Mac replacement for XCopyArea: dest must be window. */
1117 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1122 unsigned int width
, height
;
1127 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1129 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1130 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1132 ForeColor (blackColor
);
1133 BackColor (whiteColor
);
1135 mac_begin_clip (GC_CLIP_REGION (gc
));
1136 LockPixels (GetGWorldPixMap (src
));
1137 #if TARGET_API_MAC_CARBON
1142 LockPortBits (port
);
1143 CopyBits (GetPortBitMapForCopyBits (src
),
1144 GetPortBitMapForCopyBits (port
),
1145 &src_r
, &dest_r
, srcCopy
, 0);
1146 UnlockPortBits (port
);
1148 #else /* not TARGET_API_MAC_CARBON */
1149 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1150 &src_r
, &dest_r
, srcCopy
, 0);
1151 #endif /* not TARGET_API_MAC_CARBON */
1152 UnlockPixels (GetGWorldPixMap (src
));
1153 mac_end_clip (GC_CLIP_REGION (gc
));
1155 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1160 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1161 width
, height
, dest_x
, dest_y
)
1166 unsigned int width
, height
;
1171 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1173 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1174 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1176 ForeColor (blackColor
);
1177 BackColor (whiteColor
);
1179 mac_begin_clip (GC_CLIP_REGION (gc
));
1180 LockPixels (GetGWorldPixMap (src
));
1181 LockPixels (GetGWorldPixMap (mask
));
1182 #if TARGET_API_MAC_CARBON
1187 LockPortBits (port
);
1188 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1189 GetPortBitMapForCopyBits (port
),
1190 &src_r
, &src_r
, &dest_r
);
1191 UnlockPortBits (port
);
1193 #else /* not TARGET_API_MAC_CARBON */
1194 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1195 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1196 #endif /* not TARGET_API_MAC_CARBON */
1197 UnlockPixels (GetGWorldPixMap (mask
));
1198 UnlockPixels (GetGWorldPixMap (src
));
1199 mac_end_clip (GC_CLIP_REGION (gc
));
1201 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1205 /* Mac replacement for XCopyArea: used only for scrolling. */
1208 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1212 unsigned int width
, height
;
1215 #if TARGET_API_MAC_CARBON
1217 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1219 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1220 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1221 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1222 kScrollWindowNoOptions
, dummy
);
1224 #else /* not TARGET_API_MAC_CARBON */
1226 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1230 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1231 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1233 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1234 color mapping in CopyBits. Otherwise, it will be slow. */
1235 ForeColor (blackColor
);
1236 BackColor (whiteColor
);
1237 mac_begin_clip (GC_CLIP_REGION (gc
));
1238 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1239 mac_end_clip (GC_CLIP_REGION (gc
));
1241 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1242 #endif /* not TARGET_API_MAC_CARBON */
1246 /* Mac replacement for XChangeGC. */
1249 XChangeGC (display
, gc
, mask
, xgcv
)
1255 if (mask
& GCForeground
)
1256 XSetForeground (display
, gc
, xgcv
->foreground
);
1257 if (mask
& GCBackground
)
1258 XSetBackground (display
, gc
, xgcv
->background
);
1260 XSetFont (display
, gc
, xgcv
->font
);
1264 /* Mac replacement for XCreateGC. */
1267 XCreateGC (display
, window
, mask
, xgcv
)
1273 GC gc
= xmalloc (sizeof (*gc
));
1277 bzero (gc
, sizeof (*gc
));
1278 XChangeGC (display
, gc
, mask
, xgcv
);
1285 /* Used in xfaces.c. */
1288 XFreeGC (display
, gc
)
1292 if (gc
->clip_region
)
1293 DisposeRgn (gc
->clip_region
);
1298 /* Mac replacement for XGetGCValues. */
1301 XGetGCValues (display
, gc
, mask
, xgcv
)
1307 if (mask
& GCForeground
)
1308 xgcv
->foreground
= gc
->xgcv
.foreground
;
1309 if (mask
& GCBackground
)
1310 xgcv
->background
= gc
->xgcv
.background
;
1312 xgcv
->font
= gc
->xgcv
.font
;
1316 /* Mac replacement for XSetForeground. */
1319 XSetForeground (display
, gc
, color
)
1322 unsigned long color
;
1324 if (gc
->xgcv
.foreground
!= color
)
1326 gc
->xgcv
.foreground
= color
;
1327 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1328 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1329 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1334 /* Mac replacement for XSetBackground. */
1337 XSetBackground (display
, gc
, color
)
1340 unsigned long color
;
1342 if (gc
->xgcv
.background
!= color
)
1344 gc
->xgcv
.background
= color
;
1345 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1346 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1347 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1352 /* Mac replacement for XSetFont. */
1355 XSetFont (display
, gc
, font
)
1360 gc
->xgcv
.font
= font
;
1364 /* Mac replacement for XSetClipRectangles. */
1367 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1375 if (n
< 0 || n
> MAX_CLIP_RECTS
)
1379 if (gc
->clip_region
)
1381 DisposeRgn (gc
->clip_region
);
1382 gc
->clip_region
= NULL
;
1387 if (gc
->clip_region
== NULL
)
1388 gc
->clip_region
= NewRgn ();
1389 RectRgn (gc
->clip_region
, rectangles
);
1392 RgnHandle region
= NewRgn ();
1394 for (i
= 1; i
< n
; i
++)
1396 RectRgn (region
, rectangles
+ i
);
1397 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1399 DisposeRgn (region
);
1402 #if defined (MAC_OSX) && USE_ATSUI
1403 gc
->n_clip_rects
= n
;
1405 for (i
= 0; i
< n
; i
++)
1407 Rect
*rect
= rectangles
+ i
;
1409 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1410 rect
->right
- rect
->left
,
1411 rect
->bottom
- rect
->top
);
1417 /* Mac replacement for XSetClipMask. */
1420 mac_reset_clip_rectangles (display
, gc
)
1424 mac_set_clip_rectangles (display
, gc
, NULL
, 0);
1428 /* Mac replacement for XSetWindowBackground. */
1431 XSetWindowBackground (display
, w
, color
)
1434 unsigned long color
;
1436 #if !TARGET_API_MAC_CARBON
1437 AuxWinHandle aw_handle
;
1438 CTabHandle ctab_handle
;
1439 ColorSpecPtr ct_table
;
1444 bg_color
.red
= RED16_FROM_ULONG (color
);
1445 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1446 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1448 #if TARGET_API_MAC_CARBON
1449 SetWindowContentColor (w
, &bg_color
);
1451 if (GetAuxWin (w
, &aw_handle
))
1453 ctab_handle
= (*aw_handle
)->awCTable
;
1454 HandToHand ((Handle
*) &ctab_handle
);
1455 ct_table
= (*ctab_handle
)->ctTable
;
1456 ct_size
= (*ctab_handle
)->ctSize
;
1457 while (ct_size
> -1)
1459 if (ct_table
->value
== 0)
1461 ct_table
->rgb
= bg_color
;
1462 CTabChanged (ctab_handle
);
1463 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1471 /* x_sync is a no-op on Mac. */
1479 /* Flush display of frame F, or of all frames if F is null. */
1485 #if TARGET_API_MAC_CARBON
1488 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1490 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1496 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1497 Calls to XFlush should be unnecessary because the X output buffer
1498 is flushed automatically as needed by calls to XPending,
1499 XNextEvent, or XWindowEvent according to the XFlush man page.
1500 XTread_socket calls XPending. Removing XFlush improves
1503 #define XFlush(DISPLAY) (void) 0
1506 /* Return the struct mac_display_info corresponding to DPY. There's
1509 struct mac_display_info
*
1510 mac_display_info_for_display (dpy
)
1513 return &one_mac_display_info
;
1518 /***********************************************************************
1519 Starting and ending an update
1520 ***********************************************************************/
1522 /* Start an update of frame F. This function is installed as a hook
1523 for update_begin, i.e. it is called when update_begin is called.
1524 This function is called prior to calls to x_update_window_begin for
1525 each window being updated. */
1531 #if TARGET_API_MAC_CARBON
1532 /* During update of a frame, availability of input events is
1533 periodically checked with ReceiveNextEvent if
1534 redisplay-dont-pause is nil. That normally flushes window buffer
1535 changes for every check, and thus screen update looks waving even
1536 if no input is available. So we disable screen updates during
1537 update of a frame. */
1539 DisableScreenUpdates ();
1545 /* Start update of window W. Set the global variable updated_window
1546 to the window being updated and set output_cursor to the cursor
1550 x_update_window_begin (w
)
1553 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1554 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1557 set_output_cursor (&w
->cursor
);
1561 if (f
== display_info
->mouse_face_mouse_frame
)
1563 /* Don't do highlighting for mouse motion during the update. */
1564 display_info
->mouse_face_defer
= 1;
1566 /* If F needs to be redrawn, simply forget about any prior mouse
1568 if (FRAME_GARBAGED_P (f
))
1569 display_info
->mouse_face_window
= Qnil
;
1571 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1572 their mouse_face_p flag set, which means that they are always
1573 unequal to rows in a desired matrix which never have that
1574 flag set. So, rows containing mouse-face glyphs are never
1575 scrolled, and we don't have to switch the mouse highlight off
1576 here to prevent it from being scrolled. */
1578 /* Can we tell that this update does not affect the window
1579 where the mouse highlight is? If so, no need to turn off.
1580 Likewise, don't do anything if the frame is garbaged;
1581 in that case, the frame's current matrix that we would use
1582 is all wrong, and we will redisplay that line anyway. */
1583 if (!NILP (display_info
->mouse_face_window
)
1584 && w
== XWINDOW (display_info
->mouse_face_window
))
1588 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1589 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1592 if (i
< w
->desired_matrix
->nrows
)
1593 clear_mouse_face (display_info
);
1602 /* Draw a vertical window border from (x,y0) to (x,y1) */
1605 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1609 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1612 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1614 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1617 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1620 /* End update of window W (which is equal to updated_window).
1622 Draw vertical borders between horizontally adjacent windows, and
1623 display W's cursor if CURSOR_ON_P is non-zero.
1625 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1626 glyphs in mouse-face were overwritten. In that case we have to
1627 make sure that the mouse-highlight is properly redrawn.
1629 W may be a menu bar pseudo-window in case we don't have X toolkit
1630 support. Such windows don't have a cursor, so don't display it
1634 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1636 int cursor_on_p
, mouse_face_overwritten_p
;
1638 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1640 if (!w
->pseudo_window_p
)
1645 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1647 output_cursor
.x
, output_cursor
.y
);
1649 if (draw_window_fringes (w
, 1))
1650 x_draw_vertical_border (w
);
1655 /* If a row with mouse-face was overwritten, arrange for
1656 XTframe_up_to_date to redisplay the mouse highlight. */
1657 if (mouse_face_overwritten_p
)
1659 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1660 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1661 dpyinfo
->mouse_face_window
= Qnil
;
1664 updated_window
= NULL
;
1668 /* End update of frame F. This function is installed as a hook in
1675 /* Mouse highlight may be displayed again. */
1676 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1679 #if TARGET_API_MAC_CARBON
1680 EnableScreenUpdates ();
1682 XFlush (FRAME_MAC_DISPLAY (f
));
1687 /* This function is called from various places in xdisp.c whenever a
1688 complete update has been performed. The global variable
1689 updated_window is not available here. */
1692 XTframe_up_to_date (f
)
1695 if (FRAME_MAC_P (f
))
1697 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1699 if (dpyinfo
->mouse_face_deferred_gc
1700 || f
== dpyinfo
->mouse_face_mouse_frame
)
1703 if (dpyinfo
->mouse_face_mouse_frame
)
1704 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1705 dpyinfo
->mouse_face_mouse_x
,
1706 dpyinfo
->mouse_face_mouse_y
);
1707 dpyinfo
->mouse_face_deferred_gc
= 0;
1714 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1715 arrow bitmaps, or clear the fringes if no bitmaps are required
1716 before DESIRED_ROW is made current. The window being updated is
1717 found in updated_window. This function is called from
1718 update_window_line only if it is known that there are differences
1719 between bitmaps to be drawn between current row and DESIRED_ROW. */
1722 x_after_update_window_line (desired_row
)
1723 struct glyph_row
*desired_row
;
1725 struct window
*w
= updated_window
;
1731 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1732 desired_row
->redraw_fringe_bitmaps_p
= 1;
1734 /* When a window has disappeared, make sure that no rest of
1735 full-width rows stays visible in the internal border. Could
1736 check here if updated_window is the leftmost/rightmost window,
1737 but I guess it's not worth doing since vertically split windows
1738 are almost never used, internal border is rarely set, and the
1739 overhead is very small. */
1740 if (windows_or_buffers_changed
1741 && desired_row
->full_width_p
1742 && (f
= XFRAME (w
->frame
),
1743 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1745 && (height
= desired_row
->visible_height
,
1748 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1750 /* Internal border is drawn below the tool bar. */
1751 if (WINDOWP (f
->tool_bar_window
)
1752 && w
== XWINDOW (f
->tool_bar_window
))
1756 mac_clear_area (f
, 0, y
, width
, height
);
1757 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
1763 /* Draw the bitmap WHICH in one of the left or right fringes of
1764 window W. ROW is the glyph row for which to display the bitmap; it
1765 determines the vertical position at which the bitmap has to be
1769 x_draw_fringe_bitmap (w
, row
, p
)
1771 struct glyph_row
*row
;
1772 struct draw_fringe_bitmap_params
*p
;
1774 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1775 Display
*display
= FRAME_MAC_DISPLAY (f
);
1776 struct face
*face
= p
->face
;
1779 /* Must clip because of partially visible lines. */
1780 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1783 /* Adjust position of "bottom aligned" bitmap on partially
1784 visible last row. */
1786 int oldVH
= row
->visible_height
;
1787 row
->visible_height
= p
->h
;
1788 row
->y
-= rowY
- p
->y
;
1789 x_clip_to_row (w
, row
, -1, face
->gc
);
1791 row
->visible_height
= oldVH
;
1794 x_clip_to_row (w
, row
, -1, face
->gc
);
1796 if (p
->bx
>= 0 && !p
->overlay_p
)
1798 #if 0 /* MAC_TODO: stipple */
1799 /* In case the same realized face is used for fringes and
1800 for something displayed in the text (e.g. face `region' on
1801 mono-displays, the fill style may have been changed to
1802 FillSolid in x_draw_glyph_string_background. */
1804 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1806 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1809 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1811 #if 0 /* MAC_TODO: stipple */
1813 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1819 unsigned short *bits
= p
->bits
+ p
->dh
;
1822 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
1823 XSetForeground (display
, face
->gc
,
1825 ? (p
->overlay_p
? face
->background
1826 : f
->output_data
.mac
->cursor_pixel
)
1827 : face
->foreground
));
1828 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
1829 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1830 XSetForeground (display
, face
->gc
, gcv
.foreground
);
1833 mac_reset_clip_rectangles (display
, face
->gc
);
1838 /* This is called when starting Emacs and when restarting after
1839 suspend. When starting Emacs, no window is mapped. And nothing
1840 must be done to Emacs's own window if it is suspended (though that
1844 XTset_terminal_modes ()
1848 /* This is called when exiting or suspending Emacs. Exiting will make
1849 the windows go away, and suspending requires no action. */
1852 XTreset_terminal_modes ()
1858 /***********************************************************************
1860 ***********************************************************************/
1862 /* Function prototypes of this page. */
1864 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1865 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
1866 struct charset
*, int *));
1869 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1870 is not contained in the font. */
1872 static INLINE XCharStruct
*
1873 x_per_char_metric (font
, char2b
)
1877 /* The result metric information. */
1878 XCharStruct
*pcm
= NULL
;
1880 xassert (font
&& char2b
);
1883 if (font
->mac_style
)
1885 XCharStructRow
**row
= font
->bounds
.rows
+ char2b
->byte1
;
1889 *row
= xmalloc (sizeof (XCharStructRow
));
1891 bzero (*row
, sizeof (XCharStructRow
));
1895 pcm
= (*row
)->per_char
+ char2b
->byte2
;
1896 if (!XCHARSTRUCTROW_CHAR_VALID_P (*row
, char2b
->byte2
))
1899 mac_query_char_extents (font
->mac_style
,
1900 (char2b
->byte1
<< 8) + char2b
->byte2
,
1901 NULL
, NULL
, pcm
, NULL
);
1903 XCHARSTRUCTROW_SET_CHAR_VALID (*row
, char2b
->byte2
);
1910 if (font
->bounds
.per_char
!= NULL
)
1912 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1914 /* min_char_or_byte2 specifies the linear character index
1915 corresponding to the first element of the per_char array,
1916 max_char_or_byte2 is the index of the last character. A
1917 character with non-zero CHAR2B->byte1 is not in the font.
1918 A character with byte2 less than min_char_or_byte2 or
1919 greater max_char_or_byte2 is not in the font. */
1920 if (char2b
->byte1
== 0
1921 && char2b
->byte2
>= font
->min_char_or_byte2
1922 && char2b
->byte2
<= font
->max_char_or_byte2
)
1923 pcm
= font
->bounds
.per_char
1924 + (char2b
->byte2
- font
->min_char_or_byte2
);
1928 /* If either min_byte1 or max_byte1 are nonzero, both
1929 min_char_or_byte2 and max_char_or_byte2 are less than
1930 256, and the 2-byte character index values corresponding
1931 to the per_char array element N (counting from 0) are:
1933 byte1 = N/D + min_byte1
1934 byte2 = N\D + min_char_or_byte2
1938 D = max_char_or_byte2 - min_char_or_byte2 + 1
1939 / = integer division
1940 \ = integer modulus */
1941 if (char2b
->byte1
>= font
->min_byte1
1942 && char2b
->byte1
<= font
->max_byte1
1943 && char2b
->byte2
>= font
->min_char_or_byte2
1944 && char2b
->byte2
<= font
->max_char_or_byte2
)
1946 pcm
= (font
->bounds
.per_char
1947 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1948 * (char2b
->byte1
- font
->min_byte1
))
1949 + (char2b
->byte2
- font
->min_char_or_byte2
));
1955 /* If the per_char pointer is null, all glyphs between the first
1956 and last character indexes inclusive have the same
1957 information, as given by both min_bounds and max_bounds. */
1958 if (char2b
->byte2
>= font
->min_char_or_byte2
1959 && char2b
->byte2
<= font
->max_char_or_byte2
)
1960 pcm
= &font
->max_bounds
;
1966 return ((pcm
== NULL
1967 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1974 static XCharStruct
*
1975 mac_per_char_metric (font
, char2b
, font_type
)
1980 return x_per_char_metric (font
, char2b
);
1984 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1985 the two-byte form of C. Encoding is returned in *CHAR2B. */
1988 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
1991 struct font_info
*font_info
;
1992 struct charset
*charset
;
1995 XFontStruct
*font
= font_info
->font
;
1997 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1998 This may be either a program in a special encoder language or a
2000 if (font_info
->font_encoder
)
2002 /* It's a program. */
2003 struct ccl_program
*ccl
= font_info
->font_encoder
;
2005 check_ccl_update (ccl
);
2006 if (CHARSET_DIMENSION (charset
) == 1)
2008 ccl
->reg
[0] = CHARSET_ID (charset
);
2009 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
2014 ccl
->reg
[0] = CHARSET_ID (charset
);
2015 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
2016 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
2019 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
2021 /* We assume that MSBs are appropriately set/reset by CCL
2023 if (font
->max_byte1
== 0) /* 1-byte font */
2024 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
2026 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
2028 else if (font_info
->encoding_type
)
2030 /* Fixed encoding scheme. See fontset.h for the meaning of the
2031 encoding numbers. */
2032 unsigned char enc
= font_info
->encoding_type
;
2034 if ((enc
== 1 || enc
== 2)
2035 && CHARSET_DIMENSION (charset
) == 2)
2036 char2b
->byte1
|= 0x80;
2038 if (enc
== 1 || enc
== 3)
2039 char2b
->byte2
|= 0x80;
2043 int code
= (char2b
->byte1
<< 8) | char2b
->byte2
;
2046 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
2051 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2053 return FONT_TYPE_UNKNOWN
;
2058 /***********************************************************************
2060 ***********************************************************************/
2064 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2065 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2066 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2068 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2069 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2070 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2071 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2072 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2073 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2074 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2075 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2076 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2077 unsigned long *, double, int));*/
2078 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2079 double, int, unsigned long));
2080 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2081 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2082 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2083 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2084 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2085 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2087 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2088 int, int, int, int, int, int,
2090 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2091 int, int, int, Rect
*));
2094 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2098 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2103 struct glyph_string
*s
;
2105 if (s
->font
== FRAME_FONT (s
->f
)
2106 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2107 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2109 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2112 /* Cursor on non-default face: must merge. */
2116 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2117 xgcv
.foreground
= s
->face
->background
;
2119 /* If the glyph would be invisible, try a different foreground. */
2120 if (xgcv
.foreground
== xgcv
.background
)
2121 xgcv
.foreground
= s
->face
->foreground
;
2122 if (xgcv
.foreground
== xgcv
.background
)
2123 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2124 if (xgcv
.foreground
== xgcv
.background
)
2125 xgcv
.foreground
= s
->face
->foreground
;
2127 /* Make sure the cursor is distinct from text in this face. */
2128 if (xgcv
.background
== s
->face
->background
2129 && xgcv
.foreground
== s
->face
->foreground
)
2131 xgcv
.background
= s
->face
->foreground
;
2132 xgcv
.foreground
= s
->face
->background
;
2135 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2136 xgcv
.font
= s
->font
;
2137 mask
= GCForeground
| GCBackground
| GCFont
;
2139 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2140 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2143 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2144 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2146 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2151 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2154 x_set_mouse_face_gc (s
)
2155 struct glyph_string
*s
;
2160 /* What face has to be used last for the mouse face? */
2161 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2162 face
= FACE_FROM_ID (s
->f
, face_id
);
2164 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2166 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2167 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
2169 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
2170 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2171 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2173 /* If font in this face is same as S->font, use it. */
2174 if (s
->font
== s
->face
->font
)
2175 s
->gc
= s
->face
->gc
;
2178 /* Otherwise construct scratch_cursor_gc with values from FACE
2183 xgcv
.background
= s
->face
->background
;
2184 xgcv
.foreground
= s
->face
->foreground
;
2185 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2186 xgcv
.font
= s
->font
;
2187 mask
= GCForeground
| GCBackground
| GCFont
;
2189 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2190 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2193 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2194 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2196 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2199 xassert (s
->gc
!= 0);
2203 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2204 Faces to use in the mode line have already been computed when the
2205 matrix was built, so there isn't much to do, here. */
2208 x_set_mode_line_face_gc (s
)
2209 struct glyph_string
*s
;
2211 s
->gc
= s
->face
->gc
;
2215 /* Set S->gc of glyph string S for drawing that glyph string. Set
2216 S->stippled_p to a non-zero value if the face of S has a stipple
2220 x_set_glyph_string_gc (s
)
2221 struct glyph_string
*s
;
2223 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2225 if (s
->hl
== DRAW_NORMAL_TEXT
)
2227 s
->gc
= s
->face
->gc
;
2228 s
->stippled_p
= s
->face
->stipple
!= 0;
2230 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2232 x_set_mode_line_face_gc (s
);
2233 s
->stippled_p
= s
->face
->stipple
!= 0;
2235 else if (s
->hl
== DRAW_CURSOR
)
2237 x_set_cursor_gc (s
);
2240 else if (s
->hl
== DRAW_MOUSE_FACE
)
2242 x_set_mouse_face_gc (s
);
2243 s
->stippled_p
= s
->face
->stipple
!= 0;
2245 else if (s
->hl
== DRAW_IMAGE_RAISED
2246 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2248 s
->gc
= s
->face
->gc
;
2249 s
->stippled_p
= s
->face
->stipple
!= 0;
2253 s
->gc
= s
->face
->gc
;
2254 s
->stippled_p
= s
->face
->stipple
!= 0;
2257 /* GC must have been set. */
2258 xassert (s
->gc
!= 0);
2262 /* Set clipping for output of glyph string S. S may be part of a mode
2263 line or menu if we don't have X toolkit support. */
2266 x_set_glyph_string_clipping (s
)
2267 struct glyph_string
*s
;
2269 Rect rects
[MAX_CLIP_RECTS
];
2272 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2273 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2278 Compute left and right overhang of glyph string S. If S is a glyph
2279 string for a composition, assume overhangs don't exist. */
2282 mac_compute_glyph_string_overhangs (s
)
2283 struct glyph_string
*s
;
2286 && s
->first_glyph
->type
== CHAR_GLYPH
)
2289 || s
->font
->mac_style
2295 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2296 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2297 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2302 MacFontStruct
*font
= s
->font
;
2304 TextFont (font
->mac_fontnum
);
2305 TextSize (font
->mac_fontsize
);
2306 TextFace (font
->mac_fontface
);
2308 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2310 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2311 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2316 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2319 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2320 struct glyph_string
*s
;
2323 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2327 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2328 on Mac OS X because:
2329 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2330 into an offscreen graphics world first. So performance gain
2331 cannot be expected.)
2332 - It lowers rendering quality.
2333 - Some fonts leave garbage on cursor movement. */
2335 /* Draw the background of glyph_string S. If S->background_filled_p
2336 is non-zero don't draw it. FORCE_P non-zero means draw the
2337 background even if it wouldn't be drawn normally. This is used
2338 when a string preceding S draws into the background of S, or S
2339 contains the first component of a composition. */
2342 x_draw_glyph_string_background (s
, force_p
)
2343 struct glyph_string
*s
;
2346 /* Nothing to do if background has already been drawn or if it
2347 shouldn't be drawn in the first place. */
2348 if (!s
->background_filled_p
)
2350 int box_line_width
= max (s
->face
->box_line_width
, 0);
2352 #if 0 /* MAC_TODO: stipple */
2355 /* Fill background with a stipple pattern. */
2356 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2357 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2358 s
->y
+ box_line_width
,
2359 s
->background_width
,
2360 s
->height
- 2 * box_line_width
);
2361 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2362 s
->background_filled_p
= 1;
2366 #if defined (MAC_OS8) && !USE_ATSUI
2367 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2368 || s
->font_not_found_p
2369 || s
->extends_to_end_of_line_p
2373 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2374 s
->background_width
,
2375 s
->height
- 2 * box_line_width
);
2376 s
->background_filled_p
= 1;
2382 /* Draw the foreground of glyph string S. */
2385 x_draw_glyph_string_foreground (s
)
2386 struct glyph_string
*s
;
2390 /* If first glyph of S has a left box line, start drawing the text
2391 of S to the right of that box line. */
2392 if (s
->face
->box
!= FACE_NO_BOX
2393 && s
->first_glyph
->left_box_line_p
)
2394 x
= s
->x
+ abs (s
->face
->box_line_width
);
2398 /* Draw characters of S as rectangles if S's font could not be
2400 if (s
->font_not_found_p
)
2402 for (i
= 0; i
< s
->nchars
; ++i
)
2404 struct glyph
*g
= s
->first_glyph
+ i
;
2405 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2406 g
->pixel_width
- 1, s
->height
- 1);
2407 x
+= g
->pixel_width
;
2412 char *char1b
= (char *) s
->char2b
;
2413 int boff
= s
->font_info
->baseline_offset
;
2415 if (s
->font_info
->vertical_centering
)
2416 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2418 /* If we can use 8-bit functions, condense S->char2b. */
2421 && GC_FONT (s
->gc
)->mac_style
== NULL
2424 for (i
= 0; i
< s
->nchars
; ++i
)
2425 char1b
[i
] = s
->char2b
[i
].byte2
;
2427 #if defined (MAC_OS8) && !USE_ATSUI
2428 /* Draw text with XDrawString if background has already been
2429 filled. Otherwise, use XDrawImageString. (Note that
2430 XDrawImageString is usually faster than XDrawString.) Always
2431 use XDrawImageString when drawing the cursor so that there is
2432 no chance that characters under a box cursor are invisible. */
2434 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2437 /* Draw characters with 16-bit or 8-bit functions. */
2440 || GC_FONT (s
->gc
)->mac_style
2443 #if USE_CG_TEXT_DRAWING
2445 && mac_draw_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2446 s
->char2b
, s
->nchars
))
2450 mac_draw_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2451 s
->char2b
, s
->nchars
);
2453 mac_draw_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2456 #if defined (MAC_OS8) && !USE_ATSUI
2460 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2461 s
->char2b
, s
->nchars
);
2463 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2470 /* Draw the foreground of composite glyph string S. */
2473 x_draw_composite_glyph_string_foreground (s
)
2474 struct glyph_string
*s
;
2478 /* If first glyph of S has a left box line, start drawing the text
2479 of S to the right of that box line. */
2480 if (s
->face
->box
!= FACE_NO_BOX
2481 && s
->first_glyph
->left_box_line_p
)
2482 x
= s
->x
+ abs (s
->face
->box_line_width
);
2486 /* S is a glyph string for a composition. S->gidx is the index of
2487 the first character drawn for glyphs of this composition.
2488 S->gidx == 0 means we are drawing the very first character of
2489 this composition. */
2491 /* Draw a rectangle for the composition if the font for the very
2492 first character of the composition could not be loaded. */
2493 if (s
->font_not_found_p
)
2496 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2497 s
->width
- 1, s
->height
- 1);
2501 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2502 mac_draw_string_16 (s
->f
, s
->gc
,
2503 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2504 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2510 #ifdef USE_X_TOOLKIT
2512 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2515 /* Return the frame on which widget WIDGET is used.. Abort if frame
2516 cannot be determined. */
2518 static struct frame
*
2519 x_frame_of_widget (widget
)
2522 struct x_display_info
*dpyinfo
;
2526 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2528 /* Find the top-level shell of the widget. Note that this function
2529 can be called when the widget is not yet realized, so XtWindow
2530 (widget) == 0. That's the reason we can't simply use
2531 x_any_window_to_frame. */
2532 while (!XtIsTopLevelShell (widget
))
2533 widget
= XtParent (widget
);
2535 /* Look for a frame with that top-level widget. Allocate the color
2536 on that frame to get the right gamma correction value. */
2537 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2538 if (GC_FRAMEP (XCAR (tail
))
2539 && (f
= XFRAME (XCAR (tail
)),
2540 (f
->output_data
.nothing
!= 1
2541 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2542 && f
->output_data
.x
->widget
== widget
)
2549 /* Allocate the color COLOR->pixel on the screen and display of
2550 widget WIDGET in colormap CMAP. If an exact match cannot be
2551 allocated, try the nearest color available. Value is non-zero
2552 if successful. This is called from lwlib. */
2555 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2560 struct frame
*f
= x_frame_of_widget (widget
);
2561 return x_alloc_nearest_color (f
, cmap
, color
);
2565 #endif /* USE_X_TOOLKIT */
2567 #if 0 /* MAC_TODO */
2569 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2570 CMAP. If an exact match can't be allocated, try the nearest color
2571 available. Value is non-zero if successful. Set *COLOR to the
2575 x_alloc_nearest_color (f
, cmap
, color
)
2580 Display
*display
= FRAME_X_DISPLAY (f
);
2581 Screen
*screen
= FRAME_X_SCREEN (f
);
2584 gamma_correct (f
, color
);
2585 rc
= XAllocColor (display
, cmap
, color
);
2588 /* If we got to this point, the colormap is full, so we're going
2589 to try to get the next closest color. The algorithm used is
2590 a least-squares matching, which is what X uses for closest
2591 color matching with StaticColor visuals. */
2593 unsigned long nearest_delta
= ~0;
2594 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2595 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2597 for (i
= 0; i
< ncells
; ++i
)
2599 XQueryColors (display
, cmap
, cells
, ncells
);
2601 for (nearest
= i
= 0; i
< ncells
; ++i
)
2603 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2604 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2605 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2606 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2608 if (delta
< nearest_delta
)
2611 nearest_delta
= delta
;
2615 color
->red
= cells
[nearest
].red
;
2616 color
->green
= cells
[nearest
].green
;
2617 color
->blue
= cells
[nearest
].blue
;
2618 rc
= XAllocColor (display
, cmap
, color
);
2621 #ifdef DEBUG_X_COLORS
2623 register_color (color
->pixel
);
2624 #endif /* DEBUG_X_COLORS */
2630 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2631 It's necessary to do this instead of just using PIXEL directly to
2632 get color reference counts right. */
2635 x_copy_color (f
, pixel
)
2637 unsigned long pixel
;
2641 color
.pixel
= pixel
;
2643 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2644 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2646 #ifdef DEBUG_X_COLORS
2647 register_color (pixel
);
2653 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2654 It's necessary to do this instead of just using PIXEL directly to
2655 get color reference counts right. */
2658 x_copy_dpy_color (dpy
, cmap
, pixel
)
2661 unsigned long pixel
;
2665 color
.pixel
= pixel
;
2667 XQueryColor (dpy
, cmap
, &color
);
2668 XAllocColor (dpy
, cmap
, &color
);
2670 #ifdef DEBUG_X_COLORS
2671 register_color (pixel
);
2676 #endif /* MAC_TODO */
2679 /* Brightness beyond which a color won't have its highlight brightness
2682 Nominally, highlight colors for `3d' faces are calculated by
2683 brightening an object's color by a constant scale factor, but this
2684 doesn't yield good results for dark colors, so for colors who's
2685 brightness is less than this value (on a scale of 0-255) have to
2686 use an additional additive factor.
2688 The value here is set so that the default menu-bar/mode-line color
2689 (grey75) will not have its highlights changed at all. */
2690 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2693 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2694 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2695 If this produces the same color as COLOR, try a color where all RGB
2696 values have DELTA added. Return the allocated color in *COLOR.
2697 DISPLAY is the X display, CMAP is the colormap to operate on.
2698 Value is non-zero if successful. */
2701 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2703 unsigned long *color
;
2710 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2713 /* Change RGB values by specified FACTOR. Avoid overflow! */
2714 xassert (factor
>= 0);
2715 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2716 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2717 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2719 /* Calculate brightness of COLOR. */
2720 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2721 + BLUE_FROM_ULONG (*color
)) / 6;
2723 /* We only boost colors that are darker than
2724 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2725 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2726 /* Make an additive adjustment to NEW, because it's dark enough so
2727 that scaling by FACTOR alone isn't enough. */
2729 /* How far below the limit this color is (0 - 1, 1 being darker). */
2730 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2731 /* The additive adjustment. */
2732 int min_delta
= delta
* dimness
* factor
/ 2;
2735 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2736 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2737 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2739 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2740 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2741 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2745 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2746 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2747 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2749 /* MAC_TODO: Map to palette and retry with delta if same? */
2750 /* MAC_TODO: Free colors (if using palette)? */
2761 /* Set up the foreground color for drawing relief lines of glyph
2762 string S. RELIEF is a pointer to a struct relief containing the GC
2763 with which lines will be drawn. Use a color that is FACTOR or
2764 DELTA lighter or darker than the relief's background which is found
2765 in S->f->output_data.x->relief_background. If such a color cannot
2766 be allocated, use DEFAULT_PIXEL, instead. */
2769 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2771 struct relief
*relief
;
2774 unsigned long default_pixel
;
2777 struct mac_output
*di
= f
->output_data
.mac
;
2778 unsigned long mask
= GCForeground
;
2779 unsigned long pixel
;
2780 unsigned long background
= di
->relief_background
;
2781 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2783 /* MAC_TODO: Free colors (if using palette)? */
2785 /* Allocate new color. */
2786 xgcv
.foreground
= default_pixel
;
2788 if (dpyinfo
->n_planes
!= 1
2789 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2791 relief
->allocated_p
= 1;
2792 xgcv
.foreground
= relief
->pixel
= pixel
;
2795 if (relief
->gc
== 0)
2797 #if 0 /* MAC_TODO: stipple */
2798 xgcv
.stipple
= dpyinfo
->gray
;
2801 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2804 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2808 /* Set up colors for the relief lines around glyph string S. */
2811 x_setup_relief_colors (s
)
2812 struct glyph_string
*s
;
2814 struct mac_output
*di
= s
->f
->output_data
.mac
;
2815 unsigned long color
;
2817 if (s
->face
->use_box_color_for_shadows_p
)
2818 color
= s
->face
->box_color
;
2819 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2821 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2822 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2827 /* Get the background color of the face. */
2828 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2829 color
= xgcv
.background
;
2832 if (di
->white_relief
.gc
== 0
2833 || color
!= di
->relief_background
)
2835 di
->relief_background
= color
;
2836 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2837 WHITE_PIX_DEFAULT (s
->f
));
2838 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2839 BLACK_PIX_DEFAULT (s
->f
));
2844 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2845 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2846 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2847 relief. LEFT_P non-zero means draw a relief on the left side of
2848 the rectangle. RIGHT_P non-zero means draw a relief on the right
2849 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2853 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2854 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2856 int left_x
, top_y
, right_x
, bottom_y
, width
;
2857 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2860 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2865 gc
= f
->output_data
.mac
->white_relief
.gc
;
2867 gc
= f
->output_data
.mac
->black_relief
.gc
;
2868 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2872 for (i
= 0; i
< width
; ++i
)
2873 mac_draw_line (f
, gc
,
2874 left_x
+ i
* left_p
, top_y
+ i
,
2875 right_x
- i
* right_p
, top_y
+ i
);
2879 for (i
= 0; i
< width
; ++i
)
2880 mac_draw_line (f
, gc
,
2881 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2883 mac_reset_clip_rectangles (dpy
, gc
);
2885 gc
= f
->output_data
.mac
->black_relief
.gc
;
2887 gc
= f
->output_data
.mac
->white_relief
.gc
;
2888 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2892 for (i
= 0; i
< width
; ++i
)
2893 mac_draw_line (f
, gc
,
2894 left_x
+ i
* left_p
, bottom_y
- i
,
2895 right_x
- i
* right_p
, bottom_y
- i
);
2899 for (i
= 0; i
< width
; ++i
)
2900 mac_draw_line (f
, gc
,
2901 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2903 mac_reset_clip_rectangles (dpy
, gc
);
2907 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2908 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2909 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2910 left side of the rectangle. RIGHT_P non-zero means draw a line
2911 on the right side of the rectangle. CLIP_RECT is the clipping
2912 rectangle to use when drawing. */
2915 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2916 left_p
, right_p
, clip_rect
)
2917 struct glyph_string
*s
;
2918 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2923 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2924 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2925 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
2928 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2929 right_x
- left_x
+ 1, width
);
2933 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2934 width
, bottom_y
- top_y
+ 1);
2937 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
2938 right_x
- left_x
+ 1, width
);
2942 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
2943 top_y
, width
, bottom_y
- top_y
+ 1);
2945 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2946 mac_reset_clip_rectangles (s
->display
, s
->gc
);
2950 /* Draw a box around glyph string S. */
2953 x_draw_glyph_string_box (s
)
2954 struct glyph_string
*s
;
2956 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2957 int left_p
, right_p
;
2958 struct glyph
*last_glyph
;
2961 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2962 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2963 : window_box_right (s
->w
, s
->area
));
2965 /* The glyph that may have a right box line. */
2966 last_glyph
= (s
->cmp
|| s
->img
2968 : s
->first_glyph
+ s
->nchars
- 1);
2970 width
= abs (s
->face
->box_line_width
);
2971 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2973 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2975 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2977 bottom_y
= top_y
+ s
->height
- 1;
2979 left_p
= (s
->first_glyph
->left_box_line_p
2980 || (s
->hl
== DRAW_MOUSE_FACE
2982 || s
->prev
->hl
!= s
->hl
)));
2983 right_p
= (last_glyph
->right_box_line_p
2984 || (s
->hl
== DRAW_MOUSE_FACE
2986 || s
->next
->hl
!= s
->hl
)));
2988 get_glyph_string_clip_rect (s
, &clip_rect
);
2990 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2991 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2992 left_p
, right_p
, &clip_rect
);
2995 x_setup_relief_colors (s
);
2996 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2997 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3002 /* Draw foreground of image glyph string S. */
3005 x_draw_image_foreground (s
)
3006 struct glyph_string
*s
;
3009 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3011 /* If first glyph of S has a left box line, start drawing it to the
3012 right of that line. */
3013 if (s
->face
->box
!= FACE_NO_BOX
3014 && s
->first_glyph
->left_box_line_p
3016 x
+= abs (s
->face
->box_line_width
);
3018 /* If there is a margin around the image, adjust x- and y-position
3020 if (s
->slice
.x
== 0)
3021 x
+= s
->img
->hmargin
;
3022 if (s
->slice
.y
== 0)
3023 y
+= s
->img
->vmargin
;
3027 x_set_glyph_string_clipping (s
);
3030 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3031 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3032 s
->slice
.width
, s
->slice
.height
, x
, y
);
3035 mac_copy_area (s
->img
->pixmap
,
3036 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3037 s
->slice
.width
, s
->slice
.height
, x
, y
);
3039 /* When the image has a mask, we can expect that at
3040 least part of a mouse highlight or a block cursor will
3041 be visible. If the image doesn't have a mask, make
3042 a block cursor visible by drawing a rectangle around
3043 the image. I believe it's looking better if we do
3044 nothing here for mouse-face. */
3045 if (s
->hl
== DRAW_CURSOR
)
3047 int r
= s
->img
->relief
;
3049 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3050 s
->slice
.width
+ r
*2 - 1,
3051 s
->slice
.height
+ r
*2 - 1);
3056 /* Draw a rectangle if image could not be loaded. */
3057 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3058 s
->slice
.width
- 1, s
->slice
.height
- 1);
3062 /* Draw a relief around the image glyph string S. */
3065 x_draw_image_relief (s
)
3066 struct glyph_string
*s
;
3068 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3071 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3073 /* If first glyph of S has a left box line, start drawing it to the
3074 right of that line. */
3075 if (s
->face
->box
!= FACE_NO_BOX
3076 && s
->first_glyph
->left_box_line_p
3078 x
+= abs (s
->face
->box_line_width
);
3080 /* If there is a margin around the image, adjust x- and y-position
3082 if (s
->slice
.x
== 0)
3083 x
+= s
->img
->hmargin
;
3084 if (s
->slice
.y
== 0)
3085 y
+= s
->img
->vmargin
;
3087 if (s
->hl
== DRAW_IMAGE_SUNKEN
3088 || s
->hl
== DRAW_IMAGE_RAISED
)
3090 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3091 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3095 thick
= abs (s
->img
->relief
);
3096 raised_p
= s
->img
->relief
> 0;
3101 x1
= x
+ s
->slice
.width
+ thick
- 1;
3102 y1
= y
+ s
->slice
.height
+ thick
- 1;
3104 x_setup_relief_colors (s
);
3105 get_glyph_string_clip_rect (s
, &r
);
3106 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3108 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3110 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3115 /* Draw part of the background of glyph string S. X, Y, W, and H
3116 give the rectangle to draw. */
3119 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3120 struct glyph_string
*s
;
3123 #if 0 /* MAC_TODO: stipple */
3126 /* Fill background with a stipple pattern. */
3127 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3128 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3129 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3132 #endif /* MAC_TODO */
3133 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3137 /* Draw image glyph string S.
3140 s->x +-------------------------
3143 | +-------------------------
3146 | | +-------------------
3152 x_draw_image_glyph_string (s
)
3153 struct glyph_string
*s
;
3156 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3157 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3161 height
= s
->height
- 2 * box_line_vwidth
;
3164 /* Fill background with face under the image. Do it only if row is
3165 taller than image or if image has a clip mask to reduce
3167 s
->stippled_p
= s
->face
->stipple
!= 0;
3168 if (height
> s
->slice
.height
3172 || s
->img
->pixmap
== 0
3173 || s
->width
!= s
->background_width
)
3176 if (s
->first_glyph
->left_box_line_p
3178 x
+= box_line_hwidth
;
3181 if (s
->slice
.y
== 0)
3182 y
+= box_line_vwidth
;
3184 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3186 s
->background_filled_p
= 1;
3189 /* Draw the foreground. */
3190 x_draw_image_foreground (s
);
3192 /* If we must draw a relief around the image, do it. */
3194 || s
->hl
== DRAW_IMAGE_RAISED
3195 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3196 x_draw_image_relief (s
);
3200 /* Draw stretch glyph string S. */
3203 x_draw_stretch_glyph_string (s
)
3204 struct glyph_string
*s
;
3206 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3207 s
->stippled_p
= s
->face
->stipple
!= 0;
3209 if (s
->hl
== DRAW_CURSOR
3210 && !x_stretch_cursor_p
)
3212 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3213 as wide as the stretch glyph. */
3214 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3217 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3219 /* Clear rest using the GC of the original non-cursor face. */
3220 if (width
< s
->background_width
)
3222 int x
= s
->x
+ width
, y
= s
->y
;
3223 int w
= s
->background_width
- width
, h
= s
->height
;
3227 if (s
->row
->mouse_face_p
3228 && cursor_in_mouse_face_p (s
->w
))
3230 x_set_mouse_face_gc (s
);
3236 get_glyph_string_clip_rect (s
, &r
);
3237 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3239 #if 0 /* MAC_TODO: stipple */
3240 if (s
->face
->stipple
)
3242 /* Fill background with a stipple pattern. */
3243 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3244 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3245 XSetFillStyle (s
->display
, gc
, FillSolid
);
3248 #endif /* MAC_TODO */
3249 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3252 else if (!s
->background_filled_p
)
3253 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3256 s
->background_filled_p
= 1;
3260 /* Draw glyph string S. */
3263 x_draw_glyph_string (s
)
3264 struct glyph_string
*s
;
3266 int relief_drawn_p
= 0;
3268 /* If S draws into the background of its successor that does not
3269 draw a cursor, draw the background of the successor first so that
3270 S can draw into it. This makes S->next use XDrawString instead
3271 of XDrawImageString. */
3272 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3273 && s
->next
->hl
!= DRAW_CURSOR
)
3275 xassert (s
->next
->img
== NULL
);
3276 x_set_glyph_string_gc (s
->next
);
3277 x_set_glyph_string_clipping (s
->next
);
3278 x_draw_glyph_string_background (s
->next
, 1);
3281 /* Set up S->gc, set clipping and draw S. */
3282 x_set_glyph_string_gc (s
);
3284 /* Draw relief (if any) in advance for char/composition so that the
3285 glyph string can be drawn over it. */
3286 if (!s
->for_overlaps
3287 && s
->face
->box
!= FACE_NO_BOX
3288 && (s
->first_glyph
->type
== CHAR_GLYPH
3289 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3292 x_set_glyph_string_clipping (s
);
3293 x_draw_glyph_string_background (s
, 1);
3294 x_draw_glyph_string_box (s
);
3295 x_set_glyph_string_clipping (s
);
3299 x_set_glyph_string_clipping (s
);
3301 switch (s
->first_glyph
->type
)
3304 x_draw_image_glyph_string (s
);
3308 x_draw_stretch_glyph_string (s
);
3312 if (s
->for_overlaps
)
3313 s
->background_filled_p
= 1;
3315 x_draw_glyph_string_background (s
, 0);
3316 x_draw_glyph_string_foreground (s
);
3319 case COMPOSITE_GLYPH
:
3320 if (s
->for_overlaps
|| s
->gidx
> 0)
3321 s
->background_filled_p
= 1;
3323 x_draw_glyph_string_background (s
, 1);
3324 x_draw_composite_glyph_string_foreground (s
);
3331 if (!s
->for_overlaps
)
3333 /* Draw underline. */
3334 if (s
->face
->underline_p
)
3336 unsigned long h
= 1;
3337 unsigned long dy
= s
->height
- h
;
3339 if (s
->face
->underline_defaulted_p
)
3340 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3345 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3346 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3347 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3349 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3353 /* Draw overline. */
3354 if (s
->face
->overline_p
)
3356 unsigned long dy
= 0, h
= 1;
3358 if (s
->face
->overline_color_defaulted_p
)
3359 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3364 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3365 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3366 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3368 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3372 /* Draw strike-through. */
3373 if (s
->face
->strike_through_p
)
3375 unsigned long h
= 1;
3376 unsigned long dy
= (s
->height
- h
) / 2;
3378 if (s
->face
->strike_through_color_defaulted_p
)
3379 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3384 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3385 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3386 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3388 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3392 /* Draw relief if not yet drawn. */
3393 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3394 x_draw_glyph_string_box (s
);
3397 /* Reset clipping. */
3398 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3401 /* Shift display to make room for inserted glyphs. */
3404 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3406 int x
, y
, width
, height
, shift_by
;
3408 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3409 x
, y
, width
, height
,
3413 /* Delete N glyphs at the nominal cursor position. Not implemented
3424 /* Clear entire frame. If updating_frame is non-null, clear that
3425 frame. Otherwise clear the selected frame. */
3435 f
= SELECTED_FRAME ();
3437 /* Clearing the frame will erase any cursor, so mark them all as no
3439 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3440 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3441 output_cursor
.x
= -1;
3443 /* We don't set the output cursor here because there will always
3444 follow an explicit cursor_to. */
3446 mac_clear_window (f
);
3448 /* We have to clear the scroll bars, too. If we have changed
3449 colors or something like that, then they should be notified. */
3450 x_scroll_bar_clear (f
);
3452 XFlush (FRAME_MAC_DISPLAY (f
));
3458 /* Invert the middle quarter of the frame for .15 sec. */
3460 /* We use the select system call to do the waiting, so we have to make
3461 sure it's available. If it isn't, we just won't do visual bells. */
3463 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3466 /* Subtract the `struct timeval' values X and Y, storing the result in
3467 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3470 timeval_subtract (result
, x
, y
)
3471 struct timeval
*result
, x
, y
;
3473 /* Perform the carry for the later subtraction by updating y. This
3474 is safer because on some systems the tv_sec member is unsigned. */
3475 if (x
.tv_usec
< y
.tv_usec
)
3477 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3478 y
.tv_usec
-= 1000000 * nsec
;
3482 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3484 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3485 y
.tv_usec
+= 1000000 * nsec
;
3489 /* Compute the time remaining to wait. tv_usec is certainly
3491 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3492 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3494 /* Return indication of whether the result should be considered
3496 return x
.tv_sec
< y
.tv_sec
;
3503 /* Get the height not including a menu bar widget. */
3504 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3505 /* Height of each line to flash. */
3506 int flash_height
= FRAME_LINE_HEIGHT (f
);
3507 /* These will be the left and right margins of the rectangles. */
3508 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3509 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3513 /* Don't flash the area between a scroll bar and the frame
3514 edge it is next to. */
3515 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3517 case vertical_scroll_bar_left
:
3518 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3521 case vertical_scroll_bar_right
:
3522 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3529 width
= flash_right
- flash_left
;
3533 /* If window is tall, flash top and bottom line. */
3534 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3536 mac_invert_rectangle (f
, flash_left
,
3537 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3538 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3539 width
, flash_height
);
3540 mac_invert_rectangle (f
, flash_left
,
3541 (height
- flash_height
3542 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3543 width
, flash_height
);
3546 /* If it is short, flash it all. */
3547 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3548 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3553 struct timeval wakeup
;
3555 EMACS_GET_TIME (wakeup
);
3557 /* Compute time to wait until, propagating carry from usecs. */
3558 wakeup
.tv_usec
+= 150000;
3559 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3560 wakeup
.tv_usec
%= 1000000;
3562 /* Keep waiting until past the time wakeup or any input gets
3564 while (! detect_input_pending ())
3566 struct timeval current
;
3567 struct timeval timeout
;
3569 EMACS_GET_TIME (current
);
3571 /* Break if result would be negative. */
3572 if (timeval_subtract (¤t
, wakeup
, current
))
3575 /* How long `select' should wait. */
3577 timeout
.tv_usec
= 10000;
3579 /* Try to wait that long--but we might wake up sooner. */
3580 select (0, NULL
, NULL
, NULL
, &timeout
);
3584 /* If window is tall, flash top and bottom line. */
3585 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3587 mac_invert_rectangle (f
, flash_left
,
3588 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3589 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3590 width
, flash_height
);
3591 mac_invert_rectangle (f
, flash_left
,
3592 (height
- flash_height
3593 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3594 width
, flash_height
);
3597 /* If it is short, flash it all. */
3598 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3599 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3606 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3609 /* Make audible bell. */
3614 struct frame
*f
= SELECTED_FRAME ();
3616 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3624 XFlush (FRAME_MAC_DISPLAY (f
));
3630 /* Specify how many text lines, from the top of the window,
3631 should be affected by insert-lines and delete-lines operations.
3632 This, and those operations, are used only within an update
3633 that is bounded by calls to x_update_begin and x_update_end. */
3636 XTset_terminal_window (n
)
3639 /* This function intentionally left blank. */
3644 /***********************************************************************
3646 ***********************************************************************/
3648 /* Perform an insert-lines or delete-lines operation, inserting N
3649 lines or deleting -N lines at vertical position VPOS. */
3652 x_ins_del_lines (vpos
, n
)
3659 /* Scroll part of the display as described by RUN. */
3662 x_scroll_run (w
, run
)
3666 struct frame
*f
= XFRAME (w
->frame
);
3667 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3669 /* Get frame-relative bounding box of the text display area of W,
3670 without mode lines. Include in this box the left and right
3672 window_box (w
, -1, &x
, &y
, &width
, &height
);
3674 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3675 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3676 bottom_y
= y
+ height
;
3680 /* Scrolling up. Make sure we don't copy part of the mode
3681 line at the bottom. */
3682 if (from_y
+ run
->height
> bottom_y
)
3683 height
= bottom_y
- from_y
;
3685 height
= run
->height
;
3689 /* Scolling down. Make sure we don't copy over the mode line.
3691 if (to_y
+ run
->height
> bottom_y
)
3692 height
= bottom_y
- to_y
;
3694 height
= run
->height
;
3699 /* Cursor off. Will be switched on again in x_update_window_end. */
3703 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3713 /***********************************************************************
3715 ***********************************************************************/
3723 ControlRef root_control
;
3726 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3728 ActivateControl (root_control
);
3730 x_update_cursor (f
, 1);
3734 frame_unhighlight (f
)
3738 ControlRef root_control
;
3741 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3743 DeactivateControl (root_control
);
3745 x_update_cursor (f
, 1);
3748 /* The focus has changed. Update the frames as necessary to reflect
3749 the new situation. Note that we can't change the selected frame
3750 here, because the Lisp code we are interrupting might become confused.
3751 Each event gets marked with the frame in which it occurred, so the
3752 Lisp code can tell when the switch took place by examining the events. */
3755 x_new_focus_frame (dpyinfo
, frame
)
3756 struct x_display_info
*dpyinfo
;
3757 struct frame
*frame
;
3759 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3761 if (frame
!= dpyinfo
->x_focus_frame
)
3763 /* Set this before calling other routines, so that they see
3764 the correct value of x_focus_frame. */
3765 dpyinfo
->x_focus_frame
= frame
;
3767 if (old_focus
&& old_focus
->auto_lower
)
3768 x_lower_frame (old_focus
);
3771 selected_frame
= frame
;
3772 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3774 Fselect_window (selected_frame
->selected_window
, Qnil
);
3775 choose_minibuf_frame ();
3778 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3779 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3781 pending_autoraise_frame
= 0;
3784 x_frame_rehighlight (dpyinfo
);
3787 /* Handle FocusIn and FocusOut state changes for FRAME.
3788 If FRAME has focus and there exists more than one frame, puts
3789 a FOCUS_IN_EVENT into *BUFP. */
3792 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3794 struct mac_display_info
*dpyinfo
;
3795 struct frame
*frame
;
3796 struct input_event
*bufp
;
3798 if (type
== activeFlag
)
3800 if (dpyinfo
->x_focus_event_frame
!= frame
)
3802 x_new_focus_frame (dpyinfo
, frame
);
3803 dpyinfo
->x_focus_event_frame
= frame
;
3805 /* Don't stop displaying the initial startup message
3806 for a switch-frame event we don't need. */
3807 if (GC_NILP (Vterminal_frame
)
3808 && GC_CONSP (Vframe_list
)
3809 && !GC_NILP (XCDR (Vframe_list
)))
3811 bufp
->kind
= FOCUS_IN_EVENT
;
3812 XSETFRAME (bufp
->frame_or_window
, frame
);
3818 if (dpyinfo
->x_focus_event_frame
== frame
)
3820 dpyinfo
->x_focus_event_frame
= 0;
3821 x_new_focus_frame (dpyinfo
, 0);
3826 /* The focus may have changed. Figure out if it is a real focus change,
3827 by checking both FocusIn/Out and Enter/LeaveNotify events.
3829 Returns FOCUS_IN_EVENT event in *BUFP. */
3832 x_detect_focus_change (dpyinfo
, event
, bufp
)
3833 struct mac_display_info
*dpyinfo
;
3835 struct input_event
*bufp
;
3837 struct frame
*frame
;
3839 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3843 /* On Mac, this is only called from focus events, so no switch needed. */
3844 mac_focus_changed ((event
->modifiers
& activeFlag
),
3845 dpyinfo
, frame
, bufp
);
3849 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3852 x_mouse_leave (dpyinfo
)
3853 struct x_display_info
*dpyinfo
;
3855 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3858 /* The focus has changed, or we have redirected a frame's focus to
3859 another frame (this happens when a frame uses a surrogate
3860 mini-buffer frame). Shift the highlight as appropriate.
3862 The FRAME argument doesn't necessarily have anything to do with which
3863 frame is being highlighted or un-highlighted; we only use it to find
3864 the appropriate X display info. */
3867 XTframe_rehighlight (frame
)
3868 struct frame
*frame
;
3870 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3874 x_frame_rehighlight (dpyinfo
)
3875 struct x_display_info
*dpyinfo
;
3877 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3879 if (dpyinfo
->x_focus_frame
)
3881 dpyinfo
->x_highlight_frame
3882 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3883 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3884 : dpyinfo
->x_focus_frame
);
3885 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3887 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3888 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3892 dpyinfo
->x_highlight_frame
= 0;
3894 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3897 frame_unhighlight (old_highlight
);
3898 if (dpyinfo
->x_highlight_frame
)
3899 frame_highlight (dpyinfo
->x_highlight_frame
);
3905 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3907 #if 0 /* MAC_TODO */
3908 /* Initialize mode_switch_bit and modifier_meaning. */
3910 x_find_modifier_meanings (dpyinfo
)
3911 struct x_display_info
*dpyinfo
;
3913 int min_code
, max_code
;
3916 XModifierKeymap
*mods
;
3918 dpyinfo
->meta_mod_mask
= 0;
3919 dpyinfo
->shift_lock_mask
= 0;
3920 dpyinfo
->alt_mod_mask
= 0;
3921 dpyinfo
->super_mod_mask
= 0;
3922 dpyinfo
->hyper_mod_mask
= 0;
3925 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3927 min_code
= dpyinfo
->display
->min_keycode
;
3928 max_code
= dpyinfo
->display
->max_keycode
;
3931 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3932 min_code
, max_code
- min_code
+ 1,
3934 mods
= XGetModifierMapping (dpyinfo
->display
);
3936 /* Scan the modifier table to see which modifier bits the Meta and
3937 Alt keysyms are on. */
3939 int row
, col
; /* The row and column in the modifier table. */
3941 for (row
= 3; row
< 8; row
++)
3942 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3945 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3947 /* Zeroes are used for filler. Skip them. */
3951 /* Are any of this keycode's keysyms a meta key? */
3955 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3957 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3963 dpyinfo
->meta_mod_mask
|= (1 << row
);
3968 dpyinfo
->alt_mod_mask
|= (1 << row
);
3973 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3978 dpyinfo
->super_mod_mask
|= (1 << row
);
3982 /* Ignore this if it's not on the lock modifier. */
3983 if ((1 << row
) == LockMask
)
3984 dpyinfo
->shift_lock_mask
= LockMask
;
3992 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3993 if (! dpyinfo
->meta_mod_mask
)
3995 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3996 dpyinfo
->alt_mod_mask
= 0;
3999 /* If some keys are both alt and meta,
4000 make them just meta, not alt. */
4001 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
4003 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
4006 XFree ((char *) syms
);
4007 XFreeModifiermap (mods
);
4010 #endif /* MAC_TODO */
4012 /* Convert between the modifier bits X uses and the modifier bits
4016 x_mac_to_emacs_modifiers (dpyinfo
, state
)
4017 struct x_display_info
*dpyinfo
;
4018 unsigned short state
;
4020 return (((state
& shiftKey
) ? shift_modifier
: 0)
4021 | ((state
& controlKey
) ? ctrl_modifier
: 0)
4022 | ((state
& cmdKey
) ? meta_modifier
: 0)
4023 | ((state
& optionKey
) ? alt_modifier
: 0));
4026 #if 0 /* MAC_TODO */
4027 static unsigned short
4028 x_emacs_to_x_modifiers (dpyinfo
, state
)
4029 struct x_display_info
*dpyinfo
;
4032 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
4033 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
4034 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
4035 | ((state
& shift_modifier
) ? ShiftMask
: 0)
4036 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
4037 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
4039 #endif /* MAC_TODO */
4041 /* Convert a keysym to its name. */
4044 x_get_keysym_name (keysym
)
4051 value
= XKeysymToString (keysym
);
4062 /* Function to report a mouse movement to the mainstream Emacs code.
4063 The input handler calls this.
4065 We have received a mouse movement event, which is given in *event.
4066 If the mouse is over a different glyph than it was last time, tell
4067 the mainstream emacs code by setting mouse_moved. If not, ask for
4068 another motion event, so we can check again the next time it moves. */
4070 static Point last_mouse_motion_position
;
4071 static Lisp_Object last_mouse_motion_frame
;
4074 note_mouse_movement (frame
, pos
)
4078 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4079 #if TARGET_API_MAC_CARBON
4083 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4084 last_mouse_motion_position
= *pos
;
4085 XSETFRAME (last_mouse_motion_frame
, frame
);
4087 #if TARGET_API_MAC_CARBON
4088 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4090 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4093 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4094 /* This case corresponds to LeaveNotify in X11. */
4096 /* If we move outside the frame, then we're certainly no
4097 longer on any text in the frame. */
4098 clear_mouse_face (dpyinfo
);
4099 dpyinfo
->mouse_face_mouse_frame
= 0;
4100 if (!dpyinfo
->grabbed
)
4101 rif
->define_frame_cursor (frame
,
4102 frame
->output_data
.mac
->nontext_cursor
);
4106 /* Has the mouse moved off the glyph it was on at the last sighting? */
4107 if (frame
!= last_mouse_glyph_frame
4108 || !PtInRect (*pos
, &last_mouse_glyph
))
4110 frame
->mouse_moved
= 1;
4111 last_mouse_scroll_bar
= Qnil
;
4112 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4113 /* Remember which glyph we're now on. */
4114 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4115 last_mouse_glyph_frame
= frame
;
4123 /************************************************************************
4125 ************************************************************************/
4127 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4130 redo_mouse_highlight ()
4132 if (!NILP (last_mouse_motion_frame
)
4133 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4134 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4135 last_mouse_motion_position
.h
,
4136 last_mouse_motion_position
.v
);
4140 static struct frame
*
4141 mac_focus_frame (dpyinfo
)
4142 struct mac_display_info
*dpyinfo
;
4144 if (dpyinfo
->x_focus_frame
)
4145 return dpyinfo
->x_focus_frame
;
4147 /* Mac version may get events, such as a menu bar click, even when
4148 all the frames are invisible. In this case, we regard the
4149 event came to the selected frame. */
4150 return SELECTED_FRAME ();
4154 /* Return the current position of the mouse.
4155 *FP should be a frame which indicates which display to ask about.
4157 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4158 and *PART to the frame, window, and scroll bar part that the mouse
4159 is over. Set *X and *Y to the portion and whole of the mouse's
4160 position on the scroll bar.
4162 If the mouse movement started elsewhere, set *FP to the frame the
4163 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4166 Set *TIME to the server time-stamp for the time at which the mouse
4167 was at this position.
4169 Don't store anything if we don't have a valid set of values to report.
4171 This clears the mouse_moved flag, so we can wait for the next mouse
4175 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4178 Lisp_Object
*bar_window
;
4179 enum scroll_bar_part
*part
;
4181 unsigned long *time
;
4187 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4188 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4191 Lisp_Object frame
, tail
;
4193 /* Clear the mouse-moved flag for every frame on this display. */
4194 FOR_EACH_FRAME (tail
, frame
)
4195 XFRAME (frame
)->mouse_moved
= 0;
4197 last_mouse_scroll_bar
= Qnil
;
4199 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4200 && FRAME_LIVE_P (last_mouse_frame
))
4201 f1
= last_mouse_frame
;
4203 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4207 /* Ok, we found a frame. Store all the values.
4208 last_mouse_glyph is a rectangle used to reduce the
4209 generation of mouse events. To not miss any motion
4210 events, we must divide the frame into rectangles of the
4211 size of the smallest character that could be displayed
4212 on it, i.e. into the same rectangles that matrices on
4213 the frame are divided into. */
4216 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4217 GetMouse (&mouse_pos
);
4218 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4220 last_mouse_glyph_frame
= f1
;
4225 XSETINT (*x
, mouse_pos
.h
);
4226 XSETINT (*y
, mouse_pos
.v
);
4227 *time
= last_mouse_movement_time
;
4235 /************************************************************************
4237 ************************************************************************/
4239 #ifdef USE_TOOLKIT_SCROLL_BARS
4241 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4242 static OSStatus install_scroll_bar_timer
P_ ((void));
4243 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4244 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4245 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4246 struct input_event
*));
4247 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4249 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4251 struct input_event
*));
4252 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4253 struct input_event
*));
4254 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4255 Point
, struct input_event
*));
4256 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4259 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4261 static int last_scroll_bar_part
;
4263 static EventLoopTimerRef scroll_bar_timer
;
4265 static int scroll_bar_timer_event_posted_p
;
4267 #define SCROLL_BAR_FIRST_DELAY 0.5
4268 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4271 scroll_bar_timer_callback (timer
, data
)
4272 EventLoopTimerRef timer
;
4275 EventRef event
= NULL
;
4278 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4279 kEventAttributeNone
, &event
);
4284 GetMouse (&mouse_pos
);
4285 LocalToGlobal (&mouse_pos
);
4286 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4287 sizeof (Point
), &mouse_pos
);
4291 UInt32 modifiers
= GetCurrentKeyModifiers ();
4293 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4294 sizeof (UInt32
), &modifiers
);
4297 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4298 kEventPriorityStandard
);
4300 scroll_bar_timer_event_posted_p
= 1;
4303 ReleaseEvent (event
);
4307 install_scroll_bar_timer ()
4309 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4311 if (scroll_bar_timer_callbackUPP
== NULL
)
4312 scroll_bar_timer_callbackUPP
=
4313 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4315 if (scroll_bar_timer
== NULL
)
4316 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4317 kEventDurationForever as delays. */
4319 InstallEventLoopTimer (GetCurrentEventLoop (),
4320 kEventDurationForever
, kEventDurationForever
,
4321 scroll_bar_timer_callbackUPP
, NULL
,
4326 set_scroll_bar_timer (delay
)
4327 EventTimerInterval delay
;
4329 if (scroll_bar_timer
== NULL
)
4330 install_scroll_bar_timer ();
4332 scroll_bar_timer_event_posted_p
= 0;
4334 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4338 control_part_code_to_scroll_bar_part (part_code
)
4339 ControlPartCode part_code
;
4343 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4344 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4345 case kControlPageUpPart
: return scroll_bar_above_handle
;
4346 case kControlPageDownPart
: return scroll_bar_below_handle
;
4347 case kControlIndicatorPart
: return scroll_bar_handle
;
4354 construct_scroll_bar_click (bar
, part
, bufp
)
4355 struct scroll_bar
*bar
;
4357 struct input_event
*bufp
;
4359 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4360 bufp
->frame_or_window
= bar
->window
;
4364 XSETINT (bufp
->x
, 0);
4365 XSETINT (bufp
->y
, 0);
4366 bufp
->modifiers
= 0;
4370 get_control_part_bounds (ch
, part_code
, rect
)
4372 ControlPartCode part_code
;
4375 RgnHandle region
= NewRgn ();
4378 err
= GetControlRegion (ch
, part_code
, region
);
4380 GetRegionBounds (region
, rect
);
4381 DisposeRgn (region
);
4387 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4388 struct scroll_bar
*bar
;
4389 ControlPartCode part_code
;
4390 struct input_event
*bufp
;
4392 int part
= control_part_code_to_scroll_bar_part (part_code
);
4397 if (part
!= scroll_bar_handle
)
4399 construct_scroll_bar_click (bar
, part
, bufp
);
4400 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4401 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4404 last_scroll_bar_part
= part
;
4405 bar
->dragging
= Qnil
;
4406 tracked_scroll_bar
= bar
;
4410 x_scroll_bar_handle_release (bar
, bufp
)
4411 struct scroll_bar
*bar
;
4412 struct input_event
*bufp
;
4414 if (last_scroll_bar_part
!= scroll_bar_handle
4415 || !GC_NILP (bar
->dragging
))
4416 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4418 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4419 set_scroll_bar_timer (kEventDurationForever
);
4421 last_scroll_bar_part
= -1;
4422 bar
->dragging
= Qnil
;
4423 tracked_scroll_bar
= NULL
;
4427 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4429 struct scroll_bar
*bar
;
4431 struct input_event
*bufp
;
4433 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4435 if (last_scroll_bar_part
== scroll_bar_handle
)
4440 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4441 kControlIndicatorPart
, &r
);
4443 if (GC_NILP (bar
->dragging
))
4444 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4446 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4447 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4448 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4453 if (top
> top_range
)
4456 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4457 XSETINT (bufp
->x
, top
);
4458 XSETINT (bufp
->y
, top_range
);
4462 ControlPartCode part_code
;
4463 int unhilite_p
= 0, part
;
4465 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4469 part
= control_part_code_to_scroll_bar_part (part_code
);
4471 switch (last_scroll_bar_part
)
4473 case scroll_bar_above_handle
:
4474 case scroll_bar_below_handle
:
4475 if (part
!= scroll_bar_above_handle
4476 && part
!= scroll_bar_below_handle
)
4480 case scroll_bar_up_arrow
:
4481 case scroll_bar_down_arrow
:
4482 if (part
!= scroll_bar_up_arrow
4483 && part
!= scroll_bar_down_arrow
)
4490 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4491 else if (part
!= last_scroll_bar_part
4492 || scroll_bar_timer_event_posted_p
)
4494 construct_scroll_bar_click (bar
, part
, bufp
);
4495 last_scroll_bar_part
= part
;
4496 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4497 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4502 /* Set the thumb size and position of scroll bar BAR. We are currently
4503 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4506 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4507 struct scroll_bar
*bar
;
4508 int portion
, position
, whole
;
4510 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4512 int value
, viewsize
, maximum
;
4514 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4515 value
= 0, viewsize
= 1, maximum
= 0;
4520 maximum
= max (0, whole
- portion
);
4525 SetControl32BitMinimum (ch
, 0);
4526 SetControl32BitMaximum (ch
, maximum
);
4527 SetControl32BitValue (ch
, value
);
4528 SetControlViewSize (ch
, viewsize
);
4533 #endif /* USE_TOOLKIT_SCROLL_BARS */
4537 /************************************************************************
4538 Scroll bars, general
4539 ************************************************************************/
4541 /* Create a scroll bar and return the scroll bar vector for it. W is
4542 the Emacs window on which to create the scroll bar. TOP, LEFT,
4543 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4546 static struct scroll_bar
*
4547 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4549 int top
, left
, width
, height
, disp_top
, disp_height
;
4551 struct frame
*f
= XFRAME (w
->frame
);
4552 struct scroll_bar
*bar
4553 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4561 r
.right
= left
+ width
;
4562 r
.bottom
= disp_top
+ disp_height
;
4564 #if TARGET_API_MAC_CARBON
4565 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4566 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4568 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4569 0, 0, 0, scrollBarProc
, (long) bar
);
4571 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4573 XSETWINDOW (bar
->window
, w
);
4574 XSETINT (bar
->top
, top
);
4575 XSETINT (bar
->left
, left
);
4576 XSETINT (bar
->width
, width
);
4577 XSETINT (bar
->height
, height
);
4578 XSETINT (bar
->start
, 0);
4579 XSETINT (bar
->end
, 0);
4580 bar
->dragging
= Qnil
;
4581 #ifdef USE_TOOLKIT_SCROLL_BARS
4582 bar
->track_top
= Qnil
;
4583 bar
->track_height
= Qnil
;
4586 /* Add bar to its frame's list of scroll bars. */
4587 bar
->next
= FRAME_SCROLL_BARS (f
);
4589 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4590 if (!NILP (bar
->next
))
4591 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4598 /* Draw BAR's handle in the proper position.
4600 If the handle is already drawn from START to END, don't bother
4601 redrawing it, unless REBUILD is non-zero; in that case, always
4602 redraw it. (REBUILD is handy for drawing the handle after expose
4605 Normally, we want to constrain the start and end of the handle to
4606 fit inside its rectangle, but if the user is dragging the scroll
4607 bar handle, we want to let them drag it down all the way, so that
4608 the bar's top is as far down as it goes; otherwise, there's no way
4609 to move to the very end of the buffer. */
4611 #ifndef USE_TOOLKIT_SCROLL_BARS
4614 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4615 struct scroll_bar
*bar
;
4619 int dragging
= ! NILP (bar
->dragging
);
4620 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4621 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4622 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4623 int length
= end
- start
;
4625 /* If the display is already accurate, do nothing. */
4627 && start
== XINT (bar
->start
)
4628 && end
== XINT (bar
->end
))
4633 /* Make sure the values are reasonable, and try to preserve the
4634 distance between start and end. */
4637 else if (start
> top_range
)
4639 end
= start
+ length
;
4643 else if (end
> top_range
&& ! dragging
)
4646 /* Store the adjusted setting in the scroll bar. */
4647 XSETINT (bar
->start
, start
);
4648 XSETINT (bar
->end
, end
);
4650 /* Clip the end position, just for display. */
4651 if (end
> top_range
)
4654 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4655 top positions, to make sure the handle is always at least that
4656 many pixels tall. */
4657 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4659 SetControlMinimum (ch
, 0);
4660 /* Don't inadvertently activate deactivated scroll bars */
4661 if (GetControlMaximum (ch
) != -1)
4662 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4664 SetControlValue (ch
, start
);
4665 #if TARGET_API_MAC_CARBON
4666 SetControlViewSize (ch
, end
- start
);
4672 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4674 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4678 x_scroll_bar_remove (bar
)
4679 struct scroll_bar
*bar
;
4681 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4685 /* Destroy the Mac scroll bar control */
4686 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4688 /* Disassociate this scroll bar from its window. */
4689 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4695 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4696 that we are displaying PORTION characters out of a total of WHOLE
4697 characters, starting at POSITION. If WINDOW has no scroll bar,
4701 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4703 int portion
, whole
, position
;
4705 struct frame
*f
= XFRAME (w
->frame
);
4706 struct scroll_bar
*bar
;
4707 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4708 int window_y
, window_height
;
4710 /* Get window dimensions. */
4711 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4713 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4714 height
= window_height
;
4716 /* Compute the left edge of the scroll bar area. */
4717 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4719 /* Compute the width of the scroll bar which might be less than
4720 the width of the area reserved for the scroll bar. */
4721 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4722 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4726 /* Compute the left edge of the scroll bar. */
4727 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4730 sb_left
= left
+ width
- sb_width
;
4732 /* Adjustments according to Inside Macintosh to make it look nice */
4734 disp_height
= height
;
4740 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4746 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4749 /* Does the scroll bar exist yet? */
4750 if (NILP (w
->vertical_scroll_bar
))
4753 mac_clear_area (f
, left
, top
, width
, height
);
4755 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4757 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4761 /* It may just need to be moved and resized. */
4764 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4765 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4769 /* If already correctly positioned, do nothing. */
4770 if (!(XINT (bar
->left
) == sb_left
4771 && XINT (bar
->top
) == top
4772 && XINT (bar
->width
) == sb_width
4773 && XINT (bar
->height
) == height
))
4775 /* Since toolkit scroll bars are smaller than the space reserved
4776 for them on the frame, we have to clear "under" them. */
4777 mac_clear_area (f
, left
, top
, width
, height
);
4780 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4781 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4783 if (sb_width
< disp_height
)
4786 /* Remember new settings. */
4787 XSETINT (bar
->left
, sb_left
);
4788 XSETINT (bar
->top
, top
);
4789 XSETINT (bar
->width
, sb_width
);
4790 XSETINT (bar
->height
, height
);
4791 #ifdef USE_TOOLKIT_SCROLL_BARS
4792 bar
->track_top
= Qnil
;
4793 bar
->track_height
= Qnil
;
4800 #ifdef USE_TOOLKIT_SCROLL_BARS
4801 if (NILP (bar
->track_top
))
4803 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4808 SetControl32BitMinimum (ch
, 0);
4809 SetControl32BitMaximum (ch
, 1);
4810 SetControlViewSize (ch
, 1);
4812 /* Move the scroll bar thumb to the top. */
4813 SetControl32BitValue (ch
, 0);
4814 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4816 /* Move the scroll bar thumb to the bottom. */
4817 SetControl32BitValue (ch
, 1);
4818 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4820 UnionRect (&r0
, &r1
, &r0
);
4821 XSETINT (bar
->track_top
, r0
.top
);
4822 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4827 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4828 #else /* not USE_TOOLKIT_SCROLL_BARS */
4829 /* Set the scroll bar's current state, unless we're currently being
4831 if (NILP (bar
->dragging
))
4833 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4836 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4839 int start
= ((double) position
* top_range
) / whole
;
4840 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4841 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4844 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4848 /* The following three hooks are used when we're doing a thorough
4849 redisplay of the frame. We don't explicitly know which scroll bars
4850 are going to be deleted, because keeping track of when windows go
4851 away is a real pain - "Can you say set-window-configuration, boys
4852 and girls?" Instead, we just assert at the beginning of redisplay
4853 that *all* scroll bars are to be removed, and then save a scroll bar
4854 from the fiery pit when we actually redisplay its window. */
4856 /* Arrange for all scroll bars on FRAME to be removed at the next call
4857 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4858 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4861 XTcondemn_scroll_bars (frame
)
4864 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4865 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4868 bar
= FRAME_SCROLL_BARS (frame
);
4869 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4870 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4871 XSCROLL_BAR (bar
)->prev
= Qnil
;
4872 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4873 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4874 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4879 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4880 Note that WINDOW isn't necessarily condemned at all. */
4883 XTredeem_scroll_bar (window
)
4884 struct window
*window
;
4886 struct scroll_bar
*bar
;
4889 /* We can't redeem this window's scroll bar if it doesn't have one. */
4890 if (NILP (window
->vertical_scroll_bar
))
4893 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4895 /* Unlink it from the condemned list. */
4896 f
= XFRAME (WINDOW_FRAME (window
));
4897 if (NILP (bar
->prev
))
4899 /* If the prev pointer is nil, it must be the first in one of
4901 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4902 /* It's not condemned. Everything's fine. */
4904 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4905 window
->vertical_scroll_bar
))
4906 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4908 /* If its prev pointer is nil, it must be at the front of
4909 one or the other! */
4913 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4915 if (! NILP (bar
->next
))
4916 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4918 bar
->next
= FRAME_SCROLL_BARS (f
);
4920 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4921 if (! NILP (bar
->next
))
4922 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4925 /* Remove all scroll bars on FRAME that haven't been saved since the
4926 last call to `*condemn_scroll_bars_hook'. */
4929 XTjudge_scroll_bars (f
)
4932 Lisp_Object bar
, next
;
4934 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4936 /* Clear out the condemned list now so we won't try to process any
4937 more events on the hapless scroll bars. */
4938 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4940 for (; ! NILP (bar
); bar
= next
)
4942 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4944 x_scroll_bar_remove (b
);
4947 b
->next
= b
->prev
= Qnil
;
4950 /* Now there should be no references to the condemned scroll bars,
4951 and they should get garbage-collected. */
4955 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4956 is set to something other than NO_EVENT, it is enqueued.
4958 This may be called from a signal handler, so we have to ignore GC
4962 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4963 struct scroll_bar
*bar
;
4964 ControlPartCode part_code
;
4966 struct input_event
*bufp
;
4968 int win_y
, top_range
;
4970 if (! GC_WINDOWP (bar
->window
))
4973 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4974 bufp
->frame_or_window
= bar
->window
;
4977 bar
->dragging
= Qnil
;
4981 case kControlUpButtonPart
:
4982 bufp
->part
= scroll_bar_up_arrow
;
4984 case kControlDownButtonPart
:
4985 bufp
->part
= scroll_bar_down_arrow
;
4987 case kControlPageUpPart
:
4988 bufp
->part
= scroll_bar_above_handle
;
4990 case kControlPageDownPart
:
4991 bufp
->part
= scroll_bar_below_handle
;
4993 #if TARGET_API_MAC_CARBON
4996 case kControlIndicatorPart
:
4998 if (er
->what
== mouseDown
)
4999 bar
->dragging
= make_number (0);
5000 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5001 bufp
->part
= scroll_bar_handle
;
5005 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5006 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5008 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5012 if (! NILP (bar
->dragging
))
5013 win_y
-= XINT (bar
->dragging
);
5017 if (win_y
> top_range
)
5020 XSETINT (bufp
->x
, win_y
);
5021 XSETINT (bufp
->y
, top_range
);
5024 #ifndef USE_TOOLKIT_SCROLL_BARS
5026 /* Handle some mouse motion while someone is dragging the scroll bar.
5028 This may be called from a signal handler, so we have to ignore GC
5032 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5033 struct scroll_bar
*bar
;
5037 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5039 last_mouse_movement_time
= t
;
5042 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5044 /* If we're dragging the bar, display it. */
5045 if (! GC_NILP (bar
->dragging
))
5047 /* Where should the handle be now? */
5048 int new_start
= y_pos
- 24;
5050 if (new_start
!= XINT (bar
->start
))
5052 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5054 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5059 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5061 /* Return information to the user about the current position of the mouse
5062 on the scroll bar. */
5065 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5067 Lisp_Object
*bar_window
;
5068 enum scroll_bar_part
*part
;
5070 unsigned long *time
;
5072 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5073 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5074 #if TARGET_API_MAC_CARBON
5075 WindowPtr wp
= GetControlOwner (ch
);
5077 WindowPtr wp
= (*ch
)->contrlOwner
;
5080 struct frame
*f
= mac_window_to_frame (wp
);
5081 int win_y
, top_range
;
5083 SetPortWindowPort (wp
);
5085 GetMouse (&mouse_pos
);
5087 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5088 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5090 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5094 if (! NILP (bar
->dragging
))
5095 win_y
-= XINT (bar
->dragging
);
5099 if (win_y
> top_range
)
5103 *bar_window
= bar
->window
;
5105 if (! NILP (bar
->dragging
))
5106 *part
= scroll_bar_handle
;
5107 else if (win_y
< XINT (bar
->start
))
5108 *part
= scroll_bar_above_handle
;
5109 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5110 *part
= scroll_bar_handle
;
5112 *part
= scroll_bar_below_handle
;
5114 XSETINT (*x
, win_y
);
5115 XSETINT (*y
, top_range
);
5118 last_mouse_scroll_bar
= Qnil
;
5120 *time
= last_mouse_movement_time
;
5124 /* The screen has been cleared so we may have changed foreground or
5125 background colors, and the scroll bars may need to be redrawn.
5126 Clear out the scroll bars, and ask for expose events, so we can
5130 x_scroll_bar_clear (f
)
5133 XTcondemn_scroll_bars (f
);
5134 XTjudge_scroll_bars (f
);
5138 /***********************************************************************
5140 ***********************************************************************/
5142 /* Set clipping for output in glyph row ROW. W is the window in which
5143 we operate. GC is the graphics context to set clipping in.
5145 ROW may be a text row or, e.g., a mode line. Text rows must be
5146 clipped to the interior of the window dedicated to text display,
5147 mode lines must be clipped to the whole window. */
5150 x_clip_to_row (w
, row
, area
, gc
)
5152 struct glyph_row
*row
;
5156 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5158 int window_x
, window_y
, window_width
;
5160 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5162 clip_rect
.left
= window_x
;
5163 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5164 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5165 clip_rect
.right
= clip_rect
.left
+ window_width
;
5166 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5168 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5172 /* Draw a hollow box cursor on window W in glyph row ROW. */
5175 x_draw_hollow_cursor (w
, row
)
5177 struct glyph_row
*row
;
5179 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5180 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5181 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5184 struct glyph
*cursor_glyph
;
5187 /* Get the glyph the cursor is on. If we can't tell because
5188 the current matrix is invalid or such, give up. */
5189 cursor_glyph
= get_phys_cursor_glyph (w
);
5190 if (cursor_glyph
== NULL
)
5193 /* Compute frame-relative coordinates for phys cursor. */
5194 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5195 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5196 wd
= w
->phys_cursor_width
;
5198 /* The foreground of cursor_gc is typically the same as the normal
5199 background color, which can cause the cursor box to be invisible. */
5200 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5201 if (dpyinfo
->scratch_cursor_gc
)
5202 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5204 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5205 GCForeground
, &xgcv
);
5206 gc
= dpyinfo
->scratch_cursor_gc
;
5208 /* Set clipping, draw the rectangle, and reset clipping again. */
5209 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5210 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
);
5211 mac_reset_clip_rectangles (dpy
, gc
);
5215 /* Draw a bar cursor on window W in glyph row ROW.
5217 Implementation note: One would like to draw a bar cursor with an
5218 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5219 Unfortunately, I didn't find a font yet that has this property set.
5223 x_draw_bar_cursor (w
, row
, width
, kind
)
5225 struct glyph_row
*row
;
5227 enum text_cursor_kinds kind
;
5229 struct frame
*f
= XFRAME (w
->frame
);
5230 struct glyph
*cursor_glyph
;
5232 /* If cursor is out of bounds, don't draw garbage. This can happen
5233 in mini-buffer windows when switching between echo area glyphs
5235 cursor_glyph
= get_phys_cursor_glyph (w
);
5236 if (cursor_glyph
== NULL
)
5239 /* If on an image, draw like a normal cursor. That's usually better
5240 visible than drawing a bar, esp. if the image is large so that
5241 the bar might not be in the window. */
5242 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5244 struct glyph_row
*row
;
5245 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5246 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5250 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5251 Window window
= FRAME_MAC_WINDOW (f
);
5252 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5253 unsigned long mask
= GCForeground
| GCBackground
;
5254 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5257 /* If the glyph's background equals the color we normally draw
5258 the bar cursor in, the bar cursor in its normal color is
5259 invisible. Use the glyph's foreground color instead in this
5260 case, on the assumption that the glyph's colors are chosen so
5261 that the glyph is legible. */
5262 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5263 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5265 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5268 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5271 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5272 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5276 width
= FRAME_CURSOR_WIDTH (f
);
5277 width
= min (cursor_glyph
->pixel_width
, width
);
5279 w
->phys_cursor_width
= width
;
5280 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5282 if (kind
== BAR_CURSOR
)
5283 mac_fill_rectangle (f
, gc
,
5284 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5285 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5286 width
, row
->height
);
5288 mac_fill_rectangle (f
, gc
,
5289 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5290 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5291 row
->height
- width
),
5292 cursor_glyph
->pixel_width
,
5295 mac_reset_clip_rectangles (dpy
, gc
);
5300 /* RIF: Define cursor CURSOR on frame F. */
5303 mac_define_frame_cursor (f
, cursor
)
5307 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5309 if (dpyinfo
->x_focus_frame
== f
)
5310 SetThemeCursor (cursor
);
5314 /* RIF: Clear area on frame F. */
5317 mac_clear_frame_area (f
, x
, y
, width
, height
)
5319 int x
, y
, width
, height
;
5321 mac_clear_area (f
, x
, y
, width
, height
);
5325 /* RIF: Draw cursor on window W. */
5328 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5330 struct glyph_row
*glyph_row
;
5332 int cursor_type
, cursor_width
;
5337 w
->phys_cursor_type
= cursor_type
;
5338 w
->phys_cursor_on_p
= 1;
5340 if (glyph_row
->exact_window_width_line_p
5341 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5343 glyph_row
->cursor_in_fringe_p
= 1;
5344 draw_fringe_bitmap (w
, glyph_row
, 0);
5347 switch (cursor_type
)
5349 case HOLLOW_BOX_CURSOR
:
5350 x_draw_hollow_cursor (w
, glyph_row
);
5353 case FILLED_BOX_CURSOR
:
5354 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5358 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5362 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5366 w
->phys_cursor_width
= 0;
5378 #if 0 /* MAC_TODO: no icon support yet. */
5380 x_bitmap_icon (f
, icon
)
5386 if (FRAME_W32_WINDOW (f
) == 0)
5390 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5391 else if (STRINGP (icon
))
5392 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5393 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5394 else if (SYMBOLP (icon
))
5398 if (EQ (icon
, intern ("application")))
5399 name
= (LPCTSTR
) IDI_APPLICATION
;
5400 else if (EQ (icon
, intern ("hand")))
5401 name
= (LPCTSTR
) IDI_HAND
;
5402 else if (EQ (icon
, intern ("question")))
5403 name
= (LPCTSTR
) IDI_QUESTION
;
5404 else if (EQ (icon
, intern ("exclamation")))
5405 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5406 else if (EQ (icon
, intern ("asterisk")))
5407 name
= (LPCTSTR
) IDI_ASTERISK
;
5408 else if (EQ (icon
, intern ("winlogo")))
5409 name
= (LPCTSTR
) IDI_WINLOGO
;
5413 hicon
= LoadIcon (NULL
, name
);
5421 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5426 #endif /* MAC_TODO */
5428 /************************************************************************
5430 ************************************************************************/
5432 /* Display Error Handling functions not used on W32. Listing them here
5433 helps diff stay in step when comparing w32term.c with xterm.c.
5435 x_error_catcher (display, error)
5436 x_catch_errors (dpy)
5437 x_catch_errors_unwind (old_val)
5438 x_check_errors (dpy, format)
5439 x_had_errors_p (dpy)
5440 x_clear_errors (dpy)
5441 x_uncatch_errors (dpy, count)
5443 x_connection_signal (signalnum)
5444 x_connection_closed (dpy, error_message)
5445 x_error_quitter (display, error)
5446 x_error_handler (display, error)
5447 x_io_error_quitter (display)
5452 /* Changing the font of the frame. */
5454 /* Give frame F the font named FONTNAME as its default font, and
5455 return the full name of that font. FONTNAME may be a wildcard
5456 pattern; in that case, we choose some font that fits the pattern.
5457 The return value shows which font we chose. */
5460 x_new_font (f
, fontname
)
5462 register char *fontname
;
5464 struct font_info
*fontp
5465 = FS_LOAD_FONT (f
, fontname
);
5470 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
5471 /* This font is already set in frame F. There's nothing more to
5473 return build_string (fontp
->full_name
);
5475 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5476 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5477 FRAME_FONTSET (f
) = -1;
5479 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5480 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5481 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5483 compute_fringe_widths (f
, 1);
5485 /* Compute the scroll bar width in character columns. */
5486 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5488 int wid
= FRAME_COLUMN_WIDTH (f
);
5489 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5490 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5494 int wid
= FRAME_COLUMN_WIDTH (f
);
5495 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5498 /* Now make the frame display the given font. */
5499 if (FRAME_MAC_WINDOW (f
) != 0)
5501 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5503 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5505 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5508 /* Don't change the size of a tip frame; there's no point in
5509 doing it because it's done in Fx_show_tip, and it leads to
5510 problems because the tip frame has no widget. */
5511 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5512 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5515 return build_string (fontp
->full_name
);
5518 /* Give frame F the fontset named FONTSETNAME as its default fontset,
5519 and return the full name of that fontset. FONTSETNAME may be a
5520 wildcard pattern; in that case, we choose some fontset that fits
5521 the pattern. FONTSETNAME may be a font name for ASCII characters;
5522 in that case, we create a fontset from that font name.
5524 The return value shows which fontset we chose.
5525 If FONTSETNAME specifies the default fontset, return Qt.
5526 If an ASCII font in the specified fontset can't be loaded, return
5530 x_new_fontset (f
, fontsetname
)
5532 Lisp_Object fontsetname
;
5534 int fontset
= fs_query_fontset (fontsetname
, 0);
5537 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
5538 /* This fontset is already set in frame F. There's nothing more
5540 return fontset_name (fontset
);
5541 else if (fontset
== 0)
5542 /* The default fontset can't be the default font. */
5546 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5548 result
= x_new_font (f
, SDATA (fontsetname
));
5550 if (!STRINGP (result
))
5551 /* Can't load ASCII font. */
5555 fontset
= new_fontset_from_font_name (result
);
5557 /* Since x_new_font doesn't update any fontset information, do it now. */
5558 FRAME_FONTSET (f
) = fontset
;
5560 return fontset_name (fontset
);
5564 /***********************************************************************
5565 TODO: W32 Input Methods
5566 ***********************************************************************/
5567 /* Listing missing functions from xterm.c helps diff stay in step.
5569 xim_destroy_callback (xim, client_data, call_data)
5570 xim_open_dpy (dpyinfo, resource_name)
5572 xim_instantiate_callback (display, client_data, call_data)
5573 xim_initialize (dpyinfo, resource_name)
5574 xim_close_dpy (dpyinfo)
5580 mac_get_window_bounds (f
, inner
, outer
)
5582 Rect
*inner
, *outer
;
5584 #if TARGET_API_MAC_CARBON
5585 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5586 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5587 #else /* not TARGET_API_MAC_CARBON */
5588 RgnHandle region
= NewRgn ();
5590 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5591 *inner
= (*region
)->rgnBBox
;
5592 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5593 *outer
= (*region
)->rgnBBox
;
5594 DisposeRgn (region
);
5595 #endif /* not TARGET_API_MAC_CARBON */
5600 /* Calculate the absolute position in frame F
5601 from its current recorded position values and gravity. */
5604 x_calc_absolute_position (f
)
5607 int width_diff
= 0, height_diff
= 0;
5608 int flags
= f
->size_hint_flags
;
5611 /* We have nothing to do if the current position
5612 is already for the top-left corner. */
5613 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5616 /* Find the offsets of the outside upper-left corner of
5617 the inner window, with respect to the outer window. */
5618 mac_get_window_bounds (f
, &inner
, &outer
);
5620 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5621 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5623 /* Treat negative positions as relative to the leftmost bottommost
5624 position that fits on the screen. */
5625 if (flags
& XNegative
)
5626 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5628 - FRAME_PIXEL_WIDTH (f
)
5631 if (flags
& YNegative
)
5632 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5634 - FRAME_PIXEL_HEIGHT (f
)
5637 /* The left_pos and top_pos
5638 are now relative to the top and left screen edges,
5639 so the flags should correspond. */
5640 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5643 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5644 to really change the position, and 0 when calling from
5645 x_make_frame_visible (in that case, XOFF and YOFF are the current
5646 position values). It is -1 when calling from x_set_frame_parameters,
5647 which means, do adjust for borders but don't change the gravity. */
5650 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5652 register int xoff
, yoff
;
5655 if (change_gravity
> 0)
5659 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5661 f
->size_hint_flags
|= XNegative
;
5663 f
->size_hint_flags
|= YNegative
;
5664 f
->win_gravity
= NorthWestGravity
;
5666 x_calc_absolute_position (f
);
5669 x_wm_set_size_hint (f
, (long) 0, 0);
5671 #if TARGET_API_MAC_CARBON
5672 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5673 /* If the title bar is completely outside the screen, adjust the
5675 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5676 kWindowConstrainMoveRegardlessOfFit
5677 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5678 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5681 Rect inner
, outer
, screen_rect
, dummy
;
5682 RgnHandle region
= NewRgn ();
5684 mac_get_window_bounds (f
, &inner
, &outer
);
5685 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5686 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5687 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5688 f
->top_pos
+ f
->y_pixels_diff
, false);
5690 /* If the title bar is completely outside the screen, adjust the
5691 position. The variable `outer' holds the title bar rectangle.
5692 The variable `inner' holds slightly smaller one than `outer',
5693 so that the calculation of overlapping may not become too
5695 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5696 outer
= (*region
)->rgnBBox
;
5697 DisposeRgn (region
);
5699 InsetRect (&inner
, 8, 8);
5700 screen_rect
= qd
.screenBits
.bounds
;
5701 screen_rect
.top
+= GetMBarHeight ();
5703 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5705 if (inner
.right
<= screen_rect
.left
)
5706 f
->left_pos
= screen_rect
.left
;
5707 else if (inner
.left
>= screen_rect
.right
)
5708 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5710 if (inner
.bottom
<= screen_rect
.top
)
5711 f
->top_pos
= screen_rect
.top
;
5712 else if (inner
.top
>= screen_rect
.bottom
)
5713 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5715 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5716 f
->top_pos
+ f
->y_pixels_diff
, false);
5724 /* Call this to change the size of frame F's x-window.
5725 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5726 for this size change and subsequent size changes.
5727 Otherwise we leave the window gravity unchanged. */
5730 x_set_window_size (f
, change_gravity
, cols
, rows
)
5735 int pixelwidth
, pixelheight
;
5739 check_frame_size (f
, &rows
, &cols
);
5740 f
->scroll_bar_actual_width
5741 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5743 compute_fringe_widths (f
, 0);
5745 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5746 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5748 f
->win_gravity
= NorthWestGravity
;
5749 x_wm_set_size_hint (f
, (long) 0, 0);
5751 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5752 #if TARGET_API_MAC_CARBON
5753 if (f
->output_data
.mac
->hourglass_control
)
5754 MoveControl (f
->output_data
.mac
->hourglass_control
,
5755 pixelwidth
- HOURGLASS_WIDTH
, 0);
5758 /* Now, strictly speaking, we can't be sure that this is accurate,
5759 but the window manager will get around to dealing with the size
5760 change request eventually, and we'll hear how it went when the
5761 ConfigureNotify event gets here.
5763 We could just not bother storing any of this information here,
5764 and let the ConfigureNotify event set everything up, but that
5765 might be kind of confusing to the Lisp code, since size changes
5766 wouldn't be reported in the frame parameters until some random
5767 point in the future when the ConfigureNotify event arrives.
5769 We pass 1 for DELAY since we can't run Lisp code inside of
5771 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5772 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5773 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5775 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5776 receive in the ConfigureNotify event; if we get what we asked
5777 for, then the event won't cause the screen to become garbaged, so
5778 we have to make sure to do it here. */
5779 SET_FRAME_GARBAGED (f
);
5781 XFlush (FRAME_X_DISPLAY (f
));
5783 /* If cursor was outside the new size, mark it as off. */
5784 mark_window_cursors_off (XWINDOW (f
->root_window
));
5786 /* Clear out any recollection of where the mouse highlighting was,
5787 since it might be in a place that's outside the new frame size.
5788 Actually checking whether it is outside is a pain in the neck,
5789 so don't try--just let the highlighting be done afresh with new size. */
5790 cancel_mouse_face (f
);
5795 /* Mouse warping. */
5797 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5800 x_set_mouse_position (f
, x
, y
)
5806 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5807 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5809 if (pix_x
< 0) pix_x
= 0;
5810 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5812 if (pix_y
< 0) pix_y
= 0;
5813 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5815 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5819 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5823 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5826 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5827 0, 0, 0, 0, pix_x
, pix_y
);
5832 /* focus shifting, raising and lowering. */
5835 x_focus_on_frame (f
)
5838 #if 0 /* This proves to be unpleasant. */
5842 /* I don't think that the ICCCM allows programs to do things like this
5843 without the interaction of the window manager. Whatever you end up
5844 doing with this code, do it to x_unfocus_frame too. */
5845 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5846 RevertToPointerRoot
, CurrentTime
);
5856 /* Raise frame F. */
5862 if (f
->async_visible
)
5865 BringToFront (FRAME_MAC_WINDOW (f
));
5870 /* Lower frame F. */
5876 if (f
->async_visible
)
5879 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
5885 XTframe_raise_lower (f
, raise_flag
)
5895 /* Change of visibility. */
5898 mac_handle_visibility_change (f
)
5901 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5902 int visible
= 0, iconified
= 0;
5903 struct input_event buf
;
5905 if (IsWindowVisible (wp
))
5906 if (IsWindowCollapsed (wp
))
5911 if (!f
->async_visible
&& visible
)
5915 /* wait_reading_process_output will notice this and update
5916 the frame's display structures. If we were made
5917 invisible, we should not set garbaged, because that stops
5918 redrawing on Update events. */
5919 SET_FRAME_GARBAGED (f
);
5922 buf
.kind
= DEICONIFY_EVENT
;
5923 XSETFRAME (buf
.frame_or_window
, f
);
5924 kbd_buffer_store_event (&buf
);
5926 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
5927 /* Force a redisplay sooner or later to update the
5928 frame titles in case this is the second frame. */
5929 record_asynch_buffer_change ();
5931 else if (f
->async_visible
&& !visible
)
5935 buf
.kind
= ICONIFY_EVENT
;
5936 XSETFRAME (buf
.frame_or_window
, f
);
5937 kbd_buffer_store_event (&buf
);
5940 f
->async_visible
= visible
;
5941 f
->async_iconified
= iconified
;
5944 /* This tries to wait until the frame is really visible.
5945 However, if the window manager asks the user where to position
5946 the frame, this will return before the user finishes doing that.
5947 The frame will not actually be visible at that time,
5948 but it will become visible later when the window manager
5949 finishes with it. */
5952 x_make_frame_visible (f
)
5956 int original_top
, original_left
;
5960 if (! FRAME_VISIBLE_P (f
))
5962 /* We test FRAME_GARBAGED_P here to make sure we don't
5963 call x_set_offset a second time
5964 if we get to x_make_frame_visible a second time
5965 before the window gets really visible. */
5966 if (! FRAME_ICONIFIED_P (f
)
5967 && ! f
->output_data
.mac
->asked_for_visible
)
5968 #if TARGET_API_MAC_CARBON
5969 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5971 struct frame
*sf
= SELECTED_FRAME ();
5972 if (!FRAME_MAC_P (sf
))
5973 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5974 kWindowCenterOnMainScreen
);
5976 RepositionWindow (FRAME_MAC_WINDOW (f
),
5977 FRAME_MAC_WINDOW (sf
),
5978 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5979 kWindowCascadeStartAtParentWindowScreen
5981 kWindowCascadeOnParentWindowScreen
5984 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5988 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5990 f
->output_data
.mac
->asked_for_visible
= 1;
5992 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
5993 ShowWindow (FRAME_MAC_WINDOW (f
));
5996 XFlush (FRAME_MAC_DISPLAY (f
));
5998 /* Synchronize to ensure Emacs knows the frame is visible
5999 before we do anything else. We do this loop with input not blocked
6000 so that incoming events are handled. */
6005 /* This must come after we set COUNT. */
6008 XSETFRAME (frame
, f
);
6010 /* Wait until the frame is visible. Process X events until a
6011 MapNotify event has been seen, or until we think we won't get a
6012 MapNotify at all.. */
6013 for (count
= input_signal_count
+ 10;
6014 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6016 /* Force processing of queued events. */
6019 /* Machines that do polling rather than SIGIO have been
6020 observed to go into a busy-wait here. So we'll fake an
6021 alarm signal to let the handler know that there's something
6022 to be read. We used to raise a real alarm, but it seems
6023 that the handler isn't always enabled here. This is
6025 if (input_polling_used ())
6027 /* It could be confusing if a real alarm arrives while
6028 processing the fake one. Turn it off and let the
6029 handler reset it. */
6030 extern void poll_for_input_1
P_ ((void));
6031 int old_poll_suppress_count
= poll_suppress_count
;
6032 poll_suppress_count
= 1;
6033 poll_for_input_1 ();
6034 poll_suppress_count
= old_poll_suppress_count
;
6037 /* See if a MapNotify event has been processed. */
6038 FRAME_SAMPLE_VISIBILITY (f
);
6043 /* Change from mapped state to withdrawn state. */
6045 /* Make the frame visible (mapped and not iconified). */
6048 x_make_frame_invisible (f
)
6051 /* A deactivate event does not occur when the last visible frame is
6052 made invisible. So if we clear the highlight here, it will not
6053 be rehighlighted when it is made visible. */
6055 /* Don't keep the highlight on an invisible frame. */
6056 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6057 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6062 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6063 that the current position of the window is user-specified, rather than
6064 program-specified, so that when the window is mapped again, it will be
6065 placed at the same location, without forcing the user to position it
6066 by hand again (they have already done that once for this window.) */
6067 x_wm_set_size_hint (f
, (long) 0, 1);
6069 HideWindow (FRAME_MAC_WINDOW (f
));
6073 #if !USE_CARBON_EVENTS
6074 mac_handle_visibility_change (f
);
6078 /* Change window state from mapped to iconified. */
6086 /* A deactivate event does not occur when the last visible frame is
6087 iconified. So if we clear the highlight here, it will not be
6088 rehighlighted when it is deiconified. */
6090 /* Don't keep the highlight on an invisible frame. */
6091 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6092 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6095 if (f
->async_iconified
)
6100 FRAME_SAMPLE_VISIBILITY (f
);
6102 if (! FRAME_VISIBLE_P (f
))
6103 ShowWindow (FRAME_MAC_WINDOW (f
));
6105 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6110 error ("Can't notify window manager of iconification");
6112 #if !USE_CARBON_EVENTS
6113 mac_handle_visibility_change (f
);
6118 /* Free X resources of frame F. */
6121 x_free_frame_resources (f
)
6124 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6125 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6129 if (wp
!= tip_window
)
6130 remove_window_handler (wp
);
6133 if (wp
== tip_window
)
6134 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6135 closed' event. So we reset tip_window here. */
6138 free_frame_menubar (f
);
6140 if (FRAME_FACE_CACHE (f
))
6141 free_frame_faces (f
);
6145 if (FRAME_SIZE_HINTS (f
))
6146 xfree (FRAME_SIZE_HINTS (f
));
6148 xfree (f
->output_data
.mac
);
6149 f
->output_data
.mac
= NULL
;
6151 if (f
== dpyinfo
->x_focus_frame
)
6152 dpyinfo
->x_focus_frame
= 0;
6153 if (f
== dpyinfo
->x_focus_event_frame
)
6154 dpyinfo
->x_focus_event_frame
= 0;
6155 if (f
== dpyinfo
->x_highlight_frame
)
6156 dpyinfo
->x_highlight_frame
= 0;
6158 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6160 dpyinfo
->mouse_face_beg_row
6161 = dpyinfo
->mouse_face_beg_col
= -1;
6162 dpyinfo
->mouse_face_end_row
6163 = dpyinfo
->mouse_face_end_col
= -1;
6164 dpyinfo
->mouse_face_window
= Qnil
;
6165 dpyinfo
->mouse_face_deferred_gc
= 0;
6166 dpyinfo
->mouse_face_mouse_frame
= 0;
6173 /* Destroy the X window of frame F. */
6176 x_destroy_window (f
)
6179 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6181 x_free_frame_resources (f
);
6183 dpyinfo
->reference_count
--;
6187 /* Setting window manager hints. */
6189 /* Set the normal size hints for the window manager, for frame F.
6190 FLAGS is the flags word to use--or 0 meaning preserve the flags
6191 that the window now has.
6192 If USER_POSITION is nonzero, we set the USPosition
6193 flag (this is useful when FLAGS is 0). */
6195 x_wm_set_size_hint (f
, flags
, user_position
)
6200 int base_width
, base_height
, width_inc
, height_inc
;
6201 int min_rows
= 0, min_cols
= 0;
6202 XSizeHints
*size_hints
;
6204 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6205 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6206 width_inc
= FRAME_COLUMN_WIDTH (f
);
6207 height_inc
= FRAME_LINE_HEIGHT (f
);
6209 check_frame_size (f
, &min_rows
, &min_cols
);
6211 size_hints
= FRAME_SIZE_HINTS (f
);
6212 if (size_hints
== NULL
)
6214 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6215 bzero (size_hints
, sizeof (XSizeHints
));
6218 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6219 size_hints
->width_inc
= width_inc
;
6220 size_hints
->height_inc
= height_inc
;
6221 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6222 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6223 size_hints
->base_width
= base_width
;
6224 size_hints
->base_height
= base_height
;
6227 size_hints
->flags
= flags
;
6228 else if (user_position
)
6230 size_hints
->flags
&= ~ PPosition
;
6231 size_hints
->flags
|= USPosition
;
6235 #if 0 /* MAC_TODO: hide application instead of iconify? */
6236 /* Used for IconicState or NormalState */
6239 x_wm_set_window_state (f
, state
)
6243 #ifdef USE_X_TOOLKIT
6246 XtSetArg (al
[0], XtNinitialState
, state
);
6247 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6248 #else /* not USE_X_TOOLKIT */
6249 Window window
= FRAME_X_WINDOW (f
);
6251 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6252 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6254 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6255 #endif /* not USE_X_TOOLKIT */
6259 x_wm_set_icon_pixmap (f
, pixmap_id
)
6265 #ifndef USE_X_TOOLKIT
6266 Window window
= FRAME_X_WINDOW (f
);
6271 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6272 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6276 /* It seems there is no way to turn off use of an icon pixmap.
6277 The following line does it, only if no icon has yet been created,
6278 for some window managers. But with mwm it crashes.
6279 Some people say it should clear the IconPixmapHint bit in this case,
6280 but that doesn't work, and the X consortium said it isn't the
6281 right thing at all. Since there is no way to win,
6282 best to explicitly give up. */
6284 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6290 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6294 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6295 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6298 #else /* not USE_X_TOOLKIT */
6300 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6301 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6303 #endif /* not USE_X_TOOLKIT */
6306 #endif /* MAC_TODO */
6309 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6313 #if 0 /* MAC_TODO: no icons on Mac */
6314 #ifdef USE_X_TOOLKIT
6315 Window window
= XtWindow (f
->output_data
.x
->widget
);
6317 Window window
= FRAME_X_WINDOW (f
);
6320 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6321 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6322 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6324 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6325 #endif /* MAC_TODO */
6329 /***********************************************************************
6331 ***********************************************************************/
6333 /* An XLFD pattern is divided into blocks delimited by '*'. This
6334 structure holds information for each block. */
6335 struct xlfdpat_block
6337 /* Length of the pattern string in this block. Non-zero except for
6338 the first and the last blocks. */
6341 /* Pattern string except the last character in this block. The last
6342 character is replaced with NUL in order to use it as a
6344 unsigned char *pattern
;
6346 /* Last character of the pattern string. Must not be '?'. */
6347 unsigned char last_char
;
6349 /* One of the tables for the Boyer-Moore string search. It
6350 specifies the number of positions to proceed for each character
6351 with which the match fails. */
6354 /* The skip value for the last character in the above `skip' is
6355 assigned to `infinity' in order to simplify a loop condition.
6356 The original value is saved here. */
6362 /* Normalized pattern string. "Normalized" means that capital
6363 letters are lowered, blocks are not empty except the first and
6364 the last ones, and trailing '?'s in a block that is not the last
6365 one are moved to the next one. The last character in each block
6366 is replaced with NUL. */
6369 /* Number of characters except '*'s and trailing '?'s in the
6370 normalized pattern string. */
6373 /* Number of trailing '?'s in the normalized pattern string. */
6374 int trailing_anychars
;
6376 /* Number of blocks and information for each block. The latter is
6377 NULL if the pattern is exact (no '*' or '?' in it). */
6379 struct xlfdpat_block
*blocks
;
6383 xlfdpat_destroy (pat
)
6384 struct xlfdpat
*pat
;
6391 xfree (pat
->blocks
);
6398 static struct xlfdpat
*
6399 xlfdpat_create (pattern
)
6402 struct xlfdpat
*pat
;
6403 int nblocks
, i
, skip
;
6404 unsigned char last_char
, *p
, *q
, *anychar_head
;
6405 struct xlfdpat_block
*blk
;
6407 pat
= xmalloc (sizeof (struct xlfdpat
));
6411 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6412 if (pat
->buf
== NULL
)
6415 /* Normalize the pattern string and store it to `pat->buf'. */
6417 anychar_head
= NULL
;
6420 for (p
= pattern
; *p
; p
++)
6422 unsigned char c
= *p
;
6425 if (last_char
== '*')
6426 /* ...a** -> ...a* */
6430 if (last_char
== '?')
6431 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6432 /* ...*??* -> ...*?? */
6435 /* ...a??* -> ...a*?? */
6437 *anychar_head
++ = '*';
6444 if (last_char
!= '?')
6448 /* On Mac OS X 10.3, tolower also converts non-ASCII
6449 characters for some locales. */
6453 *q
++ = last_char
= c
;
6457 pat
->nblocks
= nblocks
;
6458 if (last_char
!= '?')
6459 pat
->trailing_anychars
= 0;
6462 pat
->trailing_anychars
= q
- anychar_head
;
6465 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6467 if (anychar_head
== NULL
&& nblocks
== 1)
6469 /* The pattern is exact. */
6474 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6475 if (pat
->blocks
== NULL
)
6478 /* Divide the normalized pattern into blocks. */
6480 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6485 blk
->len
= p
- blk
->pattern
;
6489 blk
->len
= q
- blk
->pattern
;
6491 /* Setup a table for the Boyer-Moore string search. */
6492 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6495 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6496 blk
->pattern
[blk
->len
- 1] = '\0';
6498 for (skip
= 1; skip
< blk
->len
; skip
++)
6499 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6502 for (i
= 0; i
< 256; i
++)
6503 blk
->skip
[i
] = skip
;
6505 p
= blk
->pattern
+ (blk
->len
- skip
);
6507 blk
->skip
[*p
++] = skip
;
6509 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6515 xlfdpat_destroy (pat
);
6520 xlfdpat_exact_p (pat
)
6521 struct xlfdpat
*pat
;
6523 return pat
->blocks
== NULL
;
6526 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6527 that the pattern in *BLK matches with its prefix. Return NULL
6528 there is no such strings. STRING must be lowered in advance. */
6531 xlfdpat_block_match_1 (blk
, string
, start_max
)
6532 struct xlfdpat_block
*blk
;
6533 unsigned char *string
;
6536 int start
, infinity
;
6537 unsigned char *p
, *s
;
6539 xassert (blk
->len
> 0);
6540 xassert (start_max
+ blk
->len
<= strlen (string
));
6541 xassert (blk
->last_char
!= '?');
6543 /* See the comments in the function `boyer_moore' (search.c) for the
6544 use of `infinity'. */
6545 infinity
= start_max
+ blk
->len
+ 1;
6546 blk
->skip
[blk
->last_char
] = infinity
;
6551 /* Check the last character of the pattern. */
6552 s
= string
+ blk
->len
- 1;
6555 start
+= blk
->skip
[*(s
+ start
)];
6557 while (start
<= start_max
);
6559 if (start
< infinity
)
6560 /* Couldn't find the last character. */
6563 /* No less than `infinity' means we could find the last
6564 character at `s[start - infinity]'. */
6567 /* Check the remaining characters. We prefer making no-'?'
6568 cases faster because the use of '?' is really rare. */
6573 while (*p
++ == *s
++)
6576 while (*(p
- 1) == '?');
6578 if (*(p
- 1) == '\0')
6580 return string
+ start
;
6583 start
+= blk
->last_char_skip
;
6585 while (start
<= start_max
);
6590 #define xlfdpat_block_match(b, s, m) \
6591 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6592 : xlfdpat_block_match_1 (b, s, m))
6594 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6595 matches with STRING. STRING must be lowered in advance. */
6598 xlfdpat_match (pat
, string
)
6599 struct xlfdpat
*pat
;
6600 unsigned char *string
;
6602 int str_len
, nblocks
, i
, start_max
;
6603 struct xlfdpat_block
*blk
;
6606 xassert (pat
->nblocks
> 0);
6608 if (xlfdpat_exact_p (pat
))
6609 return strcmp (pat
->buf
, string
) == 0;
6611 /* The number of the characters in the string must not be smaller
6612 than that in the pattern. */
6613 str_len
= strlen (string
);
6614 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6617 /* Chop off the trailing '?'s. */
6618 str_len
-= pat
->trailing_anychars
;
6620 /* The last block. When it is non-empty, it must match at the end
6622 nblocks
= pat
->nblocks
;
6623 blk
= pat
->blocks
+ (nblocks
- 1);
6625 /* The last block is also the first one. */
6626 return (str_len
== blk
->len
6627 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6628 else if (blk
->len
!= 0)
6629 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6632 /* The first block. When it is non-empty, it must match at the
6633 beginning of the string. */
6637 s
= xlfdpat_block_match (blk
, string
, 0);
6640 string
= s
+ blk
->len
;
6643 /* The rest of the blocks. */
6644 start_max
= str_len
- pat
->nchars
;
6645 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6647 s
= xlfdpat_block_match (blk
, string
, start_max
);
6650 start_max
-= s
- string
;
6651 string
= s
+ blk
->len
;
6658 /***********************************************************************
6660 ***********************************************************************/
6662 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6665 x_get_font_info (f
, font_idx
)
6669 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6672 /* the global font name table */
6673 static char **font_name_table
= NULL
;
6674 static int font_name_table_size
= 0;
6675 static int font_name_count
= 0;
6677 /* Alist linking font family names to Font Manager font family
6678 references (which can also be used as QuickDraw font IDs). We use
6679 an alist because hash tables are not ready when the terminal frame
6680 for Mac OS Classic is created. */
6681 static Lisp_Object fm_font_family_alist
;
6683 /* Hash table linking font family names to ATSU font IDs. */
6684 static Lisp_Object atsu_font_id_hash
;
6687 /* Alist linking character set strings to Mac text encoding and Emacs
6689 static Lisp_Object Vmac_charset_info_alist
;
6692 create_text_encoding_info_alist ()
6694 Lisp_Object result
= Qnil
, rest
;
6696 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6698 Lisp_Object charset_info
= XCAR (rest
);
6699 Lisp_Object charset
, coding_system
, text_encoding
;
6700 Lisp_Object existing_info
;
6702 if (!(CONSP (charset_info
)
6703 && STRINGP (charset
= XCAR (charset_info
))
6704 && CONSP (XCDR (charset_info
))
6705 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6706 && CONSP (XCDR (XCDR (charset_info
)))
6707 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6710 existing_info
= assq_no_quit (text_encoding
, result
);
6711 if (NILP (existing_info
))
6712 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6715 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6716 XSETCDR (XCDR (existing_info
),
6717 Fcons (charset
, XCDR (XCDR (existing_info
))));
6725 decode_mac_font_name (name
, size
, coding_system
)
6728 Lisp_Object coding_system
;
6730 struct coding_system coding
;
6733 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6735 for (p
= name
; *p
; p
++)
6736 if (!isascii (*p
) || iscntrl (*p
))
6741 setup_coding_system (coding_system
, &coding
);
6742 coding
.src_multibyte
= 0;
6743 coding
.dst_multibyte
= 1;
6744 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6745 coding
.dst_bytes
= size
;
6746 coding
.destination
= (unsigned char *) alloca (coding
.dst_bytes
);
6748 decode_coding_c_string (&coding
, name
, strlen (name
), Qnil
);
6749 bcopy (coding
.destination
, name
, min (coding
.produced
, size
));
6750 name
[min (coding
.produced
, size
)] = '\0';
6754 /* If there's just one occurrence of '-' in the family name, it is
6755 replaced with '_'. (More than one occurrence of '-' means a
6756 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6757 p
= strchr (name
, '-');
6758 if (p
&& strchr (p
+ 1, '-') == NULL
)
6761 for (p
= name
; *p
; p
++)
6762 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6763 for some locales. */
6770 mac_to_x_fontname (name
, size
, style
, charset
)
6778 char xf
[256], *result
;
6781 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6785 strcpy(foundry
, "Apple");
6786 strcpy(family
, name
);
6789 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6790 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6791 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
6793 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6794 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6795 for (p
= result
; *p
; p
++)
6796 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6797 for some locales. */
6804 /* Parse fully-specified and instantiated X11 font spec XF, and store
6805 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6806 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6807 caller must allocate at least 256 and 32 bytes respectively. For
6808 ordinary Mac fonts, the value stored to FAMILY should just be their
6809 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6810 intlfonts collection contain their charset designation in their
6811 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6812 types of font names are handled accordingly. */
6814 const int kDefaultFontSize
= 12;
6817 parse_x_font_name (xf
, family
, size
, style
, charset
)
6823 Str31 foundry
, weight
;
6824 int point_size
, avgwidth
;
6827 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6828 foundry
, family
, weight
, slant
, size
,
6829 &point_size
, &avgwidth
, charset
) != 8
6830 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6831 foundry
, family
, weight
, slant
, size
,
6832 &point_size
, &avgwidth
, charset
) != 8)
6838 *size
= point_size
/ 10;
6839 else if (avgwidth
> 0)
6840 *size
= avgwidth
/ 10;
6843 *size
= kDefaultFontSize
;
6846 if (strcmp (weight
, "bold") == 0)
6851 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
6853 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
6855 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
6857 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6858 but take overlap into account. */
6859 memmove (family
+ foundry_len
+ 1, family
, family_len
);
6860 memcpy (family
, foundry
, foundry_len
);
6861 family
[foundry_len
] = '-';
6862 family
[foundry_len
+ 1 + family_len
] = '-';
6863 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
6869 for (p
= family
; *p
; p
++)
6870 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6871 for some locales. */
6880 add_font_name_table_entry (char *font_name
)
6882 if (font_name_table_size
== 0)
6884 font_name_table_size
= 256;
6885 font_name_table
= (char **)
6886 xmalloc (font_name_table_size
* sizeof (char *));
6888 else if (font_name_count
+ 1 >= font_name_table_size
)
6890 font_name_table_size
*= 2;
6891 font_name_table
= (char **)
6892 xrealloc (font_name_table
,
6893 font_name_table_size
* sizeof (char *));
6896 font_name_table
[font_name_count
++] = font_name
;
6899 /* Sets up the table font_name_table to contain the list of all fonts
6900 in the system the first time the table is used so that the Resource
6901 Manager need not be accessed every time this information is
6905 init_font_name_table ()
6907 #if TARGET_API_MAC_CARBON
6908 FMFontFamilyIterator ffi
;
6909 FMFontFamilyInstanceIterator ffii
;
6911 Lisp_Object text_encoding_info_alist
;
6912 struct gcpro gcpro1
;
6914 text_encoding_info_alist
= create_text_encoding_info_alist ();
6917 #if USE_CG_TEXT_DRAWING
6918 init_cg_text_anti_aliasing_threshold ();
6920 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
6921 text_encoding_info_alist
)))
6924 ItemCount nfonts
, i
;
6925 ATSUFontID
*font_ids
= NULL
;
6926 Ptr name
, prev_name
= NULL
;
6930 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
6931 make_float (DEFAULT_REHASH_SIZE
),
6932 make_float (DEFAULT_REHASH_THRESHOLD
),
6934 err
= ATSUFontCount (&nfonts
);
6936 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
6938 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
6940 for (i
= 0; i
< nfonts
; i
++)
6942 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6943 kFontMacintoshPlatform
, kFontNoScript
,
6944 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
6947 name
= xmalloc (name_len
+ 1);
6950 name
[name_len
] = '\0';
6951 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6952 kFontMacintoshPlatform
, kFontNoScript
,
6953 kFontNoLanguage
, name_len
, name
,
6956 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
6959 && (prev_name
== NULL
6960 || strcmp (name
, prev_name
) != 0))
6962 static char *cs
= "iso10646-1";
6964 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6966 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6968 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6970 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6971 italic
| bold
, cs
));
6972 Fputhash (make_unibyte_string (name
, name_len
),
6973 long_to_cons (font_ids
[i
]), atsu_font_id_hash
);
6987 /* Create a dummy instance iterator here to avoid creating and
6988 destroying it in the loop. */
6989 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6991 /* Create an iterator to enumerate the font families. */
6992 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6995 FMDisposeFontFamilyInstanceIterator (&ffii
);
6999 GCPRO1 (text_encoding_info_alist
);
7001 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7007 TextEncoding encoding
;
7008 TextEncodingBase sc
;
7009 Lisp_Object text_encoding_info
;
7011 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7017 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7019 sc
= GetTextEncodingBase (encoding
);
7020 text_encoding_info
= assq_no_quit (make_number (sc
),
7021 text_encoding_info_alist
);
7022 if (NILP (text_encoding_info
))
7023 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7024 text_encoding_info_alist
);
7025 decode_mac_font_name (name
, sizeof (name
),
7026 XCAR (XCDR (text_encoding_info
)));
7027 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7029 fm_font_family_alist
);
7031 /* Point the instance iterator at the current font family. */
7032 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7035 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7038 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7040 if (size
> 0 || style
== normal
)
7041 for (; !NILP (rest
); rest
= XCDR (rest
))
7043 char *cs
= SDATA (XCAR (rest
));
7047 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7049 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7051 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7053 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7059 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7068 /* Dispose of the iterators. */
7069 FMDisposeFontFamilyIterator (&ffi
);
7070 FMDisposeFontFamilyInstanceIterator (&ffii
);
7071 #else /* !TARGET_API_MAC_CARBON */
7073 SInt16 fontnum
, old_fontnum
;
7074 int num_mac_fonts
= CountResources('FOND');
7076 Handle font_handle
, font_handle_2
;
7077 short id
, scriptcode
;
7080 struct FontAssoc
*fat
;
7081 struct AsscEntry
*assc_entry
;
7082 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
7083 struct gcpro gcpro1
;
7085 GetPort (&port
); /* save the current font number used */
7086 old_fontnum
= port
->txFont
;
7088 text_encoding_info_alist
= create_text_encoding_info_alist ();
7090 GCPRO1 (text_encoding_info_alist
);
7092 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7094 font_handle
= GetIndResource ('FOND', i
);
7098 GetResInfo (font_handle
, &id
, &type
, name
);
7099 GetFNum (name
, &fontnum
);
7105 scriptcode
= FontToScript (fontnum
);
7106 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7107 text_encoding_info_alist
);
7108 if (NILP (text_encoding_info
))
7109 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7110 text_encoding_info_alist
);
7111 decode_mac_font_name (name
, sizeof (name
),
7112 XCAR (XCDR (text_encoding_info
)));
7113 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7114 make_number (fontnum
)),
7115 fm_font_family_alist
);
7118 HLock (font_handle
);
7120 if (GetResourceSizeOnDisk (font_handle
)
7121 >= sizeof (struct FamRec
))
7123 fat
= (struct FontAssoc
*) (*font_handle
7124 + sizeof (struct FamRec
));
7126 = (struct AsscEntry
*) (*font_handle
7127 + sizeof (struct FamRec
)
7128 + sizeof (struct FontAssoc
));
7130 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7132 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7134 for (; !NILP (rest
); rest
= XCDR (rest
))
7136 char *cs
= SDATA (XCAR (rest
));
7138 add_font_name_table_entry (mac_to_x_fontname (name
,
7139 assc_entry
->fontSize
,
7140 assc_entry
->fontStyle
,
7146 HUnlock (font_handle
);
7147 font_handle_2
= GetNextFOND (font_handle
);
7148 ReleaseResource (font_handle
);
7149 font_handle
= font_handle_2
;
7151 while (ResError () == noErr
&& font_handle
);
7156 TextFont (old_fontnum
);
7157 #endif /* !TARGET_API_MAC_CARBON */
7162 mac_clear_font_name_table ()
7166 for (i
= 0; i
< font_name_count
; i
++)
7167 xfree (font_name_table
[i
]);
7168 xfree (font_name_table
);
7169 font_name_table
= NULL
;
7170 font_name_table_size
= font_name_count
= 0;
7171 fm_font_family_alist
= Qnil
;
7175 enum xlfd_scalable_field_index
7177 XLFD_SCL_PIXEL_SIZE
,
7178 XLFD_SCL_POINT_SIZE
,
7183 static int xlfd_scalable_fields
[] =
7192 mac_do_list_fonts (pattern
, maxnames
)
7197 Lisp_Object font_list
= Qnil
;
7198 struct xlfdpat
*pat
;
7200 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7203 if (font_name_table
== NULL
) /* Initialize when first used. */
7204 init_font_name_table ();
7206 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7209 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7210 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7211 fonts are scaled according to the specified size. */
7214 field
= xlfd_scalable_fields
;
7222 if ('0' <= *ptr
&& *ptr
<= '9')
7224 *val
= *ptr
++ - '0';
7225 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7226 *val
= *val
* 10 + *ptr
++ - '0';
7233 ptr
= strchr (ptr
, '-');
7236 while (ptr
&& i
< 14);
7238 if (i
== 14 && ptr
== NULL
)
7240 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7241 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7242 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7243 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7245 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7246 scl_val
[XLFD_SCL_POINT_SIZE
] =
7247 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7248 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7250 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7251 scl_val
[XLFD_SCL_AVGWIDTH
] =
7252 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7253 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7257 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7259 pat
= xlfdpat_create (pattern
);
7263 exact
= xlfdpat_exact_p (pat
);
7265 for (i
= 0; i
< font_name_count
; i
++)
7267 if (xlfdpat_match (pat
, font_name_table
[i
]))
7269 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7270 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7273 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7274 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7276 int former_len
= ptr
- font_name_table
[i
];
7278 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7281 memcpy (scaled
, font_name_table
[i
], former_len
);
7282 sprintf (scaled
+ former_len
,
7283 "-%d-%d-72-72-m-%d-%s",
7284 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7285 scl_val
[XLFD_SCL_POINT_SIZE
],
7286 scl_val
[XLFD_SCL_AVGWIDTH
],
7287 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7289 if (xlfdpat_match (pat
, scaled
))
7291 font_list
= Fcons (build_string (scaled
), font_list
);
7293 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7301 xlfdpat_destroy (pat
);
7306 /* Return a list of names of available fonts matching PATTERN on frame F.
7308 Frame F null means we have not yet created any frame on Mac, and
7309 consult the first display in x_display_list. MAXNAMES sets a limit
7310 on how many fonts to match. */
7313 x_list_fonts (f
, pattern
, size
, maxnames
)
7315 Lisp_Object pattern
;
7318 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7319 struct mac_display_info
*dpyinfo
7320 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7322 xassert (size
<= 0);
7324 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7325 if (NILP (patterns
))
7326 patterns
= Fcons (pattern
, Qnil
);
7328 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7330 pattern
= XCAR (patterns
);
7332 if (!STRINGP (pattern
))
7335 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7336 key
= Fcons (pattern
, make_number (maxnames
));
7338 list
= Fassoc (key
, tem
);
7341 list
= Fcdr_safe (list
);
7342 /* We have a cashed list. Don't have to get the list again. */
7347 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7350 /* MAC_TODO: add code for matching outline fonts here */
7352 /* Now store the result in the cache. */
7353 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7354 Fcons (Fcons (key
, list
),
7355 XCAR (XCDR (dpyinfo
->name_list_element
))));
7358 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7367 /* Check that FONT is valid on frame F. It is if it can be found in F's
7371 x_check_font (f
, font
)
7376 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7378 xassert (font
!= NULL
);
7380 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7381 if (dpyinfo
->font_table
[i
].name
7382 && font
== dpyinfo
->font_table
[i
].font
)
7385 xassert (i
< dpyinfo
->n_fonts
);
7388 #endif /* GLYPH_DEBUG != 0 */
7390 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7391 Note: There are (broken) X fonts out there with invalid XFontStruct
7392 min_bounds contents. For example, handa@etl.go.jp reports that
7393 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7394 have font->min_bounds.width == 0. */
7397 x_font_min_bounds (font
, w
, h
)
7398 MacFontStruct
*font
;
7401 *h
= FONT_HEIGHT (font
);
7402 *w
= font
->min_bounds
.width
;
7406 /* Compute the smallest character width and smallest font height over
7407 all fonts available on frame F. Set the members smallest_char_width
7408 and smallest_font_height in F's x_display_info structure to
7409 the values computed. Value is non-zero if smallest_font_height or
7410 smallest_char_width become smaller than they were before. */
7413 x_compute_min_glyph_bounds (f
)
7417 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7418 MacFontStruct
*font
;
7419 int old_width
= dpyinfo
->smallest_char_width
;
7420 int old_height
= dpyinfo
->smallest_font_height
;
7422 dpyinfo
->smallest_font_height
= 100000;
7423 dpyinfo
->smallest_char_width
= 100000;
7425 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7426 if (dpyinfo
->font_table
[i
].name
)
7428 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7431 font
= (MacFontStruct
*) fontp
->font
;
7432 xassert (font
!= (MacFontStruct
*) ~0);
7433 x_font_min_bounds (font
, &w
, &h
);
7435 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7436 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7439 xassert (dpyinfo
->smallest_char_width
> 0
7440 && dpyinfo
->smallest_font_height
> 0);
7442 return (dpyinfo
->n_fonts
== 1
7443 || dpyinfo
->smallest_char_width
< old_width
7444 || dpyinfo
->smallest_font_height
< old_height
);
7448 /* Determine whether given string is a fully-specified XLFD: all 14
7449 fields are present, none is '*'. */
7452 is_fully_specified_xlfd (char *p
)
7460 for (i
= 0; i
< 13; i
++)
7462 q
= strchr (p
+ 1, '-');
7465 if (q
- p
== 2 && *(p
+ 1) == '*')
7470 if (strchr (p
+ 1, '-') != NULL
)
7473 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7480 /* XLoadQueryFont creates and returns an internal representation for a
7481 font in a MacFontStruct struct. There is really no concept
7482 corresponding to "loading" a font on the Mac. But we check its
7483 existence and find the font number and all other information for it
7484 and store them in the returned MacFontStruct. */
7486 static MacFontStruct
*
7487 XLoadQueryFont (Display
*dpy
, char *fontname
)
7495 static ATSUFontID font_id
;
7496 ATSUStyle mac_style
= NULL
;
7499 #if TARGET_API_MAC_CARBON
7500 TextEncoding encoding
;
7505 MacFontStruct
*font
;
7506 XCharStruct
*space_bounds
= NULL
, *pcm
;
7508 if (is_fully_specified_xlfd (fontname
))
7512 Lisp_Object matched_fonts
;
7514 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7515 if (NILP (matched_fonts
))
7517 name
= SDATA (XCAR (matched_fonts
));
7520 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7524 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7527 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7528 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7529 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7530 sizeof (Boolean
), sizeof (Boolean
)};
7531 static Fixed size_fixed
;
7532 static Boolean bold_p
, italic_p
;
7533 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7534 &bold_p
, &italic_p
};
7535 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
,
7537 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
,
7538 kDecomposeDiacriticsSelector
};
7539 Lisp_Object font_id_cons
;
7541 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7542 atsu_font_id_hash
, Qnil
);
7543 if (NILP (font_id_cons
))
7545 font_id
= cons_to_long (font_id_cons
);
7546 size_fixed
= Long2Fix (size
);
7547 bold_p
= (fontface
& bold
) != 0;
7548 italic_p
= (fontface
& italic
) != 0;
7549 err
= ATSUCreateStyle (&mac_style
);
7552 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7556 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7557 tags
, sizes
, values
);
7559 scriptcode
= kTextEncodingMacUnicode
;
7564 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7568 fontnum
= XINT (XCDR (tmp
));
7569 #if TARGET_API_MAC_CARBON
7570 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7572 scriptcode
= GetTextEncodingBase (encoding
);
7574 scriptcode
= FontToScript (fontnum
);
7578 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7580 font
->mac_fontnum
= fontnum
;
7581 font
->mac_fontsize
= size
;
7582 font
->mac_fontface
= fontface
;
7583 font
->mac_scriptcode
= scriptcode
;
7585 font
->mac_style
= mac_style
;
7586 #if USE_CG_TEXT_DRAWING
7587 font
->cg_font
= NULL
;
7588 font
->cg_glyphs
= NULL
;
7592 /* Apple Japanese (SJIS) font is listed as both
7593 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7594 (Roman script) in init_font_name_table (). The latter should be
7595 treated as a one-byte font. */
7596 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7597 font
->mac_scriptcode
= smRoman
;
7599 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7602 if (font
->mac_style
)
7607 font
->min_byte1
= 0;
7608 font
->max_byte1
= 0xff;
7609 font
->min_char_or_byte2
= 0;
7610 font
->max_char_or_byte2
= 0xff;
7612 font
->bounds
.rows
= xmalloc (sizeof (XCharStructRow
*) * 0x100);
7613 if (font
->bounds
.rows
== NULL
)
7615 mac_unload_font (&one_mac_display_info
, font
);
7618 bzero (font
->bounds
.rows
, sizeof (XCharStructRow
*) * 0x100);
7619 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStructRow
));
7620 if (font
->bounds
.rows
[0] == NULL
)
7622 mac_unload_font (&one_mac_display_info
, font
);
7625 bzero (font
->bounds
.rows
[0], sizeof (XCharStructRow
));
7627 #if USE_CG_TEXT_DRAWING
7629 FMFontFamily font_family
;
7631 ATSFontRef ats_font
;
7633 err
= FMGetFontFamilyInstanceFromFont (font_id
, &font_family
, &style
);
7635 err
= FMGetFontFromFontFamilyInstance (font_family
, fontface
,
7637 /* Use CG text drawing if italic/bold is not synthesized. */
7638 if (err
== noErr
&& style
== fontface
)
7640 ats_font
= FMGetATSFontRefFromFont (font_id
);
7641 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7646 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7647 if (font
->cg_glyphs
)
7648 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7650 space_bounds
= font
->bounds
.rows
[0]->per_char
+ 0x20;
7651 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7652 &font
->ascent
, &font
->descent
,
7654 #if USE_CG_TEXT_DRAWING
7655 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7663 mac_unload_font (&one_mac_display_info
, font
);
7666 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], 0x20);
7668 pcm
= font
->bounds
.rows
[0]->per_char
;
7669 for (c
= 0x21; c
<= 0xff; c
++)
7672 /* Soft hyphen is not supported in ATSUI. */
7680 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
7681 #if USE_CG_TEXT_DRAWING
7682 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7688 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], c
);
7690 #if USE_CG_TEXT_DRAWING
7691 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7693 /* Don't use CG text drawing if font substitution occurs in
7694 ASCII or Latin-1 characters. */
7695 CGFontRelease (font
->cg_font
);
7696 font
->cg_font
= NULL
;
7697 xfree (font
->cg_glyphs
);
7698 font
->cg_glyphs
= NULL
;
7707 SInt16 old_fontnum
, old_fontsize
;
7709 FontInfo the_fontinfo
;
7710 int is_two_byte_font
;
7712 /* Save the current font number used. */
7714 #if TARGET_API_MAC_CARBON
7715 old_fontnum
= GetPortTextFont (port
);
7716 old_fontsize
= GetPortTextSize (port
);
7717 old_fontface
= GetPortTextFace (port
);
7719 old_fontnum
= port
->txFont
;
7720 old_fontsize
= port
->txSize
;
7721 old_fontface
= port
->txFace
;
7726 TextFace (fontface
);
7728 GetFontInfo (&the_fontinfo
);
7730 font
->ascent
= the_fontinfo
.ascent
;
7731 font
->descent
= the_fontinfo
.descent
;
7733 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7734 || font
->mac_scriptcode
== smTradChinese
7735 || font
->mac_scriptcode
== smSimpChinese
7736 || font
->mac_scriptcode
== smKorean
);
7738 if (is_two_byte_font
)
7742 font
->min_byte1
= 0xa1;
7743 font
->max_byte1
= 0xfe;
7744 font
->min_char_or_byte2
= 0xa1;
7745 font
->max_char_or_byte2
= 0xfe;
7747 /* Use the width of an "ideographic space" of that font
7748 because the_fontinfo.widMax returns the wrong width for
7750 switch (font
->mac_scriptcode
)
7753 font
->min_byte1
= 0x81;
7754 font
->max_byte1
= 0xfc;
7755 font
->min_char_or_byte2
= 0x40;
7756 font
->max_char_or_byte2
= 0xfc;
7757 char_width
= StringWidth("\p\x81\x40");
7760 font
->min_char_or_byte2
= 0x40;
7761 char_width
= StringWidth("\p\xa1\x40");
7764 char_width
= StringWidth("\p\xa1\xa1");
7767 char_width
= StringWidth("\p\xa1\xa1");
7771 font
->bounds
.per_char
= NULL
;
7773 if (fontface
& italic
)
7774 font
->max_bounds
.rbearing
= char_width
+ 1;
7776 font
->max_bounds
.rbearing
= char_width
;
7777 font
->max_bounds
.lbearing
= 0;
7778 font
->max_bounds
.width
= char_width
;
7779 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7780 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7782 font
->min_bounds
= font
->max_bounds
;
7788 font
->min_byte1
= font
->max_byte1
= 0;
7789 font
->min_char_or_byte2
= 0x20;
7790 font
->max_char_or_byte2
= 0xff;
7792 font
->bounds
.per_char
=
7793 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7794 if (font
->bounds
.per_char
== NULL
)
7796 mac_unload_font (&one_mac_display_info
, font
);
7799 bzero (font
->bounds
.per_char
,
7800 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7802 space_bounds
= font
->bounds
.per_char
;
7803 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
7804 space_bounds
, NULL
);
7806 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
7807 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
7810 /* Restore previous font number, size and face. */
7811 TextFont (old_fontnum
);
7812 TextSize (old_fontsize
);
7813 TextFace (old_fontface
);
7820 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
7821 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
7824 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
7826 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
7828 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
7830 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
7833 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
7835 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
7837 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
7839 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
7844 font
->mac_style
== NULL
&&
7846 font
->max_bounds
.width
== font
->min_bounds
.width
7847 && font
->min_bounds
.lbearing
>= 0
7848 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
7850 /* Fixed width and no overhangs. */
7851 xfree (font
->bounds
.per_char
);
7852 font
->bounds
.per_char
= NULL
;
7856 #if !defined (MAC_OS8) || USE_ATSUI
7857 /* AppKit and WebKit do some adjustment to the heights of Courier,
7858 Helvetica, and Times. This only works on the environments where
7859 the XDrawImageString counterpart is never used. */
7860 if (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
7861 || strcmp (family
, "times") == 0)
7862 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
7870 mac_unload_font (dpyinfo
, font
)
7871 struct mac_display_info
*dpyinfo
;
7874 xfree (font
->full_name
);
7876 if (font
->mac_style
)
7880 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
7881 if (font
->bounds
.rows
[i
])
7882 xfree (font
->bounds
.rows
[i
]);
7883 xfree (font
->bounds
.rows
);
7884 ATSUDisposeStyle (font
->mac_style
);
7888 if (font
->bounds
.per_char
)
7889 xfree (font
->bounds
.per_char
);
7890 #if USE_CG_TEXT_DRAWING
7892 CGFontRelease (font
->cg_font
);
7893 if (font
->cg_glyphs
)
7894 xfree (font
->cg_glyphs
);
7900 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7901 pointer to the structure font_info while allocating it dynamically.
7902 If SIZE is 0, load any size of font.
7903 If loading is failed, return NULL. */
7906 x_load_font (f
, fontname
, size
)
7908 register char *fontname
;
7911 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7912 Lisp_Object font_names
;
7914 /* Get a list of all the fonts that match this name. Once we
7915 have a list of matching fonts, we compare them against the fonts
7916 we already have by comparing names. */
7917 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7919 if (!NILP (font_names
))
7924 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7925 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7926 if (dpyinfo
->font_table
[i
].name
7927 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7928 SDATA (XCAR (tail
)))
7929 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7930 SDATA (XCAR (tail
)))))
7931 return (dpyinfo
->font_table
+ i
);
7936 /* Load the font and add it to the table. */
7939 struct MacFontStruct
*font
;
7940 struct font_info
*fontp
;
7941 unsigned long value
;
7944 fontname
= (char *) SDATA (XCAR (font_names
));
7947 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7952 /* Find a free slot in the font table. */
7953 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7954 if (dpyinfo
->font_table
[i
].name
== NULL
)
7957 /* If no free slot found, maybe enlarge the font table. */
7958 if (i
== dpyinfo
->n_fonts
7959 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7962 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7963 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7965 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7968 fontp
= dpyinfo
->font_table
+ i
;
7969 if (i
== dpyinfo
->n_fonts
)
7972 /* Now fill in the slots of *FONTP. */
7974 bzero (fontp
, sizeof (*fontp
));
7976 fontp
->font_idx
= i
;
7977 fontp
->charset
= -1; /* fs_load_font sets it. */
7978 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7979 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7981 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7983 /* Fixed width font. */
7984 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7991 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7992 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7994 fontp
->space_width
= pcm
->width
;
7996 fontp
->space_width
= FONT_WIDTH (font
);
8000 int width
= pcm
->width
;
8001 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8002 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8003 width
+= pcm
->width
;
8004 fontp
->average_width
= width
/ 95;
8007 fontp
->average_width
= FONT_WIDTH (font
);
8010 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8011 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8013 fontp
->size
= font
->max_bounds
.width
;
8014 fontp
->height
= FONT_HEIGHT (font
);
8016 /* For some font, ascent and descent in max_bounds field is
8017 larger than the above value. */
8018 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8019 if (max_height
> fontp
->height
)
8020 fontp
->height
= max_height
;
8023 /* MAC_TODO: The script encoding is irrelevant in unicode? */
8024 /* The slot `encoding' specifies how to map a character
8025 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8026 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8027 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8028 2:0xA020..0xFF7F). For the moment, we don't know which charset
8029 uses this font. So, we set information in fontp->encoding_type
8030 which is never used by any charset. If mapping can't be
8031 decided, set FONT_ENCODING_NOT_DECIDED. */
8032 if (font
->mac_scriptcode
== smJapanese
)
8033 fontp
->encoding_type
= 4;
8036 fontp
->encoding_type
8037 = (font
->max_byte1
== 0
8039 ? (font
->min_char_or_byte2
< 0x80
8040 ? (font
->max_char_or_byte2
< 0x80
8041 ? 0 /* 0x20..0x7F */
8042 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8043 : 1) /* 0xA0..0xFF */
8045 : (font
->min_byte1
< 0x80
8046 ? (font
->max_byte1
< 0x80
8047 ? (font
->min_char_or_byte2
< 0x80
8048 ? (font
->max_char_or_byte2
< 0x80
8049 ? 0 /* 0x2020..0x7F7F */
8050 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8051 : 3) /* 0x20A0..0x7FFF */
8052 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8053 : (font
->min_char_or_byte2
< 0x80
8054 ? (font
->max_char_or_byte2
< 0x80
8055 ? 2 /* 0xA020..0xFF7F */
8056 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8057 : 1))); /* 0xA0A0..0xFFFF */
8060 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8061 fontp
->baseline_offset
8062 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8063 ? (long) value
: 0);
8064 fontp
->relative_compose
8065 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8066 ? (long) value
: 0);
8067 fontp
->default_ascent
8068 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8069 ? (long) value
: 0);
8071 fontp
->baseline_offset
= 0;
8072 fontp
->relative_compose
= 0;
8073 fontp
->default_ascent
= 0;
8076 /* Set global flag fonts_changed_p to non-zero if the font loaded
8077 has a character with a smaller width than any other character
8078 before, or if the font loaded has a smaller height than any
8079 other font loaded before. If this happens, it will make a
8080 glyph matrix reallocation necessary. */
8081 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8088 /* Return a pointer to struct font_info of a font named FONTNAME for
8089 frame F. If no such font is loaded, return NULL. */
8092 x_query_font (f
, fontname
)
8094 register char *fontname
;
8096 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8099 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8100 if (dpyinfo
->font_table
[i
].name
8101 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8102 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8103 return (dpyinfo
->font_table
+ i
);
8108 /* Find a CCL program for a font specified by FONTP, and set the member
8109 `encoder' of the structure. */
8112 x_find_ccl_program (fontp
)
8113 struct font_info
*fontp
;
8115 Lisp_Object list
, elt
;
8117 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8121 && STRINGP (XCAR (elt
))
8122 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8128 struct ccl_program
*ccl
8129 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8131 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8134 fontp
->font_encoder
= ccl
;
8140 /* The Mac Event loop code */
8142 #if !TARGET_API_MAC_CARBON
8144 #include <Quickdraw.h>
8145 #include <Balloons.h>
8146 #include <Devices.h>
8148 #include <Gestalt.h>
8150 #include <Processes.h>
8152 #include <ToolUtils.h>
8153 #include <TextUtils.h>
8154 #include <Dialogs.h>
8157 #include <Resources.h>
8162 #endif /* ! TARGET_API_MAC_CARBON */
8167 #define WINDOW_RESOURCE 128
8168 #define TERM_WINDOW_RESOURCE 129
8170 #define DEFAULT_NUM_COLS 80
8172 #define MIN_DOC_SIZE 64
8173 #define MAX_DOC_SIZE 32767
8175 #define EXTRA_STACK_ALLOC (256 * 1024)
8177 #define ARGV_STRING_LIST_ID 129
8178 #define ABOUT_ALERT_ID 128
8179 #define RAM_TOO_LARGE_ALERT_ID 129
8181 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8182 Lisp_Object Qreverse
;
8185 /* Modifier associated with the control key, or nil to ignore. */
8186 Lisp_Object Vmac_control_modifier
;
8188 /* Modifier associated with the option key, or nil to ignore. */
8189 Lisp_Object Vmac_option_modifier
;
8191 /* Modifier associated with the command key, or nil to ignore. */
8192 Lisp_Object Vmac_command_modifier
;
8194 /* Modifier associated with the function key, or nil to ignore. */
8195 Lisp_Object Vmac_function_modifier
;
8197 /* True if the option and command modifiers should be used to emulate
8198 a three button mouse */
8199 Lisp_Object Vmac_emulate_three_button_mouse
;
8201 #if USE_CARBON_EVENTS
8202 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8203 mouse-2, instead of mouse-3. */
8204 int mac_wheel_button_is_mouse_2
;
8206 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8207 for processing before Emacs sees it. */
8208 int mac_pass_command_to_system
;
8210 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8211 for processing before Emacs sees it. */
8212 int mac_pass_control_to_system
;
8215 /* Points to the variable `inev' in the function XTread_socket. It is
8216 used for passing an input event to the function back from
8217 Carbon/Apple event handlers. */
8218 static struct input_event
*read_socket_inev
= NULL
;
8220 Point saved_menu_event_location
;
8223 #if USE_CARBON_EVENTS
8224 static Lisp_Object Qhicommand
;
8226 extern int mac_ready_for_apple_events
;
8227 extern Lisp_Object Qundefined
;
8228 extern void init_apple_event_handler
P_ ((void));
8229 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8230 Lisp_Object
*, Lisp_Object
*,
8232 extern OSErr init_coercion_handler
P_ ((void));
8234 #if TARGET_API_MAC_CARBON
8236 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
8237 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
8238 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
8239 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
8242 #if USE_CARBON_EVENTS
8244 extern void init_service_handler ();
8245 static Lisp_Object Qservices
, Qpaste
, Qperform
;
8247 /* Window Event Handler */
8248 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8251 OSErr
install_window_handler (WindowPtr
);
8253 extern void init_emacs_passwd_dir ();
8254 extern int emacs_main (int, char **, char **);
8256 extern void initialize_applescript();
8257 extern void terminate_applescript();
8260 #if USE_CARBON_EVENTS
8261 mac_to_emacs_modifiers (UInt32 mods
)
8263 mac_to_emacs_modifiers (EventModifiers mods
)
8266 unsigned int result
= 0;
8267 if (mods
& shiftKey
)
8268 result
|= shift_modifier
;
8270 /* Deactivated to simplify configuration:
8271 if Vmac_option_modifier is non-NIL, we fully process the Option
8272 key. Otherwise, we only process it if an additional Ctrl or Command
8273 is pressed. That way the system may convert the character to a
8275 if ((mods & optionKey) &&
8276 (( !NILP(Vmac_option_modifier) ||
8277 ((mods & cmdKey) || (mods & controlKey))))) */
8279 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8280 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8282 result
|= XUINT(val
);
8284 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8285 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8287 result
|= XUINT(val
);
8289 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8290 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8292 result
|= XUINT(val
);
8296 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8297 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8299 result
|= XUINT(val
);
8307 mac_get_emulated_btn ( UInt32 modifiers
)
8310 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8311 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8312 if (modifiers
& cmdKey
)
8313 result
= cmdIs3
? 2 : 1;
8314 else if (modifiers
& optionKey
)
8315 result
= cmdIs3
? 1 : 2;
8320 #if USE_CARBON_EVENTS
8321 /* Obtains the event modifiers from the event ref and then calls
8322 mac_to_emacs_modifiers. */
8324 mac_event_to_emacs_modifiers (EventRef eventRef
)
8327 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8328 sizeof (UInt32
), NULL
, &mods
);
8329 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8330 GetEventClass(eventRef
) == kEventClassMouse
)
8332 mods
&= ~(optionKey
| cmdKey
);
8334 return mac_to_emacs_modifiers (mods
);
8337 /* Given an event ref, return the code to use for the mouse button
8338 code in the emacs input_event. */
8340 mac_get_mouse_btn (EventRef ref
)
8342 EventMouseButton result
= kEventMouseButtonPrimary
;
8343 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8344 sizeof (EventMouseButton
), NULL
, &result
);
8347 case kEventMouseButtonPrimary
:
8348 if (NILP (Vmac_emulate_three_button_mouse
))
8352 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8353 sizeof (UInt32
), NULL
, &mods
);
8354 return mac_get_emulated_btn(mods
);
8356 case kEventMouseButtonSecondary
:
8357 return mac_wheel_button_is_mouse_2
? 2 : 1;
8358 case kEventMouseButtonTertiary
:
8359 case 4: /* 4 is the number for the mouse wheel button */
8360 return mac_wheel_button_is_mouse_2
? 1 : 2;
8366 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8367 events. However the click of the mouse wheel is not converted to a
8368 mouseDown or mouseUp event. Likewise for dead key down events.
8369 This calls ConvertEventRef, but then checks to see if it is a mouse
8370 up/down, or a dead key down carbon event that has not been
8371 converted, and if so, converts it by hand (to be picked up in the
8372 XTread_socket loop). */
8373 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8375 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8380 switch (GetEventClass (eventRef
))
8382 case kEventClassMouse
:
8383 switch (GetEventKind (eventRef
))
8385 case kEventMouseDown
:
8386 eventRec
->what
= mouseDown
;
8391 eventRec
->what
= mouseUp
;
8400 case kEventClassKeyboard
:
8401 switch (GetEventKind (eventRef
))
8403 case kEventRawKeyDown
:
8405 unsigned char char_codes
;
8408 eventRec
->what
= keyDown
;
8409 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
8410 NULL
, sizeof (char), NULL
, &char_codes
);
8411 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
8412 NULL
, sizeof (UInt32
), NULL
, &key_code
);
8413 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8429 /* Need where and when. */
8432 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8433 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8434 /* Use two step process because new event modifiers are 32-bit
8435 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8436 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8437 NULL
, sizeof (UInt32
), NULL
, &mods
);
8438 eventRec
->modifiers
= mods
;
8440 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8451 Handle menubar_handle
;
8452 MenuHandle menu_handle
;
8454 menubar_handle
= GetNewMBar (128);
8455 if(menubar_handle
== NULL
)
8457 SetMenuBar (menubar_handle
);
8460 #if !TARGET_API_MAC_CARBON
8461 menu_handle
= GetMenuHandle (M_APPLE
);
8462 if(menu_handle
!= NULL
)
8463 AppendResMenu (menu_handle
,'DRVR');
8471 do_init_managers (void)
8473 #if !TARGET_API_MAC_CARBON
8474 InitGraf (&qd
.thePort
);
8476 FlushEvents (everyEvent
, 0);
8481 #endif /* !TARGET_API_MAC_CARBON */
8484 #if !TARGET_API_MAC_CARBON
8485 /* set up some extra stack space for use by emacs */
8486 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8488 /* MaxApplZone must be called for AppleScript to execute more
8489 complicated scripts */
8492 #endif /* !TARGET_API_MAC_CARBON */
8496 do_check_ram_size (void)
8498 SInt32 physical_ram_size
, logical_ram_size
;
8500 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8501 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8502 || physical_ram_size
> (1 << VALBITS
)
8503 || logical_ram_size
> (1 << VALBITS
))
8505 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8511 do_window_update (WindowPtr win
)
8513 struct frame
*f
= mac_window_to_frame (win
);
8517 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8519 if (win
!= tip_window
)
8521 if (f
->async_visible
== 0)
8523 /* Update events may occur when a frame gets iconified. */
8525 f
->async_visible
= 1;
8526 f
->async_iconified
= 0;
8527 SET_FRAME_GARBAGED (f
);
8533 #if TARGET_API_MAC_CARBON
8534 RgnHandle region
= NewRgn ();
8536 GetPortVisibleRegion (GetWindowPort (win
), region
);
8537 GetRegionBounds (region
, &r
);
8538 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8539 UpdateControls (win
, region
);
8540 DisposeRgn (region
);
8542 r
= (*win
->visRgn
)->rgnBBox
;
8543 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8544 UpdateControls (win
, win
->visRgn
);
8553 is_emacs_window (WindowPtr win
)
8555 Lisp_Object tail
, frame
;
8560 FOR_EACH_FRAME (tail
, frame
)
8561 if (FRAME_MAC_P (XFRAME (frame
)))
8562 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8571 /* Window-activate events will do the job. */
8577 /* Window-deactivate events will do the job. */
8582 do_apple_menu (SInt16 menu_item
)
8584 #if !TARGET_API_MAC_CARBON
8586 SInt16 da_driver_refnum
;
8588 if (menu_item
== I_ABOUT
)
8589 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8592 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8593 da_driver_refnum
= OpenDeskAcc (item_name
);
8595 #endif /* !TARGET_API_MAC_CARBON */
8599 do_menu_choice (SInt32 menu_choice
)
8601 SInt16 menu_id
, menu_item
;
8603 menu_id
= HiWord (menu_choice
);
8604 menu_item
= LoWord (menu_choice
);
8612 do_apple_menu (menu_item
);
8617 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8618 MenuHandle menu
= GetMenuHandle (menu_id
);
8623 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8624 menubar_selection_callback (f
, refcon
);
8633 /* Handle drags in size box. Based on code contributed by Ben
8634 Mesander and IM - Window Manager A. */
8637 do_grow_window (WindowPtr w
, EventRecord
*e
)
8640 int rows
, columns
, width
, height
;
8641 struct frame
*f
= mac_window_to_frame (w
);
8642 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8643 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8644 #if TARGET_API_MAC_CARBON
8650 if (size_hints
->flags
& PMinSize
)
8652 min_width
= size_hints
->min_width
;
8653 min_height
= size_hints
->min_height
;
8655 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8657 #if TARGET_API_MAC_CARBON
8658 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8660 height
= new_rect
.bottom
- new_rect
.top
;
8661 width
= new_rect
.right
- new_rect
.left
;
8663 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8664 /* see if it really changed size */
8667 height
= HiWord (grow_size
);
8668 width
= LoWord (grow_size
);
8671 if (width
!= FRAME_PIXEL_WIDTH (f
)
8672 || height
!= FRAME_PIXEL_HEIGHT (f
))
8674 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8675 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8677 x_set_window_size (f
, 0, columns
, rows
);
8682 /* Handle clicks in zoom box. Calculation of "standard state" based
8683 on code in IM - Window Manager A and code contributed by Ben
8684 Mesander. The standard state of an Emacs window is 80-characters
8685 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8688 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8691 Rect zoom_rect
, port_rect
;
8693 int w_title_height
, columns
, rows
, width
, height
;
8694 struct frame
*f
= mac_window_to_frame (w
);
8695 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8697 #if TARGET_API_MAC_CARBON
8699 Point standard_size
;
8701 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8702 standard_size
.v
= dpyinfo
->height
;
8704 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8705 zoom_in_or_out
= inZoomIn
;
8708 /* Adjust the standard size according to character boundaries. */
8710 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8711 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8712 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8713 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8714 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8715 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8716 && port_rect
.left
== zoom_rect
.left
8717 && port_rect
.top
== zoom_rect
.top
)
8718 zoom_in_or_out
= inZoomIn
;
8720 zoom_in_or_out
= inZoomOut
;
8723 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8725 #else /* not TARGET_API_MAC_CARBON */
8726 GetPort (&save_port
);
8728 SetPortWindowPort (w
);
8730 /* Clear window to avoid flicker. */
8731 EraseRect (&(w
->portRect
));
8732 if (zoom_in_or_out
== inZoomOut
)
8734 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8735 LocalToGlobal (&top_left
);
8737 /* calculate height of window's title bar */
8738 w_title_height
= top_left
.v
- 1
8739 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8741 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8742 zoom_rect
= qd
.screenBits
.bounds
;
8743 zoom_rect
.top
+= w_title_height
;
8744 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8746 zoom_rect
.right
= zoom_rect
.left
8747 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8749 /* Adjust the standard size according to character boundaries. */
8750 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8752 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8754 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8758 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8760 SetPort (save_port
);
8761 #endif /* not TARGET_API_MAC_CARBON */
8763 /* retrieve window size and update application values */
8764 #if TARGET_API_MAC_CARBON
8765 GetWindowPortBounds (w
, &port_rect
);
8767 port_rect
= w
->portRect
;
8769 height
= port_rect
.bottom
- port_rect
.top
;
8770 width
= port_rect
.right
- port_rect
.left
;
8772 if (width
!= FRAME_PIXEL_WIDTH (f
)
8773 || height
!= FRAME_PIXEL_HEIGHT (f
))
8775 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8776 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8778 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8779 SET_FRAME_GARBAGED (f
);
8780 cancel_mouse_face (f
);
8782 FRAME_PIXEL_WIDTH (f
) = width
;
8783 FRAME_PIXEL_HEIGHT (f
) = height
;
8785 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8789 mac_store_apple_event (class, id
, desc
)
8790 Lisp_Object
class, id
;
8794 struct input_event buf
;
8797 desc_copy
= xmalloc (sizeof (AEDesc
));
8798 if (desc_copy
== NULL
)
8801 err
= AEDuplicateDesc (desc
, desc_copy
);
8806 buf
.kind
= MAC_APPLE_EVENT
;
8809 buf
.code
= (int)desc_copy
;
8810 XSETFRAME (buf
.frame_or_window
,
8811 mac_focus_frame (&one_mac_display_info
));
8813 kbd_buffer_store_event (&buf
);
8820 mac_make_lispy_event_code (code
)
8823 AEDesc
*desc
= (AEDesc
*)code
;
8826 obj
= mac_aedesc_to_lisp (desc
);
8827 AEDisposeDesc (desc
);
8833 #if USE_CARBON_EVENTS
8834 static pascal OSStatus
8835 mac_handle_command_event (next_handler
, event
, data
)
8836 EventHandlerCallRef next_handler
;
8843 Lisp_Object class_key
, id_key
, binding
;
8845 result
= CallNextEventHandler (next_handler
, event
);
8846 if (result
!= eventNotHandledErr
)
8849 GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8850 sizeof (HICommand
), NULL
, &command
);
8852 if (command
.commandID
== 0)
8853 return eventNotHandledErr
;
8855 /* A HICommand event is mapped to an Apple event whose event class
8856 symbol is `hicommand' and event ID is its command ID. */
8857 class_key
= Qhicommand
;
8858 mac_find_apple_event_spec (0, command
.commandID
,
8859 &class_key
, &id_key
, &binding
);
8860 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
8861 if (INTEGERP (binding
))
8862 return XINT (binding
);
8865 AppleEvent apple_event
;
8867 static EventParamName names
[] = {kEventParamDirectObject
,
8868 kEventParamKeyModifiers
};
8869 static EventParamType types
[] = {typeHICommand
,
8871 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
8875 err
= mac_store_apple_event (class_key
, id_key
, &apple_event
);
8876 AEDisposeDesc (&apple_event
);
8882 return eventNotHandledErr
;
8886 init_command_handler ()
8889 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8890 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8892 if (handle_command_eventUPP
== NULL
)
8893 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8894 return InstallApplicationEventHandler (handle_command_eventUPP
,
8895 GetEventTypeCount (specs
), specs
,
8899 static pascal OSStatus
8900 mac_handle_window_event (next_handler
, event
, data
)
8901 EventHandlerCallRef next_handler
;
8908 XSizeHints
*size_hints
;
8910 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8911 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8913 switch (GetEventKind (event
))
8915 case kEventWindowUpdate
:
8916 result
= CallNextEventHandler (next_handler
, event
);
8917 if (result
!= eventNotHandledErr
)
8920 do_window_update (wp
);
8923 case kEventWindowBoundsChanging
:
8924 result
= CallNextEventHandler (next_handler
, event
);
8925 if (result
!= eventNotHandledErr
)
8928 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8929 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8930 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8931 if ((attributes
& kWindowBoundsChangeUserResize
)
8932 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8933 == (PResizeInc
| PBaseSize
| PMinSize
)))
8938 GetEventParameter (event
, kEventParamCurrentBounds
,
8940 NULL
, sizeof (Rect
), NULL
, &bounds
);
8941 width
= bounds
.right
- bounds
.left
;
8942 height
= bounds
.bottom
- bounds
.top
;
8944 if (width
< size_hints
->min_width
)
8945 width
= size_hints
->min_width
;
8947 width
= size_hints
->base_width
8948 + (int) ((width
- size_hints
->base_width
)
8949 / (float) size_hints
->width_inc
+ .5)
8950 * size_hints
->width_inc
;
8952 if (height
< size_hints
->min_height
)
8953 height
= size_hints
->min_height
;
8955 height
= size_hints
->base_height
8956 + (int) ((height
- size_hints
->base_height
)
8957 / (float) size_hints
->height_inc
+ .5)
8958 * size_hints
->height_inc
;
8960 bounds
.right
= bounds
.left
+ width
;
8961 bounds
.bottom
= bounds
.top
+ height
;
8962 SetEventParameter (event
, kEventParamCurrentBounds
,
8963 typeQDRectangle
, sizeof (Rect
), &bounds
);
8968 case kEventWindowShown
:
8969 case kEventWindowHidden
:
8970 case kEventWindowExpanded
:
8971 case kEventWindowCollapsed
:
8972 result
= CallNextEventHandler (next_handler
, event
);
8974 mac_handle_visibility_change (mac_window_to_frame (wp
));
8980 return eventNotHandledErr
;
8983 static pascal OSStatus
8984 mac_handle_mouse_event (next_handler
, event
, data
)
8985 EventHandlerCallRef next_handler
;
8991 switch (GetEventKind (event
))
8993 case kEventMouseWheelMoved
:
8997 EventMouseWheelAxis axis
;
9001 result
= CallNextEventHandler (next_handler
, event
);
9002 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9005 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9006 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9007 f
= mac_window_to_frame (wp
);
9008 if (f
!= mac_focus_frame (&one_mac_display_info
))
9011 GetEventParameter (event
, kEventParamMouseWheelAxis
,
9012 typeMouseWheelAxis
, NULL
,
9013 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9014 if (axis
!= kEventMouseWheelAxisY
)
9017 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
9018 NULL
, sizeof (SInt32
), NULL
, &delta
);
9019 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
9020 NULL
, sizeof (Point
), NULL
, &point
);
9021 read_socket_inev
->kind
= WHEEL_EVENT
;
9022 read_socket_inev
->code
= 0;
9023 read_socket_inev
->modifiers
=
9024 (mac_event_to_emacs_modifiers (event
)
9025 | ((delta
< 0) ? down_modifier
: up_modifier
));
9026 SetPortWindowPort (wp
);
9027 GlobalToLocal (&point
);
9028 XSETINT (read_socket_inev
->x
, point
.h
);
9029 XSETINT (read_socket_inev
->y
, point
.v
);
9030 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9040 return eventNotHandledErr
;
9045 mac_store_services_event (event
)
9049 AppleEvent apple_event
;
9052 switch (GetEventKind (event
))
9054 case kEventServicePaste
:
9056 err
= create_apple_event_from_event_ref (event
, 0, NULL
, NULL
,
9060 case kEventServicePerform
:
9062 static EventParamName names
[] = {kEventParamServiceMessageName
,
9063 kEventParamServiceUserData
};
9064 static EventParamType types
[] = {typeCFStringRef
,
9068 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
9079 err
= mac_store_apple_event (Qservices
, id_key
, &apple_event
);
9080 AEDisposeDesc (&apple_event
);
9085 #endif /* MAC_OSX */
9086 #endif /* USE_CARBON_EVENTS */
9090 install_window_handler (window
)
9094 #if USE_CARBON_EVENTS
9095 EventTypeSpec specs_window
[] =
9096 {{kEventClassWindow
, kEventWindowUpdate
},
9097 {kEventClassWindow
, kEventWindowBoundsChanging
},
9098 {kEventClassWindow
, kEventWindowShown
},
9099 {kEventClassWindow
, kEventWindowHidden
},
9100 {kEventClassWindow
, kEventWindowExpanded
},
9101 {kEventClassWindow
, kEventWindowCollapsed
}};
9102 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9103 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9104 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9106 if (handle_window_eventUPP
== NULL
)
9107 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9108 if (handle_mouse_eventUPP
== NULL
)
9109 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9110 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9111 GetEventTypeCount (specs_window
),
9112 specs_window
, NULL
, NULL
);
9114 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9115 GetEventTypeCount (specs_mouse
),
9116 specs_mouse
, NULL
, NULL
);
9118 #if TARGET_API_MAC_CARBON
9119 if (mac_do_track_dragUPP
== NULL
)
9120 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
9121 if (mac_do_receive_dragUPP
== NULL
)
9122 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
9125 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
9127 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
9133 remove_window_handler (window
)
9136 #if TARGET_API_MAC_CARBON
9137 if (mac_do_track_dragUPP
)
9138 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
9139 if (mac_do_receive_dragUPP
)
9140 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
9144 #if TARGET_API_MAC_CARBON
9146 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
9147 void *handlerRefCon
, DragReference theDrag
)
9149 static int can_accept
;
9152 ItemReference theItem
;
9153 FlavorFlags theFlags
;
9156 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9157 return dragNotAcceptedErr
;
9161 case kDragTrackingEnterHandler
:
9162 CountDragItems (theDrag
, &items
);
9164 for (index
= 1; index
<= items
; index
++)
9166 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9167 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9168 if (result
== noErr
)
9176 case kDragTrackingEnterWindow
:
9179 RgnHandle hilite_rgn
= NewRgn ();
9181 struct frame
*f
= mac_window_to_frame (window
);
9183 GetWindowPortBounds (window
, &r
);
9184 OffsetRect (&r
, -r
.left
, -r
.top
);
9185 RectRgn (hilite_rgn
, &r
);
9186 ShowDragHilite (theDrag
, hilite_rgn
, true);
9187 DisposeRgn (hilite_rgn
);
9188 SetThemeCursor (kThemeCopyArrowCursor
);
9192 case kDragTrackingInWindow
:
9195 case kDragTrackingLeaveWindow
:
9198 struct frame
*f
= mac_window_to_frame (window
);
9200 HideDragHilite (theDrag
);
9201 SetThemeCursor (kThemeArrowCursor
);
9205 case kDragTrackingLeaveHandler
:
9213 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9214 DragReference theDrag
)
9218 FlavorFlags theFlags
;
9221 ItemReference theItem
;
9223 Size size
= sizeof (HFSFlavor
);
9224 Lisp_Object file_list
;
9226 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9227 return dragNotAcceptedErr
;
9230 GetDragMouse (theDrag
, &mouse
, 0L);
9231 CountDragItems (theDrag
, &items
);
9232 for (index
= 1; index
<= items
; index
++)
9234 /* Only handle file references. */
9235 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9236 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9237 if (result
== noErr
)
9242 err
= GetFlavorData (theDrag
, theItem
, flavorTypeHFS
,
9245 err
= AECoercePtr (typeFSS
, &data
.fileSpec
, sizeof (FSSpec
),
9246 TYPE_FILE_NAME
, &desc
);
9251 /* x-dnd functions expect undecoded filenames. */
9252 file
= make_uninit_string (AEGetDescDataSize (&desc
));
9253 err
= AEGetDescData (&desc
, SDATA (file
), SBYTES (file
));
9255 file_list
= Fcons (file
, file_list
);
9256 AEDisposeDesc (&desc
);
9260 /* If there are items in the list, construct an event and post it to
9261 the queue like an interrupt using kbd_buffer_store_event. */
9262 if (!NILP (file_list
))
9264 struct input_event event
;
9266 struct frame
*f
= mac_window_to_frame (window
);
9269 GlobalToLocal (&mouse
);
9270 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
9272 event
.kind
= DRAG_N_DROP_EVENT
;
9274 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9275 event
.timestamp
= TickCount () * (1000 / 60);
9276 XSETINT (event
.x
, mouse
.h
);
9277 XSETINT (event
.y
, mouse
.v
);
9278 XSETFRAME (frame
, f
);
9279 event
.frame_or_window
= frame
;
9280 event
.arg
= file_list
;
9281 /* Post to the interrupt queue */
9282 kbd_buffer_store_event (&event
);
9283 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9285 ProcessSerialNumber psn
;
9286 GetCurrentProcess (&psn
);
9287 SetFrontProcess (&psn
);
9293 return dragNotAcceptedErr
;
9300 profiler_exit_proc ()
9302 ProfilerDump ("\pEmacs.prof");
9307 /* These few functions implement Emacs as a normal Mac application
9308 (almost): set up the heap and the Toolbox, handle necessary system
9309 events plus a few simple menu events. They also set up Emacs's
9310 access to functions defined in the rest of this file. Emacs uses
9311 function hooks to perform all its terminal I/O. A complete list of
9312 these functions appear in termhooks.h. For what they do, read the
9313 comments there and see also w32term.c and xterm.c. What's
9314 noticeably missing here is the event loop, which is normally
9315 present in most Mac application. After performing the necessary
9316 Mac initializations, main passes off control to emacs_main
9317 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9318 (defined further below) to read input. This is where
9319 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9326 #if __profile__ /* is the profiler on? */
9327 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9332 /* set creator and type for files created by MSL */
9337 do_init_managers ();
9342 do_check_ram_size ();
9345 init_emacs_passwd_dir ();
9349 init_coercion_handler ();
9351 initialize_applescript ();
9353 init_apple_event_handler ();
9359 /* set up argv array from STR# resource */
9360 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9364 /* free up AppleScript resources on exit */
9365 atexit (terminate_applescript
);
9367 #if __profile__ /* is the profiler on? */
9368 atexit (profiler_exit_proc
);
9371 /* 3rd param "envp" never used in emacs_main */
9372 (void) emacs_main (argc
, argv
, 0);
9375 /* Never reached - real exit in Fkill_emacs */
9380 /* Table for translating Mac keycode to X keysym values. Contributed
9382 Mapping for special keys is now identical to that in Apple X11
9383 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9384 on the right of the Cmd key on laptops, and fn + `enter' (->
9386 static unsigned char keycode_to_xkeysym_table
[] = {
9387 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9388 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9389 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9391 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9392 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9393 /*0x38*/ 0, 0, 0, 0,
9394 /*0x3C*/ 0, 0, 0, 0,
9396 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9397 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9398 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9399 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9401 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9402 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9403 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9404 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9406 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9407 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9408 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9409 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9411 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9412 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9413 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9414 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9419 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9421 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9422 return *xKeySym
!= 0;
9425 static unsigned char fn_keycode_to_xkeysym_table
[] = {
9426 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9427 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9428 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9430 /*0x30*/ 0, 0, 0, 0,
9431 /*0x34*/ 0, 0, 0, 0,
9432 /*0x38*/ 0, 0, 0, 0,
9433 /*0x3C*/ 0, 0, 0, 0,
9435 /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
9436 /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
9437 /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
9438 /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
9440 /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
9441 /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
9442 /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
9443 /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
9445 /*0x60*/ 0, 0, 0, 0,
9446 /*0x64*/ 0, 0, 0, 0,
9447 /*0x68*/ 0, 0, 0, 0,
9448 /*0x6C*/ 0, 0, 0, 0,
9450 /*0x70*/ 0, 0, 0, 0,
9451 /*0x74*/ 0, 0, 0, 0,
9452 /*0x78*/ 0, 0, 0, 0,
9456 convert_fn_keycode (EventRef eventRef
, int keyCode
, int *newCode
)
9459 /* Use the special map to translate keys when function modifier is
9460 to be caught. KeyTranslate can't be used in that case.
9461 We can't detect the function key using the input_event.modifiers,
9462 because this uses the high word of an UInt32. Therefore,
9463 we'll just read it out of the original eventRef.
9467 /* TODO / known issues
9469 - Fn-Shift-j is regonized as Fn-j and not Fn-J.
9470 The above table always translates to lower characters. We need to use
9471 the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
9473 - The table is meant for English language keyboards, and it will work
9474 for many others with the exception of key combinations like Fn-ö on
9475 a German keyboard, which is currently mapped to Fn-;.
9476 How to solve this without keeping separate tables for all keyboards
9477 around? KeyTranslate isn't of much help here, as it only takes a 16-bit
9478 value for keycode with the modifiers in he high byte, i.e. no room for the
9479 Fn modifier. That's why we need the table.
9484 if (!NILP(Vmac_function_modifier
))
9486 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9487 sizeof (UInt32
), NULL
, &mods
);
9488 if (mods
& kEventKeyModifierFnMask
)
9489 { *newCode
= fn_keycode_to_xkeysym_table
[keyCode
& 0x7f];
9491 return (*newCode
!= 0);
9499 backtranslate_modified_keycode(int mods
, int keycode
, int def
)
9501 EventModifiers mapped_modifiers
=
9502 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9503 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9504 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9506 if (mods
& mapped_modifiers
)
9508 /* This code comes from Keyboard Resource,
9509 Appendix C of IM - Text. This is necessary
9510 since shift is ignored in KCHR table
9511 translation when option or command is pressed.
9512 It also does not translate correctly
9513 control-shift chars like C-% so mask off shift
9516 Not done for combinations with the option key (alt)
9517 unless it is to be caught by Emacs: this is
9518 to preserve key combinations translated by the OS
9521 /* Mask off modifier keys that are mapped to some Emacs
9523 int new_modifiers
= mods
& ~mapped_modifiers
;
9524 /* set high byte of keycode to modifier high byte*/
9525 int new_keycode
= keycode
| new_modifiers
;
9526 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9527 unsigned long some_state
= 0;
9528 return (int) KeyTranslate (kchr_ptr
, new_keycode
,
9529 &some_state
) & 0xff;
9530 /* TO DO: Recognize two separate resulting characters, "for
9531 example, when the user presses Option-E followed by N, you
9532 can map this through the KeyTranslate function using the
9533 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
9534 returns as two characters in the bytes labeled Character code
9535 1 and Character code 2." (from Carbon API doc) */
9543 #if !USE_CARBON_EVENTS
9544 static RgnHandle mouse_region
= NULL
;
9547 mac_wait_next_event (er
, sleep_time
, dequeue
)
9552 static EventRecord er_buf
= {nullEvent
};
9553 UInt32 target_tick
, current_tick
;
9554 EventMask event_mask
;
9556 if (mouse_region
== NULL
)
9557 mouse_region
= NewRgn ();
9559 event_mask
= everyEvent
;
9560 if (!mac_ready_for_apple_events
)
9561 event_mask
-= highLevelEventMask
;
9563 current_tick
= TickCount ();
9564 target_tick
= current_tick
+ sleep_time
;
9566 if (er_buf
.what
== nullEvent
)
9567 while (!WaitNextEvent (event_mask
, &er_buf
,
9568 target_tick
- current_tick
, mouse_region
))
9570 current_tick
= TickCount ();
9571 if (target_tick
<= current_tick
)
9577 er_buf
.what
= nullEvent
;
9580 #endif /* not USE_CARBON_EVENTS */
9582 /* Emacs calls this whenever it wants to read an input event from the
9585 XTread_socket (sd
, expected
, hold_quit
)
9587 struct input_event
*hold_quit
;
9589 struct input_event inev
;
9591 #if USE_CARBON_EVENTS
9593 EventTargetRef toolbox_dispatcher
;
9596 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9598 if (interrupt_input_blocked
)
9600 interrupt_input_pending
= 1;
9604 interrupt_input_pending
= 0;
9607 /* So people can tell when we have read the available input. */
9608 input_signal_count
++;
9612 #if USE_CARBON_EVENTS
9613 toolbox_dispatcher
= GetEventDispatcherTarget ();
9615 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9616 kEventRemoveFromQueue
, &eventRef
))
9617 #else /* !USE_CARBON_EVENTS */
9618 while (mac_wait_next_event (&er
, 0, true))
9619 #endif /* !USE_CARBON_EVENTS */
9623 unsigned long timestamp
;
9625 /* It is necessary to set this (additional) argument slot of an
9626 event to nil because keyboard.c protects incompletely
9627 processed event from being garbage collected by placing them
9628 in the kbd_buffer_gcpro vector. */
9630 inev
.kind
= NO_EVENT
;
9633 #if USE_CARBON_EVENTS
9634 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9636 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9639 #if USE_CARBON_EVENTS
9640 /* Handle new events */
9641 if (!mac_convert_event_ref (eventRef
, &er
))
9643 /* There used to be a handler for the kEventMouseWheelMoved
9644 event here. But as of Mac OS X 10.4, this kind of event
9645 is not directly posted to the main event queue by
9646 two-finger scrolling on the trackpad. Instead, some
9647 private event is posted and it is converted to a wheel
9648 event by the default handler for the application target.
9649 The converted one can be received by a Carbon event
9650 handler installed on a window target. */
9651 read_socket_inev
= &inev
;
9652 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9653 read_socket_inev
= NULL
;
9656 #endif /* USE_CARBON_EVENTS */
9662 WindowPtr window_ptr
;
9663 ControlPartCode part_code
;
9666 #if USE_CARBON_EVENTS
9667 /* This is needed to send mouse events like aqua window
9668 buttons to the correct handler. */
9669 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9670 != eventNotHandledErr
)
9673 last_mouse_glyph_frame
= 0;
9675 if (dpyinfo
->grabbed
&& last_mouse_frame
9676 && FRAME_LIVE_P (last_mouse_frame
))
9678 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9679 part_code
= inContent
;
9683 part_code
= FindWindow (er
.where
, &window_ptr
);
9684 if (tip_window
&& window_ptr
== tip_window
)
9686 HideWindow (tip_window
);
9687 part_code
= FindWindow (er
.where
, &window_ptr
);
9691 if (er
.what
!= mouseDown
&&
9692 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
9698 f
= mac_focus_frame (dpyinfo
);
9699 saved_menu_event_location
= er
.where
;
9700 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9701 XSETFRAME (inev
.frame_or_window
, f
);
9705 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9706 SelectWindow (window_ptr
);
9709 ControlPartCode control_part_code
;
9711 Point mouse_loc
= er
.where
;
9713 ControlKind control_kind
;
9716 f
= mac_window_to_frame (window_ptr
);
9717 /* convert to local coordinates of new window */
9718 SetPortWindowPort (window_ptr
);
9720 GlobalToLocal (&mouse_loc
);
9721 #if TARGET_API_MAC_CARBON
9722 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9723 &control_part_code
);
9726 GetControlKind (ch
, &control_kind
);
9729 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9733 #if USE_CARBON_EVENTS
9734 inev
.code
= mac_get_mouse_btn (eventRef
);
9735 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9737 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9738 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9740 XSETINT (inev
.x
, mouse_loc
.h
);
9741 XSETINT (inev
.y
, mouse_loc
.v
);
9743 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9745 #ifndef USE_TOOLKIT_SCROLL_BARS
9746 /* control_part_code becomes kControlNoPart if
9747 a progress indicator is clicked. */
9748 && control_part_code
!= kControlNoPart
9749 #else /* USE_TOOLKIT_SCROLL_BARS */
9751 && control_kind
.kind
== kControlKindScrollBar
9752 #endif /* MAC_OSX */
9753 #endif /* USE_TOOLKIT_SCROLL_BARS */
9756 struct scroll_bar
*bar
;
9758 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9760 bar
= tracked_scroll_bar
;
9761 #ifndef USE_TOOLKIT_SCROLL_BARS
9762 control_part_code
= kControlIndicatorPart
;
9766 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9767 #ifdef USE_TOOLKIT_SCROLL_BARS
9768 /* Make the "Ctrl-Mouse-2 splits window" work
9769 for toolkit scroll bars. */
9770 if (er
.modifiers
& controlKey
)
9771 x_scroll_bar_handle_click (bar
, control_part_code
,
9773 else if (er
.what
== mouseDown
)
9774 x_scroll_bar_handle_press (bar
, control_part_code
,
9777 x_scroll_bar_handle_release (bar
, &inev
);
9778 #else /* not USE_TOOLKIT_SCROLL_BARS */
9779 x_scroll_bar_handle_click (bar
, control_part_code
,
9781 if (er
.what
== mouseDown
9782 && control_part_code
== kControlIndicatorPart
)
9783 tracked_scroll_bar
= bar
;
9785 tracked_scroll_bar
= NULL
;
9786 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9791 int x
= mouse_loc
.h
;
9792 int y
= mouse_loc
.v
;
9794 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9795 if (EQ (window
, f
->tool_bar_window
))
9797 if (er
.what
== mouseDown
)
9798 handle_tool_bar_click (f
, x
, y
, 1, 0);
9800 handle_tool_bar_click (f
, x
, y
, 0,
9806 XSETFRAME (inev
.frame_or_window
, f
);
9807 inev
.kind
= MOUSE_CLICK_EVENT
;
9811 if (er
.what
== mouseDown
)
9813 dpyinfo
->grabbed
|= (1 << inev
.code
);
9814 last_mouse_frame
= f
;
9817 last_tool_bar_item
= -1;
9821 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9822 /* If a button is released though it was not
9823 previously pressed, that would be because
9824 of multi-button emulation. */
9825 dpyinfo
->grabbed
= 0;
9827 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9830 /* Ignore any mouse motion that happened before
9831 this event; any subsequent mouse-movement Emacs
9832 events should reflect only motion after the
9837 #ifdef USE_TOOLKIT_SCROLL_BARS
9838 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9843 inev
.modifiers
|= down_modifier
;
9846 inev
.modifiers
|= up_modifier
;
9853 #if TARGET_API_MAC_CARBON
9854 DragWindow (window_ptr
, er
.where
, NULL
);
9855 #else /* not TARGET_API_MAC_CARBON */
9856 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9857 #endif /* not TARGET_API_MAC_CARBON */
9858 /* Update the frame parameters. */
9860 struct frame
*f
= mac_window_to_frame (window_ptr
);
9862 if (f
&& !f
->async_iconified
)
9863 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9868 if (TrackGoAway (window_ptr
, er
.where
))
9870 inev
.kind
= DELETE_WINDOW_EVENT
;
9871 XSETFRAME (inev
.frame_or_window
,
9872 mac_window_to_frame (window_ptr
));
9876 /* window resize handling added --ben */
9878 do_grow_window (window_ptr
, &er
);
9881 /* window zoom handling added --ben */
9884 if (TrackBox (window_ptr
, er
.where
, part_code
))
9885 do_zoom_window (window_ptr
, part_code
);
9895 #if USE_CARBON_EVENTS
9896 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9897 != eventNotHandledErr
)
9900 do_window_update ((WindowPtr
) er
.message
);
9905 #if USE_CARBON_EVENTS
9906 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9907 != eventNotHandledErr
)
9910 switch ((er
.message
>> 24) & 0x000000FF)
9912 case suspendResumeMessage
:
9913 if ((er
.message
& resumeFlag
) == 1)
9919 case mouseMovedMessage
:
9920 #if !USE_CARBON_EVENTS
9921 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9922 er
.where
.h
+ 1, er
.where
.v
+ 1);
9924 previous_help_echo_string
= help_echo_string
;
9925 help_echo_string
= Qnil
;
9927 if (dpyinfo
->grabbed
&& last_mouse_frame
9928 && FRAME_LIVE_P (last_mouse_frame
))
9929 f
= last_mouse_frame
;
9931 f
= dpyinfo
->x_focus_frame
;
9933 if (dpyinfo
->mouse_face_hidden
)
9935 dpyinfo
->mouse_face_hidden
= 0;
9936 clear_mouse_face (dpyinfo
);
9941 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9942 Point mouse_pos
= er
.where
;
9944 SetPortWindowPort (wp
);
9946 GlobalToLocal (&mouse_pos
);
9948 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9949 #ifdef USE_TOOLKIT_SCROLL_BARS
9950 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9952 #else /* not USE_TOOLKIT_SCROLL_BARS */
9953 x_scroll_bar_note_movement (tracked_scroll_bar
,
9955 - XINT (tracked_scroll_bar
->top
),
9956 er
.when
* (1000 / 60));
9957 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9960 /* Generate SELECT_WINDOW_EVENTs when needed. */
9961 if (mouse_autoselect_window
)
9965 window
= window_from_coordinates (f
,
9970 /* Window will be selected only when it is
9971 not selected now and last mouse movement
9972 event was not in it. Minibuffer window
9973 will be selected iff it is active. */
9974 if (WINDOWP (window
)
9975 && !EQ (window
, last_window
)
9976 && !EQ (window
, selected_window
))
9978 inev
.kind
= SELECT_WINDOW_EVENT
;
9979 inev
.frame_or_window
= window
;
9984 if (!note_mouse_movement (f
, &mouse_pos
))
9985 help_echo_string
= previous_help_echo_string
;
9989 /* If the contents of the global variable
9990 help_echo_string has changed, generate a
9992 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10000 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10002 #if USE_CARBON_EVENTS
10003 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10004 != eventNotHandledErr
)
10007 if (window_ptr
== tip_window
)
10009 HideWindow (tip_window
);
10013 if (!is_emacs_window (window_ptr
))
10016 if ((er
.modifiers
& activeFlag
) != 0)
10018 /* A window has been activated */
10019 Point mouse_loc
= er
.where
;
10021 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10023 SetPortWindowPort (window_ptr
);
10024 GlobalToLocal (&mouse_loc
);
10025 /* Window-activated event counts as mouse movement,
10026 so update things that depend on mouse position. */
10027 note_mouse_movement (mac_window_to_frame (window_ptr
),
10032 /* A window has been deactivated */
10033 #if USE_TOOLKIT_SCROLL_BARS
10034 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10036 struct input_event event
;
10038 EVENT_INIT (event
);
10039 event
.kind
= NO_EVENT
;
10040 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10041 if (event
.kind
!= NO_EVENT
)
10043 event
.timestamp
= timestamp
;
10044 kbd_buffer_store_event_hold (&event
, hold_quit
);
10049 dpyinfo
->grabbed
= 0;
10051 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10053 f
= mac_window_to_frame (window_ptr
);
10054 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10056 /* If we move outside the frame, then we're
10057 certainly no longer on any text in the
10059 clear_mouse_face (dpyinfo
);
10060 dpyinfo
->mouse_face_mouse_frame
= 0;
10063 /* Generate a nil HELP_EVENT to cancel a help-echo.
10064 Do it only if there's something to cancel.
10065 Otherwise, the startup message is cleared when the
10066 mouse leaves the frame. */
10067 if (any_help_event_p
)
10076 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10079 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10080 /* When using Carbon Events, we need to pass raw keyboard
10081 events to the TSM ourselves. If TSM handles it, it
10082 will pass back noErr, otherwise it will pass back
10083 "eventNotHandledErr" and we can process it
10085 if ((mac_pass_command_to_system
10086 || !(er
.modifiers
& cmdKey
))
10087 && (mac_pass_control_to_system
10088 || !(er
.modifiers
& controlKey
))
10089 && (NILP (Vmac_option_modifier
)
10090 || !(er
.modifiers
& optionKey
)))
10091 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10092 != eventNotHandledErr
)
10097 if (dpyinfo
->x_focus_frame
== NULL
)
10099 /* Beep if keyboard input occurs when all the frames
10107 static SInt16 last_key_script
= -1;
10108 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10110 if (last_key_script
!= current_key_script
)
10112 struct input_event event
;
10114 EVENT_INIT (event
);
10115 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10117 event
.code
= current_key_script
;
10118 event
.timestamp
= timestamp
;
10119 kbd_buffer_store_event (&event
);
10122 last_key_script
= current_key_script
;
10127 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10129 clear_mouse_face (dpyinfo
);
10130 dpyinfo
->mouse_face_hidden
= 1;
10133 /* translate the keycode back to determine the original key */
10134 /* Convert key code if function key is pressed.
10135 Otherwise, if non-ASCII-event, take care of that
10136 without re-translating the key code. */
10137 #if USE_CARBON_EVENTS
10138 if (convert_fn_keycode (eventRef
, keycode
, &xkeysym
))
10140 inev
.code
= xkeysym
;
10141 /* this doesn't work - tried to add shift modifiers */
10143 backtranslate_modified_keycode(er
.modifiers
& (~0x2200),
10144 xkeysym
| 0x80, xkeysym
);
10145 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10149 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10151 inev
.code
= 0xff00 | xkeysym
;
10152 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10157 backtranslate_modified_keycode(er
.modifiers
, keycode
,
10158 er
.message
& charCodeMask
);
10159 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10163 #if USE_CARBON_EVENTS
10164 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10166 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10168 inev
.modifiers
|= (extra_keyboard_modifiers
10169 & (meta_modifier
| alt_modifier
10170 | hyper_modifier
| super_modifier
));
10171 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
10174 case kHighLevelEvent
:
10175 read_socket_inev
= &inev
;
10176 AEProcessAppleEvent (&er
);
10177 read_socket_inev
= NULL
;
10183 #if USE_CARBON_EVENTS
10184 ReleaseEvent (eventRef
);
10187 if (inev
.kind
!= NO_EVENT
)
10189 inev
.timestamp
= timestamp
;
10190 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10195 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10200 XSETFRAME (frame
, f
);
10206 any_help_event_p
= 1;
10207 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10208 help_echo_object
, help_echo_pos
);
10212 help_echo_string
= Qnil
;
10213 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10220 /* If the focus was just given to an autoraising frame,
10222 /* ??? This ought to be able to handle more than one such frame. */
10223 if (pending_autoraise_frame
)
10225 x_raise_frame (pending_autoraise_frame
);
10226 pending_autoraise_frame
= 0;
10229 #if !USE_CARBON_EVENTS
10230 /* Check which frames are still visible. We do this here because
10231 there doesn't seem to be any direct notification from the Window
10232 Manager that the visibility of a window has changed (at least,
10233 not in all cases). */
10235 Lisp_Object tail
, frame
;
10237 FOR_EACH_FRAME (tail
, frame
)
10239 struct frame
*f
= XFRAME (frame
);
10241 /* The tooltip has been drawn already. Avoid the
10242 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10243 if (EQ (frame
, tip_frame
))
10246 if (FRAME_MAC_P (f
))
10247 mac_handle_visibility_change (f
);
10258 /* Need to override CodeWarrior's input function so no conversion is
10259 done on newlines Otherwise compiled functions in .elc files will be
10260 read incorrectly. Defined in ...:MSL C:MSL
10261 Common:Source:buffer_io.c. */
10264 __convert_to_newlines (unsigned char * p
, size_t * n
)
10266 #pragma unused(p,n)
10270 __convert_from_newlines (unsigned char * p
, size_t * n
)
10272 #pragma unused(p,n)
10278 make_mac_terminal_frame (struct frame
*f
)
10283 XSETFRAME (frame
, f
);
10285 f
->output_method
= output_mac
;
10286 f
->output_data
.mac
= (struct mac_output
*)
10287 xmalloc (sizeof (struct mac_output
));
10288 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10290 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10292 FRAME_COLS (f
) = 96;
10293 FRAME_LINES (f
) = 4;
10295 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10296 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10298 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10300 f
->output_data
.mac
->cursor_pixel
= 0;
10301 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10302 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10303 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10305 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10306 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10307 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10308 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10309 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10310 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10312 FRAME_FONTSET (f
) = -1;
10313 f
->output_data
.mac
->explicit_parent
= 0;
10316 f
->border_width
= 0;
10318 f
->internal_border_width
= 0;
10323 f
->new_text_cols
= 0;
10324 f
->new_text_lines
= 0;
10326 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10327 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10328 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10332 if (!(FRAME_MAC_WINDOW (f
) =
10333 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10334 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10336 /* so that update events can find this mac_output struct */
10337 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10343 /* Need to be initialized for unshow_buffer in window.c. */
10344 selected_window
= f
->selected_window
;
10346 Fmodify_frame_parameters (frame
,
10347 Fcons (Fcons (Qfont
,
10348 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10349 Fmodify_frame_parameters (frame
,
10350 Fcons (Fcons (Qforeground_color
,
10351 build_string ("black")), Qnil
));
10352 Fmodify_frame_parameters (frame
,
10353 Fcons (Fcons (Qbackground_color
,
10354 build_string ("white")), Qnil
));
10359 /***********************************************************************
10361 ***********************************************************************/
10363 int mac_initialized
= 0;
10366 mac_initialize_display_info ()
10368 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10369 GDHandle main_device_handle
;
10371 bzero (dpyinfo
, sizeof (*dpyinfo
));
10374 dpyinfo
->mac_id_name
10375 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10376 + SCHARS (Vsystem_name
)
10378 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10379 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10381 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10382 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10385 main_device_handle
= LMGetMainDevice();
10387 dpyinfo
->reference_count
= 0;
10388 dpyinfo
->resx
= 72.0;
10389 dpyinfo
->resy
= 72.0;
10390 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10392 /* HasDepth returns true if it is possible to have a 32 bit display,
10393 but this may not be what is actually used. Mac OSX can do better.
10394 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10395 header for CGGetActiveDisplayList says that the first display returned
10396 is the active one, so we use that. */
10398 CGDirectDisplayID disp_id
[1];
10399 CGDisplayCount disp_count
;
10400 CGDisplayErr error_code
;
10402 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10403 if (error_code
!= 0)
10404 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10406 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10409 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10410 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10411 gdDevType
, dpyinfo
->color_p
))
10414 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10415 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10416 dpyinfo
->grabbed
= 0;
10417 dpyinfo
->root_window
= NULL
;
10418 dpyinfo
->image_cache
= make_image_cache ();
10420 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10421 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10422 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10423 dpyinfo
->mouse_face_window
= Qnil
;
10424 dpyinfo
->mouse_face_overlay
= Qnil
;
10425 dpyinfo
->mouse_face_hidden
= 0;
10430 mac_make_rdb (xrm_option
)
10433 XrmDatabase database
;
10435 database
= xrm_get_preference_database (NULL
);
10437 xrm_merge_string_database (database
, xrm_option
);
10442 struct mac_display_info
*
10443 mac_term_init (display_name
, xrm_option
, resource_name
)
10444 Lisp_Object display_name
;
10446 char *resource_name
;
10448 struct mac_display_info
*dpyinfo
;
10452 if (!mac_initialized
)
10455 mac_initialized
= 1;
10458 if (x_display_list
)
10459 error ("Sorry, this version can only handle one display");
10461 mac_initialize_display_info ();
10463 dpyinfo
= &one_mac_display_info
;
10465 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10467 /* Put this display on the chain. */
10468 dpyinfo
->next
= x_display_list
;
10469 x_display_list
= dpyinfo
;
10471 /* Put it on x_display_name_list. */
10472 x_display_name_list
= Fcons (Fcons (display_name
,
10473 Fcons (Qnil
, dpyinfo
->xrdb
)),
10474 x_display_name_list
);
10475 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10481 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10484 x_delete_display (dpyinfo
)
10485 struct mac_display_info
*dpyinfo
;
10489 /* Discard this display from x_display_name_list and x_display_list.
10490 We can't use Fdelq because that can quit. */
10491 if (! NILP (x_display_name_list
)
10492 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10493 x_display_name_list
= XCDR (x_display_name_list
);
10498 tail
= x_display_name_list
;
10499 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10501 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10503 XSETCDR (tail
, XCDR (XCDR (tail
)));
10506 tail
= XCDR (tail
);
10510 if (x_display_list
== dpyinfo
)
10511 x_display_list
= dpyinfo
->next
;
10514 struct x_display_info
*tail
;
10516 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10517 if (tail
->next
== dpyinfo
)
10518 tail
->next
= tail
->next
->next
;
10521 /* Free the font names in the font table. */
10522 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10523 if (dpyinfo
->font_table
[i
].name
)
10525 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10526 xfree (dpyinfo
->font_table
[i
].full_name
);
10527 xfree (dpyinfo
->font_table
[i
].name
);
10530 if (dpyinfo
->font_table
->font_encoder
)
10531 xfree (dpyinfo
->font_table
->font_encoder
);
10533 xfree (dpyinfo
->font_table
);
10534 xfree (dpyinfo
->mac_id_name
);
10536 if (x_display_list
== 0)
10538 mac_clear_font_name_table ();
10539 bzero (dpyinfo
, sizeof (*dpyinfo
));
10548 extern int inhibit_window_system
;
10549 extern int noninteractive
;
10550 CFBundleRef appsBundle
;
10553 /* No need to test if already -nw*/
10554 if (inhibit_window_system
|| noninteractive
)
10557 appsBundle
= CFBundleGetMainBundle();
10558 if (appsBundle
!= NULL
)
10560 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10561 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10562 /* We found the bundle identifier, now we know we are valid. */
10569 /* MAC_TODO: Have this start the bundled executable */
10571 /* For now, prevent the fatal error by bringing it up in the terminal */
10572 inhibit_window_system
= 1;
10576 MakeMeTheFrontProcess ()
10578 ProcessSerialNumber psn
;
10581 err
= GetCurrentProcess (&psn
);
10583 (void) SetFrontProcess (&psn
);
10586 /***** Code to handle C-g testing *****/
10588 /* Contains the Mac modifier formed from quit_char */
10589 int mac_quit_char_modifiers
= 0;
10590 int mac_quit_char_keycode
;
10591 extern int quit_char
;
10594 mac_determine_quit_char_modifiers()
10596 /* Todo: Determine modifiers from quit_char. */
10597 UInt32 qc_modifiers
= ctrl_modifier
;
10599 /* Map modifiers */
10600 mac_quit_char_modifiers
= 0;
10601 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
10602 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
10603 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
10607 init_quit_char_handler ()
10609 /* TODO: Let this support keys other the 'g' */
10610 mac_quit_char_keycode
= 5;
10611 /* Look at <architecture/adb_kb_map.h> for details */
10612 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10614 mac_determine_quit_char_modifiers();
10616 #endif /* MAC_OSX */
10624 MenuItemIndex menu_index
;
10626 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10627 &menu
, &menu_index
);
10629 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10630 #if USE_CARBON_EVENTS
10631 EnableMenuCommand (NULL
, kHICommandPreferences
);
10632 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10633 &menu
, &menu_index
);
10636 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10637 InsertMenuItemTextWithCFString (menu
, NULL
,
10638 0, kMenuItemAttrSeparator
, 0);
10639 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10640 0, 0, kHICommandAbout
);
10642 #endif /* USE_CARBON_EVENTS */
10643 #else /* !MAC_OSX */
10644 #if USE_CARBON_EVENTS
10645 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10651 /* Set up use of X before we make the first connection. */
10653 extern frame_parm_handler mac_frame_parm_handlers
[];
10655 static struct redisplay_interface x_redisplay_interface
=
10657 mac_frame_parm_handlers
,
10661 x_clear_end_of_line
,
10663 x_after_update_window_line
,
10664 x_update_window_begin
,
10665 x_update_window_end
,
10668 0, /* flush_display_optional */
10669 x_clear_window_mouse_face
,
10670 x_get_glyph_overhangs
,
10671 x_fix_overlapping_area
,
10672 x_draw_fringe_bitmap
,
10673 0, /* define_fringe_bitmap */
10674 0, /* destroy_fringe_bitmap */
10675 mac_per_char_metric
,
10677 mac_compute_glyph_string_overhangs
,
10678 x_draw_glyph_string
,
10679 mac_define_frame_cursor
,
10680 mac_clear_frame_area
,
10681 mac_draw_window_cursor
,
10682 mac_draw_vertical_window_border
,
10683 mac_shift_glyphs_for_insert
10689 rif
= &x_redisplay_interface
;
10691 clear_frame_hook
= x_clear_frame
;
10692 ins_del_lines_hook
= x_ins_del_lines
;
10693 delete_glyphs_hook
= x_delete_glyphs
;
10694 ring_bell_hook
= XTring_bell
;
10695 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10696 set_terminal_modes_hook
= XTset_terminal_modes
;
10697 update_begin_hook
= x_update_begin
;
10698 update_end_hook
= x_update_end
;
10699 set_terminal_window_hook
= XTset_terminal_window
;
10700 read_socket_hook
= XTread_socket
;
10701 frame_up_to_date_hook
= XTframe_up_to_date
;
10702 mouse_position_hook
= XTmouse_position
;
10703 frame_rehighlight_hook
= XTframe_rehighlight
;
10704 frame_raise_lower_hook
= XTframe_raise_lower
;
10706 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10707 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10708 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10709 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10711 scroll_region_ok
= 1; /* we'll scroll partial frames */
10712 char_ins_del_ok
= 1;
10713 line_ins_del_ok
= 1; /* we'll just blt 'em */
10714 fast_clear_end_of_line
= 1; /* X does this well */
10715 memory_below_frame
= 0; /* we don't remember what scrolls
10719 last_tool_bar_item
= -1;
10720 any_help_event_p
= 0;
10722 /* Try to use interrupt input; if we can't, then start polling. */
10723 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10727 #if TARGET_API_MAC_CARBON
10729 #if USE_CARBON_EVENTS
10731 init_service_handler ();
10733 init_quit_char_handler ();
10734 #endif /* MAC_OSX */
10736 init_command_handler ();
10739 #endif /* USE_CARBON_EVENTS */
10742 init_coercion_handler ();
10744 init_apple_event_handler ();
10746 if (!inhibit_window_system
)
10747 MakeMeTheFrontProcess ();
10758 staticpro (&x_error_message_string
);
10759 x_error_message_string
= Qnil
;
10762 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
10763 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
10764 Qalt
= intern ("alt"); staticpro (&Qalt
);
10765 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
10766 Qsuper
= intern ("super"); staticpro (&Qsuper
);
10767 Qmodifier_value
= intern ("modifier-value");
10768 staticpro (&Qmodifier_value
);
10770 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
10771 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10772 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10773 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10774 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10776 #if USE_CARBON_EVENTS
10777 Qhicommand
= intern ("hicommand"); staticpro (&Qhicommand
);
10779 Qservices
= intern ("services"); staticpro (&Qservices
);
10780 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10781 Qperform
= intern ("perform"); staticpro (&Qperform
);
10786 Fprovide (intern ("mac-carbon"), Qnil
);
10789 staticpro (&Qreverse
);
10790 Qreverse
= intern ("reverse");
10792 staticpro (&x_display_name_list
);
10793 x_display_name_list
= Qnil
;
10795 staticpro (&last_mouse_scroll_bar
);
10796 last_mouse_scroll_bar
= Qnil
;
10798 staticpro (&fm_font_family_alist
);
10799 fm_font_family_alist
= Qnil
;
10802 staticpro (&atsu_font_id_hash
);
10803 atsu_font_id_hash
= Qnil
;
10806 /* We don't yet support this, but defining this here avoids whining
10807 from cus-start.el and other places, like "M-x set-variable". */
10808 DEFVAR_BOOL ("x-use-underline-position-properties",
10809 &x_use_underline_position_properties
,
10810 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10811 nil means ignore them. If you encounter fonts with bogus
10812 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10813 to 4.1, set this to nil.
10815 NOTE: Not supported on Mac yet. */);
10816 x_use_underline_position_properties
= 0;
10818 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10819 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10820 #ifdef USE_TOOLKIT_SCROLL_BARS
10821 Vx_toolkit_scroll_bars
= Qt
;
10823 Vx_toolkit_scroll_bars
= Qnil
;
10826 staticpro (&last_mouse_motion_frame
);
10827 last_mouse_motion_frame
= Qnil
;
10829 /* Variables to configure modifier key assignment. */
10831 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
10832 doc
: /* *Modifier key assumed when the Mac control key is pressed.
10833 The value can be `control', `meta', `alt', `hyper', or `super' for the
10834 respective modifier. The default is `control'. */);
10835 Vmac_control_modifier
= Qcontrol
;
10837 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10838 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
10839 The value can be `control', `meta', `alt', `hyper', or `super' for the
10840 respective modifier. If the value is nil then the key will act as the
10841 normal Mac control modifier, and the option key can be used to compose
10842 characters depending on the chosen Mac keyboard setting. */);
10843 Vmac_option_modifier
= Qnil
;
10845 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
10846 doc
: /* *Modifier key assumed when the Mac command key is pressed.
10847 The value can be `control', `meta', `alt', `hyper', or `super' for the
10848 respective modifier. The default is `meta'. */);
10849 Vmac_command_modifier
= Qmeta
;
10851 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
10852 doc
: /* *Modifier key assumed when the Mac function key is pressed.
10853 The value can be `control', `meta', `alt', `hyper', or `super' for the
10854 respective modifier. Note that remapping the function key may lead to
10855 unexpected results for some keys on non-US/GB keyboards. */);
10856 Vmac_function_modifier
= Qnil
;
10858 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10859 &Vmac_emulate_three_button_mouse
,
10860 doc
: /* *Specify a way of three button mouse emulation.
10861 The value can be nil, t, or the symbol `reverse'.
10862 nil means that no emulation should be done and the modifiers should be
10863 placed on the mouse-1 event.
10864 t means that when the option-key is held down while pressing the mouse
10865 button, the click will register as mouse-2 and while the command-key
10866 is held down, the click will register as mouse-3.
10867 The symbol `reverse' means that the option-key will register for
10868 mouse-3 and the command-key will register for mouse-2. */);
10869 Vmac_emulate_three_button_mouse
= Qnil
;
10871 #if USE_CARBON_EVENTS
10872 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
10873 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
10874 Otherwise, the right click will be treated as mouse-2 and the wheel
10875 button will be mouse-3. */);
10876 mac_wheel_button_is_mouse_2
= 1;
10878 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
10879 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
10880 mac_pass_command_to_system
= 1;
10882 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
10883 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
10884 mac_pass_control_to_system
= 1;
10888 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
10889 doc
: /* *If non-nil, allow anti-aliasing.
10890 The text will be rendered using Core Graphics text rendering which
10891 may anti-alias the text. */);
10892 mac_use_core_graphics
= 0;
10894 /* Register an entry for `mac-roman' so that it can be used when
10895 creating the terminal frame on Mac OS 9 before loading
10896 term/mac-win.elc. */
10897 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10898 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
10899 Each entry should be of the form:
10901 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10903 where CHARSET-NAME is a string used in font names to identify the
10904 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
10905 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
10906 Vmac_charset_info_alist
=
10907 Fcons (list3 (build_string ("mac-roman"),
10908 make_number (smRoman
), Qnil
), Qnil
);
10911 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10912 (do not change this comment) */