1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 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 3, 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 #include <Quickdraw.h>
40 #include <ToolUtils.h>
44 #include <Resources.h>
46 #include <TextUtils.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
58 #endif /* not TARGET_API_MAC_CARBON */
71 #include "dispextern.h"
73 #include "termhooks.h"
80 #include "intervals.h"
86 /* Non-nil means Emacs uses toolkit scroll bars. */
88 Lisp_Object Vx_toolkit_scroll_bars
;
90 /* If non-zero, the text will be rendered using Core Graphics text
91 rendering which may anti-alias the text. */
92 int mac_use_core_graphics
;
94 /* Non-zero means make use of UNDERLINE_POSITION font properties.
95 (Not yet supported.) */
96 int x_use_underline_position_properties
;
98 /* Non-zero means to draw the underline at the same place as the descent line. */
100 int x_underline_at_descent_line
;
102 /* This is a chain of structures for all the X displays currently in
105 struct x_display_info
*x_display_list
;
107 /* This is a list of cons cells, each of the form (NAME
108 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
109 x_display_list and in the same order. NAME is the name of the
110 frame. FONT-LIST-CACHE records previous values returned by
111 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
112 equivalent, which is implemented with a Lisp object, for the
115 Lisp_Object x_display_name_list
;
117 /* This is display since Mac does not support multiple ones. */
118 struct mac_display_info one_mac_display_info
;
120 /* Frame being updated by update_frame. This is declared in term.c.
121 This is set by update_begin and looked at by all the XT functions.
122 It is zero while not inside an update. In that case, the XT
123 functions assume that `selected_frame' is the frame to apply to. */
125 extern struct frame
*updating_frame
;
127 /* This is a frame waiting to be auto-raised, within XTread_socket. */
129 struct frame
*pending_autoraise_frame
;
133 Formerly, we used PointerMotionHintMask (in standard_event_mask)
134 so that we would have to call XQueryPointer after each MotionNotify
135 event to ask for another such event. However, this made mouse tracking
136 slow, and there was a bug that made it eventually stop.
138 Simply asking for MotionNotify all the time seems to work better.
140 In order to avoid asking for motion events and then throwing most
141 of them away or busy-polling the server for mouse positions, we ask
142 the server for pointer motion hints. This means that we get only
143 one event per group of mouse movements. "Groups" are delimited by
144 other kinds of events (focus changes and button clicks, for
145 example), or by XQueryPointer calls; when one of these happens, we
146 get another MotionNotify event the next time the mouse moves. This
147 is at least as efficient as getting motion events when mouse
148 tracking is on, and I suspect only negligibly worse when tracking
151 /* Where the mouse was last time we reported a mouse event. */
153 Rect last_mouse_glyph
;
154 FRAME_PTR last_mouse_glyph_frame
;
156 /* The scroll bar in which the last X motion event occurred.
158 If the last X motion event occurred in a scroll bar, we set this so
159 XTmouse_position can know whether to report a scroll bar motion or
162 If the last X motion event didn't occur in a scroll bar, we set
163 this to Qnil, to tell XTmouse_position to return an ordinary motion
166 Lisp_Object last_mouse_scroll_bar
;
168 /* This is a hack. We would really prefer that XTmouse_position would
169 return the time associated with the position it returns, but there
170 doesn't seem to be any way to wrest the time-stamp from the server
171 along with the position query. So, we just keep track of the time
172 of the last movement we received, and return that in hopes that
173 it's somewhat accurate. */
175 Time last_mouse_movement_time
;
177 struct scroll_bar
*tracked_scroll_bar
= NULL
;
179 /* Incremented by XTread_socket whenever it really tries to read
183 int volatile input_signal_count
;
185 int input_signal_count
;
188 extern Lisp_Object Vsystem_name
;
190 extern Lisp_Object Qeql
;
192 /* A mask of extra modifier bits to put into every keyboard char. */
194 extern EMACS_INT extra_keyboard_modifiers
;
196 /* The keysyms to use for the various modifiers. */
198 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
200 extern int inhibit_window_system
;
202 #if __MRC__ && !TARGET_API_MAC_CARBON
203 QDGlobals qd
; /* QuickDraw global information structure. */
206 struct mac_display_info
*mac_display_info_for_display (Display
*);
207 static void x_update_window_end
P_ ((struct window
*, int, int));
208 int x_catch_errors
P_ ((Display
*));
209 void x_uncatch_errors
P_ ((Display
*, int));
210 void x_lower_frame
P_ ((struct frame
*));
211 void x_scroll_bar_clear
P_ ((struct frame
*));
212 int x_had_errors_p
P_ ((Display
*));
213 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
214 void x_raise_frame
P_ ((struct frame
*));
215 void x_set_window_size
P_ ((struct frame
*, int, int, int));
216 void x_wm_set_window_state
P_ ((struct frame
*, int));
217 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
218 void mac_initialize
P_ ((void));
219 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
220 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
221 static void x_update_end
P_ ((struct frame
*));
222 static void XTframe_up_to_date
P_ ((struct frame
*));
223 static void XTset_terminal_modes
P_ ((void));
224 static void XTreset_terminal_modes
P_ ((void));
225 static void x_clear_frame
P_ ((void));
226 static void frame_highlight
P_ ((struct frame
*));
227 static void frame_unhighlight
P_ ((struct frame
*));
228 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
229 static void XTframe_rehighlight
P_ ((struct frame
*));
230 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
231 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
232 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
233 enum text_cursor_kinds
));
235 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
236 static void x_update_begin
P_ ((struct frame
*));
237 static void x_update_window_begin
P_ ((struct window
*));
238 static void x_after_update_window_line
P_ ((struct glyph_row
*));
240 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
241 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
243 extern void mac_toolbox_initialize
P_ ((void));
244 extern void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
245 enum scroll_bar_part
*,
246 Lisp_Object
*, Lisp_Object
*,
249 extern void mac_flush_display_optional
P_ ((struct frame
*));
252 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
253 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
254 #define GC_FONT(gc) ((gc)->xgcv.font)
255 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
257 #define CG_SET_FILL_COLOR(context, color) \
258 CGContextSetRGBFillColor (context, \
259 RED_FROM_ULONG (color) / 255.0f, \
260 GREEN_FROM_ULONG (color) / 255.0f, \
261 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
262 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
263 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
264 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
266 if (CGColorGetTypeID != NULL) \
267 CGContextSetFillColorWithColor (context, cg_color); \
269 CG_SET_FILL_COLOR (context, color); \
272 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
273 CGContextSetFillColorWithColor (context, cg_color)
276 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
277 CG_SET_FILL_COLOR (context, color)
279 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
280 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
282 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
283 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
287 #define CG_SET_STROKE_COLOR(context, color) \
288 CGContextSetRGBStrokeColor (context, \
289 RED_FROM_ULONG (color) / 255.0f, \
290 GREEN_FROM_ULONG (color) / 255.0f, \
291 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
292 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
293 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
294 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
296 if (CGColorGetTypeID != NULL) \
297 CGContextSetStrokeColorWithColor (context, cg_color); \
299 CG_SET_STROKE_COLOR (context, color); \
302 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
303 CGContextSetStrokeColorWithColor (context, cg_color)
306 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
307 CG_SET_STROKE_COLOR (context, color)
309 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
310 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
314 /* Fringe bitmaps. */
316 static int max_fringe_bmp
= 0;
317 static CGImageRef
*fringe_bmp
= 0;
319 static CGColorSpaceRef mac_cg_color_space_rgb
;
320 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
321 static CGColorRef mac_cg_color_black
;
327 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
328 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
329 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
330 /* Don't check the availability of CGColorCreate; this symbol is
331 defined even in Mac OS X 10.1. */
332 if (CGColorGetTypeID
!= NULL
)
335 CGFloat rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
337 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
341 #endif /* USE_CG_DRAWING */
343 /* X display function emulation */
345 /* Mac version of XDrawLine. */
348 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
354 CGContextRef context
;
355 CGFloat gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
358 gx1
+= 0.5f
, gx2
+= 0.5f
;
360 gy1
+= 0.5f
, gy2
+= 0.5f
;
362 context
= mac_begin_cg_clip (f
, gc
);
363 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
364 CGContextBeginPath (context
);
365 CGContextMoveToPoint (context
, gx1
, gy1
);
366 CGContextAddLineToPoint (context
, gx2
, gy2
);
367 CGContextClosePath (context
);
368 CGContextStrokePath (context
);
386 mac_begin_clip (f
, gc
);
387 RGBForeColor (GC_FORE_COLOR (gc
));
390 mac_end_clip (f
, gc
);
394 /* Mac version of XDrawLine (to Pixmap). */
397 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
421 GetGWorld (&old_port
, &old_gdh
);
424 RGBForeColor (GC_FORE_COLOR (gc
));
426 LockPixels (GetGWorldPixMap (p
));
429 UnlockPixels (GetGWorldPixMap (p
));
431 SetGWorld (old_port
, old_gdh
);
436 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
440 unsigned int width
, height
;
444 CGContextRef context
;
446 context
= mac_begin_cg_clip (f
, gc
);
447 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
448 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
455 mac_begin_clip (f
, gc
);
456 RGBBackColor (GC_BACK_COLOR (gc
));
457 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
459 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
460 mac_end_clip (f
, gc
);
466 /* Mac version of XClearArea. */
469 mac_clear_area (f
, x
, y
, width
, height
)
472 unsigned int width
, height
;
474 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
477 /* Mac version of XClearWindow. */
485 CGContextRef context
;
486 GC gc
= FRAME_NORMAL_GC (f
);
488 context
= mac_begin_cg_clip (f
, NULL
);
489 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
490 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
491 FRAME_PIXEL_HEIGHT (f
)));
494 #else /* !USE_CG_DRAWING */
495 mac_begin_clip (f
, NULL
);
496 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
497 #if TARGET_API_MAC_CARBON
501 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
504 #else /* not TARGET_API_MAC_CARBON */
505 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
506 #endif /* not TARGET_API_MAC_CARBON */
507 mac_end_clip (f
, NULL
);
512 /* Mac replacement for XCopyArea. */
516 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
517 dest_x
, dest_y
, overlay_p
)
522 unsigned int width
, height
;
523 int dest_x
, dest_y
, overlay_p
;
525 CGContextRef context
;
526 CGFloat port_height
= FRAME_PIXEL_HEIGHT (f
);
527 CGRect dest_rect
= mac_rect_make (f
, dest_x
, dest_y
, width
, height
);
529 context
= mac_begin_cg_clip (f
, gc
);
532 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
533 CGContextFillRect (context
, dest_rect
);
535 CGContextClipToRect (context
, dest_rect
);
536 CGContextScaleCTM (context
, 1, -1);
537 CGContextTranslateCTM (context
, 0, -port_height
);
538 if (CGImageIsMask (image
))
539 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
540 CGContextDrawImage (context
,
541 mac_rect_make (f
, dest_x
- src_x
,
542 port_height
- (dest_y
- src_y
543 + CGImageGetHeight (image
)),
544 CGImageGetWidth (image
),
545 CGImageGetHeight (image
)),
550 #else /* !USE_CG_DRAWING */
553 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
556 int x
, y
, width
, height
;
557 unsigned short *bits
;
563 bitmap
.rowBytes
= sizeof(unsigned short);
564 bitmap
.baseAddr
= (char *)bits
;
565 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
567 mac_begin_clip (f
, gc
);
568 RGBForeColor (GC_FORE_COLOR (gc
));
569 RGBBackColor (GC_BACK_COLOR (gc
));
570 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
571 #if TARGET_API_MAC_CARBON
577 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
578 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
579 UnlockPortBits (port
);
581 #else /* not TARGET_API_MAC_CARBON */
582 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
583 overlay_p
? srcOr
: srcCopy
, 0);
584 #endif /* not TARGET_API_MAC_CARBON */
585 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
586 mac_end_clip (f
, gc
);
588 #endif /* !USE_CG_DRAWING */
591 /* Mac replacement for XCreateBitmapFromBitmapData. */
594 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
599 static const unsigned char swap_nibble
[16]
600 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
601 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
602 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
603 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
607 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
608 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
609 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
610 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
611 for (i
= 0; i
< h
; i
++)
613 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
614 for (j
= 0; j
< w1
; j
++)
616 /* Bitswap XBM bytes to match how Mac does things. */
617 unsigned char c
= *bits
++;
618 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
619 | (swap_nibble
[(c
>>4) & 0xf]));
623 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
628 mac_free_bitmap (bitmap
)
631 xfree (bitmap
->baseAddr
);
636 XCreatePixmap (display
, w
, width
, height
, depth
)
639 unsigned int width
, height
;
647 SetPortWindowPort (w
);
649 SetRect (&r
, 0, 0, width
, height
);
650 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
653 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
654 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
656 /* CreateCGImageFromPixMaps requires ARGB format. */
657 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
666 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
670 unsigned int width
, height
;
671 unsigned long fg
, bg
;
681 gc
= XCreateGC (display
, w
, 0, NULL
);
683 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
687 GetGWorld (&old_port
, &old_gdh
);
688 SetGWorld (pixmap
, NULL
);
689 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
690 XSetForeground (display
, gc
, fg
);
691 XSetBackground (display
, gc
, bg
);
692 RGBForeColor (GC_FORE_COLOR (gc
));
693 RGBBackColor (GC_BACK_COLOR (gc
));
694 LockPixels (GetGWorldPixMap (pixmap
));
695 #if TARGET_API_MAC_CARBON
696 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
697 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
698 #else /* not TARGET_API_MAC_CARBON */
699 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
700 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
701 #endif /* not TARGET_API_MAC_CARBON */
702 UnlockPixels (GetGWorldPixMap (pixmap
));
703 SetGWorld (old_port
, old_gdh
);
704 mac_free_bitmap (&bitmap
);
711 XFreePixmap (display
, pixmap
)
715 DisposeGWorld (pixmap
);
719 /* Mac replacement for XFillRectangle. */
722 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
726 unsigned int width
, height
;
729 CGContextRef context
;
731 context
= mac_begin_cg_clip (f
, gc
);
732 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
733 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
738 mac_begin_clip (f
, gc
);
739 RGBForeColor (GC_FORE_COLOR (gc
));
740 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
741 PaintRect (&r
); /* using foreground color of gc */
742 mac_end_clip (f
, gc
);
747 /* Mac replacement for XDrawRectangle: dest is a window. */
750 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
754 unsigned int width
, height
;
757 CGContextRef context
;
759 context
= mac_begin_cg_clip (f
, gc
);
760 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
761 CGContextStrokeRect (context
,
762 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
767 mac_begin_clip (f
, gc
);
768 RGBForeColor (GC_FORE_COLOR (gc
));
769 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
770 FrameRect (&r
); /* using foreground color of gc */
771 mac_end_clip (f
, gc
);
777 mac_invert_rectangle (f
, x
, y
, width
, height
)
780 unsigned int width
, height
;
782 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
783 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
784 if (CGContextSetBlendMode
!= NULL
)
787 CGContextRef context
;
789 context
= mac_begin_cg_clip (f
, NULL
);
790 CGContextSetRGBFillColor (context
, 1.0f
, 1.0f
, 1.0f
, 1.0f
);
791 CGContextSetBlendMode (context
, kCGBlendModeDifference
);
792 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
795 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
796 else /* CGContextSetBlendMode == NULL */
798 #endif /* USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */
799 #if !USE_CG_DRAWING || MAC_OS_X_VERSION_MAX_ALLOWED < 1040 || (MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020)
803 mac_begin_clip (f
, NULL
);
804 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
806 mac_end_clip (f
, NULL
);
814 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
815 ConstUniCharArrayPtr text
;
816 UniCharCount text_length
;
818 ATSUTextLayout
*text_layout
;
821 static ATSUTextLayout saved_text_layout
= NULL
;
823 if (saved_text_layout
== NULL
)
825 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
826 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
827 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
828 static ATSLineLayoutOptions line_layout
=
829 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
830 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
831 | kATSLineUseQDRendering
833 kATSLineIsDisplayOnly
| kATSLineFractDisable
836 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
838 err
= ATSUCreateTextLayoutWithTextPtr (text
,
839 kATSUFromTextBeginning
,
845 err
= ATSUSetLayoutControls (saved_text_layout
,
846 sizeof (tags
) / sizeof (tags
[0]),
847 tags
, sizes
, values
);
849 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
853 err
= ATSUSetRunStyle (saved_text_layout
, style
,
854 kATSUFromTextBeginning
, kATSUToTextEnd
);
856 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
857 kATSUFromTextBeginning
,
863 *text_layout
= saved_text_layout
;
869 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
870 overstrike_p
, bytes_per_char
)
875 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
878 ATSUTextLayout text_layout
;
880 xassert (bytes_per_char
== 2);
882 #ifndef WORDS_BIG_ENDIAN
885 UniChar
*text
= (UniChar
*)buf
;
887 for (i
= 0; i
< nchars
; i
++)
888 text
[i
] = EndianU16_BtoN (text
[i
]);
891 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
893 GC_FONT (gc
)->mac_style
,
898 if (!mac_use_core_graphics
)
901 mac_begin_clip (f
, gc
);
902 RGBForeColor (GC_FORE_COLOR (gc
));
907 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
908 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
909 RGBBackColor (GC_BACK_COLOR (gc
));
911 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
914 ATSUDrawText (text_layout
,
915 kATSUFromTextBeginning
, kATSUToTextEnd
,
916 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
920 ATSUDrawText (text_layout
,
921 kATSUFromTextBeginning
, kATSUToTextEnd
,
922 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
924 mac_end_clip (f
, gc
);
929 static CGContextRef context
;
930 CGFloat port_height
= FRAME_PIXEL_HEIGHT (f
);
931 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
932 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
933 static const ATSUAttributeValuePtr values
[] = {&context
};
936 context
= mac_begin_cg_clip (f
, gc
);
941 QDBeginCGContext (port
, &context
);
942 if (gc
->n_clip_rects
|| bg_width
)
944 CGContextTranslateCTM (context
, 0, port_height
);
945 CGContextScaleCTM (context
, 1, -1);
946 if (gc
->n_clip_rects
)
947 CGContextClipToRects (context
, gc
->clip_rects
,
952 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
953 CGContextFillRect (context
,
955 x
, y
- FONT_BASE (GC_FONT (gc
)),
957 FONT_HEIGHT (GC_FONT (gc
))));
959 CGContextScaleCTM (context
, 1, -1);
960 CGContextTranslateCTM (context
, 0, -port_height
);
964 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
965 err
= ATSUSetLayoutControls (text_layout
,
966 sizeof (tags
) / sizeof (tags
[0]),
967 tags
, sizes
, values
);
970 ATSUDrawText (text_layout
,
971 kATSUFromTextBeginning
, kATSUToTextEnd
,
972 Long2Fix (x
), Long2Fix (port_height
- y
));
974 ATSUDrawText (text_layout
,
975 kATSUFromTextBeginning
, kATSUToTextEnd
,
976 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
982 CGContextSynchronize (context
);
983 QDEndCGContext (port
, &context
);
986 /* This doesn't work on Mac OS X 10.1. */
987 ATSUClearLayoutControls (text_layout
,
988 sizeof (tags
) / sizeof (tags
[0]), tags
);
990 ATSUSetLayoutControls (text_layout
,
991 sizeof (tags
) / sizeof (tags
[0]),
992 tags
, sizes
, values
);
997 #endif /* USE_ATSUI */
1001 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1002 overstrike_p
, bytes_per_char
)
1007 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1009 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1013 mac_begin_clip (f
, gc
);
1014 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1015 if (mac_use_core_graphics
)
1016 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1018 RGBForeColor (GC_FORE_COLOR (gc
));
1022 RGBBackColor (GC_BACK_COLOR (gc
));
1028 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1030 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1031 into an offscreen graphics world first. So performance gain
1032 cannot be expected.)
1033 - It lowers rendering quality.
1034 - Some fonts leave garbage on cursor movement. */
1039 RGBBackColor (GC_BACK_COLOR (gc
));
1040 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1041 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1046 TextFont (GC_FONT (gc
)->mac_fontnum
);
1047 TextSize (GC_FONT (gc
)->mac_fontsize
);
1048 TextFace (GC_FONT (gc
)->mac_fontface
);
1050 DrawText (buf
, 0, nchars
* bytes_per_char
);
1055 DrawText (buf
, 0, nchars
* bytes_per_char
);
1058 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1059 mac_end_clip (f
, gc
);
1061 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1062 if (mac_use_core_graphics
)
1063 SwapQDTextFlags(savedFlags
);
1069 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1070 overstrike_p
, bytes_per_char
)
1075 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1078 if (GC_FONT (gc
)->mac_style
)
1079 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1080 overstrike_p
, bytes_per_char
);
1082 #endif /* USE_ATSUI */
1083 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1084 overstrike_p
, bytes_per_char
);
1088 /* Mac replacement for XDrawImageString. */
1091 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1096 int nchars
, bg_width
, overstrike_p
;
1098 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1103 /* Mac replacement for XDrawImageString16. */
1106 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1111 int nchars
, bg_width
, overstrike_p
;
1113 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1118 /* Mac replacement for XQueryTextExtents, but takes a character. If
1119 STYLE is NULL, measurement is done by QuickDraw Text routines for
1120 the font of the current graphics port. If CG_GLYPH is not NULL,
1121 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1124 mac_query_char_extents (style
, c
,
1125 font_ascent_return
, font_descent_return
,
1126 overall_return
, cg_glyph
)
1133 int *font_ascent_return
, *font_descent_return
;
1134 XCharStruct
*overall_return
;
1135 #if USE_CG_TEXT_DRAWING
1141 OSStatus err
= noErr
;
1148 ATSUTextLayout text_layout
;
1151 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1153 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1155 ATSTrapezoid glyph_bounds
;
1157 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1158 kATSUFromTextBeginning
, kATSUToTextEnd
,
1159 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1160 kATSUseFractionalOrigins
,
1162 kATSUseDeviceOrigins
,
1164 1, &glyph_bounds
, NULL
);
1167 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1168 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1170 width
= Fix2Long (glyph_bounds
.upperRight
.x
1171 - glyph_bounds
.upperLeft
.x
);
1172 if (font_ascent_return
)
1173 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1174 if (font_descent_return
)
1175 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1178 if (err
== noErr
&& overall_return
)
1180 err
= ATSUMeasureTextImage (text_layout
,
1181 kATSUFromTextBeginning
, kATSUToTextEnd
,
1182 0, 0, &char_bounds
);
1184 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1185 #if USE_CG_TEXT_DRAWING
1186 if (err
== noErr
&& cg_glyph
)
1189 ATSUGlyphInfoArray glyph_info_array
;
1190 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1192 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1193 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1195 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1196 kATSUToTextEnd
, &count
,
1199 /* Make sure that we don't have to make layout
1201 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1202 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1203 && glyph_info_array
.glyphs
[0].screenX
== 0)
1205 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1206 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1217 if (font_ascent_return
|| font_descent_return
)
1221 GetFontInfo (&font_info
);
1222 if (font_ascent_return
)
1223 *font_ascent_return
= font_info
.ascent
;
1224 if (font_descent_return
)
1225 *font_descent_return
= font_info
.descent
;
1231 width
= CharWidth (ch
);
1232 QDTextBounds (1, &ch
, &char_bounds
);
1233 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1241 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1244 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1245 XFontStruct
*font_struct
;
1248 XCharStruct
*overall_return
;
1251 short width
= 0, lbearing
= 0, rbearing
= 0;
1254 for (i
= 0; i
< nchars
; i
++)
1256 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1258 width
+= FONT_WIDTH (font_struct
);
1261 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1262 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1263 width
+= pcm
->width
;
1268 overall_return
->lbearing
= lbearing
;
1269 overall_return
->rbearing
= rbearing
;
1270 overall_return
->width
= width
;
1272 /* What's the meaning of the return value of XTextExtents16? */
1276 #if USE_CG_TEXT_DRAWING
1277 static int cg_text_anti_aliasing_threshold
= 8;
1280 init_cg_text_anti_aliasing_threshold ()
1286 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1287 kCFPreferencesCurrentApplication
,
1290 cg_text_anti_aliasing_threshold
= threshold
;
1294 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1299 int nchars
, bg_width
, overstrike_p
;
1301 CGFloat port_height
, gx
, gy
;
1303 CGContextRef context
;
1307 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1310 port_height
= FRAME_PIXEL_HEIGHT (f
);
1312 gy
= port_height
- y
;
1313 glyphs
= (CGGlyph
*)buf
;
1314 advances
= alloca (sizeof (CGSize
) * nchars
);
1315 if (advances
== NULL
)
1317 for (i
= 0; i
< nchars
; i
++)
1319 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1321 advances
[i
].width
= pcm
->width
;
1322 advances
[i
].height
= 0;
1323 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1328 context
= mac_begin_cg_clip (f
, gc
);
1330 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1331 if (gc
->n_clip_rects
|| bg_width
)
1333 CGContextTranslateCTM (context
, 0, port_height
);
1334 CGContextScaleCTM (context
, 1, -1);
1335 if (gc
->n_clip_rects
)
1336 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1340 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1343 mac_rect_make (f
, gx
, y
- FONT_BASE (GC_FONT (gc
)),
1344 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1346 CGContextScaleCTM (context
, 1, -1);
1347 CGContextTranslateCTM (context
, 0, -port_height
);
1351 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1352 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1353 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1354 CGContextSetTextMatrix (context
, CGAffineTransformIdentity
);
1355 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1356 CGContextSetShouldAntialias (context
, false);
1357 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1358 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1359 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1362 CGContextSetTextPosition (context
, gx
, gy
);
1363 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1366 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1367 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1370 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1371 else /* CGContextShowGlyphsWithAdvances == NULL */
1373 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1374 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1376 for (i
= 0; i
< nchars
; i
++)
1378 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1380 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1381 gx
+= advances
[i
].width
;
1386 mac_end_cg_clip (f
);
1388 CGContextSynchronize (context
);
1389 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1398 /* Mac replacement for XCopyArea: dest must be window. */
1401 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1406 unsigned int width
, height
;
1411 mac_begin_clip (f
, gc
);
1413 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1414 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1416 ForeColor (blackColor
);
1417 BackColor (whiteColor
);
1419 LockPixels (GetGWorldPixMap (src
));
1420 #if TARGET_API_MAC_CARBON
1425 LockPortBits (port
);
1426 CopyBits (GetPortBitMapForCopyBits (src
),
1427 GetPortBitMapForCopyBits (port
),
1428 &src_r
, &dest_r
, srcCopy
, 0);
1429 UnlockPortBits (port
);
1431 #else /* not TARGET_API_MAC_CARBON */
1432 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1433 &src_r
, &dest_r
, srcCopy
, 0);
1434 #endif /* not TARGET_API_MAC_CARBON */
1435 UnlockPixels (GetGWorldPixMap (src
));
1437 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1439 mac_end_clip (f
, gc
);
1444 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1445 width
, height
, dest_x
, dest_y
)
1450 unsigned int width
, height
;
1455 mac_begin_clip (f
, gc
);
1457 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1458 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1460 ForeColor (blackColor
);
1461 BackColor (whiteColor
);
1463 LockPixels (GetGWorldPixMap (src
));
1464 LockPixels (GetGWorldPixMap (mask
));
1465 #if TARGET_API_MAC_CARBON
1470 LockPortBits (port
);
1471 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1472 GetPortBitMapForCopyBits (port
),
1473 &src_r
, &src_r
, &dest_r
);
1474 UnlockPortBits (port
);
1476 #else /* not TARGET_API_MAC_CARBON */
1477 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1478 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1479 #endif /* not TARGET_API_MAC_CARBON */
1480 UnlockPixels (GetGWorldPixMap (mask
));
1481 UnlockPixels (GetGWorldPixMap (src
));
1483 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1485 mac_end_clip (f
, gc
);
1487 #endif /* !USE_CG_DRAWING */
1490 /* Mac replacement for XCopyArea: used only for scrolling. */
1492 #if TARGET_API_MAC_CARBON
1493 /* Defined in mactoolbox.c. */
1494 extern void mac_scroll_area
P_ ((struct frame
*, GC
, int, int,
1495 unsigned int, unsigned int, int, int));
1496 #else /* not TARGET_API_MAC_CARBON */
1498 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1502 unsigned int width
, height
;
1506 WindowRef w
= FRAME_MAC_WINDOW (f
);
1508 mac_begin_clip (f
, gc
);
1510 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1511 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1513 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1514 color mapping in CopyBits. Otherwise, it will be slow. */
1515 ForeColor (blackColor
);
1516 BackColor (whiteColor
);
1517 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1519 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1521 mac_end_clip (f
, gc
);
1523 #endif /* not TARGET_API_MAC_CARBON */
1526 /* Mac replacement for XChangeGC. */
1529 XChangeGC (display
, gc
, mask
, xgcv
)
1535 if (mask
& GCForeground
)
1536 XSetForeground (display
, gc
, xgcv
->foreground
);
1537 if (mask
& GCBackground
)
1538 XSetBackground (display
, gc
, xgcv
->background
);
1540 XSetFont (display
, gc
, xgcv
->font
);
1544 /* Mac replacement for XCreateGC. */
1547 XCreateGC (display
, d
, mask
, xgcv
)
1553 GC gc
= xmalloc (sizeof (*gc
));
1555 bzero (gc
, sizeof (*gc
));
1556 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1557 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1558 if (CGColorGetTypeID
!= NULL
)
1561 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1562 CGColorRetain (gc
->cg_fore_color
);
1563 CGColorRetain (gc
->cg_back_color
);
1566 XChangeGC (display
, gc
, mask
, xgcv
);
1572 /* Used in xfaces.c. */
1575 XFreeGC (display
, gc
)
1579 if (gc
->clip_region
)
1580 DisposeRgn (gc
->clip_region
);
1581 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1582 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1583 if (CGColorGetTypeID
!= NULL
)
1586 CGColorRelease (gc
->cg_fore_color
);
1587 CGColorRelease (gc
->cg_back_color
);
1594 /* Mac replacement for XGetGCValues. */
1597 XGetGCValues (display
, gc
, mask
, xgcv
)
1603 if (mask
& GCForeground
)
1604 xgcv
->foreground
= gc
->xgcv
.foreground
;
1605 if (mask
& GCBackground
)
1606 xgcv
->background
= gc
->xgcv
.background
;
1608 xgcv
->font
= gc
->xgcv
.font
;
1612 /* Mac replacement for XSetForeground. */
1615 XSetForeground (display
, gc
, color
)
1618 unsigned long color
;
1620 if (gc
->xgcv
.foreground
!= color
)
1622 gc
->xgcv
.foreground
= color
;
1623 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1624 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1625 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1626 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1627 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1628 if (CGColorGetTypeID
!= NULL
)
1631 CGColorRelease (gc
->cg_fore_color
);
1634 gc
->cg_fore_color
= mac_cg_color_black
;
1635 CGColorRetain (gc
->cg_fore_color
);
1641 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1642 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1643 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1645 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1653 /* Mac replacement for XSetBackground. */
1656 XSetBackground (display
, gc
, color
)
1659 unsigned long color
;
1661 if (gc
->xgcv
.background
!= color
)
1663 gc
->xgcv
.background
= color
;
1664 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1665 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1666 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1667 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1668 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1669 if (CGColorGetTypeID
!= NULL
)
1672 CGColorRelease (gc
->cg_back_color
);
1675 gc
->cg_back_color
= mac_cg_color_black
;
1676 CGColorRetain (gc
->cg_back_color
);
1682 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1683 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1684 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1686 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1694 /* Mac replacement for XSetFont. */
1697 XSetFont (display
, gc
, font
)
1702 gc
->xgcv
.font
= font
;
1706 /* Mac replacement for XSetClipRectangles. */
1709 mac_set_clip_rectangles (f
, gc
, rectangles
, n
)
1717 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1719 gc
->n_clip_rects
= n
;
1722 if (gc
->clip_region
== NULL
)
1723 gc
->clip_region
= NewRgn ();
1724 RectRgn (gc
->clip_region
, rectangles
);
1727 RgnHandle region
= NewRgn ();
1729 for (i
= 1; i
< n
; i
++)
1731 RectRgn (region
, rectangles
+ i
);
1732 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1734 DisposeRgn (region
);
1737 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1738 for (i
= 0; i
< n
; i
++)
1740 Rect
*rect
= rectangles
+ i
;
1742 gc
->clip_rects
[i
] = mac_rect_make (f
, rect
->left
, rect
->top
,
1743 rect
->right
- rect
->left
,
1744 rect
->bottom
- rect
->top
);
1750 /* Mac replacement for XSetClipMask. */
1753 mac_reset_clip_rectangles (f
, gc
)
1757 gc
->n_clip_rects
= 0;
1760 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1761 Calls to XFlush should be unnecessary because the X output buffer
1762 is flushed automatically as needed by calls to XPending,
1763 XNextEvent, or XWindowEvent according to the XFlush man page.
1764 XTread_socket calls XPending. Removing XFlush improves
1767 #define XFlush(DISPLAY) (void) 0
1770 /***********************************************************************
1771 Starting and ending an update
1772 ***********************************************************************/
1774 /* Start an update of frame F. This function is installed as a hook
1775 for update_begin, i.e. it is called when update_begin is called.
1776 This function is called prior to calls to x_update_window_begin for
1777 each window being updated. */
1784 mac_update_begin (f
);
1789 /* Start update of window W. Set the global variable updated_window
1790 to the window being updated and set output_cursor to the cursor
1794 x_update_window_begin (w
)
1797 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1798 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1801 set_output_cursor (&w
->cursor
);
1805 if (f
== display_info
->mouse_face_mouse_frame
)
1807 /* Don't do highlighting for mouse motion during the update. */
1808 display_info
->mouse_face_defer
= 1;
1810 /* If F needs to be redrawn, simply forget about any prior mouse
1812 if (FRAME_GARBAGED_P (f
))
1813 display_info
->mouse_face_window
= Qnil
;
1815 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1816 their mouse_face_p flag set, which means that they are always
1817 unequal to rows in a desired matrix which never have that
1818 flag set. So, rows containing mouse-face glyphs are never
1819 scrolled, and we don't have to switch the mouse highlight off
1820 here to prevent it from being scrolled. */
1822 /* Can we tell that this update does not affect the window
1823 where the mouse highlight is? If so, no need to turn off.
1824 Likewise, don't do anything if the frame is garbaged;
1825 in that case, the frame's current matrix that we would use
1826 is all wrong, and we will redisplay that line anyway. */
1827 if (!NILP (display_info
->mouse_face_window
)
1828 && w
== XWINDOW (display_info
->mouse_face_window
))
1832 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1833 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1836 if (i
< w
->desired_matrix
->nrows
)
1837 clear_mouse_face (display_info
);
1846 /* Draw a vertical window border from (x,y0) to (x,y1) */
1849 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1853 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1856 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1858 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1861 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1864 /* End update of window W (which is equal to updated_window).
1866 Draw vertical borders between horizontally adjacent windows, and
1867 display W's cursor if CURSOR_ON_P is non-zero.
1869 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1870 glyphs in mouse-face were overwritten. In that case we have to
1871 make sure that the mouse-highlight is properly redrawn.
1873 W may be a menu bar pseudo-window in case we don't have X toolkit
1874 support. Such windows don't have a cursor, so don't display it
1878 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1880 int cursor_on_p
, mouse_face_overwritten_p
;
1882 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1884 if (!w
->pseudo_window_p
)
1889 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1891 output_cursor
.x
, output_cursor
.y
);
1893 if (draw_window_fringes (w
, 1))
1894 x_draw_vertical_border (w
);
1899 /* If a row with mouse-face was overwritten, arrange for
1900 XTframe_up_to_date to redisplay the mouse highlight. */
1901 if (mouse_face_overwritten_p
)
1903 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1904 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1905 dpyinfo
->mouse_face_window
= Qnil
;
1908 updated_window
= NULL
;
1912 /* End update of frame F. This function is installed as a hook in
1919 /* Mouse highlight may be displayed again. */
1920 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1924 XFlush (FRAME_MAC_DISPLAY (f
));
1929 /* This function is called from various places in xdisp.c whenever a
1930 complete update has been performed. The global variable
1931 updated_window is not available here. */
1934 XTframe_up_to_date (f
)
1937 if (FRAME_MAC_P (f
))
1939 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1941 if (dpyinfo
->mouse_face_deferred_gc
1942 || f
== dpyinfo
->mouse_face_mouse_frame
)
1945 if (dpyinfo
->mouse_face_mouse_frame
)
1946 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1947 dpyinfo
->mouse_face_mouse_x
,
1948 dpyinfo
->mouse_face_mouse_y
);
1949 dpyinfo
->mouse_face_deferred_gc
= 0;
1953 mac_frame_up_to_date (f
);
1958 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1959 arrow bitmaps, or clear the fringes if no bitmaps are required
1960 before DESIRED_ROW is made current. The window being updated is
1961 found in updated_window. This function is called from
1962 update_window_line only if it is known that there are differences
1963 between bitmaps to be drawn between current row and DESIRED_ROW. */
1966 x_after_update_window_line (desired_row
)
1967 struct glyph_row
*desired_row
;
1969 struct window
*w
= updated_window
;
1975 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1976 desired_row
->redraw_fringe_bitmaps_p
= 1;
1978 /* When a window has disappeared, make sure that no rest of
1979 full-width rows stays visible in the internal border. Could
1980 check here if updated_window is the leftmost/rightmost window,
1981 but I guess it's not worth doing since vertically split windows
1982 are almost never used, internal border is rarely set, and the
1983 overhead is very small. */
1984 if (windows_or_buffers_changed
1985 && desired_row
->full_width_p
1986 && (f
= XFRAME (w
->frame
),
1987 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1989 && (height
= desired_row
->visible_height
,
1992 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1994 /* Internal border is drawn below the tool bar. */
1995 if (WINDOWP (f
->tool_bar_window
)
1996 && w
== XWINDOW (f
->tool_bar_window
))
2000 mac_clear_area (f
, 0, y
, width
, height
);
2001 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2007 /* Draw the bitmap WHICH in one of the left or right fringes of
2008 window W. ROW is the glyph row for which to display the bitmap; it
2009 determines the vertical position at which the bitmap has to be
2013 x_draw_fringe_bitmap (w
, row
, p
)
2015 struct glyph_row
*row
;
2016 struct draw_fringe_bitmap_params
*p
;
2018 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2019 Display
*display
= FRAME_MAC_DISPLAY (f
);
2020 struct face
*face
= p
->face
;
2022 int overlay_p
= p
->overlay_p
;
2027 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
2029 #if 0 /* MAC_TODO: stipple */
2030 /* In case the same realized face is used for fringes and
2031 for something displayed in the text (e.g. face `region' on
2032 mono-displays, the fill style may have been changed to
2033 FillSolid in x_draw_glyph_string_background. */
2035 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2037 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2040 /* If the fringe is adjacent to the left (right) scroll bar of a
2041 leftmost (rightmost, respectively) window, then extend its
2042 background to the gap between the fringe and the bar. */
2043 if ((WINDOW_LEFTMOST_P (w
)
2044 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
2045 || (WINDOW_RIGHTMOST_P (w
)
2046 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
2048 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
2052 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
2053 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
2054 * FRAME_COLUMN_WIDTH (f
));
2057 && (left
+ width
== p
->x
2058 || p
->x
+ p
->wd
== left
))
2060 /* Bitmap fills the fringe and we need background
2062 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
2066 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
2068 ny
= row
->visible_height
;
2073 if (left
+ width
== bx
)
2075 bx
= left
+ sb_width
;
2076 nx
+= width
- sb_width
;
2078 else if (bx
+ nx
== left
)
2079 nx
+= width
- sb_width
;
2086 mac_erase_rectangle (f
, face
->gc
, bx
, by
, nx
, ny
);
2087 /* The fringe background has already been filled. */
2091 #if 0 /* MAC_TODO: stipple */
2093 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2096 #endif /* MAC_OSX */
2098 /* Must clip because of partially visible lines. */
2099 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2102 /* Adjust position of "bottom aligned" bitmap on partially
2103 visible last row. */
2105 int oldVH
= row
->visible_height
;
2106 row
->visible_height
= p
->h
;
2107 row
->y
-= rowY
- p
->y
;
2108 x_clip_to_row (w
, row
, -1, face
->gc
);
2110 row
->visible_height
= oldVH
;
2113 x_clip_to_row (w
, row
, -1, face
->gc
);
2116 if (p
->bx
>= 0 && !p
->overlay_p
)
2118 #if 0 /* MAC_TODO: stipple */
2119 /* In case the same realized face is used for fringes and
2120 for something displayed in the text (e.g. face `region' on
2121 mono-displays, the fill style may have been changed to
2122 FillSolid in x_draw_glyph_string_background. */
2124 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2126 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2129 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2131 #if 0 /* MAC_TODO: stipple */
2133 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2136 #endif /* !MAC_OSX */
2140 && p
->which
< max_fringe_bmp
2146 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2147 XSetForeground (display
, face
->gc
,
2149 ? (p
->overlay_p
? face
->background
2150 : f
->output_data
.mac
->cursor_pixel
)
2151 : face
->foreground
));
2153 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2154 p
->wd
, p
->h
, p
->x
, p
->y
, overlay_p
);
2156 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2157 p
->wd
, p
->h
, p
->bits
+ p
->dh
, overlay_p
);
2159 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2162 mac_reset_clip_rectangles (f
, face
->gc
);
2167 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2169 unsigned short *bits
;
2173 CGDataProviderRef provider
;
2175 if (which
>= max_fringe_bmp
)
2178 max_fringe_bmp
= which
+ 20;
2179 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2180 while (i
< max_fringe_bmp
)
2181 fringe_bmp
[i
++] = 0;
2184 for (i
= 0; i
< h
; i
++)
2189 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2190 sizeof (unsigned short) * h
, NULL
);
2193 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2194 sizeof (unsigned short),
2196 CGDataProviderRelease (provider
);
2203 mac_destroy_fringe_bitmap (which
)
2206 if (which
>= max_fringe_bmp
)
2209 if (fringe_bmp
[which
])
2212 CGImageRelease (fringe_bmp
[which
]);
2215 fringe_bmp
[which
] = 0;
2220 /* This is called when starting Emacs and when restarting after
2221 suspend. When starting Emacs, no window is mapped. And nothing
2222 must be done to Emacs's own window if it is suspended (though that
2226 XTset_terminal_modes ()
2230 /* This is called when exiting or suspending Emacs. Exiting will make
2231 the windows go away, and suspending requires no action. */
2234 XTreset_terminal_modes ()
2240 /***********************************************************************
2242 ***********************************************************************/
2244 /* Function prototypes of this page. */
2246 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2247 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2251 pcm_init (pcm
, count
)
2255 bzero (pcm
, sizeof (XCharStruct
) * count
);
2256 while (--count
>= 0)
2258 pcm
->descent
= PCM_INVALID
;
2263 static enum pcm_status
2264 pcm_get_status (pcm
)
2265 const XCharStruct
*pcm
;
2267 int height
= pcm
->ascent
+ pcm
->descent
;
2269 /* Negative height means some special status. */
2270 return height
>= 0 ? PCM_VALID
: height
;
2273 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2274 is not contained in the font. */
2276 static INLINE XCharStruct
*
2277 x_per_char_metric (font
, char2b
)
2281 /* The result metric information. */
2282 XCharStruct
*pcm
= NULL
;
2284 xassert (font
&& char2b
);
2287 if (font
->mac_style
)
2289 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2293 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2294 pcm_init (*row
, 0x100);
2296 pcm
= *row
+ char2b
->byte2
;
2297 if (pcm_get_status (pcm
) != PCM_VALID
)
2300 mac_query_char_extents (font
->mac_style
,
2301 (char2b
->byte1
<< 8) + char2b
->byte2
,
2302 NULL
, NULL
, pcm
, NULL
);
2309 if (font
->bounds
.per_char
!= NULL
)
2311 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2313 /* min_char_or_byte2 specifies the linear character index
2314 corresponding to the first element of the per_char array,
2315 max_char_or_byte2 is the index of the last character. A
2316 character with non-zero CHAR2B->byte1 is not in the font.
2317 A character with byte2 less than min_char_or_byte2 or
2318 greater max_char_or_byte2 is not in the font. */
2319 if (char2b
->byte1
== 0
2320 && char2b
->byte2
>= font
->min_char_or_byte2
2321 && char2b
->byte2
<= font
->max_char_or_byte2
)
2322 pcm
= font
->bounds
.per_char
2323 + (char2b
->byte2
- font
->min_char_or_byte2
);
2327 /* If either min_byte1 or max_byte1 are nonzero, both
2328 min_char_or_byte2 and max_char_or_byte2 are less than
2329 256, and the 2-byte character index values corresponding
2330 to the per_char array element N (counting from 0) are:
2332 byte1 = N/D + min_byte1
2333 byte2 = N\D + min_char_or_byte2
2337 D = max_char_or_byte2 - min_char_or_byte2 + 1
2338 / = integer division
2339 \ = integer modulus */
2340 if (char2b
->byte1
>= font
->min_byte1
2341 && char2b
->byte1
<= font
->max_byte1
2342 && char2b
->byte2
>= font
->min_char_or_byte2
2343 && char2b
->byte2
<= font
->max_char_or_byte2
)
2345 pcm
= (font
->bounds
.per_char
2346 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2347 * (char2b
->byte1
- font
->min_byte1
))
2348 + (char2b
->byte2
- font
->min_char_or_byte2
));
2354 /* If the per_char pointer is null, all glyphs between the first
2355 and last character indexes inclusive have the same
2356 information, as given by both min_bounds and max_bounds. */
2357 if (char2b
->byte2
>= font
->min_char_or_byte2
2358 && char2b
->byte2
<= font
->max_char_or_byte2
)
2359 pcm
= &font
->max_bounds
;
2365 return ((pcm
== NULL
2367 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2368 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2377 static XCharStruct
*
2378 mac_per_char_metric (font
, char2b
, font_type
)
2383 return x_per_char_metric (font
, char2b
);
2387 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2388 the two-byte form of C. Encoding is returned in *CHAR2B. */
2391 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2394 struct font_info
*font_info
;
2397 int charset
= CHAR_CHARSET (c
);
2398 XFontStruct
*font
= font_info
->font
;
2400 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2401 This may be either a program in a special encoder language or a
2403 if (font_info
->font_encoder
)
2405 /* It's a program. */
2406 struct ccl_program
*ccl
= font_info
->font_encoder
;
2408 check_ccl_update (ccl
);
2409 if (CHARSET_DIMENSION (charset
) == 1)
2411 ccl
->reg
[0] = charset
;
2412 ccl
->reg
[1] = char2b
->byte2
;
2417 ccl
->reg
[0] = charset
;
2418 ccl
->reg
[1] = char2b
->byte1
;
2419 ccl
->reg
[2] = char2b
->byte2
;
2422 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2424 /* We assume that MSBs are appropriately set/reset by CCL
2426 if (font
->max_byte1
== 0) /* 1-byte font */
2427 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2429 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2431 else if (font_info
->encoding
[charset
])
2433 /* Fixed encoding scheme. See fontset.h for the meaning of the
2434 encoding numbers. */
2435 int enc
= font_info
->encoding
[charset
];
2437 if ((enc
== 1 || enc
== 2)
2438 && CHARSET_DIMENSION (charset
) == 2)
2439 char2b
->byte1
|= 0x80;
2441 if (enc
== 1 || enc
== 3)
2442 char2b
->byte2
|= 0x80;
2448 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2449 char2b
->byte1
= sjis1
;
2450 char2b
->byte2
= sjis2
;
2455 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2457 return FONT_TYPE_UNKNOWN
;
2462 /***********************************************************************
2464 ***********************************************************************/
2468 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2469 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2470 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2472 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2473 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2474 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2475 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2476 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2477 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2478 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2479 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2480 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2481 unsigned long *, double, int));*/
2482 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2483 double, int, unsigned long));
2484 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2485 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2486 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2487 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2488 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2490 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2491 int, int, int, int, int, int,
2493 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2494 int, int, int, Rect
*));
2497 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2501 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2506 struct glyph_string
*s
;
2508 if (s
->font
== FRAME_FONT (s
->f
)
2509 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2510 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2512 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2515 /* Cursor on non-default face: must merge. */
2519 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2520 xgcv
.foreground
= s
->face
->background
;
2522 /* If the glyph would be invisible, try a different foreground. */
2523 if (xgcv
.foreground
== xgcv
.background
)
2524 xgcv
.foreground
= s
->face
->foreground
;
2525 if (xgcv
.foreground
== xgcv
.background
)
2526 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2527 if (xgcv
.foreground
== xgcv
.background
)
2528 xgcv
.foreground
= s
->face
->foreground
;
2530 /* Make sure the cursor is distinct from text in this face. */
2531 if (xgcv
.background
== s
->face
->background
2532 && xgcv
.foreground
== s
->face
->foreground
)
2534 xgcv
.background
= s
->face
->foreground
;
2535 xgcv
.foreground
= s
->face
->background
;
2538 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2539 xgcv
.font
= s
->font
;
2540 mask
= GCForeground
| GCBackground
| GCFont
;
2542 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2543 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2546 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2547 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2549 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2554 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2557 x_set_mouse_face_gc (s
)
2558 struct glyph_string
*s
;
2563 /* What face has to be used last for the mouse face? */
2564 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2565 face
= FACE_FROM_ID (s
->f
, face_id
);
2567 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2569 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2570 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2572 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2573 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2574 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2576 /* If font in this face is same as S->font, use it. */
2577 if (s
->font
== s
->face
->font
)
2578 s
->gc
= s
->face
->gc
;
2581 /* Otherwise construct scratch_cursor_gc with values from FACE
2586 xgcv
.background
= s
->face
->background
;
2587 xgcv
.foreground
= s
->face
->foreground
;
2588 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2589 xgcv
.font
= s
->font
;
2590 mask
= GCForeground
| GCBackground
| GCFont
;
2592 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2593 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2596 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2597 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2599 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2602 xassert (s
->gc
!= 0);
2606 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2607 Faces to use in the mode line have already been computed when the
2608 matrix was built, so there isn't much to do, here. */
2611 x_set_mode_line_face_gc (s
)
2612 struct glyph_string
*s
;
2614 s
->gc
= s
->face
->gc
;
2618 /* Set S->gc of glyph string S for drawing that glyph string. Set
2619 S->stippled_p to a non-zero value if the face of S has a stipple
2623 x_set_glyph_string_gc (s
)
2624 struct glyph_string
*s
;
2626 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2628 if (s
->hl
== DRAW_NORMAL_TEXT
)
2630 s
->gc
= s
->face
->gc
;
2631 s
->stippled_p
= s
->face
->stipple
!= 0;
2633 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2635 x_set_mode_line_face_gc (s
);
2636 s
->stippled_p
= s
->face
->stipple
!= 0;
2638 else if (s
->hl
== DRAW_CURSOR
)
2640 x_set_cursor_gc (s
);
2643 else if (s
->hl
== DRAW_MOUSE_FACE
)
2645 x_set_mouse_face_gc (s
);
2646 s
->stippled_p
= s
->face
->stipple
!= 0;
2648 else if (s
->hl
== DRAW_IMAGE_RAISED
2649 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2651 s
->gc
= s
->face
->gc
;
2652 s
->stippled_p
= s
->face
->stipple
!= 0;
2656 s
->gc
= s
->face
->gc
;
2657 s
->stippled_p
= s
->face
->stipple
!= 0;
2660 /* GC must have been set. */
2661 xassert (s
->gc
!= 0);
2665 /* Set clipping for output of glyph string S. S may be part of a mode
2666 line or menu if we don't have X toolkit support. */
2669 x_set_glyph_string_clipping (s
)
2670 struct glyph_string
*s
;
2672 Rect rects
[MAX_CLIP_RECTS
];
2675 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2676 mac_set_clip_rectangles (s
->f
, s
->gc
, rects
, n
);
2681 Compute left and right overhang of glyph string S. If S is a glyph
2682 string for a composition, assume overhangs don't exist. */
2685 mac_compute_glyph_string_overhangs (s
)
2686 struct glyph_string
*s
;
2688 if (!(s
->cmp
== NULL
2689 && s
->first_glyph
->type
== CHAR_GLYPH
))
2694 || s
->font
->mac_style
2700 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2701 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2702 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2707 MacFontStruct
*font
= s
->font
;
2709 mac_begin_clip (s
->f
, NULL
);
2711 TextFont (font
->mac_fontnum
);
2712 TextSize (font
->mac_fontsize
);
2713 TextFace (font
->mac_fontface
);
2715 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2717 mac_end_clip (s
->f
, NULL
);
2719 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2720 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2725 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2728 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2729 struct glyph_string
*s
;
2732 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2736 /* Draw the background of glyph_string S. If S->background_filled_p
2737 is non-zero don't draw it. FORCE_P non-zero means draw the
2738 background even if it wouldn't be drawn normally. This is used
2739 when a string preceding S draws into the background of S, or S
2740 contains the first component of a composition. */
2743 x_draw_glyph_string_background (s
, force_p
)
2744 struct glyph_string
*s
;
2747 /* Nothing to do if background has already been drawn or if it
2748 shouldn't be drawn in the first place. */
2749 if (!s
->background_filled_p
)
2751 int box_line_width
= max (s
->face
->box_line_width
, 0);
2753 #if 0 /* MAC_TODO: stipple */
2756 /* Fill background with a stipple pattern. */
2757 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2758 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2759 s
->y
+ box_line_width
,
2760 s
->background_width
,
2761 s
->height
- 2 * box_line_width
);
2762 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2763 s
->background_filled_p
= 1;
2767 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2768 || s
->font_not_found_p
2769 || s
->extends_to_end_of_line_p
2772 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2773 s
->background_width
,
2774 s
->height
- 2 * box_line_width
);
2775 s
->background_filled_p
= 1;
2781 /* Draw the foreground of glyph string S. */
2784 x_draw_glyph_string_foreground (s
)
2785 struct glyph_string
*s
;
2789 /* If first glyph of S has a left box line, start drawing the text
2790 of S to the right of that box line. */
2791 if (s
->face
->box
!= FACE_NO_BOX
2792 && s
->first_glyph
->left_box_line_p
)
2793 x
= s
->x
+ abs (s
->face
->box_line_width
);
2797 /* Draw characters of S as rectangles if S's font could not be
2799 if (s
->font_not_found_p
)
2801 for (i
= 0; i
< s
->nchars
; ++i
)
2803 struct glyph
*g
= s
->first_glyph
+ i
;
2804 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2805 g
->pixel_width
- 1, s
->height
- 1);
2806 x
+= g
->pixel_width
;
2811 char *char1b
= (char *) s
->char2b
;
2812 int boff
= s
->font_info
->baseline_offset
;
2814 if (s
->font_info
->vertical_centering
)
2815 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2817 /* If we can use 8-bit functions, condense S->char2b. */
2820 && GC_FONT (s
->gc
)->mac_style
== NULL
2823 for (i
= 0; i
< s
->nchars
; ++i
)
2824 char1b
[i
] = s
->char2b
[i
].byte2
;
2826 /* Draw text with XDrawString if background has already been
2827 filled. Otherwise, use XDrawImageString. (Note that
2828 XDrawImageString is usually faster than XDrawString.) Always
2829 use XDrawImageString when drawing the cursor so that there is
2830 no chance that characters under a box cursor are invisible. */
2832 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2833 bg_width
= 0; /* Corresponds to XDrawString. */
2835 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2839 || GC_FONT (s
->gc
)->mac_style
2842 #if USE_CG_TEXT_DRAWING
2844 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2845 s
->char2b
, s
->nchars
, bg_width
,
2846 s
->face
->overstrike
))
2850 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2851 s
->char2b
, s
->nchars
, bg_width
,
2852 s
->face
->overstrike
);
2854 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2855 char1b
, s
->nchars
, bg_width
,
2856 s
->face
->overstrike
);
2860 /* Draw the foreground of composite glyph string S. */
2863 x_draw_composite_glyph_string_foreground (s
)
2864 struct glyph_string
*s
;
2868 /* If first glyph of S has a left box line, start drawing the text
2869 of S to the right of that box line. */
2870 if (s
->face
->box
!= FACE_NO_BOX
2871 && s
->first_glyph
->left_box_line_p
)
2872 x
= s
->x
+ abs (s
->face
->box_line_width
);
2876 /* S is a glyph string for a composition. S->gidx is the index of
2877 the first character drawn for glyphs of this composition.
2878 S->gidx == 0 means we are drawing the very first character of
2879 this composition. */
2881 /* Draw a rectangle for the composition if the font for the very
2882 first character of the composition could not be loaded. */
2883 if (s
->font_not_found_p
)
2886 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2887 s
->width
- 1, s
->height
- 1);
2891 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2892 if (mac_per_char_metric (GC_FONT (s
->gc
), s
->char2b
+ i
, 0) == NULL
)
2893 /* This is a nonexistent or zero-width glyph such as a
2894 combining diacritic. Draw a rectangle. */
2895 mac_draw_rectangle (s
->f
, s
->gc
,
2896 x
+ s
->cmp
->offsets
[s
->gidx
* 2], s
->y
,
2897 FONT_WIDTH (GC_FONT (s
->gc
)) - 1, s
->height
- 1);
2899 mac_draw_image_string_16 (s
->f
, s
->gc
,
2900 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2901 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2902 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
2907 #ifdef USE_X_TOOLKIT
2909 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2912 /* Return the frame on which widget WIDGET is used.. Abort if frame
2913 cannot be determined. */
2915 static struct frame
*
2916 x_frame_of_widget (widget
)
2919 struct x_display_info
*dpyinfo
;
2923 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2925 /* Find the top-level shell of the widget. Note that this function
2926 can be called when the widget is not yet realized, so XtWindow
2927 (widget) == 0. That's the reason we can't simply use
2928 x_any_window_to_frame. */
2929 while (!XtIsTopLevelShell (widget
))
2930 widget
= XtParent (widget
);
2932 /* Look for a frame with that top-level widget. Allocate the color
2933 on that frame to get the right gamma correction value. */
2934 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2935 if (GC_FRAMEP (XCAR (tail
))
2936 && (f
= XFRAME (XCAR (tail
)),
2937 (f
->output_data
.nothing
!= 1
2938 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2939 && f
->output_data
.x
->widget
== widget
)
2946 /* Allocate the color COLOR->pixel on the screen and display of
2947 widget WIDGET in colormap CMAP. If an exact match cannot be
2948 allocated, try the nearest color available. Value is non-zero
2949 if successful. This is called from lwlib. */
2952 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2957 struct frame
*f
= x_frame_of_widget (widget
);
2958 return x_alloc_nearest_color (f
, cmap
, color
);
2962 #endif /* USE_X_TOOLKIT */
2964 #if 0 /* MAC_TODO */
2966 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2967 CMAP. If an exact match can't be allocated, try the nearest color
2968 available. Value is non-zero if successful. Set *COLOR to the
2972 x_alloc_nearest_color (f
, cmap
, color
)
2977 Display
*display
= FRAME_X_DISPLAY (f
);
2978 Screen
*screen
= FRAME_X_SCREEN (f
);
2981 gamma_correct (f
, color
);
2982 rc
= XAllocColor (display
, cmap
, color
);
2985 /* If we got to this point, the colormap is full, so we're going
2986 to try to get the next closest color. The algorithm used is
2987 a least-squares matching, which is what X uses for closest
2988 color matching with StaticColor visuals. */
2990 unsigned long nearest_delta
= ~0;
2991 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2992 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2994 for (i
= 0; i
< ncells
; ++i
)
2996 XQueryColors (display
, cmap
, cells
, ncells
);
2998 for (nearest
= i
= 0; i
< ncells
; ++i
)
3000 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3001 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3002 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3003 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3005 if (delta
< nearest_delta
)
3008 nearest_delta
= delta
;
3012 color
->red
= cells
[nearest
].red
;
3013 color
->green
= cells
[nearest
].green
;
3014 color
->blue
= cells
[nearest
].blue
;
3015 rc
= XAllocColor (display
, cmap
, color
);
3018 #ifdef DEBUG_X_COLORS
3020 register_color (color
->pixel
);
3021 #endif /* DEBUG_X_COLORS */
3027 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3028 It's necessary to do this instead of just using PIXEL directly to
3029 get color reference counts right. */
3032 x_copy_color (f
, pixel
)
3034 unsigned long pixel
;
3038 color
.pixel
= pixel
;
3040 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3041 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3043 #ifdef DEBUG_X_COLORS
3044 register_color (pixel
);
3050 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3051 It's necessary to do this instead of just using PIXEL directly to
3052 get color reference counts right. */
3055 x_copy_dpy_color (dpy
, cmap
, pixel
)
3058 unsigned long pixel
;
3062 color
.pixel
= pixel
;
3064 XQueryColor (dpy
, cmap
, &color
);
3065 XAllocColor (dpy
, cmap
, &color
);
3067 #ifdef DEBUG_X_COLORS
3068 register_color (pixel
);
3073 #endif /* MAC_TODO */
3076 /* Brightness beyond which a color won't have its highlight brightness
3079 Nominally, highlight colors for `3d' faces are calculated by
3080 brightening an object's color by a constant scale factor, but this
3081 doesn't yield good results for dark colors, so for colors who's
3082 brightness is less than this value (on a scale of 0-255) have to
3083 use an additional additive factor.
3085 The value here is set so that the default menu-bar/mode-line color
3086 (grey75) will not have its highlights changed at all. */
3087 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3090 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3091 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3092 If this produces the same color as COLOR, try a color where all RGB
3093 values have DELTA added. Return the allocated color in *COLOR.
3094 DISPLAY is the X display, CMAP is the colormap to operate on.
3095 Value is non-zero if successful. */
3098 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3100 unsigned long *color
;
3107 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3110 /* Change RGB values by specified FACTOR. Avoid overflow! */
3111 xassert (factor
>= 0);
3112 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3113 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3114 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3116 /* Calculate brightness of COLOR. */
3117 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3118 + BLUE_FROM_ULONG (*color
)) / 6;
3120 /* We only boost colors that are darker than
3121 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3122 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3123 /* Make an additive adjustment to NEW, because it's dark enough so
3124 that scaling by FACTOR alone isn't enough. */
3126 /* How far below the limit this color is (0 - 1, 1 being darker). */
3127 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3128 /* The additive adjustment. */
3129 int min_delta
= delta
* dimness
* factor
/ 2;
3132 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3133 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3134 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3136 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3137 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3138 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3142 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3143 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3144 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3146 /* MAC_TODO: Map to palette and retry with delta if same? */
3147 /* MAC_TODO: Free colors (if using palette)? */
3158 /* Set up the foreground color for drawing relief lines of glyph
3159 string S. RELIEF is a pointer to a struct relief containing the GC
3160 with which lines will be drawn. Use a color that is FACTOR or
3161 DELTA lighter or darker than the relief's background which is found
3162 in S->f->output_data.x->relief_background. If such a color cannot
3163 be allocated, use DEFAULT_PIXEL, instead. */
3166 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3168 struct relief
*relief
;
3171 unsigned long default_pixel
;
3174 struct mac_output
*di
= f
->output_data
.mac
;
3175 unsigned long mask
= GCForeground
;
3176 unsigned long pixel
;
3177 unsigned long background
= di
->relief_background
;
3178 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3180 /* MAC_TODO: Free colors (if using palette)? */
3182 /* Allocate new color. */
3183 xgcv
.foreground
= default_pixel
;
3185 if (dpyinfo
->n_planes
!= 1
3186 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3188 relief
->allocated_p
= 1;
3189 xgcv
.foreground
= relief
->pixel
= pixel
;
3192 if (relief
->gc
== 0)
3194 #if 0 /* MAC_TODO: stipple */
3195 xgcv
.stipple
= dpyinfo
->gray
;
3198 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3201 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3205 /* Set up colors for the relief lines around glyph string S. */
3208 x_setup_relief_colors (s
)
3209 struct glyph_string
*s
;
3211 struct mac_output
*di
= s
->f
->output_data
.mac
;
3212 unsigned long color
;
3214 if (s
->face
->use_box_color_for_shadows_p
)
3215 color
= s
->face
->box_color
;
3216 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3218 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3219 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3224 /* Get the background color of the face. */
3225 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3226 color
= xgcv
.background
;
3229 if (di
->white_relief
.gc
== 0
3230 || color
!= di
->relief_background
)
3232 di
->relief_background
= color
;
3233 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3234 WHITE_PIX_DEFAULT (s
->f
));
3235 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3236 BLACK_PIX_DEFAULT (s
->f
));
3241 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3242 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3243 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3244 relief. LEFT_P non-zero means draw a relief on the left side of
3245 the rectangle. RIGHT_P non-zero means draw a relief on the right
3246 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3250 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3251 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3253 int left_x
, top_y
, right_x
, bottom_y
, width
;
3254 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3257 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3262 gc
= f
->output_data
.mac
->white_relief
.gc
;
3264 gc
= f
->output_data
.mac
->black_relief
.gc
;
3265 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3269 for (i
= 0; i
< width
; ++i
)
3270 mac_draw_line (f
, gc
,
3271 left_x
+ i
* left_p
, top_y
+ i
,
3272 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3276 for (i
= 0; i
< width
; ++i
)
3277 mac_draw_line (f
, gc
,
3278 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3280 mac_reset_clip_rectangles (f
, gc
);
3282 gc
= f
->output_data
.mac
->black_relief
.gc
;
3284 gc
= f
->output_data
.mac
->white_relief
.gc
;
3285 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3289 for (i
= 0; i
< width
; ++i
)
3290 mac_draw_line (f
, gc
,
3291 left_x
+ i
* left_p
, bottom_y
- i
,
3292 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3296 for (i
= 0; i
< width
; ++i
)
3297 mac_draw_line (f
, gc
,
3298 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3300 mac_reset_clip_rectangles (f
, gc
);
3304 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3305 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3306 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3307 left side of the rectangle. RIGHT_P non-zero means draw a line
3308 on the right side of the rectangle. CLIP_RECT is the clipping
3309 rectangle to use when drawing. */
3312 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3313 left_p
, right_p
, clip_rect
)
3314 struct glyph_string
*s
;
3315 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3320 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3321 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3322 mac_set_clip_rectangles (s
->f
, s
->gc
, clip_rect
, 1);
3325 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3326 right_x
- left_x
+ 1, width
);
3330 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3331 width
, bottom_y
- top_y
+ 1);
3334 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3335 right_x
- left_x
+ 1, width
);
3339 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3340 top_y
, width
, bottom_y
- top_y
+ 1);
3342 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3343 mac_reset_clip_rectangles (s
->f
, s
->gc
);
3347 /* Draw a box around glyph string S. */
3350 x_draw_glyph_string_box (s
)
3351 struct glyph_string
*s
;
3353 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3354 int left_p
, right_p
;
3355 struct glyph
*last_glyph
;
3358 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3359 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3360 : window_box_right (s
->w
, s
->area
));
3362 /* The glyph that may have a right box line. */
3363 last_glyph
= (s
->cmp
|| s
->img
3365 : s
->first_glyph
+ s
->nchars
- 1);
3367 width
= abs (s
->face
->box_line_width
);
3368 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3370 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3372 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3374 bottom_y
= top_y
+ s
->height
- 1;
3376 left_p
= (s
->first_glyph
->left_box_line_p
3377 || (s
->hl
== DRAW_MOUSE_FACE
3379 || s
->prev
->hl
!= s
->hl
)));
3380 right_p
= (last_glyph
->right_box_line_p
3381 || (s
->hl
== DRAW_MOUSE_FACE
3383 || s
->next
->hl
!= s
->hl
)));
3385 get_glyph_string_clip_rect (s
, &clip_rect
);
3387 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3388 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3389 left_p
, right_p
, &clip_rect
);
3392 x_setup_relief_colors (s
);
3393 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3394 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3399 /* Draw foreground of image glyph string S. */
3402 x_draw_image_foreground (s
)
3403 struct glyph_string
*s
;
3406 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3408 /* If first glyph of S has a left box line, start drawing it to the
3409 right of that line. */
3410 if (s
->face
->box
!= FACE_NO_BOX
3411 && s
->first_glyph
->left_box_line_p
3413 x
+= abs (s
->face
->box_line_width
);
3415 /* If there is a margin around the image, adjust x- and y-position
3417 if (s
->slice
.x
== 0)
3418 x
+= s
->img
->hmargin
;
3419 if (s
->slice
.y
== 0)
3420 y
+= s
->img
->vmargin
;
3424 x_set_glyph_string_clipping (s
);
3427 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3428 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3429 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3433 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3434 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3435 s
->slice
.width
, s
->slice
.height
, x
, y
);
3442 mac_copy_area (s
->img
->pixmap
,
3443 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3444 s
->slice
.width
, s
->slice
.height
, x
, y
);
3447 /* When the image has a mask, we can expect that at
3448 least part of a mouse highlight or a block cursor will
3449 be visible. If the image doesn't have a mask, make
3450 a block cursor visible by drawing a rectangle around
3451 the image. I believe it's looking better if we do
3452 nothing here for mouse-face. */
3453 if (s
->hl
== DRAW_CURSOR
)
3455 int r
= s
->img
->relief
;
3457 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3458 s
->slice
.width
+ r
*2 - 1,
3459 s
->slice
.height
+ r
*2 - 1);
3464 /* Draw a rectangle if image could not be loaded. */
3465 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3466 s
->slice
.width
- 1, s
->slice
.height
- 1);
3470 /* Draw a relief around the image glyph string S. */
3473 x_draw_image_relief (s
)
3474 struct glyph_string
*s
;
3476 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3479 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3481 /* If first glyph of S has a left box line, start drawing it to the
3482 right of that line. */
3483 if (s
->face
->box
!= FACE_NO_BOX
3484 && s
->first_glyph
->left_box_line_p
3486 x
+= abs (s
->face
->box_line_width
);
3488 /* If there is a margin around the image, adjust x- and y-position
3490 if (s
->slice
.x
== 0)
3491 x
+= s
->img
->hmargin
;
3492 if (s
->slice
.y
== 0)
3493 y
+= s
->img
->vmargin
;
3495 if (s
->hl
== DRAW_IMAGE_SUNKEN
3496 || s
->hl
== DRAW_IMAGE_RAISED
)
3498 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3499 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3503 thick
= abs (s
->img
->relief
);
3504 raised_p
= s
->img
->relief
> 0;
3509 x1
= x
+ s
->slice
.width
+ thick
- 1;
3510 y1
= y
+ s
->slice
.height
+ thick
- 1;
3512 x_setup_relief_colors (s
);
3513 get_glyph_string_clip_rect (s
, &r
);
3514 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3516 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3518 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3523 /* Draw part of the background of glyph string S. X, Y, W, and H
3524 give the rectangle to draw. */
3527 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3528 struct glyph_string
*s
;
3531 #if 0 /* MAC_TODO: stipple */
3534 /* Fill background with a stipple pattern. */
3535 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3536 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3537 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3540 #endif /* MAC_TODO */
3541 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3545 /* Draw image glyph string S.
3548 s->x +-------------------------
3551 | +-------------------------
3554 | | +-------------------
3560 x_draw_image_glyph_string (s
)
3561 struct glyph_string
*s
;
3564 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3565 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3568 height
= s
->height
- 2 * box_line_vwidth
;
3571 /* Fill background with face under the image. Do it only if row is
3572 taller than image or if image has a clip mask to reduce
3574 s
->stippled_p
= s
->face
->stipple
!= 0;
3575 if (height
> s
->slice
.height
3579 || s
->img
->pixmap
== 0
3580 || s
->width
!= s
->background_width
)
3583 if (s
->first_glyph
->left_box_line_p
3585 x
+= box_line_hwidth
;
3588 if (s
->slice
.y
== 0)
3589 y
+= box_line_vwidth
;
3591 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3593 s
->background_filled_p
= 1;
3596 /* Draw the foreground. */
3597 x_draw_image_foreground (s
);
3599 /* If we must draw a relief around the image, do it. */
3601 || s
->hl
== DRAW_IMAGE_RAISED
3602 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3603 x_draw_image_relief (s
);
3607 /* Draw stretch glyph string S. */
3610 x_draw_stretch_glyph_string (s
)
3611 struct glyph_string
*s
;
3613 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3615 if (s
->hl
== DRAW_CURSOR
3616 && !x_stretch_cursor_p
)
3618 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3619 as wide as the stretch glyph. */
3620 int width
, background_width
= s
->background_width
;
3621 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3625 background_width
-= left_x
- x
;
3628 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3631 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3633 /* Clear rest using the GC of the original non-cursor face. */
3634 if (width
< background_width
)
3637 int w
= background_width
- width
, h
= s
->height
;
3642 if (s
->row
->mouse_face_p
3643 && cursor_in_mouse_face_p (s
->w
))
3645 x_set_mouse_face_gc (s
);
3651 get_glyph_string_clip_rect (s
, &r
);
3652 mac_set_clip_rectangles (s
->f
, gc
, &r
, 1);
3654 #if 0 /* MAC_TODO: stipple */
3655 if (s
->face
->stipple
)
3657 /* Fill background with a stipple pattern. */
3658 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3659 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3660 XSetFillStyle (s
->display
, gc
, FillSolid
);
3663 #endif /* MAC_TODO */
3664 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3667 else if (!s
->background_filled_p
)
3669 int background_width
= s
->background_width
;
3670 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3672 /* Don't draw into left margin, fringe or scrollbar area
3673 except for header line and mode line. */
3674 if (x
< left_x
&& !s
->row
->mode_line_p
)
3676 background_width
-= left_x
- x
;
3679 if (background_width
> 0)
3680 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3683 s
->background_filled_p
= 1;
3687 /* Draw glyph string S. */
3690 x_draw_glyph_string (s
)
3691 struct glyph_string
*s
;
3693 int relief_drawn_p
= 0;
3695 /* If S draws into the background of its successor that does not
3696 draw a cursor, draw the background of the successor first so that
3697 S can draw into it. This makes S->next use XDrawString instead
3698 of XDrawImageString. */
3699 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3700 && s
->next
->hl
!= DRAW_CURSOR
)
3702 xassert (s
->next
->img
== NULL
);
3703 x_set_glyph_string_gc (s
->next
);
3704 x_set_glyph_string_clipping (s
->next
);
3705 x_draw_glyph_string_background (s
->next
, 1);
3708 /* Set up S->gc, set clipping and draw S. */
3709 x_set_glyph_string_gc (s
);
3711 /* Draw relief (if any) in advance for char/composition so that the
3712 glyph string can be drawn over it. */
3713 if (!s
->for_overlaps
3714 && s
->face
->box
!= FACE_NO_BOX
3715 && (s
->first_glyph
->type
== CHAR_GLYPH
3716 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3719 x_set_glyph_string_clipping (s
);
3720 x_draw_glyph_string_background (s
, 1);
3721 x_draw_glyph_string_box (s
);
3722 x_set_glyph_string_clipping (s
);
3726 x_set_glyph_string_clipping (s
);
3728 switch (s
->first_glyph
->type
)
3731 x_draw_image_glyph_string (s
);
3735 x_draw_stretch_glyph_string (s
);
3739 if (s
->for_overlaps
)
3740 s
->background_filled_p
= 1;
3742 x_draw_glyph_string_background (s
, 0);
3743 x_draw_glyph_string_foreground (s
);
3746 case COMPOSITE_GLYPH
:
3747 if (s
->for_overlaps
|| s
->gidx
> 0)
3748 s
->background_filled_p
= 1;
3750 x_draw_glyph_string_background (s
, 1);
3751 x_draw_composite_glyph_string_foreground (s
);
3758 if (!s
->for_overlaps
)
3760 /* Draw underline. */
3761 if (s
->face
->underline_p
)
3763 unsigned long tem
, h
;
3767 /* Get the underline thickness. Default is 1 pixel. */
3768 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3772 y
= s
->y
+ s
->height
- h
;
3773 if (!x_underline_at_descent_line
)
3775 /* Get the underline position. This is the recommended
3776 vertical offset in pixels from the baseline to the top of
3777 the underline. This is a signed value according to the
3778 specs, and its default is
3780 ROUND ((maximum descent) / 2), with
3781 ROUND(x) = floor (x + 0.5) */
3784 if (x_use_underline_position_properties
3785 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3786 y
= s
->ybase
+ (long) tem
;
3790 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3793 if (s
->face
->underline_defaulted_p
)
3794 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3795 s
->background_width
, h
);
3799 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3800 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3801 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3802 s
->background_width
, h
);
3803 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3807 /* Draw overline. */
3808 if (s
->face
->overline_p
)
3810 unsigned long dy
= 0, h
= 1;
3812 if (s
->face
->overline_color_defaulted_p
)
3813 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3814 s
->background_width
, h
);
3818 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3819 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3820 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3821 s
->background_width
, h
);
3822 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3826 /* Draw strike-through. */
3827 if (s
->face
->strike_through_p
)
3829 unsigned long h
= 1;
3830 unsigned long dy
= (s
->height
- h
) / 2;
3832 if (s
->face
->strike_through_color_defaulted_p
)
3833 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3838 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3839 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3840 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3842 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3846 /* Draw relief if not yet drawn. */
3847 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3848 x_draw_glyph_string_box (s
);
3851 /* Reset clipping. */
3852 mac_reset_clip_rectangles (s
->f
, s
->gc
);
3855 /* Shift display to make room for inserted glyphs. */
3858 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3860 int x
, y
, width
, height
, shift_by
;
3862 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3863 x
, y
, width
, height
,
3867 /* Delete N glyphs at the nominal cursor position. Not implemented
3878 /* Clear entire frame. If updating_frame is non-null, clear that
3879 frame. Otherwise clear the selected frame. */
3889 f
= SELECTED_FRAME ();
3891 /* Clearing the frame will erase any cursor, so mark them all as no
3893 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3894 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3895 output_cursor
.x
= -1;
3897 /* We don't set the output cursor here because there will always
3898 follow an explicit cursor_to. */
3900 mac_clear_window (f
);
3902 /* We have to clear the scroll bars, too. If we have changed
3903 colors or something like that, then they should be notified. */
3904 x_scroll_bar_clear (f
);
3906 XFlush (FRAME_MAC_DISPLAY (f
));
3912 /* Invert the middle quarter of the frame for .15 sec. */
3914 /* We use the select system call to do the waiting, so we have to make
3915 sure it's available. If it isn't, we just won't do visual bells. */
3917 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3920 /* Subtract the `struct timeval' values X and Y, storing the result in
3921 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3924 timeval_subtract (result
, x
, y
)
3925 struct timeval
*result
, x
, y
;
3927 /* Perform the carry for the later subtraction by updating y. This
3928 is safer because on some systems the tv_sec member is unsigned. */
3929 if (x
.tv_usec
< y
.tv_usec
)
3931 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3932 y
.tv_usec
-= 1000000 * nsec
;
3936 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3938 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3939 y
.tv_usec
+= 1000000 * nsec
;
3943 /* Compute the time remaining to wait. tv_usec is certainly
3945 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3946 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3948 /* Return indication of whether the result should be considered
3950 return x
.tv_sec
< y
.tv_sec
;
3957 /* Get the height not including a menu bar widget. */
3958 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3959 /* Height of each line to flash. */
3960 int flash_height
= FRAME_LINE_HEIGHT (f
);
3961 /* These will be the left and right margins of the rectangles. */
3962 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3963 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3967 /* Don't flash the area between a scroll bar and the frame
3968 edge it is next to. */
3969 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3971 case vertical_scroll_bar_left
:
3972 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3975 case vertical_scroll_bar_right
:
3976 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3983 width
= flash_right
- flash_left
;
3987 /* If window is tall, flash top and bottom line. */
3988 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3990 mac_invert_rectangle (f
, flash_left
,
3991 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3992 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3993 width
, flash_height
);
3994 mac_invert_rectangle (f
, flash_left
,
3995 (height
- flash_height
3996 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3997 width
, flash_height
);
4000 /* If it is short, flash it all. */
4001 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4002 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4007 struct timeval wakeup
;
4009 EMACS_GET_TIME (wakeup
);
4011 /* Compute time to wait until, propagating carry from usecs. */
4012 wakeup
.tv_usec
+= 150000;
4013 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4014 wakeup
.tv_usec
%= 1000000;
4016 /* Keep waiting until past the time wakeup or any input gets
4018 while (! detect_input_pending ())
4020 struct timeval current
;
4021 struct timeval timeout
;
4023 EMACS_GET_TIME (current
);
4025 /* Break if result would be negative. */
4026 if (timeval_subtract (¤t
, wakeup
, current
))
4029 /* How long `select' should wait. */
4031 timeout
.tv_usec
= 10000;
4033 /* Try to wait that long--but we might wake up sooner. */
4034 select (0, NULL
, NULL
, NULL
, &timeout
);
4038 /* If window is tall, flash top and bottom line. */
4039 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4041 mac_invert_rectangle (f
, flash_left
,
4042 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4043 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4044 width
, flash_height
);
4045 mac_invert_rectangle (f
, flash_left
,
4046 (height
- flash_height
4047 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4048 width
, flash_height
);
4051 /* If it is short, flash it all. */
4052 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4053 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4060 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4063 /* Make audible bell. */
4068 struct frame
*f
= SELECTED_FRAME ();
4070 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4077 mac_alert_sound_play ();
4078 XFlush (FRAME_MAC_DISPLAY (f
));
4084 /* Specify how many text lines, from the top of the window,
4085 should be affected by insert-lines and delete-lines operations.
4086 This, and those operations, are used only within an update
4087 that is bounded by calls to x_update_begin and x_update_end. */
4090 XTset_terminal_window (n
)
4093 /* This function intentionally left blank. */
4098 /***********************************************************************
4100 ***********************************************************************/
4102 /* Perform an insert-lines or delete-lines operation, inserting N
4103 lines or deleting -N lines at vertical position VPOS. */
4106 x_ins_del_lines (vpos
, n
)
4113 /* Scroll part of the display as described by RUN. */
4116 x_scroll_run (w
, run
)
4120 struct frame
*f
= XFRAME (w
->frame
);
4121 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4123 /* Get frame-relative bounding box of the text display area of W,
4124 without mode lines. Include in this box the left and right
4126 window_box (w
, -1, &x
, &y
, &width
, &height
);
4128 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4129 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4130 bottom_y
= y
+ height
;
4134 /* Scrolling up. Make sure we don't copy part of the mode
4135 line at the bottom. */
4136 if (from_y
+ run
->height
> bottom_y
)
4137 height
= bottom_y
- from_y
;
4139 height
= run
->height
;
4143 /* Scolling down. Make sure we don't copy over the mode line.
4145 if (to_y
+ run
->height
> bottom_y
)
4146 height
= bottom_y
- to_y
;
4148 height
= run
->height
;
4153 /* Cursor off. Will be switched on again in x_update_window_end. */
4157 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4167 /***********************************************************************
4169 ***********************************************************************/
4176 x_update_cursor (f
, 1);
4180 frame_unhighlight (f
)
4183 x_update_cursor (f
, 1);
4186 /* The focus has changed. Update the frames as necessary to reflect
4187 the new situation. Note that we can't change the selected frame
4188 here, because the Lisp code we are interrupting might become confused.
4189 Each event gets marked with the frame in which it occurred, so the
4190 Lisp code can tell when the switch took place by examining the events. */
4193 x_new_focus_frame (dpyinfo
, frame
)
4194 struct x_display_info
*dpyinfo
;
4195 struct frame
*frame
;
4197 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4199 if (frame
!= dpyinfo
->x_focus_frame
)
4201 /* Set this before calling other routines, so that they see
4202 the correct value of x_focus_frame. */
4203 dpyinfo
->x_focus_frame
= frame
;
4205 if (old_focus
&& old_focus
->auto_lower
)
4206 x_lower_frame (old_focus
);
4209 selected_frame
= frame
;
4210 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4212 Fselect_window (selected_frame
->selected_window
, Qnil
);
4213 choose_minibuf_frame ();
4216 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4217 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4219 pending_autoraise_frame
= 0;
4221 #if USE_MAC_FONT_PANEL
4223 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4227 x_frame_rehighlight (dpyinfo
);
4230 /* Handle FocusIn and FocusOut state changes for FRAME.
4231 If FRAME has focus and there exists more than one frame, puts
4232 a FOCUS_IN_EVENT into *BUFP. */
4235 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4237 struct mac_display_info
*dpyinfo
;
4238 struct frame
*frame
;
4239 struct input_event
*bufp
;
4241 if (type
== activeFlag
)
4243 if (dpyinfo
->x_focus_event_frame
!= frame
)
4245 x_new_focus_frame (dpyinfo
, frame
);
4246 dpyinfo
->x_focus_event_frame
= frame
;
4248 /* Don't stop displaying the initial startup message
4249 for a switch-frame event we don't need. */
4250 if (GC_NILP (Vterminal_frame
)
4251 && GC_CONSP (Vframe_list
)
4252 && !GC_NILP (XCDR (Vframe_list
)))
4254 bufp
->kind
= FOCUS_IN_EVENT
;
4255 XSETFRAME (bufp
->frame_or_window
, frame
);
4261 if (dpyinfo
->x_focus_event_frame
== frame
)
4263 dpyinfo
->x_focus_event_frame
= 0;
4264 x_new_focus_frame (dpyinfo
, 0);
4269 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4272 x_mouse_leave (dpyinfo
)
4273 struct x_display_info
*dpyinfo
;
4275 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4278 /* The focus has changed, or we have redirected a frame's focus to
4279 another frame (this happens when a frame uses a surrogate
4280 mini-buffer frame). Shift the highlight as appropriate.
4282 The FRAME argument doesn't necessarily have anything to do with which
4283 frame is being highlighted or un-highlighted; we only use it to find
4284 the appropriate X display info. */
4287 XTframe_rehighlight (frame
)
4288 struct frame
*frame
;
4290 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4294 x_frame_rehighlight (dpyinfo
)
4295 struct x_display_info
*dpyinfo
;
4297 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4299 if (dpyinfo
->x_focus_frame
)
4301 dpyinfo
->x_highlight_frame
4302 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4303 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4304 : dpyinfo
->x_focus_frame
);
4305 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4307 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4308 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4312 dpyinfo
->x_highlight_frame
= 0;
4314 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4317 frame_unhighlight (old_highlight
);
4318 if (dpyinfo
->x_highlight_frame
)
4319 frame_highlight (dpyinfo
->x_highlight_frame
);
4325 /* Convert a keysym to its name. */
4328 x_get_keysym_name (keysym
)
4335 value
= XKeysymToString (keysym
);
4346 /* Function to report a mouse movement to the mainstream Emacs code.
4347 The input handler calls this.
4349 We have received a mouse movement event, which is given in *event.
4350 If the mouse is over a different glyph than it was last time, tell
4351 the mainstream emacs code by setting mouse_moved. If not, ask for
4352 another motion event, so we can check again the next time it moves. */
4354 static Point last_mouse_motion_position
;
4355 static Lisp_Object last_mouse_motion_frame
;
4358 note_mouse_movement (frame
, pos
)
4362 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4365 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4366 last_mouse_motion_position
= *pos
;
4367 XSETFRAME (last_mouse_motion_frame
, frame
);
4369 if (frame
== dpyinfo
->mouse_face_mouse_frame
4370 && !PtInRect (*pos
, mac_get_frame_bounds (frame
, &r
)))
4372 /* This case corresponds to LeaveNotify in X11. If we move
4373 outside the frame, then we're certainly no longer on any text
4375 clear_mouse_face (dpyinfo
);
4376 dpyinfo
->mouse_face_mouse_frame
= 0;
4377 if (!dpyinfo
->grabbed
)
4378 rif
->define_frame_cursor (frame
,
4379 frame
->output_data
.mac
->nontext_cursor
);
4382 /* Has the mouse moved off the glyph it was on at the last sighting? */
4383 if (frame
!= last_mouse_glyph_frame
4384 || !PtInRect (*pos
, &last_mouse_glyph
))
4386 frame
->mouse_moved
= 1;
4387 last_mouse_scroll_bar
= Qnil
;
4388 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4389 /* Remember which glyph we're now on. */
4390 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4391 last_mouse_glyph_frame
= frame
;
4399 /************************************************************************
4401 ************************************************************************/
4403 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4406 redo_mouse_highlight ()
4408 if (!NILP (last_mouse_motion_frame
)
4409 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4410 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4411 last_mouse_motion_position
.h
,
4412 last_mouse_motion_position
.v
);
4417 mac_focus_frame (dpyinfo
)
4418 struct mac_display_info
*dpyinfo
;
4420 if (dpyinfo
->x_focus_frame
)
4421 return dpyinfo
->x_focus_frame
;
4423 /* Mac version may get events, such as a menu bar click, even when
4424 all the frames are invisible. In this case, we regard the
4425 event came to the selected frame. */
4426 return SELECTED_FRAME ();
4430 /* Return the current position of the mouse.
4431 *FP should be a frame which indicates which display to ask about.
4433 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4434 and *PART to the frame, window, and scroll bar part that the mouse
4435 is over. Set *X and *Y to the portion and whole of the mouse's
4436 position on the scroll bar.
4438 If the mouse movement started elsewhere, set *FP to the frame the
4439 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4442 Set *TIME to the server time-stamp for the time at which the mouse
4443 was at this position.
4445 Don't store anything if we don't have a valid set of values to report.
4447 This clears the mouse_moved flag, so we can wait for the next mouse
4451 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4454 Lisp_Object
*bar_window
;
4455 enum scroll_bar_part
*part
;
4457 unsigned long *time
;
4463 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4464 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4467 Lisp_Object frame
, tail
;
4469 /* Clear the mouse-moved flag for every frame on this display. */
4470 FOR_EACH_FRAME (tail
, frame
)
4471 XFRAME (frame
)->mouse_moved
= 0;
4473 last_mouse_scroll_bar
= Qnil
;
4475 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4476 && FRAME_LIVE_P (last_mouse_frame
))
4477 f1
= last_mouse_frame
;
4479 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4483 /* Ok, we found a frame. Store all the values.
4484 last_mouse_glyph is a rectangle used to reduce the
4485 generation of mouse events. To not miss any motion
4486 events, we must divide the frame into rectangles of the
4487 size of the smallest character that could be displayed
4488 on it, i.e. into the same rectangles that matrices on
4489 the frame are divided into. */
4492 mac_get_frame_mouse (f1
, &mouse_pos
);
4493 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4495 last_mouse_glyph_frame
= f1
;
4500 XSETINT (*x
, mouse_pos
.h
);
4501 XSETINT (*y
, mouse_pos
.v
);
4502 *time
= last_mouse_movement_time
;
4510 /************************************************************************
4511 Scroll bars, general
4512 ************************************************************************/
4514 /* Create a scroll bar and return the scroll bar vector for it. W is
4515 the Emacs window on which to create the scroll bar. TOP, LEFT,
4516 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4519 static struct scroll_bar
*
4520 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4522 int top
, left
, width
, height
, disp_top
, disp_height
;
4524 struct frame
*f
= XFRAME (w
->frame
);
4525 struct scroll_bar
*bar
4526 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4531 XSETWINDOW (bar
->window
, w
);
4532 XSETINT (bar
->top
, top
);
4533 XSETINT (bar
->left
, left
);
4534 XSETINT (bar
->width
, width
);
4535 XSETINT (bar
->height
, height
);
4537 bar
->fringe_extended_p
= Qnil
;
4539 bar
->redraw_needed_p
= Qnil
;
4541 SetRect (&r
, left
, disp_top
, left
+ width
, disp_top
+ disp_height
);
4542 mac_create_scroll_bar (bar
, &r
,
4543 #ifdef USE_TOOLKIT_SCROLL_BARS
4550 /* Add bar to its frame's list of scroll bars. */
4551 bar
->next
= FRAME_SCROLL_BARS (f
);
4553 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4554 if (!NILP (bar
->next
))
4555 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4562 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4566 x_scroll_bar_remove (bar
)
4567 struct scroll_bar
*bar
;
4571 /* Destroy the Mac scroll bar control */
4572 mac_dispose_scroll_bar (bar
);
4574 /* Disassociate this scroll bar from its window. */
4575 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4581 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4582 that we are displaying PORTION characters out of a total of WHOLE
4583 characters, starting at POSITION. If WINDOW has no scroll bar,
4587 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4589 int portion
, whole
, position
;
4591 struct frame
*f
= XFRAME (w
->frame
);
4592 struct scroll_bar
*bar
;
4593 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4594 int window_y
, window_height
;
4596 int fringe_extended_p
;
4599 /* Get window dimensions. */
4600 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4602 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4603 height
= window_height
;
4605 /* Compute the left edge of the scroll bar area. */
4606 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4608 /* Compute the width of the scroll bar which might be less than
4609 the width of the area reserved for the scroll bar. */
4610 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4611 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4615 /* Compute the left edge of the scroll bar. */
4616 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4617 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
4619 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
4621 /* Adjustments according to Inside Macintosh to make it look nice */
4623 disp_height
= height
;
4630 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4636 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4641 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
4642 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
4643 && WINDOW_LEFT_FRINGE_WIDTH (w
)
4644 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
4645 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
4647 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
4648 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
4649 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
4650 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
4653 /* Does the scroll bar exist yet? */
4654 if (NILP (w
->vertical_scroll_bar
))
4658 if (fringe_extended_p
)
4659 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
4662 mac_clear_area (f
, left
, top
, width
, height
);
4664 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4666 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4670 /* It may just need to be moved and resized. */
4671 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4675 /* If already correctly positioned, do nothing. */
4676 if (XINT (bar
->left
) == sb_left
4677 && XINT (bar
->top
) == top
4678 && XINT (bar
->width
) == sb_width
4679 && XINT (bar
->height
) == height
4681 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
4685 if (!NILP (bar
->redraw_needed_p
))
4686 mac_redraw_scroll_bar (bar
);
4692 /* Since toolkit scroll bars are smaller than the space reserved
4693 for them on the frame, we have to clear "under" them. */
4695 if (fringe_extended_p
)
4696 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
4699 mac_clear_area (f
, left
, top
, width
, height
);
4701 SetRect (&r
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
,
4702 sb_left
+ sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4703 disp_top
+ disp_height
);
4704 mac_set_scroll_bar_bounds (bar
, &r
);
4706 /* Remember new settings. */
4707 XSETINT (bar
->left
, sb_left
);
4708 XSETINT (bar
->top
, top
);
4709 XSETINT (bar
->width
, sb_width
);
4710 XSETINT (bar
->height
, height
);
4717 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
4719 bar
->redraw_needed_p
= Qnil
;
4721 #ifdef USE_TOOLKIT_SCROLL_BARS
4722 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4723 #else /* not USE_TOOLKIT_SCROLL_BARS */
4724 /* Set the scroll bar's current state, unless we're currently being
4726 if (NILP (bar
->dragging
))
4728 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4731 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4734 int start
= ((double) position
* top_range
) / whole
;
4735 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4736 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4739 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4743 /* The following three hooks are used when we're doing a thorough
4744 redisplay of the frame. We don't explicitly know which scroll bars
4745 are going to be deleted, because keeping track of when windows go
4746 away is a real pain - "Can you say set-window-configuration, boys
4747 and girls?" Instead, we just assert at the beginning of redisplay
4748 that *all* scroll bars are to be removed, and then save a scroll bar
4749 from the fiery pit when we actually redisplay its window. */
4751 /* Arrange for all scroll bars on FRAME to be removed at the next call
4752 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4753 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4756 XTcondemn_scroll_bars (frame
)
4759 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4760 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4763 bar
= FRAME_SCROLL_BARS (frame
);
4764 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4765 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4766 XSCROLL_BAR (bar
)->prev
= Qnil
;
4767 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4768 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4769 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4774 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4775 Note that WINDOW isn't necessarily condemned at all. */
4778 XTredeem_scroll_bar (window
)
4779 struct window
*window
;
4781 struct scroll_bar
*bar
;
4784 /* We can't redeem this window's scroll bar if it doesn't have one. */
4785 if (NILP (window
->vertical_scroll_bar
))
4788 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4790 /* Unlink it from the condemned list. */
4791 f
= XFRAME (WINDOW_FRAME (window
));
4792 if (NILP (bar
->prev
))
4794 /* If the prev pointer is nil, it must be the first in one of
4796 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4797 /* It's not condemned. Everything's fine. */
4799 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4800 window
->vertical_scroll_bar
))
4801 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4803 /* If its prev pointer is nil, it must be at the front of
4804 one or the other! */
4808 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4810 if (! NILP (bar
->next
))
4811 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4813 bar
->next
= FRAME_SCROLL_BARS (f
);
4815 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4816 if (! NILP (bar
->next
))
4817 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4820 /* Remove all scroll bars on FRAME that haven't been saved since the
4821 last call to `*condemn_scroll_bars_hook'. */
4824 XTjudge_scroll_bars (f
)
4827 Lisp_Object bar
, next
;
4829 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4831 /* Clear out the condemned list now so we won't try to process any
4832 more events on the hapless scroll bars. */
4833 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4835 for (; ! NILP (bar
); bar
= next
)
4837 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4839 x_scroll_bar_remove (b
);
4842 b
->next
= b
->prev
= Qnil
;
4845 /* Now there should be no references to the condemned scroll bars,
4846 and they should get garbage-collected. */
4849 /* The screen has been cleared so we may have changed foreground or
4850 background colors, and the scroll bars may need to be redrawn.
4851 Clear out the scroll bars, and ask for expose events, so we can
4855 x_scroll_bar_clear (f
)
4860 /* We can have scroll bars even if this is 0,
4861 if we just turned off scroll bar mode.
4862 But in that case we should not clear them. */
4863 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4864 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
4865 bar
= XSCROLL_BAR (bar
)->next
)
4866 XSCROLL_BAR (bar
)->redraw_needed_p
= Qt
;
4870 /***********************************************************************
4872 ***********************************************************************/
4875 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
4882 mac_get_window_bounds (f
, &inner
, &outer
);
4884 switch (win_gravity
)
4886 case NorthWestGravity
:
4888 case SouthWestGravity
:
4889 left
+= inner
.left
- outer
.left
;
4895 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
4898 case NorthEastGravity
:
4900 case SouthEastGravity
:
4901 left
+= inner
.right
- outer
.right
;
4905 switch (win_gravity
)
4907 case NorthWestGravity
:
4909 case NorthEastGravity
:
4910 top
+= inner
.top
- outer
.top
;
4916 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
4919 case SouthWestGravity
:
4921 case SouthEastGravity
:
4922 top
+= inner
.bottom
- outer
.bottom
;
4926 mac_move_window (FRAME_MAC_WINDOW (f
), left
, top
, false);
4930 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
4937 mac_get_window_bounds (f
, &inner
, &outer
);
4939 switch (win_gravity
)
4941 case NorthWestGravity
:
4943 case SouthWestGravity
:
4950 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
4951 - (inner
.right
- inner
.left
)) / 2;
4954 case NorthEastGravity
:
4956 case SouthEastGravity
:
4957 *left
= outer
.right
- (inner
.right
- inner
.left
);
4961 switch (win_gravity
)
4963 case NorthWestGravity
:
4965 case NorthEastGravity
:
4972 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
4973 - (inner
.bottom
- inner
.top
)) / 2;
4976 case SouthWestGravity
:
4978 case SouthEastGravity
:
4979 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
4985 mac_image_spec_to_cg_image (f
, image
)
4989 if (!valid_image_p (image
))
4993 int img_id
= lookup_image (f
, image
);
4994 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
4996 prepare_image_for_display (f
, img
);
4998 return img
->data
.ptr_val
;
5001 #endif /* USE_MAC_TOOLBAR */
5004 /***********************************************************************
5006 ***********************************************************************/
5008 /* Set clipping for output in glyph row ROW. W is the window in which
5009 we operate. GC is the graphics context to set clipping in.
5011 ROW may be a text row or, e.g., a mode line. Text rows must be
5012 clipped to the interior of the window dedicated to text display,
5013 mode lines must be clipped to the whole window. */
5016 x_clip_to_row (w
, row
, area
, gc
)
5018 struct glyph_row
*row
;
5022 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5024 int window_x
, window_y
, window_width
;
5026 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5028 clip_rect
.left
= window_x
;
5029 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5030 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5031 clip_rect
.right
= clip_rect
.left
+ window_width
;
5032 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5034 mac_set_clip_rectangles (f
, gc
, &clip_rect
, 1);
5038 /* Draw a hollow box cursor on window W in glyph row ROW. */
5041 x_draw_hollow_cursor (w
, row
)
5043 struct glyph_row
*row
;
5045 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5046 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5047 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5050 struct glyph
*cursor_glyph
;
5053 /* Get the glyph the cursor is on. If we can't tell because
5054 the current matrix is invalid or such, give up. */
5055 cursor_glyph
= get_phys_cursor_glyph (w
);
5056 if (cursor_glyph
== NULL
)
5059 /* Compute frame-relative coordinates for phys cursor. */
5060 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5061 wd
= w
->phys_cursor_width
;
5063 /* The foreground of cursor_gc is typically the same as the normal
5064 background color, which can cause the cursor box to be invisible. */
5065 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5066 if (dpyinfo
->scratch_cursor_gc
)
5067 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5069 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5070 GCForeground
, &xgcv
);
5071 gc
= dpyinfo
->scratch_cursor_gc
;
5073 /* Set clipping, draw the rectangle, and reset clipping again. */
5074 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5075 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5076 mac_reset_clip_rectangles (f
, gc
);
5080 /* Draw a bar cursor on window W in glyph row ROW.
5082 Implementation note: One would like to draw a bar cursor with an
5083 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5084 Unfortunately, I didn't find a font yet that has this property set.
5088 x_draw_bar_cursor (w
, row
, width
, kind
)
5090 struct glyph_row
*row
;
5092 enum text_cursor_kinds kind
;
5094 struct frame
*f
= XFRAME (w
->frame
);
5095 struct glyph
*cursor_glyph
;
5097 /* If cursor is out of bounds, don't draw garbage. This can happen
5098 in mini-buffer windows when switching between echo area glyphs
5100 cursor_glyph
= get_phys_cursor_glyph (w
);
5101 if (cursor_glyph
== NULL
)
5104 /* If on an image, draw like a normal cursor. That's usually better
5105 visible than drawing a bar, esp. if the image is large so that
5106 the bar might not be in the window. */
5107 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5109 struct glyph_row
*row
;
5110 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5111 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5115 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5116 Window window
= FRAME_MAC_WINDOW (f
);
5117 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5118 unsigned long mask
= GCForeground
| GCBackground
;
5119 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5122 /* If the glyph's background equals the color we normally draw
5123 the bar cursor in, the bar cursor in its normal color is
5124 invisible. Use the glyph's foreground color instead in this
5125 case, on the assumption that the glyph's colors are chosen so
5126 that the glyph is legible. */
5127 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5128 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5130 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5133 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5136 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5137 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5141 width
= FRAME_CURSOR_WIDTH (f
);
5142 width
= min (cursor_glyph
->pixel_width
, width
);
5144 w
->phys_cursor_width
= width
;
5145 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5147 if (kind
== BAR_CURSOR
)
5148 mac_fill_rectangle (f
, gc
,
5149 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5150 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5151 width
, row
->height
);
5153 mac_fill_rectangle (f
, gc
,
5154 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5155 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5156 row
->height
- width
),
5157 cursor_glyph
->pixel_width
,
5160 mac_reset_clip_rectangles (f
, gc
);
5165 /* RIF: Define cursor CURSOR on frame F. */
5168 mac_define_frame_cursor (f
, cursor
)
5172 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5174 if (dpyinfo
->x_focus_frame
== f
)
5175 SetThemeCursor (cursor
);
5179 /* RIF: Clear area on frame F. */
5182 mac_clear_frame_area (f
, x
, y
, width
, height
)
5184 int x
, y
, width
, height
;
5186 mac_clear_area (f
, x
, y
, width
, height
);
5190 /* RIF: Draw cursor on window W. */
5193 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5195 struct glyph_row
*glyph_row
;
5197 int cursor_type
, cursor_width
;
5202 w
->phys_cursor_type
= cursor_type
;
5203 w
->phys_cursor_on_p
= 1;
5205 if (glyph_row
->exact_window_width_line_p
5206 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5208 glyph_row
->cursor_in_fringe_p
= 1;
5209 draw_fringe_bitmap (w
, glyph_row
, 0);
5212 switch (cursor_type
)
5214 case HOLLOW_BOX_CURSOR
:
5215 x_draw_hollow_cursor (w
, glyph_row
);
5218 case FILLED_BOX_CURSOR
:
5219 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5223 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5227 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5231 w
->phys_cursor_width
= 0;
5243 #if 0 /* MAC_TODO: no icon support yet. */
5245 x_bitmap_icon (f
, icon
)
5251 if (FRAME_W32_WINDOW (f
) == 0)
5255 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5256 else if (STRINGP (icon
))
5257 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5258 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5259 else if (SYMBOLP (icon
))
5263 if (EQ (icon
, intern ("application")))
5264 name
= (LPCTSTR
) IDI_APPLICATION
;
5265 else if (EQ (icon
, intern ("hand")))
5266 name
= (LPCTSTR
) IDI_HAND
;
5267 else if (EQ (icon
, intern ("question")))
5268 name
= (LPCTSTR
) IDI_QUESTION
;
5269 else if (EQ (icon
, intern ("exclamation")))
5270 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5271 else if (EQ (icon
, intern ("asterisk")))
5272 name
= (LPCTSTR
) IDI_ASTERISK
;
5273 else if (EQ (icon
, intern ("winlogo")))
5274 name
= (LPCTSTR
) IDI_WINLOGO
;
5278 hicon
= LoadIcon (NULL
, name
);
5286 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5291 #endif /* MAC_TODO */
5293 /************************************************************************
5295 ************************************************************************/
5297 /* Display Error Handling functions not used on W32. Listing them here
5298 helps diff stay in step when comparing w32term.c with xterm.c.
5300 x_error_catcher (display, error)
5301 x_catch_errors (dpy)
5302 x_catch_errors_unwind (old_val)
5303 x_check_errors (dpy, format)
5304 x_had_errors_p (dpy)
5305 x_clear_errors (dpy)
5306 x_uncatch_errors (dpy, count)
5308 x_connection_signal (signalnum)
5309 x_connection_closed (dpy, error_message)
5310 x_error_quitter (display, error)
5311 x_error_handler (display, error)
5312 x_io_error_quitter (display)
5317 /* Changing the font of the frame. */
5319 /* Give frame F the font named FONTNAME as its default font, and
5320 return the full name of that font. FONTNAME may be a wildcard
5321 pattern; in that case, we choose some font that fits the pattern.
5322 The return value shows which font we chose. */
5325 x_new_font (f
, fontname
)
5327 register char *fontname
;
5329 struct font_info
*fontp
5330 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5335 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5336 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5337 FRAME_FONTSET (f
) = -1;
5339 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5340 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5341 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5343 compute_fringe_widths (f
, 1);
5345 /* Compute the scroll bar width in character columns. */
5346 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5348 int wid
= FRAME_COLUMN_WIDTH (f
);
5349 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5350 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5354 int wid
= FRAME_COLUMN_WIDTH (f
);
5355 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5358 /* Now make the frame display the given font. */
5359 if (FRAME_MAC_WINDOW (f
) != 0)
5361 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5363 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5365 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5368 /* Don't change the size of a tip frame; there's no point in
5369 doing it because it's done in Fx_show_tip, and it leads to
5370 problems because the tip frame has no widget. */
5371 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5372 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5375 return build_string (fontp
->full_name
);
5378 /* Give frame F the fontset named FONTSETNAME as its default font, and
5379 return the full name of that fontset. FONTSETNAME may be a wildcard
5380 pattern; in that case, we choose some fontset that fits the pattern.
5381 The return value shows which fontset we chose. */
5384 x_new_fontset (f
, fontsetname
)
5388 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5394 if (FRAME_FONTSET (f
) == fontset
)
5395 /* This fontset is already set in frame F. There's nothing more
5397 return fontset_name (fontset
);
5399 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5401 if (!STRINGP (result
))
5402 /* Can't load ASCII font. */
5405 /* Since x_new_font doesn't update any fontset information, do it now. */
5406 FRAME_FONTSET (f
) = fontset
;
5408 return build_string (fontsetname
);
5412 /***********************************************************************
5413 TODO: W32 Input Methods
5414 ***********************************************************************/
5415 /* Listing missing functions from xterm.c helps diff stay in step.
5417 xim_destroy_callback (xim, client_data, call_data)
5418 xim_open_dpy (dpyinfo, resource_name)
5420 xim_instantiate_callback (display, client_data, call_data)
5421 xim_initialize (dpyinfo, resource_name)
5422 xim_close_dpy (dpyinfo)
5428 mac_handle_origin_change (f
)
5431 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5435 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
5437 int pixelwidth
, pixelheight
;
5441 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
5442 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
5444 if (cols
!= FRAME_COLS (f
)
5445 || rows
!= FRAME_LINES (f
)
5446 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
5447 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
5449 /* We pass 1 for DELAY since we can't run Lisp code inside of
5451 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5452 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5453 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5455 /* If cursor was outside the new size, mark it as off. */
5456 mark_window_cursors_off (XWINDOW (f
->root_window
));
5458 /* Clear out any recollection of where the mouse highlighting
5459 was, since it might be in a place that's outside the new
5460 frame size. Actually checking whether it is outside is a
5461 pain in the neck, so don't try--just let the highlighting be
5462 done afresh with new size. */
5463 cancel_mouse_face (f
);
5465 #if TARGET_API_MAC_CARBON
5466 mac_reposition_hourglass (f
);
5472 /* Calculate the absolute position in frame F
5473 from its current recorded position values and gravity. */
5476 x_calc_absolute_position (f
)
5479 int flags
= f
->size_hint_flags
;
5482 /* We have nothing to do if the current position
5483 is already for the top-left corner. */
5484 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5487 /* Find the offsets of the outside upper-left corner of
5488 the inner window, with respect to the outer window. */
5490 mac_get_window_bounds (f
, &inner
, &outer
);
5493 /* Treat negative positions as relative to the leftmost bottommost
5494 position that fits on the screen. */
5495 if (flags
& XNegative
)
5496 f
->left_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->width
5497 - (outer
.right
- outer
.left
));
5499 if (flags
& YNegative
)
5500 f
->top_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->height
5501 - (outer
.bottom
- outer
.top
));
5503 /* The left_pos and top_pos
5504 are now relative to the top and left screen edges,
5505 so the flags should correspond. */
5506 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5509 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5510 to really change the position, and 0 when calling from
5511 x_make_frame_visible (in that case, XOFF and YOFF are the current
5512 position values). It is -1 when calling from x_set_frame_parameters,
5513 which means, do adjust for borders but don't change the gravity. */
5516 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5518 register int xoff
, yoff
;
5521 if (change_gravity
> 0)
5525 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5527 f
->size_hint_flags
|= XNegative
;
5529 f
->size_hint_flags
|= YNegative
;
5530 f
->win_gravity
= NorthWestGravity
;
5532 x_calc_absolute_position (f
);
5535 x_wm_set_size_hint (f
, (long) 0, 0);
5537 #if TARGET_API_MAC_CARBON
5538 mac_move_window_structure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5539 /* If the title bar is completely outside the screen, adjust the
5541 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5542 kWindowConstrainMoveRegardlessOfFit
5543 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5544 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
5545 mac_handle_origin_change (f
);
5548 Rect inner
, outer
, screen_rect
, dummy
;
5549 RgnHandle region
= NewRgn ();
5551 mac_get_window_bounds (f
, &inner
, &outer
);
5552 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5553 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5554 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5555 f
->top_pos
+ f
->y_pixels_diff
, false);
5557 /* If the title bar is completely outside the screen, adjust the
5558 position. The variable `outer' holds the title bar rectangle.
5559 The variable `inner' holds slightly smaller one than `outer',
5560 so that the calculation of overlapping may not become too
5562 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5563 outer
= (*region
)->rgnBBox
;
5564 DisposeRgn (region
);
5566 InsetRect (&inner
, 8, 8);
5567 screen_rect
= qd
.screenBits
.bounds
;
5568 screen_rect
.top
+= GetMBarHeight ();
5570 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5572 if (inner
.right
<= screen_rect
.left
)
5573 f
->left_pos
= screen_rect
.left
;
5574 else if (inner
.left
>= screen_rect
.right
)
5575 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5577 if (inner
.bottom
<= screen_rect
.top
)
5578 f
->top_pos
= screen_rect
.top
;
5579 else if (inner
.top
>= screen_rect
.bottom
)
5580 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5582 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5583 f
->top_pos
+ f
->y_pixels_diff
, false);
5591 /* Call this to change the size of frame F's x-window.
5592 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5593 for this size change and subsequent size changes.
5594 Otherwise we leave the window gravity unchanged. */
5597 x_set_window_size (f
, change_gravity
, cols
, rows
)
5602 int pixelwidth
, pixelheight
;
5606 check_frame_size (f
, &rows
, &cols
);
5607 f
->scroll_bar_actual_width
5608 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5610 compute_fringe_widths (f
, 0);
5612 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5613 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5615 f
->win_gravity
= NorthWestGravity
;
5616 x_wm_set_size_hint (f
, (long) 0, 0);
5618 mac_size_window (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5620 #if TARGET_API_MAC_CARBON
5621 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
5623 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
5625 if (f
->output_data
.mac
->internal_border_width
5626 != FRAME_INTERNAL_BORDER_WIDTH (f
))
5628 mac_clear_window (f
);
5629 f
->output_data
.mac
->internal_border_width
5630 = FRAME_INTERNAL_BORDER_WIDTH (f
);
5633 SET_FRAME_GARBAGED (f
);
5638 /* Mouse warping. */
5640 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5643 x_set_mouse_position (f
, x
, y
)
5649 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5650 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5652 if (pix_x
< 0) pix_x
= 0;
5653 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5655 if (pix_y
< 0) pix_y
= 0;
5656 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5658 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5662 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5668 mac_convert_frame_point_to_global (f
, &pix_x
, &pix_y
);
5669 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
5672 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
5675 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5676 0, 0, 0, 0, pix_x
, pix_y
);
5682 /* focus shifting, raising and lowering. */
5685 x_focus_on_frame (f
)
5688 #if 0 /* This proves to be unpleasant. */
5692 /* I don't think that the ICCCM allows programs to do things like this
5693 without the interaction of the window manager. Whatever you end up
5694 doing with this code, do it to x_unfocus_frame too. */
5695 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5696 RevertToPointerRoot
, CurrentTime
);
5706 /* Raise frame F. */
5712 if (f
->async_visible
)
5715 mac_bring_window_to_front (FRAME_MAC_WINDOW (f
));
5720 /* Lower frame F. */
5726 if (f
->async_visible
)
5729 mac_send_window_behind (FRAME_MAC_WINDOW (f
), NULL
);
5735 XTframe_raise_lower (f
, raise_flag
)
5745 /* Change of visibility. */
5748 mac_handle_visibility_change (f
)
5751 Window wp
= FRAME_MAC_WINDOW (f
);
5752 int visible
= 0, iconified
= 0;
5753 struct input_event buf
;
5755 if (mac_is_window_visible (wp
))
5757 if (mac_is_window_collapsed (wp
))
5763 if (!f
->async_visible
&& visible
)
5767 /* wait_reading_process_output will notice this and update
5768 the frame's display structures. If we were made
5769 invisible, we should not set garbaged, because that stops
5770 redrawing on Update events. */
5771 SET_FRAME_GARBAGED (f
);
5774 buf
.kind
= DEICONIFY_EVENT
;
5775 XSETFRAME (buf
.frame_or_window
, f
);
5777 kbd_buffer_store_event (&buf
);
5779 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
5780 /* Force a redisplay sooner or later to update the
5781 frame titles in case this is the second frame. */
5782 record_asynch_buffer_change ();
5784 else if (f
->async_visible
&& !visible
)
5788 buf
.kind
= ICONIFY_EVENT
;
5789 XSETFRAME (buf
.frame_or_window
, f
);
5791 kbd_buffer_store_event (&buf
);
5794 f
->async_visible
= visible
;
5795 f
->async_iconified
= iconified
;
5798 /* This tries to wait until the frame is really visible.
5799 However, if the window manager asks the user where to position
5800 the frame, this will return before the user finishes doing that.
5801 The frame will not actually be visible at that time,
5802 but it will become visible later when the window manager
5803 finishes with it. */
5806 x_make_frame_visible (f
)
5811 if (! FRAME_VISIBLE_P (f
))
5813 /* We test FRAME_GARBAGED_P here to make sure we don't
5814 call x_set_offset a second time
5815 if we get to x_make_frame_visible a second time
5816 before the window gets really visible. */
5817 if (! FRAME_ICONIFIED_P (f
)
5818 && ! f
->output_data
.mac
->asked_for_visible
)
5819 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5821 f
->output_data
.mac
->asked_for_visible
= 1;
5823 mac_collapse_window (FRAME_MAC_WINDOW (f
), false);
5824 mac_show_window (FRAME_MAC_WINDOW (f
));
5827 XFlush (FRAME_MAC_DISPLAY (f
));
5829 /* Synchronize to ensure Emacs knows the frame is visible
5830 before we do anything else. We do this loop with input not blocked
5831 so that incoming events are handled. */
5836 /* This must come after we set COUNT. */
5839 XSETFRAME (frame
, f
);
5841 /* Wait until the frame is visible. Process X events until a
5842 MapNotify event has been seen, or until we think we won't get a
5843 MapNotify at all.. */
5844 for (count
= input_signal_count
+ 10;
5845 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5847 /* Force processing of queued events. */
5850 /* Machines that do polling rather than SIGIO have been
5851 observed to go into a busy-wait here. So we'll fake an
5852 alarm signal to let the handler know that there's something
5853 to be read. We used to raise a real alarm, but it seems
5854 that the handler isn't always enabled here. This is
5856 if (input_polling_used ())
5858 /* It could be confusing if a real alarm arrives while
5859 processing the fake one. Turn it off and let the
5860 handler reset it. */
5861 extern void poll_for_input_1
P_ ((void));
5862 int old_poll_suppress_count
= poll_suppress_count
;
5863 poll_suppress_count
= 1;
5864 poll_for_input_1 ();
5865 poll_suppress_count
= old_poll_suppress_count
;
5868 /* See if a MapNotify event has been processed. */
5869 FRAME_SAMPLE_VISIBILITY (f
);
5874 /* Change from mapped state to withdrawn state. */
5876 /* Make the frame visible (mapped and not iconified). */
5879 x_make_frame_invisible (f
)
5882 /* A deactivate event does not occur when the last visible frame is
5883 made invisible. So if we clear the highlight here, it will not
5884 be rehighlighted when it is made visible. */
5886 /* Don't keep the highlight on an invisible frame. */
5887 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5888 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5893 #if !TARGET_API_MAC_CARBON
5894 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5895 that the current position of the window is user-specified, rather than
5896 program-specified, so that when the window is mapped again, it will be
5897 placed at the same location, without forcing the user to position it
5898 by hand again (they have already done that once for this window.) */
5899 x_wm_set_size_hint (f
, (long) 0, 1);
5902 mac_hide_window (FRAME_MAC_WINDOW (f
));
5906 #if !TARGET_API_MAC_CARBON
5907 mac_handle_visibility_change (f
);
5911 /* Change window state from mapped to iconified. */
5919 /* A deactivate event does not occur when the last visible frame is
5920 iconified. So if we clear the highlight here, it will not be
5921 rehighlighted when it is deiconified. */
5923 /* Don't keep the highlight on an invisible frame. */
5924 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5925 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5928 if (f
->async_iconified
)
5933 FRAME_SAMPLE_VISIBILITY (f
);
5935 if (! FRAME_VISIBLE_P (f
))
5936 mac_show_window (FRAME_MAC_WINDOW (f
));
5938 err
= mac_collapse_window (FRAME_MAC_WINDOW (f
), true);
5943 error ("Can't notify window manager of iconification");
5945 #if !TARGET_API_MAC_CARBON
5946 mac_handle_visibility_change (f
);
5951 /* Free X resources of frame F. */
5954 x_free_frame_resources (f
)
5957 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5958 Window wp
= FRAME_MAC_WINDOW (f
);
5962 /* AppKit version of mac_dispose_frame_window, which is implemented
5963 as -[NSWindow close], will change the focus to the next window
5964 during its call. So, unlike other platforms, we clean up the
5965 focus-related variables before calling mac_dispose_frame_window. */
5966 if (f
== dpyinfo
->x_focus_frame
)
5968 dpyinfo
->x_focus_frame
= 0;
5969 #if USE_MAC_FONT_PANEL
5970 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
5973 if (f
== dpyinfo
->x_focus_event_frame
)
5974 dpyinfo
->x_focus_event_frame
= 0;
5975 if (f
== dpyinfo
->x_highlight_frame
)
5976 dpyinfo
->x_highlight_frame
= 0;
5978 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5980 dpyinfo
->mouse_face_beg_row
5981 = dpyinfo
->mouse_face_beg_col
= -1;
5982 dpyinfo
->mouse_face_end_row
5983 = dpyinfo
->mouse_face_end_col
= -1;
5984 dpyinfo
->mouse_face_window
= Qnil
;
5985 dpyinfo
->mouse_face_deferred_gc
= 0;
5986 dpyinfo
->mouse_face_mouse_frame
= 0;
5989 mac_dispose_frame_window (f
);
5990 if (wp
== tip_window
)
5991 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5992 closed' event. So we reset tip_window here. */
5995 free_frame_menubar (f
);
5997 if (FRAME_FACE_CACHE (f
))
5998 free_frame_faces (f
);
6002 if (FRAME_SIZE_HINTS (f
))
6003 xfree (FRAME_SIZE_HINTS (f
));
6005 xfree (f
->output_data
.mac
);
6006 f
->output_data
.mac
= NULL
;
6012 /* Destroy the X window of frame F. */
6015 x_destroy_window (f
)
6018 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6020 x_free_frame_resources (f
);
6022 dpyinfo
->reference_count
--;
6026 /* Setting window manager hints. */
6028 /* Set the normal size hints for the window manager, for frame F.
6029 FLAGS is the flags word to use--or 0 meaning preserve the flags
6030 that the window now has.
6031 If USER_POSITION is nonzero, we set the USPosition
6032 flag (this is useful when FLAGS is 0). */
6034 x_wm_set_size_hint (f
, flags
, user_position
)
6039 int base_width
, base_height
, width_inc
, height_inc
;
6040 int min_rows
= 0, min_cols
= 0;
6041 XSizeHints
*size_hints
;
6043 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6044 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6045 width_inc
= FRAME_COLUMN_WIDTH (f
);
6046 height_inc
= FRAME_LINE_HEIGHT (f
);
6048 check_frame_size (f
, &min_rows
, &min_cols
);
6050 size_hints
= FRAME_SIZE_HINTS (f
);
6051 if (size_hints
== NULL
)
6053 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6054 bzero (size_hints
, sizeof (XSizeHints
));
6057 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6058 size_hints
->width_inc
= width_inc
;
6059 size_hints
->height_inc
= height_inc
;
6060 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6061 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6062 size_hints
->base_width
= base_width
;
6063 size_hints
->base_height
= base_height
;
6066 size_hints
->flags
= flags
;
6067 else if (user_position
)
6069 size_hints
->flags
&= ~ PPosition
;
6070 size_hints
->flags
|= USPosition
;
6074 #if 0 /* MAC_TODO: hide application instead of iconify? */
6075 /* Used for IconicState or NormalState */
6078 x_wm_set_window_state (f
, state
)
6082 #ifdef USE_X_TOOLKIT
6085 XtSetArg (al
[0], XtNinitialState
, state
);
6086 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6087 #else /* not USE_X_TOOLKIT */
6088 Window window
= FRAME_X_WINDOW (f
);
6090 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6091 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6093 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6094 #endif /* not USE_X_TOOLKIT */
6098 x_wm_set_icon_pixmap (f
, pixmap_id
)
6104 #ifndef USE_X_TOOLKIT
6105 Window window
= FRAME_X_WINDOW (f
);
6110 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6111 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6115 /* It seems there is no way to turn off use of an icon pixmap.
6116 The following line does it, only if no icon has yet been created,
6117 for some window managers. But with mwm it crashes.
6118 Some people say it should clear the IconPixmapHint bit in this case,
6119 but that doesn't work, and the X consortium said it isn't the
6120 right thing at all. Since there is no way to win,
6121 best to explicitly give up. */
6123 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6129 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6133 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6134 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6137 #else /* not USE_X_TOOLKIT */
6139 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6140 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6142 #endif /* not USE_X_TOOLKIT */
6145 #endif /* MAC_TODO */
6148 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6152 #if 0 /* MAC_TODO: no icons on Mac */
6153 #ifdef USE_X_TOOLKIT
6154 Window window
= XtWindow (f
->output_data
.x
->widget
);
6156 Window window
= FRAME_X_WINDOW (f
);
6159 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6160 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6161 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6163 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6164 #endif /* MAC_TODO */
6168 /***********************************************************************
6170 ***********************************************************************/
6172 /* An XLFD pattern is divided into blocks delimited by '*'. This
6173 structure holds information for each block. */
6174 struct xlfdpat_block
6176 /* Length of the pattern string in this block. Non-zero except for
6177 the first and the last blocks. */
6180 /* Pattern string except the last character in this block. The last
6181 character is replaced with NUL in order to use it as a
6183 unsigned char *pattern
;
6185 /* Last character of the pattern string. Must not be '?'. */
6186 unsigned char last_char
;
6188 /* One of the tables for the Boyer-Moore string search. It
6189 specifies the number of positions to proceed for each character
6190 with which the match fails. */
6193 /* The skip value for the last character in the above `skip' is
6194 assigned to `infinity' in order to simplify a loop condition.
6195 The original value is saved here. */
6201 /* Normalized pattern string. "Normalized" means that capital
6202 letters are lowered, blocks are not empty except the first and
6203 the last ones, and trailing '?'s in a block that is not the last
6204 one are moved to the next one. The last character in each block
6205 is replaced with NUL. */
6208 /* Number of characters except '*'s and trailing '?'s in the
6209 normalized pattern string. */
6212 /* Number of trailing '?'s in the normalized pattern string. */
6213 int trailing_anychars
;
6215 /* Number of blocks and information for each block. The latter is
6216 NULL if the pattern is exact (no '*' or '?' in it). */
6218 struct xlfdpat_block
*blocks
;
6222 xlfdpat_destroy (pat
)
6223 struct xlfdpat
*pat
;
6230 xfree (pat
->blocks
);
6237 static struct xlfdpat
*
6238 xlfdpat_create (pattern
)
6239 const char *pattern
;
6241 struct xlfdpat
*pat
;
6242 int nblocks
, i
, skip
;
6243 unsigned char last_char
, *p
, *q
, *anychar_head
;
6244 const unsigned char *ptr
;
6245 struct xlfdpat_block
*blk
;
6247 pat
= xmalloc (sizeof (struct xlfdpat
));
6248 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6250 /* Normalize the pattern string and store it to `pat->buf'. */
6252 anychar_head
= NULL
;
6255 for (ptr
= pattern
; *ptr
; ptr
++)
6257 unsigned char c
= *ptr
;
6260 if (last_char
== '*')
6261 /* ...a** -> ...a* */
6265 if (last_char
== '?')
6267 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6268 /* ...*??* -> ...*?? */
6271 /* ...a??* -> ...a*?? */
6273 *anychar_head
++ = '*';
6281 if (last_char
!= '?')
6285 /* On Mac OS X 10.3, tolower also converts non-ASCII
6286 characters for some locales. */
6290 *q
++ = last_char
= c
;
6294 pat
->nblocks
= nblocks
;
6295 if (last_char
!= '?')
6296 pat
->trailing_anychars
= 0;
6299 pat
->trailing_anychars
= q
- anychar_head
;
6302 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6304 if (anychar_head
== NULL
&& nblocks
== 1)
6306 /* The pattern is exact. */
6311 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6313 /* Divide the normalized pattern into blocks. */
6315 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6320 blk
->len
= p
- blk
->pattern
;
6324 blk
->len
= q
- blk
->pattern
;
6326 /* Setup a table for the Boyer-Moore string search. */
6327 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6330 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6331 blk
->pattern
[blk
->len
- 1] = '\0';
6333 for (skip
= 1; skip
< blk
->len
; skip
++)
6334 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6337 for (i
= 0; i
< 256; i
++)
6338 blk
->skip
[i
] = skip
;
6340 p
= blk
->pattern
+ (blk
->len
- skip
);
6342 blk
->skip
[*p
++] = skip
;
6344 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6351 xlfdpat_exact_p (pat
)
6352 struct xlfdpat
*pat
;
6354 return pat
->blocks
== NULL
;
6357 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6358 that the pattern in *BLK matches with its prefix. Return NULL
6359 there is no such strings. STRING must be lowered in advance. */
6362 xlfdpat_block_match_1 (blk
, string
, start_max
)
6363 struct xlfdpat_block
*blk
;
6364 const unsigned char *string
;
6367 int start
, infinity
;
6369 const unsigned char *s
;
6371 xassert (blk
->len
> 0);
6372 xassert (start_max
+ blk
->len
<= strlen (string
));
6373 xassert (blk
->last_char
!= '?');
6375 /* See the comments in the function `boyer_moore' (search.c) for the
6376 use of `infinity'. */
6377 infinity
= start_max
+ blk
->len
+ 1;
6378 blk
->skip
[blk
->last_char
] = infinity
;
6383 /* Check the last character of the pattern. */
6384 s
= string
+ blk
->len
- 1;
6387 start
+= blk
->skip
[*(s
+ start
)];
6389 while (start
<= start_max
);
6391 if (start
< infinity
)
6392 /* Couldn't find the last character. */
6395 /* No less than `infinity' means we could find the last
6396 character at `s[start - infinity]'. */
6399 /* Check the remaining characters. We prefer making no-'?'
6400 cases faster because the use of '?' is really rare. */
6405 while (*p
++ == *s
++)
6408 while (*(p
- 1) == '?');
6410 if (*(p
- 1) == '\0')
6412 return string
+ start
;
6415 start
+= blk
->last_char_skip
;
6417 while (start
<= start_max
);
6422 #define xlfdpat_block_match(b, s, m) \
6423 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6424 : xlfdpat_block_match_1 (b, s, m))
6426 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
6427 matches with STRING. STRING must be lowered in advance. */
6430 xlfdpat_match (pat
, string
)
6431 struct xlfdpat
*pat
;
6432 const unsigned char *string
;
6434 int str_len
, nblocks
, i
, start_max
;
6435 struct xlfdpat_block
*blk
;
6436 const unsigned char *s
;
6438 xassert (pat
->nblocks
> 0);
6440 if (xlfdpat_exact_p (pat
))
6441 return strcmp (pat
->buf
, string
) == 0;
6443 /* The number of the characters in the string must not be smaller
6444 than that in the pattern. */
6445 str_len
= strlen (string
);
6446 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6449 /* Chop off the trailing '?'s. */
6450 str_len
-= pat
->trailing_anychars
;
6452 /* The last block. When it is non-empty, it must match at the end
6454 nblocks
= pat
->nblocks
;
6455 blk
= pat
->blocks
+ (nblocks
- 1);
6457 /* The last block is also the first one. */
6458 return (str_len
== blk
->len
6459 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6460 else if (blk
->len
!= 0)
6461 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6464 /* The first block. When it is non-empty, it must match at the
6465 beginning of the string. */
6469 s
= xlfdpat_block_match (blk
, string
, 0);
6472 string
= s
+ blk
->len
;
6475 /* The rest of the blocks. */
6476 start_max
= str_len
- pat
->nchars
;
6477 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6479 s
= xlfdpat_block_match (blk
, string
, start_max
);
6482 start_max
-= s
- string
;
6483 string
= s
+ blk
->len
;
6490 /***********************************************************************
6492 ***********************************************************************/
6494 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6497 x_get_font_info (f
, font_idx
)
6501 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6504 /* the global font name table */
6505 static char **font_name_table
= NULL
;
6506 static int font_name_table_size
= 0;
6507 static int font_name_count
= 0;
6509 /* Alist linking font family names to Font Manager font family
6510 references (which can also be used as QuickDraw font IDs). We use
6511 an alist because hash tables are not ready when the terminal frame
6512 for Mac OS Classic is created. */
6513 static Lisp_Object fm_font_family_alist
;
6515 /* Hash table linking font family names to ATSU font IDs. */
6516 static Lisp_Object atsu_font_id_hash
;
6517 /* Alist linking Font Manager style to face attributes. */
6518 static Lisp_Object fm_style_face_attributes_alist
;
6519 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
6521 #if USE_MAC_FONT_PANEL
6522 Lisp_Object Qpanel_closed
, Qselection
;
6525 /* Alist linking character set strings to Mac text encoding and Emacs
6527 static Lisp_Object Vmac_charset_info_alist
;
6530 create_text_encoding_info_alist ()
6532 Lisp_Object result
= Qnil
, rest
;
6534 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6536 Lisp_Object charset_info
= XCAR (rest
);
6537 Lisp_Object charset
, coding_system
, text_encoding
;
6538 Lisp_Object existing_info
;
6540 if (!(CONSP (charset_info
)
6541 && (charset
= XCAR (charset_info
),
6543 && CONSP (XCDR (charset_info
))
6544 && (text_encoding
= XCAR (XCDR (charset_info
)),
6545 INTEGERP (text_encoding
))
6546 && CONSP (XCDR (XCDR (charset_info
)))
6547 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
6548 SYMBOLP (coding_system
))))
6551 existing_info
= assq_no_quit (text_encoding
, result
);
6552 if (NILP (existing_info
))
6553 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6556 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6557 XSETCDR (XCDR (existing_info
),
6558 Fcons (charset
, XCDR (XCDR (existing_info
))));
6566 decode_mac_font_name (name
, size
, coding_system
)
6569 Lisp_Object coding_system
;
6571 struct coding_system coding
;
6574 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6576 for (p
= name
; *p
; p
++)
6577 if (!isascii (*p
) || iscntrl (*p
))
6582 setup_coding_system (coding_system
, &coding
);
6583 coding
.src_multibyte
= 0;
6584 coding
.dst_multibyte
= 1;
6585 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6586 coding
.composing
= COMPOSITION_DISABLED
;
6587 buf
= (char *) alloca (size
);
6589 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6590 bcopy (buf
, name
, coding
.produced
);
6591 name
[coding
.produced
] = '\0';
6595 /* If there's just one occurrence of '-' in the family name, it is
6596 replaced with '_'. (More than one occurrence of '-' means a
6597 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6598 p
= strchr (name
, '-');
6599 if (p
&& strchr (p
+ 1, '-') == NULL
)
6602 for (p
= name
; *p
; p
++)
6603 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6604 for some locales. */
6611 mac_to_x_fontname (name
, size
, style
, charset
)
6619 char xf
[256], *result
;
6622 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6626 strcpy(foundry
, "Apple");
6627 strcpy(family
, name
);
6630 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6631 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6632 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
6634 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6635 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6636 for (p
= result
; *p
; p
++)
6637 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6638 for some locales. */
6645 /* Parse fully-specified and instantiated X11 font spec XF, and store
6646 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6647 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6648 caller must allocate at least 256 and 32 bytes respectively. For
6649 ordinary Mac fonts, the value stored to FAMILY should just be their
6650 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6651 intlfonts collection contain their charset designation in their
6652 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6653 types of font names are handled accordingly. */
6655 const int kDefaultFontSize
= 12;
6658 parse_x_font_name (xf
, family
, size
, style
, charset
)
6665 Str31 foundry
, weight
;
6666 int point_size
, avgwidth
;
6669 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6670 foundry
, family
, weight
, slant
, size
,
6671 &point_size
, &avgwidth
, charset
) != 8
6672 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6673 foundry
, family
, weight
, slant
, size
,
6674 &point_size
, &avgwidth
, charset
) != 8)
6680 *size
= point_size
/ 10;
6681 else if (avgwidth
> 0)
6682 *size
= avgwidth
/ 10;
6685 *size
= kDefaultFontSize
;
6688 if (strcmp (weight
, "bold") == 0)
6693 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
6695 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
6697 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
6699 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6700 but take overlap into account. */
6701 memmove (family
+ foundry_len
+ 1, family
, family_len
);
6702 memcpy (family
, foundry
, foundry_len
);
6703 family
[foundry_len
] = '-';
6704 family
[foundry_len
+ 1 + family_len
] = '-';
6705 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
6711 for (p
= family
; *p
; p
++)
6712 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6713 for some locales. */
6722 add_font_name_table_entry (char *font_name
)
6724 if (font_name_table_size
== 0)
6726 font_name_table_size
= 256;
6727 font_name_table
= (char **)
6728 xmalloc (font_name_table_size
* sizeof (char *));
6730 else if (font_name_count
+ 1 >= font_name_table_size
)
6732 font_name_table_size
*= 2;
6733 font_name_table
= (char **)
6734 xrealloc (font_name_table
,
6735 font_name_table_size
* sizeof (char *));
6738 font_name_table
[font_name_count
++] = font_name
;
6742 add_mac_font_name (name
, size
, style
, charset
)
6746 const char *charset
;
6749 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
6752 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
6753 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
6754 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
6755 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
6762 fm_get_style_from_font (font
)
6766 FMFontStyle style
= normal
;
6769 FMFontFamily font_family
;
6770 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
6772 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
6773 some font (e.g., Optima) even if it is `bold'. */
6774 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
6775 sizeof (mac_style
), &mac_style
, &len
);
6777 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
6778 style
= EndianU16_BtoN (mac_style
);
6780 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
6786 atsu_find_font_from_family_name (family
)
6789 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
6792 Lisp_Object rest
, best
;
6793 FMFontStyle min_style
, style
;
6795 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
6798 return kATSUInvalidFontID
;
6800 rest
= HASH_VALUE (h
, i
);
6801 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
6802 return cons_to_long (rest
);
6804 rest
= Fnreverse (rest
);
6808 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
6811 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
6812 if (style
< min_style
)
6815 if (style
== normal
)
6822 while (!NILP (rest
));
6824 HASH_VALUE (h
, i
) = best
;
6825 return cons_to_long (best
);
6829 fm_style_to_face_attributes (fm_style
)
6830 FMFontStyle fm_style
;
6834 fm_style
&= (bold
| italic
);
6835 tem
= assq_no_quit (make_number (fm_style
),
6836 fm_style_face_attributes_alist
);
6840 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
6841 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
6842 fm_style_face_attributes_alist
=
6843 Fcons (Fcons (make_number (fm_style
), tem
),
6844 fm_style_face_attributes_alist
);
6850 atsu_find_font_family_name (font_id
)
6855 Lisp_Object family
= Qnil
;
6857 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
6858 kFontMacintoshPlatform
, kFontNoScript
,
6859 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
6862 family
= make_uninit_string (len
);
6863 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
6864 kFontMacintoshPlatform
, kFontNoScript
,
6865 kFontNoLanguage
, len
, SDATA (family
),
6869 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
6875 mac_atsu_font_face_attributes (font_id
)
6878 Lisp_Object family
, style_attrs
;
6880 family
= atsu_find_font_family_name (font_id
);
6883 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
6884 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
6888 /* Sets up the table font_name_table to contain the list of all fonts
6889 in the system the first time the table is used so that the Resource
6890 Manager need not be accessed every time this information is
6894 init_font_name_table ()
6896 #if TARGET_API_MAC_CARBON
6897 FMFontFamilyIterator ffi
;
6898 FMFontFamilyInstanceIterator ffii
;
6900 Lisp_Object text_encoding_info_alist
;
6901 struct gcpro gcpro1
;
6903 text_encoding_info_alist
= create_text_encoding_info_alist ();
6906 #if USE_CG_TEXT_DRAWING
6907 init_cg_text_anti_aliasing_threshold ();
6909 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
6910 text_encoding_info_alist
)))
6913 struct Lisp_Hash_Table
*h
;
6915 ItemCount nfonts
, i
;
6916 ATSUFontID
*font_ids
= NULL
;
6917 Lisp_Object prev_family
= Qnil
;
6921 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
6922 make_float (DEFAULT_REHASH_SIZE
),
6923 make_float (DEFAULT_REHASH_THRESHOLD
),
6925 h
= XHASH_TABLE (atsu_font_id_hash
);
6927 err
= ATSUFontCount (&nfonts
);
6930 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
6931 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
6934 for (i
= 0; i
< nfonts
; i
++)
6938 family
= atsu_find_font_family_name (font_ids
[i
]);
6939 if (NILP (family
) || SREF (family
, 0) == '.')
6941 if (!NILP (Fequal (prev_family
, family
)))
6942 family
= prev_family
;
6944 j
= hash_lookup (h
, family
, &hash_code
);
6947 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
6948 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
6951 else if (EQ (prev_family
, family
))
6952 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
6954 prev_family
= family
;
6961 /* Create a dummy instance iterator here to avoid creating and
6962 destroying it in the loop. */
6963 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6965 /* Create an iterator to enumerate the font families. */
6966 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6969 FMDisposeFontFamilyInstanceIterator (&ffii
);
6973 GCPRO1 (text_encoding_info_alist
);
6975 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6981 TextEncoding encoding
;
6982 TextEncodingBase sc
;
6983 Lisp_Object text_encoding_info
, family
;
6985 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6991 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6993 sc
= GetTextEncodingBase (encoding
);
6994 text_encoding_info
= assq_no_quit (make_number (sc
),
6995 text_encoding_info_alist
);
6996 if (NILP (text_encoding_info
))
6997 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
6998 text_encoding_info_alist
);
6999 decode_mac_font_name (name
, sizeof (name
),
7000 XCAR (XCDR (text_encoding_info
)));
7001 family
= build_string (name
);
7002 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7004 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7005 fm_font_family_alist
);
7007 /* Point the instance iterator at the current font family. */
7008 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7011 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7014 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7016 if (size
> 0 || style
== normal
)
7017 for (; !NILP (rest
); rest
= XCDR (rest
))
7018 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7024 /* Dispose of the iterators. */
7025 FMDisposeFontFamilyIterator (&ffi
);
7026 FMDisposeFontFamilyInstanceIterator (&ffii
);
7027 #else /* !TARGET_API_MAC_CARBON */
7029 SInt16 fontnum
, old_fontnum
;
7030 int num_mac_fonts
= CountResources('FOND');
7032 Handle font_handle
, font_handle_2
;
7033 short id
, scriptcode
;
7036 struct FontAssoc
*fat
;
7037 struct AsscEntry
*assc_entry
;
7038 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7039 struct gcpro gcpro1
;
7041 GetPort (&port
); /* save the current font number used */
7042 old_fontnum
= port
->txFont
;
7044 text_encoding_info_alist
= create_text_encoding_info_alist ();
7046 GCPRO1 (text_encoding_info_alist
);
7048 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7050 font_handle
= GetIndResource ('FOND', i
);
7054 GetResInfo (font_handle
, &id
, &type
, name
);
7055 GetFNum (name
, &fontnum
);
7057 if (fontnum
== 0 || *name
== '.')
7061 scriptcode
= FontToScript (fontnum
);
7062 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7063 text_encoding_info_alist
);
7064 if (NILP (text_encoding_info
))
7065 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7066 text_encoding_info_alist
);
7067 decode_mac_font_name (name
, sizeof (name
),
7068 XCAR (XCDR (text_encoding_info
)));
7069 family
= build_string (name
);
7070 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7072 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7073 fm_font_family_alist
);
7076 HLock (font_handle
);
7078 if (GetResourceSizeOnDisk (font_handle
)
7079 >= sizeof (struct FamRec
))
7081 fat
= (struct FontAssoc
*) (*font_handle
7082 + sizeof (struct FamRec
));
7084 = (struct AsscEntry
*) (*font_handle
7085 + sizeof (struct FamRec
)
7086 + sizeof (struct FontAssoc
));
7088 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7090 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7092 for (; !NILP (rest
); rest
= XCDR (rest
))
7093 add_mac_font_name (name
, assc_entry
->fontSize
,
7094 assc_entry
->fontStyle
,
7095 SDATA (XCAR (rest
)));
7099 HUnlock (font_handle
);
7100 font_handle_2
= GetNextFOND (font_handle
);
7101 ReleaseResource (font_handle
);
7102 font_handle
= font_handle_2
;
7104 while (ResError () == noErr
&& font_handle
);
7109 TextFont (old_fontnum
);
7110 #endif /* !TARGET_API_MAC_CARBON */
7115 mac_clear_font_name_table ()
7119 for (i
= 0; i
< font_name_count
; i
++)
7120 xfree (font_name_table
[i
]);
7121 xfree (font_name_table
);
7122 font_name_table
= NULL
;
7123 font_name_table_size
= font_name_count
= 0;
7124 fm_font_family_alist
= Qnil
;
7128 enum xlfd_scalable_field_index
7130 XLFD_SCL_PIXEL_SIZE
,
7131 XLFD_SCL_POINT_SIZE
,
7136 static const int xlfd_scalable_fields
[] =
7145 mac_do_list_fonts (pattern
, maxnames
)
7146 const char *pattern
;
7150 Lisp_Object font_list
= Qnil
;
7151 struct xlfdpat
*pat
;
7154 int scl_val
[XLFD_SCL_LAST
], *val
;
7158 if (font_name_table
== NULL
) /* Initialize when first used. */
7159 init_font_name_table ();
7161 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7164 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7165 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7166 fonts are scaled according to the specified size. */
7169 field
= xlfd_scalable_fields
;
7177 if ('0' <= *ptr
&& *ptr
<= '9')
7179 *val
= *ptr
++ - '0';
7180 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7181 *val
= *val
* 10 + *ptr
++ - '0';
7188 ptr
= strchr (ptr
, '-');
7191 while (ptr
&& i
< 14);
7193 if (i
== 14 && ptr
== NULL
)
7195 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7196 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7197 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7198 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7200 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7201 scl_val
[XLFD_SCL_POINT_SIZE
] =
7202 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7203 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7205 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7206 scl_val
[XLFD_SCL_AVGWIDTH
] =
7207 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7208 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7212 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7214 pat
= xlfdpat_create (pattern
);
7218 exact
= xlfdpat_exact_p (pat
);
7220 for (i
= 0; i
< font_name_count
; i
++)
7222 if (xlfdpat_match (pat
, font_name_table
[i
]))
7224 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7225 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7228 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7229 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7231 int former_len
= ptr
- font_name_table
[i
];
7233 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7234 memcpy (scaled
, font_name_table
[i
], former_len
);
7235 sprintf (scaled
+ former_len
,
7236 "-%d-%d-72-72-m-%d-%s",
7237 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7238 scl_val
[XLFD_SCL_POINT_SIZE
],
7239 scl_val
[XLFD_SCL_AVGWIDTH
],
7240 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7242 if (xlfdpat_match (pat
, scaled
))
7244 font_list
= Fcons (build_string (scaled
), font_list
);
7246 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7254 xlfdpat_destroy (pat
);
7259 /* Return a list of names of available fonts matching PATTERN on frame F.
7261 Frame F null means we have not yet created any frame on Mac, and
7262 consult the first display in x_display_list. MAXNAMES sets a limit
7263 on how many fonts to match. */
7266 x_list_fonts (f
, pattern
, size
, maxnames
)
7268 Lisp_Object pattern
;
7271 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7272 struct mac_display_info
*dpyinfo
7273 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7275 xassert (size
<= 0);
7277 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7278 if (NILP (patterns
))
7279 patterns
= Fcons (pattern
, Qnil
);
7281 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7283 pattern
= XCAR (patterns
);
7285 if (!STRINGP (pattern
))
7288 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7289 key
= Fcons (pattern
, make_number (maxnames
));
7291 list
= Fassoc (key
, tem
);
7294 list
= Fcdr_safe (list
);
7295 /* We have a cashed list. Don't have to get the list again. */
7300 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7303 /* MAC_TODO: add code for matching outline fonts here */
7305 /* Now store the result in the cache. */
7306 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7307 Fcons (Fcons (key
, list
),
7308 XCAR (XCDR (dpyinfo
->name_list_element
))));
7311 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7320 /* Check that FONT is valid on frame F. It is if it can be found in F's
7324 x_check_font (f
, font
)
7329 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7331 xassert (font
!= NULL
);
7333 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7334 if (dpyinfo
->font_table
[i
].name
7335 && font
== dpyinfo
->font_table
[i
].font
)
7338 xassert (i
< dpyinfo
->n_fonts
);
7341 #endif /* GLYPH_DEBUG != 0 */
7343 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7344 Note: There are (broken) X fonts out there with invalid XFontStruct
7345 min_bounds contents. For example, handa@etl.go.jp reports that
7346 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7347 have font->min_bounds.width == 0. */
7350 x_font_min_bounds (font
, w
, h
)
7351 MacFontStruct
*font
;
7354 *h
= FONT_HEIGHT (font
);
7355 *w
= font
->min_bounds
.width
;
7359 /* Compute the smallest character width and smallest font height over
7360 all fonts available on frame F. Set the members smallest_char_width
7361 and smallest_font_height in F's x_display_info structure to
7362 the values computed. Value is non-zero if smallest_font_height or
7363 smallest_char_width become smaller than they were before. */
7366 x_compute_min_glyph_bounds (f
)
7370 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7371 MacFontStruct
*font
;
7372 int old_width
= dpyinfo
->smallest_char_width
;
7373 int old_height
= dpyinfo
->smallest_font_height
;
7375 dpyinfo
->smallest_font_height
= 100000;
7376 dpyinfo
->smallest_char_width
= 100000;
7378 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7379 if (dpyinfo
->font_table
[i
].name
)
7381 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7384 font
= (MacFontStruct
*) fontp
->font
;
7385 xassert (font
!= (MacFontStruct
*) ~0);
7386 x_font_min_bounds (font
, &w
, &h
);
7388 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7389 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7392 xassert (dpyinfo
->smallest_char_width
> 0
7393 && dpyinfo
->smallest_font_height
> 0);
7395 return (dpyinfo
->n_fonts
== 1
7396 || dpyinfo
->smallest_char_width
< old_width
7397 || dpyinfo
->smallest_font_height
< old_height
);
7401 /* Determine whether given string is a fully-specified XLFD: all 14
7402 fields are present, none is '*'. */
7405 is_fully_specified_xlfd (p
)
7414 for (i
= 0; i
< 13; i
++)
7416 q
= strchr (p
+ 1, '-');
7419 if (q
- p
== 2 && *(p
+ 1) == '*')
7424 if (strchr (p
+ 1, '-') != NULL
)
7427 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7434 /* mac_load_query_font creates and returns an internal representation
7435 for a font in a MacFontStruct struct. There is really no concept
7436 corresponding to "loading" a font on the Mac. But we check its
7437 existence and find the font number and all other information for it
7438 and store them in the returned MacFontStruct. */
7440 static MacFontStruct
*
7441 mac_load_query_font (f
, fontname
)
7451 static ATSUFontID font_id
;
7452 ATSUStyle mac_style
= NULL
;
7455 #if TARGET_API_MAC_CARBON
7456 TextEncoding encoding
;
7461 MacFontStruct
*font
;
7462 XCharStruct
*space_bounds
= NULL
, *pcm
;
7464 if (is_fully_specified_xlfd (fontname
))
7468 Lisp_Object matched_fonts
;
7470 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7471 if (NILP (matched_fonts
))
7473 name
= SDATA (XCAR (matched_fonts
));
7476 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7480 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7483 static const ATSUAttributeTag tags
[] =
7484 {kATSUFontTag
, kATSUSizeTag
,
7485 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7486 static const ByteCount sizes
[] =
7487 {sizeof (ATSUFontID
), sizeof (Fixed
),
7488 sizeof (Boolean
), sizeof (Boolean
)};
7489 static Fixed size_fixed
;
7490 static Boolean bold_p
, italic_p
;
7491 static const ATSUAttributeValuePtr values
[] =
7492 {&font_id
, &size_fixed
,
7493 &bold_p
, &italic_p
};
7494 static const ATSUFontFeatureType types
[] =
7495 {kAllTypographicFeaturesType
, kDiacriticsType
};
7496 static const ATSUFontFeatureSelector selectors
[] =
7497 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
7500 font_id
= atsu_find_font_from_family_name (family
);
7501 if (font_id
== kATSUInvalidFontID
)
7503 size_fixed
= Long2Fix (size
);
7504 bold_p
= (fontface
& bold
) != 0;
7505 italic_p
= (fontface
& italic
) != 0;
7506 err
= ATSUCreateStyle (&mac_style
);
7509 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7513 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7514 tags
, sizes
, values
);
7517 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
7520 scriptcode
= kTextEncodingMacUnicode
;
7525 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7529 fontnum
= XINT (XCDR (tmp
));
7530 #if TARGET_API_MAC_CARBON
7531 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7533 scriptcode
= GetTextEncodingBase (encoding
);
7535 scriptcode
= FontToScript (fontnum
);
7539 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7541 font
->mac_fontnum
= fontnum
;
7542 font
->mac_fontsize
= size
;
7543 font
->mac_fontface
= fontface
;
7544 font
->mac_scriptcode
= scriptcode
;
7546 font
->mac_style
= mac_style
;
7547 #if USE_CG_TEXT_DRAWING
7548 font
->cg_font
= NULL
;
7549 font
->cg_glyphs
= NULL
;
7553 /* Apple Japanese (SJIS) font is listed as both
7554 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7555 (Roman script) in init_font_name_table (). The latter should be
7556 treated as a one-byte font. */
7557 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7558 font
->mac_scriptcode
= smRoman
;
7560 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7563 if (font
->mac_style
)
7568 font
->min_byte1
= 0;
7569 font
->max_byte1
= 0xff;
7570 font
->min_char_or_byte2
= 0;
7571 font
->max_char_or_byte2
= 0xff;
7573 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
7574 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
7575 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
7576 pcm_init (font
->bounds
.rows
[0], 0x100);
7578 #if USE_CG_TEXT_DRAWING
7582 ATSFontRef ats_font
;
7584 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
7586 /* Use CG text drawing if italic/bold is not synthesized. */
7587 if (err
== noErr
&& style
== fontface
)
7589 ats_font
= FMGetATSFontRefFromFont (font_id
);
7590 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7596 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7597 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7600 space_bounds
= font
->bounds
.rows
[0] + 0x20;
7601 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7602 &font
->ascent
, &font
->descent
,
7604 #if USE_CG_TEXT_DRAWING
7605 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7612 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
7614 mac_unload_font (&one_mac_display_info
, font
);
7618 pcm
= font
->bounds
.rows
[0];
7619 for (c
= 0x21; c
<= 0xff; c
++)
7622 /* Soft hyphen is not supported in ATSUI. */
7626 #if USE_CG_TEXT_DRAWING
7627 if (font
->cg_glyphs
)
7637 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
7638 pcm
? pcm
+ c
: NULL
,
7639 #if USE_CG_TEXT_DRAWING
7640 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7647 #if USE_CG_TEXT_DRAWING
7648 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7650 /* Don't use CG text drawing if font substitution occurs in
7651 ASCII or Latin-1 characters. */
7652 CGFontRelease (font
->cg_font
);
7653 font
->cg_font
= NULL
;
7654 xfree (font
->cg_glyphs
);
7655 font
->cg_glyphs
= NULL
;
7666 FontInfo the_fontinfo
;
7667 int is_two_byte_font
;
7669 mac_begin_clip (f
, NULL
);
7673 TextFace (fontface
);
7675 GetFontInfo (&the_fontinfo
);
7677 font
->ascent
= the_fontinfo
.ascent
;
7678 font
->descent
= the_fontinfo
.descent
;
7680 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7681 || font
->mac_scriptcode
== smTradChinese
7682 || font
->mac_scriptcode
== smSimpChinese
7683 || font
->mac_scriptcode
== smKorean
);
7685 if (is_two_byte_font
)
7689 font
->min_byte1
= 0xa1;
7690 font
->max_byte1
= 0xfe;
7691 font
->min_char_or_byte2
= 0xa1;
7692 font
->max_char_or_byte2
= 0xfe;
7694 /* Use the width of an "ideographic space" of that font
7695 because the_fontinfo.widMax returns the wrong width for
7697 switch (font
->mac_scriptcode
)
7700 font
->min_byte1
= 0x81;
7701 font
->max_byte1
= 0xfc;
7702 font
->min_char_or_byte2
= 0x40;
7703 font
->max_char_or_byte2
= 0xfc;
7704 char_width
= StringWidth("\p\x81\x40");
7707 font
->min_char_or_byte2
= 0x40;
7708 char_width
= StringWidth("\p\xa1\x40");
7711 char_width
= StringWidth("\p\xa1\xa1");
7714 char_width
= StringWidth("\p\xa1\xa1");
7718 font
->bounds
.per_char
= NULL
;
7720 if (fontface
& italic
)
7721 font
->max_bounds
.rbearing
= char_width
+ 1;
7723 font
->max_bounds
.rbearing
= char_width
;
7724 font
->max_bounds
.lbearing
= 0;
7725 font
->max_bounds
.width
= char_width
;
7726 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7727 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7729 font
->min_bounds
= font
->max_bounds
;
7735 font
->min_byte1
= font
->max_byte1
= 0;
7736 font
->min_char_or_byte2
= 0x20;
7737 font
->max_char_or_byte2
= 0xff;
7739 font
->bounds
.per_char
=
7740 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7741 bzero (font
->bounds
.per_char
,
7742 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7744 space_bounds
= font
->bounds
.per_char
;
7745 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
7746 &font
->descent
, space_bounds
, NULL
);
7747 if (err
!= noErr
|| space_bounds
->width
<= 0)
7749 mac_unload_font (&one_mac_display_info
, font
);
7753 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
7754 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
7757 mac_end_clip (f
, NULL
);
7764 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
7765 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
7768 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
7770 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
7772 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
7774 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
7776 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
7779 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
7781 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
7783 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
7785 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
7787 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
7792 font
->mac_style
== NULL
&&
7794 font
->max_bounds
.width
== font
->min_bounds
.width
7795 && font
->min_bounds
.lbearing
>= 0
7796 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
7798 /* Fixed width and no overhangs. */
7799 xfree (font
->bounds
.per_char
);
7800 font
->bounds
.per_char
= NULL
;
7804 #if !defined (MAC_OS8) || USE_ATSUI
7805 /* AppKit and WebKit do some adjustment to the heights of Courier,
7806 Helvetica, and Times. This only works on the environments where
7807 srcCopy text transfer mode is never used. */
7809 #ifdef MAC_OS8 /* implies USE_ATSUI */
7812 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
7813 || strcmp (family
, "times") == 0))
7814 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
7822 mac_unload_font (dpyinfo
, font
)
7823 struct mac_display_info
*dpyinfo
;
7826 xfree (font
->full_name
);
7828 if (font
->mac_style
)
7832 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
7833 if (font
->bounds
.rows
[i
])
7834 xfree (font
->bounds
.rows
[i
]);
7835 xfree (font
->bounds
.rows
);
7836 ATSUDisposeStyle (font
->mac_style
);
7840 if (font
->bounds
.per_char
)
7841 xfree (font
->bounds
.per_char
);
7842 #if USE_CG_TEXT_DRAWING
7844 CGFontRelease (font
->cg_font
);
7845 if (font
->cg_glyphs
)
7846 xfree (font
->cg_glyphs
);
7852 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7853 pointer to the structure font_info while allocating it dynamically.
7854 If SIZE is 0, load any size of font.
7855 If loading is failed, return NULL. */
7858 x_load_font (f
, fontname
, size
)
7860 register char *fontname
;
7863 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7864 Lisp_Object font_names
;
7866 /* Get a list of all the fonts that match this name. Once we
7867 have a list of matching fonts, we compare them against the fonts
7868 we already have by comparing names. */
7869 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7871 if (!NILP (font_names
))
7876 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7877 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7878 if (dpyinfo
->font_table
[i
].name
7879 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7880 SDATA (XCAR (tail
)))
7881 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7882 SDATA (XCAR (tail
)))))
7883 return (dpyinfo
->font_table
+ i
);
7888 /* Load the font and add it to the table. */
7890 struct MacFontStruct
*font
;
7891 struct font_info
*fontp
;
7894 fontname
= (char *) SDATA (XCAR (font_names
));
7897 font
= mac_load_query_font (f
, fontname
);
7902 /* Find a free slot in the font table. */
7903 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7904 if (dpyinfo
->font_table
[i
].name
== NULL
)
7907 /* If no free slot found, maybe enlarge the font table. */
7908 if (i
== dpyinfo
->n_fonts
7909 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7912 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7913 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7915 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7918 fontp
= dpyinfo
->font_table
+ i
;
7919 if (i
== dpyinfo
->n_fonts
)
7922 /* Now fill in the slots of *FONTP. */
7924 bzero (fontp
, sizeof (*fontp
));
7926 fontp
->font_idx
= i
;
7927 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7928 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7930 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7932 /* Fixed width font. */
7933 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7940 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7941 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7943 fontp
->space_width
= pcm
->width
;
7945 fontp
->space_width
= FONT_WIDTH (font
);
7949 int width
= pcm
->width
;
7950 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7951 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7952 width
+= pcm
->width
;
7953 fontp
->average_width
= width
/ 95;
7956 fontp
->average_width
= FONT_WIDTH (font
);
7959 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
7960 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
7962 fontp
->size
= font
->max_bounds
.width
;
7963 fontp
->height
= FONT_HEIGHT (font
);
7965 /* For some font, ascent and descent in max_bounds field is
7966 larger than the above value. */
7967 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
7968 if (max_height
> fontp
->height
)
7969 fontp
->height
= max_height
;
7972 /* The slot `encoding' specifies how to map a character
7973 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7974 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7975 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7976 2:0xA020..0xFF7F). For the moment, we don't know which charset
7977 uses this font. So, we set information in fontp->encoding[1]
7978 which is never used by any charset. If mapping can't be
7979 decided, set FONT_ENCODING_NOT_DECIDED. */
7980 if (font
->mac_scriptcode
== smJapanese
)
7981 fontp
->encoding
[1] = 4;
7985 = (font
->max_byte1
== 0
7987 ? (font
->min_char_or_byte2
< 0x80
7988 ? (font
->max_char_or_byte2
< 0x80
7989 ? 0 /* 0x20..0x7F */
7990 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
7991 : 1) /* 0xA0..0xFF */
7993 : (font
->min_byte1
< 0x80
7994 ? (font
->max_byte1
< 0x80
7995 ? (font
->min_char_or_byte2
< 0x80
7996 ? (font
->max_char_or_byte2
< 0x80
7997 ? 0 /* 0x2020..0x7F7F */
7998 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
7999 : 3) /* 0x20A0..0x7FFF */
8000 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8001 : (font
->min_char_or_byte2
< 0x80
8002 ? (font
->max_char_or_byte2
< 0x80
8003 ? 2 /* 0xA020..0xFF7F */
8004 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8005 : 1))); /* 0xA0A0..0xFFFF */
8008 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8009 fontp
->baseline_offset
8010 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8011 ? (long) value
: 0);
8012 fontp
->relative_compose
8013 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8014 ? (long) value
: 0);
8015 fontp
->default_ascent
8016 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8017 ? (long) value
: 0);
8019 fontp
->baseline_offset
= 0;
8020 fontp
->relative_compose
= 0;
8021 fontp
->default_ascent
= 0;
8024 /* Set global flag fonts_changed_p to non-zero if the font loaded
8025 has a character with a smaller width than any other character
8026 before, or if the font loaded has a smaller height than any
8027 other font loaded before. If this happens, it will make a
8028 glyph matrix reallocation necessary. */
8029 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8036 /* Return a pointer to struct font_info of a font named FONTNAME for
8037 frame F. If no such font is loaded, return NULL. */
8040 x_query_font (f
, fontname
)
8042 register char *fontname
;
8044 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8047 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8048 if (dpyinfo
->font_table
[i
].name
8049 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
8050 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8051 return (dpyinfo
->font_table
+ i
);
8056 /* Find a CCL program for a font specified by FONTP, and set the member
8057 `encoder' of the structure. */
8060 x_find_ccl_program (fontp
)
8061 struct font_info
*fontp
;
8063 Lisp_Object list
, elt
;
8065 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8069 && STRINGP (XCAR (elt
))
8070 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8076 struct ccl_program
*ccl
8077 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8079 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8082 fontp
->font_encoder
= ccl
;
8087 /* The Mac Event loop code */
8089 #if !TARGET_API_MAC_CARBON
8091 #include <Quickdraw.h>
8092 #include <Balloons.h>
8093 #include <Devices.h>
8095 #include <Gestalt.h>
8097 #include <Processes.h>
8099 #include <ToolUtils.h>
8100 #include <TextUtils.h>
8101 #include <Dialogs.h>
8104 #include <Resources.h>
8109 #endif /* ! TARGET_API_MAC_CARBON */
8111 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8112 Lisp_Object Qreverse
;
8115 /* Modifier associated with the control key, or nil to ignore. */
8116 Lisp_Object Vmac_control_modifier
;
8118 /* Modifier associated with the option key, or nil to ignore. */
8119 Lisp_Object Vmac_option_modifier
;
8121 /* Modifier associated with the command key, or nil to ignore. */
8122 Lisp_Object Vmac_command_modifier
;
8124 /* Modifier associated with the function key, or nil to ignore. */
8125 Lisp_Object Vmac_function_modifier
;
8127 /* True if the option and command modifiers should be used to emulate
8128 a three button mouse */
8129 Lisp_Object Vmac_emulate_three_button_mouse
;
8131 #if TARGET_API_MAC_CARBON
8132 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8133 mouse-2, instead of mouse-3. */
8134 int mac_wheel_button_is_mouse_2
;
8136 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8137 for processing before Emacs sees it. */
8138 int mac_pass_command_to_system
;
8140 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8141 for processing before Emacs sees it. */
8142 int mac_pass_control_to_system
;
8145 /* Whether or not the screen configuration has changed. */
8146 int mac_screen_config_changed
= 0;
8149 #if TARGET_API_MAC_CARBON
8150 Lisp_Object Qhi_command
;
8152 Lisp_Object Qtoolbar_switch_mode
;
8155 Lisp_Object Qtext_input
;
8156 Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8157 Lisp_Object Vmac_ts_active_input_overlay
, Vmac_ts_active_input_buf
;
8158 static Lisp_Object Vmac_ts_script_language_on_focus
;
8159 static Lisp_Object saved_ts_script_language_on_focus
;
8160 static ScriptLanguageRecord saved_ts_language
;
8161 static Component saved_ts_component
;
8164 Lisp_Object Qservice
, Qpaste
, Qperform
;
8165 Lisp_Object Qmouse_drag_overlay
;
8167 #endif /* TARGET_API_MAC_CARBON */
8168 extern Lisp_Object Qundefined
;
8169 extern int XTread_socket
P_ ((int, int, struct input_event
*));
8170 extern void init_apple_event_handler
P_ ((void));
8171 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8172 Lisp_Object
*, Lisp_Object
*,
8174 extern OSErr init_coercion_handler
P_ ((void));
8176 /* Table for translating Mac keycode to X keysym values. Contributed
8178 Mapping for special keys is now identical to that in Apple X11
8179 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8180 on the right of the Cmd key on laptops, and fn + `enter' (->
8182 const unsigned char keycode_to_xkeysym_table
[] = {
8183 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8184 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8185 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8187 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8188 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8189 /*0x38*/ 0, 0, 0, 0,
8190 /*0x3C*/ 0, 0, 0, 0,
8192 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8193 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8194 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8195 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8197 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8198 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8199 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8200 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8202 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8203 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8204 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8205 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8207 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8208 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8209 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8210 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8214 /* Table for translating Mac keycode with the laptop `fn' key to that
8215 without it. Destination symbols in comments are keys on US
8216 keyboard, and they may not be the same on other types of keyboards.
8217 If the destination is identical to the source, it doesn't map `fn'
8218 key to a modifier. */
8219 static const unsigned char fn_keycode_to_keycode_table
[] = {
8220 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8221 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8222 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8224 /*0x30*/ 0, 0, 0, 0,
8225 /*0x34*/ 0, 0, 0, 0,
8226 /*0x38*/ 0, 0, 0, 0,
8227 /*0x3C*/ 0, 0, 0, 0,
8229 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8230 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8231 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8232 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8234 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8235 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8236 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8237 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8239 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8240 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8241 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
8242 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8244 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
8245 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8246 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
8247 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
8249 #endif /* MAC_OSX */
8252 #if TARGET_API_MAC_CARBON
8253 mac_to_emacs_modifiers (UInt32 mods
, UInt32 unmapped_mods
)
8255 mac_to_emacs_modifiers (EventModifiers mods
, EventModifiers unmapped_mods
)
8258 unsigned int result
= 0;
8259 if ((mods
| unmapped_mods
) & shiftKey
)
8260 result
|= shift_modifier
;
8262 /* Deactivated to simplify configuration:
8263 if Vmac_option_modifier is non-NIL, we fully process the Option
8264 key. Otherwise, we only process it if an additional Ctrl or Command
8265 is pressed. That way the system may convert the character to a
8267 if ((mods & optionKey) &&
8268 (( !NILP(Vmac_option_modifier) ||
8269 ((mods & cmdKey) || (mods & controlKey))))) */
8271 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8272 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8274 result
|= XUINT(val
);
8276 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8277 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8279 result
|= XUINT(val
);
8281 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8282 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8284 result
|= XUINT(val
);
8288 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8289 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8291 result
|= XUINT(val
);
8299 mac_mapped_modifiers (modifiers
, key_code
)
8300 UInt32 modifiers
, key_code
;
8302 UInt32 mapped_modifiers_all
=
8303 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
8304 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
8305 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
8308 mapped_modifiers_all
|=
8309 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
8311 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
8312 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
8313 no longer means laptop's `fn' key is down for the following keys:
8314 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
8315 Down, the arrow keys, and Clear. We ignore the corresponding bit
8316 if that key can be entered without the `fn' key on laptops. */
8317 if (modifiers
& kEventKeyModifierFnMask
8319 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
8320 modifiers
&= ~kEventKeyModifierFnMask
;
8323 return mapped_modifiers_all
& modifiers
;
8327 mac_get_emulated_btn ( UInt32 modifiers
)
8330 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8331 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8332 if (modifiers
& cmdKey
)
8333 result
= cmdIs3
? 2 : 1;
8334 else if (modifiers
& optionKey
)
8335 result
= cmdIs3
? 1 : 2;
8342 mac_get_selected_range (w
, range
)
8346 Lisp_Object overlay
= find_symbol_value (Qmouse_drag_overlay
);
8347 struct buffer
*b
= XBUFFER (w
->buffer
);
8348 int begv
= BUF_BEGV (b
), zv
= BUF_ZV (b
);
8351 if (OVERLAYP (overlay
)
8352 && EQ (Foverlay_buffer (overlay
), w
->buffer
)
8353 && (start
= XINT (Foverlay_start (overlay
)),
8354 end
= XINT (Foverlay_end (overlay
)),
8359 if (w
== XWINDOW (selected_window
) && b
== current_buffer
)
8362 start
= marker_position (w
->pointm
);
8364 if (NILP (Vtransient_mark_mode
) || NILP (b
->mark_active
))
8368 int mark_pos
= marker_position (b
->mark
);
8370 if (start
<= mark_pos
)
8384 else if (start
> zv
)
8393 range
->location
= start
- begv
;
8394 range
->length
= end
- start
;
8397 /* Store the text of the buffer BUF from START to END as Unicode
8398 characters in CHARACTERS. Return non-zero if successful. */
8401 mac_store_buffer_text_to_unicode_chars (buf
, start
, end
, characters
)
8404 UniChar
*characters
;
8406 int start_byte
, end_byte
, char_count
, byte_count
;
8407 struct coding_system coding
;
8408 unsigned char *dst
= (unsigned char *) characters
;
8410 start_byte
= buf_charpos_to_bytepos (buf
, start
);
8411 end_byte
= buf_charpos_to_bytepos (buf
, end
);
8412 char_count
= end
- start
;
8413 byte_count
= end_byte
- start_byte
;
8415 if (setup_coding_system (
8416 #ifdef WORDS_BIG_ENDIAN
8424 coding
.src_multibyte
= !NILP (buf
->enable_multibyte_characters
);
8425 coding
.dst_multibyte
= 0;
8426 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
8427 coding
.composing
= COMPOSITION_DISABLED
;
8429 if (BUF_GPT_BYTE (buf
) <= start_byte
|| end_byte
<= BUF_GPT_BYTE (buf
))
8430 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
8431 byte_count
, char_count
* sizeof (UniChar
));
8434 int first_byte_count
= BUF_GPT_BYTE (buf
) - start_byte
;
8436 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
8437 first_byte_count
, char_count
* sizeof (UniChar
));
8438 if (coding
.result
== CODING_FINISH_NORMAL
)
8439 encode_coding (&coding
,
8440 BUF_BYTE_ADDRESS (buf
, start_byte
+ first_byte_count
),
8441 dst
+ coding
.produced
,
8442 byte_count
- first_byte_count
,
8443 char_count
* sizeof (UniChar
) - coding
.produced
);
8446 if (coding
.result
!= CODING_FINISH_NORMAL
)
8453 mac_ax_selected_text_range (f
, range
)
8457 mac_get_selected_range (XWINDOW (f
->selected_window
), range
);
8460 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8462 mac_ax_number_of_characters (f
)
8465 struct buffer
*b
= XBUFFER (XWINDOW (f
->selected_window
)->buffer
);
8467 return BUF_ZV (b
) - BUF_BEGV (b
);
8474 mac_restore_keyboard_input_source ()
8476 OSStatus err
= noErr
;
8477 ScriptLanguageRecord slrec
, *slptr
= NULL
;
8479 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
8480 && EQ (saved_ts_script_language_on_focus
, Qt
))
8481 slptr
= &saved_ts_language
;
8482 else if (CONSP (Vmac_ts_script_language_on_focus
)
8483 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
8484 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
8485 && CONSP (saved_ts_script_language_on_focus
)
8486 && EQ (XCAR (saved_ts_script_language_on_focus
),
8487 XCAR (Vmac_ts_script_language_on_focus
))
8488 && EQ (XCDR (saved_ts_script_language_on_focus
),
8489 XCDR (Vmac_ts_script_language_on_focus
)))
8491 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
8492 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
8498 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8499 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
8500 kKeyboardInputMethodClass
);
8502 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
8505 err
= SetTextServiceLanguage (slptr
);
8507 /* Seems to be needed on Mac OS X 10.2. */
8509 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
8516 mac_save_keyboard_input_source ()
8519 ScriptLanguageRecord slrec
, *slptr
= NULL
;
8521 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
8523 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
8525 err
= GetTextServiceLanguage (&saved_ts_language
);
8527 slptr
= &saved_ts_language
;
8529 else if (CONSP (Vmac_ts_script_language_on_focus
)
8530 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
8531 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
8533 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
8534 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
8540 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8541 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
8542 kKeyboardInputMethodClass
);
8544 GetDefaultInputMethod (&saved_ts_component
, slptr
);
8550 #if TARGET_API_MAC_CARBON
8551 /***** Code to handle C-g testing *****/
8552 extern int quit_char
;
8553 extern int make_ctrl_char
P_ ((int));
8556 mac_quit_char_key_p (modifiers
, key_code
)
8557 UInt32 modifiers
, key_code
;
8559 UInt32 char_code
, mapped_modifiers
;
8560 unsigned long some_state
= 0;
8561 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
8562 int c
, emacs_modifiers
;
8564 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
8565 mapped_modifiers
= mac_mapped_modifiers (modifiers
, key_code
);
8566 key_code
|= (modifiers
& ~mapped_modifiers
);
8567 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
8568 if (char_code
& ~0xff)
8571 emacs_modifiers
= mac_to_emacs_modifiers (mapped_modifiers
, modifiers
);
8572 if (emacs_modifiers
& ctrl_modifier
)
8573 c
= make_ctrl_char (char_code
);
8575 c
|= (emacs_modifiers
8576 & (meta_modifier
| alt_modifier
8577 | hyper_modifier
| super_modifier
));
8579 return c
== quit_char
;
8584 mac_set_unicode_keystroke_event (code
, buf
)
8586 struct input_event
*buf
;
8588 int charset_id
, c1
, c2
;
8592 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
8595 else if (code
< 0x100)
8598 charset_id
= CHARSET_8_BIT_CONTROL
;
8600 charset_id
= charset_latin_iso8859_1
;
8601 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
8602 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
8607 charset_id
= charset_mule_unicode_0100_24ff
,
8609 else if (code
< 0x33FF)
8610 charset_id
= charset_mule_unicode_2500_33ff
,
8612 else if (code
>= 0xE000)
8613 charset_id
= charset_mule_unicode_e000_ffff
,
8615 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
8616 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
8617 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
8622 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
8624 unsigned char char_code
;
8625 UInt32 key_code
, modifiers
;
8626 unsigned long timestamp
;
8627 struct input_event
*buf
;
8629 static SInt16 last_key_script
= -1;
8630 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
8631 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
, key_code
);
8634 if (mapped_modifiers
& kEventKeyModifierFnMask
8636 && fn_keycode_to_keycode_table
[key_code
])
8637 key_code
= fn_keycode_to_keycode_table
[key_code
];
8640 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
8642 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
8643 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
8645 else if (mapped_modifiers
)
8647 /* translate the keycode back to determine the original key */
8649 UCKeyboardLayout
*uchr_ptr
= NULL
;
8650 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8652 KeyboardLayoutRef layout
;
8654 err
= KLGetCurrentKeyboardLayout (&layout
);
8656 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
8657 (const void **) &uchr_ptr
);
8659 static SInt16 last_key_layout_id
= 0;
8660 static Handle uchr_handle
= (Handle
)-1;
8661 SInt16 current_key_layout_id
=
8662 GetScriptVariable (current_key_script
, smScriptKeys
);
8664 if (uchr_handle
== (Handle
)-1
8665 || last_key_layout_id
!= current_key_layout_id
)
8667 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
8668 last_key_layout_id
= current_key_layout_id
;
8671 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
8677 UInt16 key_action
= action
- keyDown
;
8678 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
8679 UInt32 keyboard_type
= LMGetKbdType ();
8680 SInt32 dead_key_state
= 0;
8682 UniCharCount actual_length
;
8684 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
8685 modifier_key_state
, keyboard_type
,
8686 kUCKeyTranslateNoDeadKeysMask
,
8688 1, &actual_length
, &code
);
8689 if (status
== noErr
&& actual_length
== 1)
8690 mac_set_unicode_keystroke_event (code
, buf
);
8692 #endif /* MAC_OSX */
8694 if (buf
->kind
== NO_EVENT
)
8696 /* This code comes from Keyboard Resource, Appendix C of IM
8697 - Text. This is necessary since shift is ignored in KCHR
8698 table translation when option or command is pressed. It
8699 also does not translate correctly control-shift chars
8700 like C-% so mask off shift here also. */
8701 /* Mask off modifier keys that are mapped to some Emacs
8703 int new_modifiers
= modifiers
& ~mapped_modifiers
;
8704 /* set high byte of keycode to modifier high byte*/
8705 int new_key_code
= key_code
| new_modifiers
;
8706 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
8707 unsigned long some_state
= 0;
8708 UInt32 new_char_code
;
8710 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
8711 if (new_char_code
== 0)
8712 /* Seems like a dead key. Append up-stroke. */
8713 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
8717 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
8718 buf
->code
= new_char_code
& 0xff;
8723 if (buf
->kind
== NO_EVENT
)
8725 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
8726 buf
->code
= char_code
;
8729 buf
->modifiers
= mac_to_emacs_modifiers (mapped_modifiers
, modifiers
);
8730 buf
->modifiers
|= (extra_keyboard_modifiers
8731 & (meta_modifier
| alt_modifier
8732 | hyper_modifier
| super_modifier
));
8734 #if TARGET_API_MAC_CARBON
8735 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
8736 && buf
->code
>= 0x80 && buf
->modifiers
)
8739 TextEncoding encoding
= kTextEncodingMacRoman
;
8740 TextToUnicodeInfo ttu_info
;
8742 UpgradeScriptInfoToTextEncoding (current_key_script
,
8743 kTextLanguageDontCare
,
8744 kTextRegionDontCare
,
8746 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
8751 ByteCount unicode_len
;
8754 pstr
[1] = buf
->code
;
8755 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
8757 &unicode_len
, &code
);
8758 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
8759 mac_set_unicode_keystroke_event (code
, buf
);
8760 DisposeTextToUnicodeInfo (&ttu_info
);
8765 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
8766 && buf
->code
>= 0x80
8767 && last_key_script
!= current_key_script
)
8769 struct input_event event
;
8772 event
.kind
= LANGUAGE_CHANGE_EVENT
;
8774 event
.code
= current_key_script
;
8775 event
.timestamp
= timestamp
;
8776 kbd_buffer_store_event (&event
);
8777 last_key_script
= current_key_script
;
8782 mac_store_apple_event (class, id
, desc
)
8783 Lisp_Object
class, id
;
8786 struct input_event buf
;
8790 buf
.kind
= MAC_APPLE_EVENT
;
8793 XSETFRAME (buf
.frame_or_window
,
8794 mac_focus_frame (&one_mac_display_info
));
8795 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
8796 is safe to use them during read_socket_hook. */
8797 buf
.arg
= mac_aedesc_to_lisp (desc
);
8798 kbd_buffer_store_event (&buf
);
8801 #if TARGET_API_MAC_CARBON
8803 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
8804 event
, num_params
, names
, types
)
8807 Lisp_Object class_key
, id_key
;
8810 const EventParamName
*names
;
8811 const EventParamType
*types
;
8813 OSStatus err
= eventNotHandledErr
;
8814 Lisp_Object binding
;
8816 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
8817 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
8819 if (INTEGERP (binding
))
8820 err
= XINT (binding
);
8823 struct input_event buf
;
8827 buf
.kind
= MAC_APPLE_EVENT
;
8830 XSETFRAME (buf
.frame_or_window
,
8831 mac_focus_frame (&one_mac_display_info
));
8832 /* Now that Lisp object allocations are protected by
8833 BLOCK_INPUT, it is safe to use them during
8834 read_socket_hook. */
8835 buf
.arg
= Fcons (build_string ("aevt"),
8836 mac_event_parameters_to_lisp (event
, num_params
,
8838 kbd_buffer_store_event (&buf
);
8839 mac_wakeup_from_rne ();
8845 #endif /* TARGET_API_MAC_CARBON */
8848 mac_handle_dm_notification (event
)
8851 mac_screen_config_changed
= 1;
8854 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8856 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
8857 CGDirectDisplayID display
;
8858 CGDisplayChangeSummaryFlags flags
;
8861 mac_screen_config_changed
= 1;
8866 init_dm_notification_handler ()
8870 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8871 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8872 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
8875 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
8878 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8879 else /* CGDisplayRegisterReconfigurationCallback == NULL */
8881 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
8882 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8884 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
8885 ProcessSerialNumber psn
;
8887 if (handle_dm_notificationUPP
== NULL
)
8888 handle_dm_notificationUPP
=
8889 NewDMNotificationUPP (mac_handle_dm_notification
);
8891 err
= GetCurrentProcess (&psn
);
8893 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
8901 mac_get_screen_info (dpyinfo
)
8902 struct mac_display_info
*dpyinfo
;
8905 /* HasDepth returns true if it is possible to have a 32 bit display,
8906 but this may not be what is actually used. Mac OSX can do better. */
8907 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
8908 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
8911 CGDisplayCount ndisps
;
8912 CGDirectDisplayID
*displays
;
8914 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
8917 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
8918 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
8922 CGRect bounds
= CGRectZero
;
8924 while (ndisps
-- > 0)
8925 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
8926 dpyinfo
->height
= CGRectGetHeight (bounds
);
8927 dpyinfo
->width
= CGRectGetWidth (bounds
);
8931 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
8932 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
8935 #else /* !MAC_OSX */
8937 GDHandle gdh
= GetMainDevice ();
8938 Rect rect
= (**gdh
).gdRect
;
8940 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
8941 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
8942 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
8945 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
8946 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
8947 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
8949 dpyinfo
->height
= rect
.bottom
- rect
.top
;
8950 dpyinfo
->width
= rect
.right
- rect
.left
;
8952 #endif /* !MAC_OSX */
8956 /***********************************************************************
8957 Initialization (Mac OS Classic)
8958 ***********************************************************************/
8961 extern void init_emacs_passwd_dir ();
8962 extern int emacs_main (int, char **, char **);
8964 extern void initialize_applescript();
8965 extern void terminate_applescript();
8970 Handle menubar_handle
;
8973 menubar_handle
= GetNewMBar (128);
8974 if(menubar_handle
== NULL
)
8976 SetMenuBar (menubar_handle
);
8979 #if !TARGET_API_MAC_CARBON
8980 menu
= GetMenuRef (M_APPLE
);
8982 AppendResMenu (menu
, 'DRVR');
8989 do_init_managers (void)
8991 #if !TARGET_API_MAC_CARBON
8992 InitGraf (&qd
.thePort
);
8994 FlushEvents (everyEvent
, 0);
8999 #endif /* !TARGET_API_MAC_CARBON */
9002 #if !TARGET_API_MAC_CARBON
9003 /* set up some extra stack space for use by emacs */
9004 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
9006 /* MaxApplZone must be called for AppleScript to execute more
9007 complicated scripts */
9010 #endif /* !TARGET_API_MAC_CARBON */
9014 do_check_ram_size (void)
9016 SInt32 physical_ram_size
, logical_ram_size
;
9018 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
9019 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
9020 || physical_ram_size
> (1 << VALBITS
)
9021 || logical_ram_size
> (1 << VALBITS
))
9023 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
9030 profiler_exit_proc ()
9032 ProfilerDump ("\pEmacs.prof");
9037 /* These few functions implement Emacs as a normal Mac application
9038 (almost): set up the heap and the Toolbox, handle necessary system
9039 events plus a few simple menu events. They also set up Emacs's
9040 access to functions defined in the rest of this file. Emacs uses
9041 function hooks to perform all its terminal I/O. A complete list of
9042 these functions appear in termhooks.h. For what they do, read the
9043 comments there and see also w32term.c and xterm.c. What's
9044 noticeably missing here is the event loop, which is normally
9045 present in most Mac application. After performing the necessary
9046 Mac initializations, main passes off control to emacs_main
9047 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9048 (defined further below) to read input. This is where
9049 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9055 #if __profile__ /* is the profiler on? */
9056 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9061 /* set creator and type for files created by MSL */
9062 _fcreator
= MAC_EMACS_CREATOR_CODE
;
9066 do_init_managers ();
9071 do_check_ram_size ();
9074 init_emacs_passwd_dir ();
9078 init_coercion_handler ();
9080 initialize_applescript ();
9082 init_apple_event_handler ();
9084 init_dm_notification_handler ();
9090 /* set up argv array from STR# resource */
9091 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9095 /* free up AppleScript resources on exit */
9096 atexit (terminate_applescript
);
9098 #if __profile__ /* is the profiler on? */
9099 atexit (profiler_exit_proc
);
9102 /* 3rd param "envp" never used in emacs_main */
9103 (void) emacs_main (argc
, argv
, 0);
9106 /* Never reached - real exit in Fkill_emacs */
9110 /* Need to override CodeWarrior's input function so no conversion is
9111 done on newlines Otherwise compiled functions in .elc files will be
9112 read incorrectly. Defined in ...:MSL C:MSL
9113 Common:Source:buffer_io.c. */
9116 __convert_to_newlines (unsigned char * p
, size_t * n
)
9122 __convert_from_newlines (unsigned char * p
, size_t * n
)
9129 make_mac_terminal_frame (struct frame
*f
)
9134 XSETFRAME (frame
, f
);
9136 f
->output_method
= output_mac
;
9137 f
->output_data
.mac
= (struct mac_output
*)
9138 xmalloc (sizeof (struct mac_output
));
9139 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9141 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9143 FRAME_COLS (f
) = 96;
9144 FRAME_LINES (f
) = 4;
9146 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9147 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9149 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9151 f
->output_data
.mac
->cursor_pixel
= 0;
9152 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9153 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9154 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9156 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
9157 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
9158 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
9159 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
9160 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
9161 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
9163 FRAME_FONTSET (f
) = -1;
9164 f
->output_data
.mac
->explicit_parent
= 0;
9167 f
->border_width
= 0;
9169 f
->internal_border_width
= 0;
9174 f
->new_text_cols
= 0;
9175 f
->new_text_lines
= 0;
9177 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9178 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9179 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9183 if (!(FRAME_MAC_WINDOW (f
) =
9184 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9185 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
9187 /* so that update events can find this mac_output struct */
9188 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9194 /* Need to be initialized for unshow_buffer in window.c. */
9195 selected_window
= f
->selected_window
;
9197 Fmodify_frame_parameters (frame
,
9198 Fcons (Fcons (Qfont
,
9199 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9200 Fmodify_frame_parameters (frame
,
9201 Fcons (Fcons (Qforeground_color
,
9202 build_string ("black")), Qnil
));
9203 Fmodify_frame_parameters (frame
,
9204 Fcons (Fcons (Qbackground_color
,
9205 build_string ("white")), Qnil
));
9207 #endif /* MAC_OS8 */
9210 /***********************************************************************
9212 ***********************************************************************/
9214 static int mac_initialized
= 0;
9217 mac_make_rdb (xrm_option
)
9218 const char *xrm_option
;
9220 XrmDatabase database
;
9222 database
= xrm_get_preference_database (NULL
);
9224 xrm_merge_string_database (database
, xrm_option
);
9229 struct mac_display_info
*
9230 mac_term_init (display_name
, xrm_option
, resource_name
)
9231 Lisp_Object display_name
;
9233 char *resource_name
;
9235 struct mac_display_info
*dpyinfo
;
9239 if (!mac_initialized
)
9242 mac_initialized
= 1;
9246 error ("Sorry, this version can only handle one display");
9248 dpyinfo
= &one_mac_display_info
;
9249 bzero (dpyinfo
, sizeof (*dpyinfo
));
9252 dpyinfo
->mac_id_name
9253 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9254 + SCHARS (Vsystem_name
)
9256 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9257 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9259 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9260 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9263 dpyinfo
->reference_count
= 0;
9264 dpyinfo
->resx
= 72.0;
9265 dpyinfo
->resy
= 72.0;
9267 mac_get_screen_info (dpyinfo
);
9269 dpyinfo
->grabbed
= 0;
9270 dpyinfo
->root_window
= NULL
;
9271 dpyinfo
->image_cache
= make_image_cache ();
9273 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
9274 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
9275 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
9276 dpyinfo
->mouse_face_window
= Qnil
;
9277 dpyinfo
->mouse_face_overlay
= Qnil
;
9278 dpyinfo
->mouse_face_hidden
= 0;
9280 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
9282 /* Put this display on the chain. */
9283 dpyinfo
->next
= x_display_list
;
9284 x_display_list
= dpyinfo
;
9286 /* Put it on x_display_name_list. */
9287 x_display_name_list
= Fcons (Fcons (display_name
,
9288 Fcons (Qnil
, dpyinfo
->xrdb
)),
9289 x_display_name_list
);
9290 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
9297 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9300 x_delete_display (dpyinfo
)
9301 struct mac_display_info
*dpyinfo
;
9305 /* Discard this display from x_display_name_list and x_display_list.
9306 We can't use Fdelq because that can quit. */
9307 if (! NILP (x_display_name_list
)
9308 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
9309 x_display_name_list
= XCDR (x_display_name_list
);
9314 tail
= x_display_name_list
;
9315 while (CONSP (tail
) && CONSP (XCDR (tail
)))
9317 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
9319 XSETCDR (tail
, XCDR (XCDR (tail
)));
9326 if (x_display_list
== dpyinfo
)
9327 x_display_list
= dpyinfo
->next
;
9330 struct x_display_info
*tail
;
9332 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
9333 if (tail
->next
== dpyinfo
)
9334 tail
->next
= tail
->next
->next
;
9337 /* Free the font names in the font table. */
9338 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9339 if (dpyinfo
->font_table
[i
].name
)
9341 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
9342 xfree (dpyinfo
->font_table
[i
].full_name
);
9343 xfree (dpyinfo
->font_table
[i
].name
);
9346 if (dpyinfo
->font_table
)
9348 if (dpyinfo
->font_table
->font_encoder
)
9349 xfree (dpyinfo
->font_table
->font_encoder
);
9350 xfree (dpyinfo
->font_table
);
9352 if (dpyinfo
->mac_id_name
)
9353 xfree (dpyinfo
->mac_id_name
);
9355 if (x_display_list
== 0)
9357 mac_clear_font_name_table ();
9358 bzero (dpyinfo
, sizeof (*dpyinfo
));
9363 /* Set up use of X before we make the first connection. */
9365 extern frame_parm_handler mac_frame_parm_handlers
[];
9367 static struct redisplay_interface x_redisplay_interface
=
9369 mac_frame_parm_handlers
,
9373 x_clear_end_of_line
,
9375 x_after_update_window_line
,
9376 x_update_window_begin
,
9377 x_update_window_end
,
9381 mac_flush_display_optional
,
9383 0, /* flush_display_optional */
9385 x_clear_window_mouse_face
,
9386 x_get_glyph_overhangs
,
9387 x_fix_overlapping_area
,
9388 x_draw_fringe_bitmap
,
9390 mac_define_fringe_bitmap
,
9391 mac_destroy_fringe_bitmap
,
9393 0, /* define_fringe_bitmap */
9394 0, /* destroy_fringe_bitmap */
9396 mac_per_char_metric
,
9398 mac_compute_glyph_string_overhangs
,
9399 x_draw_glyph_string
,
9400 mac_define_frame_cursor
,
9401 mac_clear_frame_area
,
9402 mac_draw_window_cursor
,
9403 mac_draw_vertical_window_border
,
9404 mac_shift_glyphs_for_insert
9410 rif
= &x_redisplay_interface
;
9412 clear_frame_hook
= x_clear_frame
;
9413 ins_del_lines_hook
= x_ins_del_lines
;
9414 delete_glyphs_hook
= x_delete_glyphs
;
9415 ring_bell_hook
= XTring_bell
;
9416 reset_terminal_modes_hook
= XTreset_terminal_modes
;
9417 set_terminal_modes_hook
= XTset_terminal_modes
;
9418 update_begin_hook
= x_update_begin
;
9419 update_end_hook
= x_update_end
;
9420 set_terminal_window_hook
= XTset_terminal_window
;
9421 read_socket_hook
= XTread_socket
;
9422 frame_up_to_date_hook
= XTframe_up_to_date
;
9423 mouse_position_hook
= XTmouse_position
;
9424 frame_rehighlight_hook
= XTframe_rehighlight
;
9425 frame_raise_lower_hook
= XTframe_raise_lower
;
9427 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
9428 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
9429 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
9430 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
9432 scroll_region_ok
= 1; /* we'll scroll partial frames */
9433 char_ins_del_ok
= 1;
9434 line_ins_del_ok
= 1; /* we'll just blt 'em */
9435 fast_clear_end_of_line
= 1; /* X does this well */
9436 memory_below_frame
= 0; /* we don't remember what scrolls
9440 last_tool_bar_item
= -1;
9442 /* Try to use interrupt input; if we can't, then start polling. */
9443 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
9447 #if TARGET_API_MAC_CARBON
9449 init_coercion_handler ();
9451 init_dm_notification_handler ();
9454 install_application_handler ();
9456 mac_toolbox_initialize ();
9459 if (!inhibit_window_system
)
9461 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
9463 SetFrontProcess (&psn
);
9482 staticpro (&x_error_message_string
);
9483 x_error_message_string
= Qnil
;
9486 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
9487 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
9488 Qalt
= intern ("alt"); staticpro (&Qalt
);
9489 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
9490 Qsuper
= intern ("super"); staticpro (&Qsuper
);
9491 Qmodifier_value
= intern ("modifier-value");
9492 staticpro (&Qmodifier_value
);
9494 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
9495 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
9496 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
9497 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
9498 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
9500 #if TARGET_API_MAC_CARBON
9501 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
9503 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
9504 staticpro (&Qtoolbar_switch_mode
);
9505 #if USE_MAC_FONT_PANEL
9506 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
9507 Qselection
= intern ("selection"); staticpro (&Qselection
);
9510 Qservice
= intern ("service"); staticpro (&Qservice
);
9511 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
9512 Qperform
= intern ("perform"); staticpro (&Qperform
);
9514 Qmouse_drag_overlay
= intern ("mouse-drag-overlay");
9515 staticpro (&Qmouse_drag_overlay
);
9518 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
9519 Qupdate_active_input_area
= intern ("update-active-input-area");
9520 staticpro (&Qupdate_active_input_area
);
9521 Qunicode_for_key_event
= intern ("unicode-for-key-event");
9522 staticpro (&Qunicode_for_key_event
);
9527 Fprovide (intern ("mac-carbon"), Qnil
);
9530 staticpro (&Qreverse
);
9531 Qreverse
= intern ("reverse");
9533 staticpro (&x_display_name_list
);
9534 x_display_name_list
= Qnil
;
9536 staticpro (&last_mouse_scroll_bar
);
9537 last_mouse_scroll_bar
= Qnil
;
9539 staticpro (&fm_font_family_alist
);
9540 fm_font_family_alist
= Qnil
;
9543 staticpro (&atsu_font_id_hash
);
9544 atsu_font_id_hash
= Qnil
;
9546 staticpro (&fm_style_face_attributes_alist
);
9547 fm_style_face_attributes_alist
= Qnil
;
9551 staticpro (&saved_ts_script_language_on_focus
);
9552 saved_ts_script_language_on_focus
= Qnil
;
9555 /* We don't yet support this, but defining this here avoids whining
9556 from cus-start.el and other places, like "M-x set-variable". */
9557 DEFVAR_BOOL ("x-use-underline-position-properties",
9558 &x_use_underline_position_properties
,
9559 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9560 A value of nil means ignore them. If you encounter fonts with bogus
9561 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9562 to 4.1, set this to nil.
9564 NOTE: Not supported on Mac yet. */);
9565 x_use_underline_position_properties
= 0;
9567 DEFVAR_BOOL ("x-underline-at-descent-line",
9568 &x_underline_at_descent_line
,
9569 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
9570 A value of nil means to draw the underline according to the value of the
9571 variable `x-use-underline-position-properties', which is usually at the
9572 baseline level. The default value is nil. */);
9573 x_underline_at_descent_line
= 0;
9575 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
9576 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
9577 #ifdef USE_TOOLKIT_SCROLL_BARS
9578 Vx_toolkit_scroll_bars
= Qt
;
9580 Vx_toolkit_scroll_bars
= Qnil
;
9583 staticpro (&last_mouse_motion_frame
);
9584 last_mouse_motion_frame
= Qnil
;
9586 /* Variables to configure modifier key assignment. */
9588 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
9589 doc
: /* *Modifier key assumed when the Mac control key is pressed.
9590 The value can be `control', `meta', `alt', `hyper', or `super' for the
9591 respective modifier. The default is `control'. */);
9592 Vmac_control_modifier
= Qcontrol
;
9594 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
9595 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
9596 The value can be `control', `meta', `alt', `hyper', or `super' for the
9597 respective modifier. If the value is nil then the key will act as the
9598 normal Mac control modifier, and the option key can be used to compose
9599 characters depending on the chosen Mac keyboard setting. */);
9600 Vmac_option_modifier
= Qnil
;
9602 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
9603 doc
: /* *Modifier key assumed when the Mac command key is pressed.
9604 The value can be `control', `meta', `alt', `hyper', or `super' for the
9605 respective modifier. The default is `meta'. */);
9606 Vmac_command_modifier
= Qmeta
;
9608 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
9609 doc
: /* *Modifier key assumed when the Mac function key is pressed.
9610 The value can be `control', `meta', `alt', `hyper', or `super' for the
9611 respective modifier. Note that remapping the function key may lead to
9612 unexpected results for some keys on non-US/GB keyboards. */);
9613 Vmac_function_modifier
= Qnil
;
9615 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9616 &Vmac_emulate_three_button_mouse
,
9617 doc
: /* *Specify a way of three button mouse emulation.
9618 The value can be nil, t, or the symbol `reverse'.
9619 A value of nil means that no emulation should be done and the modifiers
9620 should be placed on the mouse-1 event.
9621 t means that when the option-key is held down while pressing the mouse
9622 button, the click will register as mouse-2 and while the command-key
9623 is held down, the click will register as mouse-3.
9624 The symbol `reverse' means that the option-key will register for
9625 mouse-3 and the command-key will register for mouse-2. */);
9626 Vmac_emulate_three_button_mouse
= Qnil
;
9628 #if TARGET_API_MAC_CARBON
9629 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
9630 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
9631 Otherwise, the right click will be treated as mouse-2 and the wheel
9632 button will be mouse-3. */);
9633 mac_wheel_button_is_mouse_2
= 1;
9635 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
9636 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
9637 mac_pass_command_to_system
= 1;
9639 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
9640 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
9641 mac_pass_control_to_system
= 1;
9645 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
9646 doc
: /* *If non-nil, allow anti-aliasing.
9647 The text will be rendered using Core Graphics text rendering which
9648 may anti-alias the text. */);
9650 mac_use_core_graphics
= 1;
9652 mac_use_core_graphics
= 0;
9655 /* Register an entry for `mac-roman' so that it can be used when
9656 creating the terminal frame on Mac OS 9 before loading
9657 term/mac-win.elc. */
9658 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
9659 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
9660 Each entry should be of the form:
9662 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
9664 where CHARSET-NAME is a string used in font names to identify the
9665 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
9666 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
9667 Vmac_charset_info_alist
=
9668 Fcons (list3 (build_string ("mac-roman"),
9669 make_number (smRoman
), Qnil
), Qnil
);
9672 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
9673 doc
: /* Overlay used to display Mac TSM active input area. */);
9674 Vmac_ts_active_input_overlay
= Qnil
;
9676 DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf
,
9677 doc
: /* Byte sequence of the current Mac TSM active input area. */);
9678 /* `empty_string' is not ready yet on Mac OS Classic. */
9679 Vmac_ts_active_input_buf
= build_string ("");
9681 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
9682 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
9683 If the value is t, the input script and language are restored to those
9684 used in the last focus frame. If the value is a pair of integers, the
9685 input script and language codes, which are defined in the Script
9686 Manager, are set to its car and cdr parts, respectively. Otherwise,
9687 Emacs doesn't set them and thus follows the system default behavior. */);
9688 Vmac_ts_script_language_on_focus
= Qnil
;
9692 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9693 (do not change this comment) */