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