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