(XDrawLine) [USE_MAC_IMAGE_IO]: Remove spurious return.
[bpt/emacs.git] / src / macterm.c
CommitLineData
1a578e9b 1/* Implementation of GUI terminal on the Mac OS.
0b5538bd 2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
8cabe764 3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
1a578e9b
AC
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
684d6f5b 9the Free Software Foundation; either version 3, or (at your option)
1a578e9b
AC
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
1a578e9b 21
e0f712ba 22/* Contributed by Andrew Choi (akochoi@mac.com). */
1a578e9b
AC
23
24#include <config.h>
1a578e9b 25#include <signal.h>
95dfb192 26
1a578e9b 27#include <stdio.h>
95dfb192 28
1a578e9b
AC
29#include "lisp.h"
30#include "blockinput.h"
31
1a578e9b
AC
32#include "macterm.h"
33
e0f712ba 34#ifndef MAC_OSX
1a578e9b 35#include <alloca.h>
e0f712ba 36#endif
1a578e9b 37
660425fa 38#if !TARGET_API_MAC_CARBON
1a578e9b
AC
39#include <Quickdraw.h>
40#include <ToolUtils.h>
41#include <Sound.h>
42#include <Events.h>
43#include <Script.h>
44#include <Resources.h>
45#include <Fonts.h>
46#include <TextUtils.h>
47#include <LowMem.h>
48#include <Controls.h>
bf06c82f 49#include <Windows.h>
19ee09cc 50#include <Displays.h>
e0f712ba 51#if defined (__MRC__) || (__MSL__ >= 0x6000)
1a578e9b
AC
52#include <ControlDefinitions.h>
53#endif
54
55#if __profile__
56#include <profiler.h>
57#endif
25c9622b 58#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
59
60#include "systty.h"
61#include "systime.h"
62
1a578e9b
AC
63#include <ctype.h>
64#include <errno.h>
65#include <setjmp.h>
66#include <sys/stat.h>
67
95dfb192
YM
68#include "charset.h"
69#include "coding.h"
1a578e9b
AC
70#include "frame.h"
71#include "dispextern.h"
72#include "fontset.h"
73#include "termhooks.h"
74#include "termopts.h"
75#include "termchar.h"
1a578e9b
AC
76#include "disptab.h"
77#include "buffer.h"
78#include "window.h"
95dfb192 79#include "keyboard.h"
1a578e9b 80#include "intervals.h"
95dfb192
YM
81#include "atimer.h"
82#include "keymap.h"
16805b2e 83
1a578e9b 84\f
1a578e9b 85
e0f712ba 86/* Non-nil means Emacs uses toolkit scroll bars. */
1a578e9b 87
e0f712ba 88Lisp_Object Vx_toolkit_scroll_bars;
1a578e9b 89
70ed951a
YM
90/* If non-zero, the text will be rendered using Core Graphics text
91 rendering which may anti-alias the text. */
92int mac_use_core_graphics;
743d0696 93
70ed951a
YM
94/* Non-zero means make use of UNDERLINE_POSITION font properties.
95 (Not yet supported.) */
96int x_use_underline_position_properties;
97
cf2c6835
YM
98/* Non-zero means to draw the underline at the same place as the descent line. */
99
100int x_underline_at_descent_line;
101
1a578e9b
AC
102/* This is a chain of structures for all the X displays currently in
103 use. */
104
105struct x_display_info *x_display_list;
106
107/* This is a list of cons cells, each of the form (NAME
b298e813
YM
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
113 display. */
1a578e9b
AC
114
115Lisp_Object x_display_name_list;
116
117/* This is display since Mac does not support multiple ones. */
118struct mac_display_info one_mac_display_info;
119
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. */
124
125extern struct frame *updating_frame;
126
1a578e9b
AC
127/* This is a frame waiting to be auto-raised, within XTread_socket. */
128
129struct frame *pending_autoraise_frame;
130
1a578e9b
AC
131/* Mouse movement.
132
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.
137
138 Simply asking for MotionNotify all the time seems to work better.
139
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
149 is off. */
150
151/* Where the mouse was last time we reported a mouse event. */
152
f2ec385e
YM
153Rect last_mouse_glyph;
154FRAME_PTR last_mouse_glyph_frame;
1a578e9b
AC
155
156/* The scroll bar in which the last X motion event occurred.
157
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
160 an ordinary motion.
161
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
164 event. */
165
f2ec385e 166Lisp_Object last_mouse_scroll_bar;
1a578e9b
AC
167
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. */
174
f2ec385e 175Time last_mouse_movement_time;
1a578e9b 176
1a578e9b
AC
177struct scroll_bar *tracked_scroll_bar = NULL;
178
179/* Incremented by XTread_socket whenever it really tries to read
180 events. */
181
182#ifdef __STDC__
f2ec385e 183int volatile input_signal_count;
1a578e9b 184#else
f2ec385e 185int input_signal_count;
1a578e9b
AC
186#endif
187
95dfb192 188extern Lisp_Object Vsystem_name;
1a578e9b 189
92289429
YM
190extern Lisp_Object Qeql;
191
1a578e9b
AC
192/* A mask of extra modifier bits to put into every keyboard char. */
193
95dfb192 194extern EMACS_INT extra_keyboard_modifiers;
1a578e9b 195
a36f1680
JW
196/* The keysyms to use for the various modifiers. */
197
70ed951a 198static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
a36f1680 199
8030369c 200extern int inhibit_window_system;
1a578e9b 201
25c9622b 202#if __MRC__ && !TARGET_API_MAC_CARBON
1a578e9b
AC
203QDGlobals qd; /* QuickDraw global information structure. */
204#endif
205
1a578e9b
AC
206struct mac_display_info *mac_display_info_for_display (Display *);
207static void x_update_window_end P_ ((struct window *, int, int));
1a578e9b
AC
208int x_catch_errors P_ ((Display *));
209void x_uncatch_errors P_ ((Display *, int));
210void x_lower_frame P_ ((struct frame *));
211void x_scroll_bar_clear P_ ((struct frame *));
212int x_had_errors_p P_ ((Display *));
213void x_wm_set_size_hint P_ ((struct frame *, long, int));
214void x_raise_frame P_ ((struct frame *));
215void x_set_window_size P_ ((struct frame *, int, int, int));
216void x_wm_set_window_state P_ ((struct frame *, int));
217void x_wm_set_icon_pixmap P_ ((struct frame *, int));
e0f712ba 218void mac_initialize P_ ((void));
1a578e9b
AC
219static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
220static int x_compute_min_glyph_bounds P_ ((struct frame *));
1a578e9b
AC
221static void x_update_end P_ ((struct frame *));
222static void XTframe_up_to_date P_ ((struct frame *));
1a578e9b
AC
223static void XTset_terminal_modes P_ ((void));
224static void XTreset_terminal_modes P_ ((void));
1a578e9b 225static void x_clear_frame P_ ((void));
1a578e9b
AC
226static void frame_highlight P_ ((struct frame *));
227static void frame_unhighlight P_ ((struct frame *));
228static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
229static void XTframe_rehighlight P_ ((struct frame *));
230static void x_frame_rehighlight P_ ((struct x_display_info *));
231static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
e3564461
ST
232static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
233 enum text_cursor_kinds));
234
08f66682 235static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
1a578e9b
AC
236static void x_update_begin P_ ((struct frame *));
237static void x_update_window_begin P_ ((struct window *));
1a578e9b 238static void x_after_update_window_line P_ ((struct glyph_row *));
1a578e9b 239
b73e4d84 240static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
e4f5e019 241static void XSetFont P_ ((Display *, GC, XFontStruct *));
1a578e9b 242
f2ec385e
YM
243extern void mac_toolbox_initialize P_ ((void));
244extern void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
245 enum scroll_bar_part *,
246 Lisp_Object *, Lisp_Object *,
247 unsigned long *));
248#if USE_CG_DRAWING
249extern void mac_flush_display_optional P_ ((struct frame *));
250#endif
251
e4f5e019
YM
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)
236072ae 255#define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
e2d3b7e1
YM
256
257#define CG_SET_FILL_COLOR(context, color) \
4ea08bbf
YM
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)
e2d3b7e1
YM
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) \
265 do { \
266 if (CGColorGetTypeID != NULL) \
267 CGContextSetFillColorWithColor (context, cg_color); \
268 else \
269 CG_SET_FILL_COLOR (context, color); \
270 } while (0)
271#else
272#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
273 CGContextSetFillColorWithColor (context, cg_color)
274#endif
275#else
276#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
277 CG_SET_FILL_COLOR (context, color)
278#endif
279#define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
280 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
281 (gc)->cg_fore_color)
282#define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
283 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
284 (gc)->cg_back_color)
285
286
287#define CG_SET_STROKE_COLOR(context, color) \
4ea08bbf
YM
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)
e2d3b7e1
YM
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) \
295 do { \
296 if (CGColorGetTypeID != NULL) \
297 CGContextSetStrokeColorWithColor (context, cg_color); \
298 else \
299 CG_SET_STROKE_COLOR (context, color); \
300 } while (0)
301#else
302#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
303 CGContextSetStrokeColorWithColor (context, cg_color)
304#endif
305#else
306#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
307 CG_SET_STROKE_COLOR (context, color)
308#endif
309#define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
310 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
311 (gc)->cg_fore_color)
312
4ea08bbf 313#if USE_CG_DRAWING
ad21830e
YM
314/* Fringe bitmaps. */
315
316static int max_fringe_bmp = 0;
317static CGImageRef *fringe_bmp = 0;
318
b03daa51 319CGColorSpaceRef mac_cg_color_space_rgb;
e2d3b7e1
YM
320#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
321static CGColorRef mac_cg_color_black;
322#endif
323
324static void
325init_cg_color ()
326{
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)
333#endif
334 {
834263b6 335 CGFloat rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
e2d3b7e1
YM
336
337 mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
338 }
339#endif
340}
f2ec385e 341#endif /* USE_CG_DRAWING */
e4f5e019 342
1a578e9b
AC
343/* X display function emulation */
344
1a578e9b
AC
345/* Mac version of XDrawLine. */
346
347static void
236072ae
YM
348mac_draw_line (f, gc, x1, y1, x2, y2)
349 struct frame *f;
1a578e9b
AC
350 GC gc;
351 int x1, y1, x2, y2;
352{
4ea08bbf
YM
353#if USE_CG_DRAWING
354 CGContextRef context;
834263b6 355 CGFloat gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
458dbb8c
YM
356
357 if (y1 != y2)
358 gx1 += 0.5f, gx2 += 0.5f;
359 if (x1 != x2)
360 gy1 += 0.5f, gy2 += 0.5f;
4ea08bbf
YM
361
362 context = mac_begin_cg_clip (f, gc);
e2d3b7e1 363 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
4ea08bbf 364 CGContextBeginPath (context);
458dbb8c
YM
365 CGContextMoveToPoint (context, gx1, gy1);
366 CGContextAddLineToPoint (context, gx2, gy2);
4ea08bbf
YM
367 CGContextClosePath (context);
368 CGContextStrokePath (context);
369 mac_end_cg_clip (f);
370#else
458dbb8c
YM
371 if (x1 == x2)
372 {
373 if (y1 > y2)
374 y1--;
375 else if (y2 > y1)
376 y2--;
377 }
378 else if (y1 == y2)
379 {
380 if (x1 > x2)
381 x1--;
382 else
383 x2--;
384 }
385
660425fa 386 mac_begin_clip (f, gc);
e4f5e019 387 RGBForeColor (GC_FORE_COLOR (gc));
1a578e9b
AC
388 MoveTo (x1, y1);
389 LineTo (x2, y2);
f2ec385e 390 mac_end_clip (f, gc);
4ea08bbf 391#endif
1a578e9b
AC
392}
393
a84cad70
YM
394/* Mac version of XDrawLine (to Pixmap). */
395
e3564461 396void
a84cad70 397XDrawLine (display, p, gc, x1, y1, x2, y2)
e3564461
ST
398 Display *display;
399 Pixmap p;
400 GC gc;
401 int x1, y1, x2, y2;
402{
b03daa51
YM
403#if USE_MAC_IMAGE_IO
404 CGContextRef context;
405 XImagePtr ximg = p;
406 CGColorSpaceRef color_space;
407 CGImageAlphaInfo alpha_info;
408 CGFloat gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
409
410 if (y1 != y2)
411 gx1 += 0.5f, gx2 += 0.5f;
412 if (x1 != x2)
413 gy1 += 0.5f, gy2 += 0.5f;
414
415 if (ximg->bits_per_pixel == 32)
416 {
417 color_space = mac_cg_color_space_rgb;
91b953ac 418 alpha_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
b03daa51
YM
419 }
420 else
421 {
422 color_space = NULL;
423 alpha_info = kCGImageAlphaOnly;
424 }
9d2bcff4 425 context = CGBitmapContextCreate (ximg->data, ximg->width, ximg->height, 8,
b03daa51
YM
426 ximg->bytes_per_line, color_space,
427 alpha_info);
428 if (ximg->bits_per_pixel == 32)
429 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
430 else
431 CGContextSetGrayStrokeColor (context, gc->xgcv.foreground / 255.0f, 1.0);
432 CGContextMoveToPoint (context, gx1, gy1);
433 CGContextAddLineToPoint (context, gx2, gy2);
434 CGContextClosePath (context);
435 CGContextStrokePath (context);
436 CGContextRelease (context);
437#else
2a316a84
ST
438 CGrafPtr old_port;
439 GDHandle old_gdh;
440
458dbb8c
YM
441 if (x1 == x2)
442 {
443 if (y1 > y2)
444 y1--;
445 else if (y2 > y1)
446 y2--;
447 }
448 else if (y1 == y2)
449 {
450 if (x1 > x2)
451 x1--;
452 else
453 x2--;
454 }
455
2a316a84 456 GetGWorld (&old_port, &old_gdh);
e3564461
ST
457 SetGWorld (p, NULL);
458
e4f5e019 459 RGBForeColor (GC_FORE_COLOR (gc));
e3564461
ST
460
461 LockPixels (GetGWorldPixMap (p));
462 MoveTo (x1, y1);
463 LineTo (x2, y2);
464 UnlockPixels (GetGWorldPixMap (p));
2a316a84
ST
465
466 SetGWorld (old_port, old_gdh);
b03daa51 467#endif
e3564461
ST
468}
469
1a578e9b 470
e4f5e019 471static void
236072ae
YM
472mac_erase_rectangle (f, gc, x, y, width, height)
473 struct frame *f;
e4f5e019 474 GC gc;
1a578e9b
AC
475 int x, y;
476 unsigned int width, height;
1a578e9b 477{
4ea08bbf 478#if USE_CG_DRAWING
660425fa
YM
479 {
480 CGContextRef context;
4ea08bbf 481
660425fa
YM
482 context = mac_begin_cg_clip (f, gc);
483 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
834263b6 484 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
660425fa
YM
485 mac_end_cg_clip (f);
486 }
4ea08bbf 487#else
660425fa
YM
488 {
489 Rect r;
b69efa23 490
660425fa
YM
491 mac_begin_clip (f, gc);
492 RGBBackColor (GC_BACK_COLOR (gc));
493 SetRect (&r, x, y, x + width, y + height);
494 EraseRect (&r);
495 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
f2ec385e 496 mac_end_clip (f, gc);
660425fa 497 }
4ea08bbf 498#endif
e4f5e019
YM
499}
500
501
502/* Mac version of XClearArea. */
503
504void
236072ae
YM
505mac_clear_area (f, x, y, width, height)
506 struct frame *f;
e4f5e019
YM
507 int x, y;
508 unsigned int width, height;
e4f5e019 509{
236072ae 510 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
1a578e9b
AC
511}
512
513/* Mac version of XClearWindow. */
514
515static void
236072ae
YM
516mac_clear_window (f)
517 struct frame *f;
1a578e9b 518{
4ea08bbf 519#if USE_CG_DRAWING
660425fa
YM
520 {
521 CGContextRef context;
522 GC gc = FRAME_NORMAL_GC (f);
523
524 context = mac_begin_cg_clip (f, NULL);
525 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
526 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
527 FRAME_PIXEL_HEIGHT (f)));
528 mac_end_cg_clip (f);
529 }
530#else /* !USE_CG_DRAWING */
f2ec385e 531 mac_begin_clip (f, NULL);
236072ae 532 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
e0f712ba
AC
533#if TARGET_API_MAC_CARBON
534 {
535 Rect r;
177c0ea7 536
236072ae 537 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
e0f712ba
AC
538 EraseRect (&r);
539 }
540#else /* not TARGET_API_MAC_CARBON */
236072ae 541 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
e0f712ba 542#endif /* not TARGET_API_MAC_CARBON */
f2ec385e 543 mac_end_clip (f, NULL);
4ea08bbf 544#endif
1a578e9b
AC
545}
546
547
548/* Mac replacement for XCopyArea. */
549
ad21830e
YM
550#if USE_CG_DRAWING
551static void
552mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
553 dest_x, dest_y, overlay_p)
554 CGImageRef image;
555 struct frame *f;
556 GC gc;
557 int src_x, src_y;
558 unsigned int width, height;
559 int dest_x, dest_y, overlay_p;
560{
561 CGContextRef context;
834263b6
YM
562 CGFloat port_height = FRAME_PIXEL_HEIGHT (f);
563 CGRect dest_rect = mac_rect_make (f, dest_x, dest_y, width, height);
ad21830e
YM
564
565 context = mac_begin_cg_clip (f, gc);
566 if (!overlay_p)
567 {
e2d3b7e1 568 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
ad21830e
YM
569 CGContextFillRect (context, dest_rect);
570 }
571 CGContextClipToRect (context, dest_rect);
572 CGContextScaleCTM (context, 1, -1);
573 CGContextTranslateCTM (context, 0, -port_height);
574 if (CGImageIsMask (image))
e2d3b7e1 575 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
ad21830e 576 CGContextDrawImage (context,
834263b6
YM
577 mac_rect_make (f, dest_x - src_x,
578 port_height - (dest_y - src_y
579 + CGImageGetHeight (image)),
580 CGImageGetWidth (image),
581 CGImageGetHeight (image)),
ad21830e
YM
582 image);
583 mac_end_cg_clip (f);
584}
585
586#else /* !USE_CG_DRAWING */
587
1a578e9b 588static void
236072ae
YM
589mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
590 struct frame *f;
1a578e9b 591 GC gc;
dcd0c645
KS
592 int x, y, width, height;
593 unsigned short *bits;
41840482 594 int overlay_p;
1a578e9b 595{
dcd0c645 596 BitMap bitmap;
1a578e9b
AC
597 Rect r;
598
dcd0c645 599 bitmap.rowBytes = sizeof(unsigned short);
e3564461 600 bitmap.baseAddr = (char *)bits;
dcd0c645
KS
601 SetRect (&(bitmap.bounds), 0, 0, width, height);
602
660425fa 603 mac_begin_clip (f, gc);
e4f5e019
YM
604 RGBForeColor (GC_FORE_COLOR (gc));
605 RGBBackColor (GC_BACK_COLOR (gc));
e3564461 606 SetRect (&r, x, y, x + width, y + height);
e0f712ba 607#if TARGET_API_MAC_CARBON
236072ae
YM
608 {
609 CGrafPtr port;
610
611 GetPort (&port);
612 LockPortBits (port);
613 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
614 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
615 UnlockPortBits (port);
616 }
e0f712ba 617#else /* not TARGET_API_MAC_CARBON */
236072ae 618 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
41840482 619 overlay_p ? srcOr : srcCopy, 0);
e0f712ba 620#endif /* not TARGET_API_MAC_CARBON */
236072ae 621 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
f2ec385e 622 mac_end_clip (f, gc);
1a578e9b 623}
ad21830e 624#endif /* !USE_CG_DRAWING */
1a578e9b
AC
625
626
1a578e9b
AC
627/* Mac replacement for XCreateBitmapFromBitmapData. */
628
629static void
630mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
631 BitMap *bitmap;
632 char *bits;
633 int w, h;
634{
369a7a37 635 static const unsigned char swap_nibble[16]
30c92fab
ST
636 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
637 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
638 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
639 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
e3564461
ST
640 int i, j, w1;
641 char *p;
1a578e9b 642
e3564461
ST
643 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
644 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
1a578e9b 645 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
1a578e9b
AC
646 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
647 for (i = 0; i < h; i++)
e3564461
ST
648 {
649 p = bitmap->baseAddr + i * bitmap->rowBytes;
650 for (j = 0; j < w1; j++)
30c92fab
ST
651 {
652 /* Bitswap XBM bytes to match how Mac does things. */
653 unsigned char c = *bits++;
654 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
685cdf3a 655 | (swap_nibble[(c>>4) & 0xf]));
30c92fab 656 }
e3564461 657 }
1a578e9b
AC
658
659 SetRect (&(bitmap->bounds), 0, 0, w, h);
660}
661
662
663static void
664mac_free_bitmap (bitmap)
665 BitMap *bitmap;
666{
667 xfree (bitmap->baseAddr);
668}
669
e3564461
ST
670
671Pixmap
672XCreatePixmap (display, w, width, height, depth)
660425fa 673 Display *display;
834263b6 674 Window w;
e3564461 675 unsigned int width, height;
fc7a70cc 676 unsigned int depth;
e3564461 677{
b03daa51
YM
678#if USE_MAC_IMAGE_IO
679 XImagePtr ximg;
680
681 ximg = xmalloc (sizeof (*ximg));
682 ximg->width = width;
683 ximg->height = height;
684 ximg->bits_per_pixel = depth == 1 ? 8 : 32;
685 ximg->bytes_per_line = width * (ximg->bits_per_pixel / 8);
686 ximg->data = xmalloc (ximg->bytes_per_line * height);
687 return ximg;
688#else
e3564461
ST
689 Pixmap pixmap;
690 Rect r;
691 QDErr err;
692
834263b6 693#ifdef MAC_OS8
50bf7673 694 SetPortWindowPort (w);
834263b6 695#endif
e3564461 696 SetRect (&r, 0, 0, width, height);
e09ce637
YM
697#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
698 if (depth == 1)
699#endif
700 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
701#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
702 else
703 /* CreateCGImageFromPixMaps requires ARGB format. */
704 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
705#endif
e3564461
ST
706 if (err != noErr)
707 return NULL;
708 return pixmap;
b03daa51 709#endif
e3564461
ST
710}
711
712
713Pixmap
714XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
660425fa 715 Display *display;
834263b6 716 Window w;
e3564461
ST
717 char *data;
718 unsigned int width, height;
719 unsigned long fg, bg;
e4f5e019 720 unsigned int depth;
e3564461
ST
721{
722 Pixmap pixmap;
723 BitMap bitmap;
b03daa51
YM
724#if USE_MAC_IMAGE_IO
725 CGDataProviderRef provider;
726 CGImageRef image_mask;
727 CGContextRef context;
728
729 pixmap = XCreatePixmap (display, w, width, height, depth);
730 if (pixmap == NULL)
731 return NULL;
732
733 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
734 provider = CGDataProviderCreateWithData (NULL, bitmap.baseAddr,
735 bitmap.rowBytes * height, NULL);
736 image_mask = CGImageMaskCreate (width, height, 1, 1, bitmap.rowBytes,
737 provider, NULL, 0);
738 CGDataProviderRelease (provider);
739
740 context = CGBitmapContextCreate (pixmap->data, width, height, 8,
741 pixmap->bytes_per_line,
742 mac_cg_color_space_rgb,
0e9378b3 743 kCGImageAlphaNoneSkipFirst
91b953ac 744 | kCGBitmapByteOrder32Host);
b03daa51
YM
745
746 CG_SET_FILL_COLOR (context, fg);
747 CGContextFillRect (context, CGRectMake (0, 0, width, height));
748 CG_SET_FILL_COLOR (context, bg);
749 CGContextDrawImage (context, CGRectMake (0, 0, width, height), image_mask);
750 CGContextRelease (context);
751 CGImageRelease (image_mask);
752#else
2a316a84
ST
753 CGrafPtr old_port;
754 GDHandle old_gdh;
660425fa 755 static GC gc = NULL;
e4f5e019
YM
756
757 if (gc == NULL)
758 gc = XCreateGC (display, w, 0, NULL);
e3564461
ST
759
760 pixmap = XCreatePixmap (display, w, width, height, depth);
761 if (pixmap == NULL)
762 return NULL;
763
2a316a84 764 GetGWorld (&old_port, &old_gdh);
e3564461
ST
765 SetGWorld (pixmap, NULL);
766 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
e4f5e019
YM
767 XSetForeground (display, gc, fg);
768 XSetBackground (display, gc, bg);
769 RGBForeColor (GC_FORE_COLOR (gc));
770 RGBBackColor (GC_BACK_COLOR (gc));
e3564461
ST
771 LockPixels (GetGWorldPixMap (pixmap));
772#if TARGET_API_MAC_CARBON
773 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
774 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
775#else /* not TARGET_API_MAC_CARBON */
776 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
777 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
778#endif /* not TARGET_API_MAC_CARBON */
779 UnlockPixels (GetGWorldPixMap (pixmap));
2a316a84 780 SetGWorld (old_port, old_gdh);
b03daa51 781#endif
e3564461
ST
782 mac_free_bitmap (&bitmap);
783
784 return pixmap;
785}
786
787
660425fa
YM
788void
789XFreePixmap (display, pixmap)
790 Display *display;
791 Pixmap pixmap;
792{
b03daa51
YM
793#if USE_MAC_IMAGE_IO
794 if (pixmap)
795 {
796 if (pixmap->data)
797 xfree (pixmap->data);
798 xfree (pixmap);
799 }
800#else
660425fa 801 DisposeGWorld (pixmap);
b03daa51 802#endif
660425fa
YM
803}
804
805
1a578e9b
AC
806/* Mac replacement for XFillRectangle. */
807
808static void
236072ae
YM
809mac_fill_rectangle (f, gc, x, y, width, height)
810 struct frame *f;
1a578e9b
AC
811 GC gc;
812 int x, y;
813 unsigned int width, height;
814{
4ea08bbf
YM
815#if USE_CG_DRAWING
816 CGContextRef context;
817
818 context = mac_begin_cg_clip (f, gc);
e2d3b7e1 819 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
834263b6 820 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
4ea08bbf
YM
821 mac_end_cg_clip (f);
822#else
1a578e9b
AC
823 Rect r;
824
660425fa 825 mac_begin_clip (f, gc);
e4f5e019 826 RGBForeColor (GC_FORE_COLOR (gc));
1a578e9b 827 SetRect (&r, x, y, x + width, y + height);
1a578e9b 828 PaintRect (&r); /* using foreground color of gc */
f2ec385e 829 mac_end_clip (f, gc);
4ea08bbf 830#endif
1a578e9b
AC
831}
832
833
834/* Mac replacement for XDrawRectangle: dest is a window. */
835
836static void
236072ae
YM
837mac_draw_rectangle (f, gc, x, y, width, height)
838 struct frame *f;
1a578e9b
AC
839 GC gc;
840 int x, y;
841 unsigned int width, height;
842{
4ea08bbf
YM
843#if USE_CG_DRAWING
844 CGContextRef context;
845
846 context = mac_begin_cg_clip (f, gc);
e2d3b7e1 847 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
4ea08bbf
YM
848 CGContextStrokeRect (context,
849 CGRectMake (x + 0.5f, y + 0.5f, width, height));
850 mac_end_cg_clip (f);
851#else
1a578e9b
AC
852 Rect r;
853
660425fa 854 mac_begin_clip (f, gc);
e4f5e019 855 RGBForeColor (GC_FORE_COLOR (gc));
4ea08bbf 856 SetRect (&r, x, y, x + width + 1, y + height + 1);
1a578e9b 857 FrameRect (&r); /* using foreground color of gc */
f2ec385e 858 mac_end_clip (f, gc);
4ea08bbf 859#endif
1a578e9b
AC
860}
861
862
660425fa
YM
863static void
864mac_invert_rectangle (f, x, y, width, height)
865 struct frame *f;
866 int x, y;
867 unsigned int width, height;
868{
834263b6
YM
869#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
870#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
871 if (CGContextSetBlendMode != NULL)
872#endif
873 {
874 CGContextRef context;
660425fa 875
834263b6
YM
876 context = mac_begin_cg_clip (f, NULL);
877 CGContextSetRGBFillColor (context, 1.0f, 1.0f, 1.0f, 1.0f);
878 CGContextSetBlendMode (context, kCGBlendModeDifference);
879 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
880 mac_end_cg_clip (f);
881 }
882#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
883 else /* CGContextSetBlendMode == NULL */
884#endif
885#endif /* USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */
886#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)
887 {
888 Rect r;
889
890 mac_begin_clip (f, NULL);
891 SetRect (&r, x, y, x + width, y + height);
892 InvertRect (&r);
893 mac_end_clip (f, NULL);
894 }
895#endif
660425fa
YM
896}
897
898
c3bd8190
YM
899#if USE_ATSUI
900static OSStatus
901atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
902 ConstUniCharArrayPtr text;
903 UniCharCount text_length;
904 ATSUStyle style;
905 ATSUTextLayout *text_layout;
906{
907 OSStatus err;
660425fa 908 static ATSUTextLayout saved_text_layout = NULL;
c3bd8190
YM
909
910 if (saved_text_layout == NULL)
911 {
369a7a37
YM
912 static const UniCharCount lengths[] = {kATSUToTextEnd};
913 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
914 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
c3bd8190
YM
915 static ATSLineLayoutOptions line_layout =
916#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6a0b5d37 917 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
3e16e799 918 | kATSLineUseQDRendering
c3bd8190 919#else
1c4ac540 920 kATSLineIsDisplayOnly | kATSLineFractDisable
c3bd8190
YM
921#endif
922 ;
369a7a37 923 static const ATSUAttributeValuePtr values[] = {&line_layout};
c3bd8190
YM
924
925 err = ATSUCreateTextLayoutWithTextPtr (text,
926 kATSUFromTextBeginning,
927 kATSUToTextEnd,
928 text_length,
929 1, lengths, &style,
930 &saved_text_layout);
931 if (err == noErr)
932 err = ATSUSetLayoutControls (saved_text_layout,
933 sizeof (tags) / sizeof (tags[0]),
934 tags, sizes, values);
c3bd8190
YM
935 if (err == noErr)
936 err = ATSUSetTransientFontMatching (saved_text_layout, true);
937 }
938 else
939 {
940 err = ATSUSetRunStyle (saved_text_layout, style,
941 kATSUFromTextBeginning, kATSUToTextEnd);
942 if (err == noErr)
943 err = ATSUSetTextPointerLocation (saved_text_layout, text,
944 kATSUFromTextBeginning,
945 kATSUToTextEnd,
946 text_length);
947 }
948
949 if (err == noErr)
950 *text_layout = saved_text_layout;
951 return err;
952}
d4a8455b
YM
953
954
1a578e9b 955static void
660425fa
YM
956mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
957 overstrike_p, bytes_per_char)
236072ae 958 struct frame *f;
1a578e9b
AC
959 GC gc;
960 int x, y;
961 char *buf;
bb420759 962 int nchars, bg_width, overstrike_p, bytes_per_char;
1a578e9b 963{
660425fa
YM
964 OSStatus err;
965 ATSUTextLayout text_layout;
c3bd8190 966
660425fa 967 xassert (bytes_per_char == 2);
c3bd8190
YM
968
969#ifndef WORDS_BIG_ENDIAN
660425fa
YM
970 {
971 int i;
972 UniChar *text = (UniChar *)buf;
c3bd8190 973
660425fa
YM
974 for (i = 0; i < nchars; i++)
975 text[i] = EndianU16_BtoN (text[i]);
976 }
c3bd8190 977#endif
660425fa
YM
978 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
979 nchars,
980 GC_FONT (gc)->mac_style,
981 &text_layout);
982 if (err != noErr)
983 return;
c3bd8190 984#ifdef MAC_OSX
660425fa
YM
985 if (!mac_use_core_graphics)
986 {
c3bd8190 987#endif
660425fa
YM
988 mac_begin_clip (f, gc);
989 RGBForeColor (GC_FORE_COLOR (gc));
990 if (bg_width)
991 {
992 Rect r;
9fb446e3 993
660425fa
YM
994 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
995 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
996 RGBBackColor (GC_BACK_COLOR (gc));
997 EraseRect (&r);
998 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
999 }
1000 MoveTo (x, y);
1001 ATSUDrawText (text_layout,
1002 kATSUFromTextBeginning, kATSUToTextEnd,
1003 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1004 if (overstrike_p)
1005 {
1006 MoveTo (x + 1, y);
9fb446e3
YM
1007 ATSUDrawText (text_layout,
1008 kATSUFromTextBeginning, kATSUToTextEnd,
1009 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
9fb446e3 1010 }
f2ec385e 1011 mac_end_clip (f, gc);
660425fa
YM
1012#ifdef MAC_OSX
1013 }
1014 else
1015 {
1016 static CGContextRef context;
834263b6 1017 CGFloat port_height = FRAME_PIXEL_HEIGHT (f);
660425fa
YM
1018 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
1019 static const ByteCount sizes[] = {sizeof (CGContextRef)};
1020 static const ATSUAttributeValuePtr values[] = {&context};
9fb446e3 1021
4ea08bbf 1022#if USE_CG_DRAWING
660425fa 1023 context = mac_begin_cg_clip (f, gc);
4ea08bbf 1024#else
660425fa
YM
1025 CGrafPtr port;
1026
1027 GetPort (&port);
1028 QDBeginCGContext (port, &context);
1029 if (gc->n_clip_rects || bg_width)
1030 {
1031 CGContextTranslateCTM (context, 0, port_height);
1032 CGContextScaleCTM (context, 1, -1);
1033 if (gc->n_clip_rects)
1034 CGContextClipToRects (context, gc->clip_rects,
1035 gc->n_clip_rects);
4ea08bbf 1036#endif
660425fa 1037 if (bg_width)
bb420759 1038 {
660425fa
YM
1039 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1040 CGContextFillRect (context,
834263b6
YM
1041 mac_rect_make (f,
1042 x, y - FONT_BASE (GC_FONT (gc)),
1043 bg_width,
1044 FONT_HEIGHT (GC_FONT (gc))));
bb420759 1045 }
660425fa
YM
1046 CGContextScaleCTM (context, 1, -1);
1047 CGContextTranslateCTM (context, 0, -port_height);
1048#if !USE_CG_DRAWING
1049 }
1050#endif
1051 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1052 err = ATSUSetLayoutControls (text_layout,
1053 sizeof (tags) / sizeof (tags[0]),
1054 tags, sizes, values);
1055 if (err == noErr)
1056 {
1057 ATSUDrawText (text_layout,
1058 kATSUFromTextBeginning, kATSUToTextEnd,
1059 Long2Fix (x), Long2Fix (port_height - y));
1060 if (overstrike_p)
1061 ATSUDrawText (text_layout,
1062 kATSUFromTextBeginning, kATSUToTextEnd,
1063 Long2Fix (x + 1), Long2Fix (port_height - y));
1064 }
4ea08bbf 1065#if USE_CG_DRAWING
660425fa
YM
1066 mac_end_cg_clip (f);
1067 context = NULL;
4ea08bbf 1068#else
660425fa
YM
1069 CGContextSynchronize (context);
1070 QDEndCGContext (port, &context);
4ea08bbf 1071#endif
9fb446e3 1072#if 0
660425fa
YM
1073 /* This doesn't work on Mac OS X 10.1. */
1074 ATSUClearLayoutControls (text_layout,
1075 sizeof (tags) / sizeof (tags[0]), tags);
05f7d868 1076#else
660425fa
YM
1077 ATSUSetLayoutControls (text_layout,
1078 sizeof (tags) / sizeof (tags[0]),
1079 tags, sizes, values);
c3bd8190 1080#endif
c3bd8190 1081 }
660425fa
YM
1082#endif /* MAC_OSX */
1083}
9fb446e3 1084#endif /* USE_ATSUI */
9fb446e3 1085
660425fa
YM
1086
1087static void
1088mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1089 overstrike_p, bytes_per_char)
1090 struct frame *f;
1091 GC gc;
1092 int x, y;
1093 char *buf;
1094 int nchars, bg_width, overstrike_p, bytes_per_char;
1095{
1096#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1097 UInt32 savedFlags;
4ea08bbf 1098#endif
660425fa
YM
1099
1100 mac_begin_clip (f, gc);
1101#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1102 if (mac_use_core_graphics)
1103 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
c3bd8190 1104#endif
660425fa 1105 RGBForeColor (GC_FORE_COLOR (gc));
9fb446e3 1106#ifdef MAC_OS8
660425fa
YM
1107 if (bg_width)
1108 {
1109 RGBBackColor (GC_BACK_COLOR (gc));
1110 TextMode (srcCopy);
1111 }
1112 else
1113 TextMode (srcOr);
9fb446e3 1114#else
660425fa
YM
1115 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1116 because:
1117 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1118 into an offscreen graphics world first. So performance gain
1119 cannot be expected.)
1120 - It lowers rendering quality.
1121 - Some fonts leave garbage on cursor movement. */
1122 if (bg_width)
1123 {
1124 Rect r;
1a578e9b 1125
660425fa
YM
1126 RGBBackColor (GC_BACK_COLOR (gc));
1127 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1128 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1129 EraseRect (&r);
1130 }
1131 TextMode (srcOr);
c3bd8190 1132#endif
660425fa
YM
1133 TextFont (GC_FONT (gc)->mac_fontnum);
1134 TextSize (GC_FONT (gc)->mac_fontsize);
1135 TextFace (GC_FONT (gc)->mac_fontface);
1136 MoveTo (x, y);
1137 DrawText (buf, 0, nchars * bytes_per_char);
1138 if (overstrike_p)
1139 {
1140 TextMode (srcOr);
1141 MoveTo (x + 1, y);
9fb446e3 1142 DrawText (buf, 0, nchars * bytes_per_char);
660425fa
YM
1143 }
1144 if (bg_width)
1145 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
f2ec385e 1146 mac_end_clip (f, gc);
b69efa23 1147
e9859e26 1148#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
660425fa
YM
1149 if (mac_use_core_graphics)
1150 SwapQDTextFlags(savedFlags);
743d0696 1151#endif
660425fa
YM
1152}
1153
1154
1155static INLINE void
1156mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1157 overstrike_p, bytes_per_char)
1158 struct frame *f;
1159 GC gc;
1160 int x, y;
1161 char *buf;
1162 int nchars, bg_width, overstrike_p, bytes_per_char;
1163{
1164#if USE_ATSUI
1165 if (GC_FONT (gc)->mac_style)
1166 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
1167 overstrike_p, bytes_per_char);
1168 else
1169#endif /* USE_ATSUI */
1170 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1171 overstrike_p, bytes_per_char);
1a578e9b
AC
1172}
1173
1174
1a578e9b
AC
1175/* Mac replacement for XDrawImageString. */
1176
1177static void
bb420759 1178mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
236072ae 1179 struct frame *f;
1a578e9b
AC
1180 GC gc;
1181 int x, y;
1182 char *buf;
bb420759 1183 int nchars, bg_width, overstrike_p;
1a578e9b 1184{
bb420759
YM
1185 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1186 overstrike_p, 1);
1a578e9b
AC
1187}
1188
1189
bb420759 1190/* Mac replacement for XDrawImageString16. */
1a578e9b
AC
1191
1192static void
bb420759 1193mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
236072ae 1194 struct frame *f;
1a578e9b
AC
1195 GC gc;
1196 int x, y;
1197 XChar2b *buf;
bb420759 1198 int nchars, bg_width, overstrike_p;
1a578e9b 1199{
bb420759
YM
1200 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1201 overstrike_p, 2);
1a578e9b
AC
1202}
1203
1204
b73e4d84
YM
1205/* Mac replacement for XQueryTextExtents, but takes a character. If
1206 STYLE is NULL, measurement is done by QuickDraw Text routines for
1207 the font of the current graphics port. If CG_GLYPH is not NULL,
1208 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1209
3e7424f7 1210static OSStatus
b73e4d84
YM
1211mac_query_char_extents (style, c,
1212 font_ascent_return, font_descent_return,
1213 overall_return, cg_glyph)
1214#if USE_ATSUI
1215 ATSUStyle style;
1216#else
1217 void *style;
1218#endif
1219 int c;
1220 int *font_ascent_return, *font_descent_return;
1221 XCharStruct *overall_return;
16805b2e 1222#if USE_CG_TEXT_DRAWING
b73e4d84
YM
1223 CGGlyph *cg_glyph;
1224#else
1225 void *cg_glyph;
1226#endif
1227{
3e7424f7 1228 OSStatus err = noErr;
b73e4d84
YM
1229 int width;
1230 Rect char_bounds;
1231
1232#if USE_ATSUI
1233 if (style)
1234 {
1235 ATSUTextLayout text_layout;
1236 UniChar ch = c;
1237
1238 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
0d36bf23
YM
1239 if (err == noErr
1240 && (font_ascent_return || font_descent_return || overall_return))
b73e4d84
YM
1241 {
1242 ATSTrapezoid glyph_bounds;
16805b2e 1243
b73e4d84
YM
1244 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1245 kATSUFromTextBeginning, kATSUToTextEnd,
1246#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1247 kATSUseFractionalOrigins,
1248#else
1249 kATSUseDeviceOrigins,
1250#endif
1251 1, &glyph_bounds, NULL);
1252 if (err == noErr)
1253 {
1254 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1255 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1256
1257 width = Fix2Long (glyph_bounds.upperRight.x
1258 - glyph_bounds.upperLeft.x);
1259 if (font_ascent_return)
1260 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1261 if (font_descent_return)
1262 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1263 }
1264 }
1265 if (err == noErr && overall_return)
1266 {
1267 err = ATSUMeasureTextImage (text_layout,
1268 kATSUFromTextBeginning, kATSUToTextEnd,
1269 0, 0, &char_bounds);
1270 if (err == noErr)
1271 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1272#if USE_CG_TEXT_DRAWING
1273 if (err == noErr && cg_glyph)
1274 {
3e7424f7 1275 OSStatus err1;
b73e4d84
YM
1276 ATSUGlyphInfoArray glyph_info_array;
1277 ByteCount count = sizeof (ATSUGlyphInfoArray);
1278
1279 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1280 kATSUToTextEnd, NULL, NULL, NULL);
1281 if (err1 == noErr)
1282 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1283 kATSUToTextEnd, &count,
1284 &glyph_info_array);
7c682cf1
YM
1285 if (err1 == noErr
1286 /* Make sure that we don't have to make layout
1287 adjustments. */
1288 && glyph_info_array.glyphs[0].deltaY == 0.0f
1289 && glyph_info_array.glyphs[0].idealX == 0.0f
1290 && glyph_info_array.glyphs[0].screenX == 0)
b73e4d84
YM
1291 {
1292 xassert (glyph_info_array.glyphs[0].glyphID);
1293 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1294 }
1295 else
1296 *cg_glyph = 0;
1297 }
1298#endif
1299 }
1300 }
1301 else
1302#endif
1303 {
1304 if (font_ascent_return || font_descent_return)
1305 {
1306 FontInfo font_info;
1307
1308 GetFontInfo (&font_info);
1309 if (font_ascent_return)
1310 *font_ascent_return = font_info.ascent;
1311 if (font_descent_return)
1312 *font_descent_return = font_info.descent;
1313 }
1314 if (overall_return)
1315 {
1316 char ch = c;
1317
1318 width = CharWidth (ch);
1319 QDTextBounds (1, &ch, &char_bounds);
1320 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1321 }
1322 }
1323
1324 return err;
1325}
1326
1327
1328/* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1329
1330static int
1331mac_text_extents_16 (font_struct, string, nchars, overall_return)
1332 XFontStruct *font_struct;
1333 XChar2b *string;
1334 int nchars;
1335 XCharStruct *overall_return;
1336{
1337 int i;
1338 short width = 0, lbearing = 0, rbearing = 0;
1339 XCharStruct *pcm;
1340
1341 for (i = 0; i < nchars; i++)
1342 {
1343 pcm = mac_per_char_metric (font_struct, string, 0);
1344 if (pcm == NULL)
1345 width += FONT_WIDTH (font_struct);
1346 else
1347 {
1348 lbearing = min (lbearing, width + pcm->lbearing);
1349 rbearing = max (rbearing, width + pcm->rbearing);
1350 width += pcm->width;
1351 }
1352 string++;
1353 }
1354
1355 overall_return->lbearing = lbearing;
1356 overall_return->rbearing = rbearing;
1357 overall_return->width = width;
1358
1359 /* What's the meaning of the return value of XTextExtents16? */
1360}
1361
1362
1363#if USE_CG_TEXT_DRAWING
6b9ad469
YM
1364static int cg_text_anti_aliasing_threshold = 8;
1365
1366static void
1367init_cg_text_anti_aliasing_threshold ()
1368{
b465419f
YM
1369 int threshold;
1370 Boolean valid_p;
6b9ad469 1371
b465419f
YM
1372 threshold =
1373 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1374 kCFPreferencesCurrentApplication,
1375 &valid_p);
1376 if (valid_p)
1377 cg_text_anti_aliasing_threshold = threshold;
6b9ad469
YM
1378}
1379
16805b2e 1380static int
bb420759 1381mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
16805b2e
YM
1382 struct frame *f;
1383 GC gc;
1384 int x, y;
1385 XChar2b *buf;
bb420759 1386 int nchars, bg_width, overstrike_p;
16805b2e 1387{
834263b6 1388 CGFloat port_height, gx, gy;
16805b2e
YM
1389 int i;
1390 CGContextRef context;
1391 CGGlyph *glyphs;
1392 CGSize *advances;
1393
70ed951a 1394 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
16805b2e
YM
1395 return 0;
1396
16805b2e
YM
1397 port_height = FRAME_PIXEL_HEIGHT (f);
1398 gx = x;
1399 gy = port_height - y;
1400 glyphs = (CGGlyph *)buf;
9fb446e3
YM
1401 advances = alloca (sizeof (CGSize) * nchars);
1402 if (advances == NULL)
1403 return 0;
16805b2e
YM
1404 for (i = 0; i < nchars; i++)
1405 {
b73e4d84
YM
1406 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1407
1408 advances[i].width = pcm->width;
16805b2e
YM
1409 advances[i].height = 0;
1410 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1411 buf++;
1412 }
1413
4ea08bbf
YM
1414#if USE_CG_DRAWING
1415 context = mac_begin_cg_clip (f, gc);
1416#else
660425fa 1417 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
9fb446e3 1418 if (gc->n_clip_rects || bg_width)
16805b2e
YM
1419 {
1420 CGContextTranslateCTM (context, 0, port_height);
1421 CGContextScaleCTM (context, 1, -1);
9fb446e3
YM
1422 if (gc->n_clip_rects)
1423 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
4ea08bbf 1424#endif
9fb446e3
YM
1425 if (bg_width)
1426 {
e2d3b7e1 1427 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
9fb446e3
YM
1428 CGContextFillRect
1429 (context,
834263b6
YM
1430 mac_rect_make (f, gx, y - FONT_BASE (GC_FONT (gc)),
1431 bg_width, FONT_HEIGHT (GC_FONT (gc))));
9fb446e3 1432 }
16805b2e
YM
1433 CGContextScaleCTM (context, 1, -1);
1434 CGContextTranslateCTM (context, 0, -port_height);
4ea08bbf 1435#if !USE_CG_DRAWING
16805b2e 1436 }
4ea08bbf 1437#endif
e2d3b7e1 1438 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
16805b2e
YM
1439 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1440 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
f2ec385e 1441 CGContextSetTextMatrix (context, CGAffineTransformIdentity);
6b9ad469
YM
1442 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1443 CGContextSetShouldAntialias (context, false);
16805b2e 1444#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1d4412cd
YM
1445#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1446 if (CGContextShowGlyphsWithAdvances != NULL)
1447#endif
bb420759 1448 {
1d4412cd 1449 CGContextSetTextPosition (context, gx, gy);
bb420759 1450 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1d4412cd
YM
1451 if (overstrike_p)
1452 {
1453 CGContextSetTextPosition (context, gx + 1.0f, gy);
1454 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1455 }
bb420759 1456 }
1d4412cd 1457#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
660425fa 1458 else /* CGContextShowGlyphsWithAdvances == NULL */
1d4412cd
YM
1459#endif
1460#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1461#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
16805b2e 1462 {
1d4412cd
YM
1463 for (i = 0; i < nchars; i++)
1464 {
1465 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1466 if (overstrike_p)
1467 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1468 gx += advances[i].width;
1469 }
16805b2e
YM
1470 }
1471#endif
4ea08bbf
YM
1472#if USE_CG_DRAWING
1473 mac_end_cg_clip (f);
1474#else
16805b2e 1475 CGContextSynchronize (context);
660425fa 1476 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
4ea08bbf 1477#endif
16805b2e 1478
16805b2e
YM
1479 return 1;
1480}
1481#endif
1482
1483
e09ce637 1484#if !USE_CG_DRAWING
1a578e9b
AC
1485/* Mac replacement for XCopyArea: dest must be window. */
1486
1487static void
236072ae 1488mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1a578e9b 1489 Pixmap src;
236072ae 1490 struct frame *f;
1a578e9b
AC
1491 GC gc;
1492 int src_x, src_y;
1493 unsigned int width, height;
1494 int dest_x, dest_y;
1495{
1496 Rect src_r, dest_r;
1497
660425fa 1498 mac_begin_clip (f, gc);
e0f712ba 1499
1a578e9b
AC
1500 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1501 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1502
e3564461
ST
1503 ForeColor (blackColor);
1504 BackColor (whiteColor);
1505
1506 LockPixels (GetGWorldPixMap (src));
e0f712ba 1507#if TARGET_API_MAC_CARBON
236072ae
YM
1508 {
1509 CGrafPtr port;
1510
1511 GetPort (&port);
1512 LockPortBits (port);
1513 CopyBits (GetPortBitMapForCopyBits (src),
1514 GetPortBitMapForCopyBits (port),
1515 &src_r, &dest_r, srcCopy, 0);
1516 UnlockPortBits (port);
1517 }
e3564461 1518#else /* not TARGET_API_MAC_CARBON */
236072ae 1519 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
e3564461
ST
1520 &src_r, &dest_r, srcCopy, 0);
1521#endif /* not TARGET_API_MAC_CARBON */
1522 UnlockPixels (GetGWorldPixMap (src));
1f98fbb4 1523
236072ae 1524 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
660425fa 1525
f2ec385e 1526 mac_end_clip (f, gc);
e3564461 1527}
e0f712ba 1528
e3564461
ST
1529
1530static void
236072ae 1531mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
e3564461 1532 width, height, dest_x, dest_y)
e3564461 1533 Pixmap src, mask;
236072ae 1534 struct frame *f;
e3564461
ST
1535 GC gc;
1536 int src_x, src_y;
1537 unsigned int width, height;
1538 int dest_x, dest_y;
1539{
1540 Rect src_r, dest_r;
1541
660425fa 1542 mac_begin_clip (f, gc);
e3564461
ST
1543
1544 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1545 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1546
1547 ForeColor (blackColor);
1548 BackColor (whiteColor);
1549
1550 LockPixels (GetGWorldPixMap (src));
1551 LockPixels (GetGWorldPixMap (mask));
1552#if TARGET_API_MAC_CARBON
236072ae
YM
1553 {
1554 CGrafPtr port;
1555
1556 GetPort (&port);
1557 LockPortBits (port);
1558 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1559 GetPortBitMapForCopyBits (port),
1560 &src_r, &src_r, &dest_r);
1561 UnlockPortBits (port);
1562 }
e0f712ba 1563#else /* not TARGET_API_MAC_CARBON */
e3564461 1564 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
236072ae 1565 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
e0f712ba 1566#endif /* not TARGET_API_MAC_CARBON */
e3564461
ST
1567 UnlockPixels (GetGWorldPixMap (mask));
1568 UnlockPixels (GetGWorldPixMap (src));
1f98fbb4 1569
236072ae 1570 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
660425fa 1571
f2ec385e 1572 mac_end_clip (f, gc);
1a578e9b 1573}
e09ce637 1574#endif /* !USE_CG_DRAWING */
1a578e9b
AC
1575
1576
1a578e9b
AC
1577/* Mac replacement for XCopyArea: used only for scrolling. */
1578
f2ec385e
YM
1579#if TARGET_API_MAC_CARBON
1580/* Defined in mactoolbox.c. */
1581extern void mac_scroll_area P_ ((struct frame *, GC, int, int,
1582 unsigned int, unsigned int, int, int));
1583#else /* not TARGET_API_MAC_CARBON */
1a578e9b 1584static void
236072ae
YM
1585mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1586 struct frame *f;
1a578e9b
AC
1587 GC gc;
1588 int src_x, src_y;
1589 unsigned int width, height;
1590 int dest_x, dest_y;
1591{
1592 Rect src_r, dest_r;
660425fa 1593 WindowRef w = FRAME_MAC_WINDOW (f);
1a578e9b 1594
660425fa 1595 mac_begin_clip (f, gc);
1a578e9b
AC
1596
1597 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1598 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1599
f9e25d0c
AC
1600 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1601 color mapping in CopyBits. Otherwise, it will be slow. */
1602 ForeColor (blackColor);
1603 BackColor (whiteColor);
1604 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
177c0ea7 1605
236072ae 1606 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
660425fa 1607
f2ec385e 1608 mac_end_clip (f, gc);
1a578e9b 1609}
f2ec385e 1610#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
1611
1612
1a578e9b
AC
1613/* Mac replacement for XChangeGC. */
1614
1615static void
e4f5e019
YM
1616XChangeGC (display, gc, mask, xgcv)
1617 Display *display;
1618 GC gc;
1619 unsigned long mask;
1620 XGCValues *xgcv;
1a578e9b
AC
1621{
1622 if (mask & GCForeground)
e4f5e019 1623 XSetForeground (display, gc, xgcv->foreground);
1a578e9b 1624 if (mask & GCBackground)
e4f5e019 1625 XSetBackground (display, gc, xgcv->background);
1a578e9b 1626 if (mask & GCFont)
e4f5e019 1627 XSetFont (display, gc, xgcv->font);
1a578e9b
AC
1628}
1629
1630
1631/* Mac replacement for XCreateGC. */
1632
e4f5e019 1633GC
a84cad70 1634XCreateGC (display, d, mask, xgcv)
e4f5e019 1635 Display *display;
a84cad70 1636 void *d;
e4f5e019
YM
1637 unsigned long mask;
1638 XGCValues *xgcv;
1a578e9b 1639{
e4f5e019 1640 GC gc = xmalloc (sizeof (*gc));
1a578e9b 1641
b96fe6ea 1642 bzero (gc, sizeof (*gc));
e2d3b7e1
YM
1643#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1644#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1645 if (CGColorGetTypeID != NULL)
1646#endif
1647 {
1648 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1649 CGColorRetain (gc->cg_fore_color);
1650 CGColorRetain (gc->cg_back_color);
1651 }
1652#endif
b96fe6ea 1653 XChangeGC (display, gc, mask, xgcv);
1a578e9b
AC
1654
1655 return gc;
1656}
1657
1658
1659/* Used in xfaces.c. */
1660
1661void
1662XFreeGC (display, gc)
1663 Display *display;
1664 GC gc;
1665{
1c4ac540
YM
1666 if (gc->clip_region)
1667 DisposeRgn (gc->clip_region);
e2d3b7e1 1668#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
a84cad70
YM
1669#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1670 if (CGColorGetTypeID != NULL)
1671#endif
1672 {
1673 CGColorRelease (gc->cg_fore_color);
1674 CGColorRelease (gc->cg_back_color);
1675 }
e2d3b7e1 1676#endif
1a578e9b
AC
1677 xfree (gc);
1678}
1679
1680
1681/* Mac replacement for XGetGCValues. */
1682
1683static void
e4f5e019
YM
1684XGetGCValues (display, gc, mask, xgcv)
1685 Display *display;
1686 GC gc;
1687 unsigned long mask;
1688 XGCValues *xgcv;
1a578e9b 1689{
e4f5e019
YM
1690 if (mask & GCForeground)
1691 xgcv->foreground = gc->xgcv.foreground;
1692 if (mask & GCBackground)
1693 xgcv->background = gc->xgcv.background;
1694 if (mask & GCFont)
1695 xgcv->font = gc->xgcv.font;
1a578e9b
AC
1696}
1697
1698
1699/* Mac replacement for XSetForeground. */
1700
e3564461 1701void
1a578e9b
AC
1702XSetForeground (display, gc, color)
1703 Display *display;
1704 GC gc;
1705 unsigned long color;
1706{
e4f5e019
YM
1707 if (gc->xgcv.foreground != color)
1708 {
1709 gc->xgcv.foreground = color;
1710 gc->fore_color.red = RED16_FROM_ULONG (color);
1711 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1712 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
e2d3b7e1
YM
1713#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1714#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1715 if (CGColorGetTypeID != NULL)
1716#endif
1717 {
1718 CGColorRelease (gc->cg_fore_color);
1719 if (color == 0)
1720 {
1721 gc->cg_fore_color = mac_cg_color_black;
1722 CGColorRetain (gc->cg_fore_color);
1723 }
1724 else
1725 {
834263b6 1726 CGFloat rgba[4];
e2d3b7e1
YM
1727
1728 rgba[0] = gc->fore_color.red / 65535.0f;
1729 rgba[1] = gc->fore_color.green / 65535.0f;
1730 rgba[2] = gc->fore_color.blue / 65535.0f;
1731 rgba[3] = 1.0f;
1732 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1733 }
1734 }
1735#endif
e4f5e019 1736 }
1a578e9b
AC
1737}
1738
1739
9cdd4884
ST
1740/* Mac replacement for XSetBackground. */
1741
1742void
1743XSetBackground (display, gc, color)
1744 Display *display;
1745 GC gc;
1746 unsigned long color;
1747{
e4f5e019
YM
1748 if (gc->xgcv.background != color)
1749 {
1750 gc->xgcv.background = color;
1751 gc->back_color.red = RED16_FROM_ULONG (color);
1752 gc->back_color.green = GREEN16_FROM_ULONG (color);
1753 gc->back_color.blue = BLUE16_FROM_ULONG (color);
e2d3b7e1
YM
1754#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1755#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1756 if (CGColorGetTypeID != NULL)
1757#endif
1758 {
1759 CGColorRelease (gc->cg_back_color);
1760 if (color == 0)
1761 {
1762 gc->cg_back_color = mac_cg_color_black;
1763 CGColorRetain (gc->cg_back_color);
1764 }
1765 else
1766 {
834263b6 1767 CGFloat rgba[4];
e2d3b7e1
YM
1768
1769 rgba[0] = gc->back_color.red / 65535.0f;
1770 rgba[1] = gc->back_color.green / 65535.0f;
1771 rgba[2] = gc->back_color.blue / 65535.0f;
1772 rgba[3] = 1.0f;
1773 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1774 }
1775 }
1776#endif
e4f5e019
YM
1777 }
1778}
1779
1780
1781/* Mac replacement for XSetFont. */
1782
1783static void
1784XSetFont (display, gc, font)
1785 Display *display;
1786 GC gc;
1787 XFontStruct *font;
1788{
1789 gc->xgcv.font = font;
9cdd4884
ST
1790}
1791
1792
1c4ac540
YM
1793/* Mac replacement for XSetClipRectangles. */
1794
1795static void
834263b6
YM
1796mac_set_clip_rectangles (f, gc, rectangles, n)
1797 struct frame *f;
1c4ac540
YM
1798 GC gc;
1799 Rect *rectangles;
1800 int n;
1801{
1802 int i;
1803
b6e3efe0
YM
1804 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1805
1806 gc->n_clip_rects = n;
1807 if (n > 0)
1c4ac540
YM
1808 {
1809 if (gc->clip_region == NULL)
1810 gc->clip_region = NewRgn ();
1811 RectRgn (gc->clip_region, rectangles);
1812 if (n > 1)
1813 {
1814 RgnHandle region = NewRgn ();
1815
1816 for (i = 1; i < n; i++)
1817 {
1818 RectRgn (region, rectangles + i);
1819 UnionRgn (gc->clip_region, region, gc->clip_region);
1820 }
1821 DisposeRgn (region);
1822 }
1823 }
458dbb8c 1824#if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1c4ac540
YM
1825 for (i = 0; i < n; i++)
1826 {
1827 Rect *rect = rectangles + i;
1828
834263b6
YM
1829 gc->clip_rects[i] = mac_rect_make (f, rect->left, rect->top,
1830 rect->right - rect->left,
1831 rect->bottom - rect->top);
1c4ac540
YM
1832 }
1833#endif
1834}
1835
1836
1837/* Mac replacement for XSetClipMask. */
1838
1839static INLINE void
834263b6
YM
1840mac_reset_clip_rectangles (f, gc)
1841 struct frame *f;
1c4ac540
YM
1842 GC gc;
1843{
b6e3efe0 1844 gc->n_clip_rects = 0;
1c4ac540
YM
1845}
1846
fc7a70cc
ST
1847/* Remove calls to XFlush by defining XFlush to an empty replacement.
1848 Calls to XFlush should be unnecessary because the X output buffer
1849 is flushed automatically as needed by calls to XPending,
1850 XNextEvent, or XWindowEvent according to the XFlush man page.
1851 XTread_socket calls XPending. Removing XFlush improves
1852 performance. */
1853
1854#define XFlush(DISPLAY) (void) 0
1855
1a578e9b
AC
1856\f
1857/***********************************************************************
1858 Starting and ending an update
1859 ***********************************************************************/
177c0ea7 1860
1a578e9b
AC
1861/* Start an update of frame F. This function is installed as a hook
1862 for update_begin, i.e. it is called when update_begin is called.
1863 This function is called prior to calls to x_update_window_begin for
e0f712ba 1864 each window being updated. */
1a578e9b 1865
e0f712ba 1866static void
1a578e9b
AC
1867x_update_begin (f)
1868 struct frame *f;
1869{
b15325b2 1870 BLOCK_INPUT;
f2ec385e 1871 mac_update_begin (f);
b15325b2 1872 UNBLOCK_INPUT;
1a578e9b
AC
1873}
1874
1875
1876/* Start update of window W. Set the global variable updated_window
1877 to the window being updated and set output_cursor to the cursor
1878 position of W. */
1879
e0f712ba 1880static void
1a578e9b
AC
1881x_update_window_begin (w)
1882 struct window *w;
1883{
1884 struct frame *f = XFRAME (WINDOW_FRAME (w));
1885 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
177c0ea7 1886
1a578e9b
AC
1887 updated_window = w;
1888 set_output_cursor (&w->cursor);
1889
1890 BLOCK_INPUT;
1891
1892 if (f == display_info->mouse_face_mouse_frame)
1893 {
1894 /* Don't do highlighting for mouse motion during the update. */
1895 display_info->mouse_face_defer = 1;
1896
1897 /* If F needs to be redrawn, simply forget about any prior mouse
1898 highlighting. */
1899 if (FRAME_GARBAGED_P (f))
1900 display_info->mouse_face_window = Qnil;
1901
1902#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1903 their mouse_face_p flag set, which means that they are always
1904 unequal to rows in a desired matrix which never have that
1905 flag set. So, rows containing mouse-face glyphs are never
1906 scrolled, and we don't have to switch the mouse highlight off
1907 here to prevent it from being scrolled. */
177c0ea7 1908
1a578e9b
AC
1909 /* Can we tell that this update does not affect the window
1910 where the mouse highlight is? If so, no need to turn off.
1911 Likewise, don't do anything if the frame is garbaged;
1912 in that case, the frame's current matrix that we would use
1913 is all wrong, and we will redisplay that line anyway. */
1914 if (!NILP (display_info->mouse_face_window)
1915 && w == XWINDOW (display_info->mouse_face_window))
1916 {
1917 int i;
1918
50bf7673 1919 for (i = 0; i < w->desired_matrix->nrows; ++i)
1a578e9b
AC
1920 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1921 break;
1922
1923 if (i < w->desired_matrix->nrows)
1924 clear_mouse_face (display_info);
1925 }
1926#endif /* 0 */
1927 }
1928
1929 UNBLOCK_INPUT;
1930}
1931
1932
f9e65eb3 1933/* Draw a vertical window border from (x,y0) to (x,y1) */
1a578e9b
AC
1934
1935static void
f9e65eb3 1936mac_draw_vertical_window_border (w, x, y0, y1)
1a578e9b 1937 struct window *w;
f9e65eb3 1938 int x, y0, y1;
1a578e9b
AC
1939{
1940 struct frame *f = XFRAME (WINDOW_FRAME (w));
dd15724d
YM
1941 struct face *face;
1942
1943 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
1944 if (face)
1945 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
1946 face->foreground);
ffe8b3f4 1947
236072ae 1948 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
1a578e9b 1949}
e0f712ba 1950
1a578e9b
AC
1951/* End update of window W (which is equal to updated_window).
1952
1953 Draw vertical borders between horizontally adjacent windows, and
1954 display W's cursor if CURSOR_ON_P is non-zero.
1955
1956 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1957 glyphs in mouse-face were overwritten. In that case we have to
1958 make sure that the mouse-highlight is properly redrawn.
1959
1960 W may be a menu bar pseudo-window in case we don't have X toolkit
b15325b2 1961 support. Such windows don't have a cursor, so don't display it
95dfb192 1962 here. */
1a578e9b 1963
e0f712ba 1964static void
1a578e9b
AC
1965x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1966 struct window *w;
1967 int cursor_on_p, mouse_face_overwritten_p;
1968{
f9e65eb3 1969 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
e0f712ba 1970
1a578e9b
AC
1971 if (!w->pseudo_window_p)
1972 {
1a578e9b
AC
1973 BLOCK_INPUT;
1974
1a578e9b 1975 if (cursor_on_p)
f9e65eb3
KS
1976 display_and_set_cursor (w, 1, output_cursor.hpos,
1977 output_cursor.vpos,
1978 output_cursor.x, output_cursor.y);
177c0ea7 1979
f94a2622
KS
1980 if (draw_window_fringes (w, 1))
1981 x_draw_vertical_border (w);
797dc7b8 1982
1a578e9b
AC
1983 UNBLOCK_INPUT;
1984 }
e0f712ba
AC
1985
1986 /* If a row with mouse-face was overwritten, arrange for
1987 XTframe_up_to_date to redisplay the mouse highlight. */
1988 if (mouse_face_overwritten_p)
1989 {
1990 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1991 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1992 dpyinfo->mouse_face_window = Qnil;
1993 }
1994
1a578e9b
AC
1995 updated_window = NULL;
1996}
1997
1998
1999/* End update of frame F. This function is installed as a hook in
2000 update_end. */
2001
e0f712ba 2002static void
1a578e9b
AC
2003x_update_end (f)
2004 struct frame *f;
2005{
404e4b84
ST
2006 /* Mouse highlight may be displayed again. */
2007 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
2008
2009 BLOCK_INPUT;
f2ec385e 2010 mac_update_end (f);
1a578e9b
AC
2011 XFlush (FRAME_MAC_DISPLAY (f));
2012 UNBLOCK_INPUT;
2013}
2014
2015
2016/* This function is called from various places in xdisp.c whenever a
2017 complete update has been performed. The global variable
2018 updated_window is not available here. */
2019
e0f712ba 2020static void
1a578e9b
AC
2021XTframe_up_to_date (f)
2022 struct frame *f;
2023{
fe97e8df 2024 if (FRAME_MAC_P (f))
1a578e9b
AC
2025 {
2026 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2027
2028 if (dpyinfo->mouse_face_deferred_gc
2029 || f == dpyinfo->mouse_face_mouse_frame)
2030 {
2031 BLOCK_INPUT;
2032 if (dpyinfo->mouse_face_mouse_frame)
2033 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
2034 dpyinfo->mouse_face_mouse_x,
2035 dpyinfo->mouse_face_mouse_y);
2036 dpyinfo->mouse_face_deferred_gc = 0;
2037 UNBLOCK_INPUT;
2038 }
f2ec385e
YM
2039
2040 mac_frame_up_to_date (f);
1a578e9b
AC
2041 }
2042}
2043
2044
2045/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
3f332ef3 2046 arrow bitmaps, or clear the fringes if no bitmaps are required
1a578e9b 2047 before DESIRED_ROW is made current. The window being updated is
e0f712ba 2048 found in updated_window. This function is called from
1a578e9b
AC
2049 update_window_line only if it is known that there are differences
2050 between bitmaps to be drawn between current row and DESIRED_ROW. */
2051
e0f712ba 2052static void
1a578e9b
AC
2053x_after_update_window_line (desired_row)
2054 struct glyph_row *desired_row;
2055{
2056 struct window *w = updated_window;
e0f712ba
AC
2057 struct frame *f;
2058 int width, height;
2059
1a578e9b 2060 xassert (w);
177c0ea7 2061
1a578e9b 2062 if (!desired_row->mode_line_p && !w->pseudo_window_p)
797dc7b8 2063 desired_row->redraw_fringe_bitmaps_p = 1;
1a578e9b 2064
e0f712ba
AC
2065 /* When a window has disappeared, make sure that no rest of
2066 full-width rows stays visible in the internal border. Could
2067 check here if updated_window is the leftmost/rightmost window,
2068 but I guess it's not worth doing since vertically split windows
2069 are almost never used, internal border is rarely set, and the
2070 overhead is very small. */
2071 if (windows_or_buffers_changed
2072 && desired_row->full_width_p
2073 && (f = XFRAME (w->frame),
2074 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2075 width != 0)
2076 && (height = desired_row->visible_height,
2077 height > 0))
2078 {
2079 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
95dfb192 2080
e0f712ba
AC
2081 /* Internal border is drawn below the tool bar. */
2082 if (WINDOWP (f->tool_bar_window)
2083 && w == XWINDOW (f->tool_bar_window))
2084 y -= width;
1a578e9b 2085
e0f712ba 2086 BLOCK_INPUT;
236072ae
YM
2087 mac_clear_area (f, 0, y, width, height);
2088 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
1a578e9b
AC
2089 UNBLOCK_INPUT;
2090 }
2091}
2092
2093
3f332ef3 2094/* Draw the bitmap WHICH in one of the left or right fringes of
1a578e9b
AC
2095 window W. ROW is the glyph row for which to display the bitmap; it
2096 determines the vertical position at which the bitmap has to be
2097 drawn. */
2098
2099static void
5958f265 2100x_draw_fringe_bitmap (w, row, p)
1a578e9b
AC
2101 struct window *w;
2102 struct glyph_row *row;
5958f265 2103 struct draw_fringe_bitmap_params *p;
1a578e9b
AC
2104{
2105 struct frame *f = XFRAME (WINDOW_FRAME (w));
2106 Display *display = FRAME_MAC_DISPLAY (f);
5958f265 2107 struct face *face = p->face;
797dc7b8 2108 int rowY;
660425fa
YM
2109 int overlay_p = p->overlay_p;
2110
2111#ifdef MAC_OSX
2112 if (!overlay_p)
2113 {
2114 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2115
2116#if 0 /* MAC_TODO: stipple */
2117 /* In case the same realized face is used for fringes and
2118 for something displayed in the text (e.g. face `region' on
2119 mono-displays, the fill style may have been changed to
2120 FillSolid in x_draw_glyph_string_background. */
2121 if (face->stipple)
2122 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2123 else
2124 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2125#endif
2126
2127 /* If the fringe is adjacent to the left (right) scroll bar of a
2128 leftmost (rightmost, respectively) window, then extend its
2129 background to the gap between the fringe and the bar. */
2130 if ((WINDOW_LEFTMOST_P (w)
2131 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2132 || (WINDOW_RIGHTMOST_P (w)
2133 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2134 {
2135 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2136
2137 if (sb_width > 0)
2138 {
2139 int left = WINDOW_SCROLL_BAR_AREA_X (w);
2140 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2141 * FRAME_COLUMN_WIDTH (f));
2142
2143 if (bx < 0
2144 && (left + width == p->x
2145 || p->x + p->wd == left))
2146 {
2147 /* Bitmap fills the fringe and we need background
2148 extension. */
2149 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2150
2151 bx = p->x;
2152 nx = p->wd;
2153 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2154 row->y));
2155 ny = row->visible_height;
2156 }
2157
2158 if (bx >= 0)
2159 {
2160 if (left + width == bx)
2161 {
2162 bx = left + sb_width;
2163 nx += width - sb_width;
2164 }
2165 else if (bx + nx == left)
2166 nx += width - sb_width;
2167 }
2168 }
2169 }
2170
2171 if (bx >= 0)
2172 {
2173 mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
2174 /* The fringe background has already been filled. */
2175 overlay_p = 1;
2176 }
2177
2178#if 0 /* MAC_TODO: stipple */
2179 if (!face->stipple)
2180 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2181#endif
2182 }
2183#endif /* MAC_OSX */
1a578e9b
AC
2184
2185 /* Must clip because of partially visible lines. */
797dc7b8
KS
2186 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2187 if (p->y < rowY)
2188 {
2189 /* Adjust position of "bottom aligned" bitmap on partially
2190 visible last row. */
2191 int oldY = row->y;
2192 int oldVH = row->visible_height;
2193 row->visible_height = p->h;
2194 row->y -= rowY - p->y;
236072ae 2195 x_clip_to_row (w, row, -1, face->gc);
797dc7b8
KS
2196 row->y = oldY;
2197 row->visible_height = oldVH;
2198 }
2199 else
236072ae 2200 x_clip_to_row (w, row, -1, face->gc);
1a578e9b 2201
660425fa 2202#ifndef MAC_OSX
288670f5 2203 if (p->bx >= 0 && !p->overlay_p)
d33c49e8 2204 {
d33c49e8
KS
2205#if 0 /* MAC_TODO: stipple */
2206 /* In case the same realized face is used for fringes and
2207 for something displayed in the text (e.g. face `region' on
2208 mono-displays, the fill style may have been changed to
2209 FillSolid in x_draw_glyph_string_background. */
2210 if (face->stipple)
2211 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2212 else
2213 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2214#endif
2215
236072ae 2216 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
d33c49e8
KS
2217
2218#if 0 /* MAC_TODO: stipple */
2219 if (!face->stipple)
2220 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2221#endif
2222 }
660425fa 2223#endif /* !MAC_OSX */
d33c49e8 2224
ad21830e
YM
2225 if (p->which
2226#if USE_CG_DRAWING
2227 && p->which < max_fringe_bmp
2228#endif
2229 )
e0f712ba 2230 {
e4f5e019 2231 XGCValues gcv;
1a578e9b 2232
e4f5e019
YM
2233 XGetGCValues (display, face->gc, GCForeground, &gcv);
2234 XSetForeground (display, face->gc,
2235 (p->cursor_p
2236 ? (p->overlay_p ? face->background
2237 : f->output_data.mac->cursor_pixel)
2238 : face->foreground));
ad21830e
YM
2239#if USE_CG_DRAWING
2240 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
660425fa 2241 p->wd, p->h, p->x, p->y, overlay_p);
ad21830e 2242#else
236072ae 2243 mac_draw_bitmap (f, face->gc, p->x, p->y,
660425fa 2244 p->wd, p->h, p->bits + p->dh, overlay_p);
ad21830e 2245#endif
e4f5e019 2246 XSetForeground (display, face->gc, gcv.foreground);
d33c49e8 2247 }
1a578e9b 2248
834263b6 2249 mac_reset_clip_rectangles (f, face->gc);
1a578e9b
AC
2250}
2251
ad21830e
YM
2252#if USE_CG_DRAWING
2253static void
2254mac_define_fringe_bitmap (which, bits, h, wd)
2255 int which;
2256 unsigned short *bits;
2257 int h, wd;
2258{
ad21830e
YM
2259 int i;
2260 CGDataProviderRef provider;
2261
2262 if (which >= max_fringe_bmp)
2263 {
2264 i = max_fringe_bmp;
2265 max_fringe_bmp = which + 20;
2266 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2267 while (i < max_fringe_bmp)
2268 fringe_bmp[i++] = 0;
2269 }
2270
2271 for (i = 0; i < h; i++)
2272 bits[i] = ~bits[i];
cb91e86a
YM
2273
2274 BLOCK_INPUT;
2275
ad21830e
YM
2276 provider = CGDataProviderCreateWithData (NULL, bits,
2277 sizeof (unsigned short) * h, NULL);
2278 if (provider)
2279 {
2280 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2281 sizeof (unsigned short),
2282 provider, NULL, 0);
2283 CGDataProviderRelease (provider);
2284 }
cb91e86a
YM
2285
2286 UNBLOCK_INPUT;
ad21830e
YM
2287}
2288
2289static void
2290mac_destroy_fringe_bitmap (which)
2291 int which;
2292{
2293 if (which >= max_fringe_bmp)
2294 return;
2295
2296 if (fringe_bmp[which])
cb91e86a
YM
2297 {
2298 BLOCK_INPUT;
2299 CGImageRelease (fringe_bmp[which]);
2300 UNBLOCK_INPUT;
2301 }
ad21830e
YM
2302 fringe_bmp[which] = 0;
2303}
2304#endif
1a578e9b 2305\f
95dfb192 2306
1a578e9b 2307/* This is called when starting Emacs and when restarting after
e0f712ba 2308 suspend. When starting Emacs, no window is mapped. And nothing
1a578e9b
AC
2309 must be done to Emacs's own window if it is suspended (though that
2310 rarely happens). */
2311
e0f712ba 2312static void
1a578e9b
AC
2313XTset_terminal_modes ()
2314{
2315}
2316
2317/* This is called when exiting or suspending Emacs. Exiting will make
e0f712ba 2318 the windows go away, and suspending requires no action. */
1a578e9b 2319
e0f712ba 2320static void
1a578e9b
AC
2321XTreset_terminal_modes ()
2322{
2323}
2324
95dfb192 2325
1a578e9b
AC
2326\f
2327/***********************************************************************
2328 Display Iterator
2329 ***********************************************************************/
2330
2331/* Function prototypes of this page. */
2332
1a578e9b 2333static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
750fc673 2334static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1a578e9b
AC
2335
2336
458dbb8c
YM
2337static void
2338pcm_init (pcm, count)
2339 XCharStruct *pcm;
2340 int count;
2341{
2342 bzero (pcm, sizeof (XCharStruct) * count);
2343 while (--count >= 0)
2344 {
2345 pcm->descent = PCM_INVALID;
2346 pcm++;
2347 }
2348}
2349
2350static enum pcm_status
2351pcm_get_status (pcm)
369a7a37 2352 const XCharStruct *pcm;
458dbb8c
YM
2353{
2354 int height = pcm->ascent + pcm->descent;
2355
2356 /* Negative height means some special status. */
2357 return height >= 0 ? PCM_VALID : height;
2358}
2359
1a578e9b
AC
2360/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2361 is not contained in the font. */
2362
2363static INLINE XCharStruct *
2364x_per_char_metric (font, char2b)
2365 XFontStruct *font;
2366 XChar2b *char2b;
2367{
2368 /* The result metric information. */
2369 XCharStruct *pcm = NULL;
2370
2371 xassert (font && char2b);
2372
c3bd8190
YM
2373#if USE_ATSUI
2374 if (font->mac_style)
2375 {
458dbb8c 2376 XCharStruct **row = font->bounds.rows + char2b->byte1;
b73e4d84
YM
2377
2378 if (*row == NULL)
c3bd8190 2379 {
458dbb8c
YM
2380 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2381 pcm_init (*row, 0x100);
c3bd8190 2382 }
458dbb8c
YM
2383 pcm = *row + char2b->byte2;
2384 if (pcm_get_status (pcm) != PCM_VALID)
c3bd8190 2385 {
b96fe6ea
YM
2386 BLOCK_INPUT;
2387 mac_query_char_extents (font->mac_style,
2388 (char2b->byte1 << 8) + char2b->byte2,
2389 NULL, NULL, pcm, NULL);
2390 UNBLOCK_INPUT;
c3bd8190
YM
2391 }
2392 }
2393 else
2394 {
2395#endif
b73e4d84 2396 if (font->bounds.per_char != NULL)
1a578e9b
AC
2397 {
2398 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2399 {
2400 /* min_char_or_byte2 specifies the linear character index
2401 corresponding to the first element of the per_char array,
2402 max_char_or_byte2 is the index of the last character. A
2403 character with non-zero CHAR2B->byte1 is not in the font.
2404 A character with byte2 less than min_char_or_byte2 or
2405 greater max_char_or_byte2 is not in the font. */
2406 if (char2b->byte1 == 0
2407 && char2b->byte2 >= font->min_char_or_byte2
2408 && char2b->byte2 <= font->max_char_or_byte2)
b73e4d84
YM
2409 pcm = font->bounds.per_char
2410 + (char2b->byte2 - font->min_char_or_byte2);
1a578e9b
AC
2411 }
2412 else
2413 {
2414 /* If either min_byte1 or max_byte1 are nonzero, both
2415 min_char_or_byte2 and max_char_or_byte2 are less than
2416 256, and the 2-byte character index values corresponding
2417 to the per_char array element N (counting from 0) are:
2418
2419 byte1 = N/D + min_byte1
2420 byte2 = N\D + min_char_or_byte2
2421
2422 where:
2423
2424 D = max_char_or_byte2 - min_char_or_byte2 + 1
2425 / = integer division
2426 \ = integer modulus */
2427 if (char2b->byte1 >= font->min_byte1
2428 && char2b->byte1 <= font->max_byte1
2429 && char2b->byte2 >= font->min_char_or_byte2
2430 && char2b->byte2 <= font->max_char_or_byte2)
2431 {
b73e4d84 2432 pcm = (font->bounds.per_char
1a578e9b
AC
2433 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2434 * (char2b->byte1 - font->min_byte1))
2435 + (char2b->byte2 - font->min_char_or_byte2));
2436 }
2437 }
2438 }
2439 else
2440 {
2441 /* If the per_char pointer is null, all glyphs between the first
2442 and last character indexes inclusive have the same
2443 information, as given by both min_bounds and max_bounds. */
2444 if (char2b->byte2 >= font->min_char_or_byte2
2445 && char2b->byte2 <= font->max_char_or_byte2)
2446 pcm = &font->max_bounds;
2447 }
c3bd8190
YM
2448#if USE_ATSUI
2449 }
2450#endif
1a578e9b
AC
2451
2452 return ((pcm == NULL
a0c62ca2
YM
2453 || (pcm->width == 0
2454#if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2455 && (pcm->rbearing - pcm->lbearing) == 0
2456#endif
2457 ))
1a578e9b
AC
2458 ? NULL : pcm);
2459}
2460
750fc673
KS
2461/* RIF:
2462 */
2463
2464static XCharStruct *
2465mac_per_char_metric (font, char2b, font_type)
2466 XFontStruct *font;
2467 XChar2b *char2b;
2468 int font_type;
2469{
2470 return x_per_char_metric (font, char2b);
2471}
1a578e9b 2472
750fc673
KS
2473/* RIF:
2474 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1a578e9b
AC
2475 the two-byte form of C. Encoding is returned in *CHAR2B. */
2476
750fc673
KS
2477static int
2478mac_encode_char (c, char2b, font_info, two_byte_p)
1a578e9b
AC
2479 int c;
2480 XChar2b *char2b;
2481 struct font_info *font_info;
750fc673 2482 int *two_byte_p;
1a578e9b
AC
2483{
2484 int charset = CHAR_CHARSET (c);
2485 XFontStruct *font = font_info->font;
2486
2487 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2488 This may be either a program in a special encoder language or a
2489 fixed encoding. */
2490 if (font_info->font_encoder)
2491 {
2492 /* It's a program. */
2493 struct ccl_program *ccl = font_info->font_encoder;
2494
dd15724d 2495 check_ccl_update (ccl);
1a578e9b
AC
2496 if (CHARSET_DIMENSION (charset) == 1)
2497 {
2498 ccl->reg[0] = charset;
2499 ccl->reg[1] = char2b->byte2;
dd15724d 2500 ccl->reg[2] = -1;
1a578e9b
AC
2501 }
2502 else
2503 {
2504 ccl->reg[0] = charset;
2505 ccl->reg[1] = char2b->byte1;
2506 ccl->reg[2] = char2b->byte2;
2507 }
177c0ea7 2508
1a578e9b 2509 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
177c0ea7 2510
1a578e9b
AC
2511 /* We assume that MSBs are appropriately set/reset by CCL
2512 program. */
2513 if (font->max_byte1 == 0) /* 1-byte font */
2514 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2515 else
2516 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2517 }
2518 else if (font_info->encoding[charset])
2519 {
2520 /* Fixed encoding scheme. See fontset.h for the meaning of the
2521 encoding numbers. */
2522 int enc = font_info->encoding[charset];
177c0ea7 2523
1a578e9b
AC
2524 if ((enc == 1 || enc == 2)
2525 && CHARSET_DIMENSION (charset) == 2)
2526 char2b->byte1 |= 0x80;
177c0ea7 2527
1a578e9b
AC
2528 if (enc == 1 || enc == 3)
2529 char2b->byte2 |= 0x80;
2530
2531 if (enc == 4)
2532 {
2533 int sjis1, sjis2;
2534
2535 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2536 char2b->byte1 = sjis1;
2537 char2b->byte2 = sjis2;
2538 }
2539 }
1a578e9b
AC
2540
2541 if (two_byte_p)
750fc673 2542 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1a578e9b 2543
750fc673 2544 return FONT_TYPE_UNKNOWN;
1a578e9b
AC
2545}
2546
2547
1a578e9b
AC
2548\f
2549/***********************************************************************
2550 Glyph display
2551 ***********************************************************************/
2552
1a578e9b 2553
95dfb192 2554
1a578e9b
AC
2555static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2556static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2557static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2558 int));
2559static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2560static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2561static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2562static void x_draw_glyph_string P_ ((struct glyph_string *));
95dfb192 2563static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
1a578e9b
AC
2564static void x_set_cursor_gc P_ ((struct glyph_string *));
2565static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2566static void x_set_mouse_face_gc P_ ((struct glyph_string *));
e0f712ba
AC
2567/*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2568 unsigned long *, double, int));*/
1a578e9b
AC
2569static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2570 double, int, unsigned long));
2571static void x_setup_relief_colors P_ ((struct glyph_string *));
2572static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2573static void x_draw_image_relief P_ ((struct glyph_string *));
2574static void x_draw_image_foreground P_ ((struct glyph_string *));
1a578e9b
AC
2575static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2576 int, int, int));
2577static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
ffe8b3f4
KS
2578 int, int, int, int, int, int,
2579 Rect *));
1a578e9b 2580static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
e0f712ba 2581 int, int, int, Rect *));
1a578e9b
AC
2582
2583#if GLYPH_DEBUG
2584static void x_check_font P_ ((struct frame *, XFontStruct *));
2585#endif
2586
177c0ea7 2587
1a578e9b
AC
2588/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2589 face. */
2590
2591static void
2592x_set_cursor_gc (s)
2593 struct glyph_string *s;
2594{
2595 if (s->font == FRAME_FONT (s->f)
2596 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2597 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2598 && !s->cmp)
2599 s->gc = s->f->output_data.mac->cursor_gc;
2600 else
2601 {
2602 /* Cursor on non-default face: must merge. */
2603 XGCValues xgcv;
2604 unsigned long mask;
2605
2606 xgcv.background = s->f->output_data.mac->cursor_pixel;
2607 xgcv.foreground = s->face->background;
2608
2609 /* If the glyph would be invisible, try a different foreground. */
2610 if (xgcv.foreground == xgcv.background)
2611 xgcv.foreground = s->face->foreground;
2612 if (xgcv.foreground == xgcv.background)
2613 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2614 if (xgcv.foreground == xgcv.background)
2615 xgcv.foreground = s->face->foreground;
2616
2617 /* Make sure the cursor is distinct from text in this face. */
2618 if (xgcv.background == s->face->background
2619 && xgcv.foreground == s->face->foreground)
2620 {
2621 xgcv.background = s->face->foreground;
2622 xgcv.foreground = s->face->background;
2623 }
2624
2625 IF_DEBUG (x_check_font (s->f, s->font));
2626 xgcv.font = s->font;
2627 mask = GCForeground | GCBackground | GCFont;
2628
2629 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2630 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2631 mask, &xgcv);
2632 else
2633 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2634 = XCreateGC (s->display, s->window, mask, &xgcv);
2635
2636 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2637 }
2638}
2639
2640
2641/* Set up S->gc of glyph string S for drawing text in mouse face. */
177c0ea7 2642
1a578e9b
AC
2643static void
2644x_set_mouse_face_gc (s)
2645 struct glyph_string *s;
177c0ea7 2646{
1a578e9b
AC
2647 int face_id;
2648 struct face *face;
2649
e0f712ba 2650 /* What face has to be used last for the mouse face? */
1a578e9b
AC
2651 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2652 face = FACE_FROM_ID (s->f, face_id);
e0f712ba
AC
2653 if (face == NULL)
2654 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
177c0ea7 2655
1a578e9b
AC
2656 if (s->first_glyph->type == CHAR_GLYPH)
2657 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2658 else
2659 face_id = FACE_FOR_CHAR (s->f, face, 0);
2660 s->face = FACE_FROM_ID (s->f, face_id);
2661 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2662
2663 /* If font in this face is same as S->font, use it. */
2664 if (s->font == s->face->font)
2665 s->gc = s->face->gc;
2666 else
2667 {
2668 /* Otherwise construct scratch_cursor_gc with values from FACE
2669 but font FONT. */
2670 XGCValues xgcv;
2671 unsigned long mask;
177c0ea7 2672
1a578e9b
AC
2673 xgcv.background = s->face->background;
2674 xgcv.foreground = s->face->foreground;
2675 IF_DEBUG (x_check_font (s->f, s->font));
2676 xgcv.font = s->font;
2677 mask = GCForeground | GCBackground | GCFont;
177c0ea7 2678
1a578e9b
AC
2679 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2680 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2681 mask, &xgcv);
2682 else
2683 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2684 = XCreateGC (s->display, s->window, mask, &xgcv);
177c0ea7 2685
1a578e9b
AC
2686 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2687 }
2688
2689 xassert (s->gc != 0);
2690}
2691
2692
2693/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2694 Faces to use in the mode line have already been computed when the
2695 matrix was built, so there isn't much to do, here. */
2696
2697static INLINE void
2698x_set_mode_line_face_gc (s)
2699 struct glyph_string *s;
177c0ea7 2700{
1a578e9b
AC
2701 s->gc = s->face->gc;
2702}
2703
2704
2705/* Set S->gc of glyph string S for drawing that glyph string. Set
2706 S->stippled_p to a non-zero value if the face of S has a stipple
2707 pattern. */
2708
2709static INLINE void
2710x_set_glyph_string_gc (s)
2711 struct glyph_string *s;
2712{
2713 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
177c0ea7 2714
1a578e9b
AC
2715 if (s->hl == DRAW_NORMAL_TEXT)
2716 {
2717 s->gc = s->face->gc;
2718 s->stippled_p = s->face->stipple != 0;
2719 }
2720 else if (s->hl == DRAW_INVERSE_VIDEO)
2721 {
2722 x_set_mode_line_face_gc (s);
2723 s->stippled_p = s->face->stipple != 0;
2724 }
2725 else if (s->hl == DRAW_CURSOR)
2726 {
2727 x_set_cursor_gc (s);
2728 s->stippled_p = 0;
2729 }
2730 else if (s->hl == DRAW_MOUSE_FACE)
2731 {
2732 x_set_mouse_face_gc (s);
2733 s->stippled_p = s->face->stipple != 0;
2734 }
2735 else if (s->hl == DRAW_IMAGE_RAISED
2736 || s->hl == DRAW_IMAGE_SUNKEN)
2737 {
2738 s->gc = s->face->gc;
2739 s->stippled_p = s->face->stipple != 0;
2740 }
2741 else
2742 {
2743 s->gc = s->face->gc;
2744 s->stippled_p = s->face->stipple != 0;
2745 }
2746
2747 /* GC must have been set. */
2748 xassert (s->gc != 0);
2749}
2750
2751
1a578e9b
AC
2752/* Set clipping for output of glyph string S. S may be part of a mode
2753 line or menu if we don't have X toolkit support. */
2754
2755static INLINE void
2756x_set_glyph_string_clipping (s)
2757 struct glyph_string *s;
2758{
1c4ac540
YM
2759 Rect rects[MAX_CLIP_RECTS];
2760 int n;
2761
2762 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
834263b6 2763 mac_set_clip_rectangles (s->f, s->gc, rects, n);
1a578e9b
AC
2764}
2765
2766
750fc673
KS
2767/* RIF:
2768 Compute left and right overhang of glyph string S. If S is a glyph
1a578e9b
AC
2769 string for a composition, assume overhangs don't exist. */
2770
750fc673
KS
2771static void
2772mac_compute_glyph_string_overhangs (s)
1a578e9b
AC
2773 struct glyph_string *s;
2774{
f93e4d4f
YM
2775 if (!(s->cmp == NULL
2776 && s->first_glyph->type == CHAR_GLYPH))
2777 return;
2778
2779 if (!s->two_byte_p
c3bd8190 2780#if USE_ATSUI
f93e4d4f 2781 || s->font->mac_style
b73e4d84 2782#endif
f93e4d4f
YM
2783 )
2784 {
2785 XCharStruct cs;
c3bd8190 2786
f93e4d4f
YM
2787 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2788 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2789 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2790 }
2791 else
2792 {
2793 Rect r;
2794 MacFontStruct *font = s->font;
c3bd8190 2795
f2ec385e 2796 mac_begin_clip (s->f, NULL);
444a42fd 2797
f93e4d4f
YM
2798 TextFont (font->mac_fontnum);
2799 TextSize (font->mac_fontsize);
2800 TextFace (font->mac_fontface);
95085023 2801
f93e4d4f 2802 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
8c2da0fa 2803
f2ec385e
YM
2804 mac_end_clip (s->f, NULL);
2805
f93e4d4f
YM
2806 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2807 s->left_overhang = r.left < 0 ? -r.left : 0;
2808 }
1a578e9b
AC
2809}
2810
2811
2812/* Fill rectangle X, Y, W, H with background color of glyph string S. */
2813
2814static INLINE void
2815x_clear_glyph_string_rect (s, x, y, w, h)
2816 struct glyph_string *s;
2817 int x, y, w, h;
2818{
236072ae 2819 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
1a578e9b
AC
2820}
2821
2822
2823/* Draw the background of glyph_string S. If S->background_filled_p
2824 is non-zero don't draw it. FORCE_P non-zero means draw the
2825 background even if it wouldn't be drawn normally. This is used
2826 when a string preceding S draws into the background of S, or S
2827 contains the first component of a composition. */
2828
2829static void
2830x_draw_glyph_string_background (s, force_p)
2831 struct glyph_string *s;
2832 int force_p;
2833{
2834 /* Nothing to do if background has already been drawn or if it
2835 shouldn't be drawn in the first place. */
2836 if (!s->background_filled_p)
2837 {
e0f712ba
AC
2838 int box_line_width = max (s->face->box_line_width, 0);
2839
1a578e9b
AC
2840#if 0 /* MAC_TODO: stipple */
2841 if (s->stippled_p)
2842 {
2843 /* Fill background with a stipple pattern. */
2844 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2845 XFillRectangle (s->display, s->window, s->gc, s->x,
e0f712ba 2846 s->y + box_line_width,
1a578e9b 2847 s->background_width,
e0f712ba 2848 s->height - 2 * box_line_width);
1a578e9b
AC
2849 XSetFillStyle (s->display, s->gc, FillSolid);
2850 s->background_filled_p = 1;
2851 }
2852 else
2853#endif
e0f712ba 2854 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1a578e9b
AC
2855 || s->font_not_found_p
2856 || s->extends_to_end_of_line_p
2857 || force_p)
2858 {
e0f712ba 2859 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1a578e9b 2860 s->background_width,
e0f712ba 2861 s->height - 2 * box_line_width);
1a578e9b
AC
2862 s->background_filled_p = 1;
2863 }
2864 }
2865}
2866
2867
2868/* Draw the foreground of glyph string S. */
2869
2870static void
2871x_draw_glyph_string_foreground (s)
2872 struct glyph_string *s;
2873{
9fb446e3 2874 int i, x, bg_width;
1a578e9b
AC
2875
2876 /* If first glyph of S has a left box line, start drawing the text
2877 of S to the right of that box line. */
2878 if (s->face->box != FACE_NO_BOX
2879 && s->first_glyph->left_box_line_p)
e0f712ba 2880 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
2881 else
2882 x = s->x;
2883
2884 /* Draw characters of S as rectangles if S's font could not be
2885 loaded. */
2886 if (s->font_not_found_p)
2887 {
2888 for (i = 0; i < s->nchars; ++i)
2889 {
2890 struct glyph *g = s->first_glyph + i;
236072ae 2891 mac_draw_rectangle (s->f, s->gc, x, s->y,
4ea08bbf 2892 g->pixel_width - 1, s->height - 1);
1a578e9b
AC
2893 x += g->pixel_width;
2894 }
2895 }
2896 else
2897 {
2898 char *char1b = (char *) s->char2b;
2899 int boff = s->font_info->baseline_offset;
2900
2901 if (s->font_info->vertical_centering)
2902 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2903
2904 /* If we can use 8-bit functions, condense S->char2b. */
c3bd8190
YM
2905 if (!s->two_byte_p
2906#if USE_ATSUI
2907 && GC_FONT (s->gc)->mac_style == NULL
2908#endif
2909 )
1a578e9b
AC
2910 for (i = 0; i < s->nchars; ++i)
2911 char1b[i] = s->char2b[i].byte2;
2912
2913 /* Draw text with XDrawString if background has already been
2914 filled. Otherwise, use XDrawImageString. (Note that
2915 XDrawImageString is usually faster than XDrawString.) Always
2916 use XDrawImageString when drawing the cursor so that there is
2917 no chance that characters under a box cursor are invisible. */
c2ded1b7 2918 if (s->for_overlaps
1a578e9b 2919 || (s->background_filled_p && s->hl != DRAW_CURSOR))
9fb446e3
YM
2920 bg_width = 0; /* Corresponds to XDrawString. */
2921 else
2922 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
2923
2924 if (s->two_byte_p
c3bd8190 2925#if USE_ATSUI
9fb446e3 2926 || GC_FONT (s->gc)->mac_style
c3bd8190 2927#endif
9fb446e3 2928 )
16805b2e 2929#if USE_CG_TEXT_DRAWING
9fb446e3
YM
2930 if (!s->two_byte_p
2931 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
bb420759
YM
2932 s->char2b, s->nchars, bg_width,
2933 s->face->overstrike))
9fb446e3
YM
2934 ;
2935 else
16805b2e 2936#endif
9fb446e3 2937 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
bb420759
YM
2938 s->char2b, s->nchars, bg_width,
2939 s->face->overstrike);
1a578e9b 2940 else
9fb446e3 2941 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
bb420759
YM
2942 char1b, s->nchars, bg_width,
2943 s->face->overstrike);
1a578e9b
AC
2944 }
2945}
2946
2947/* Draw the foreground of composite glyph string S. */
2948
2949static void
2950x_draw_composite_glyph_string_foreground (s)
2951 struct glyph_string *s;
2952{
2953 int i, x;
2954
2955 /* If first glyph of S has a left box line, start drawing the text
2956 of S to the right of that box line. */
2957 if (s->face->box != FACE_NO_BOX
2958 && s->first_glyph->left_box_line_p)
e0f712ba 2959 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
2960 else
2961 x = s->x;
2962
2963 /* S is a glyph string for a composition. S->gidx is the index of
2964 the first character drawn for glyphs of this composition.
2965 S->gidx == 0 means we are drawing the very first character of
2966 this composition. */
2967
2968 /* Draw a rectangle for the composition if the font for the very
2969 first character of the composition could not be loaded. */
2970 if (s->font_not_found_p)
2971 {
2972 if (s->gidx == 0)
236072ae 2973 mac_draw_rectangle (s->f, s->gc, x, s->y,
4ea08bbf 2974 s->width - 1, s->height - 1);
1a578e9b
AC
2975 }
2976 else
2977 {
2978 for (i = 0; i < s->nchars; i++, ++s->gidx)
769174c4
YM
2979 if (mac_per_char_metric (GC_FONT (s->gc), s->char2b + i, 0) == NULL)
2980 /* This is a nonexistent or zero-width glyph such as a
2981 combining diacritic. Draw a rectangle. */
2982 mac_draw_rectangle (s->f, s->gc,
2983 x + s->cmp->offsets[s->gidx * 2], s->y,
2984 FONT_WIDTH (GC_FONT (s->gc)) - 1, s->height - 1);
2985 else
2986 mac_draw_image_string_16 (s->f, s->gc,
2987 x + s->cmp->offsets[s->gidx * 2],
2988 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2989 s->char2b + i, 1, 0, s->face->overstrike);
1a578e9b
AC
2990 }
2991}
2992
2993
2994#ifdef USE_X_TOOLKIT
2995
2996static struct frame *x_frame_of_widget P_ ((Widget));
2997
2998
2999/* Return the frame on which widget WIDGET is used.. Abort if frame
3000 cannot be determined. */
3001
3002static struct frame *
3003x_frame_of_widget (widget)
3004 Widget widget;
3005{
3006 struct x_display_info *dpyinfo;
3007 Lisp_Object tail;
3008 struct frame *f;
177c0ea7 3009
1a578e9b 3010 dpyinfo = x_display_info_for_display (XtDisplay (widget));
177c0ea7 3011
1a578e9b
AC
3012 /* Find the top-level shell of the widget. Note that this function
3013 can be called when the widget is not yet realized, so XtWindow
3014 (widget) == 0. That's the reason we can't simply use
3015 x_any_window_to_frame. */
3016 while (!XtIsTopLevelShell (widget))
3017 widget = XtParent (widget);
3018
3019 /* Look for a frame with that top-level widget. Allocate the color
3020 on that frame to get the right gamma correction value. */
3021 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3022 if (GC_FRAMEP (XCAR (tail))
3023 && (f = XFRAME (XCAR (tail)),
3024 (f->output_data.nothing != 1
3025 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3026 && f->output_data.x->widget == widget)
3027 return f;
3028
3029 abort ();
3030}
3031
3032
3033/* Allocate the color COLOR->pixel on the screen and display of
3034 widget WIDGET in colormap CMAP. If an exact match cannot be
3035 allocated, try the nearest color available. Value is non-zero
3036 if successful. This is called from lwlib. */
3037
3038int
3039x_alloc_nearest_color_for_widget (widget, cmap, color)
3040 Widget widget;
3041 Colormap cmap;
3042 XColor *color;
3043{
3044 struct frame *f = x_frame_of_widget (widget);
3045 return x_alloc_nearest_color (f, cmap, color);
3046}
3047
3048
3049#endif /* USE_X_TOOLKIT */
3050
e0f712ba 3051#if 0 /* MAC_TODO */
1a578e9b
AC
3052
3053/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3054 CMAP. If an exact match can't be allocated, try the nearest color
3055 available. Value is non-zero if successful. Set *COLOR to the
3056 color allocated. */
3057
3058int
3059x_alloc_nearest_color (f, cmap, color)
3060 struct frame *f;
3061 Colormap cmap;
3062 XColor *color;
3063{
3064 Display *display = FRAME_X_DISPLAY (f);
3065 Screen *screen = FRAME_X_SCREEN (f);
3066 int rc;
3067
3068 gamma_correct (f, color);
3069 rc = XAllocColor (display, cmap, color);
3070 if (rc == 0)
3071 {
3072 /* If we got to this point, the colormap is full, so we're going
3073 to try to get the next closest color. The algorithm used is
3074 a least-squares matching, which is what X uses for closest
3075 color matching with StaticColor visuals. */
3076 int nearest, i;
3077 unsigned long nearest_delta = ~0;
3078 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3079 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3080
3081 for (i = 0; i < ncells; ++i)
3082 cells[i].pixel = i;
3083 XQueryColors (display, cmap, cells, ncells);
3084
3085 for (nearest = i = 0; i < ncells; ++i)
3086 {
3087 long dred = (color->red >> 8) - (cells[i].red >> 8);
3088 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3089 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3090 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3091
3092 if (delta < nearest_delta)
3093 {
3094 nearest = i;
3095 nearest_delta = delta;
3096 }
3097 }
177c0ea7 3098
1a578e9b
AC
3099 color->red = cells[nearest].red;
3100 color->green = cells[nearest].green;
3101 color->blue = cells[nearest].blue;
3102 rc = XAllocColor (display, cmap, color);
3103 }
3104
3105#ifdef DEBUG_X_COLORS
3106 if (rc)
3107 register_color (color->pixel);
3108#endif /* DEBUG_X_COLORS */
177c0ea7 3109
1a578e9b
AC
3110 return rc;
3111}
3112
3113
3114/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3115 It's necessary to do this instead of just using PIXEL directly to
3116 get color reference counts right. */
3117
3118unsigned long
3119x_copy_color (f, pixel)
3120 struct frame *f;
3121 unsigned long pixel;
3122{
3123 XColor color;
3124
3125 color.pixel = pixel;
3126 BLOCK_INPUT;
3127 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3128 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3129 UNBLOCK_INPUT;
3130#ifdef DEBUG_X_COLORS
3131 register_color (pixel);
3132#endif
3133 return color.pixel;
3134}
3135
3136
3137/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3138 It's necessary to do this instead of just using PIXEL directly to
3139 get color reference counts right. */
3140
3141unsigned long
3142x_copy_dpy_color (dpy, cmap, pixel)
3143 Display *dpy;
3144 Colormap cmap;
3145 unsigned long pixel;
3146{
3147 XColor color;
3148
3149 color.pixel = pixel;
3150 BLOCK_INPUT;
3151 XQueryColor (dpy, cmap, &color);
3152 XAllocColor (dpy, cmap, &color);
3153 UNBLOCK_INPUT;
3154#ifdef DEBUG_X_COLORS
3155 register_color (pixel);
3156#endif
3157 return color.pixel;
3158}
3159
e0f712ba 3160#endif /* MAC_TODO */
1a578e9b 3161
e3564461
ST
3162
3163/* Brightness beyond which a color won't have its highlight brightness
3164 boosted.
3165
3166 Nominally, highlight colors for `3d' faces are calculated by
3167 brightening an object's color by a constant scale factor, but this
3168 doesn't yield good results for dark colors, so for colors who's
3169 brightness is less than this value (on a scale of 0-255) have to
3170 use an additional additive factor.
3171
3172 The value here is set so that the default menu-bar/mode-line color
3173 (grey75) will not have its highlights changed at all. */
3174#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3175
3176
1a578e9b
AC
3177/* Allocate a color which is lighter or darker than *COLOR by FACTOR
3178 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3179 If this produces the same color as COLOR, try a color where all RGB
3180 values have DELTA added. Return the allocated color in *COLOR.
3181 DISPLAY is the X display, CMAP is the colormap to operate on.
3182 Value is non-zero if successful. */
3183
3184static int
3185mac_alloc_lighter_color (f, color, factor, delta)
3186 struct frame *f;
3187 unsigned long *color;
3188 double factor;
3189 int delta;
3190{
3191 unsigned long new;
e3564461
ST
3192 long bright;
3193
3194 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3195 delta /= 256;
1a578e9b
AC
3196
3197 /* Change RGB values by specified FACTOR. Avoid overflow! */
3198 xassert (factor >= 0);
3199 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3200 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3201 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
e3564461
ST
3202
3203 /* Calculate brightness of COLOR. */
3204 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3205 + BLUE_FROM_ULONG (*color)) / 6;
3206
3207 /* We only boost colors that are darker than
3208 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3209 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3210 /* Make an additive adjustment to NEW, because it's dark enough so
3211 that scaling by FACTOR alone isn't enough. */
3212 {
3213 /* How far below the limit this color is (0 - 1, 1 being darker). */
3214 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3215 /* The additive adjustment. */
3216 int min_delta = delta * dimness * factor / 2;
3217
3218 if (factor < 1)
3219 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3220 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3221 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3222 else
3223 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3224 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3225 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3226 }
3227
1a578e9b
AC
3228 if (new == *color)
3229 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3230 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3231 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3232
3233 /* MAC_TODO: Map to palette and retry with delta if same? */
3234 /* MAC_TODO: Free colors (if using palette)? */
3235
3236 if (new == *color)
3237 return 0;
3238
3239 *color = new;
3240
3241 return 1;
3242}
3243
3244
3245/* Set up the foreground color for drawing relief lines of glyph
3246 string S. RELIEF is a pointer to a struct relief containing the GC
3247 with which lines will be drawn. Use a color that is FACTOR or
3248 DELTA lighter or darker than the relief's background which is found
3249 in S->f->output_data.x->relief_background. If such a color cannot
3250 be allocated, use DEFAULT_PIXEL, instead. */
177c0ea7 3251
1a578e9b
AC
3252static void
3253x_setup_relief_color (f, relief, factor, delta, default_pixel)
3254 struct frame *f;
3255 struct relief *relief;
3256 double factor;
3257 int delta;
3258 unsigned long default_pixel;
3259{
3260 XGCValues xgcv;
3261 struct mac_output *di = f->output_data.mac;
3262 unsigned long mask = GCForeground;
3263 unsigned long pixel;
3264 unsigned long background = di->relief_background;
3265 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3266
3267 /* MAC_TODO: Free colors (if using palette)? */
3268
3269 /* Allocate new color. */
3270 xgcv.foreground = default_pixel;
3271 pixel = background;
e3564461
ST
3272 if (dpyinfo->n_planes != 1
3273 && mac_alloc_lighter_color (f, &pixel, factor, delta))
1a578e9b
AC
3274 {
3275 relief->allocated_p = 1;
3276 xgcv.foreground = relief->pixel = pixel;
3277 }
177c0ea7 3278
1a578e9b
AC
3279 if (relief->gc == 0)
3280 {
3281#if 0 /* MAC_TODO: stipple */
3282 xgcv.stipple = dpyinfo->gray;
3283 mask |= GCStipple;
3284#endif
3285 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3286 }
3287 else
3288 XChangeGC (NULL, relief->gc, mask, &xgcv);
3289}
3290
3291
3292/* Set up colors for the relief lines around glyph string S. */
3293
3294static void
3295x_setup_relief_colors (s)
3296 struct glyph_string *s;
3297{
3298 struct mac_output *di = s->f->output_data.mac;
3299 unsigned long color;
3300
3301 if (s->face->use_box_color_for_shadows_p)
3302 color = s->face->box_color;
e3564461
ST
3303 else if (s->first_glyph->type == IMAGE_GLYPH
3304 && s->img->pixmap
3305 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3306 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1a578e9b
AC
3307 else
3308 {
3309 XGCValues xgcv;
177c0ea7 3310
1a578e9b
AC
3311 /* Get the background color of the face. */
3312 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3313 color = xgcv.background;
3314 }
3315
3316 if (di->white_relief.gc == 0
3317 || color != di->relief_background)
3318 {
3319 di->relief_background = color;
3320 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3321 WHITE_PIX_DEFAULT (s->f));
3322 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3323 BLACK_PIX_DEFAULT (s->f));
3324 }
3325}
3326
3327
3328/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3329 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3330 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3331 relief. LEFT_P non-zero means draw a relief on the left side of
3332 the rectangle. RIGHT_P non-zero means draw a relief on the right
3333 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3334 when drawing. */
3335
3336static void
3337x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
ffe8b3f4 3338 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
1a578e9b 3339 struct frame *f;
ffe8b3f4
KS
3340 int left_x, top_y, right_x, bottom_y, width;
3341 int top_p, bot_p, left_p, right_p, raised_p;
1a578e9b
AC
3342 Rect *clip_rect;
3343{
3344 int i;
3345 GC gc;
177c0ea7 3346
1a578e9b
AC
3347 if (raised_p)
3348 gc = f->output_data.mac->white_relief.gc;
3349 else
3350 gc = f->output_data.mac->black_relief.gc;
834263b6 3351 mac_set_clip_rectangles (f, gc, clip_rect, 1);
1a578e9b
AC
3352
3353 /* Top. */
ffe8b3f4
KS
3354 if (top_p)
3355 for (i = 0; i < width; ++i)
236072ae
YM
3356 mac_draw_line (f, gc,
3357 left_x + i * left_p, top_y + i,
458dbb8c 3358 right_x + 1 - i * right_p, top_y + i);
1a578e9b
AC
3359
3360 /* Left. */
3361 if (left_p)
3362 for (i = 0; i < width; ++i)
236072ae 3363 mac_draw_line (f, gc,
458dbb8c 3364 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
1a578e9b 3365
834263b6 3366 mac_reset_clip_rectangles (f, gc);
1a578e9b
AC
3367 if (raised_p)
3368 gc = f->output_data.mac->black_relief.gc;
3369 else
3370 gc = f->output_data.mac->white_relief.gc;
834263b6 3371 mac_set_clip_rectangles (f, gc, clip_rect, 1);
177c0ea7 3372
1a578e9b 3373 /* Bottom. */
ffe8b3f4
KS
3374 if (bot_p)
3375 for (i = 0; i < width; ++i)
236072ae
YM
3376 mac_draw_line (f, gc,
3377 left_x + i * left_p, bottom_y - i,
458dbb8c 3378 right_x + 1 - i * right_p, bottom_y - i);
177c0ea7 3379
1a578e9b
AC
3380 /* Right. */
3381 if (right_p)
3382 for (i = 0; i < width; ++i)
236072ae 3383 mac_draw_line (f, gc,
458dbb8c 3384 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
1a578e9b 3385
834263b6 3386 mac_reset_clip_rectangles (f, gc);
1a578e9b
AC
3387}
3388
3389
3390/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3391 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3392 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3393 left side of the rectangle. RIGHT_P non-zero means draw a line
3394 on the right side of the rectangle. CLIP_RECT is the clipping
3395 rectangle to use when drawing. */
3396
3397static void
3398x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3399 left_p, right_p, clip_rect)
3400 struct glyph_string *s;
e3564461 3401 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
1a578e9b
AC
3402 Rect *clip_rect;
3403{
3404 XGCValues xgcv;
177c0ea7 3405
e4f5e019
YM
3406 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3407 XSetForeground (s->display, s->gc, s->face->box_color);
834263b6 3408 mac_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
177c0ea7 3409
1a578e9b 3410 /* Top. */
236072ae
YM
3411 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3412 right_x - left_x + 1, width);
1a578e9b
AC
3413
3414 /* Left. */
3415 if (left_p)
236072ae
YM
3416 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3417 width, bottom_y - top_y + 1);
1a578e9b
AC
3418
3419 /* Bottom. */
236072ae
YM
3420 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3421 right_x - left_x + 1, width);
177c0ea7 3422
1a578e9b
AC
3423 /* Right. */
3424 if (right_p)
236072ae
YM
3425 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3426 top_y, width, bottom_y - top_y + 1);
1a578e9b 3427
e4f5e019 3428 XSetForeground (s->display, s->gc, xgcv.foreground);
834263b6 3429 mac_reset_clip_rectangles (s->f, s->gc);
1a578e9b
AC
3430}
3431
3432
3433/* Draw a box around glyph string S. */
3434
3435static void
3436x_draw_glyph_string_box (s)
3437 struct glyph_string *s;
3438{
3439 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3440 int left_p, right_p;
3441 struct glyph *last_glyph;
3442 Rect clip_rect;
3443
82ead4b1
KS
3444 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3445 ? WINDOW_RIGHT_EDGE_X (s->w)
3446 : window_box_right (s->w, s->area));
177c0ea7 3447
1a578e9b
AC
3448 /* The glyph that may have a right box line. */
3449 last_glyph = (s->cmp || s->img
3450 ? s->first_glyph
3451 : s->first_glyph + s->nchars - 1);
3452
e0f712ba 3453 width = abs (s->face->box_line_width);
1a578e9b
AC
3454 raised_p = s->face->box == FACE_RAISED_BOX;
3455 left_x = s->x;
e3564461
ST
3456 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3457 ? last_x - 1
3458 : min (last_x, s->x + s->background_width) - 1);
1a578e9b
AC
3459 top_y = s->y;
3460 bottom_y = top_y + s->height - 1;
3461
3462 left_p = (s->first_glyph->left_box_line_p
3463 || (s->hl == DRAW_MOUSE_FACE
3464 && (s->prev == NULL
3465 || s->prev->hl != s->hl)));
3466 right_p = (last_glyph->right_box_line_p
3467 || (s->hl == DRAW_MOUSE_FACE
3468 && (s->next == NULL
3469 || s->next->hl != s->hl)));
177c0ea7 3470
f9e65eb3 3471 get_glyph_string_clip_rect (s, &clip_rect);
1a578e9b
AC
3472
3473 if (s->face->box == FACE_SIMPLE_BOX)
3474 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3475 left_p, right_p, &clip_rect);
3476 else
3477 {
3478 x_setup_relief_colors (s);
3479 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
ffe8b3f4 3480 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
1a578e9b
AC
3481 }
3482}
3483
3484
3485/* Draw foreground of image glyph string S. */
3486
3487static void
3488x_draw_image_foreground (s)
3489 struct glyph_string *s;
3490{
ffe8b3f4
KS
3491 int x = s->x;
3492 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1a578e9b
AC
3493
3494 /* If first glyph of S has a left box line, start drawing it to the
3495 right of that line. */
3496 if (s->face->box != FACE_NO_BOX
ffe8b3f4
KS
3497 && s->first_glyph->left_box_line_p
3498 && s->slice.x == 0)
3499 x += abs (s->face->box_line_width);
1a578e9b
AC
3500
3501 /* If there is a margin around the image, adjust x- and y-position
3502 by that margin. */
ffe8b3f4
KS
3503 if (s->slice.x == 0)
3504 x += s->img->hmargin;
3505 if (s->slice.y == 0)
3506 y += s->img->vmargin;
1a578e9b
AC
3507
3508 if (s->img->pixmap)
3509 {
fc7a70cc
ST
3510 x_set_glyph_string_clipping (s);
3511
e09ce637
YM
3512#if USE_CG_DRAWING
3513 mac_draw_cg_image (s->img->data.ptr_val,
3514 s->f, s->gc, s->slice.x, s->slice.y,
3515 s->slice.width, s->slice.height, x, y, 1);
3516#endif
1a578e9b 3517 if (s->img->mask)
e09ce637 3518#if !USE_CG_DRAWING
236072ae
YM
3519 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3520 s->f, s->gc, s->slice.x, s->slice.y,
fc7a70cc 3521 s->slice.width, s->slice.height, x, y);
e09ce637
YM
3522#else
3523 ;
3524#endif
1a578e9b 3525 else
1a578e9b 3526 {
e09ce637 3527#if !USE_CG_DRAWING
236072ae
YM
3528 mac_copy_area (s->img->pixmap,
3529 s->f, s->gc, s->slice.x, s->slice.y,
fc7a70cc 3530 s->slice.width, s->slice.height, x, y);
e09ce637 3531#endif
177c0ea7 3532
1a578e9b
AC
3533 /* When the image has a mask, we can expect that at
3534 least part of a mouse highlight or a block cursor will
3535 be visible. If the image doesn't have a mask, make
3536 a block cursor visible by drawing a rectangle around
3537 the image. I believe it's looking better if we do
3538 nothing here for mouse-face. */
3539 if (s->hl == DRAW_CURSOR)
534c20b2
KS
3540 {
3541 int r = s->img->relief;
3542 if (r < 0) r = -r;
236072ae 3543 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
4ea08bbf
YM
3544 s->slice.width + r*2 - 1,
3545 s->slice.height + r*2 - 1);
534c20b2 3546 }
1a578e9b
AC
3547 }
3548 }
3549 else
3550 /* Draw a rectangle if image could not be loaded. */
236072ae 3551 mac_draw_rectangle (s->f, s->gc, x, y,
4ea08bbf 3552 s->slice.width - 1, s->slice.height - 1);
1a578e9b
AC
3553}
3554
3555
3556/* Draw a relief around the image glyph string S. */
3557
3558static void
3559x_draw_image_relief (s)
3560 struct glyph_string *s;
3561{
3562 int x0, y0, x1, y1, thick, raised_p;
3563 Rect r;
ffe8b3f4
KS
3564 int x = s->x;
3565 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
177c0ea7 3566
1a578e9b
AC
3567 /* If first glyph of S has a left box line, start drawing it to the
3568 right of that line. */
3569 if (s->face->box != FACE_NO_BOX
ffe8b3f4
KS
3570 && s->first_glyph->left_box_line_p
3571 && s->slice.x == 0)
3572 x += abs (s->face->box_line_width);
177c0ea7 3573
1a578e9b
AC
3574 /* If there is a margin around the image, adjust x- and y-position
3575 by that margin. */
ffe8b3f4
KS
3576 if (s->slice.x == 0)
3577 x += s->img->hmargin;
3578 if (s->slice.y == 0)
3579 y += s->img->vmargin;
177c0ea7 3580
1a578e9b
AC
3581 if (s->hl == DRAW_IMAGE_SUNKEN
3582 || s->hl == DRAW_IMAGE_RAISED)
3583 {
e0f712ba 3584 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1a578e9b
AC
3585 raised_p = s->hl == DRAW_IMAGE_RAISED;
3586 }
3587 else
3588 {
3589 thick = abs (s->img->relief);
3590 raised_p = s->img->relief > 0;
3591 }
177c0ea7 3592
1a578e9b
AC
3593 x0 = x - thick;
3594 y0 = y - thick;
ffe8b3f4
KS
3595 x1 = x + s->slice.width + thick - 1;
3596 y1 = y + s->slice.height + thick - 1;
177c0ea7 3597
1a578e9b 3598 x_setup_relief_colors (s);
f9e65eb3 3599 get_glyph_string_clip_rect (s, &r);
ffe8b3f4
KS
3600 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3601 s->slice.y == 0,
3602 s->slice.y + s->slice.height == s->img->height,
3603 s->slice.x == 0,
3604 s->slice.x + s->slice.width == s->img->width,
3605 &r);
1a578e9b
AC
3606}
3607
3608
1a578e9b
AC
3609/* Draw part of the background of glyph string S. X, Y, W, and H
3610 give the rectangle to draw. */
3611
3612static void
3613x_draw_glyph_string_bg_rect (s, x, y, w, h)
3614 struct glyph_string *s;
3615 int x, y, w, h;
3616{
3617#if 0 /* MAC_TODO: stipple */
3618 if (s->stippled_p)
3619 {
3620 /* Fill background with a stipple pattern. */
3621 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3622 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3623 XSetFillStyle (s->display, s->gc, FillSolid);
3624 }
3625 else
e0f712ba 3626#endif /* MAC_TODO */
1a578e9b
AC
3627 x_clear_glyph_string_rect (s, x, y, w, h);
3628}
3629
3630
177c0ea7 3631/* Draw image glyph string S.
1a578e9b
AC
3632
3633 s->y
3634 s->x +-------------------------
3635 | s->face->box
3636 |
3637 | +-------------------------
e3564461 3638 | | s->img->margin
1a578e9b
AC
3639 | |
3640 | | +-------------------
3641 | | | the image
3642
3643 */
3644
3645static void
3646x_draw_image_glyph_string (s)
3647 struct glyph_string *s;
3648{
3649 int x, y;
e0f712ba
AC
3650 int box_line_hwidth = abs (s->face->box_line_width);
3651 int box_line_vwidth = max (s->face->box_line_width, 0);
1a578e9b 3652 int height;
1a578e9b 3653
e0f712ba 3654 height = s->height - 2 * box_line_vwidth;
1a578e9b 3655
e3564461 3656
1a578e9b
AC
3657 /* Fill background with face under the image. Do it only if row is
3658 taller than image or if image has a clip mask to reduce
3659 flickering. */
3660 s->stippled_p = s->face->stipple != 0;
ffe8b3f4 3661 if (height > s->slice.height
83a96b4d 3662 || s->img->hmargin
e0f712ba 3663 || s->img->vmargin
1a578e9b 3664 || s->img->mask
1a578e9b
AC
3665 || s->img->pixmap == 0
3666 || s->width != s->background_width)
3667 {
ffe8b3f4
KS
3668 x = s->x;
3669 if (s->first_glyph->left_box_line_p
3670 && s->slice.x == 0)
3671 x += box_line_hwidth;
177c0ea7 3672
ffe8b3f4
KS
3673 y = s->y;
3674 if (s->slice.y == 0)
3675 y += box_line_vwidth;
e3564461 3676
236072ae 3677 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
177c0ea7 3678
1a578e9b
AC
3679 s->background_filled_p = 1;
3680 }
3681
3682 /* Draw the foreground. */
236072ae 3683 x_draw_image_foreground (s);
1a578e9b
AC
3684
3685 /* If we must draw a relief around the image, do it. */
3686 if (s->img->relief
3687 || s->hl == DRAW_IMAGE_RAISED
3688 || s->hl == DRAW_IMAGE_SUNKEN)
3689 x_draw_image_relief (s);
3690}
3691
3692
3693/* Draw stretch glyph string S. */
3694
3695static void
3696x_draw_stretch_glyph_string (s)
3697 struct glyph_string *s;
3698{
3699 xassert (s->first_glyph->type == STRETCH_GLYPH);
1a578e9b
AC
3700
3701 if (s->hl == DRAW_CURSOR
3702 && !x_stretch_cursor_p)
3703 {
3704 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3705 as wide as the stretch glyph. */
e8f6b0db
KS
3706 int width, background_width = s->background_width;
3707 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3708
3709 if (x < left_x)
3710 {
3711 background_width -= left_x - x;
3712 x = left_x;
3713 }
3714 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
1a578e9b
AC
3715
3716 /* Draw cursor. */
e8f6b0db 3717 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
1a578e9b
AC
3718
3719 /* Clear rest using the GC of the original non-cursor face. */
e8f6b0db 3720 if (width < background_width)
1a578e9b 3721 {
e8f6b0db
KS
3722 int y = s->y;
3723 int w = background_width - width, h = s->height;
1a578e9b 3724 Rect r;
e3564461 3725 GC gc;
1a578e9b 3726
e8f6b0db 3727 x += width;
e0f712ba
AC
3728 if (s->row->mouse_face_p
3729 && cursor_in_mouse_face_p (s->w))
3730 {
3731 x_set_mouse_face_gc (s);
3732 gc = s->gc;
3733 }
3734 else
3735 gc = s->face->gc;
177c0ea7 3736
f9e65eb3 3737 get_glyph_string_clip_rect (s, &r);
834263b6 3738 mac_set_clip_rectangles (s->f, gc, &r, 1);
1a578e9b
AC
3739
3740#if 0 /* MAC_TODO: stipple */
3741 if (s->face->stipple)
3742 {
3743 /* Fill background with a stipple pattern. */
3744 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3745 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3746 XSetFillStyle (s->display, gc, FillSolid);
3747 }
3748 else
e0f712ba 3749#endif /* MAC_TODO */
236072ae 3750 mac_erase_rectangle (s->f, gc, x, y, w, h);
1a578e9b
AC
3751 }
3752 }
e0f712ba 3753 else if (!s->background_filled_p)
e8f6b0db
KS
3754 {
3755 int background_width = s->background_width;
3756 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3757
6c693929
KS
3758 /* Don't draw into left margin, fringe or scrollbar area
3759 except for header line and mode line. */
3760 if (x < left_x && !s->row->mode_line_p)
e8f6b0db
KS
3761 {
3762 background_width -= left_x - x;
3763 x = left_x;
3764 }
3765 if (background_width > 0)
3766 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3767 }
177c0ea7 3768
1a578e9b
AC
3769 s->background_filled_p = 1;
3770}
3771
3772
3773/* Draw glyph string S. */
3774
3775static void
3776x_draw_glyph_string (s)
3777 struct glyph_string *s;
3778{
e0f712ba
AC
3779 int relief_drawn_p = 0;
3780
8c2da0fa
ST
3781 /* If S draws into the background of its successor that does not
3782 draw a cursor, draw the background of the successor first so that
3783 S can draw into it. This makes S->next use XDrawString instead
3784 of XDrawImageString. */
c2ded1b7 3785 if (s->next && s->right_overhang && !s->for_overlaps
8c2da0fa 3786 && s->next->hl != DRAW_CURSOR)
1a578e9b
AC
3787 {
3788 xassert (s->next->img == NULL);
3789 x_set_glyph_string_gc (s->next);
3790 x_set_glyph_string_clipping (s->next);
3791 x_draw_glyph_string_background (s->next, 1);
3792 }
3793
3794 /* Set up S->gc, set clipping and draw S. */
3795 x_set_glyph_string_gc (s);
e0f712ba
AC
3796
3797 /* Draw relief (if any) in advance for char/composition so that the
3798 glyph string can be drawn over it. */
c2ded1b7 3799 if (!s->for_overlaps
e0f712ba
AC
3800 && s->face->box != FACE_NO_BOX
3801 && (s->first_glyph->type == CHAR_GLYPH
3802 || s->first_glyph->type == COMPOSITE_GLYPH))
3803
3804 {
3805 x_set_glyph_string_clipping (s);
3806 x_draw_glyph_string_background (s, 1);
3807 x_draw_glyph_string_box (s);
3808 x_set_glyph_string_clipping (s);
3809 relief_drawn_p = 1;
3810 }
3811 else
3812 x_set_glyph_string_clipping (s);
1a578e9b
AC
3813
3814 switch (s->first_glyph->type)
3815 {
3816 case IMAGE_GLYPH:
3817 x_draw_image_glyph_string (s);
3818 break;
3819
3820 case STRETCH_GLYPH:
3821 x_draw_stretch_glyph_string (s);
3822 break;
3823
3824 case CHAR_GLYPH:
c2ded1b7 3825 if (s->for_overlaps)
1a578e9b
AC
3826 s->background_filled_p = 1;
3827 else
e3564461 3828 x_draw_glyph_string_background (s, 0);
1a578e9b
AC
3829 x_draw_glyph_string_foreground (s);
3830 break;
3831
3832 case COMPOSITE_GLYPH:
c2ded1b7 3833 if (s->for_overlaps || s->gidx > 0)
1a578e9b
AC
3834 s->background_filled_p = 1;
3835 else
3836 x_draw_glyph_string_background (s, 1);
3837 x_draw_composite_glyph_string_foreground (s);
3838 break;
3839
3840 default:
3841 abort ();
3842 }
3843
c2ded1b7 3844 if (!s->for_overlaps)
1a578e9b
AC
3845 {
3846 /* Draw underline. */
3847 if (s->face->underline_p)
3848 {
cf2c6835
YM
3849 unsigned long tem, h;
3850 int y;
3851
3852#if 0
3853 /* Get the underline thickness. Default is 1 pixel. */
3854 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3855#endif
3856 h = 1;
3857
3858 y = s->y + s->height - h;
3859 if (!x_underline_at_descent_line)
3860 {
3861 /* Get the underline position. This is the recommended
3862 vertical offset in pixels from the baseline to the top of
3863 the underline. This is a signed value according to the
3864 specs, and its default is
3865
3866 ROUND ((maximum descent) / 2), with
3867 ROUND(x) = floor (x + 0.5) */
3868
3869#if 0
3870 if (x_use_underline_position_properties
3871 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
3872 y = s->ybase + (long) tem;
3873 else
3874#endif
3875 if (s->face->font)
3876 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
3877 }
177c0ea7 3878
1a578e9b 3879 if (s->face->underline_defaulted_p)
cf2c6835 3880 mac_fill_rectangle (s->f, s->gc, s->x, y,
30f27523 3881 s->background_width, h);
1a578e9b
AC
3882 else
3883 {
3884 XGCValues xgcv;
3885 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3886 XSetForeground (s->display, s->gc, s->face->underline_color);
cf2c6835 3887 mac_fill_rectangle (s->f, s->gc, s->x, y,
30f27523 3888 s->background_width, h);
1a578e9b
AC
3889 XSetForeground (s->display, s->gc, xgcv.foreground);
3890 }
3891 }
3892
3893 /* Draw overline. */
3894 if (s->face->overline_p)
3895 {
3896 unsigned long dy = 0, h = 1;
3897
3898 if (s->face->overline_color_defaulted_p)
236072ae 3899 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
30f27523 3900 s->background_width, h);
1a578e9b
AC
3901 else
3902 {
3903 XGCValues xgcv;
3904 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3905 XSetForeground (s->display, s->gc, s->face->overline_color);
236072ae 3906 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
30f27523 3907 s->background_width, h);
1a578e9b
AC
3908 XSetForeground (s->display, s->gc, xgcv.foreground);
3909 }
3910 }
177c0ea7 3911
1a578e9b
AC
3912 /* Draw strike-through. */
3913 if (s->face->strike_through_p)
3914 {
3915 unsigned long h = 1;
3916 unsigned long dy = (s->height - h) / 2;
3917
3918 if (s->face->strike_through_color_defaulted_p)
236072ae
YM
3919 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3920 s->width, h);
1a578e9b
AC
3921 else
3922 {
3923 XGCValues xgcv;
3924 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3925 XSetForeground (s->display, s->gc, s->face->strike_through_color);
236072ae
YM
3926 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3927 s->width, h);
1a578e9b
AC
3928 XSetForeground (s->display, s->gc, xgcv.foreground);
3929 }
3930 }
177c0ea7 3931
e3564461 3932 /* Draw relief if not yet drawn. */
e0f712ba 3933 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
e3564461 3934 x_draw_glyph_string_box (s);
1a578e9b 3935 }
e0f712ba 3936
1a578e9b 3937 /* Reset clipping. */
834263b6 3938 mac_reset_clip_rectangles (s->f, s->gc);
1a578e9b
AC
3939}
3940
f9e65eb3 3941/* Shift display to make room for inserted glyphs. */
1a578e9b 3942
f9e65eb3
KS
3943void
3944mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3945 struct frame *f;
3946 int x, y, width, height, shift_by;
1a578e9b 3947{
236072ae 3948 mac_scroll_area (f, f->output_data.mac->normal_gc,
f9e65eb3
KS
3949 x, y, width, height,
3950 x + shift_by, y);
1a578e9b
AC
3951}
3952
1a578e9b
AC
3953/* Delete N glyphs at the nominal cursor position. Not implemented
3954 for X frames. */
3955
e0f712ba 3956static void
1a578e9b
AC
3957x_delete_glyphs (n)
3958 register int n;
3959{
3960 abort ();
3961}
3962
3963
1a578e9b
AC
3964/* Clear entire frame. If updating_frame is non-null, clear that
3965 frame. Otherwise clear the selected frame. */
3966
e0f712ba 3967static void
1a578e9b
AC
3968x_clear_frame ()
3969{
3970 struct frame *f;
3971
3972 if (updating_frame)
3973 f = updating_frame;
3974 else
3975 f = SELECTED_FRAME ();
3976
3977 /* Clearing the frame will erase any cursor, so mark them all as no
3978 longer visible. */
3979 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3980 output_cursor.hpos = output_cursor.vpos = 0;
3981 output_cursor.x = -1;
3982
3983 /* We don't set the output cursor here because there will always
3984 follow an explicit cursor_to. */
3985 BLOCK_INPUT;
236072ae 3986 mac_clear_window (f);
1a578e9b 3987
1a578e9b
AC
3988 /* We have to clear the scroll bars, too. If we have changed
3989 colors or something like that, then they should be notified. */
3990 x_scroll_bar_clear (f);
1a578e9b
AC
3991
3992 XFlush (FRAME_MAC_DISPLAY (f));
3993 UNBLOCK_INPUT;
3994}
3995
3996
3997\f
3998/* Invert the middle quarter of the frame for .15 sec. */
3999
4000/* We use the select system call to do the waiting, so we have to make
4001 sure it's available. If it isn't, we just won't do visual bells. */
4002
4003#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4004
e3564461 4005
1a578e9b
AC
4006/* Subtract the `struct timeval' values X and Y, storing the result in
4007 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4008
4009static int
4010timeval_subtract (result, x, y)
4011 struct timeval *result, x, y;
4012{
4013 /* Perform the carry for the later subtraction by updating y. This
4014 is safer because on some systems the tv_sec member is unsigned. */
4015 if (x.tv_usec < y.tv_usec)
4016 {
4017 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4018 y.tv_usec -= 1000000 * nsec;
4019 y.tv_sec += nsec;
4020 }
177c0ea7 4021
1a578e9b
AC
4022 if (x.tv_usec - y.tv_usec > 1000000)
4023 {
4024 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4025 y.tv_usec += 1000000 * nsec;
4026 y.tv_sec -= nsec;
4027 }
4028
4029 /* Compute the time remaining to wait. tv_usec is certainly
4030 positive. */
4031 result->tv_sec = x.tv_sec - y.tv_sec;
4032 result->tv_usec = x.tv_usec - y.tv_usec;
4033
4034 /* Return indication of whether the result should be considered
4035 negative. */
4036 return x.tv_sec < y.tv_sec;
4037}
4038
4039void
4040XTflash (f)
4041 struct frame *f;
4042{
d4a8455b
YM
4043 /* Get the height not including a menu bar widget. */
4044 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
4045 /* Height of each line to flash. */
4046 int flash_height = FRAME_LINE_HEIGHT (f);
4047 /* These will be the left and right margins of the rectangles. */
4048 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4049 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4050
4051 int width;
4052
4053 /* Don't flash the area between a scroll bar and the frame
4054 edge it is next to. */
4055 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4056 {
4057 case vertical_scroll_bar_left:
4058 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4059 break;
4060
4061 case vertical_scroll_bar_right:
4062 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4063 break;
4064
4065 default:
4066 break;
4067 }
4068
4069 width = flash_right - flash_left;
4070
1a578e9b
AC
4071 BLOCK_INPUT;
4072
d4a8455b
YM
4073 /* If window is tall, flash top and bottom line. */
4074 if (height > 3 * FRAME_LINE_HEIGHT (f))
4075 {
236072ae 4076 mac_invert_rectangle (f, flash_left,
d4a8455b
YM
4077 (FRAME_INTERNAL_BORDER_WIDTH (f)
4078 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4079 width, flash_height);
236072ae 4080 mac_invert_rectangle (f, flash_left,
d4a8455b
YM
4081 (height - flash_height
4082 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4083 width, flash_height);
4084 }
4085 else
4086 /* If it is short, flash it all. */
236072ae 4087 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
d4a8455b
YM
4088 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4089
4090 x_flush (f);
1a578e9b
AC
4091
4092 {
4093 struct timeval wakeup;
4094
4095 EMACS_GET_TIME (wakeup);
4096
4097 /* Compute time to wait until, propagating carry from usecs. */
4098 wakeup.tv_usec += 150000;
4099 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4100 wakeup.tv_usec %= 1000000;
4101
d4a8455b
YM
4102 /* Keep waiting until past the time wakeup or any input gets
4103 available. */
4104 while (! detect_input_pending ())
1a578e9b 4105 {
d4a8455b
YM
4106 struct timeval current;
4107 struct timeval timeout;
4108
4109 EMACS_GET_TIME (current);
1a578e9b 4110
d4a8455b
YM
4111 /* Break if result would be negative. */
4112 if (timeval_subtract (&current, wakeup, current))
4113 break;
1a578e9b 4114
d4a8455b
YM
4115 /* How long `select' should wait. */
4116 timeout.tv_sec = 0;
4117 timeout.tv_usec = 10000;
1a578e9b 4118
d4a8455b
YM
4119 /* Try to wait that long--but we might wake up sooner. */
4120 select (0, NULL, NULL, NULL, &timeout);
1a578e9b
AC
4121 }
4122 }
177c0ea7 4123
d4a8455b
YM
4124 /* If window is tall, flash top and bottom line. */
4125 if (height > 3 * FRAME_LINE_HEIGHT (f))
4126 {
236072ae 4127 mac_invert_rectangle (f, flash_left,
d4a8455b
YM
4128 (FRAME_INTERNAL_BORDER_WIDTH (f)
4129 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4130 width, flash_height);
236072ae 4131 mac_invert_rectangle (f, flash_left,
d4a8455b
YM
4132 (height - flash_height
4133 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4134 width, flash_height);
4135 }
4136 else
4137 /* If it is short, flash it all. */
236072ae 4138 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
d4a8455b
YM
4139 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4140
4141 x_flush (f);
1a578e9b
AC
4142
4143 UNBLOCK_INPUT;
4144}
4145
4146#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4147
4148
4149/* Make audible bell. */
4150
4151void
4152XTring_bell ()
4153{
4154 struct frame *f = SELECTED_FRAME ();
177c0ea7 4155
1a578e9b
AC
4156#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4157 if (visible_bell)
4158 XTflash (f);
4159 else
4160#endif
4161 {
4162 BLOCK_INPUT;
f2ec385e 4163 mac_alert_sound_play ();
1a578e9b
AC
4164 XFlush (FRAME_MAC_DISPLAY (f));
4165 UNBLOCK_INPUT;
4166 }
4167}
4168
1a578e9b
AC
4169\f
4170/* Specify how many text lines, from the top of the window,
4171 should be affected by insert-lines and delete-lines operations.
4172 This, and those operations, are used only within an update
4173 that is bounded by calls to x_update_begin and x_update_end. */
4174
e3564461 4175static void
1a578e9b
AC
4176XTset_terminal_window (n)
4177 register int n;
4178{
4179 /* This function intentionally left blank. */
4180}
4181
4182
4183\f
4184/***********************************************************************
4185 Line Dance
4186 ***********************************************************************/
4187
4188/* Perform an insert-lines or delete-lines operation, inserting N
4189 lines or deleting -N lines at vertical position VPOS. */
4190
e0f712ba 4191static void
1a578e9b
AC
4192x_ins_del_lines (vpos, n)
4193 int vpos, n;
4194{
4195 abort ();
4196}
4197
4198
4199/* Scroll part of the display as described by RUN. */
4200
e0f712ba 4201static void
1a578e9b
AC
4202x_scroll_run (w, run)
4203 struct window *w;
4204 struct run *run;
4205{
4206 struct frame *f = XFRAME (w->frame);
4207 int x, y, width, height, from_y, to_y, bottom_y;
4208
4209 /* Get frame-relative bounding box of the text display area of W,
3f332ef3 4210 without mode lines. Include in this box the left and right
e3564461 4211 fringe of W. */
1a578e9b 4212 window_box (w, -1, &x, &y, &width, &height);
1a578e9b
AC
4213
4214 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4215 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4216 bottom_y = y + height;
4217
4218 if (to_y < from_y)
4219 {
4220 /* Scrolling up. Make sure we don't copy part of the mode
4221 line at the bottom. */
4222 if (from_y + run->height > bottom_y)
4223 height = bottom_y - from_y;
4224 else
4225 height = run->height;
4226 }
4227 else
4228 {
4229 /* Scolling down. Make sure we don't copy over the mode line.
4230 at the bottom. */
4231 if (to_y + run->height > bottom_y)
4232 height = bottom_y - to_y;
4233 else
4234 height = run->height;
4235 }
4236
4237 BLOCK_INPUT;
177c0ea7 4238
1a578e9b
AC
4239 /* Cursor off. Will be switched on again in x_update_window_end. */
4240 updated_window = w;
4241 x_clear_cursor (w);
4242
236072ae
YM
4243 mac_scroll_area (f, f->output_data.mac->normal_gc,
4244 x, from_y,
4245 width, height,
4246 x, to_y);
177c0ea7 4247
1a578e9b
AC
4248 UNBLOCK_INPUT;
4249}
4250
4251
4252\f
4253/***********************************************************************
4254 Exposure Events
4255 ***********************************************************************/
177c0ea7 4256
f9e65eb3
KS
4257\f
4258static void
4259frame_highlight (f)
4260 struct frame *f;
4261{
4262 x_update_cursor (f, 1);
4263}
1a578e9b
AC
4264
4265static void
f9e65eb3 4266frame_unhighlight (f)
1a578e9b 4267 struct frame *f;
1a578e9b 4268{
f9e65eb3
KS
4269 x_update_cursor (f, 1);
4270}
4271
4272/* The focus has changed. Update the frames as necessary to reflect
4273 the new situation. Note that we can't change the selected frame
4274 here, because the Lisp code we are interrupting might become confused.
4275 Each event gets marked with the frame in which it occurred, so the
4276 Lisp code can tell when the switch took place by examining the events. */
1a578e9b 4277
f9e65eb3
KS
4278static void
4279x_new_focus_frame (dpyinfo, frame)
4280 struct x_display_info *dpyinfo;
4281 struct frame *frame;
4282{
4283 struct frame *old_focus = dpyinfo->x_focus_frame;
1a578e9b 4284
f9e65eb3 4285 if (frame != dpyinfo->x_focus_frame)
1a578e9b 4286 {
f9e65eb3
KS
4287 /* Set this before calling other routines, so that they see
4288 the correct value of x_focus_frame. */
4289 dpyinfo->x_focus_frame = frame;
1a578e9b 4290
f9e65eb3
KS
4291 if (old_focus && old_focus->auto_lower)
4292 x_lower_frame (old_focus);
1a578e9b 4293
f9e65eb3
KS
4294#if 0
4295 selected_frame = frame;
4296 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4297 selected_frame);
f1321dc3 4298 Fselect_window (selected_frame->selected_window, Qnil);
f9e65eb3
KS
4299 choose_minibuf_frame ();
4300#endif /* ! 0 */
1a578e9b 4301
f9e65eb3
KS
4302 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4303 pending_autoraise_frame = dpyinfo->x_focus_frame;
4304 else
4305 pending_autoraise_frame = 0;
68c767a3
YM
4306
4307#if USE_MAC_FONT_PANEL
4308 if (frame)
4cb62a90 4309 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
68c767a3 4310#endif
1a578e9b 4311 }
1a578e9b 4312
f9e65eb3
KS
4313 x_frame_rehighlight (dpyinfo);
4314}
1a578e9b 4315
7ca7ccd5
YM
4316/* Handle FocusIn and FocusOut state changes for FRAME.
4317 If FRAME has focus and there exists more than one frame, puts
4318 a FOCUS_IN_EVENT into *BUFP. */
4319
f2ec385e 4320void
7ca7ccd5
YM
4321mac_focus_changed (type, dpyinfo, frame, bufp)
4322 int type;
4323 struct mac_display_info *dpyinfo;
4324 struct frame *frame;
4325 struct input_event *bufp;
4326{
4327 if (type == activeFlag)
4328 {
4329 if (dpyinfo->x_focus_event_frame != frame)
4330 {
4331 x_new_focus_frame (dpyinfo, frame);
4332 dpyinfo->x_focus_event_frame = frame;
4333
4334 /* Don't stop displaying the initial startup message
4335 for a switch-frame event we don't need. */
4336 if (GC_NILP (Vterminal_frame)
4337 && GC_CONSP (Vframe_list)
4338 && !GC_NILP (XCDR (Vframe_list)))
4339 {
4340 bufp->kind = FOCUS_IN_EVENT;
4341 XSETFRAME (bufp->frame_or_window, frame);
4342 }
4343 }
4344 }
4345 else
4346 {
4347 if (dpyinfo->x_focus_event_frame == frame)
4348 {
4349 dpyinfo->x_focus_event_frame = 0;
4350 x_new_focus_frame (dpyinfo, 0);
4351 }
4352 }
4353}
4354
f9e65eb3 4355/* Handle an event saying the mouse has moved out of an Emacs frame. */
1a578e9b 4356
f9e65eb3
KS
4357void
4358x_mouse_leave (dpyinfo)
4359 struct x_display_info *dpyinfo;
1a578e9b 4360{
f9e65eb3 4361 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
1a578e9b
AC
4362}
4363
f9e65eb3
KS
4364/* The focus has changed, or we have redirected a frame's focus to
4365 another frame (this happens when a frame uses a surrogate
4366 mini-buffer frame). Shift the highlight as appropriate.
1a578e9b 4367
f9e65eb3
KS
4368 The FRAME argument doesn't necessarily have anything to do with which
4369 frame is being highlighted or un-highlighted; we only use it to find
4370 the appropriate X display info. */
1a578e9b
AC
4371
4372static void
f9e65eb3 4373XTframe_rehighlight (frame)
1a578e9b
AC
4374 struct frame *frame;
4375{
1a578e9b
AC
4376 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4377}
4378
4379static void
4380x_frame_rehighlight (dpyinfo)
4381 struct x_display_info *dpyinfo;
4382{
4383 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4384
4385 if (dpyinfo->x_focus_frame)
4386 {
4387 dpyinfo->x_highlight_frame
4388 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4389 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4390 : dpyinfo->x_focus_frame);
4391 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4392 {
4393 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4394 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4395 }
4396 }
4397 else
4398 dpyinfo->x_highlight_frame = 0;
4399
4400 if (dpyinfo->x_highlight_frame != old_highlight)
4401 {
4402 if (old_highlight)
4403 frame_unhighlight (old_highlight);
4404 if (dpyinfo->x_highlight_frame)
4405 frame_highlight (dpyinfo->x_highlight_frame);
4406 }
4407}
4408
4409
4410\f
1a578e9b
AC
4411/* Convert a keysym to its name. */
4412
4413char *
4414x_get_keysym_name (keysym)
4415 int keysym;
4416{
4417 char *value;
4418
4419 BLOCK_INPUT;
4420#if 0
4421 value = XKeysymToString (keysym);
4422#else
4423 value = 0;
4424#endif
4425 UNBLOCK_INPUT;
4426
4427 return value;
4428}
4429
4430
4431\f
f9e65eb3
KS
4432/* Function to report a mouse movement to the mainstream Emacs code.
4433 The input handler calls this.
4434
4435 We have received a mouse movement event, which is given in *event.
4436 If the mouse is over a different glyph than it was last time, tell
4437 the mainstream emacs code by setting mouse_moved. If not, ask for
4438 another motion event, so we can check again the next time it moves. */
1a578e9b 4439
f9e65eb3
KS
4440static Point last_mouse_motion_position;
4441static Lisp_Object last_mouse_motion_frame;
1a578e9b 4442
f2ec385e 4443int
f9e65eb3
KS
4444note_mouse_movement (frame, pos)
4445 FRAME_PTR frame;
4446 Point *pos;
1a578e9b 4447{
50bf7673 4448 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
f9e65eb3 4449 Rect r;
1a578e9b 4450
f9e65eb3
KS
4451 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4452 last_mouse_motion_position = *pos;
4453 XSETFRAME (last_mouse_motion_frame, frame);
4454
6a0ace5b 4455 if (frame == dpyinfo->mouse_face_mouse_frame
f2ec385e 4456 && !PtInRect (*pos, mac_get_frame_bounds (frame, &r)))
f9e65eb3 4457 {
6a0ace5b
YM
4458 /* This case corresponds to LeaveNotify in X11. If we move
4459 outside the frame, then we're certainly no longer on any text
4460 in the frame. */
4461 clear_mouse_face (dpyinfo);
4462 dpyinfo->mouse_face_mouse_frame = 0;
4463 if (!dpyinfo->grabbed)
4464 rif->define_frame_cursor (frame,
4465 frame->output_data.mac->nontext_cursor);
f9e65eb3 4466 }
6a0ace5b 4467
f9e65eb3 4468 /* Has the mouse moved off the glyph it was on at the last sighting? */
05f7d868
YM
4469 if (frame != last_mouse_glyph_frame
4470 || !PtInRect (*pos, &last_mouse_glyph))
f9e65eb3
KS
4471 {
4472 frame->mouse_moved = 1;
4473 last_mouse_scroll_bar = Qnil;
4474 note_mouse_highlight (frame, pos->h, pos->v);
e2570d37
KS
4475 /* Remember which glyph we're now on. */
4476 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
05f7d868 4477 last_mouse_glyph_frame = frame;
af1229d9 4478 return 1;
f9e65eb3 4479 }
af1229d9
YM
4480
4481 return 0;
1a578e9b
AC
4482}
4483
1a578e9b 4484\f
f9e65eb3
KS
4485/************************************************************************
4486 Mouse Face
4487 ************************************************************************/
4488
f9e65eb3
KS
4489/* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4490
4491static void
4492redo_mouse_highlight ()
4493{
4494 if (!NILP (last_mouse_motion_frame)
4495 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4496 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4497 last_mouse_motion_position.h,
4498 last_mouse_motion_position.v);
4499}
4500
4501
f2ec385e 4502struct frame *
7ca7ccd5
YM
4503mac_focus_frame (dpyinfo)
4504 struct mac_display_info *dpyinfo;
50bf7673 4505{
7ca7ccd5
YM
4506 if (dpyinfo->x_focus_frame)
4507 return dpyinfo->x_focus_frame;
4508 else
4509 /* Mac version may get events, such as a menu bar click, even when
4510 all the frames are invisible. In this case, we regard the
4511 event came to the selected frame. */
4512 return SELECTED_FRAME ();
50bf7673
ST
4513}
4514
50bf7673 4515
1a578e9b 4516/* Return the current position of the mouse.
e2570d37 4517 *FP should be a frame which indicates which display to ask about.
1a578e9b 4518
e2570d37
KS
4519 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4520 and *PART to the frame, window, and scroll bar part that the mouse
4521 is over. Set *X and *Y to the portion and whole of the mouse's
1a578e9b
AC
4522 position on the scroll bar.
4523
e2570d37
KS
4524 If the mouse movement started elsewhere, set *FP to the frame the
4525 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
1a578e9b
AC
4526 the mouse is over.
4527
e2570d37 4528 Set *TIME to the server time-stamp for the time at which the mouse
1a578e9b
AC
4529 was at this position.
4530
4531 Don't store anything if we don't have a valid set of values to report.
4532
4533 This clears the mouse_moved flag, so we can wait for the next mouse
4534 movement. */
4535
e0f712ba 4536static void
1a578e9b
AC
4537XTmouse_position (fp, insist, bar_window, part, x, y, time)
4538 FRAME_PTR *fp;
4539 int insist;
4540 Lisp_Object *bar_window;
4541 enum scroll_bar_part *part;
4542 Lisp_Object *x, *y;
4543 unsigned long *time;
4544{
e2570d37 4545 FRAME_PTR f1;
1a578e9b
AC
4546
4547 BLOCK_INPUT;
4548
4549 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4550 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4551 else
4552 {
e2570d37
KS
4553 Lisp_Object frame, tail;
4554
1a578e9b
AC
4555 /* Clear the mouse-moved flag for every frame on this display. */
4556 FOR_EACH_FRAME (tail, frame)
e2570d37 4557 XFRAME (frame)->mouse_moved = 0;
1a578e9b
AC
4558
4559 last_mouse_scroll_bar = Qnil;
4560
e2570d37
KS
4561 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4562 && FRAME_LIVE_P (last_mouse_frame))
4563 f1 = last_mouse_frame;
4564 else
4565 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
1a578e9b 4566
e2570d37
KS
4567 if (f1)
4568 {
4569 /* Ok, we found a frame. Store all the values.
4570 last_mouse_glyph is a rectangle used to reduce the
4571 generation of mouse events. To not miss any motion
4572 events, we must divide the frame into rectangles of the
4573 size of the smallest character that could be displayed
4574 on it, i.e. into the same rectangles that matrices on
4575 the frame are divided into. */
4576 Point mouse_pos;
4577
f2ec385e 4578 mac_get_frame_mouse (f1, &mouse_pos);
e2570d37
KS
4579 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4580 &last_mouse_glyph);
05f7d868 4581 last_mouse_glyph_frame = f1;
e2570d37
KS
4582
4583 *bar_window = Qnil;
4584 *part = 0;
4585 *fp = f1;
4586 XSETINT (*x, mouse_pos.h);
4587 XSETINT (*y, mouse_pos.v);
4588 *time = last_mouse_movement_time;
4589 }
1a578e9b 4590 }
177c0ea7 4591
1a578e9b
AC
4592 UNBLOCK_INPUT;
4593}
4594
4595\f
5b8b73ff 4596/************************************************************************
f2ec385e 4597 Scroll bars, general
5b8b73ff
YM
4598 ************************************************************************/
4599
f2ec385e
YM
4600/* Create a scroll bar and return the scroll bar vector for it. W is
4601 the Emacs window on which to create the scroll bar. TOP, LEFT,
4602 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4603 scroll bar. */
5b8b73ff 4604
f2ec385e
YM
4605static struct scroll_bar *
4606x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4607 struct window *w;
4608 int top, left, width, height, disp_top, disp_height;
5b8b73ff 4609{
f2ec385e
YM
4610 struct frame *f = XFRAME (w->frame);
4611 struct scroll_bar *bar
4612 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4613 Rect r;
5b8b73ff 4614
f2ec385e 4615 BLOCK_INPUT;
5b8b73ff 4616
f2ec385e
YM
4617 XSETWINDOW (bar->window, w);
4618 XSETINT (bar->top, top);
4619 XSETINT (bar->left, left);
4620 XSETINT (bar->width, width);
4621 XSETINT (bar->height, height);
4622#ifdef MAC_OSX
4623 bar->fringe_extended_p = Qnil;
4624#endif
4625 bar->redraw_needed_p = Qnil;
5b8b73ff 4626
f2ec385e
YM
4627 SetRect (&r, left, disp_top, left + width, disp_top + disp_height);
4628 mac_create_scroll_bar (bar, &r,
4629#ifdef USE_TOOLKIT_SCROLL_BARS
4630 false
4631#else
4632 width < disp_height
4633#endif
4634 );
5b8b73ff 4635
f2ec385e
YM
4636 /* Add bar to its frame's list of scroll bars. */
4637 bar->next = FRAME_SCROLL_BARS (f);
4638 bar->prev = Qnil;
4639 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4640 if (!NILP (bar->next))
4641 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5b8b73ff 4642
f2ec385e
YM
4643 UNBLOCK_INPUT;
4644 return bar;
5b8b73ff
YM
4645}
4646
5b8b73ff 4647
f2ec385e
YM
4648/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4649 nil. */
f9e65eb3
KS
4650
4651static void
f2ec385e 4652x_scroll_bar_remove (bar)
5b8b73ff 4653 struct scroll_bar *bar;
5b8b73ff 4654{
f2ec385e 4655 BLOCK_INPUT;
5b8b73ff 4656
f2ec385e
YM
4657 /* Destroy the Mac scroll bar control */
4658 mac_dispose_scroll_bar (bar);
5b8b73ff 4659
f2ec385e
YM
4660 /* Disassociate this scroll bar from its window. */
4661 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5b8b73ff 4662
f2ec385e 4663 UNBLOCK_INPUT;
5b8b73ff
YM
4664}
4665
5b8b73ff 4666
f2ec385e
YM
4667/* Set the handle of the vertical scroll bar for WINDOW to indicate
4668 that we are displaying PORTION characters out of a total of WHOLE
4669 characters, starting at POSITION. If WINDOW has no scroll bar,
4670 create one. */
5b8b73ff
YM
4671
4672static void
f2ec385e
YM
4673XTset_vertical_scroll_bar (w, portion, whole, position)
4674 struct window *w;
4675 int portion, whole, position;
1a578e9b
AC
4676{
4677 struct frame *f = XFRAME (w->frame);
4678 struct scroll_bar *bar;
4679 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
f1a83aab 4680 int window_y, window_height;
660425fa
YM
4681#ifdef MAC_OSX
4682 int fringe_extended_p;
4683#endif
1a578e9b
AC
4684
4685 /* Get window dimensions. */
f1a83aab 4686 window_box (w, -1, 0, &window_y, 0, &window_height);
1a578e9b 4687 top = window_y;
f1a83aab 4688 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
1a578e9b
AC
4689 height = window_height;
4690
4691 /* Compute the left edge of the scroll bar area. */
f1a83aab 4692 left = WINDOW_SCROLL_BAR_AREA_X (w);
1a578e9b
AC
4693
4694 /* Compute the width of the scroll bar which might be less than
4695 the width of the area reserved for the scroll bar. */
f1a83aab
KS
4696 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4697 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
1a578e9b
AC
4698 else
4699 sb_width = width;
4700
4701 /* Compute the left edge of the scroll bar. */
f1a83aab 4702 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
660425fa 4703 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
1a578e9b 4704 else
660425fa 4705 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
177c0ea7 4706
1a578e9b
AC
4707 /* Adjustments according to Inside Macintosh to make it look nice */
4708 disp_top = top;
4709 disp_height = height;
a3510ffa 4710#ifdef MAC_OS8
1a578e9b
AC
4711 if (disp_top == 0)
4712 {
4713 disp_top = -1;
4714 disp_height++;
4715 }
f1a83aab 4716 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
1a578e9b
AC
4717 {
4718 disp_top++;
4719 disp_height--;
4720 }
177c0ea7 4721
f1a83aab 4722 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
1a578e9b 4723 sb_left++;
a3510ffa 4724#endif
177c0ea7 4725
660425fa
YM
4726#ifdef MAC_OSX
4727 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
4728 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
4729 && WINDOW_LEFT_FRINGE_WIDTH (w)
4730 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4731 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
4732 else
4733 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
4734 && WINDOW_RIGHT_FRINGE_WIDTH (w)
4735 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4736 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
4737#endif
4738
1a578e9b
AC
4739 /* Does the scroll bar exist yet? */
4740 if (NILP (w->vertical_scroll_bar))
4741 {
4742 BLOCK_INPUT;
660425fa
YM
4743#ifdef MAC_OSX
4744 if (fringe_extended_p)
4745 mac_clear_area (f, sb_left, top, sb_width, height);
4746 else
4747#endif
4748 mac_clear_area (f, left, top, width, height);
1a578e9b
AC
4749 UNBLOCK_INPUT;
4750 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4751 disp_height);
4752 XSETVECTOR (w->vertical_scroll_bar, bar);
4753 }
4754 else
4755 {
4756 /* It may just need to be moved and resized. */
1a578e9b 4757 bar = XSCROLL_BAR (w->vertical_scroll_bar);
1a578e9b
AC
4758
4759 BLOCK_INPUT;
4760
4761 /* If already correctly positioned, do nothing. */
1ec6ded9
YM
4762 if (XINT (bar->left) == sb_left
4763 && XINT (bar->top) == top
4764 && XINT (bar->width) == sb_width
660425fa
YM
4765 && XINT (bar->height) == height
4766#ifdef MAC_OSX
4767 && !NILP (bar->fringe_extended_p) == fringe_extended_p
4768#endif
4769 )
1ec6ded9
YM
4770 {
4771 if (!NILP (bar->redraw_needed_p))
f2ec385e 4772 mac_redraw_scroll_bar (bar);
1ec6ded9
YM
4773 }
4774 else
e6bdfa32 4775 {
f2ec385e
YM
4776 Rect r;
4777
e4f5e019
YM
4778 /* Since toolkit scroll bars are smaller than the space reserved
4779 for them on the frame, we have to clear "under" them. */
660425fa
YM
4780#ifdef MAC_OSX
4781 if (fringe_extended_p)
4782 mac_clear_area (f, sb_left, top, sb_width, height);
4783 else
4784#endif
4785 mac_clear_area (f, left, top, width, height);
1a578e9b 4786
f2ec385e
YM
4787 SetRect (&r, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top,
4788 sb_left + sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4789 disp_top + disp_height);
4790 mac_set_scroll_bar_bounds (bar, &r);
177c0ea7 4791
1a578e9b
AC
4792 /* Remember new settings. */
4793 XSETINT (bar->left, sb_left);
4794 XSETINT (bar->top, top);
4795 XSETINT (bar->width, sb_width);
4796 XSETINT (bar->height, height);
4797 }
4798
4799 UNBLOCK_INPUT;
4800 }
4801
660425fa
YM
4802#ifdef MAC_OSX
4803 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
4804#endif
1ec6ded9
YM
4805 bar->redraw_needed_p = Qnil;
4806
5b8b73ff 4807#ifdef USE_TOOLKIT_SCROLL_BARS
5b8b73ff
YM
4808 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4809#else /* not USE_TOOLKIT_SCROLL_BARS */
1a578e9b
AC
4810 /* Set the scroll bar's current state, unless we're currently being
4811 dragged. */
4812 if (NILP (bar->dragging))
4813 {
4814 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4815
4816 if (whole == 0)
4817 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4818 else
4819 {
4820 int start = ((double) position * top_range) / whole;
4821 int end = ((double) (position + portion) * top_range) / whole;
4822 x_scroll_bar_set_handle (bar, start, end, 0);
4823 }
4824 }
5b8b73ff 4825#endif /* not USE_TOOLKIT_SCROLL_BARS */
1a578e9b
AC
4826}
4827
4828
4829/* The following three hooks are used when we're doing a thorough
4830 redisplay of the frame. We don't explicitly know which scroll bars
4831 are going to be deleted, because keeping track of when windows go
4832 away is a real pain - "Can you say set-window-configuration, boys
4833 and girls?" Instead, we just assert at the beginning of redisplay
4834 that *all* scroll bars are to be removed, and then save a scroll bar
4835 from the fiery pit when we actually redisplay its window. */
4836
4837/* Arrange for all scroll bars on FRAME to be removed at the next call
4838 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4839 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4840
4841static void
4842XTcondemn_scroll_bars (frame)
4843 FRAME_PTR frame;
4844{
4845 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4846 while (! NILP (FRAME_SCROLL_BARS (frame)))
4847 {
4848 Lisp_Object bar;
4849 bar = FRAME_SCROLL_BARS (frame);
4850 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4851 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4852 XSCROLL_BAR (bar)->prev = Qnil;
4853 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4854 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4855 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4856 }
4857}
4858
e0f712ba 4859
1a578e9b
AC
4860/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4861 Note that WINDOW isn't necessarily condemned at all. */
e0f712ba 4862
1a578e9b
AC
4863static void
4864XTredeem_scroll_bar (window)
4865 struct window *window;
4866{
4867 struct scroll_bar *bar;
95dfb192 4868 struct frame *f;
1a578e9b
AC
4869
4870 /* We can't redeem this window's scroll bar if it doesn't have one. */
4871 if (NILP (window->vertical_scroll_bar))
4872 abort ();
4873
4874 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4875
4876 /* Unlink it from the condemned list. */
95dfb192
YM
4877 f = XFRAME (WINDOW_FRAME (window));
4878 if (NILP (bar->prev))
4879 {
4880 /* If the prev pointer is nil, it must be the first in one of
4881 the lists. */
4882 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4883 /* It's not condemned. Everything's fine. */
4884 return;
4885 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4886 window->vertical_scroll_bar))
4887 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4888 else
4889 /* If its prev pointer is nil, it must be at the front of
4890 one or the other! */
4891 abort ();
4892 }
4893 else
4894 XSCROLL_BAR (bar->prev)->next = bar->next;
1a578e9b 4895
95dfb192
YM
4896 if (! NILP (bar->next))
4897 XSCROLL_BAR (bar->next)->prev = bar->prev;
1a578e9b 4898
95dfb192
YM
4899 bar->next = FRAME_SCROLL_BARS (f);
4900 bar->prev = Qnil;
4901 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4902 if (! NILP (bar->next))
4903 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
1a578e9b
AC
4904}
4905
4906/* Remove all scroll bars on FRAME that haven't been saved since the
4907 last call to `*condemn_scroll_bars_hook'. */
4908
4909static void
4910XTjudge_scroll_bars (f)
4911 FRAME_PTR f;
4912{
4913 Lisp_Object bar, next;
4914
4915 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4916
4917 /* Clear out the condemned list now so we won't try to process any
4918 more events on the hapless scroll bars. */
4919 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4920
4921 for (; ! NILP (bar); bar = next)
4922 {
4923 struct scroll_bar *b = XSCROLL_BAR (bar);
4924
4925 x_scroll_bar_remove (b);
4926
4927 next = b->next;
4928 b->next = b->prev = Qnil;
4929 }
4930
4931 /* Now there should be no references to the condemned scroll bars,
4932 and they should get garbage-collected. */
4933}
4934
f2ec385e
YM
4935/* The screen has been cleared so we may have changed foreground or
4936 background colors, and the scroll bars may need to be redrawn.
4937 Clear out the scroll bars, and ask for expose events, so we can
4938 redraw them. */
1a578e9b 4939
f2ec385e
YM
4940void
4941x_scroll_bar_clear (f)
4942 FRAME_PTR f;
1a578e9b 4943{
f2ec385e 4944 Lisp_Object bar;
50bf7673 4945
f2ec385e
YM
4946 /* We can have scroll bars even if this is 0,
4947 if we just turned off scroll bar mode.
4948 But in that case we should not clear them. */
4949 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4950 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4951 bar = XSCROLL_BAR (bar)->next)
4952 XSCROLL_BAR (bar)->redraw_needed_p = Qt;
4953}
1a578e9b 4954
f2ec385e
YM
4955\f
4956/***********************************************************************
4957 Tool-bars
4958 ***********************************************************************/
4959#if USE_MAC_TOOLBAR
4960void
4961mac_move_window_with_gravity (f, win_gravity, left, top)
4962 struct frame *f;
4963 int win_gravity;
4964 short left, top;
4965{
4966 Rect inner, outer;
1a578e9b 4967
f2ec385e 4968 mac_get_window_bounds (f, &inner, &outer);
177c0ea7 4969
f2ec385e 4970 switch (win_gravity)
1a578e9b 4971 {
f2ec385e
YM
4972 case NorthWestGravity:
4973 case WestGravity:
4974 case SouthWestGravity:
4975 left += inner.left - outer.left;
1a578e9b 4976 break;
f2ec385e
YM
4977
4978 case NorthGravity:
4979 case CenterGravity:
4980 case SouthGravity:
4981 left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
1a578e9b 4982 break;
f2ec385e
YM
4983
4984 case NorthEastGravity:
4985 case EastGravity:
4986 case SouthEastGravity:
4987 left += inner.right - outer.right;
1a578e9b
AC
4988 break;
4989 }
50bf7673 4990
f2ec385e
YM
4991 switch (win_gravity)
4992 {
4993 case NorthWestGravity:
4994 case NorthGravity:
4995 case NorthEastGravity:
4996 top += inner.top - outer.top;
4997 break;
1a578e9b 4998
660425fa
YM
4999 case WestGravity:
5000 case CenterGravity:
5001 case EastGravity:
5002 top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
5003 break;
1a578e9b 5004
660425fa
YM
5005 case SouthWestGravity:
5006 case SouthGravity:
5007 case SouthEastGravity:
5008 top += inner.bottom - outer.bottom;
5009 break;
5010 }
5011
f2ec385e 5012 mac_move_window (FRAME_MAC_WINDOW (f), left, top, false);
660425fa 5013}
1a578e9b 5014
f2ec385e 5015void
660425fa
YM
5016mac_get_window_origin_with_gravity (f, win_gravity, left, top)
5017 struct frame *f;
5018 int win_gravity;
5019 short *left, *top;
1a578e9b 5020{
660425fa 5021 Rect inner, outer;
e3564461 5022
660425fa 5023 mac_get_window_bounds (f, &inner, &outer);
e3564461 5024
660425fa 5025 switch (win_gravity)
e3564461 5026 {
660425fa
YM
5027 case NorthWestGravity:
5028 case WestGravity:
5029 case SouthWestGravity:
5030 *left = outer.left;
5031 break;
177c0ea7 5032
660425fa
YM
5033 case NorthGravity:
5034 case CenterGravity:
5035 case SouthGravity:
5036 *left = outer.left + ((outer.right - outer.left)
5037 - (inner.right - inner.left)) / 2;
5038 break;
1a578e9b 5039
660425fa
YM
5040 case NorthEastGravity:
5041 case EastGravity:
5042 case SouthEastGravity:
5043 *left = outer.right - (inner.right - inner.left);
5044 break;
5045 }
1a578e9b 5046
660425fa
YM
5047 switch (win_gravity)
5048 {
5049 case NorthWestGravity:
5050 case NorthGravity:
5051 case NorthEastGravity:
5052 *top = outer.top;
5053 break;
e3564461 5054
660425fa
YM
5055 case WestGravity:
5056 case CenterGravity:
5057 case EastGravity:
5058 *top = outer.top + ((outer.bottom - outer.top)
5059 - (inner.bottom - inner.top)) / 2;
5060 break;
e3564461 5061
660425fa
YM
5062 case SouthWestGravity:
5063 case SouthGravity:
5064 case SouthEastGravity:
5065 *top = outer.bottom - (inner.bottom - inner.top);
5066 break;
1a578e9b
AC
5067 }
5068}
5069
f2ec385e 5070CGImageRef
660425fa
YM
5071mac_image_spec_to_cg_image (f, image)
5072 struct frame *f;
5073 Lisp_Object image;
5074{
5075 if (!valid_image_p (image))
5076 return NULL;
5077 else
5078 {
5079 int img_id = lookup_image (f, image);
5080 struct image *img = IMAGE_FROM_ID (f, img_id);
5081
5082 prepare_image_for_display (f, img);
5083
5084 return img->data.ptr_val;
5085 }
5086}
f2ec385e 5087#endif /* USE_MAC_TOOLBAR */
660425fa 5088
f2ec385e
YM
5089\f
5090/***********************************************************************
5091 Text Cursor
5092 ***********************************************************************/
660425fa 5093
f2ec385e
YM
5094/* Set clipping for output in glyph row ROW. W is the window in which
5095 we operate. GC is the graphics context to set clipping in.
660425fa 5096
f2ec385e
YM
5097 ROW may be a text row or, e.g., a mode line. Text rows must be
5098 clipped to the interior of the window dedicated to text display,
5099 mode lines must be clipped to the whole window. */
660425fa 5100
f2ec385e
YM
5101static void
5102x_clip_to_row (w, row, area, gc)
5103 struct window *w;
5104 struct glyph_row *row;
5105 int area;
5106 GC gc;
5107{
5108 struct frame *f = XFRAME (WINDOW_FRAME (w));
5109 Rect clip_rect;
5110 int window_x, window_y, window_width;
660425fa 5111
f2ec385e 5112 window_box (w, area, &window_x, &window_y, &window_width, 0);
660425fa 5113
f2ec385e
YM
5114 clip_rect.left = window_x;
5115 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5116 clip_rect.top = max (clip_rect.top, window_y);
5117 clip_rect.right = clip_rect.left + window_width;
5118 clip_rect.bottom = clip_rect.top + row->visible_height;
660425fa 5119
834263b6 5120 mac_set_clip_rectangles (f, gc, &clip_rect, 1);
660425fa
YM
5121}
5122
660425fa 5123
f2ec385e
YM
5124/* Draw a hollow box cursor on window W in glyph row ROW. */
5125
5126static void
5127x_draw_hollow_cursor (w, row)
5128 struct window *w;
5129 struct glyph_row *row;
660425fa 5130{
f2ec385e 5131 struct frame *f = XFRAME (WINDOW_FRAME (w));
660425fa 5132 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
f2ec385e
YM
5133 Display *dpy = FRAME_MAC_DISPLAY (f);
5134 int x, y, wd, h;
5135 XGCValues xgcv;
5136 struct glyph *cursor_glyph;
5137 GC gc;
660425fa 5138
f2ec385e
YM
5139 /* Get the glyph the cursor is on. If we can't tell because
5140 the current matrix is invalid or such, give up. */
5141 cursor_glyph = get_phys_cursor_glyph (w);
5142 if (cursor_glyph == NULL)
5143 return;
660425fa 5144
f2ec385e
YM
5145 /* Compute frame-relative coordinates for phys cursor. */
5146 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
5147 wd = w->phys_cursor_width;
660425fa 5148
f2ec385e
YM
5149 /* The foreground of cursor_gc is typically the same as the normal
5150 background color, which can cause the cursor box to be invisible. */
5151 xgcv.foreground = f->output_data.mac->cursor_pixel;
5152 if (dpyinfo->scratch_cursor_gc)
5153 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5154 else
5155 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5156 GCForeground, &xgcv);
5157 gc = dpyinfo->scratch_cursor_gc;
660425fa 5158
f2ec385e
YM
5159 /* Set clipping, draw the rectangle, and reset clipping again. */
5160 x_clip_to_row (w, row, TEXT_AREA, gc);
5161 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
834263b6 5162 mac_reset_clip_rectangles (f, gc);
f2ec385e 5163}
660425fa 5164
660425fa 5165
f2ec385e 5166/* Draw a bar cursor on window W in glyph row ROW.
660425fa 5167
f2ec385e
YM
5168 Implementation note: One would like to draw a bar cursor with an
5169 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5170 Unfortunately, I didn't find a font yet that has this property set.
5171 --gerd. */
660425fa 5172
f2ec385e
YM
5173static void
5174x_draw_bar_cursor (w, row, width, kind)
5175 struct window *w;
5176 struct glyph_row *row;
5177 int width;
5178 enum text_cursor_kinds kind;
5179{
5180 struct frame *f = XFRAME (w->frame);
5181 struct glyph *cursor_glyph;
660425fa
YM
5182
5183 /* If cursor is out of bounds, don't draw garbage. This can happen
5184 in mini-buffer windows when switching between echo area glyphs
5185 and mini-buffer. */
5186 cursor_glyph = get_phys_cursor_glyph (w);
5187 if (cursor_glyph == NULL)
5188 return;
5189
5190 /* If on an image, draw like a normal cursor. That's usually better
5191 visible than drawing a bar, esp. if the image is large so that
5192 the bar might not be in the window. */
5193 if (cursor_glyph->type == IMAGE_GLYPH)
5194 {
5195 struct glyph_row *row;
5196 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5197 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5198 }
5199 else
5200 {
5201 Display *dpy = FRAME_MAC_DISPLAY (f);
5202 Window window = FRAME_MAC_WINDOW (f);
5203 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5204 unsigned long mask = GCForeground | GCBackground;
5205 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5206 XGCValues xgcv;
5207
5208 /* If the glyph's background equals the color we normally draw
5209 the bar cursor in, the bar cursor in its normal color is
5210 invisible. Use the glyph's foreground color instead in this
5211 case, on the assumption that the glyph's colors are chosen so
5212 that the glyph is legible. */
5213 if (face->background == f->output_data.mac->cursor_pixel)
5214 xgcv.background = xgcv.foreground = face->foreground;
5215 else
5216 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5217
5218 if (gc)
5219 XChangeGC (dpy, gc, mask, &xgcv);
5220 else
5221 {
5222 gc = XCreateGC (dpy, window, mask, &xgcv);
5223 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5224 }
5225
5226 if (width < 0)
5227 width = FRAME_CURSOR_WIDTH (f);
5228 width = min (cursor_glyph->pixel_width, width);
5229
5230 w->phys_cursor_width = width;
5231 x_clip_to_row (w, row, TEXT_AREA, gc);
5232
5233 if (kind == BAR_CURSOR)
5234 mac_fill_rectangle (f, gc,
5235 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5236 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5237 width, row->height);
5238 else
5239 mac_fill_rectangle (f, gc,
5240 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5241 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5242 row->height - width),
5243 cursor_glyph->pixel_width,
5244 width);
5245
834263b6 5246 mac_reset_clip_rectangles (f, gc);
660425fa
YM
5247 }
5248}
5249
5250
5251/* RIF: Define cursor CURSOR on frame F. */
5252
5253static void
5254mac_define_frame_cursor (f, cursor)
5255 struct frame *f;
5256 Cursor cursor;
5257{
5258 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5259
5260 if (dpyinfo->x_focus_frame == f)
5261 SetThemeCursor (cursor);
5262}
5263
5264
5265/* RIF: Clear area on frame F. */
1a578e9b
AC
5266
5267static void
f9e65eb3
KS
5268mac_clear_frame_area (f, x, y, width, height)
5269 struct frame *f;
5270 int x, y, width, height;
1a578e9b 5271{
236072ae 5272 mac_clear_area (f, x, y, width, height);
1a578e9b
AC
5273}
5274
5275
f9e65eb3 5276/* RIF: Draw cursor on window W. */
1a578e9b
AC
5277
5278static void
e5a3b7d9 5279mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
1a578e9b 5280 struct window *w;
f9e65eb3 5281 struct glyph_row *glyph_row;
e5a3b7d9
KS
5282 int x, y;
5283 int cursor_type, cursor_width;
5284 int on_p, active_p;
1a578e9b 5285{
e5a3b7d9 5286 if (on_p)
1a578e9b 5287 {
e5a3b7d9 5288 w->phys_cursor_type = cursor_type;
1a578e9b
AC
5289 w->phys_cursor_on_p = 1;
5290
797dc7b8
KS
5291 if (glyph_row->exact_window_width_line_p
5292 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5293 {
5294 glyph_row->cursor_in_fringe_p = 1;
5295 draw_fringe_bitmap (w, glyph_row, 0);
797dc7b8 5296 }
e3564461 5297 else
e5a3b7d9 5298 switch (cursor_type)
1a578e9b
AC
5299 {
5300 case HOLLOW_BOX_CURSOR:
5301 x_draw_hollow_cursor (w, glyph_row);
5302 break;
5303
5304 case FILLED_BOX_CURSOR:
f9e65eb3 5305 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
1a578e9b
AC
5306 break;
5307
5308 case BAR_CURSOR:
e3564461
ST
5309 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5310 break;
5311
5312 case HBAR_CURSOR:
5313 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
1a578e9b
AC
5314 break;
5315
5316 case NO_CURSOR:
e3564461 5317 w->phys_cursor_width = 0;
1a578e9b
AC
5318 break;
5319
5320 default:
5321 abort ();
5322 }
1a578e9b 5323 }
1a578e9b
AC
5324}
5325
e0f712ba
AC
5326\f
5327/* Icons. */
1a578e9b 5328
e0f712ba 5329#if 0 /* MAC_TODO: no icon support yet. */
1a578e9b 5330int
e0f712ba 5331x_bitmap_icon (f, icon)
1a578e9b 5332 struct frame *f;
e0f712ba 5333 Lisp_Object icon;
1a578e9b 5334{
e0f712ba 5335 HANDLE hicon;
1a578e9b 5336
e0f712ba 5337 if (FRAME_W32_WINDOW (f) == 0)
1a578e9b
AC
5338 return 1;
5339
e0f712ba
AC
5340 if (NILP (icon))
5341 hicon = LoadIcon (hinst, EMACS_CLASS);
5342 else if (STRINGP (icon))
d5db4077 5343 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
e0f712ba
AC
5344 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5345 else if (SYMBOLP (icon))
5346 {
5347 LPCTSTR name;
5348
5349 if (EQ (icon, intern ("application")))
5350 name = (LPCTSTR) IDI_APPLICATION;
5351 else if (EQ (icon, intern ("hand")))
5352 name = (LPCTSTR) IDI_HAND;
5353 else if (EQ (icon, intern ("question")))
5354 name = (LPCTSTR) IDI_QUESTION;
5355 else if (EQ (icon, intern ("exclamation")))
5356 name = (LPCTSTR) IDI_EXCLAMATION;
5357 else if (EQ (icon, intern ("asterisk")))
5358 name = (LPCTSTR) IDI_ASTERISK;
5359 else if (EQ (icon, intern ("winlogo")))
5360 name = (LPCTSTR) IDI_WINLOGO;
5361 else
5362 return 1;
1a578e9b 5363
e0f712ba 5364 hicon = LoadIcon (NULL, name);
1a578e9b 5365 }
e0f712ba 5366 else
1a578e9b
AC
5367 return 1;
5368
e0f712ba
AC
5369 if (hicon == NULL)
5370 return 1;
1a578e9b 5371
e0f712ba
AC
5372 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5373 (LPARAM) hicon);
1a578e9b
AC
5374
5375 return 0;
5376}
e0f712ba 5377#endif /* MAC_TODO */
1a578e9b 5378\f
e0f712ba
AC
5379/************************************************************************
5380 Handling X errors
5381 ************************************************************************/
1a578e9b 5382
e0f712ba
AC
5383/* Display Error Handling functions not used on W32. Listing them here
5384 helps diff stay in step when comparing w32term.c with xterm.c.
1a578e9b 5385
1a578e9b 5386x_error_catcher (display, error)
1a578e9b 5387x_catch_errors (dpy)
1a578e9b 5388x_catch_errors_unwind (old_val)
1a578e9b 5389x_check_errors (dpy, format)
1a578e9b 5390x_had_errors_p (dpy)
1a578e9b 5391x_clear_errors (dpy)
1a578e9b 5392x_uncatch_errors (dpy, count)
1a578e9b 5393x_trace_wire ()
e0f712ba
AC
5394x_connection_signal (signalnum)
5395x_connection_closed (dpy, error_message)
1a578e9b 5396x_error_quitter (display, error)
1a578e9b 5397x_error_handler (display, error)
1a578e9b 5398x_io_error_quitter (display)
1a578e9b 5399
e0f712ba
AC
5400 */
5401
1a578e9b
AC
5402\f
5403/* Changing the font of the frame. */
5404
5405/* Give frame F the font named FONTNAME as its default font, and
5406 return the full name of that font. FONTNAME may be a wildcard
5407 pattern; in that case, we choose some font that fits the pattern.
5408 The return value shows which font we chose. */
5409
5410Lisp_Object
5411x_new_font (f, fontname)
5412 struct frame *f;
5413 register char *fontname;
5414{
5415 struct font_info *fontp
5416 = FS_LOAD_FONT (f, 0, fontname, -1);
5417
5418 if (!fontp)
5419 return Qnil;
5420
e0f712ba
AC
5421 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5422 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5423 FRAME_FONTSET (f) = -1;
5424
e169f939
ST
5425 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5426 FRAME_SPACE_WIDTH (f) = fontp->space_width;
f1a83aab
KS
5427 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5428
5429 compute_fringe_widths (f, 1);
5430
1a578e9b 5431 /* Compute the scroll bar width in character columns. */
f1a83aab 5432 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
1a578e9b 5433 {
f1a83aab 5434 int wid = FRAME_COLUMN_WIDTH (f);
ffe8b3f4 5435 FRAME_CONFIG_SCROLL_BAR_COLS (f)
f1a83aab 5436 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
1a578e9b
AC
5437 }
5438 else
5439 {
f1a83aab
KS
5440 int wid = FRAME_COLUMN_WIDTH (f);
5441 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
1a578e9b
AC
5442 }
5443
5444 /* Now make the frame display the given font. */
5445 if (FRAME_MAC_WINDOW (f) != 0)
5446 {
f00691a3 5447 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
f1a83aab 5448 FRAME_FONT (f));
f00691a3 5449 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
f1a83aab 5450 FRAME_FONT (f));
f00691a3 5451 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
f1a83aab 5452 FRAME_FONT (f));
f00691a3 5453
b15325b2
ST
5454 /* Don't change the size of a tip frame; there's no point in
5455 doing it because it's done in Fx_show_tip, and it leads to
5456 problems because the tip frame has no widget. */
e0f712ba 5457 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
f1a83aab 5458 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
1a578e9b 5459 }
1a578e9b
AC
5460
5461 return build_string (fontp->full_name);
5462}
b15325b2 5463
1a578e9b 5464/* Give frame F the fontset named FONTSETNAME as its default font, and
e0f712ba
AC
5465 return the full name of that fontset. FONTSETNAME may be a wildcard
5466 pattern; in that case, we choose some fontset that fits the pattern.
5467 The return value shows which fontset we chose. */
1a578e9b
AC
5468
5469Lisp_Object
5470x_new_fontset (f, fontsetname)
5471 struct frame *f;
5472 char *fontsetname;
5473{
5474 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5475 Lisp_Object result;
5476
5477 if (fontset < 0)
5478 return Qnil;
5479
e0f712ba 5480 if (FRAME_FONTSET (f) == fontset)
1a578e9b
AC
5481 /* This fontset is already set in frame F. There's nothing more
5482 to do. */
5483 return fontset_name (fontset);
5484
d5db4077 5485 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
1a578e9b
AC
5486
5487 if (!STRINGP (result))
5488 /* Can't load ASCII font. */
5489 return Qnil;
5490
e0f712ba 5491 /* Since x_new_font doesn't update any fontset information, do it now. */
7ca7ccd5 5492 FRAME_FONTSET (f) = fontset;
1a578e9b 5493
1a578e9b
AC
5494 return build_string (fontsetname);
5495}
5496
1a578e9b
AC
5497\f
5498/***********************************************************************
e0f712ba 5499 TODO: W32 Input Methods
1a578e9b 5500 ***********************************************************************/
e0f712ba 5501/* Listing missing functions from xterm.c helps diff stay in step.
1a578e9b 5502
1a578e9b 5503xim_destroy_callback (xim, client_data, call_data)
1a578e9b 5504xim_open_dpy (dpyinfo, resource_name)
1a578e9b 5505struct xim_inst_t
1a578e9b 5506xim_instantiate_callback (display, client_data, call_data)
1a578e9b 5507xim_initialize (dpyinfo, resource_name)
1a578e9b 5508xim_close_dpy (dpyinfo)
1a578e9b 5509
e0f712ba 5510 */
1a578e9b 5511
1a578e9b 5512\f
bf06c82f 5513void
bed0bf95
YM
5514mac_handle_origin_change (f)
5515 struct frame *f;
5516{
5517 x_real_positions (f, &f->left_pos, &f->top_pos);
5518}
5519
f2ec385e 5520void
bed0bf95
YM
5521mac_handle_size_change (f, pixelwidth, pixelheight)
5522 struct frame *f;
5523 int pixelwidth, pixelheight;
5524{
5525 int cols, rows;
5526
5527 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
5528 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
5529
5530 if (cols != FRAME_COLS (f)
5531 || rows != FRAME_LINES (f)
5532 || pixelwidth != FRAME_PIXEL_WIDTH (f)
5533 || pixelheight != FRAME_PIXEL_HEIGHT (f))
5534 {
5535 /* We pass 1 for DELAY since we can't run Lisp code inside of
5536 a BLOCK_INPUT. */
5537 change_frame_size (f, rows, cols, 0, 1, 0);
5538 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5539 FRAME_PIXEL_HEIGHT (f) = pixelheight;
bed0bf95
YM
5540
5541 /* If cursor was outside the new size, mark it as off. */
5542 mark_window_cursors_off (XWINDOW (f->root_window));
5543
5544 /* Clear out any recollection of where the mouse highlighting
5545 was, since it might be in a place that's outside the new
5546 frame size. Actually checking whether it is outside is a
5547 pain in the neck, so don't try--just let the highlighting be
5548 done afresh with new size. */
5549 cancel_mouse_face (f);
5550
5551#if TARGET_API_MAC_CARBON
f2ec385e 5552 mac_reposition_hourglass (f);
bed0bf95
YM
5553#endif
5554 }
5555}
bf06c82f 5556
95dfb192 5557\f
1a578e9b
AC
5558/* Calculate the absolute position in frame F
5559 from its current recorded position values and gravity. */
5560
e0f712ba 5561void
1a578e9b
AC
5562x_calc_absolute_position (f)
5563 struct frame *f;
5564{
f1a83aab 5565 int flags = f->size_hint_flags;
bf06c82f 5566 Rect inner, outer;
1a578e9b 5567
bf06c82f
ST
5568 /* We have nothing to do if the current position
5569 is already for the top-left corner. */
5570 if (! ((flags & XNegative) || (flags & YNegative)))
5571 return;
1a578e9b 5572
bf06c82f 5573 /* Find the offsets of the outside upper-left corner of
1a578e9b 5574 the inner window, with respect to the outer window. */
1d5bcd55 5575 BLOCK_INPUT;
bf06c82f 5576 mac_get_window_bounds (f, &inner, &outer);
1d5bcd55 5577 UNBLOCK_INPUT;
e0f712ba 5578
1a578e9b
AC
5579 /* Treat negative positions as relative to the leftmost bottommost
5580 position that fits on the screen. */
5581 if (flags & XNegative)
834263b6
YM
5582 f->left_pos += (FRAME_MAC_DISPLAY_INFO (f)->width
5583 - (outer.right - outer.left));
bf06c82f 5584
1a578e9b 5585 if (flags & YNegative)
834263b6
YM
5586 f->top_pos += (FRAME_MAC_DISPLAY_INFO (f)->height
5587 - (outer.bottom - outer.top));
bf06c82f 5588
1a578e9b
AC
5589 /* The left_pos and top_pos
5590 are now relative to the top and left screen edges,
5591 so the flags should correspond. */
f1a83aab 5592 f->size_hint_flags &= ~ (XNegative | YNegative);
1a578e9b
AC
5593}
5594
5595/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5596 to really change the position, and 0 when calling from
5597 x_make_frame_visible (in that case, XOFF and YOFF are the current
5598 position values). It is -1 when calling from x_set_frame_parameters,
5599 which means, do adjust for borders but don't change the gravity. */
5600
5601void
5602x_set_offset (f, xoff, yoff, change_gravity)
5603 struct frame *f;
5604 register int xoff, yoff;
5605 int change_gravity;
5606{
5607 if (change_gravity > 0)
5608 {
f1a83aab
KS
5609 f->top_pos = yoff;
5610 f->left_pos = xoff;
5611 f->size_hint_flags &= ~ (XNegative | YNegative);
1a578e9b 5612 if (xoff < 0)
f1a83aab 5613 f->size_hint_flags |= XNegative;
1a578e9b 5614 if (yoff < 0)
f1a83aab
KS
5615 f->size_hint_flags |= YNegative;
5616 f->win_gravity = NorthWestGravity;
1a578e9b
AC
5617 }
5618 x_calc_absolute_position (f);
5619
5620 BLOCK_INPUT;
5621 x_wm_set_size_hint (f, (long) 0, 0);
5622
bf06c82f 5623#if TARGET_API_MAC_CARBON
f2ec385e 5624 mac_move_window_structure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
bf06c82f
ST
5625 /* If the title bar is completely outside the screen, adjust the
5626 position. */
5627 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5628 kWindowConstrainMoveRegardlessOfFit
5629 | kWindowConstrainAllowPartial, NULL, NULL);
bed0bf95 5630 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
bed0bf95 5631 mac_handle_origin_change (f);
bf06c82f
ST
5632#else
5633 {
5634 Rect inner, outer, screen_rect, dummy;
5635 RgnHandle region = NewRgn ();
f94a2622 5636
bf06c82f
ST
5637 mac_get_window_bounds (f, &inner, &outer);
5638 f->x_pixels_diff = inner.left - outer.left;
5639 f->y_pixels_diff = inner.top - outer.top;
5640 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5641 f->top_pos + f->y_pixels_diff, false);
5642
5643 /* If the title bar is completely outside the screen, adjust the
5644 position. The variable `outer' holds the title bar rectangle.
5645 The variable `inner' holds slightly smaller one than `outer',
5646 so that the calculation of overlapping may not become too
5647 strict. */
5648 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5649 outer = (*region)->rgnBBox;
5650 DisposeRgn (region);
5651 inner = outer;
5652 InsetRect (&inner, 8, 8);
5653 screen_rect = qd.screenBits.bounds;
5654 screen_rect.top += GetMBarHeight ();
5655
5656 if (!SectRect (&inner, &screen_rect, &dummy))
5657 {
5658 if (inner.right <= screen_rect.left)
5659 f->left_pos = screen_rect.left;
5660 else if (inner.left >= screen_rect.right)
5661 f->left_pos = screen_rect.right - (outer.right - outer.left);
5662
5663 if (inner.bottom <= screen_rect.top)
5664 f->top_pos = screen_rect.top;
5665 else if (inner.top >= screen_rect.bottom)
5666 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5667
5668 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5669 f->top_pos + f->y_pixels_diff, false);
5670 }
5671 }
5672#endif
1a578e9b
AC
5673
5674 UNBLOCK_INPUT;
5675}
5676
5677/* Call this to change the size of frame F's x-window.
5678 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5679 for this size change and subsequent size changes.
5680 Otherwise we leave the window gravity unchanged. */
5681
5682void
5683x_set_window_size (f, change_gravity, cols, rows)
5684 struct frame *f;
5685 int change_gravity;
5686 int cols, rows;
5687{
5688 int pixelwidth, pixelheight;
177c0ea7 5689
e0f712ba 5690 BLOCK_INPUT;
177c0ea7 5691
1a578e9b 5692 check_frame_size (f, &rows, &cols);
f1a83aab
KS
5693 f->scroll_bar_actual_width
5694 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
d33c49e8 5695
5958f265 5696 compute_fringe_widths (f, 0);
d33c49e8 5697
f1a83aab
KS
5698 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5699 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
1a578e9b 5700
f1a83aab 5701 f->win_gravity = NorthWestGravity;
1a578e9b
AC
5702 x_wm_set_size_hint (f, (long) 0, 0);
5703
f2ec385e 5704 mac_size_window (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
1a578e9b 5705
660425fa 5706#if TARGET_API_MAC_CARBON
bed0bf95
YM
5707 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
5708#endif
5709 mac_handle_size_change (f, pixelwidth, pixelheight);
e0f712ba 5710
70385fe6
YM
5711 if (f->output_data.mac->internal_border_width
5712 != FRAME_INTERNAL_BORDER_WIDTH (f))
5713 {
5714 mac_clear_window (f);
5715 f->output_data.mac->internal_border_width
5716 = FRAME_INTERNAL_BORDER_WIDTH (f);
5717 }
5718
5719 SET_FRAME_GARBAGED (f);
5720
e0f712ba 5721 UNBLOCK_INPUT;
1a578e9b
AC
5722}
5723\f
5724/* Mouse warping. */
5725
5726void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5727
5728void
5729x_set_mouse_position (f, x, y)
5730 struct frame *f;
5731 int x, y;
5732{
5733 int pix_x, pix_y;
5734
f1a83aab
KS
5735 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5736 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
1a578e9b
AC
5737
5738 if (pix_x < 0) pix_x = 0;
f1a83aab 5739 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
1a578e9b
AC
5740
5741 if (pix_y < 0) pix_y = 0;
f1a83aab 5742 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
1a578e9b
AC
5743
5744 x_set_mouse_pixel_position (f, pix_x, pix_y);
5745}
5746
1a578e9b
AC
5747void
5748x_set_mouse_pixel_position (f, pix_x, pix_y)
5749 struct frame *f;
5750 int pix_x, pix_y;
5751{
92289429 5752#ifdef MAC_OSX
92289429 5753 BLOCK_INPUT;
f2ec385e 5754 mac_convert_frame_point_to_global (f, &pix_x, &pix_y);
660425fa 5755 CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
92289429
YM
5756 UNBLOCK_INPUT;
5757#else
5758#if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
1a578e9b
AC
5759 BLOCK_INPUT;
5760
5761 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5762 0, 0, 0, 0, pix_x, pix_y);
5763 UNBLOCK_INPUT;
5764#endif
92289429 5765#endif
1a578e9b
AC
5766}
5767\f
5768/* focus shifting, raising and lowering. */
5769
e0f712ba 5770void
1a578e9b
AC
5771x_focus_on_frame (f)
5772 struct frame *f;
5773{
5774#if 0 /* This proves to be unpleasant. */
5775 x_raise_frame (f);
5776#endif
5777#if 0
5778 /* I don't think that the ICCCM allows programs to do things like this
5779 without the interaction of the window manager. Whatever you end up
5780 doing with this code, do it to x_unfocus_frame too. */
5781 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5782 RevertToPointerRoot, CurrentTime);
5783#endif /* ! 0 */
5784}
5785
e0f712ba 5786void
1a578e9b
AC
5787x_unfocus_frame (f)
5788 struct frame *f;
5789{
1a578e9b
AC
5790}
5791
5792/* Raise frame F. */
95dfb192 5793
1a578e9b
AC
5794void
5795x_raise_frame (f)
5796 struct frame *f;
5797{
5798 if (f->async_visible)
c3f4c690
ST
5799 {
5800 BLOCK_INPUT;
f2ec385e 5801 mac_bring_window_to_front (FRAME_MAC_WINDOW (f));
c3f4c690
ST
5802 UNBLOCK_INPUT;
5803 }
1a578e9b
AC
5804}
5805
5806/* Lower frame F. */
95dfb192 5807
1a578e9b
AC
5808void
5809x_lower_frame (f)
5810 struct frame *f;
5811{
5812 if (f->async_visible)
c3f4c690
ST
5813 {
5814 BLOCK_INPUT;
f2ec385e 5815 mac_send_window_behind (FRAME_MAC_WINDOW (f), NULL);
c3f4c690
ST
5816 UNBLOCK_INPUT;
5817 }
1a578e9b
AC
5818}
5819
e0f712ba 5820static void
1a578e9b
AC
5821XTframe_raise_lower (f, raise_flag)
5822 FRAME_PTR f;
5823 int raise_flag;
5824{
5825 if (raise_flag)
5826 x_raise_frame (f);
5827 else
5828 x_lower_frame (f);
5829}
5830\f
5831/* Change of visibility. */
5832
f2ec385e 5833void
1f98fbb4
YM
5834mac_handle_visibility_change (f)
5835 struct frame *f;
5836{
f2ec385e 5837 Window wp = FRAME_MAC_WINDOW (f);
1f98fbb4
YM
5838 int visible = 0, iconified = 0;
5839 struct input_event buf;
5840
f2ec385e 5841 if (mac_is_window_visible (wp))
f93e4d4f 5842 {
f2ec385e 5843 if (mac_is_window_collapsed (wp))
f93e4d4f
YM
5844 iconified = 1;
5845 else
5846 visible = 1;
5847 }
1f98fbb4
YM
5848
5849 if (!f->async_visible && visible)
5850 {
5851 if (f->iconified)
5852 {
5853 /* wait_reading_process_output will notice this and update
5854 the frame's display structures. If we were made
5855 invisible, we should not set garbaged, because that stops
5856 redrawing on Update events. */
5857 SET_FRAME_GARBAGED (f);
5858
5859 EVENT_INIT (buf);
5860 buf.kind = DEICONIFY_EVENT;
5861 XSETFRAME (buf.frame_or_window, f);
36f0107c 5862 buf.arg = Qnil;
1f98fbb4
YM
5863 kbd_buffer_store_event (&buf);
5864 }
5865 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
5866 /* Force a redisplay sooner or later to update the
5867 frame titles in case this is the second frame. */
5868 record_asynch_buffer_change ();
5869 }
5870 else if (f->async_visible && !visible)
5871 if (iconified)
5872 {
5873 EVENT_INIT (buf);
5874 buf.kind = ICONIFY_EVENT;
5875 XSETFRAME (buf.frame_or_window, f);
36f0107c 5876 buf.arg = Qnil;
1f98fbb4
YM
5877 kbd_buffer_store_event (&buf);
5878 }
5879
5880 f->async_visible = visible;
5881 f->async_iconified = iconified;
5882}
5883
1a578e9b
AC
5884/* This tries to wait until the frame is really visible.
5885 However, if the window manager asks the user where to position
5886 the frame, this will return before the user finishes doing that.
5887 The frame will not actually be visible at that time,
5888 but it will become visible later when the window manager
5889 finishes with it. */
5890
5891void
5892x_make_frame_visible (f)
5893 struct frame *f;
5894{
1a578e9b
AC
5895 BLOCK_INPUT;
5896
5897 if (! FRAME_VISIBLE_P (f))
5898 {
5899 /* We test FRAME_GARBAGED_P here to make sure we don't
660425fa
YM
5900 call x_set_offset a second time
5901 if we get to x_make_frame_visible a second time
5902 before the window gets really visible. */
5903 if (! FRAME_ICONIFIED_P (f)
5904 && ! f->output_data.mac->asked_for_visible)
5905 x_set_offset (f, f->left_pos, f->top_pos, 0);
1f98fbb4
YM
5906
5907 f->output_data.mac->asked_for_visible = 1;
5908
f2ec385e
YM
5909 mac_collapse_window (FRAME_MAC_WINDOW (f), false);
5910 mac_show_window (FRAME_MAC_WINDOW (f));
1a578e9b
AC
5911 }
5912
5913 XFlush (FRAME_MAC_DISPLAY (f));
5914
5915 /* Synchronize to ensure Emacs knows the frame is visible
5916 before we do anything else. We do this loop with input not blocked
5917 so that incoming events are handled. */
5918 {
5919 Lisp_Object frame;
5920 int count;
5921
5922 /* This must come after we set COUNT. */
5923 UNBLOCK_INPUT;
5924
5925 XSETFRAME (frame, f);
5926
5927 /* Wait until the frame is visible. Process X events until a
5928 MapNotify event has been seen, or until we think we won't get a
5929 MapNotify at all.. */
5930 for (count = input_signal_count + 10;
5931 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5932 {
5933 /* Force processing of queued events. */
5934 x_sync (f);
5935
5936 /* Machines that do polling rather than SIGIO have been
5937 observed to go into a busy-wait here. So we'll fake an
5938 alarm signal to let the handler know that there's something
5939 to be read. We used to raise a real alarm, but it seems
5940 that the handler isn't always enabled here. This is
5941 probably a bug. */
5942 if (input_polling_used ())
5943 {
5944 /* It could be confusing if a real alarm arrives while
5945 processing the fake one. Turn it off and let the
5946 handler reset it. */
5947 extern void poll_for_input_1 P_ ((void));
5948 int old_poll_suppress_count = poll_suppress_count;
5949 poll_suppress_count = 1;
5950 poll_for_input_1 ();
5951 poll_suppress_count = old_poll_suppress_count;
5952 }
5953
5954 /* See if a MapNotify event has been processed. */
5955 FRAME_SAMPLE_VISIBILITY (f);
5956 }
5957 }
5958}
5959
5960/* Change from mapped state to withdrawn state. */
5961
5962/* Make the frame visible (mapped and not iconified). */
5963
5964void
5965x_make_frame_invisible (f)
5966 struct frame *f;
5967{
1f98fbb4
YM
5968 /* A deactivate event does not occur when the last visible frame is
5969 made invisible. So if we clear the highlight here, it will not
5970 be rehighlighted when it is made visible. */
5971#if 0
1a578e9b
AC
5972 /* Don't keep the highlight on an invisible frame. */
5973 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5974 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
1f98fbb4 5975#endif
177c0ea7 5976
1a578e9b 5977 BLOCK_INPUT;
177c0ea7 5978
660425fa 5979#if !TARGET_API_MAC_CARBON
7ca7ccd5
YM
5980 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5981 that the current position of the window is user-specified, rather than
5982 program-specified, so that when the window is mapped again, it will be
5983 placed at the same location, without forcing the user to position it
5984 by hand again (they have already done that once for this window.) */
5985 x_wm_set_size_hint (f, (long) 0, 1);
660425fa 5986#endif
7ca7ccd5 5987
f2ec385e 5988 mac_hide_window (FRAME_MAC_WINDOW (f));
177c0ea7 5989
1a578e9b 5990 UNBLOCK_INPUT;
1f98fbb4 5991
660425fa 5992#if !TARGET_API_MAC_CARBON
1f98fbb4
YM
5993 mac_handle_visibility_change (f);
5994#endif
1a578e9b
AC
5995}
5996
5997/* Change window state from mapped to iconified. */
5998
5999void
6000x_iconify_frame (f)
6001 struct frame *f;
6002{
3e7424f7 6003 OSStatus err;
1f98fbb4
YM
6004
6005 /* A deactivate event does not occur when the last visible frame is
6006 iconified. So if we clear the highlight here, it will not be
6007 rehighlighted when it is deiconified. */
6008#if 0
1a578e9b 6009 /* Don't keep the highlight on an invisible frame. */
742fbed7
AC
6010 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6011 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
1f98fbb4 6012#endif
1a578e9b
AC
6013
6014 if (f->async_iconified)
6015 return;
6016
6017 BLOCK_INPUT;
6018
1f98fbb4
YM
6019 FRAME_SAMPLE_VISIBILITY (f);
6020
6021 if (! FRAME_VISIBLE_P (f))
f2ec385e 6022 mac_show_window (FRAME_MAC_WINDOW (f));
1f98fbb4 6023
f2ec385e 6024 err = mac_collapse_window (FRAME_MAC_WINDOW (f), true);
177c0ea7 6025
1a578e9b 6026 UNBLOCK_INPUT;
1f98fbb4
YM
6027
6028 if (err != noErr)
6029 error ("Can't notify window manager of iconification");
6030
660425fa 6031#if !TARGET_API_MAC_CARBON
1f98fbb4
YM
6032 mac_handle_visibility_change (f);
6033#endif
1a578e9b 6034}
e0f712ba 6035
1a578e9b 6036\f
e3564461 6037/* Free X resources of frame F. */
1a578e9b
AC
6038
6039void
e3564461 6040x_free_frame_resources (f)
1a578e9b
AC
6041 struct frame *f;
6042{
6043 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
f2ec385e 6044 Window wp = FRAME_MAC_WINDOW (f);
1a578e9b
AC
6045
6046 BLOCK_INPUT;
6047
f2ec385e
YM
6048 /* AppKit version of mac_dispose_frame_window, which is implemented
6049 as -[NSWindow close], will change the focus to the next window
6050 during its call. So, unlike other platforms, we clean up the
6051 focus-related variables before calling mac_dispose_frame_window. */
1a578e9b 6052 if (f == dpyinfo->x_focus_frame)
4cb62a90
YM
6053 {
6054 dpyinfo->x_focus_frame = 0;
6055#if USE_MAC_FONT_PANEL
6056 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
6057#endif
6058 }
1a578e9b
AC
6059 if (f == dpyinfo->x_focus_event_frame)
6060 dpyinfo->x_focus_event_frame = 0;
6061 if (f == dpyinfo->x_highlight_frame)
6062 dpyinfo->x_highlight_frame = 0;
6063
1a578e9b
AC
6064 if (f == dpyinfo->mouse_face_mouse_frame)
6065 {
6066 dpyinfo->mouse_face_beg_row
6067 = dpyinfo->mouse_face_beg_col = -1;
6068 dpyinfo->mouse_face_end_row
6069 = dpyinfo->mouse_face_end_col = -1;
6070 dpyinfo->mouse_face_window = Qnil;
6071 dpyinfo->mouse_face_deferred_gc = 0;
6072 dpyinfo->mouse_face_mouse_frame = 0;
6073 }
6074
f2ec385e
YM
6075 mac_dispose_frame_window (f);
6076 if (wp == tip_window)
6077 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6078 closed' event. So we reset tip_window here. */
6079 tip_window = NULL;
6080
6081 free_frame_menubar (f);
6082
6083 if (FRAME_FACE_CACHE (f))
6084 free_frame_faces (f);
6085
6086 x_free_gcs (f);
6087
6088 if (FRAME_SIZE_HINTS (f))
6089 xfree (FRAME_SIZE_HINTS (f));
6090
6091 xfree (f->output_data.mac);
6092 f->output_data.mac = NULL;
6093
1a578e9b
AC
6094 UNBLOCK_INPUT;
6095}
e3564461
ST
6096
6097
6098/* Destroy the X window of frame F. */
6099
6100void
6101x_destroy_window (f)
6102 struct frame *f;
6103{
6104 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6105
6106 x_free_frame_resources (f);
6107
6108 dpyinfo->reference_count--;
6109}
6110
1a578e9b
AC
6111\f
6112/* Setting window manager hints. */
6113
6114/* Set the normal size hints for the window manager, for frame F.
6115 FLAGS is the flags word to use--or 0 meaning preserve the flags
6116 that the window now has.
6117 If USER_POSITION is nonzero, we set the USPosition
6118 flag (this is useful when FLAGS is 0). */
1a578e9b
AC
6119void
6120x_wm_set_size_hint (f, flags, user_position)
6121 struct frame *f;
6122 long flags;
6123 int user_position;
6124{
b15325b2
ST
6125 int base_width, base_height, width_inc, height_inc;
6126 int min_rows = 0, min_cols = 0;
6127 XSizeHints *size_hints;
1a578e9b 6128
b15325b2
ST
6129 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6130 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6131 width_inc = FRAME_COLUMN_WIDTH (f);
6132 height_inc = FRAME_LINE_HEIGHT (f);
1a578e9b 6133
b15325b2 6134 check_frame_size (f, &min_rows, &min_cols);
1a578e9b 6135
b15325b2
ST
6136 size_hints = FRAME_SIZE_HINTS (f);
6137 if (size_hints == NULL)
1a578e9b 6138 {
b15325b2
ST
6139 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6140 bzero (size_hints, sizeof (XSizeHints));
1a578e9b 6141 }
1a578e9b 6142
b15325b2
ST
6143 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6144 size_hints->width_inc = width_inc;
6145 size_hints->height_inc = height_inc;
6146 size_hints->min_width = base_width + min_cols * width_inc;
6147 size_hints->min_height = base_height + min_rows * height_inc;
6148 size_hints->base_width = base_width;
6149 size_hints->base_height = base_height;
1a578e9b 6150
b15325b2
ST
6151 if (flags)
6152 size_hints->flags = flags;
6153 else if (user_position)
1a578e9b 6154 {
b15325b2
ST
6155 size_hints->flags &= ~ PPosition;
6156 size_hints->flags |= USPosition;
1a578e9b 6157 }
1a578e9b
AC
6158}
6159
e0f712ba 6160#if 0 /* MAC_TODO: hide application instead of iconify? */
1a578e9b
AC
6161/* Used for IconicState or NormalState */
6162
6163void
6164x_wm_set_window_state (f, state)
6165 struct frame *f;
6166 int state;
6167{
6168#ifdef USE_X_TOOLKIT
6169 Arg al[1];
6170
6171 XtSetArg (al[0], XtNinitialState, state);
6172 XtSetValues (f->output_data.x->widget, al, 1);
6173#else /* not USE_X_TOOLKIT */
6174 Window window = FRAME_X_WINDOW (f);
6175
6176 f->output_data.x->wm_hints.flags |= StateHint;
6177 f->output_data.x->wm_hints.initial_state = state;
6178
6179 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6180#endif /* not USE_X_TOOLKIT */
6181}
6182
6183void
6184x_wm_set_icon_pixmap (f, pixmap_id)
6185 struct frame *f;
6186 int pixmap_id;
6187{
6188 Pixmap icon_pixmap;
6189
6190#ifndef USE_X_TOOLKIT
6191 Window window = FRAME_X_WINDOW (f);
6192#endif
6193
6194 if (pixmap_id > 0)
6195 {
6196 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6197 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6198 }
6199 else
6200 {
6201 /* It seems there is no way to turn off use of an icon pixmap.
6202 The following line does it, only if no icon has yet been created,
6203 for some window managers. But with mwm it crashes.
6204 Some people say it should clear the IconPixmapHint bit in this case,
6205 but that doesn't work, and the X consortium said it isn't the
6206 right thing at all. Since there is no way to win,
6207 best to explicitly give up. */
6208#if 0
6209 f->output_data.x->wm_hints.icon_pixmap = None;
6210#else
6211 return;
6212#endif
6213 }
6214
6215#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6216
6217 {
6218 Arg al[1];
6219 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6220 XtSetValues (f->output_data.x->widget, al, 1);
6221 }
6222
6223#else /* not USE_X_TOOLKIT */
177c0ea7 6224
1a578e9b
AC
6225 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6226 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6227
6228#endif /* not USE_X_TOOLKIT */
6229}
6230
e0f712ba 6231#endif /* MAC_TODO */
1a578e9b
AC
6232
6233void
6234x_wm_set_icon_position (f, icon_x, icon_y)
6235 struct frame *f;
6236 int icon_x, icon_y;
6237{
6238#if 0 /* MAC_TODO: no icons on Mac */
6239#ifdef USE_X_TOOLKIT
6240 Window window = XtWindow (f->output_data.x->widget);
6241#else
6242 Window window = FRAME_X_WINDOW (f);
6243#endif
6244
6245 f->output_data.x->wm_hints.flags |= IconPositionHint;
6246 f->output_data.x->wm_hints.icon_x = icon_x;
6247 f->output_data.x->wm_hints.icon_y = icon_y;
6248
6249 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
e0f712ba 6250#endif /* MAC_TODO */
1a578e9b
AC
6251}
6252
6253\f
468213f1
YM
6254/***********************************************************************
6255 XLFD Pattern Match
6256 ***********************************************************************/
6257
6258/* An XLFD pattern is divided into blocks delimited by '*'. This
6259 structure holds information for each block. */
6260struct xlfdpat_block
6261{
6262 /* Length of the pattern string in this block. Non-zero except for
6263 the first and the last blocks. */
6264 int len;
6265
6266 /* Pattern string except the last character in this block. The last
6267 character is replaced with NUL in order to use it as a
6268 sentinel. */
6269 unsigned char *pattern;
6270
6271 /* Last character of the pattern string. Must not be '?'. */
6272 unsigned char last_char;
6273
6274 /* One of the tables for the Boyer-Moore string search. It
6275 specifies the number of positions to proceed for each character
6276 with which the match fails. */
6277 int skip[256];
6278
6279 /* The skip value for the last character in the above `skip' is
6280 assigned to `infinity' in order to simplify a loop condition.
6281 The original value is saved here. */
6282 int last_char_skip;
6283};
6284
6285struct xlfdpat
6286{
6287 /* Normalized pattern string. "Normalized" means that capital
6288 letters are lowered, blocks are not empty except the first and
6289 the last ones, and trailing '?'s in a block that is not the last
6290 one are moved to the next one. The last character in each block
6291 is replaced with NUL. */
6292 unsigned char *buf;
6293
6294 /* Number of characters except '*'s and trailing '?'s in the
6295 normalized pattern string. */
6296 int nchars;
6297
6298 /* Number of trailing '?'s in the normalized pattern string. */
6299 int trailing_anychars;
6300
6301 /* Number of blocks and information for each block. The latter is
6302 NULL if the pattern is exact (no '*' or '?' in it). */
6303 int nblocks;
6304 struct xlfdpat_block *blocks;
6305};
6306
6307static void
6308xlfdpat_destroy (pat)
6309 struct xlfdpat *pat;
6310{
6311 if (pat)
6312 {
6313 if (pat->buf)
6314 {
6315 if (pat->blocks)
6316 xfree (pat->blocks);
6317 xfree (pat->buf);
6318 }
6319 xfree (pat);
6320 }
6321}
6322
6323static struct xlfdpat *
6324xlfdpat_create (pattern)
369a7a37 6325 const char *pattern;
468213f1
YM
6326{
6327 struct xlfdpat *pat;
6328 int nblocks, i, skip;
6329 unsigned char last_char, *p, *q, *anychar_head;
369a7a37 6330 const unsigned char *ptr;
468213f1
YM
6331 struct xlfdpat_block *blk;
6332
6333 pat = xmalloc (sizeof (struct xlfdpat));
468213f1 6334 pat->buf = xmalloc (strlen (pattern) + 1);
468213f1
YM
6335
6336 /* Normalize the pattern string and store it to `pat->buf'. */
6337 nblocks = 0;
6338 anychar_head = NULL;
6339 q = pat->buf;
6340 last_char = '\0';
369a7a37 6341 for (ptr = pattern; *ptr; ptr++)
468213f1 6342 {
369a7a37 6343 unsigned char c = *ptr;
468213f1
YM
6344
6345 if (c == '*')
6346 if (last_char == '*')
6347 /* ...a** -> ...a* */
6348 continue;
6349 else
6350 {
6351 if (last_char == '?')
f93e4d4f
YM
6352 {
6353 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6354 /* ...*??* -> ...*?? */
6355 continue;
6356 else
6357 /* ...a??* -> ...a*?? */
6358 {
6359 *anychar_head++ = '*';
6360 c = '?';
6361 }
6362 }
468213f1
YM
6363 nblocks++;
6364 }
6365 else if (c == '?')
6366 {
6367 if (last_char != '?')
6368 anychar_head = q;
6369 }
6370 else
6371 /* On Mac OS X 10.3, tolower also converts non-ASCII
6372 characters for some locales. */
6373 if (isascii (c))
6374 c = tolower (c);
6375
6376 *q++ = last_char = c;
6377 }
6378 *q = '\0';
6379 nblocks++;
6380 pat->nblocks = nblocks;
6381 if (last_char != '?')
6382 pat->trailing_anychars = 0;
6383 else
6384 {
6385 pat->trailing_anychars = q - anychar_head;
6386 q = anychar_head;
6387 }
6388 pat->nchars = q - pat->buf - (nblocks - 1);
6389
6390 if (anychar_head == NULL && nblocks == 1)
6391 {
6392 /* The pattern is exact. */
6393 pat->blocks = NULL;
6394 return pat;
6395 }
6396
6397 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
468213f1
YM
6398
6399 /* Divide the normalized pattern into blocks. */
6400 p = pat->buf;
6401 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6402 {
6403 blk->pattern = p;
6404 while (*p != '*')
6405 p++;
6406 blk->len = p - blk->pattern;
6407 p++;
6408 }
6409 blk->pattern = p;
6410 blk->len = q - blk->pattern;
6411
6412 /* Setup a table for the Boyer-Moore string search. */
6413 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6414 if (blk->len != 0)
6415 {
6416 blk->last_char = blk->pattern[blk->len - 1];
6417 blk->pattern[blk->len - 1] = '\0';
6418
6419 for (skip = 1; skip < blk->len; skip++)
6420 if (blk->pattern[blk->len - skip - 1] == '?')
6421 break;
6422
6423 for (i = 0; i < 256; i++)
6424 blk->skip[i] = skip;
6425
6426 p = blk->pattern + (blk->len - skip);
6427 while (--skip > 0)
6428 blk->skip[*p++] = skip;
6429
6430 blk->last_char_skip = blk->skip[blk->last_char];
6431 }
6432
6433 return pat;
468213f1
YM
6434}
6435
6436static INLINE int
6437xlfdpat_exact_p (pat)
6438 struct xlfdpat *pat;
6439{
7c3d233d 6440 return pat->blocks == NULL;
468213f1
YM
6441}
6442
6443/* Return the first string in STRING + 0, ..., STRING + START_MAX such
6444 that the pattern in *BLK matches with its prefix. Return NULL
6445 there is no such strings. STRING must be lowered in advance. */
6446
369a7a37 6447static const char *
468213f1
YM
6448xlfdpat_block_match_1 (blk, string, start_max)
6449 struct xlfdpat_block *blk;
369a7a37 6450 const unsigned char *string;
468213f1
YM
6451 int start_max;
6452{
6453 int start, infinity;
369a7a37
YM
6454 unsigned char *p;
6455 const unsigned char *s;
468213f1
YM
6456
6457 xassert (blk->len > 0);
6458 xassert (start_max + blk->len <= strlen (string));
7c3d233d 6459 xassert (blk->last_char != '?');
468213f1
YM
6460
6461 /* See the comments in the function `boyer_moore' (search.c) for the
6462 use of `infinity'. */
6463 infinity = start_max + blk->len + 1;
6464 blk->skip[blk->last_char] = infinity;
6465
6466 start = 0;
6467 do
6468 {
6469 /* Check the last character of the pattern. */
6470 s = string + blk->len - 1;
6471 do
6472 {
6473 start += blk->skip[*(s + start)];
6474 }
6475 while (start <= start_max);
6476
6477 if (start < infinity)
6478 /* Couldn't find the last character. */
6479 return NULL;
6480
6481 /* No less than `infinity' means we could find the last
6482 character at `s[start - infinity]'. */
6483 start -= infinity;
6484
6485 /* Check the remaining characters. We prefer making no-'?'
6486 cases faster because the use of '?' is really rare. */
6487 p = blk->pattern;
6488 s = string + start;
6489 do
6490 {
6491 while (*p++ == *s++)
6492 ;
6493 }
6494 while (*(p - 1) == '?');
6495
6496 if (*(p - 1) == '\0')
6497 /* Matched. */
6498 return string + start;
6499
6500 /* Didn't match. */
6501 start += blk->last_char_skip;
6502 }
6503 while (start <= start_max);
6504
6505 return NULL;
6506}
6507
6508#define xlfdpat_block_match(b, s, m) \
6509 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6510 : xlfdpat_block_match_1 (b, s, m))
6511
369a7a37 6512/* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
468213f1
YM
6513 matches with STRING. STRING must be lowered in advance. */
6514
6515static int
6516xlfdpat_match (pat, string)
6517 struct xlfdpat *pat;
369a7a37 6518 const unsigned char *string;
468213f1
YM
6519{
6520 int str_len, nblocks, i, start_max;
6521 struct xlfdpat_block *blk;
369a7a37 6522 const unsigned char *s;
468213f1
YM
6523
6524 xassert (pat->nblocks > 0);
6525
6526 if (xlfdpat_exact_p (pat))
6527 return strcmp (pat->buf, string) == 0;
6528
6529 /* The number of the characters in the string must not be smaller
6530 than that in the pattern. */
6531 str_len = strlen (string);
6532 if (str_len < pat->nchars + pat->trailing_anychars)
6533 return 0;
6534
6535 /* Chop off the trailing '?'s. */
6536 str_len -= pat->trailing_anychars;
6537
6538 /* The last block. When it is non-empty, it must match at the end
6539 of the string. */
6540 nblocks = pat->nblocks;
6541 blk = pat->blocks + (nblocks - 1);
6542 if (nblocks == 1)
6543 /* The last block is also the first one. */
6544 return (str_len == blk->len
6545 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
6546 else if (blk->len != 0)
6547 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
6548 return 0;
6549
6550 /* The first block. When it is non-empty, it must match at the
6551 beginning of the string. */
6552 blk = pat->blocks;
6553 if (blk->len != 0)
6554 {
6555 s = xlfdpat_block_match (blk, string, 0);
6556 if (s == NULL)
6557 return 0;
6558 string = s + blk->len;
6559 }
6560
6561 /* The rest of the blocks. */
6562 start_max = str_len - pat->nchars;
6563 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
6564 {
6565 s = xlfdpat_block_match (blk, string, start_max);
6566 if (s == NULL)
6567 return 0;
6568 start_max -= s - string;
6569 string = s + blk->len;
6570 }
6571
6572 return 1;
6573}
6574
6575\f
1a578e9b
AC
6576/***********************************************************************
6577 Fonts
6578 ***********************************************************************/
6579
6580/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6581
6582struct font_info *
6583x_get_font_info (f, font_idx)
6584 FRAME_PTR f;
6585 int font_idx;
6586{
6587 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
6588}
6589
6590/* the global font name table */
95dfb192
YM
6591static char **font_name_table = NULL;
6592static int font_name_table_size = 0;
6593static int font_name_count = 0;
1a578e9b 6594
71b7a47f
YM
6595/* Alist linking font family names to Font Manager font family
6596 references (which can also be used as QuickDraw font IDs). We use
6597 an alist because hash tables are not ready when the terminal frame
6598 for Mac OS Classic is created. */
6599static Lisp_Object fm_font_family_alist;
c3bd8190 6600#if USE_ATSUI
71b7a47f 6601/* Hash table linking font family names to ATSU font IDs. */
c3bd8190 6602static Lisp_Object atsu_font_id_hash;
92289429
YM
6603/* Alist linking Font Manager style to face attributes. */
6604static Lisp_Object fm_style_face_attributes_alist;
68c767a3 6605extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
c3bd8190 6606#endif
f2ec385e
YM
6607#if USE_MAC_FONT_PANEL
6608Lisp_Object Qpanel_closed, Qselection;
6609#endif
c3bd8190 6610
94d0e806
YM
6611/* Alist linking character set strings to Mac text encoding and Emacs
6612 coding system. */
6613static Lisp_Object Vmac_charset_info_alist;
1a578e9b 6614
94d0e806
YM
6615static Lisp_Object
6616create_text_encoding_info_alist ()
1a578e9b 6617{
94d0e806 6618 Lisp_Object result = Qnil, rest;
1a578e9b 6619
94d0e806
YM
6620 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6621 {
6622 Lisp_Object charset_info = XCAR (rest);
6623 Lisp_Object charset, coding_system, text_encoding;
6624 Lisp_Object existing_info;
1a578e9b 6625
94d0e806 6626 if (!(CONSP (charset_info)
b51065cf
YM
6627 && (charset = XCAR (charset_info),
6628 STRINGP (charset))
94d0e806 6629 && CONSP (XCDR (charset_info))
b51065cf
YM
6630 && (text_encoding = XCAR (XCDR (charset_info)),
6631 INTEGERP (text_encoding))
94d0e806 6632 && CONSP (XCDR (XCDR (charset_info)))
b51065cf
YM
6633 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
6634 SYMBOLP (coding_system))))
94d0e806 6635 continue;
1a578e9b 6636
94d0e806
YM
6637 existing_info = assq_no_quit (text_encoding, result);
6638 if (NILP (existing_info))
6639 result = Fcons (list3 (text_encoding, coding_system, charset),
6640 result);
1a578e9b 6641 else
94d0e806
YM
6642 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
6643 XSETCDR (XCDR (existing_info),
6644 Fcons (charset, XCDR (XCDR (existing_info))));
1a578e9b 6645 }
1a578e9b 6646
94d0e806 6647 return result;
1a578e9b 6648}
e3564461 6649
e3564461
ST
6650
6651static void
94d0e806 6652decode_mac_font_name (name, size, coding_system)
fc7a70cc
ST
6653 char *name;
6654 int size;
94d0e806 6655 Lisp_Object coding_system;
e3564461 6656{
e3564461 6657 struct coding_system coding;
94d0e806 6658 char *buf, *p;
e3564461 6659
71b7a47f
YM
6660 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
6661 {
6662 for (p = name; *p; p++)
6663 if (!isascii (*p) || iscntrl (*p))
6664 break;
94d0e806 6665
71b7a47f
YM
6666 if (*p)
6667 {
6668 setup_coding_system (coding_system, &coding);
6669 coding.src_multibyte = 0;
6670 coding.dst_multibyte = 1;
6671 coding.mode |= CODING_MODE_LAST_BLOCK;
6672 coding.composing = COMPOSITION_DISABLED;
6673 buf = (char *) alloca (size);
6674
6675 decode_coding (&coding, name, buf, strlen (name), size - 1);
6676 bcopy (buf, name, coding.produced);
6677 name[coding.produced] = '\0';
6678 }
6679 }
e3564461 6680
71b7a47f
YM
6681 /* If there's just one occurrence of '-' in the family name, it is
6682 replaced with '_'. (More than one occurrence of '-' means a
6683 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6684 p = strchr (name, '-');
6685 if (p && strchr (p + 1, '-') == NULL)
6686 *p = '_';
e3564461 6687
71b7a47f
YM
6688 for (p = name; *p; p++)
6689 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6690 for some locales. */
6691 if (isascii (*p))
6692 *p = tolower (*p);
e3564461 6693}
1a578e9b
AC
6694
6695
6696static char *
94d0e806 6697mac_to_x_fontname (name, size, style, charset)
369a7a37 6698 const char *name;
fc7a70cc
ST
6699 int size;
6700 Style style;
94d0e806 6701 char *charset;
1a578e9b 6702{
dd15724d
YM
6703 Str31 foundry, cs;
6704 Str255 family;
468213f1
YM
6705 char xf[256], *result;
6706 unsigned char *p;
1a578e9b 6707
dd15724d 6708 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
94d0e806
YM
6709 charset = cs;
6710 else
1a578e9b
AC
6711 {
6712 strcpy(foundry, "Apple");
6713 strcpy(family, name);
1a578e9b
AC
6714 }
6715
dd15724d
YM
6716 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6717 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
05f7d868 6718 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
177c0ea7 6719
dd15724d
YM
6720 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
6721 sprintf (result, "-%s-%s-%s", foundry, family, xf);
1a578e9b 6722 for (p = result; *p; p++)
468213f1
YM
6723 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6724 for some locales. */
6725 if (isascii (*p))
6726 *p = tolower (*p);
1a578e9b
AC
6727 return result;
6728}
177c0ea7 6729
1a578e9b 6730
71b7a47f
YM
6731/* Parse fully-specified and instantiated X11 font spec XF, and store
6732 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6733 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6734 caller must allocate at least 256 and 32 bytes respectively. For
6735 ordinary Mac fonts, the value stored to FAMILY should just be their
6736 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6737 intlfonts collection contain their charset designation in their
6738 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6739 types of font names are handled accordingly. */
6740
6741const int kDefaultFontSize = 12;
6742
6743static int
6744parse_x_font_name (xf, family, size, style, charset)
369a7a37
YM
6745 const char *xf;
6746 char *family;
71b7a47f 6747 int *size;
94d0e806 6748 Style *style;
71b7a47f 6749 char *charset;
1a578e9b 6750{
71b7a47f
YM
6751 Str31 foundry, weight;
6752 int point_size, avgwidth;
6753 char slant[2], *p;
1a578e9b 6754
71b7a47f
YM
6755 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6756 foundry, family, weight, slant, size,
6757 &point_size, &avgwidth, charset) != 8
6758 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6759 foundry, family, weight, slant, size,
6760 &point_size, &avgwidth, charset) != 8)
6761 return 0;
1a578e9b 6762
71b7a47f
YM
6763 if (*size == 0)
6764 {
6765 if (point_size > 0)
6766 *size = point_size / 10;
6767 else if (avgwidth > 0)
6768 *size = avgwidth / 10;
6769 }
6770 if (*size == 0)
6771 *size = kDefaultFontSize;
1a578e9b 6772
94d0e806
YM
6773 *style = normal;
6774 if (strcmp (weight, "bold") == 0)
6775 *style |= bold;
6776 if (*slant == 'i')
6777 *style |= italic;
6778
71b7a47f 6779 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
94d0e806 6780 {
71b7a47f
YM
6781 int foundry_len = strlen (foundry), family_len = strlen (family);
6782
6783 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
6784 {
6785 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6786 but take overlap into account. */
6787 memmove (family + foundry_len + 1, family, family_len);
6788 memcpy (family, foundry, foundry_len);
6789 family[foundry_len] = '-';
6790 family[foundry_len + 1 + family_len] = '-';
6791 strcpy (family + foundry_len + 1 + family_len + 1, charset);
6792 }
6793 else
6794 return 0;
94d0e806 6795 }
e3564461 6796
71b7a47f
YM
6797 for (p = family; *p; p++)
6798 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6799 for some locales. */
6800 if (isascii (*p))
6801 *p = tolower (*p);
94d0e806 6802
71b7a47f 6803 return 1;
1a578e9b
AC
6804}
6805
6806
f00691a3
AC
6807static void
6808add_font_name_table_entry (char *font_name)
6809{
6810 if (font_name_table_size == 0)
6811 {
468213f1 6812 font_name_table_size = 256;
f00691a3
AC
6813 font_name_table = (char **)
6814 xmalloc (font_name_table_size * sizeof (char *));
6815 }
6816 else if (font_name_count + 1 >= font_name_table_size)
6817 {
468213f1 6818 font_name_table_size *= 2;
f00691a3
AC
6819 font_name_table = (char **)
6820 xrealloc (font_name_table,
6821 font_name_table_size * sizeof (char *));
6822 }
6823
6824 font_name_table[font_name_count++] = font_name;
6825}
6826
a0c62ca2
YM
6827static void
6828add_mac_font_name (name, size, style, charset)
369a7a37 6829 const char *name;
a0c62ca2
YM
6830 int size;
6831 Style style;
369a7a37 6832 const char *charset;
a0c62ca2
YM
6833{
6834 if (size > 0)
6835 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
6836 else
6837 {
6838 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
6839 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
6840 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
6841 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
6842 charset));
6843 }
6844}
6845
92289429 6846#if USE_ATSUI
0d36bf23
YM
6847static FMFontStyle
6848fm_get_style_from_font (font)
6849 FMFont font;
6850{
6851 OSStatus err;
6852 FMFontStyle style = normal;
6853 ByteCount len;
6854 UInt16 mac_style;
6855 FMFontFamily font_family;
6856#define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
6857
6858 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
6859 some font (e.g., Optima) even if it is `bold'. */
6860 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
6861 sizeof (mac_style), &mac_style, &len);
6862 if (err == noErr
6863 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
6864 style = EndianU16_BtoN (mac_style);
6865 else
6866 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
6867
6868 return style;
6869}
6870
6871static ATSUFontID
6872atsu_find_font_from_family_name (family)
6873 const char *family;
6874{
6875 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
6876 unsigned hash_code;
6877 int i;
6878 Lisp_Object rest, best;
6879 FMFontStyle min_style, style;
6880
6881 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
6882 &hash_code);
6883 if (i < 0)
6884 return kATSUInvalidFontID;
6885
6886 rest = HASH_VALUE (h, i);
6887 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
6888 return cons_to_long (rest);
6889
6890 rest = Fnreverse (rest);
6891 best = XCAR (rest);
6892 rest = XCDR (rest);
6893 if (!NILP (rest)
6894 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
6895 do
6896 {
6897 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
6898 if (style < min_style)
6899 {
6900 best = XCAR (rest);
6901 if (style == normal)
6902 break;
6903 else
6904 min_style = style;
6905 }
6906 rest = XCDR (rest);
6907 }
6908 while (!NILP (rest));
6909
6910 HASH_VALUE (h, i) = best;
6911 return cons_to_long (best);
6912}
6913
92289429
YM
6914static Lisp_Object
6915fm_style_to_face_attributes (fm_style)
6916 FMFontStyle fm_style;
6917{
6918 Lisp_Object tem;
6919
6920 fm_style &= (bold | italic);
6921 tem = assq_no_quit (make_number (fm_style),
6922 fm_style_face_attributes_alist);
6923 if (!NILP (tem))
6924 return XCDR (tem);
6925
6926 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
6927 QCslant, fm_style & italic ? Qitalic : Qnormal);
6928 fm_style_face_attributes_alist =
6929 Fcons (Fcons (make_number (fm_style), tem),
6930 fm_style_face_attributes_alist);
6931
6932 return tem;
6933}
0d36bf23
YM
6934
6935static Lisp_Object
6936atsu_find_font_family_name (font_id)
6937 ATSUFontID font_id;
6938{
6939 OSStatus err;
6940 ByteCount len;
6941 Lisp_Object family = Qnil;
6942
6943 err = ATSUFindFontName (font_id, kFontFamilyName,
6944 kFontMacintoshPlatform, kFontNoScript,
6945 kFontNoLanguage, 0, NULL, &len, NULL);
6946 if (err == noErr)
6947 {
6948 family = make_uninit_string (len);
6949 err = ATSUFindFontName (font_id, kFontFamilyName,
6950 kFontMacintoshPlatform, kFontNoScript,
6951 kFontNoLanguage, len, SDATA (family),
6952 NULL, NULL);
6953 }
6954 if (err == noErr)
6955 decode_mac_font_name (SDATA (family), len + 1, Qnil);
6956
6957 return family;
6958}
6959
6960Lisp_Object
6961mac_atsu_font_face_attributes (font_id)
6962 ATSUFontID font_id;
6963{
6964 Lisp_Object family, style_attrs;
6965
6966 family = atsu_find_font_family_name (font_id);
6967 if (NILP (family))
6968 return Qnil;
6969 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
6970 return Fcons (QCfamily, Fcons (family, style_attrs));
6971}
92289429
YM
6972#endif
6973
f00691a3
AC
6974/* Sets up the table font_name_table to contain the list of all fonts
6975 in the system the first time the table is used so that the Resource
6976 Manager need not be accessed every time this information is
6977 needed. */
1a578e9b
AC
6978
6979static void
6980init_font_name_table ()
6981{
e0f712ba 6982#if TARGET_API_MAC_CARBON
94d0e806
YM
6983 FMFontFamilyIterator ffi;
6984 FMFontFamilyInstanceIterator ffii;
6985 FMFontFamily ff;
6986 Lisp_Object text_encoding_info_alist;
6987 struct gcpro gcpro1;
6988
c3bd8190
YM
6989 text_encoding_info_alist = create_text_encoding_info_alist ();
6990
6991#if USE_ATSUI
6b9ad469
YM
6992#if USE_CG_TEXT_DRAWING
6993 init_cg_text_anti_aliasing_threshold ();
6994#endif
c3bd8190
YM
6995 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
6996 text_encoding_info_alist)))
6997 {
3e7424f7 6998 OSStatus err;
a0c62ca2
YM
6999 struct Lisp_Hash_Table *h;
7000 unsigned hash_code;
c3bd8190
YM
7001 ItemCount nfonts, i;
7002 ATSUFontID *font_ids = NULL;
0d36bf23
YM
7003 Lisp_Object prev_family = Qnil;
7004 int j;
c3bd8190
YM
7005
7006 atsu_font_id_hash =
7007 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
7008 make_float (DEFAULT_REHASH_SIZE),
7009 make_float (DEFAULT_REHASH_THRESHOLD),
685cdf3a 7010 Qnil, Qnil, Qnil);
a0c62ca2
YM
7011 h = XHASH_TABLE (atsu_font_id_hash);
7012
c3bd8190
YM
7013 err = ATSUFontCount (&nfonts);
7014 if (err == noErr)
b96fe6ea
YM
7015 {
7016 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
7017 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
7018 }
c3bd8190
YM
7019 if (err == noErr)
7020 for (i = 0; i < nfonts; i++)
7021 {
0d36bf23
YM
7022 Lisp_Object family;
7023
7024 family = atsu_find_font_family_name (font_ids[i]);
7025 if (NILP (family) || SREF (family, 0) == '.')
c3bd8190 7026 continue;
0d36bf23
YM
7027 if (!NILP (Fequal (prev_family, family)))
7028 family = prev_family;
7029 else
7030 j = hash_lookup (h, family, &hash_code);
7031 if (j < 0)
c3bd8190 7032 {
0d36bf23
YM
7033 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
7034 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
7035 Qnil), hash_code);
c3bd8190 7036 }
0d36bf23
YM
7037 else if (EQ (prev_family, family))
7038 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
7039 HASH_VALUE (h, j));
7040 prev_family = family;
c3bd8190 7041 }
c3bd8190
YM
7042 if (font_ids)
7043 xfree (font_ids);
7044 }
7045#endif
7046
94d0e806
YM
7047 /* Create a dummy instance iterator here to avoid creating and
7048 destroying it in the loop. */
7049 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
7050 return;
7051 /* Create an iterator to enumerate the font families. */
7052 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
7053 != noErr)
7054 {
7055 FMDisposeFontFamilyInstanceIterator (&ffii);
7056 return;
7057 }
7058
94d0e806
YM
7059 GCPRO1 (text_encoding_info_alist);
7060
7061 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
e0f712ba 7062 {
94d0e806
YM
7063 Str255 name;
7064 FMFont font;
7065 FMFontStyle style;
7066 FMFontSize size;
7067 TextEncoding encoding;
7068 TextEncodingBase sc;
a0c62ca2 7069 Lisp_Object text_encoding_info, family;
1a578e9b 7070
94d0e806 7071 if (FMGetFontFamilyName (ff, name) != noErr)
a0c62ca2 7072 continue;
94d0e806
YM
7073 p2cstr (name);
7074 if (*name == '.')
7075 continue;
1a578e9b 7076
94d0e806 7077 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
a0c62ca2 7078 continue;
94d0e806
YM
7079 sc = GetTextEncodingBase (encoding);
7080 text_encoding_info = assq_no_quit (make_number (sc),
7081 text_encoding_info_alist);
71b7a47f 7082 if (NILP (text_encoding_info))
94d0e806
YM
7083 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
7084 text_encoding_info_alist);
71b7a47f
YM
7085 decode_mac_font_name (name, sizeof (name),
7086 XCAR (XCDR (text_encoding_info)));
a0c62ca2
YM
7087 family = build_string (name);
7088 if (!NILP (Fassoc (family, fm_font_family_alist)))
7089 continue;
7090 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
71b7a47f 7091 fm_font_family_alist);
177c0ea7 7092
94d0e806
YM
7093 /* Point the instance iterator at the current font family. */
7094 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
a0c62ca2 7095 continue;
b15325b2 7096
94d0e806
YM
7097 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
7098 == noErr)
7099 {
7100 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
177c0ea7 7101
7c3d233d
YM
7102 if (size > 0 || style == normal)
7103 for (; !NILP (rest); rest = XCDR (rest))
a0c62ca2 7104 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
e0f712ba 7105 }
e0f712ba 7106 }
94d0e806
YM
7107
7108 UNGCPRO;
7109
7110 /* Dispose of the iterators. */
7111 FMDisposeFontFamilyIterator (&ffi);
7112 FMDisposeFontFamilyInstanceIterator (&ffii);
7113#else /* !TARGET_API_MAC_CARBON */
7114 GrafPtr port;
7115 SInt16 fontnum, old_fontnum;
7116 int num_mac_fonts = CountResources('FOND');
7117 int i, j;
7118 Handle font_handle, font_handle_2;
7119 short id, scriptcode;
7120 ResType type;
dd15724d 7121 Str255 name;
94d0e806
YM
7122 struct FontAssoc *fat;
7123 struct AsscEntry *assc_entry;
a0c62ca2 7124 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
94d0e806
YM
7125 struct gcpro gcpro1;
7126
7127 GetPort (&port); /* save the current font number used */
7128 old_fontnum = port->txFont;
7129
7130 text_encoding_info_alist = create_text_encoding_info_alist ();
7131
7132 GCPRO1 (text_encoding_info_alist);
7133
7134 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
1a578e9b 7135 {
94d0e806
YM
7136 font_handle = GetIndResource ('FOND', i);
7137 if (!font_handle)
7138 continue;
e0f712ba 7139
94d0e806
YM
7140 GetResInfo (font_handle, &id, &type, name);
7141 GetFNum (name, &fontnum);
7142 p2cstr (name);
a0c62ca2 7143 if (fontnum == 0 || *name == '.')
94d0e806 7144 continue;
177c0ea7 7145
94d0e806
YM
7146 TextFont (fontnum);
7147 scriptcode = FontToScript (fontnum);
7148 text_encoding_info = assq_no_quit (make_number (scriptcode),
7149 text_encoding_info_alist);
71b7a47f 7150 if (NILP (text_encoding_info))
94d0e806
YM
7151 text_encoding_info = assq_no_quit (make_number (smRoman),
7152 text_encoding_info_alist);
71b7a47f
YM
7153 decode_mac_font_name (name, sizeof (name),
7154 XCAR (XCDR (text_encoding_info)));
a0c62ca2
YM
7155 family = build_string (name);
7156 if (!NILP (Fassoc (family, fm_font_family_alist)))
7157 continue;
7158 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
71b7a47f 7159 fm_font_family_alist);
94d0e806
YM
7160 do
7161 {
7162 HLock (font_handle);
177c0ea7 7163
94d0e806
YM
7164 if (GetResourceSizeOnDisk (font_handle)
7165 >= sizeof (struct FamRec))
e0f712ba 7166 {
94d0e806
YM
7167 fat = (struct FontAssoc *) (*font_handle
7168 + sizeof (struct FamRec));
7169 assc_entry
7170 = (struct AsscEntry *) (*font_handle
7171 + sizeof (struct FamRec)
7172 + sizeof (struct FontAssoc));
7173
7174 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
e0f712ba 7175 {
94d0e806
YM
7176 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7177
7178 for (; !NILP (rest); rest = XCDR (rest))
a0c62ca2
YM
7179 add_mac_font_name (name, assc_entry->fontSize,
7180 assc_entry->fontStyle,
7181 SDATA (XCAR (rest)));
e0f712ba 7182 }
e0f712ba 7183 }
177c0ea7 7184
94d0e806
YM
7185 HUnlock (font_handle);
7186 font_handle_2 = GetNextFOND (font_handle);
7187 ReleaseResource (font_handle);
7188 font_handle = font_handle_2;
7189 }
7190 while (ResError () == noErr && font_handle);
1a578e9b 7191 }
94d0e806
YM
7192
7193 UNGCPRO;
7194
7195 TextFont (old_fontnum);
7196#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
7197}
7198
7199
b15325b2
ST
7200void
7201mac_clear_font_name_table ()
7202{
7203 int i;
7204
7205 for (i = 0; i < font_name_count; i++)
7206 xfree (font_name_table[i]);
7207 xfree (font_name_table);
7208 font_name_table = NULL;
7209 font_name_table_size = font_name_count = 0;
71b7a47f 7210 fm_font_family_alist = Qnil;
b15325b2
ST
7211}
7212
7213
e3564461
ST
7214enum xlfd_scalable_field_index
7215 {
7216 XLFD_SCL_PIXEL_SIZE,
7217 XLFD_SCL_POINT_SIZE,
7218 XLFD_SCL_AVGWIDTH,
7219 XLFD_SCL_LAST
7220 };
7221
369a7a37 7222static const int xlfd_scalable_fields[] =
e3564461
ST
7223 {
7224 6, /* PIXEL_SIZE */
7225 7, /* POINT_SIZE */
7226 11, /* AVGWIDTH */
7227 -1
7228 };
7229
7230static Lisp_Object
7231mac_do_list_fonts (pattern, maxnames)
369a7a37 7232 const char *pattern;
e3564461
ST
7233 int maxnames;
7234{
7235 int i, n_fonts = 0;
468213f1
YM
7236 Lisp_Object font_list = Qnil;
7237 struct xlfdpat *pat;
369a7a37
YM
7238 char *scaled;
7239 const char *ptr;
7240 int scl_val[XLFD_SCL_LAST], *val;
7241 const int *field;
468213f1 7242 int exact;
e3564461 7243
b15325b2
ST
7244 if (font_name_table == NULL) /* Initialize when first used. */
7245 init_font_name_table ();
7246
e3564461
ST
7247 for (i = 0; i < XLFD_SCL_LAST; i++)
7248 scl_val[i] = -1;
7249
7250 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7251 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7252 fonts are scaled according to the specified size. */
7253 ptr = pattern;
7254 i = 0;
7255 field = xlfd_scalable_fields;
7256 val = scl_val;
7257 if (*ptr == '-')
7258 do
7259 {
7260 ptr++;
7261 if (i == *field)
7262 {
94d0e806 7263 if ('0' <= *ptr && *ptr <= '9')
e3564461
ST
7264 {
7265 *val = *ptr++ - '0';
7266 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7267 *val = *val * 10 + *ptr++ - '0';
7268 if (*ptr != '-')
7269 *val = -1;
7270 }
7271 field++;
7272 val++;
7273 }
7274 ptr = strchr (ptr, '-');
7275 i++;
7276 }
7277 while (ptr && i < 14);
7278
7279 if (i == 14 && ptr == NULL)
7280 {
94d0e806
YM
7281 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7282 scl_val[XLFD_SCL_PIXEL_SIZE] =
7283 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7284 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7285 : -1));
7286 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7287 scl_val[XLFD_SCL_POINT_SIZE] =
7288 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7289 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7290 : -1));
7291 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7292 scl_val[XLFD_SCL_AVGWIDTH] =
7293 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7294 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7295 : -1));
e3564461
ST
7296 }
7297 else
7298 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7299
468213f1
YM
7300 pat = xlfdpat_create (pattern);
7301 if (pat == NULL)
7302 return Qnil;
fbe6152f 7303
468213f1 7304 exact = xlfdpat_exact_p (pat);
e3564461
ST
7305
7306 for (i = 0; i < font_name_count; i++)
7307 {
468213f1 7308 if (xlfdpat_match (pat, font_name_table[i]))
e3564461 7309 {
468213f1 7310 font_list = Fcons (build_string (font_name_table[i]), font_list);
f93e4d4f 7311 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
68c69027 7312 break;
e3564461
ST
7313 }
7314 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
b0241f69 7315 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
e3564461
ST
7316 {
7317 int former_len = ptr - font_name_table[i];
7318
dd15724d 7319 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
e3564461
ST
7320 memcpy (scaled, font_name_table[i], former_len);
7321 sprintf (scaled + former_len,
05f7d868 7322 "-%d-%d-72-72-m-%d-%s",
e3564461
ST
7323 scl_val[XLFD_SCL_PIXEL_SIZE],
7324 scl_val[XLFD_SCL_POINT_SIZE],
7325 scl_val[XLFD_SCL_AVGWIDTH],
b0241f69 7326 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
468213f1
YM
7327
7328 if (xlfdpat_match (pat, scaled))
e3564461 7329 {
468213f1
YM
7330 font_list = Fcons (build_string (scaled), font_list);
7331 xfree (scaled);
f93e4d4f 7332 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
468213f1 7333 break;
e3564461 7334 }
468213f1
YM
7335 else
7336 xfree (scaled);
e3564461
ST
7337 }
7338 }
fbe6152f 7339
468213f1 7340 xlfdpat_destroy (pat);
fbe6152f 7341
e3564461
ST
7342 return font_list;
7343}
7344
94d0e806
YM
7345/* Return a list of names of available fonts matching PATTERN on frame F.
7346
7347 Frame F null means we have not yet created any frame on Mac, and
7348 consult the first display in x_display_list. MAXNAMES sets a limit
7349 on how many fonts to match. */
1a578e9b
AC
7350
7351Lisp_Object
94d0e806
YM
7352x_list_fonts (f, pattern, size, maxnames)
7353 struct frame *f;
7354 Lisp_Object pattern;
7355 int size, maxnames;
1a578e9b 7356{
94d0e806
YM
7357 Lisp_Object list = Qnil, patterns, tem, key;
7358 struct mac_display_info *dpyinfo
7359 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
1a578e9b 7360
94d0e806
YM
7361 xassert (size <= 0);
7362
7363 patterns = Fassoc (pattern, Valternate_fontname_alist);
7364 if (NILP (patterns))
7365 patterns = Fcons (pattern, Qnil);
7366
7367 for (; CONSP (patterns); patterns = XCDR (patterns))
10ba2aec 7368 {
94d0e806
YM
7369 pattern = XCAR (patterns);
7370
7371 if (!STRINGP (pattern))
7372 continue;
7373
b298e813 7374 tem = XCAR (XCDR (dpyinfo->name_list_element));
10ba2aec
AC
7375 key = Fcons (pattern, make_number (maxnames));
7376
94d0e806
YM
7377 list = Fassoc (key, tem);
7378 if (!NILP (list))
10ba2aec 7379 {
94d0e806
YM
7380 list = Fcdr_safe (list);
7381 /* We have a cashed list. Don't have to get the list again. */
10ba2aec
AC
7382 goto label_cached;
7383 }
10ba2aec 7384
94d0e806
YM
7385 BLOCK_INPUT;
7386 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7387 UNBLOCK_INPUT;
177c0ea7 7388
94d0e806 7389 /* MAC_TODO: add code for matching outline fonts here */
1a578e9b 7390
94d0e806 7391 /* Now store the result in the cache. */
b298e813 7392 XSETCAR (XCDR (dpyinfo->name_list_element),
94d0e806 7393 Fcons (Fcons (key, list),
b298e813 7394 XCAR (XCDR (dpyinfo->name_list_element))));
94d0e806
YM
7395
7396 label_cached:
7397 if (NILP (list)) continue; /* Try the remaining alternatives. */
10ba2aec 7398 }
177c0ea7 7399
94d0e806 7400 return list;
1a578e9b
AC
7401}
7402
7403
7404#if GLYPH_DEBUG
7405
e0f712ba
AC
7406/* Check that FONT is valid on frame F. It is if it can be found in F's
7407 font table. */
1a578e9b
AC
7408
7409static void
7410x_check_font (f, font)
7411 struct frame *f;
7412 XFontStruct *font;
7413{
7414 int i;
7415 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7416
7417 xassert (font != NULL);
7418
7419 for (i = 0; i < dpyinfo->n_fonts; i++)
177c0ea7 7420 if (dpyinfo->font_table[i].name
1a578e9b
AC
7421 && font == dpyinfo->font_table[i].font)
7422 break;
7423
7424 xassert (i < dpyinfo->n_fonts);
7425}
7426
7427#endif /* GLYPH_DEBUG != 0 */
7428
1a578e9b
AC
7429/* Set *W to the minimum width, *H to the minimum font height of FONT.
7430 Note: There are (broken) X fonts out there with invalid XFontStruct
7431 min_bounds contents. For example, handa@etl.go.jp reports that
7432 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7433 have font->min_bounds.width == 0. */
7434
7435static INLINE void
7436x_font_min_bounds (font, w, h)
7437 MacFontStruct *font;
7438 int *w, *h;
7439{
7440 *h = FONT_HEIGHT (font);
e169f939 7441 *w = font->min_bounds.width;
1a578e9b
AC
7442}
7443
7444
7445/* Compute the smallest character width and smallest font height over
7446 all fonts available on frame F. Set the members smallest_char_width
7447 and smallest_font_height in F's x_display_info structure to
7448 the values computed. Value is non-zero if smallest_font_height or
7449 smallest_char_width become smaller than they were before. */
7450
dd15724d 7451static int
1a578e9b
AC
7452x_compute_min_glyph_bounds (f)
7453 struct frame *f;
7454{
7455 int i;
7456 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7457 MacFontStruct *font;
7458 int old_width = dpyinfo->smallest_char_width;
7459 int old_height = dpyinfo->smallest_font_height;
177c0ea7 7460
1a578e9b
AC
7461 dpyinfo->smallest_font_height = 100000;
7462 dpyinfo->smallest_char_width = 100000;
177c0ea7 7463
1a578e9b
AC
7464 for (i = 0; i < dpyinfo->n_fonts; ++i)
7465 if (dpyinfo->font_table[i].name)
7466 {
7467 struct font_info *fontp = dpyinfo->font_table + i;
7468 int w, h;
177c0ea7 7469
1a578e9b
AC
7470 font = (MacFontStruct *) fontp->font;
7471 xassert (font != (MacFontStruct *) ~0);
7472 x_font_min_bounds (font, &w, &h);
177c0ea7 7473
1a578e9b
AC
7474 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
7475 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
7476 }
7477
7478 xassert (dpyinfo->smallest_char_width > 0
7479 && dpyinfo->smallest_font_height > 0);
7480
7481 return (dpyinfo->n_fonts == 1
7482 || dpyinfo->smallest_char_width < old_width
7483 || dpyinfo->smallest_font_height < old_height);
7484}
7485
7486
7487/* Determine whether given string is a fully-specified XLFD: all 14
7488 fields are present, none is '*'. */
7489
7490static int
369a7a37
YM
7491is_fully_specified_xlfd (p)
7492 const char *p;
1a578e9b
AC
7493{
7494 int i;
7495 char *q;
7496
7497 if (*p != '-')
7498 return 0;
177c0ea7 7499
1a578e9b
AC
7500 for (i = 0; i < 13; i++)
7501 {
7502 q = strchr (p + 1, '-');
7503 if (q == NULL)
7504 return 0;
7505 if (q - p == 2 && *(p + 1) == '*')
7506 return 0;
7507 p = q;
7508 }
7509
7510 if (strchr (p + 1, '-') != NULL)
7511 return 0;
177c0ea7 7512
1a578e9b
AC
7513 if (*(p + 1) == '*' && *(p + 2) == '\0')
7514 return 0;
7515
7516 return 1;
7517}
7518
7519
bb420759
YM
7520/* mac_load_query_font creates and returns an internal representation
7521 for a font in a MacFontStruct struct. There is really no concept
e0f712ba
AC
7522 corresponding to "loading" a font on the Mac. But we check its
7523 existence and find the font number and all other information for it
7524 and store them in the returned MacFontStruct. */
1a578e9b
AC
7525
7526static MacFontStruct *
bb420759
YM
7527mac_load_query_font (f, fontname)
7528 struct frame *f;
7529 char *fontname;
1a578e9b 7530{
b73e4d84 7531 int size;
1a578e9b 7532 char *name;
71b7a47f 7533 Str255 family;
dd15724d 7534 Str31 charset;
1a578e9b 7535 SInt16 fontnum;
c3bd8190 7536#if USE_ATSUI
16805b2e 7537 static ATSUFontID font_id;
c3bd8190
YM
7538 ATSUStyle mac_style = NULL;
7539#endif
94d0e806
YM
7540 Style fontface;
7541#if TARGET_API_MAC_CARBON
7542 TextEncoding encoding;
7543 int scriptcode;
7544#else
7545 short scriptcode;
7546#endif
1a578e9b 7547 MacFontStruct *font;
b73e4d84 7548 XCharStruct *space_bounds = NULL, *pcm;
1a578e9b
AC
7549
7550 if (is_fully_specified_xlfd (fontname))
7551 name = fontname;
7552 else
7553 {
e3564461 7554 Lisp_Object matched_fonts;
1a578e9b 7555
e3564461
ST
7556 matched_fonts = mac_do_list_fonts (fontname, 1);
7557 if (NILP (matched_fonts))
7558 return NULL;
7559 name = SDATA (XCAR (matched_fonts));
1a578e9b
AC
7560 }
7561
71b7a47f
YM
7562 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
7563 return NULL;
1a578e9b 7564
c3bd8190
YM
7565#if USE_ATSUI
7566 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
7567 {
3e7424f7 7568 OSStatus err;
369a7a37
YM
7569 static const ATSUAttributeTag tags[] =
7570 {kATSUFontTag, kATSUSizeTag,
7571 kATSUQDBoldfaceTag, kATSUQDItalicTag};
7572 static const ByteCount sizes[] =
7573 {sizeof (ATSUFontID), sizeof (Fixed),
7574 sizeof (Boolean), sizeof (Boolean)};
c3bd8190
YM
7575 static Fixed size_fixed;
7576 static Boolean bold_p, italic_p;
369a7a37
YM
7577 static const ATSUAttributeValuePtr values[] =
7578 {&font_id, &size_fixed,
7579 &bold_p, &italic_p};
7580 static const ATSUFontFeatureType types[] =
7581 {kAllTypographicFeaturesType, kDiacriticsType};
7582 static const ATSUFontFeatureSelector selectors[] =
7583 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
68c767a3 7584 FMFontStyle style;
1c4ac540 7585
0d36bf23
YM
7586 font_id = atsu_find_font_from_family_name (family);
7587 if (font_id == kATSUInvalidFontID)
cb91e86a 7588 return NULL;
c3bd8190
YM
7589 size_fixed = Long2Fix (size);
7590 bold_p = (fontface & bold) != 0;
7591 italic_p = (fontface & italic) != 0;
7592 err = ATSUCreateStyle (&mac_style);
7593 if (err != noErr)
7594 return NULL;
7595 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
7596 types, selectors);
7597 if (err != noErr)
7598 return NULL;
7599 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
7600 tags, sizes, values);
68c767a3
YM
7601 if (err != noErr)
7602 return NULL;
7603 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
7604 if (err != noErr)
7605 fontnum = -1;
c3bd8190
YM
7606 scriptcode = kTextEncodingMacUnicode;
7607 }
7608 else
c3bd8190 7609#endif
71b7a47f
YM
7610 {
7611 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
7612
7613 if (NILP (tmp))
7614 return NULL;
7615 fontnum = XINT (XCDR (tmp));
94d0e806 7616#if TARGET_API_MAC_CARBON
71b7a47f
YM
7617 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
7618 return NULL;
7619 scriptcode = GetTextEncodingBase (encoding);
94d0e806 7620#else
71b7a47f 7621 scriptcode = FontToScript (fontnum);
94d0e806 7622#endif
c3bd8190 7623 }
177c0ea7 7624
1a578e9b 7625 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
177c0ea7 7626
1a578e9b
AC
7627 font->mac_fontnum = fontnum;
7628 font->mac_fontsize = size;
7629 font->mac_fontface = fontface;
94d0e806 7630 font->mac_scriptcode = scriptcode;
c3bd8190
YM
7631#if USE_ATSUI
7632 font->mac_style = mac_style;
16805b2e
YM
7633#if USE_CG_TEXT_DRAWING
7634 font->cg_font = NULL;
7635 font->cg_glyphs = NULL;
7636#endif
c3bd8190 7637#endif
1a578e9b 7638
199f9270 7639 /* Apple Japanese (SJIS) font is listed as both
2f64cf3a 7640 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
e0f712ba 7641 (Roman script) in init_font_name_table (). The latter should be
2f64cf3a 7642 treated as a one-byte font. */
94d0e806
YM
7643 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
7644 font->mac_scriptcode = smRoman;
199f9270 7645
71b7a47f 7646 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
177c0ea7 7647
c3bd8190
YM
7648#if USE_ATSUI
7649 if (font->mac_style)
7650 {
3e7424f7 7651 OSStatus err;
b73e4d84 7652 UniChar c;
c3bd8190 7653
b73e4d84
YM
7654 font->min_byte1 = 0;
7655 font->max_byte1 = 0xff;
7656 font->min_char_or_byte2 = 0;
7657 font->max_char_or_byte2 = 0xff;
7658
458dbb8c
YM
7659 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
7660 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
7661 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
7662 pcm_init (font->bounds.rows[0], 0x100);
c3bd8190 7663
16805b2e 7664#if USE_CG_TEXT_DRAWING
68c767a3
YM
7665 if (fontnum != -1)
7666 {
7667 FMFontStyle style;
7668 ATSFontRef ats_font;
16805b2e 7669
68c767a3 7670 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
16805b2e 7671 &font_id, &style);
68c767a3
YM
7672 /* Use CG text drawing if italic/bold is not synthesized. */
7673 if (err == noErr && style == fontface)
7674 {
7675 ats_font = FMGetATSFontRefFromFont (font_id);
7676 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
7677 }
7678 }
16805b2e
YM
7679
7680 if (font->cg_font)
b96fe6ea
YM
7681 {
7682 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
7683 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
7684 }
16805b2e 7685#endif
458dbb8c 7686 space_bounds = font->bounds.rows[0] + 0x20;
b73e4d84
YM
7687 err = mac_query_char_extents (font->mac_style, 0x20,
7688 &font->ascent, &font->descent,
7689 space_bounds,
7690#if USE_CG_TEXT_DRAWING
7691 (font->cg_glyphs ? font->cg_glyphs + 0x20
7692 : NULL)
7693#else
7694 NULL
7695#endif
7696 );
7c682cf1
YM
7697 if (err != noErr
7698 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
c3bd8190
YM
7699 {
7700 mac_unload_font (&one_mac_display_info, font);
7701 return NULL;
7702 }
7703
458dbb8c 7704 pcm = font->bounds.rows[0];
b73e4d84 7705 for (c = 0x21; c <= 0xff; c++)
c3bd8190 7706 {
16805b2e
YM
7707 if (c == 0xad)
7708 /* Soft hyphen is not supported in ATSUI. */
7709 continue;
7710 else if (c == 0x7f)
7711 {
0d36bf23
YM
7712#if USE_CG_TEXT_DRAWING
7713 if (font->cg_glyphs)
7714 {
7715 c = 0x9f;
7716 pcm = NULL;
7717 continue;
7718 }
7719#endif
7720 break;
16805b2e
YM
7721 }
7722
0d36bf23
YM
7723 mac_query_char_extents (font->mac_style, c, NULL, NULL,
7724 pcm ? pcm + c : NULL,
b73e4d84
YM
7725#if USE_CG_TEXT_DRAWING
7726 (font->cg_glyphs ? font->cg_glyphs + c
7727 : NULL)
05f7d868 7728#else
b73e4d84 7729 NULL
05f7d868 7730#endif
b73e4d84 7731 );
c3bd8190 7732
16805b2e 7733#if USE_CG_TEXT_DRAWING
b73e4d84 7734 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
16805b2e 7735 {
b73e4d84
YM
7736 /* Don't use CG text drawing if font substitution occurs in
7737 ASCII or Latin-1 characters. */
7738 CGFontRelease (font->cg_font);
7739 font->cg_font = NULL;
7740 xfree (font->cg_glyphs);
7741 font->cg_glyphs = NULL;
0d36bf23
YM
7742 if (pcm == NULL)
7743 break;
16805b2e
YM
7744 }
7745#endif
c3bd8190 7746 }
c3bd8190
YM
7747 }
7748 else
71b7a47f 7749#endif
c3bd8190 7750 {
0d36bf23 7751 OSStatus err;
71b7a47f
YM
7752 FontInfo the_fontinfo;
7753 int is_two_byte_font;
7754
f2ec385e 7755 mac_begin_clip (f, NULL);
1a578e9b 7756
71b7a47f
YM
7757 TextFont (fontnum);
7758 TextSize (size);
7759 TextFace (fontface);
177c0ea7 7760
71b7a47f 7761 GetFontInfo (&the_fontinfo);
1a578e9b 7762
71b7a47f
YM
7763 font->ascent = the_fontinfo.ascent;
7764 font->descent = the_fontinfo.descent;
1a578e9b 7765
71b7a47f
YM
7766 is_two_byte_font = (font->mac_scriptcode == smJapanese
7767 || font->mac_scriptcode == smTradChinese
7768 || font->mac_scriptcode == smSimpChinese
7769 || font->mac_scriptcode == smKorean);
c3bd8190 7770
71b7a47f
YM
7771 if (is_two_byte_font)
7772 {
b73e4d84
YM
7773 int char_width;
7774
71b7a47f
YM
7775 font->min_byte1 = 0xa1;
7776 font->max_byte1 = 0xfe;
7777 font->min_char_or_byte2 = 0xa1;
7778 font->max_char_or_byte2 = 0xfe;
7779
7780 /* Use the width of an "ideographic space" of that font
7781 because the_fontinfo.widMax returns the wrong width for
7782 some fonts. */
7783 switch (font->mac_scriptcode)
7784 {
7785 case smJapanese:
7786 font->min_byte1 = 0x81;
7787 font->max_byte1 = 0xfc;
7788 font->min_char_or_byte2 = 0x40;
7789 font->max_char_or_byte2 = 0xfc;
7790 char_width = StringWidth("\p\x81\x40");
7791 break;
7792 case smTradChinese:
7793 font->min_char_or_byte2 = 0x40;
7794 char_width = StringWidth("\p\xa1\x40");
7795 break;
7796 case smSimpChinese:
7797 char_width = StringWidth("\p\xa1\xa1");
7798 break;
7799 case smKorean:
7800 char_width = StringWidth("\p\xa1\xa1");
7801 break;
7802 }
c3bd8190 7803
b73e4d84 7804 font->bounds.per_char = NULL;
1a578e9b 7805
71b7a47f
YM
7806 if (fontface & italic)
7807 font->max_bounds.rbearing = char_width + 1;
7808 else
7809 font->max_bounds.rbearing = char_width;
7810 font->max_bounds.lbearing = 0;
7811 font->max_bounds.width = char_width;
7812 font->max_bounds.ascent = the_fontinfo.ascent;
7813 font->max_bounds.descent = the_fontinfo.descent;
1a578e9b 7814
71b7a47f
YM
7815 font->min_bounds = font->max_bounds;
7816 }
7817 else
7818 {
b73e4d84 7819 int c;
c3bd8190 7820
b73e4d84
YM
7821 font->min_byte1 = font->max_byte1 = 0;
7822 font->min_char_or_byte2 = 0x20;
7823 font->max_char_or_byte2 = 0xff;
16805b2e 7824
b73e4d84
YM
7825 font->bounds.per_char =
7826 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
b73e4d84
YM
7827 bzero (font->bounds.per_char,
7828 sizeof (XCharStruct) * (0xff - 0x20 + 1));
7829
7830 space_bounds = font->bounds.per_char;
0d36bf23
YM
7831 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
7832 &font->descent, space_bounds, NULL);
7833 if (err != noErr || space_bounds->width <= 0)
7834 {
7835 mac_unload_font (&one_mac_display_info, font);
7836 return NULL;
7837 }
b73e4d84
YM
7838
7839 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
7840 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
c3bd8190 7841 }
f2ec385e
YM
7842
7843 mac_end_clip (f, NULL);
71b7a47f 7844 }
177c0ea7 7845
b73e4d84
YM
7846 if (space_bounds)
7847 {
7848 int c;
7849
7850 font->min_bounds = font->max_bounds = *space_bounds;
7851 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
7852 if (pcm->width > 0)
7853 {
7854 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
7855 pcm->lbearing);
7856 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
7857 pcm->rbearing);
7858 font->min_bounds.width = min (font->min_bounds.width,
7859 pcm->width);
7860 font->min_bounds.ascent = min (font->min_bounds.ascent,
7861 pcm->ascent);
cf2c6835
YM
7862 font->min_bounds.descent = min (font->min_bounds.descent,
7863 pcm->descent);
b73e4d84
YM
7864
7865 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
7866 pcm->lbearing);
7867 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
7868 pcm->rbearing);
7869 font->max_bounds.width = max (font->max_bounds.width,
7870 pcm->width);
7871 font->max_bounds.ascent = max (font->max_bounds.ascent,
7872 pcm->ascent);
cf2c6835
YM
7873 font->max_bounds.descent = max (font->max_bounds.descent,
7874 pcm->descent);
b73e4d84
YM
7875 }
7876 if (
7877#if USE_ATSUI
7878 font->mac_style == NULL &&
7879#endif
7880 font->max_bounds.width == font->min_bounds.width
7881 && font->min_bounds.lbearing >= 0
7882 && font->max_bounds.rbearing <= font->max_bounds.width)
7883 {
7884 /* Fixed width and no overhangs. */
7885 xfree (font->bounds.per_char);
7886 font->bounds.per_char = NULL;
7887 }
7888 }
7889
16805b2e
YM
7890#if !defined (MAC_OS8) || USE_ATSUI
7891 /* AppKit and WebKit do some adjustment to the heights of Courier,
7892 Helvetica, and Times. This only works on the environments where
9fb446e3
YM
7893 srcCopy text transfer mode is never used. */
7894 if (
7895#ifdef MAC_OS8 /* implies USE_ATSUI */
7896 font->mac_style &&
7897#endif
7898 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
7899 || strcmp (family, "times") == 0))
16805b2e
YM
7900 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
7901#endif
7902
1a578e9b
AC
7903 return font;
7904}
7905
7906
b15325b2
ST
7907void
7908mac_unload_font (dpyinfo, font)
7909 struct mac_display_info *dpyinfo;
7910 XFontStruct *font;
7911{
94d0e806 7912 xfree (font->full_name);
c3bd8190
YM
7913#if USE_ATSUI
7914 if (font->mac_style)
b73e4d84
YM
7915 {
7916 int i;
7917
7918 for (i = font->min_byte1; i <= font->max_byte1; i++)
7919 if (font->bounds.rows[i])
7920 xfree (font->bounds.rows[i]);
7921 xfree (font->bounds.rows);
7922 ATSUDisposeStyle (font->mac_style);
7923 }
7924 else
7925#endif
7926 if (font->bounds.per_char)
7927 xfree (font->bounds.per_char);
16805b2e
YM
7928#if USE_CG_TEXT_DRAWING
7929 if (font->cg_font)
7930 CGFontRelease (font->cg_font);
7931 if (font->cg_glyphs)
7932 xfree (font->cg_glyphs);
c3bd8190 7933#endif
b15325b2
ST
7934 xfree (font);
7935}
7936
7937
1a578e9b
AC
7938/* Load font named FONTNAME of the size SIZE for frame F, and return a
7939 pointer to the structure font_info while allocating it dynamically.
7940 If SIZE is 0, load any size of font.
7941 If loading is failed, return NULL. */
7942
7943struct font_info *
7944x_load_font (f, fontname, size)
7945 struct frame *f;
7946 register char *fontname;
7947 int size;
7948{
7949 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7950 Lisp_Object font_names;
7951
7952 /* Get a list of all the fonts that match this name. Once we
7953 have a list of matching fonts, we compare them against the fonts
7954 we already have by comparing names. */
7955 font_names = x_list_fonts (f, build_string (fontname), size, 1);
7956
7957 if (!NILP (font_names))
7958 {
7959 Lisp_Object tail;
7960 int i;
7961
7962 for (i = 0; i < dpyinfo->n_fonts; i++)
7963 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
7964 if (dpyinfo->font_table[i].name
7965 && (!strcmp (dpyinfo->font_table[i].name,
d5db4077 7966 SDATA (XCAR (tail)))
1a578e9b 7967 || !strcmp (dpyinfo->font_table[i].full_name,
d5db4077 7968 SDATA (XCAR (tail)))))
1a578e9b
AC
7969 return (dpyinfo->font_table + i);
7970 }
94d0e806
YM
7971 else
7972 return NULL;
1a578e9b
AC
7973
7974 /* Load the font and add it to the table. */
7975 {
1a578e9b
AC
7976 struct MacFontStruct *font;
7977 struct font_info *fontp;
1a578e9b
AC
7978 int i;
7979
94d0e806 7980 fontname = (char *) SDATA (XCAR (font_names));
1a578e9b 7981
b15325b2 7982 BLOCK_INPUT;
bb420759 7983 font = mac_load_query_font (f, fontname);
b15325b2 7984 UNBLOCK_INPUT;
1a578e9b
AC
7985 if (!font)
7986 return NULL;
7987
7988 /* Find a free slot in the font table. */
7989 for (i = 0; i < dpyinfo->n_fonts; ++i)
7990 if (dpyinfo->font_table[i].name == NULL)
7991 break;
7992
7993 /* If no free slot found, maybe enlarge the font table. */
7994 if (i == dpyinfo->n_fonts
7995 && dpyinfo->n_fonts == dpyinfo->font_table_size)
7996 {
7997 int sz;
7998 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
7999 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
8000 dpyinfo->font_table
8001 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
8002 }
8003
8004 fontp = dpyinfo->font_table + i;
8005 if (i == dpyinfo->n_fonts)
8006 ++dpyinfo->n_fonts;
8007
8008 /* Now fill in the slots of *FONTP. */
8009 BLOCK_INPUT;
be2fdba9 8010 bzero (fontp, sizeof (*fontp));
1a578e9b
AC
8011 fontp->font = font;
8012 fontp->font_idx = i;
94d0e806
YM
8013 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
8014 bcopy (fontname, fontp->name, strlen (fontname) + 1);
1a578e9b 8015
e169f939
ST
8016 if (font->min_bounds.width == font->max_bounds.width)
8017 {
8018 /* Fixed width font. */
8019 fontp->average_width = fontp->space_width = font->min_bounds.width;
8020 }
8021 else
8022 {
8023 XChar2b char2b;
8024 XCharStruct *pcm;
8025
8026 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
8027 pcm = mac_per_char_metric (font, &char2b, 0);
8028 if (pcm)
8029 fontp->space_width = pcm->width;
8030 else
8031 fontp->space_width = FONT_WIDTH (font);
8032
8033 if (pcm)
8034 {
8035 int width = pcm->width;
8036 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
8037 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
8038 width += pcm->width;
8039 fontp->average_width = width / 95;
8040 }
8041 else
8042 fontp->average_width = FONT_WIDTH (font);
8043 }
8044
94d0e806
YM
8045 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
8046 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
1a578e9b
AC
8047
8048 fontp->size = font->max_bounds.width;
8049 fontp->height = FONT_HEIGHT (font);
8050 {
8051 /* For some font, ascent and descent in max_bounds field is
8052 larger than the above value. */
8053 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
8054 if (max_height > fontp->height)
8055 fontp->height = max_height;
8056 }
8057
8058 /* The slot `encoding' specifies how to map a character
8059 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8060 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8061 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8062 2:0xA020..0xFF7F). For the moment, we don't know which charset
8063 uses this font. So, we set information in fontp->encoding[1]
8064 which is never used by any charset. If mapping can't be
8065 decided, set FONT_ENCODING_NOT_DECIDED. */
8066 if (font->mac_scriptcode == smJapanese)
8067 fontp->encoding[1] = 4;
8068 else
8069 {
8070 fontp->encoding[1]
8071 = (font->max_byte1 == 0
8072 /* 1-byte font */
8073 ? (font->min_char_or_byte2 < 0x80
8074 ? (font->max_char_or_byte2 < 0x80
8075 ? 0 /* 0x20..0x7F */
8076 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
8077 : 1) /* 0xA0..0xFF */
8078 /* 2-byte font */
8079 : (font->min_byte1 < 0x80
8080 ? (font->max_byte1 < 0x80
8081 ? (font->min_char_or_byte2 < 0x80
8082 ? (font->max_char_or_byte2 < 0x80
8083 ? 0 /* 0x2020..0x7F7F */
8084 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
8085 : 3) /* 0x20A0..0x7FFF */
8086 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
8087 : (font->min_char_or_byte2 < 0x80
8088 ? (font->max_char_or_byte2 < 0x80
8089 ? 2 /* 0xA020..0xFF7F */
8090 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
8091 : 1))); /* 0xA0A0..0xFFFF */
8092 }
8093
8094#if 0 /* MAC_TODO: fill these out with more reasonably values */
8095 fontp->baseline_offset
8096 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
8097 ? (long) value : 0);
8098 fontp->relative_compose
8099 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8100 ? (long) value : 0);
8101 fontp->default_ascent
8102 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8103 ? (long) value : 0);
8104#else
8105 fontp->baseline_offset = 0;
8106 fontp->relative_compose = 0;
8107 fontp->default_ascent = 0;
8108#endif
8109
8110 /* Set global flag fonts_changed_p to non-zero if the font loaded
8111 has a character with a smaller width than any other character
1f98fbb4 8112 before, or if the font loaded has a smaller height than any
1a578e9b
AC
8113 other font loaded before. If this happens, it will make a
8114 glyph matrix reallocation necessary. */
dd15724d 8115 fonts_changed_p |= x_compute_min_glyph_bounds (f);
1a578e9b
AC
8116 UNBLOCK_INPUT;
8117 return fontp;
8118 }
8119}
8120
8121
8122/* Return a pointer to struct font_info of a font named FONTNAME for
8123 frame F. If no such font is loaded, return NULL. */
8124
8125struct font_info *
8126x_query_font (f, fontname)
8127 struct frame *f;
8128 register char *fontname;
8129{
8130 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8131 int i;
8132
8133 for (i = 0; i < dpyinfo->n_fonts; i++)
8134 if (dpyinfo->font_table[i].name
3e7424f7
YM
8135 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
8136 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
1a578e9b
AC
8137 return (dpyinfo->font_table + i);
8138 return NULL;
8139}
8140
8141
8142/* Find a CCL program for a font specified by FONTP, and set the member
8143 `encoder' of the structure. */
8144
8145void
8146x_find_ccl_program (fontp)
8147 struct font_info *fontp;
8148{
8149 Lisp_Object list, elt;
8150
8151 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8152 {
8153 elt = XCAR (list);
8154 if (CONSP (elt)
8155 && STRINGP (XCAR (elt))
8156 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8157 >= 0))
8158 break;
8159 }
8160 if (! NILP (list))
8161 {
8162 struct ccl_program *ccl
8163 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8164
8165 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8166 xfree (ccl);
8167 else
8168 fontp->font_encoder = ccl;
8169 }
8170}
8171
f2ec385e
YM
8172\f
8173/* The Mac Event loop code */
1a578e9b 8174
25c9622b 8175#if !TARGET_API_MAC_CARBON
1a578e9b
AC
8176#include <Events.h>
8177#include <Quickdraw.h>
8178#include <Balloons.h>
8179#include <Devices.h>
8180#include <Fonts.h>
8181#include <Gestalt.h>
8182#include <Menus.h>
8183#include <Processes.h>
8184#include <Sound.h>
8185#include <ToolUtils.h>
8186#include <TextUtils.h>
8187#include <Dialogs.h>
8188#include <Script.h>
1a578e9b 8189#include <Types.h>
1a578e9b
AC
8190#include <Resources.h>
8191
8192#if __MWERKS__
8193#include <unix.h>
8194#endif
25c9622b 8195#endif /* ! TARGET_API_MAC_CARBON */
1a578e9b 8196
dd4497dc
ST
8197/* Contains the string "reverse", which is a constant for mouse button emu.*/
8198Lisp_Object Qreverse;
8199
1a578e9b 8200
b02e3f7b
ST
8201/* Modifier associated with the control key, or nil to ignore. */
8202Lisp_Object Vmac_control_modifier;
8203
8204/* Modifier associated with the option key, or nil to ignore. */
a36f1680
JW
8205Lisp_Object Vmac_option_modifier;
8206
b02e3f7b
ST
8207/* Modifier associated with the command key, or nil to ignore. */
8208Lisp_Object Vmac_command_modifier;
8209
8210/* Modifier associated with the function key, or nil to ignore. */
8211Lisp_Object Vmac_function_modifier;
742fbed7 8212
dd4497dc
ST
8213/* True if the option and command modifiers should be used to emulate
8214 a three button mouse */
8215Lisp_Object Vmac_emulate_three_button_mouse;
8216
660425fa 8217#if TARGET_API_MAC_CARBON
70ed951a 8218/* Non-zero if the mouse wheel button (i.e. button 4) should map to
742fbed7 8219 mouse-2, instead of mouse-3. */
70ed951a 8220int mac_wheel_button_is_mouse_2;
5883787c 8221
70ed951a 8222/* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
5883787c 8223 for processing before Emacs sees it. */
70ed951a 8224int mac_pass_command_to_system;
5883787c 8225
70ed951a 8226/* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
5883787c 8227 for processing before Emacs sees it. */
70ed951a 8228int mac_pass_control_to_system;
1f98fbb4 8229#endif
95085023 8230
19ee09cc 8231/* Whether or not the screen configuration has changed. */
f2ec385e 8232int mac_screen_config_changed = 0;
1a578e9b
AC
8233
8234/* Apple Events */
660425fa 8235#if TARGET_API_MAC_CARBON
f2ec385e 8236Lisp_Object Qhi_command;
68c767a3 8237#ifdef MAC_OSX
f2ec385e 8238Lisp_Object Qtoolbar_switch_mode;
68c767a3 8239#endif
02236cbc 8240#if USE_MAC_TSM
f2ec385e
YM
8241Lisp_Object Qtext_input;
8242Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
e1adb139 8243Lisp_Object Vmac_ts_active_input_overlay, Vmac_ts_active_input_buf;
834263b6
YM
8244static Lisp_Object Vmac_ts_script_language_on_focus;
8245static Lisp_Object saved_ts_script_language_on_focus;
b4c51596
YM
8246static ScriptLanguageRecord saved_ts_language;
8247static Component saved_ts_component;
02236cbc 8248#endif
f2ec385e
YM
8249#ifdef MAC_OSX
8250Lisp_Object Qservice, Qpaste, Qperform;
e1adb139 8251Lisp_Object Qmouse_drag_overlay;
f2ec385e 8252#endif
660425fa 8253#endif /* TARGET_API_MAC_CARBON */
6a0b5d37 8254extern Lisp_Object Qundefined;
f2ec385e 8255extern int XTread_socket P_ ((int, int, struct input_event *));
6a0b5d37
YM
8256extern void init_apple_event_handler P_ ((void));
8257extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8258 Lisp_Object *, Lisp_Object *,
8259 Lisp_Object *));
0e0a1663 8260extern OSErr init_coercion_handler P_ ((void));
742fbed7 8261
1e53bd0e
YM
8262/* Table for translating Mac keycode to X keysym values. Contributed
8263 by Sudhir Shenoy.
8264 Mapping for special keys is now identical to that in Apple X11
8265 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8266 on the right of the Cmd key on laptops, and fn + `enter' (->
8267 <linefeed>). */
f2ec385e 8268const unsigned char keycode_to_xkeysym_table[] = {
1e53bd0e
YM
8269 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8270 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8271 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8272
8273 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8274 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8275 /*0x38*/ 0, 0, 0, 0,
8276 /*0x3C*/ 0, 0, 0, 0,
8277
bad70f79 8278 /*0x40*/ 0xce /*f17*/, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
1e53bd0e
YM
8279 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8280 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
bad70f79 8281 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0xcf /*f18*/,
1e53bd0e 8282
bad70f79 8283 /*0x50*/ 0xd0 /*f19*/, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
1e53bd0e
YM
8284 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8285 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8286 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8287
8288 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8289 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8290 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8291 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8292
8293 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8294 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8295 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8296 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8297};
8298
8299#ifdef MAC_OSX
8300/* Table for translating Mac keycode with the laptop `fn' key to that
8301 without it. Destination symbols in comments are keys on US
8302 keyboard, and they may not be the same on other types of keyboards.
10fdc4c2
YM
8303 If the destination is identical to the source, it doesn't map `fn'
8304 key to a modifier. */
369a7a37 8305static const unsigned char fn_keycode_to_keycode_table[] = {
1e53bd0e
YM
8306 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8307 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8308 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8309
8310 /*0x30*/ 0, 0, 0, 0,
8311 /*0x34*/ 0, 0, 0, 0,
8312 /*0x38*/ 0, 0, 0, 0,
8313 /*0x3C*/ 0, 0, 0, 0,
8314
bad70f79 8315 /*0x40*/ 0x40 /*f17 = f17*/, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
1e53bd0e
YM
8316 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8317 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
bad70f79 8318 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0x4f /*f18 = f18*/,
1e53bd0e 8319
bad70f79 8320 /*0x50*/ 0x50 /*f19 = f19*/, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
1e53bd0e
YM
8321 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8322 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8323 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8324
8325 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8326 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
10fdc4c2 8327 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
1e53bd0e
YM
8328 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8329
10fdc4c2 8330 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
1e53bd0e 8331 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
10fdc4c2
YM
8332 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
8333 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
1e53bd0e
YM
8334};
8335#endif /* MAC_OSX */
8336
f2ec385e 8337int
660425fa 8338#if TARGET_API_MAC_CARBON
ca1617bf 8339mac_to_emacs_modifiers (UInt32 mods, UInt32 unmapped_mods)
742fbed7 8340#else
ca1617bf 8341mac_to_emacs_modifiers (EventModifiers mods, EventModifiers unmapped_mods)
742fbed7
AC
8342#endif
8343{
8344 unsigned int result = 0;
ca1617bf 8345 if ((mods | unmapped_mods) & shiftKey)
742fbed7 8346 result |= shift_modifier;
16805b2e 8347
b02e3f7b
ST
8348 /* Deactivated to simplify configuration:
8349 if Vmac_option_modifier is non-NIL, we fully process the Option
8350 key. Otherwise, we only process it if an additional Ctrl or Command
16805b2e 8351 is pressed. That way the system may convert the character to a
b02e3f7b
ST
8352 composed one.
8353 if ((mods & optionKey) &&
16805b2e 8354 (( !NILP(Vmac_option_modifier) ||
b02e3f7b
ST
8355 ((mods & cmdKey) || (mods & controlKey))))) */
8356
a36f1680 8357 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
b02e3f7b
ST
8358 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
8359 if (INTEGERP(val))
8360 result |= XUINT(val);
a36f1680 8361 }
b02e3f7b
ST
8362 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
8363 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
8364 if (INTEGERP(val))
8365 result |= XUINT(val);
16805b2e 8366 }
b02e3f7b
ST
8367 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
8368 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
8369 if (INTEGERP(val))
8370 result |= XUINT(val);
16805b2e 8371 }
a36f1680 8372
b02e3f7b
ST
8373#ifdef MAC_OSX
8374 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
8375 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
8376 if (INTEGERP(val))
8377 result |= XUINT(val);
16805b2e 8378 }
b02e3f7b 8379#endif
16805b2e 8380
742fbed7
AC
8381 return result;
8382}
8383
f2ec385e 8384UInt32
10fdc4c2
YM
8385mac_mapped_modifiers (modifiers, key_code)
8386 UInt32 modifiers, key_code;
a84cad70
YM
8387{
8388 UInt32 mapped_modifiers_all =
8389 (NILP (Vmac_control_modifier) ? 0 : controlKey)
8390 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
8391 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
8392
8393#ifdef MAC_OSX
8394 mapped_modifiers_all |=
8395 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
10fdc4c2
YM
8396
8397 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
8398 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
8399 no longer means laptop's `fn' key is down for the following keys:
8400 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
8401 Down, the arrow keys, and Clear. We ignore the corresponding bit
8402 if that key can be entered without the `fn' key on laptops. */
8403 if (modifiers & kEventKeyModifierFnMask
8404 && key_code <= 0x7f
8405 && fn_keycode_to_keycode_table[key_code] == key_code)
8406 modifiers &= ~kEventKeyModifierFnMask;
a84cad70
YM
8407#endif
8408
8409 return mapped_modifiers_all & modifiers;
8410}
8411
f2ec385e 8412int
dd4497dc
ST
8413mac_get_emulated_btn ( UInt32 modifiers )
8414{
8415 int result = 0;
a433994a
ST
8416 if (!NILP (Vmac_emulate_three_button_mouse)) {
8417 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
c61278bb 8418 if (modifiers & cmdKey)
dd4497dc
ST
8419 result = cmdIs3 ? 2 : 1;
8420 else if (modifiers & optionKey)
ffe8b3f4 8421 result = cmdIs3 ? 1 : 2;
dd4497dc
ST
8422 }
8423 return result;
8424}
8425
e1adb139
YM
8426#ifdef MAC_OSX
8427void
8428mac_get_selected_range (w, range)
8429 struct window *w;
8430 CFRange *range;
8431{
8432 Lisp_Object overlay = find_symbol_value (Qmouse_drag_overlay);
8433 struct buffer *b = XBUFFER (w->buffer);
8434 int begv = BUF_BEGV (b), zv = BUF_ZV (b);
8435 int start, end;
8436
8437 if (OVERLAYP (overlay)
8438 && EQ (Foverlay_buffer (overlay), w->buffer)
8439 && (start = XINT (Foverlay_start (overlay)),
8440 end = XINT (Foverlay_end (overlay)),
8441 start != end))
8442 ;
8443 else
8444 {
8445 if (w == XWINDOW (selected_window) && b == current_buffer)
8446 start = PT;
8447 else
8448 start = marker_position (w->pointm);
8449
8450 if (NILP (Vtransient_mark_mode) || NILP (b->mark_active))
8451 end = start;
8452 else
8453 {
8454 int mark_pos = marker_position (b->mark);
8455
8456 if (start <= mark_pos)
8457 end = mark_pos;
8458 else
8459 {
8460 end = start;
8461 start = mark_pos;
8462 }
8463 }
8464 }
8465
8466 if (start != end)
8467 {
8468 if (start < begv)
8469 start = begv;
8470 else if (start > zv)
8471 start = zv;
8472
8473 if (end < begv)
8474 end = begv;
8475 else if (end > zv)
8476 end = zv;
8477 }
8478
8479 range->location = start - begv;
8480 range->length = end - start;
8481}
8482
8483/* Store the text of the buffer BUF from START to END as Unicode
8484 characters in CHARACTERS. Return non-zero if successful. */
8485
8486int
8487mac_store_buffer_text_to_unicode_chars (buf, start, end, characters)
8488 struct buffer *buf;
8489 int start, end;
8490 UniChar *characters;
8491{
8492 int start_byte, end_byte, char_count, byte_count;
8493 struct coding_system coding;
8494 unsigned char *dst = (unsigned char *) characters;
8495
8496 start_byte = buf_charpos_to_bytepos (buf, start);
8497 end_byte = buf_charpos_to_bytepos (buf, end);
8498 char_count = end - start;
8499 byte_count = end_byte - start_byte;
8500
8501 if (setup_coding_system (
8502#ifdef WORDS_BIG_ENDIAN
8503 intern ("utf-16be")
8504#else
8505 intern ("utf-16le")
8506#endif
8507 , &coding) < 0)
8508 return 0;
8509
8510 coding.src_multibyte = !NILP (buf->enable_multibyte_characters);
8511 coding.dst_multibyte = 0;
8512 coding.mode |= CODING_MODE_LAST_BLOCK;
8513 coding.composing = COMPOSITION_DISABLED;
8514
8515 if (BUF_GPT_BYTE (buf) <= start_byte || end_byte <= BUF_GPT_BYTE (buf))
8516 encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
8517 byte_count, char_count * sizeof (UniChar));
8518 else
8519 {
8520 int first_byte_count = BUF_GPT_BYTE (buf) - start_byte;
8521
8522 encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
8523 first_byte_count, char_count * sizeof (UniChar));
8524 if (coding.result == CODING_FINISH_NORMAL)
8525 encode_coding (&coding,
8526 BUF_BYTE_ADDRESS (buf, start_byte + first_byte_count),
8527 dst + coding.produced,
8528 byte_count - first_byte_count,
8529 char_count * sizeof (UniChar) - coding.produced);
8530 }
8531
8532 if (coding.result != CODING_FINISH_NORMAL)
8533 return 0;
8534
8535 return 1;
8536}
8537
8538void
8539mac_ax_selected_text_range (f, range)
8540 struct frame *f;
8541 CFRange *range;
8542{
8543 mac_get_selected_range (XWINDOW (f->selected_window), range);
8544}
8545
8546#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8547unsigned int
8548mac_ax_number_of_characters (f)
8549 struct frame *f;
8550{
8551 struct buffer *b = XBUFFER (XWINDOW (f->selected_window)->buffer);
8552
8553 return BUF_ZV (b) - BUF_BEGV (b);
8554}
8555#endif
8556#endif
8557
f2ec385e
YM
8558#if USE_MAC_TSM
8559OSStatus
8560mac_restore_keyboard_input_source ()
8561{
8562 OSStatus err = noErr;
8563 ScriptLanguageRecord slrec, *slptr = NULL;
8564
8565 if (EQ (Vmac_ts_script_language_on_focus, Qt)
8566 && EQ (saved_ts_script_language_on_focus, Qt))
8567 slptr = &saved_ts_language;
8568 else if (CONSP (Vmac_ts_script_language_on_focus)
8569 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8570 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
8571 && CONSP (saved_ts_script_language_on_focus)
8572 && EQ (XCAR (saved_ts_script_language_on_focus),
8573 XCAR (Vmac_ts_script_language_on_focus))
8574 && EQ (XCDR (saved_ts_script_language_on_focus),
8575 XCDR (Vmac_ts_script_language_on_focus)))
8576 {
8577 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8578 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8579 slptr = &slrec;
8580 }
8581
8582 if (slptr)
8583 {
8584#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8585 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
8586 kKeyboardInputMethodClass);
8587#else
8588 err = SetDefaultInputMethod (saved_ts_component, slptr);
8589#endif
8590 if (err == noErr)
8591 err = SetTextServiceLanguage (slptr);
8592
8593 /* Seems to be needed on Mac OS X 10.2. */
8594 if (err == noErr)
8595 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
8596 }
8597
8598 return err;
8599}
8600
8601void
8602mac_save_keyboard_input_source ()
8603{
8604 OSStatus err;
8605 ScriptLanguageRecord slrec, *slptr = NULL;
8606
8607 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
8608
8609 if (EQ (Vmac_ts_script_language_on_focus, Qt))
8610 {
8611 err = GetTextServiceLanguage (&saved_ts_language);
8612 if (err == noErr)
8613 slptr = &saved_ts_language;
8614 }
8615 else if (CONSP (Vmac_ts_script_language_on_focus)
8616 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8617 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
8618 {
8619 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8620 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8621 slptr = &slrec;
8622 }
8623
8624 if (slptr)
8625 {
8626#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8627 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
8628 kKeyboardInputMethodClass);
8629#else
8630 GetDefaultInputMethod (&saved_ts_component, slptr);
8631#endif
8632 }
8633}
8634#endif
8635
c857519f
YM
8636#if TARGET_API_MAC_CARBON
8637/***** Code to handle C-g testing *****/
8638extern int quit_char;
8639extern int make_ctrl_char P_ ((int));
8640
8641int
8642mac_quit_char_key_p (modifiers, key_code)
8643 UInt32 modifiers, key_code;
8644{
10fdc4c2 8645 UInt32 char_code, mapped_modifiers;
c857519f
YM
8646 unsigned long some_state = 0;
8647 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8648 int c, emacs_modifiers;
8649
8650 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
10fdc4c2
YM
8651 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
8652 key_code |= (modifiers & ~mapped_modifiers);
c857519f
YM
8653 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
8654 if (char_code & ~0xff)
8655 return 0;
8656
ca1617bf 8657 emacs_modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
c857519f
YM
8658 if (emacs_modifiers & ctrl_modifier)
8659 c = make_ctrl_char (char_code);
8660
8661 c |= (emacs_modifiers
8662 & (meta_modifier | alt_modifier
8663 | hyper_modifier | super_modifier));
8664
8665 return c == quit_char;
8666}
8667#endif
8668
f2ec385e
YM
8669static void
8670mac_set_unicode_keystroke_event (code, buf)
8671 UniChar code;
8672 struct input_event *buf;
742fbed7 8673{
f2ec385e 8674 int charset_id, c1, c2;
660425fa 8675
f2ec385e 8676 if (code < 0x80)
dd4497dc 8677 {
f2ec385e
YM
8678 buf->kind = ASCII_KEYSTROKE_EVENT;
8679 buf->code = code;
dd4497dc 8680 }
f2ec385e 8681 else if (code < 0x100)
742fbed7 8682 {
f2ec385e
YM
8683 if (code < 0xA0)
8684 charset_id = CHARSET_8_BIT_CONTROL;
8685 else
8686 charset_id = charset_latin_iso8859_1;
8687 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8688 buf->code = MAKE_CHAR (charset_id, code, 0);
8689 }
8690 else
8691 {
8692 if (code < 0x2500)
8693 charset_id = charset_mule_unicode_0100_24ff,
8694 code -= 0x100;
8695 else if (code < 0x33FF)
8696 charset_id = charset_mule_unicode_2500_33ff,
8697 code -= 0x2500;
8698 else if (code >= 0xE000)
8699 charset_id = charset_mule_unicode_e000_ffff,
8700 code -= 0xE000;
8701 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
8702 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8703 buf->code = MAKE_CHAR (charset_id, c1, c2);
742fbed7
AC
8704 }
8705}
8706
f2ec385e
YM
8707void
8708do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
8709 EventKind action;
8710 unsigned char char_code;
8711 UInt32 key_code, modifiers;
8712 unsigned long timestamp;
8713 struct input_event *buf;
742fbed7 8714{
f2ec385e
YM
8715 static SInt16 last_key_script = -1;
8716 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
8717 UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
95085023 8718
f2ec385e
YM
8719#ifdef MAC_OSX
8720 if (mapped_modifiers & kEventKeyModifierFnMask
8721 && key_code <= 0x7f
8722 && fn_keycode_to_keycode_table[key_code])
8723 key_code = fn_keycode_to_keycode_table[key_code];
8724#endif
95085023 8725
f2ec385e 8726 if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
177c0ea7 8727 {
f2ec385e
YM
8728 buf->kind = NON_ASCII_KEYSTROKE_EVENT;
8729 buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
8730 }
8731 else if (mapped_modifiers)
8732 {
8733 /* translate the keycode back to determine the original key */
8734#ifdef MAC_OSX
8735 UCKeyboardLayout *uchr_ptr = NULL;
8736#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8737 OSStatus err;
8738 KeyboardLayoutRef layout;
95085023 8739
f2ec385e
YM
8740 err = KLGetCurrentKeyboardLayout (&layout);
8741 if (err == noErr)
8742 err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
8743 (const void **) &uchr_ptr);
8744#else
8745 static SInt16 last_key_layout_id = 0;
8746 static Handle uchr_handle = (Handle)-1;
8747 SInt16 current_key_layout_id =
8748 GetScriptVariable (current_key_script, smScriptKeys);
95085023 8749
f2ec385e
YM
8750 if (uchr_handle == (Handle)-1
8751 || last_key_layout_id != current_key_layout_id)
8752 {
8753 uchr_handle = GetResource ('uchr', current_key_layout_id);
8754 last_key_layout_id = current_key_layout_id;
742fbed7 8755 }
f2ec385e
YM
8756 if (uchr_handle)
8757 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
8758#endif
95085023 8759
f2ec385e 8760 if (uchr_ptr)
742fbed7 8761 {
f2ec385e
YM
8762 OSStatus status;
8763 UInt16 key_action = action - keyDown;
8764 UInt32 modifier_key_state = (modifiers & ~mapped_modifiers) >> 8;
8765 UInt32 keyboard_type = LMGetKbdType ();
8766 SInt32 dead_key_state = 0;
8767 UniChar code;
8768 UniCharCount actual_length;
95085023 8769
f2ec385e
YM
8770 status = UCKeyTranslate (uchr_ptr, key_code, key_action,
8771 modifier_key_state, keyboard_type,
8772 kUCKeyTranslateNoDeadKeysMask,
8773 &dead_key_state,
8774 1, &actual_length, &code);
8775 if (status == noErr && actual_length == 1)
8776 mac_set_unicode_keystroke_event (code, buf);
742fbed7 8777 }
f2ec385e 8778#endif /* MAC_OSX */
95085023 8779
f2ec385e
YM
8780 if (buf->kind == NO_EVENT)
8781 {
8782 /* This code comes from Keyboard Resource, Appendix C of IM
8783 - Text. This is necessary since shift is ignored in KCHR
8784 table translation when option or command is pressed. It
8785 also does not translate correctly control-shift chars
8786 like C-% so mask off shift here also. */
8787 /* Mask off modifier keys that are mapped to some Emacs
8788 modifiers. */
8789 int new_modifiers = modifiers & ~mapped_modifiers;
8790 /* set high byte of keycode to modifier high byte*/
8791 int new_key_code = key_code | new_modifiers;
8792 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8793 unsigned long some_state = 0;
8794 UInt32 new_char_code;
95085023 8795
f2ec385e
YM
8796 new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
8797 if (new_char_code == 0)
8798 /* Seems like a dead key. Append up-stroke. */
8799 new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
8800 &some_state);
8801 if (new_char_code)
8802 {
8803 buf->kind = ASCII_KEYSTROKE_EVENT;
8804 buf->code = new_char_code & 0xff;
8805 }
8806 }
95085023
YM
8807 }
8808
f2ec385e
YM
8809 if (buf->kind == NO_EVENT)
8810 {
8811 buf->kind = ASCII_KEYSTROKE_EVENT;
8812 buf->code = char_code;
8813 }
742fbed7 8814
f2ec385e
YM
8815 buf->modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
8816 buf->modifiers |= (extra_keyboard_modifiers
8817 & (meta_modifier | alt_modifier
8818 | hyper_modifier | super_modifier));
1a578e9b 8819
f2ec385e
YM
8820#if TARGET_API_MAC_CARBON
8821 if (buf->kind == ASCII_KEYSTROKE_EVENT
8822 && buf->code >= 0x80 && buf->modifiers)
8823 {
8824 OSStatus err;
8825 TextEncoding encoding = kTextEncodingMacRoman;
8826 TextToUnicodeInfo ttu_info;
177c0ea7 8827
f2ec385e
YM
8828 UpgradeScriptInfoToTextEncoding (current_key_script,
8829 kTextLanguageDontCare,
8830 kTextRegionDontCare,
8831 NULL, &encoding);
8832 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
8833 if (err == noErr)
8834 {
8835 UniChar code;
8836 Str255 pstr;
8837 ByteCount unicode_len;
1a578e9b 8838
f2ec385e
YM
8839 pstr[0] = 1;
8840 pstr[1] = buf->code;
8841 err = ConvertFromPStringToUnicode (ttu_info, pstr,
8842 sizeof (UniChar),
8843 &unicode_len, &code);
8844 if (err == noErr && unicode_len == sizeof (UniChar))
8845 mac_set_unicode_keystroke_event (code, buf);
8846 DisposeTextToUnicodeInfo (&ttu_info);
8847 }
8848 }
1c05c15b 8849#endif
177c0ea7 8850
f2ec385e
YM
8851 if (buf->kind == ASCII_KEYSTROKE_EVENT
8852 && buf->code >= 0x80
8853 && last_key_script != current_key_script)
8854 {
8855 struct input_event event;
1a578e9b 8856
f2ec385e
YM
8857 EVENT_INIT (event);
8858 event.kind = LANGUAGE_CHANGE_EVENT;
8859 event.arg = Qnil;
8860 event.code = current_key_script;
8861 event.timestamp = timestamp;
8862 kbd_buffer_store_event (&event);
8863 last_key_script = current_key_script;
8864 }
1a578e9b
AC
8865}
8866
f2ec385e
YM
8867void
8868mac_store_apple_event (class, id, desc)
8869 Lisp_Object class, id;
8870 const AEDesc *desc;
2e875e36 8871{
f2ec385e 8872 struct input_event buf;
177c0ea7 8873
f2ec385e
YM
8874 EVENT_INIT (buf);
8875
8876 buf.kind = MAC_APPLE_EVENT;
8877 buf.x = class;
8878 buf.y = id;
8879 XSETFRAME (buf.frame_or_window,
8880 mac_focus_frame (&one_mac_display_info));
8881 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
8882 is safe to use them during read_socket_hook. */
8883 buf.arg = mac_aedesc_to_lisp (desc);
8884 kbd_buffer_store_event (&buf);
2e875e36
AC
8885}
8886
f2ec385e
YM
8887#if TARGET_API_MAC_CARBON
8888OSStatus
8889mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
8890 event, num_params, names, types)
8891 AEEventClass class;
8892 AEEventID id;
8893 Lisp_Object class_key, id_key;
8894 EventRef event;
8895 UInt32 num_params;
8896 const EventParamName *names;
8897 const EventParamType *types;
1a578e9b 8898{
f2ec385e
YM
8899 OSStatus err = eventNotHandledErr;
8900 Lisp_Object binding;
1a578e9b 8901
f2ec385e
YM
8902 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
8903 if (!NILP (binding) && !EQ (binding, Qundefined))
1a578e9b 8904 {
f2ec385e
YM
8905 if (INTEGERP (binding))
8906 err = XINT (binding);
1a578e9b 8907 else
1f98fbb4 8908 {
834263b6
YM
8909 struct input_event buf;
8910
8911 EVENT_INIT (buf);
8912
8913 buf.kind = MAC_APPLE_EVENT;
8914 buf.x = class_key;
8915 buf.y = id_key;
8916 XSETFRAME (buf.frame_or_window,
8917 mac_focus_frame (&one_mac_display_info));
8918 /* Now that Lisp object allocations are protected by
8919 BLOCK_INPUT, it is safe to use them during
8920 read_socket_hook. */
8921 buf.arg = Fcons (build_string ("aevt"),
8922 mac_event_parameters_to_lisp (event, num_params,
8923 names, types));
8924 kbd_buffer_store_event (&buf);
8925 mac_wakeup_from_rne ();
6750bd93 8926 err = noErr;
1f98fbb4 8927 }
1a578e9b 8928 }
b15325b2 8929
f2ec385e 8930 return err;
1a578e9b 8931}
f2ec385e 8932#endif /* TARGET_API_MAC_CARBON */
1a578e9b 8933
f2ec385e
YM
8934static pascal void
8935mac_handle_dm_notification (event)
8936 AppleEvent *event;
e0f712ba 8937{
f2ec385e 8938 mac_screen_config_changed = 1;
e0f712ba
AC
8939}
8940
f2ec385e
YM
8941#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8942static void
8943mac_handle_cg_display_reconfig (display, flags, user_info)
8944 CGDirectDisplayID display;
8945 CGDisplayChangeSummaryFlags flags;
8946 void *user_info;
b4c51596 8947{
f2ec385e
YM
8948 mac_screen_config_changed = 1;
8949}
8950#endif
b4c51596 8951
f2ec385e
YM
8952static OSErr
8953init_dm_notification_handler ()
8954{
8955 OSErr err = noErr;
b4c51596 8956
f2ec385e
YM
8957#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8958#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8959 if (CGDisplayRegisterReconfigurationCallback != NULL)
8960#endif
b4c51596 8961 {
f2ec385e
YM
8962 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
8963 NULL);
b4c51596 8964 }
f2ec385e
YM
8965#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8966 else /* CGDisplayRegisterReconfigurationCallback == NULL */
02236cbc 8967#endif
f2ec385e
YM
8968#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
8969#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8970 {
8971 static DMNotificationUPP handle_dm_notificationUPP = NULL;
8972 ProcessSerialNumber psn;
b4c51596 8973
f2ec385e
YM
8974 if (handle_dm_notificationUPP == NULL)
8975 handle_dm_notificationUPP =
8976 NewDMNotificationUPP (mac_handle_dm_notification);
8977
8978 err = GetCurrentProcess (&psn);
b4c51596 8979 if (err == noErr)
f2ec385e 8980 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
b4c51596 8981 }
f2ec385e 8982#endif
b4c51596
YM
8983
8984 return err;
1a578e9b
AC
8985}
8986
1a578e9b 8987void
f2ec385e
YM
8988mac_get_screen_info (dpyinfo)
8989 struct mac_display_info *dpyinfo;
1a578e9b 8990{
f2ec385e
YM
8991#ifdef MAC_OSX
8992 /* HasDepth returns true if it is possible to have a 32 bit display,
8993 but this may not be what is actually used. Mac OSX can do better. */
8994 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
8995 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
1a578e9b 8996 {
f2ec385e
YM
8997 CGDisplayErr err;
8998 CGDisplayCount ndisps;
8999 CGDirectDisplayID *displays;
b15325b2 9000
f2ec385e
YM
9001 err = CGGetActiveDisplayList (0, NULL, &ndisps);
9002 if (err == noErr)
b15325b2 9003 {
f2ec385e
YM
9004 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
9005 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
b15325b2 9006 }
f2ec385e
YM
9007 if (err == noErr)
9008 {
9009 CGRect bounds = CGRectZero;
b15325b2 9010
f2ec385e
YM
9011 while (ndisps-- > 0)
9012 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
9013 dpyinfo->height = CGRectGetHeight (bounds);
9014 dpyinfo->width = CGRectGetWidth (bounds);
9015 }
9016 else
9017 {
9018 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
9019 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
9020 }
9021 }
9022#else /* !MAC_OSX */
9023 {
9024 GDHandle gdh = GetMainDevice ();
9025 Rect rect = (**gdh).gdRect;
7ca7ccd5 9026
f2ec385e
YM
9027 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
9028 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9029 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
9030 break;
7ca7ccd5 9031
f2ec385e
YM
9032 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
9033 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
9034 UnionRect (&rect, &(**gdh).gdRect, &rect);
1a578e9b 9035
f2ec385e
YM
9036 dpyinfo->height = rect.bottom - rect.top;
9037 dpyinfo->width = rect.right - rect.left;
9038 }
9039#endif /* !MAC_OSX */
9040}
50bf7673 9041
f2ec385e
YM
9042\f
9043/***********************************************************************
9044 Initialization (Mac OS Classic)
9045 ***********************************************************************/
177c0ea7 9046
f2ec385e
YM
9047#ifdef MAC_OS8
9048extern void init_emacs_passwd_dir ();
9049extern int emacs_main (int, char **, char **);
177c0ea7 9050
f2ec385e
YM
9051extern void initialize_applescript();
9052extern void terminate_applescript();
660425fa 9053
f2ec385e
YM
9054static void
9055do_get_menus (void)
9056{
9057 Handle menubar_handle;
9058 MenuRef menu;
f94a2622 9059
f2ec385e
YM
9060 menubar_handle = GetNewMBar (128);
9061 if(menubar_handle == NULL)
9062 abort ();
9063 SetMenuBar (menubar_handle);
9064 DrawMenuBar ();
660425fa 9065
f2ec385e
YM
9066#if !TARGET_API_MAC_CARBON
9067 menu = GetMenuRef (M_APPLE);
9068 if (menu != NULL)
9069 AppendResMenu (menu, 'DRVR');
9070 else
9071 abort ();
5b8b73ff 9072#endif
f2ec385e 9073}
59feca74 9074
f2ec385e
YM
9075static void
9076do_init_managers (void)
9077{
9078#if !TARGET_API_MAC_CARBON
9079 InitGraf (&qd.thePort);
9080 InitFonts ();
9081 FlushEvents (everyEvent, 0);
9082 InitWindows ();
9083 InitMenus ();
9084 TEInit ();
9085 InitDialogs (NULL);
9086#endif /* !TARGET_API_MAC_CARBON */
9087 InitCursor ();
177c0ea7 9088
f2ec385e
YM
9089#if !TARGET_API_MAC_CARBON
9090 /* set up some extra stack space for use by emacs */
9091 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
177c0ea7 9092
f2ec385e
YM
9093 /* MaxApplZone must be called for AppleScript to execute more
9094 complicated scripts */
9095 MaxApplZone ();
9096 MoreMasters ();
9097#endif /* !TARGET_API_MAC_CARBON */
9098}
177c0ea7 9099
f2ec385e
YM
9100static void
9101do_check_ram_size (void)
9102{
9103 SInt32 physical_ram_size, logical_ram_size;
660425fa 9104
f2ec385e
YM
9105 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
9106 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
9107 || physical_ram_size > (1 << VALBITS)
9108 || logical_ram_size > (1 << VALBITS))
9109 {
9110 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
9111 exit (1);
9112 }
9113}
660425fa 9114
f2ec385e
YM
9115#if __profile__
9116void
9117profiler_exit_proc ()
9118{
9119 ProfilerDump ("\pEmacs.prof");
9120 ProfilerTerm ();
9121}
9122#endif
660425fa 9123
f2ec385e
YM
9124/* These few functions implement Emacs as a normal Mac application
9125 (almost): set up the heap and the Toolbox, handle necessary system
9126 events plus a few simple menu events. They also set up Emacs's
9127 access to functions defined in the rest of this file. Emacs uses
9128 function hooks to perform all its terminal I/O. A complete list of
9129 these functions appear in termhooks.h. For what they do, read the
9130 comments there and see also w32term.c and xterm.c. What's
9131 noticeably missing here is the event loop, which is normally
9132 present in most Mac application. After performing the necessary
9133 Mac initializations, main passes off control to emacs_main
9134 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9135 (defined further below) to read input. This is where
9136 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
b8c6940e 9137
f2ec385e
YM
9138#undef main
9139int
9140main (void)
9141{
9142#if __profile__ /* is the profiler on? */
9143 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
9144 exit(1);
a16ac624 9145#endif
b8c6940e 9146
f2ec385e
YM
9147#if __MWERKS__
9148 /* set creator and type for files created by MSL */
9149 _fcreator = MAC_EMACS_CREATOR_CODE;
9150 _ftype = 'TEXT';
742fbed7 9151#endif
177c0ea7 9152
f2ec385e 9153 do_init_managers ();
177c0ea7 9154
f2ec385e 9155 do_get_menus ();
660425fa 9156
f2ec385e
YM
9157#ifndef USE_LSB_TAG
9158 do_check_ram_size ();
742fbed7 9159#endif
1a578e9b 9160
f2ec385e 9161 init_emacs_passwd_dir ();
50bf7673 9162
f2ec385e 9163 init_environ ();
50bf7673 9164
f2ec385e 9165 init_coercion_handler ();
50bf7673 9166
f2ec385e 9167 initialize_applescript ();
50bf7673 9168
f2ec385e 9169 init_apple_event_handler ();
1a578e9b 9170
f2ec385e 9171 init_dm_notification_handler ();
19ee09cc 9172
1f98fbb4 9173 {
f2ec385e
YM
9174 char **argv;
9175 int argc = 0;
1f98fbb4 9176
f2ec385e
YM
9177 /* set up argv array from STR# resource */
9178 get_string_list (&argv, ARGV_STRING_LIST_ID);
9179 while (argv[argc])
9180 argc++;
1f98fbb4 9181
f2ec385e
YM
9182 /* free up AppleScript resources on exit */
9183 atexit (terminate_applescript);
1f98fbb4 9184
f2ec385e
YM
9185#if __profile__ /* is the profiler on? */
9186 atexit (profiler_exit_proc);
1f98fbb4
YM
9187#endif
9188
f2ec385e
YM
9189 /* 3rd param "envp" never used in emacs_main */
9190 (void) emacs_main (argc, argv, 0);
9191 }
1a578e9b 9192
f2ec385e
YM
9193 /* Never reached - real exit in Fkill_emacs */
9194 return 0;
9195}
1a578e9b
AC
9196
9197/* Need to override CodeWarrior's input function so no conversion is
9198 done on newlines Otherwise compiled functions in .elc files will be
9199 read incorrectly. Defined in ...:MSL C:MSL
9200 Common:Source:buffer_io.c. */
9201#ifdef __MWERKS__
9202void
9203__convert_to_newlines (unsigned char * p, size_t * n)
9204{
9205#pragma unused(p,n)
9206}
9207
9208void
9209__convert_from_newlines (unsigned char * p, size_t * n)
9210{
9211#pragma unused(p,n)
9212}
9213#endif
9214
770136ad 9215void
50bf7673 9216make_mac_terminal_frame (struct frame *f)
1a578e9b 9217{
50bf7673 9218 Lisp_Object frame;
b15325b2 9219 Rect r;
50bf7673
ST
9220
9221 XSETFRAME (frame, f);
9222
9223 f->output_method = output_mac;
9224 f->output_data.mac = (struct mac_output *)
9225 xmalloc (sizeof (struct mac_output));
9226 bzero (f->output_data.mac, sizeof (struct mac_output));
9227
9228 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
177c0ea7 9229
50bf7673
ST
9230 FRAME_COLS (f) = 96;
9231 FRAME_LINES (f) = 4;
9232
9233 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9234 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9235
9236 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
1a578e9b
AC
9237
9238 f->output_data.mac->cursor_pixel = 0;
9239 f->output_data.mac->border_pixel = 0x00ff00;
9240 f->output_data.mac->mouse_pixel = 0xff00ff;
9241 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9242
25c9622b
YM
9243 f->output_data.mac->text_cursor = kThemeIBeamCursor;
9244 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
9245 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
9246 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
9247 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
9248 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
b15325b2 9249
f1a83aab 9250 FRAME_FONTSET (f) = -1;
1a578e9b 9251 f->output_data.mac->explicit_parent = 0;
b15325b2
ST
9252 f->left_pos = 8;
9253 f->top_pos = 32;
f1a83aab 9254 f->border_width = 0;
177c0ea7 9255
f1a83aab 9256 f->internal_border_width = 0;
1a578e9b 9257
1a578e9b
AC
9258 f->auto_raise = 1;
9259 f->auto_lower = 1;
177c0ea7 9260
f1a83aab
KS
9261 f->new_text_cols = 0;
9262 f->new_text_lines = 0;
21a3e657 9263
b15325b2
ST
9264 SetRect (&r, f->left_pos, f->top_pos,
9265 f->left_pos + FRAME_PIXEL_WIDTH (f),
9266 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9267
9268 BLOCK_INPUT;
9269
9270 if (!(FRAME_MAC_WINDOW (f) =
9271 NewCWindow (NULL, &r, "\p", true, dBoxProc,
660425fa 9272 (WindowRef) -1, 1, (long) f->output_data.mac)))
b15325b2
ST
9273 abort ();
9274 /* so that update events can find this mac_output struct */
9275 f->output_data.mac->mFP = f; /* point back to emacs frame */
9276
9277 UNBLOCK_INPUT;
e0f712ba
AC
9278
9279 x_make_gc (f);
177c0ea7 9280
e0f712ba
AC
9281 /* Need to be initialized for unshow_buffer in window.c. */
9282 selected_window = f->selected_window;
9283
1a578e9b
AC
9284 Fmodify_frame_parameters (frame,
9285 Fcons (Fcons (Qfont,
9286 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9287 Fmodify_frame_parameters (frame,
9288 Fcons (Fcons (Qforeground_color,
9289 build_string ("black")), Qnil));
9290 Fmodify_frame_parameters (frame,
9291 Fcons (Fcons (Qbackground_color,
9292 build_string ("white")), Qnil));
9293}
f2ec385e 9294#endif /* MAC_OS8 */
1a578e9b 9295
e0f712ba
AC
9296\f
9297/***********************************************************************
9298 Initialization
9299 ***********************************************************************/
9300
19ee09cc 9301static int mac_initialized = 0;
b15325b2 9302
b298e813 9303static XrmDatabase
b15325b2 9304mac_make_rdb (xrm_option)
369a7a37 9305 const char *xrm_option;
b15325b2 9306{
b298e813 9307 XrmDatabase database;
b15325b2 9308
b298e813
YM
9309 database = xrm_get_preference_database (NULL);
9310 if (xrm_option)
9311 xrm_merge_string_database (database, xrm_option);
b15325b2 9312
b298e813 9313 return database;
b15325b2
ST
9314}
9315
e0f712ba
AC
9316struct mac_display_info *
9317mac_term_init (display_name, xrm_option, resource_name)
9318 Lisp_Object display_name;
9319 char *xrm_option;
9320 char *resource_name;
9321{
9322 struct mac_display_info *dpyinfo;
b15325b2
ST
9323
9324 BLOCK_INPUT;
e0f712ba
AC
9325
9326 if (!mac_initialized)
9327 {
9328 mac_initialize ();
9329 mac_initialized = 1;
9330 }
9331
b15325b2
ST
9332 if (x_display_list)
9333 error ("Sorry, this version can only handle one display");
9334
e0f712ba 9335 dpyinfo = &one_mac_display_info;
19ee09cc
YM
9336 bzero (dpyinfo, sizeof (*dpyinfo));
9337
9338#ifdef MAC_OSX
9339 dpyinfo->mac_id_name
9340 = (char *) xmalloc (SCHARS (Vinvocation_name)
9341 + SCHARS (Vsystem_name)
9342 + 2);
9343 sprintf (dpyinfo->mac_id_name, "%s@%s",
9344 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9345#else
9346 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9347 strcpy (dpyinfo->mac_id_name, "Mac Display");
9348#endif
9349
9350 dpyinfo->reference_count = 0;
9351 dpyinfo->resx = 72.0;
9352 dpyinfo->resy = 72.0;
9353
9354 mac_get_screen_info (dpyinfo);
9355
9356 dpyinfo->grabbed = 0;
9357 dpyinfo->root_window = NULL;
9358 dpyinfo->image_cache = make_image_cache ();
9359
9360 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9361 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9362 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9363 dpyinfo->mouse_face_window = Qnil;
9364 dpyinfo->mouse_face_overlay = Qnil;
9365 dpyinfo->mouse_face_hidden = 0;
e0f712ba 9366
b298e813 9367 dpyinfo->xrdb = mac_make_rdb (xrm_option);
e0f712ba 9368
b15325b2
ST
9369 /* Put this display on the chain. */
9370 dpyinfo->next = x_display_list;
9371 x_display_list = dpyinfo;
9372
9373 /* Put it on x_display_name_list. */
b298e813
YM
9374 x_display_name_list = Fcons (Fcons (display_name,
9375 Fcons (Qnil, dpyinfo->xrdb)),
b15325b2
ST
9376 x_display_name_list);
9377 dpyinfo->name_list_element = XCAR (x_display_name_list);
9378
9379 UNBLOCK_INPUT;
1a578e9b 9380
e0f712ba 9381 return dpyinfo;
1a578e9b 9382}
19ee09cc 9383\f
b15325b2
ST
9384/* Get rid of display DPYINFO, assuming all frames are already gone. */
9385
9386void
9387x_delete_display (dpyinfo)
9388 struct mac_display_info *dpyinfo;
9389{
9390 int i;
9391
9392 /* Discard this display from x_display_name_list and x_display_list.
9393 We can't use Fdelq because that can quit. */
9394 if (! NILP (x_display_name_list)
9395 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9396 x_display_name_list = XCDR (x_display_name_list);
9397 else
9398 {
9399 Lisp_Object tail;
9400
9401 tail = x_display_name_list;
9402 while (CONSP (tail) && CONSP (XCDR (tail)))
9403 {
9404 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9405 {
9406 XSETCDR (tail, XCDR (XCDR (tail)));
9407 break;
9408 }
9409 tail = XCDR (tail);
9410 }
9411 }
9412
9413 if (x_display_list == dpyinfo)
9414 x_display_list = dpyinfo->next;
9415 else
9416 {
9417 struct x_display_info *tail;
9418
9419 for (tail = x_display_list; tail; tail = tail->next)
9420 if (tail->next == dpyinfo)
9421 tail->next = tail->next->next;
9422 }
9423
9424 /* Free the font names in the font table. */
9425 for (i = 0; i < dpyinfo->n_fonts; i++)
9426 if (dpyinfo->font_table[i].name)
9427 {
9428 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9429 xfree (dpyinfo->font_table[i].full_name);
9430 xfree (dpyinfo->font_table[i].name);
9431 }
9432
1e53bd0e
YM
9433 if (dpyinfo->font_table)
9434 {
9435 if (dpyinfo->font_table->font_encoder)
9436 xfree (dpyinfo->font_table->font_encoder);
9437 xfree (dpyinfo->font_table);
9438 }
9439 if (dpyinfo->mac_id_name)
9440 xfree (dpyinfo->mac_id_name);
b15325b2
ST
9441
9442 if (x_display_list == 0)
9443 {
9444 mac_clear_font_name_table ();
9445 bzero (dpyinfo, sizeof (*dpyinfo));
9446 }
9447}
9448
e0f712ba
AC
9449\f
9450/* Set up use of X before we make the first connection. */
9451
88cd462d
KS
9452extern frame_parm_handler mac_frame_parm_handlers[];
9453
e0f712ba
AC
9454static struct redisplay_interface x_redisplay_interface =
9455{
88cd462d 9456 mac_frame_parm_handlers,
e0f712ba
AC
9457 x_produce_glyphs,
9458 x_write_glyphs,
9459 x_insert_glyphs,
9460 x_clear_end_of_line,
9461 x_scroll_run,
9462 x_after_update_window_line,
9463 x_update_window_begin,
9464 x_update_window_end,
f9e65eb3
KS
9465 x_cursor_to,
9466 x_flush,
e6509087
YM
9467#if USE_CG_DRAWING
9468 mac_flush_display_optional,
9469#else
fc7a70cc 9470 0, /* flush_display_optional */
e6509087 9471#endif
f9e65eb3 9472 x_clear_window_mouse_face,
e0f712ba 9473 x_get_glyph_overhangs,
5958f265 9474 x_fix_overlapping_area,
750fc673 9475 x_draw_fringe_bitmap,
ad21830e
YM
9476#if USE_CG_DRAWING
9477 mac_define_fringe_bitmap,
9478 mac_destroy_fringe_bitmap,
9479#else
288670f5
KS
9480 0, /* define_fringe_bitmap */
9481 0, /* destroy_fringe_bitmap */
ad21830e 9482#endif
750fc673
KS
9483 mac_per_char_metric,
9484 mac_encode_char,
8c2da0fa 9485 mac_compute_glyph_string_overhangs,
f9e65eb3
KS
9486 x_draw_glyph_string,
9487 mac_define_frame_cursor,
9488 mac_clear_frame_area,
9489 mac_draw_window_cursor,
efcf4234 9490 mac_draw_vertical_window_border,
f9e65eb3 9491 mac_shift_glyphs_for_insert
e0f712ba 9492};
1a578e9b
AC
9493
9494void
e0f712ba 9495mac_initialize ()
1a578e9b
AC
9496{
9497 rif = &x_redisplay_interface;
9498
9499 clear_frame_hook = x_clear_frame;
9500 ins_del_lines_hook = x_ins_del_lines;
1a578e9b
AC
9501 delete_glyphs_hook = x_delete_glyphs;
9502 ring_bell_hook = XTring_bell;
9503 reset_terminal_modes_hook = XTreset_terminal_modes;
9504 set_terminal_modes_hook = XTset_terminal_modes;
9505 update_begin_hook = x_update_begin;
9506 update_end_hook = x_update_end;
9507 set_terminal_window_hook = XTset_terminal_window;
9508 read_socket_hook = XTread_socket;
9509 frame_up_to_date_hook = XTframe_up_to_date;
1a578e9b
AC
9510 mouse_position_hook = XTmouse_position;
9511 frame_rehighlight_hook = XTframe_rehighlight;
9512 frame_raise_lower_hook = XTframe_raise_lower;
9513
9514 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9515 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9516 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9517 judge_scroll_bars_hook = XTjudge_scroll_bars;
9518
e0f712ba
AC
9519 scroll_region_ok = 1; /* we'll scroll partial frames */
9520 char_ins_del_ok = 1;
9521 line_ins_del_ok = 1; /* we'll just blt 'em */
9522 fast_clear_end_of_line = 1; /* X does this well */
9523 memory_below_frame = 0; /* we don't remember what scrolls
1a578e9b
AC
9524 off the bottom */
9525 baud_rate = 19200;
9526
1a578e9b 9527 last_tool_bar_item = -1;
177c0ea7 9528
1a578e9b
AC
9529 /* Try to use interrupt input; if we can't, then start polling. */
9530 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9531
c3f4c690 9532 BLOCK_INPUT;
bc21bf11
AC
9533
9534#if TARGET_API_MAC_CARBON
25c9622b 9535#ifdef MAC_OSX
0e0a1663
YM
9536 init_coercion_handler ();
9537
19ee09cc 9538 init_dm_notification_handler ();
f2ec385e 9539#endif
19ee09cc 9540
f2ec385e
YM
9541 install_application_handler ();
9542
9543 mac_toolbox_initialize ();
9544
9545#ifdef MAC_OSX
8030369c 9546 if (!inhibit_window_system)
5eafe967
YM
9547 {
9548 static const ProcessSerialNumber psn = {0, kCurrentProcess};
9549
9550 SetFrontProcess (&psn);
9551 }
25c9622b 9552#endif
bc21bf11 9553#endif
ad21830e
YM
9554
9555#if USE_CG_DRAWING
e2d3b7e1
YM
9556 init_cg_color ();
9557
ad21830e
YM
9558 mac_init_fringe ();
9559#endif
9560
c3f4c690 9561 UNBLOCK_INPUT;
1a578e9b
AC
9562}
9563
9564
9565void
9566syms_of_macterm ()
9567{
9568#if 0
9569 staticpro (&x_error_message_string);
9570 x_error_message_string = Qnil;
9571#endif
9572
f2d8779b
YM
9573 Qcontrol = intern ("control"); staticpro (&Qcontrol);
9574 Qmeta = intern ("meta"); staticpro (&Qmeta);
9575 Qalt = intern ("alt"); staticpro (&Qalt);
9576 Qhyper = intern ("hyper"); staticpro (&Qhyper);
9577 Qsuper = intern ("super"); staticpro (&Qsuper);
a36f1680 9578 Qmodifier_value = intern ("modifier-value");
f2d8779b
YM
9579 staticpro (&Qmodifier_value);
9580
9581 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
9582 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
9583 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9584 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9585 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
a36f1680 9586
660425fa 9587#if TARGET_API_MAC_CARBON
3e7424f7 9588 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
6a0b5d37 9589#ifdef MAC_OSX
68c767a3
YM
9590 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
9591 staticpro (&Qtoolbar_switch_mode);
9592#if USE_MAC_FONT_PANEL
9593 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
9594 Qselection = intern ("selection"); staticpro (&Qselection);
9595#endif
9596
4cb62a90 9597 Qservice = intern ("service"); staticpro (&Qservice);
1c05c15b
YM
9598 Qpaste = intern ("paste"); staticpro (&Qpaste);
9599 Qperform = intern ("perform"); staticpro (&Qperform);
e1adb139
YM
9600
9601 Qmouse_drag_overlay = intern ("mouse-drag-overlay");
9602 staticpro (&Qmouse_drag_overlay);
1c05c15b 9603#endif
02236cbc
YM
9604#if USE_MAC_TSM
9605 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
9606 Qupdate_active_input_area = intern ("update-active-input-area");
9607 staticpro (&Qupdate_active_input_area);
9608 Qunicode_for_key_event = intern ("unicode-for-key-event");
9609 staticpro (&Qunicode_for_key_event);
9610#endif
6a0b5d37 9611#endif
1c05c15b 9612
b15325b2 9613#ifdef MAC_OSX
8c609cff 9614 Fprovide (intern ("mac-carbon"), Qnil);
b15325b2 9615#endif
8c609cff 9616
dd4497dc
ST
9617 staticpro (&Qreverse);
9618 Qreverse = intern ("reverse");
9619
1a578e9b
AC
9620 staticpro (&x_display_name_list);
9621 x_display_name_list = Qnil;
9622
9623 staticpro (&last_mouse_scroll_bar);
9624 last_mouse_scroll_bar = Qnil;
9625
71b7a47f
YM
9626 staticpro (&fm_font_family_alist);
9627 fm_font_family_alist = Qnil;
8f47302e 9628
c3bd8190
YM
9629#if USE_ATSUI
9630 staticpro (&atsu_font_id_hash);
9631 atsu_font_id_hash = Qnil;
92289429
YM
9632
9633 staticpro (&fm_style_face_attributes_alist);
9634 fm_style_face_attributes_alist = Qnil;
9635#endif
9636
9637#if USE_MAC_TSM
9638 staticpro (&saved_ts_script_language_on_focus);
9639 saved_ts_script_language_on_focus = Qnil;
c3bd8190
YM
9640#endif
9641
70ed951a
YM
9642 /* We don't yet support this, but defining this here avoids whining
9643 from cus-start.el and other places, like "M-x set-variable". */
9644 DEFVAR_BOOL ("x-use-underline-position-properties",
9645 &x_use_underline_position_properties,
9646 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
17cf2c3e 9647A value of nil means ignore them. If you encounter fonts with bogus
70ed951a
YM
9648UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9649to 4.1, set this to nil.
9650
9651NOTE: Not supported on Mac yet. */);
9652 x_use_underline_position_properties = 0;
9653
cf2c6835
YM
9654 DEFVAR_BOOL ("x-underline-at-descent-line",
9655 &x_underline_at_descent_line,
9656 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
17cf2c3e
JB
9657A value of nil means to draw the underline according to the value of the
9658variable `x-use-underline-position-properties', which is usually at the
9659baseline level. The default value is nil. */);
cf2c6835
YM
9660 x_underline_at_descent_line = 0;
9661
e0f712ba 9662 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
68c767a3 9663 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
5b8b73ff 9664#ifdef USE_TOOLKIT_SCROLL_BARS
e0f712ba 9665 Vx_toolkit_scroll_bars = Qt;
5b8b73ff
YM
9666#else
9667 Vx_toolkit_scroll_bars = Qnil;
9668#endif
e0f712ba 9669
1a578e9b
AC
9670 staticpro (&last_mouse_motion_frame);
9671 last_mouse_motion_frame = Qnil;
16805b2e 9672
b02e3f7b 9673/* Variables to configure modifier key assignment. */
16805b2e 9674
b02e3f7b 9675 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
70ed951a
YM
9676 doc: /* *Modifier key assumed when the Mac control key is pressed.
9677The value can be `control', `meta', `alt', `hyper', or `super' for the
f2d8779b
YM
9678respective modifier. The default is `control'. */);
9679 Vmac_control_modifier = Qcontrol;
1a578e9b 9680
a36f1680 9681 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
70ed951a
YM
9682 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
9683The value can be `control', `meta', `alt', `hyper', or `super' for the
f2d8779b
YM
9684respective modifier. If the value is nil then the key will act as the
9685normal Mac control modifier, and the option key can be used to compose
9686characters depending on the chosen Mac keyboard setting. */);
a36f1680
JW
9687 Vmac_option_modifier = Qnil;
9688
b02e3f7b 9689 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
70ed951a
YM
9690 doc: /* *Modifier key assumed when the Mac command key is pressed.
9691The value can be `control', `meta', `alt', `hyper', or `super' for the
f2d8779b 9692respective modifier. The default is `meta'. */);
b02e3f7b
ST
9693 Vmac_command_modifier = Qmeta;
9694
9695 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
70ed951a
YM
9696 doc: /* *Modifier key assumed when the Mac function key is pressed.
9697The value can be `control', `meta', `alt', `hyper', or `super' for the
f2d8779b
YM
9698respective modifier. Note that remapping the function key may lead to
9699unexpected results for some keys on non-US/GB keyboards. */);
b02e3f7b 9700 Vmac_function_modifier = Qnil;
742fbed7 9701
ffe8b3f4 9702 DEFVAR_LISP ("mac-emulate-three-button-mouse",
dd4497dc 9703 &Vmac_emulate_three_button_mouse,
70ed951a 9704 doc: /* *Specify a way of three button mouse emulation.
f2d8779b 9705The value can be nil, t, or the symbol `reverse'.
17cf2c3e
JB
9706A value of nil means that no emulation should be done and the modifiers
9707should be placed on the mouse-1 event.
f2d8779b
YM
9708t means that when the option-key is held down while pressing the mouse
9709button, the click will register as mouse-2 and while the command-key
9710is held down, the click will register as mouse-3.
9711The symbol `reverse' means that the option-key will register for
9712mouse-3 and the command-key will register for mouse-2. */);
dd4497dc
ST
9713 Vmac_emulate_three_button_mouse = Qnil;
9714
660425fa 9715#if TARGET_API_MAC_CARBON
70ed951a 9716 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
68c767a3 9717 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
f2d8779b
YM
9718Otherwise, the right click will be treated as mouse-2 and the wheel
9719button will be mouse-3. */);
70ed951a 9720 mac_wheel_button_is_mouse_2 = 1;
5883787c 9721
70ed951a 9722 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
68c767a3 9723 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
70ed951a 9724 mac_pass_command_to_system = 1;
5883787c 9725
70ed951a 9726 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
68c767a3 9727 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
70ed951a 9728 mac_pass_control_to_system = 1;
743d0696 9729
742fbed7
AC
9730#endif
9731
70ed951a 9732 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
68c767a3 9733 doc: /* *If non-nil, allow anti-aliasing.
e24531b7
KS
9734The text will be rendered using Core Graphics text rendering which
9735may anti-alias the text. */);
458dbb8c
YM
9736#if USE_CG_DRAWING
9737 mac_use_core_graphics = 1;
9738#else
faef8681 9739 mac_use_core_graphics = 0;
458dbb8c 9740#endif
94d0e806
YM
9741
9742 /* Register an entry for `mac-roman' so that it can be used when
9743 creating the terminal frame on Mac OS 9 before loading
9744 term/mac-win.elc. */
9745 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
68c767a3 9746 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
94d0e806
YM
9747Each entry should be of the form:
9748
9749 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
9750
9751where CHARSET-NAME is a string used in font names to identify the
f2d8779b
YM
9752charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
9753CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
94d0e806
YM
9754 Vmac_charset_info_alist =
9755 Fcons (list3 (build_string ("mac-roman"),
9756 make_number (smRoman), Qnil), Qnil);
68c767a3 9757
02236cbc
YM
9758#if USE_MAC_TSM
9759 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
9760 doc: /* Overlay used to display Mac TSM active input area. */);
9761 Vmac_ts_active_input_overlay = Qnil;
b4c51596 9762
e1adb139
YM
9763 DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf,
9764 doc: /* Byte sequence of the current Mac TSM active input area. */);
9765 /* `empty_string' is not ready yet on Mac OS Classic. */
9766 Vmac_ts_active_input_buf = build_string ("");
9767
b4c51596
YM
9768 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
9769 doc: /* *How to change Mac TSM script/language when a frame gets focus.
9770If the value is t, the input script and language are restored to those
9771used in the last focus frame. If the value is a pair of integers, the
9772input script and language codes, which are defined in the Script
9773Manager, are set to its car and cdr parts, respectively. Otherwise,
9774Emacs doesn't set them and thus follows the system default behavior. */);
9775 Vmac_ts_script_language_on_focus = Qnil;
02236cbc 9776#endif
1a578e9b 9777}
ab5796a9
MB
9778
9779/* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9780 (do not change this comment) */