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