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