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