Add 2007 to copyright years.
[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
88 \f
89
90 /* Non-nil means Emacs uses toolkit scroll bars. */
91
92 Lisp_Object Vx_toolkit_scroll_bars;
93
94 /* If non-zero, the text will be rendered using Core Graphics text
95 rendering which may anti-alias the text. */
96 int mac_use_core_graphics;
97
98
99 /* Non-zero means that a HELP_EVENT has been generated since Emacs
100 start. */
101
102 static int any_help_event_p;
103
104 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
105 static Lisp_Object last_window;
106
107 /* Non-zero means make use of UNDERLINE_POSITION font properties.
108 (Not yet supported.) */
109 int x_use_underline_position_properties;
110
111 /* Non-zero means to draw the underline at the same place as the descent line. */
112
113 int x_underline_at_descent_line;
114
115 /* This is a chain of structures for all the X displays currently in
116 use. */
117
118 struct x_display_info *x_display_list;
119
120 /* This is a list of cons cells, each of the form (NAME
121 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
122 x_display_list and in the same order. NAME is the name of the
123 frame. FONT-LIST-CACHE records previous values returned by
124 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
125 equivalent, which is implemented with a Lisp object, for the
126 display. */
127
128 Lisp_Object x_display_name_list;
129
130 /* This is display since Mac does not support multiple ones. */
131 struct mac_display_info one_mac_display_info;
132
133 /* Frame being updated by update_frame. This is declared in term.c.
134 This is set by update_begin and looked at by all the XT functions.
135 It is zero while not inside an update. In that case, the XT
136 functions assume that `selected_frame' is the frame to apply to. */
137
138 extern struct frame *updating_frame;
139
140 /* This is a frame waiting to be auto-raised, within XTread_socket. */
141
142 struct frame *pending_autoraise_frame;
143
144 /* Mouse movement.
145
146 Formerly, we used PointerMotionHintMask (in standard_event_mask)
147 so that we would have to call XQueryPointer after each MotionNotify
148 event to ask for another such event. However, this made mouse tracking
149 slow, and there was a bug that made it eventually stop.
150
151 Simply asking for MotionNotify all the time seems to work better.
152
153 In order to avoid asking for motion events and then throwing most
154 of them away or busy-polling the server for mouse positions, we ask
155 the server for pointer motion hints. This means that we get only
156 one event per group of mouse movements. "Groups" are delimited by
157 other kinds of events (focus changes and button clicks, for
158 example), or by XQueryPointer calls; when one of these happens, we
159 get another MotionNotify event the next time the mouse moves. This
160 is at least as efficient as getting motion events when mouse
161 tracking is on, and I suspect only negligibly worse when tracking
162 is off. */
163
164 /* Where the mouse was last time we reported a mouse event. */
165
166 static Rect last_mouse_glyph;
167 static FRAME_PTR last_mouse_glyph_frame;
168
169 /* The scroll bar in which the last X motion event occurred.
170
171 If the last X motion event occurred in a scroll bar, we set this so
172 XTmouse_position can know whether to report a scroll bar motion or
173 an ordinary motion.
174
175 If the last X motion event didn't occur in a scroll bar, we set
176 this to Qnil, to tell XTmouse_position to return an ordinary motion
177 event. */
178
179 static Lisp_Object last_mouse_scroll_bar;
180
181 /* This is a hack. We would really prefer that XTmouse_position would
182 return the time associated with the position it returns, but there
183 doesn't seem to be any way to wrest the time-stamp from the server
184 along with the position query. So, we just keep track of the time
185 of the last movement we received, and return that in hopes that
186 it's somewhat accurate. */
187
188 static Time last_mouse_movement_time;
189
190 struct scroll_bar *tracked_scroll_bar = NULL;
191
192 /* Incremented by XTread_socket whenever it really tries to read
193 events. */
194
195 #ifdef __STDC__
196 static int volatile input_signal_count;
197 #else
198 static int input_signal_count;
199 #endif
200
201 extern Lisp_Object Vsystem_name;
202
203 extern Lisp_Object Qeql;
204
205 /* A mask of extra modifier bits to put into every keyboard char. */
206
207 extern EMACS_INT extra_keyboard_modifiers;
208
209 /* The keysyms to use for the various modifiers. */
210
211 static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
212
213 extern int inhibit_window_system;
214
215 #if __MRC__ && !TARGET_API_MAC_CARBON
216 QDGlobals qd; /* QuickDraw global information structure. */
217 #endif
218
219 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
220
221 struct mac_display_info *mac_display_info_for_display (Display *);
222 static void x_update_window_end P_ ((struct window *, int, int));
223 int x_catch_errors P_ ((Display *));
224 void x_uncatch_errors P_ ((Display *, int));
225 void x_lower_frame P_ ((struct frame *));
226 void x_scroll_bar_clear P_ ((struct frame *));
227 int x_had_errors_p P_ ((Display *));
228 void x_wm_set_size_hint P_ ((struct frame *, long, int));
229 void x_raise_frame P_ ((struct frame *));
230 void x_set_window_size P_ ((struct frame *, int, int, int));
231 void x_wm_set_window_state P_ ((struct frame *, int));
232 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
233 void mac_initialize P_ ((void));
234 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
235 static int x_compute_min_glyph_bounds P_ ((struct frame *));
236 static void x_update_end P_ ((struct frame *));
237 static void XTframe_up_to_date P_ ((struct frame *));
238 static void XTset_terminal_modes P_ ((void));
239 static void XTreset_terminal_modes P_ ((void));
240 static void x_clear_frame P_ ((void));
241 static void frame_highlight P_ ((struct frame *));
242 static void frame_unhighlight P_ ((struct frame *));
243 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
244 static void mac_focus_changed P_ ((int, struct mac_display_info *,
245 struct frame *, struct input_event *));
246 static void x_detect_focus_change P_ ((struct mac_display_info *,
247 const EventRecord *,
248 struct input_event *));
249 static void XTframe_rehighlight P_ ((struct frame *));
250 static void x_frame_rehighlight P_ ((struct x_display_info *));
251 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
252 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
253 enum text_cursor_kinds));
254
255 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
256 static void x_flush P_ ((struct frame *f));
257 static void x_update_begin P_ ((struct frame *));
258 static void x_update_window_begin P_ ((struct window *));
259 static void x_after_update_window_line P_ ((struct glyph_row *));
260 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
261 enum scroll_bar_part *,
262 Lisp_Object *, Lisp_Object *,
263 unsigned long *));
264
265 static int is_emacs_window P_ ((WindowPtr));
266 static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
267 static void XSetFont P_ ((Display *, GC, XFontStruct *));
268
269 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
270 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
271 #define GC_FONT(gc) ((gc)->xgcv.font)
272 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
273
274 #define CG_SET_FILL_COLOR(context, color) \
275 CGContextSetRGBFillColor (context, \
276 RED_FROM_ULONG (color) / 255.0f, \
277 GREEN_FROM_ULONG (color) / 255.0f, \
278 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
279 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
280 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
281 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
282 do { \
283 if (CGColorGetTypeID != NULL) \
284 CGContextSetFillColorWithColor (context, cg_color); \
285 else \
286 CG_SET_FILL_COLOR (context, color); \
287 } while (0)
288 #else
289 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
290 CGContextSetFillColorWithColor (context, cg_color)
291 #endif
292 #else
293 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
294 CG_SET_FILL_COLOR (context, color)
295 #endif
296 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
297 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
298 (gc)->cg_fore_color)
299 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
300 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
301 (gc)->cg_back_color)
302
303
304 #define CG_SET_STROKE_COLOR(context, color) \
305 CGContextSetRGBStrokeColor (context, \
306 RED_FROM_ULONG (color) / 255.0f, \
307 GREEN_FROM_ULONG (color) / 255.0f, \
308 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
309 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
310 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
311 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
312 do { \
313 if (CGColorGetTypeID != NULL) \
314 CGContextSetStrokeColorWithColor (context, cg_color); \
315 else \
316 CG_SET_STROKE_COLOR (context, color); \
317 } while (0)
318 #else
319 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
320 CGContextSetStrokeColorWithColor (context, cg_color)
321 #endif
322 #else
323 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
324 CG_SET_STROKE_COLOR (context, color)
325 #endif
326 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
327 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
328 (gc)->cg_fore_color)
329
330 #if USE_CG_DRAWING
331 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
332
333 /* Fringe bitmaps. */
334
335 static int max_fringe_bmp = 0;
336 static CGImageRef *fringe_bmp = 0;
337
338 static CGColorSpaceRef mac_cg_color_space_rgb;
339 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
340 static CGColorRef mac_cg_color_black;
341 #endif
342
343 static void
344 init_cg_color ()
345 {
346 mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB ();
347 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
348 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
349 /* Don't check the availability of CGColorCreate; this symbol is
350 defined even in Mac OS X 10.1. */
351 if (CGColorGetTypeID != NULL)
352 #endif
353 {
354 float rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
355
356 mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
357 }
358 #endif
359 }
360
361 static CGContextRef
362 mac_begin_cg_clip (f, gc)
363 struct frame *f;
364 GC gc;
365 {
366 CGContextRef context = FRAME_CG_CONTEXT (f);
367
368 if (!context)
369 {
370 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
371 FRAME_CG_CONTEXT (f) = context;
372 }
373
374 CGContextSaveGState (context);
375 CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
376 CGContextScaleCTM (context, 1, -1);
377 if (gc && gc->n_clip_rects)
378 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
379
380 return context;
381 }
382
383 static void
384 mac_end_cg_clip (f)
385 struct frame *f;
386 {
387 CGContextRestoreGState (FRAME_CG_CONTEXT (f));
388 }
389
390 void
391 mac_prepare_for_quickdraw (f)
392 struct frame *f;
393 {
394 if (f == NULL)
395 {
396 Lisp_Object rest, frame;
397 FOR_EACH_FRAME (rest, frame)
398 if (FRAME_MAC_P (XFRAME (frame)))
399 mac_prepare_for_quickdraw (XFRAME (frame));
400 }
401 else
402 {
403 CGContextRef context = FRAME_CG_CONTEXT (f);
404
405 if (context)
406 {
407 CGContextSynchronize (context);
408 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
409 &FRAME_CG_CONTEXT (f));
410 }
411 }
412 }
413 #endif
414
415 static RgnHandle saved_port_clip_region = NULL;
416
417 static void
418 mac_begin_clip (gc)
419 GC gc;
420 {
421 static RgnHandle new_region = NULL;
422
423 if (saved_port_clip_region == NULL)
424 saved_port_clip_region = NewRgn ();
425 if (new_region == NULL)
426 new_region = NewRgn ();
427
428 if (gc->n_clip_rects)
429 {
430 GetClip (saved_port_clip_region);
431 SectRgn (saved_port_clip_region, gc->clip_region, new_region);
432 SetClip (new_region);
433 }
434 }
435
436 static void
437 mac_end_clip (gc)
438 GC gc;
439 {
440 if (gc->n_clip_rects)
441 SetClip (saved_port_clip_region);
442 }
443
444
445 /* X display function emulation */
446
447 void
448 XFreePixmap (display, pixmap)
449 Display *display; /* not used */
450 Pixmap pixmap;
451 {
452 DisposeGWorld (pixmap);
453 }
454
455
456 /* Mac version of XDrawLine. */
457
458 static void
459 mac_draw_line (f, gc, x1, y1, x2, y2)
460 struct frame *f;
461 GC gc;
462 int x1, y1, x2, y2;
463 {
464 #if USE_CG_DRAWING
465 CGContextRef context;
466 float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
467
468 if (y1 != y2)
469 gx1 += 0.5f, gx2 += 0.5f;
470 if (x1 != x2)
471 gy1 += 0.5f, gy2 += 0.5f;
472
473 context = mac_begin_cg_clip (f, gc);
474 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
475 CGContextBeginPath (context);
476 CGContextMoveToPoint (context, gx1, gy1);
477 CGContextAddLineToPoint (context, gx2, gy2);
478 CGContextClosePath (context);
479 CGContextStrokePath (context);
480 mac_end_cg_clip (f);
481 #else
482 if (x1 == x2)
483 {
484 if (y1 > y2)
485 y1--;
486 else if (y2 > y1)
487 y2--;
488 }
489 else if (y1 == y2)
490 {
491 if (x1 > x2)
492 x1--;
493 else
494 x2--;
495 }
496
497 SetPortWindowPort (FRAME_MAC_WINDOW (f));
498
499 RGBForeColor (GC_FORE_COLOR (gc));
500
501 mac_begin_clip (gc);
502 MoveTo (x1, y1);
503 LineTo (x2, y2);
504 mac_end_clip (gc);
505 #endif
506 }
507
508 /* Mac version of XDrawLine (to Pixmap). */
509
510 void
511 XDrawLine (display, p, gc, x1, y1, x2, y2)
512 Display *display;
513 Pixmap p;
514 GC gc;
515 int x1, y1, x2, y2;
516 {
517 CGrafPtr old_port;
518 GDHandle old_gdh;
519
520 if (x1 == x2)
521 {
522 if (y1 > y2)
523 y1--;
524 else if (y2 > y1)
525 y2--;
526 }
527 else if (y1 == y2)
528 {
529 if (x1 > x2)
530 x1--;
531 else
532 x2--;
533 }
534
535 GetGWorld (&old_port, &old_gdh);
536 SetGWorld (p, NULL);
537
538 RGBForeColor (GC_FORE_COLOR (gc));
539
540 LockPixels (GetGWorldPixMap (p));
541 MoveTo (x1, y1);
542 LineTo (x2, y2);
543 UnlockPixels (GetGWorldPixMap (p));
544
545 SetGWorld (old_port, old_gdh);
546 }
547
548
549 static void
550 mac_erase_rectangle (f, gc, x, y, width, height)
551 struct frame *f;
552 GC gc;
553 int x, y;
554 unsigned int width, height;
555 {
556 #if USE_CG_DRAWING
557 CGContextRef context;
558
559 context = mac_begin_cg_clip (f, gc);
560 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
561 CGContextFillRect (context, CGRectMake (x, y, width, height));
562 mac_end_cg_clip (f);
563 #else
564 Rect r;
565
566 SetPortWindowPort (FRAME_MAC_WINDOW (f));
567
568 RGBBackColor (GC_BACK_COLOR (gc));
569 SetRect (&r, x, y, x + width, y + height);
570
571 mac_begin_clip (gc);
572 EraseRect (&r);
573 mac_end_clip (gc);
574
575 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
576 #endif
577 }
578
579
580 /* Mac version of XClearArea. */
581
582 void
583 mac_clear_area (f, x, y, width, height)
584 struct frame *f;
585 int x, y;
586 unsigned int width, height;
587 {
588 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
589 }
590
591 /* Mac version of XClearWindow. */
592
593 static void
594 mac_clear_window (f)
595 struct frame *f;
596 {
597 #if USE_CG_DRAWING
598 CGContextRef context;
599 GC gc = FRAME_NORMAL_GC (f);
600
601 context = mac_begin_cg_clip (f, NULL);
602 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
603 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
604 FRAME_PIXEL_HEIGHT (f)));
605 mac_end_cg_clip (f);
606 #else
607 SetPortWindowPort (FRAME_MAC_WINDOW (f));
608
609 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
610
611 #if TARGET_API_MAC_CARBON
612 {
613 Rect r;
614
615 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
616 EraseRect (&r);
617 }
618 #else /* not TARGET_API_MAC_CARBON */
619 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
620 #endif /* not TARGET_API_MAC_CARBON */
621 #endif
622 }
623
624
625 /* Mac replacement for XCopyArea. */
626
627 #if USE_CG_DRAWING
628 static void
629 mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
630 dest_x, dest_y, overlay_p)
631 CGImageRef image;
632 struct frame *f;
633 GC gc;
634 int src_x, src_y;
635 unsigned int width, height;
636 int dest_x, dest_y, overlay_p;
637 {
638 CGContextRef context;
639 float port_height = FRAME_PIXEL_HEIGHT (f);
640 CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
641
642 context = mac_begin_cg_clip (f, gc);
643 if (!overlay_p)
644 {
645 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
646 CGContextFillRect (context, dest_rect);
647 }
648 CGContextClipToRect (context, dest_rect);
649 CGContextScaleCTM (context, 1, -1);
650 CGContextTranslateCTM (context, 0, -port_height);
651 if (CGImageIsMask (image))
652 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
653 CGContextDrawImage (context,
654 CGRectMake (dest_x - src_x,
655 port_height - (dest_y - src_y
656 + CGImageGetHeight (image)),
657 CGImageGetWidth (image),
658 CGImageGetHeight (image)),
659 image);
660 mac_end_cg_clip (f);
661 }
662
663 #else /* !USE_CG_DRAWING */
664
665 static void
666 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
667 struct frame *f;
668 GC gc;
669 int x, y, width, height;
670 unsigned short *bits;
671 int overlay_p;
672 {
673 BitMap bitmap;
674 Rect r;
675
676 bitmap.rowBytes = sizeof(unsigned short);
677 bitmap.baseAddr = (char *)bits;
678 SetRect (&(bitmap.bounds), 0, 0, width, height);
679
680 SetPortWindowPort (FRAME_MAC_WINDOW (f));
681
682 RGBForeColor (GC_FORE_COLOR (gc));
683 RGBBackColor (GC_BACK_COLOR (gc));
684 SetRect (&r, x, y, x + width, y + height);
685
686 mac_begin_clip (gc);
687 #if TARGET_API_MAC_CARBON
688 {
689 CGrafPtr port;
690
691 GetPort (&port);
692 LockPortBits (port);
693 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
694 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
695 UnlockPortBits (port);
696 }
697 #else /* not TARGET_API_MAC_CARBON */
698 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
699 overlay_p ? srcOr : srcCopy, 0);
700 #endif /* not TARGET_API_MAC_CARBON */
701 mac_end_clip (gc);
702
703 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
704 }
705 #endif /* !USE_CG_DRAWING */
706
707
708 /* Mac replacement for XCreateBitmapFromBitmapData. */
709
710 static void
711 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
712 BitMap *bitmap;
713 char *bits;
714 int w, h;
715 {
716 static const unsigned char swap_nibble[16]
717 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
718 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
719 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
720 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
721 int i, j, w1;
722 char *p;
723
724 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
725 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
726 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
727 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
728 for (i = 0; i < h; i++)
729 {
730 p = bitmap->baseAddr + i * bitmap->rowBytes;
731 for (j = 0; j < w1; j++)
732 {
733 /* Bitswap XBM bytes to match how Mac does things. */
734 unsigned char c = *bits++;
735 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
736 | (swap_nibble[(c>>4) & 0xf]));;
737 }
738 }
739
740 SetRect (&(bitmap->bounds), 0, 0, w, h);
741 }
742
743
744 static void
745 mac_free_bitmap (bitmap)
746 BitMap *bitmap;
747 {
748 xfree (bitmap->baseAddr);
749 }
750
751
752 Pixmap
753 XCreatePixmap (display, w, width, height, depth)
754 Display *display; /* not used */
755 WindowPtr w;
756 unsigned int width, height;
757 unsigned int depth;
758 {
759 Pixmap pixmap;
760 Rect r;
761 QDErr err;
762
763 SetPortWindowPort (w);
764
765 SetRect (&r, 0, 0, width, height);
766 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
767 if (depth == 1)
768 #endif
769 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
770 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
771 else
772 /* CreateCGImageFromPixMaps requires ARGB format. */
773 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
774 #endif
775 if (err != noErr)
776 return NULL;
777 return pixmap;
778 }
779
780
781 Pixmap
782 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
783 Display *display; /* not used */
784 WindowPtr w;
785 char *data;
786 unsigned int width, height;
787 unsigned long fg, bg;
788 unsigned int depth;
789 {
790 Pixmap pixmap;
791 BitMap bitmap;
792 CGrafPtr old_port;
793 GDHandle old_gdh;
794 static GC gc = NULL; /* not reentrant */
795
796 if (gc == NULL)
797 gc = XCreateGC (display, w, 0, NULL);
798
799 pixmap = XCreatePixmap (display, w, width, height, depth);
800 if (pixmap == NULL)
801 return NULL;
802
803 GetGWorld (&old_port, &old_gdh);
804 SetGWorld (pixmap, NULL);
805 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
806 XSetForeground (display, gc, fg);
807 XSetBackground (display, gc, bg);
808 RGBForeColor (GC_FORE_COLOR (gc));
809 RGBBackColor (GC_BACK_COLOR (gc));
810 LockPixels (GetGWorldPixMap (pixmap));
811 #if TARGET_API_MAC_CARBON
812 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
813 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
814 #else /* not TARGET_API_MAC_CARBON */
815 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
816 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
817 #endif /* not TARGET_API_MAC_CARBON */
818 UnlockPixels (GetGWorldPixMap (pixmap));
819 SetGWorld (old_port, old_gdh);
820 mac_free_bitmap (&bitmap);
821
822 return pixmap;
823 }
824
825
826 /* Mac replacement for XFillRectangle. */
827
828 static void
829 mac_fill_rectangle (f, gc, x, y, width, height)
830 struct frame *f;
831 GC gc;
832 int x, y;
833 unsigned int width, height;
834 {
835 #if USE_CG_DRAWING
836 CGContextRef context;
837
838 context = mac_begin_cg_clip (f, gc);
839 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
840 CGContextFillRect (context, CGRectMake (x, y, width, height));
841 mac_end_cg_clip (f);
842 #else
843 Rect r;
844
845 SetPortWindowPort (FRAME_MAC_WINDOW (f));
846
847 RGBForeColor (GC_FORE_COLOR (gc));
848 SetRect (&r, x, y, x + width, y + height);
849
850 mac_begin_clip (gc);
851 PaintRect (&r); /* using foreground color of gc */
852 mac_end_clip (gc);
853 #endif
854 }
855
856
857 /* Mac replacement for XDrawRectangle: dest is a window. */
858
859 static void
860 mac_draw_rectangle (f, gc, x, y, width, height)
861 struct frame *f;
862 GC gc;
863 int x, y;
864 unsigned int width, height;
865 {
866 #if USE_CG_DRAWING
867 CGContextRef context;
868
869 context = mac_begin_cg_clip (f, gc);
870 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
871 CGContextStrokeRect (context,
872 CGRectMake (x + 0.5f, y + 0.5f, width, height));
873 mac_end_cg_clip (f);
874 #else
875 Rect r;
876
877 SetPortWindowPort (FRAME_MAC_WINDOW (f));
878
879 RGBForeColor (GC_FORE_COLOR (gc));
880 SetRect (&r, x, y, x + width + 1, y + height + 1);
881
882 mac_begin_clip (gc);
883 FrameRect (&r); /* using foreground color of gc */
884 mac_end_clip (gc);
885 #endif
886 }
887
888
889 #if USE_ATSUI
890 static OSStatus
891 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
892 ConstUniCharArrayPtr text;
893 UniCharCount text_length;
894 ATSUStyle style;
895 ATSUTextLayout *text_layout;
896 {
897 OSStatus err;
898 static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */
899
900 if (saved_text_layout == NULL)
901 {
902 static const UniCharCount lengths[] = {kATSUToTextEnd};
903 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
904 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
905 static ATSLineLayoutOptions line_layout =
906 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
907 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
908 | kATSLineUseQDRendering
909 #else
910 kATSLineIsDisplayOnly | kATSLineFractDisable
911 #endif
912 ;
913 static const ATSUAttributeValuePtr values[] = {&line_layout};
914
915 err = ATSUCreateTextLayoutWithTextPtr (text,
916 kATSUFromTextBeginning,
917 kATSUToTextEnd,
918 text_length,
919 1, lengths, &style,
920 &saved_text_layout);
921 if (err == noErr)
922 err = ATSUSetLayoutControls (saved_text_layout,
923 sizeof (tags) / sizeof (tags[0]),
924 tags, sizes, values);
925 /* XXX: Should we do this? */
926 if (err == noErr)
927 err = ATSUSetTransientFontMatching (saved_text_layout, true);
928 }
929 else
930 {
931 err = ATSUSetRunStyle (saved_text_layout, style,
932 kATSUFromTextBeginning, kATSUToTextEnd);
933 if (err == noErr)
934 err = ATSUSetTextPointerLocation (saved_text_layout, text,
935 kATSUFromTextBeginning,
936 kATSUToTextEnd,
937 text_length);
938 }
939
940 if (err == noErr)
941 *text_layout = saved_text_layout;
942 return err;
943 }
944 #endif
945
946
947 static void
948 mac_invert_rectangle (f, x, y, width, height)
949 struct frame *f;
950 int x, y;
951 unsigned int width, height;
952 {
953 Rect r;
954
955 #if USE_CG_DRAWING
956 mac_prepare_for_quickdraw (f);
957 #endif
958 SetPortWindowPort (FRAME_MAC_WINDOW (f));
959
960 SetRect (&r, x, y, x + width, y + height);
961
962 InvertRect (&r);
963 }
964
965
966 static void
967 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
968 overstrike_p, bytes_per_char)
969 struct frame *f;
970 GC gc;
971 int x, y;
972 char *buf;
973 int nchars, bg_width, overstrike_p, bytes_per_char;
974 {
975 SetPortWindowPort (FRAME_MAC_WINDOW (f));
976
977 #if USE_ATSUI
978 if (GC_FONT (gc)->mac_style)
979 {
980 OSStatus err;
981 ATSUTextLayout text_layout;
982
983 xassert (bytes_per_char == 2);
984
985 #ifndef WORDS_BIG_ENDIAN
986 {
987 int i;
988 UniChar *text = (UniChar *)buf;
989
990 for (i = 0; i < nchars; i++)
991 text[i] = EndianU16_BtoN (text[i]);
992 }
993 #endif
994 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
995 nchars,
996 GC_FONT (gc)->mac_style,
997 &text_layout);
998 if (err != noErr)
999 return;
1000 #ifdef MAC_OSX
1001 if (!mac_use_core_graphics)
1002 {
1003 #endif
1004 #if USE_CG_DRAWING
1005 mac_prepare_for_quickdraw (f);
1006 #endif
1007 mac_begin_clip (gc);
1008 RGBForeColor (GC_FORE_COLOR (gc));
1009 if (bg_width)
1010 {
1011 Rect r;
1012
1013 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1014 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1015 RGBBackColor (GC_BACK_COLOR (gc));
1016 EraseRect (&r);
1017 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1018 }
1019 MoveTo (x, y);
1020 ATSUDrawText (text_layout,
1021 kATSUFromTextBeginning, kATSUToTextEnd,
1022 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1023 if (overstrike_p)
1024 {
1025 MoveTo (x + 1, y);
1026 ATSUDrawText (text_layout,
1027 kATSUFromTextBeginning, kATSUToTextEnd,
1028 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1029 }
1030 mac_end_clip (gc);
1031 #ifdef MAC_OSX
1032 }
1033 else
1034 {
1035 CGrafPtr port;
1036 static CGContextRef context;
1037 float port_height = FRAME_PIXEL_HEIGHT (f);
1038 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
1039 static const ByteCount sizes[] = {sizeof (CGContextRef)};
1040 static const ATSUAttributeValuePtr values[] = {&context};
1041
1042 #if USE_CG_DRAWING
1043 context = mac_begin_cg_clip (f, gc);
1044 #else
1045 GetPort (&port);
1046 QDBeginCGContext (port, &context);
1047 if (gc->n_clip_rects || bg_width)
1048 {
1049 CGContextTranslateCTM (context, 0, port_height);
1050 CGContextScaleCTM (context, 1, -1);
1051 if (gc->n_clip_rects)
1052 CGContextClipToRects (context, gc->clip_rects,
1053 gc->n_clip_rects);
1054 #endif
1055 if (bg_width)
1056 {
1057 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1058 CGContextFillRect
1059 (context,
1060 CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
1061 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1062 }
1063 CGContextScaleCTM (context, 1, -1);
1064 CGContextTranslateCTM (context, 0, -port_height);
1065 #if !USE_CG_DRAWING
1066 }
1067 #endif
1068 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1069 err = ATSUSetLayoutControls (text_layout,
1070 sizeof (tags) / sizeof (tags[0]),
1071 tags, sizes, values);
1072 if (err == noErr)
1073 {
1074 ATSUDrawText (text_layout,
1075 kATSUFromTextBeginning, kATSUToTextEnd,
1076 Long2Fix (x), Long2Fix (port_height - y));
1077 if (overstrike_p)
1078 ATSUDrawText (text_layout,
1079 kATSUFromTextBeginning, kATSUToTextEnd,
1080 Long2Fix (x + 1), Long2Fix (port_height - y));
1081 }
1082 #if USE_CG_DRAWING
1083 mac_end_cg_clip (f);
1084 context = NULL;
1085 #else
1086 CGContextSynchronize (context);
1087 QDEndCGContext (port, &context);
1088 #endif
1089 #if 0
1090 /* This doesn't work on Mac OS X 10.1. */
1091 ATSUClearLayoutControls (text_layout,
1092 sizeof (tags) / sizeof (tags[0]), tags);
1093 #else
1094 ATSUSetLayoutControls (text_layout,
1095 sizeof (tags) / sizeof (tags[0]),
1096 tags, sizes, values);
1097 #endif
1098 }
1099 #endif /* MAC_OSX */
1100 }
1101 else
1102 #endif /* USE_ATSUI */
1103 {
1104 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1105 UInt32 savedFlags;
1106
1107 if (mac_use_core_graphics)
1108 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
1109 #endif
1110 #if USE_CG_DRAWING
1111 mac_prepare_for_quickdraw (f);
1112 #endif
1113 mac_begin_clip (gc);
1114 RGBForeColor (GC_FORE_COLOR (gc));
1115 #ifdef MAC_OS8
1116 if (bg_width)
1117 {
1118 RGBBackColor (GC_BACK_COLOR (gc));
1119 TextMode (srcCopy);
1120 }
1121 else
1122 TextMode (srcOr);
1123 #else
1124 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1125 because:
1126 - Screen is double-buffered. (In srcCopy mode, a text is
1127 drawn into an offscreen graphics world first. So
1128 performance gain cannot be expected.)
1129 - It lowers rendering quality.
1130 - Some fonts leave garbage on cursor movement. */
1131 if (bg_width)
1132 {
1133 Rect r;
1134
1135 RGBBackColor (GC_BACK_COLOR (gc));
1136 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1137 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1138 EraseRect (&r);
1139 }
1140 TextMode (srcOr);
1141 #endif
1142 TextFont (GC_FONT (gc)->mac_fontnum);
1143 TextSize (GC_FONT (gc)->mac_fontsize);
1144 TextFace (GC_FONT (gc)->mac_fontface);
1145 MoveTo (x, y);
1146 DrawText (buf, 0, nchars * bytes_per_char);
1147 if (overstrike_p)
1148 {
1149 TextMode (srcOr);
1150 MoveTo (x + 1, y);
1151 DrawText (buf, 0, nchars * bytes_per_char);
1152 }
1153 if (bg_width)
1154 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1155 mac_end_clip (gc);
1156
1157 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1158 if (mac_use_core_graphics)
1159 SwapQDTextFlags(savedFlags);
1160 #endif
1161 }
1162 }
1163
1164
1165 /* Mac replacement for XDrawImageString. */
1166
1167 static void
1168 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1169 struct frame *f;
1170 GC gc;
1171 int x, y;
1172 char *buf;
1173 int nchars, bg_width, overstrike_p;
1174 {
1175 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1176 overstrike_p, 1);
1177 }
1178
1179
1180 /* Mac replacement for XDrawImageString16. */
1181
1182 static void
1183 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1184 struct frame *f;
1185 GC gc;
1186 int x, y;
1187 XChar2b *buf;
1188 int nchars, bg_width, overstrike_p;
1189 {
1190 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1191 overstrike_p, 2);
1192 }
1193
1194
1195 /* Mac replacement for XQueryTextExtents, but takes a character. If
1196 STYLE is NULL, measurement is done by QuickDraw Text routines for
1197 the font of the current graphics port. If CG_GLYPH is not NULL,
1198 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1199
1200 static OSStatus
1201 mac_query_char_extents (style, c,
1202 font_ascent_return, font_descent_return,
1203 overall_return, cg_glyph)
1204 #if USE_ATSUI
1205 ATSUStyle style;
1206 #else
1207 void *style;
1208 #endif
1209 int c;
1210 int *font_ascent_return, *font_descent_return;
1211 XCharStruct *overall_return;
1212 #if USE_CG_TEXT_DRAWING
1213 CGGlyph *cg_glyph;
1214 #else
1215 void *cg_glyph;
1216 #endif
1217 {
1218 OSStatus err = noErr;
1219 int width;
1220 Rect char_bounds;
1221
1222 #if USE_ATSUI
1223 if (style)
1224 {
1225 ATSUTextLayout text_layout;
1226 UniChar ch = c;
1227
1228 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1229 if (err == noErr
1230 && (font_ascent_return || font_descent_return || overall_return))
1231 {
1232 ATSTrapezoid glyph_bounds;
1233
1234 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1235 kATSUFromTextBeginning, kATSUToTextEnd,
1236 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1237 kATSUseFractionalOrigins,
1238 #else
1239 kATSUseDeviceOrigins,
1240 #endif
1241 1, &glyph_bounds, NULL);
1242 if (err == noErr)
1243 {
1244 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1245 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1246
1247 width = Fix2Long (glyph_bounds.upperRight.x
1248 - glyph_bounds.upperLeft.x);
1249 if (font_ascent_return)
1250 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1251 if (font_descent_return)
1252 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1253 }
1254 }
1255 if (err == noErr && overall_return)
1256 {
1257 err = ATSUMeasureTextImage (text_layout,
1258 kATSUFromTextBeginning, kATSUToTextEnd,
1259 0, 0, &char_bounds);
1260 if (err == noErr)
1261 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1262 #if USE_CG_TEXT_DRAWING
1263 if (err == noErr && cg_glyph)
1264 {
1265 OSStatus err1;
1266 ATSUGlyphInfoArray glyph_info_array;
1267 ByteCount count = sizeof (ATSUGlyphInfoArray);
1268
1269 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1270 kATSUToTextEnd, NULL, NULL, NULL);
1271 if (err1 == noErr)
1272 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1273 kATSUToTextEnd, &count,
1274 &glyph_info_array);
1275 if (err1 == noErr
1276 /* Make sure that we don't have to make layout
1277 adjustments. */
1278 && glyph_info_array.glyphs[0].deltaY == 0.0f
1279 && glyph_info_array.glyphs[0].idealX == 0.0f
1280 && glyph_info_array.glyphs[0].screenX == 0)
1281 {
1282 xassert (glyph_info_array.glyphs[0].glyphID);
1283 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1284 }
1285 else
1286 *cg_glyph = 0;
1287 }
1288 #endif
1289 }
1290 }
1291 else
1292 #endif
1293 {
1294 if (font_ascent_return || font_descent_return)
1295 {
1296 FontInfo font_info;
1297
1298 GetFontInfo (&font_info);
1299 if (font_ascent_return)
1300 *font_ascent_return = font_info.ascent;
1301 if (font_descent_return)
1302 *font_descent_return = font_info.descent;
1303 }
1304 if (overall_return)
1305 {
1306 char ch = c;
1307
1308 width = CharWidth (ch);
1309 QDTextBounds (1, &ch, &char_bounds);
1310 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1311 }
1312 }
1313
1314 return err;
1315 }
1316
1317
1318 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1319
1320 static int
1321 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1322 XFontStruct *font_struct;
1323 XChar2b *string;
1324 int nchars;
1325 XCharStruct *overall_return;
1326 {
1327 int i;
1328 short width = 0, lbearing = 0, rbearing = 0;
1329 XCharStruct *pcm;
1330
1331 for (i = 0; i < nchars; i++)
1332 {
1333 pcm = mac_per_char_metric (font_struct, string, 0);
1334 if (pcm == NULL)
1335 width += FONT_WIDTH (font_struct);
1336 else
1337 {
1338 lbearing = min (lbearing, width + pcm->lbearing);
1339 rbearing = max (rbearing, width + pcm->rbearing);
1340 width += pcm->width;
1341 }
1342 string++;
1343 }
1344
1345 overall_return->lbearing = lbearing;
1346 overall_return->rbearing = rbearing;
1347 overall_return->width = width;
1348
1349 /* What's the meaning of the return value of XTextExtents16? */
1350 }
1351
1352
1353 #if USE_CG_TEXT_DRAWING
1354 static int cg_text_anti_aliasing_threshold = 8;
1355
1356 static void
1357 init_cg_text_anti_aliasing_threshold ()
1358 {
1359 int threshold;
1360 Boolean valid_p;
1361
1362 threshold =
1363 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1364 kCFPreferencesCurrentApplication,
1365 &valid_p);
1366 if (valid_p)
1367 cg_text_anti_aliasing_threshold = threshold;
1368 }
1369
1370 static int
1371 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1372 struct frame *f;
1373 GC gc;
1374 int x, y;
1375 XChar2b *buf;
1376 int nchars, bg_width, overstrike_p;
1377 {
1378 CGrafPtr port;
1379 float port_height, gx, gy;
1380 int i;
1381 CGContextRef context;
1382 CGGlyph *glyphs;
1383 CGSize *advances;
1384
1385 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1386 return 0;
1387
1388 port = GetWindowPort (FRAME_MAC_WINDOW (f));
1389 port_height = FRAME_PIXEL_HEIGHT (f);
1390 gx = x;
1391 gy = port_height - y;
1392 glyphs = (CGGlyph *)buf;
1393 advances = alloca (sizeof (CGSize) * nchars);
1394 if (advances == NULL)
1395 return 0;
1396 for (i = 0; i < nchars; i++)
1397 {
1398 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1399
1400 advances[i].width = pcm->width;
1401 advances[i].height = 0;
1402 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1403 buf++;
1404 }
1405
1406 #if USE_CG_DRAWING
1407 context = mac_begin_cg_clip (f, gc);
1408 #else
1409 QDBeginCGContext (port, &context);
1410 if (gc->n_clip_rects || bg_width)
1411 {
1412 CGContextTranslateCTM (context, 0, port_height);
1413 CGContextScaleCTM (context, 1, -1);
1414 if (gc->n_clip_rects)
1415 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1416 #endif
1417 if (bg_width)
1418 {
1419 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1420 CGContextFillRect
1421 (context,
1422 CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
1423 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1424 }
1425 CGContextScaleCTM (context, 1, -1);
1426 CGContextTranslateCTM (context, 0, -port_height);
1427 #if !USE_CG_DRAWING
1428 }
1429 #endif
1430 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1431 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1432 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1433 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1434 CGContextSetShouldAntialias (context, false);
1435 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1436 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1437 if (CGContextShowGlyphsWithAdvances != NULL)
1438 #endif
1439 {
1440 CGContextSetTextPosition (context, gx, gy);
1441 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1442 if (overstrike_p)
1443 {
1444 CGContextSetTextPosition (context, gx + 1.0f, gy);
1445 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1446 }
1447 }
1448 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1449 else
1450 #endif
1451 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1452 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1453 {
1454 for (i = 0; i < nchars; i++)
1455 {
1456 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1457 if (overstrike_p)
1458 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1459 gx += advances[i].width;
1460 }
1461 }
1462 #endif
1463 #if USE_CG_DRAWING
1464 mac_end_cg_clip (f);
1465 #else
1466 CGContextSynchronize (context);
1467 QDEndCGContext (port, &context);
1468 #endif
1469
1470 return 1;
1471 }
1472 #endif
1473
1474
1475 #if !USE_CG_DRAWING
1476 /* Mac replacement for XCopyArea: dest must be window. */
1477
1478 static void
1479 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1480 Pixmap src;
1481 struct frame *f;
1482 GC gc;
1483 int src_x, src_y;
1484 unsigned int width, height;
1485 int dest_x, dest_y;
1486 {
1487 Rect src_r, dest_r;
1488
1489 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1490
1491 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1492 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1493
1494 ForeColor (blackColor);
1495 BackColor (whiteColor);
1496
1497 mac_begin_clip (gc);
1498 LockPixels (GetGWorldPixMap (src));
1499 #if TARGET_API_MAC_CARBON
1500 {
1501 CGrafPtr port;
1502
1503 GetPort (&port);
1504 LockPortBits (port);
1505 CopyBits (GetPortBitMapForCopyBits (src),
1506 GetPortBitMapForCopyBits (port),
1507 &src_r, &dest_r, srcCopy, 0);
1508 UnlockPortBits (port);
1509 }
1510 #else /* not TARGET_API_MAC_CARBON */
1511 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1512 &src_r, &dest_r, srcCopy, 0);
1513 #endif /* not TARGET_API_MAC_CARBON */
1514 UnlockPixels (GetGWorldPixMap (src));
1515 mac_end_clip (gc);
1516
1517 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1518 }
1519
1520
1521 static void
1522 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1523 width, height, dest_x, dest_y)
1524 Pixmap src, mask;
1525 struct frame *f;
1526 GC gc;
1527 int src_x, src_y;
1528 unsigned int width, height;
1529 int dest_x, dest_y;
1530 {
1531 Rect src_r, dest_r;
1532
1533 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1534
1535 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1536 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1537
1538 ForeColor (blackColor);
1539 BackColor (whiteColor);
1540
1541 mac_begin_clip (gc);
1542 LockPixels (GetGWorldPixMap (src));
1543 LockPixels (GetGWorldPixMap (mask));
1544 #if TARGET_API_MAC_CARBON
1545 {
1546 CGrafPtr port;
1547
1548 GetPort (&port);
1549 LockPortBits (port);
1550 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1551 GetPortBitMapForCopyBits (port),
1552 &src_r, &src_r, &dest_r);
1553 UnlockPortBits (port);
1554 }
1555 #else /* not TARGET_API_MAC_CARBON */
1556 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1557 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1558 #endif /* not TARGET_API_MAC_CARBON */
1559 UnlockPixels (GetGWorldPixMap (mask));
1560 UnlockPixels (GetGWorldPixMap (src));
1561 mac_end_clip (gc);
1562
1563 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1564 }
1565 #endif /* !USE_CG_DRAWING */
1566
1567
1568 /* Mac replacement for XCopyArea: used only for scrolling. */
1569
1570 static void
1571 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1572 struct frame *f;
1573 GC gc;
1574 int src_x, src_y;
1575 unsigned int width, height;
1576 int dest_x, dest_y;
1577 {
1578 #if TARGET_API_MAC_CARBON
1579 Rect src_r;
1580 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
1581
1582 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1583 #if USE_CG_DRAWING
1584 mac_prepare_for_quickdraw (f);
1585 #endif
1586 ScrollWindowRect (FRAME_MAC_WINDOW (f),
1587 &src_r, dest_x - src_x, dest_y - src_y,
1588 kScrollWindowNoOptions, dummy);
1589 DisposeRgn (dummy);
1590 #else /* not TARGET_API_MAC_CARBON */
1591 Rect src_r, dest_r;
1592 WindowPtr w = FRAME_MAC_WINDOW (f);
1593
1594 SetPort (w);
1595
1596 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1597 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1598
1599 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1600 color mapping in CopyBits. Otherwise, it will be slow. */
1601 ForeColor (blackColor);
1602 BackColor (whiteColor);
1603 mac_begin_clip (gc);
1604 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1605 mac_end_clip (gc);
1606
1607 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1608 #endif /* not TARGET_API_MAC_CARBON */
1609 }
1610
1611
1612 /* Mac replacement for XChangeGC. */
1613
1614 static void
1615 XChangeGC (display, gc, mask, xgcv)
1616 Display *display;
1617 GC gc;
1618 unsigned long mask;
1619 XGCValues *xgcv;
1620 {
1621 if (mask & GCForeground)
1622 XSetForeground (display, gc, xgcv->foreground);
1623 if (mask & GCBackground)
1624 XSetBackground (display, gc, xgcv->background);
1625 if (mask & GCFont)
1626 XSetFont (display, gc, xgcv->font);
1627 }
1628
1629
1630 /* Mac replacement for XCreateGC. */
1631
1632 GC
1633 XCreateGC (display, d, mask, xgcv)
1634 Display *display;
1635 void *d;
1636 unsigned long mask;
1637 XGCValues *xgcv;
1638 {
1639 GC gc = xmalloc (sizeof (*gc));
1640
1641 bzero (gc, sizeof (*gc));
1642 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1643 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1644 if (CGColorGetTypeID != NULL)
1645 #endif
1646 {
1647 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1648 CGColorRetain (gc->cg_fore_color);
1649 CGColorRetain (gc->cg_back_color);
1650 }
1651 #endif
1652 XChangeGC (display, gc, mask, xgcv);
1653
1654 return gc;
1655 }
1656
1657
1658 /* Used in xfaces.c. */
1659
1660 void
1661 XFreeGC (display, gc)
1662 Display *display;
1663 GC gc;
1664 {
1665 if (gc->clip_region)
1666 DisposeRgn (gc->clip_region);
1667 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1668 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1669 if (CGColorGetTypeID != NULL)
1670 #endif
1671 {
1672 CGColorRelease (gc->cg_fore_color);
1673 CGColorRelease (gc->cg_back_color);
1674 }
1675 #endif
1676 xfree (gc);
1677 }
1678
1679
1680 /* Mac replacement for XGetGCValues. */
1681
1682 static void
1683 XGetGCValues (display, gc, mask, xgcv)
1684 Display *display;
1685 GC gc;
1686 unsigned long mask;
1687 XGCValues *xgcv;
1688 {
1689 if (mask & GCForeground)
1690 xgcv->foreground = gc->xgcv.foreground;
1691 if (mask & GCBackground)
1692 xgcv->background = gc->xgcv.background;
1693 if (mask & GCFont)
1694 xgcv->font = gc->xgcv.font;
1695 }
1696
1697
1698 /* Mac replacement for XSetForeground. */
1699
1700 void
1701 XSetForeground (display, gc, color)
1702 Display *display;
1703 GC gc;
1704 unsigned long color;
1705 {
1706 if (gc->xgcv.foreground != color)
1707 {
1708 gc->xgcv.foreground = color;
1709 gc->fore_color.red = RED16_FROM_ULONG (color);
1710 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1711 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1712 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1713 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1714 if (CGColorGetTypeID != NULL)
1715 #endif
1716 {
1717 CGColorRelease (gc->cg_fore_color);
1718 if (color == 0)
1719 {
1720 gc->cg_fore_color = mac_cg_color_black;
1721 CGColorRetain (gc->cg_fore_color);
1722 }
1723 else
1724 {
1725 float rgba[4];
1726
1727 rgba[0] = gc->fore_color.red / 65535.0f;
1728 rgba[1] = gc->fore_color.green / 65535.0f;
1729 rgba[2] = gc->fore_color.blue / 65535.0f;
1730 rgba[3] = 1.0f;
1731 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1732 }
1733 }
1734 #endif
1735 }
1736 }
1737
1738
1739 /* Mac replacement for XSetBackground. */
1740
1741 void
1742 XSetBackground (display, gc, color)
1743 Display *display;
1744 GC gc;
1745 unsigned long color;
1746 {
1747 if (gc->xgcv.background != color)
1748 {
1749 gc->xgcv.background = color;
1750 gc->back_color.red = RED16_FROM_ULONG (color);
1751 gc->back_color.green = GREEN16_FROM_ULONG (color);
1752 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1753 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1754 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1755 if (CGColorGetTypeID != NULL)
1756 #endif
1757 {
1758 CGColorRelease (gc->cg_back_color);
1759 if (color == 0)
1760 {
1761 gc->cg_back_color = mac_cg_color_black;
1762 CGColorRetain (gc->cg_back_color);
1763 }
1764 else
1765 {
1766 float rgba[4];
1767
1768 rgba[0] = gc->back_color.red / 65535.0f;
1769 rgba[1] = gc->back_color.green / 65535.0f;
1770 rgba[2] = gc->back_color.blue / 65535.0f;
1771 rgba[3] = 1.0f;
1772 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1773 }
1774 }
1775 #endif
1776 }
1777 }
1778
1779
1780 /* Mac replacement for XSetFont. */
1781
1782 static void
1783 XSetFont (display, gc, font)
1784 Display *display;
1785 GC gc;
1786 XFontStruct *font;
1787 {
1788 gc->xgcv.font = font;
1789 }
1790
1791
1792 /* Mac replacement for XSetClipRectangles. */
1793
1794 static void
1795 mac_set_clip_rectangles (display, gc, rectangles, n)
1796 Display *display;
1797 GC gc;
1798 Rect *rectangles;
1799 int n;
1800 {
1801 int i;
1802
1803 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1804
1805 gc->n_clip_rects = n;
1806 if (n > 0)
1807 {
1808 if (gc->clip_region == NULL)
1809 gc->clip_region = NewRgn ();
1810 RectRgn (gc->clip_region, rectangles);
1811 if (n > 1)
1812 {
1813 RgnHandle region = NewRgn ();
1814
1815 for (i = 1; i < n; i++)
1816 {
1817 RectRgn (region, rectangles + i);
1818 UnionRgn (gc->clip_region, region, gc->clip_region);
1819 }
1820 DisposeRgn (region);
1821 }
1822 }
1823 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1824 for (i = 0; i < n; i++)
1825 {
1826 Rect *rect = rectangles + i;
1827
1828 gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
1829 rect->right - rect->left,
1830 rect->bottom - rect->top);
1831 }
1832 #endif
1833 }
1834
1835
1836 /* Mac replacement for XSetClipMask. */
1837
1838 static INLINE void
1839 mac_reset_clip_rectangles (display, gc)
1840 Display *display;
1841 GC gc;
1842 {
1843 gc->n_clip_rects = 0;
1844 }
1845
1846
1847 /* Mac replacement for XSetWindowBackground. */
1848
1849 void
1850 XSetWindowBackground (display, w, color)
1851 Display *display;
1852 WindowPtr w;
1853 unsigned long color;
1854 {
1855 #if !TARGET_API_MAC_CARBON
1856 AuxWinHandle aw_handle;
1857 CTabHandle ctab_handle;
1858 ColorSpecPtr ct_table;
1859 short ct_size;
1860 #endif
1861 RGBColor bg_color;
1862
1863 bg_color.red = RED16_FROM_ULONG (color);
1864 bg_color.green = GREEN16_FROM_ULONG (color);
1865 bg_color.blue = BLUE16_FROM_ULONG (color);
1866
1867 #if TARGET_API_MAC_CARBON
1868 SetWindowContentColor (w, &bg_color);
1869 #else
1870 if (GetAuxWin (w, &aw_handle))
1871 {
1872 ctab_handle = (*aw_handle)->awCTable;
1873 HandToHand ((Handle *) &ctab_handle);
1874 ct_table = (*ctab_handle)->ctTable;
1875 ct_size = (*ctab_handle)->ctSize;
1876 while (ct_size > -1)
1877 {
1878 if (ct_table->value == 0)
1879 {
1880 ct_table->rgb = bg_color;
1881 CTabChanged (ctab_handle);
1882 SetWinColor (w, (WCTabHandle) ctab_handle);
1883 }
1884 ct_size--;
1885 }
1886 }
1887 #endif
1888 }
1889
1890 /* Flush display of frame F, or of all frames if F is null. */
1891
1892 static void
1893 x_flush (f)
1894 struct frame *f;
1895 {
1896 #if TARGET_API_MAC_CARBON
1897 BLOCK_INPUT;
1898 #if USE_CG_DRAWING
1899 mac_prepare_for_quickdraw (f);
1900 #endif
1901 if (f)
1902 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1903 else
1904 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1905 UNBLOCK_INPUT;
1906 #endif
1907 }
1908
1909
1910 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1911 Calls to XFlush should be unnecessary because the X output buffer
1912 is flushed automatically as needed by calls to XPending,
1913 XNextEvent, or XWindowEvent according to the XFlush man page.
1914 XTread_socket calls XPending. Removing XFlush improves
1915 performance. */
1916
1917 #define XFlush(DISPLAY) (void) 0
1918
1919 \f
1920 /* Return the struct mac_display_info corresponding to DPY. There's
1921 only one. */
1922
1923 struct mac_display_info *
1924 mac_display_info_for_display (dpy)
1925 Display *dpy;
1926 {
1927 return &one_mac_display_info;
1928 }
1929
1930
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 *, int *));
2332
2333
2334 static void
2335 pcm_init (pcm, count)
2336 XCharStruct *pcm;
2337 int count;
2338 {
2339 bzero (pcm, sizeof (XCharStruct) * count);
2340 while (--count >= 0)
2341 {
2342 pcm->descent = PCM_INVALID;
2343 pcm++;
2344 }
2345 }
2346
2347 static enum pcm_status
2348 pcm_get_status (pcm)
2349 const XCharStruct *pcm;
2350 {
2351 int height = pcm->ascent + pcm->descent;
2352
2353 /* Negative height means some special status. */
2354 return height >= 0 ? PCM_VALID : height;
2355 }
2356
2357 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2358 is not contained in the font. */
2359
2360 static INLINE XCharStruct *
2361 x_per_char_metric (font, char2b)
2362 XFontStruct *font;
2363 XChar2b *char2b;
2364 {
2365 /* The result metric information. */
2366 XCharStruct *pcm = NULL;
2367
2368 xassert (font && char2b);
2369
2370 #if USE_ATSUI
2371 if (font->mac_style)
2372 {
2373 XCharStruct **row = font->bounds.rows + char2b->byte1;
2374
2375 if (*row == NULL)
2376 {
2377 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2378 pcm_init (*row, 0x100);
2379 }
2380 pcm = *row + char2b->byte2;
2381 if (pcm_get_status (pcm) != PCM_VALID)
2382 {
2383 BLOCK_INPUT;
2384 mac_query_char_extents (font->mac_style,
2385 (char2b->byte1 << 8) + char2b->byte2,
2386 NULL, NULL, pcm, NULL);
2387 UNBLOCK_INPUT;
2388 }
2389 }
2390 else
2391 {
2392 #endif
2393 if (font->bounds.per_char != NULL)
2394 {
2395 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2396 {
2397 /* min_char_or_byte2 specifies the linear character index
2398 corresponding to the first element of the per_char array,
2399 max_char_or_byte2 is the index of the last character. A
2400 character with non-zero CHAR2B->byte1 is not in the font.
2401 A character with byte2 less than min_char_or_byte2 or
2402 greater max_char_or_byte2 is not in the font. */
2403 if (char2b->byte1 == 0
2404 && char2b->byte2 >= font->min_char_or_byte2
2405 && char2b->byte2 <= font->max_char_or_byte2)
2406 pcm = font->bounds.per_char
2407 + (char2b->byte2 - font->min_char_or_byte2);
2408 }
2409 else
2410 {
2411 /* If either min_byte1 or max_byte1 are nonzero, both
2412 min_char_or_byte2 and max_char_or_byte2 are less than
2413 256, and the 2-byte character index values corresponding
2414 to the per_char array element N (counting from 0) are:
2415
2416 byte1 = N/D + min_byte1
2417 byte2 = N\D + min_char_or_byte2
2418
2419 where:
2420
2421 D = max_char_or_byte2 - min_char_or_byte2 + 1
2422 / = integer division
2423 \ = integer modulus */
2424 if (char2b->byte1 >= font->min_byte1
2425 && char2b->byte1 <= font->max_byte1
2426 && char2b->byte2 >= font->min_char_or_byte2
2427 && char2b->byte2 <= font->max_char_or_byte2)
2428 {
2429 pcm = (font->bounds.per_char
2430 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2431 * (char2b->byte1 - font->min_byte1))
2432 + (char2b->byte2 - font->min_char_or_byte2));
2433 }
2434 }
2435 }
2436 else
2437 {
2438 /* If the per_char pointer is null, all glyphs between the first
2439 and last character indexes inclusive have the same
2440 information, as given by both min_bounds and max_bounds. */
2441 if (char2b->byte2 >= font->min_char_or_byte2
2442 && char2b->byte2 <= font->max_char_or_byte2)
2443 pcm = &font->max_bounds;
2444 }
2445 #if USE_ATSUI
2446 }
2447 #endif
2448
2449 return ((pcm == NULL
2450 || (pcm->width == 0
2451 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2452 && (pcm->rbearing - pcm->lbearing) == 0
2453 #endif
2454 ))
2455 ? NULL : pcm);
2456 }
2457
2458 /* RIF:
2459 */
2460
2461 static XCharStruct *
2462 mac_per_char_metric (font, char2b, font_type)
2463 XFontStruct *font;
2464 XChar2b *char2b;
2465 int font_type;
2466 {
2467 return x_per_char_metric (font, char2b);
2468 }
2469
2470 /* RIF:
2471 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2472 the two-byte form of C. Encoding is returned in *CHAR2B. */
2473
2474 static int
2475 mac_encode_char (c, char2b, font_info, two_byte_p)
2476 int c;
2477 XChar2b *char2b;
2478 struct font_info *font_info;
2479 int *two_byte_p;
2480 {
2481 int charset = CHAR_CHARSET (c);
2482 XFontStruct *font = font_info->font;
2483
2484 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2485 This may be either a program in a special encoder language or a
2486 fixed encoding. */
2487 if (font_info->font_encoder)
2488 {
2489 /* It's a program. */
2490 struct ccl_program *ccl = font_info->font_encoder;
2491
2492 check_ccl_update (ccl);
2493 if (CHARSET_DIMENSION (charset) == 1)
2494 {
2495 ccl->reg[0] = charset;
2496 ccl->reg[1] = char2b->byte2;
2497 ccl->reg[2] = -1;
2498 }
2499 else
2500 {
2501 ccl->reg[0] = charset;
2502 ccl->reg[1] = char2b->byte1;
2503 ccl->reg[2] = char2b->byte2;
2504 }
2505
2506 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2507
2508 /* We assume that MSBs are appropriately set/reset by CCL
2509 program. */
2510 if (font->max_byte1 == 0) /* 1-byte font */
2511 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2512 else
2513 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2514 }
2515 else if (font_info->encoding[charset])
2516 {
2517 /* Fixed encoding scheme. See fontset.h for the meaning of the
2518 encoding numbers. */
2519 int enc = font_info->encoding[charset];
2520
2521 if ((enc == 1 || enc == 2)
2522 && CHARSET_DIMENSION (charset) == 2)
2523 char2b->byte1 |= 0x80;
2524
2525 if (enc == 1 || enc == 3)
2526 char2b->byte2 |= 0x80;
2527
2528 if (enc == 4)
2529 {
2530 int sjis1, sjis2;
2531
2532 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2533 char2b->byte1 = sjis1;
2534 char2b->byte2 = sjis2;
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);
2655 else
2656 face_id = FACE_FOR_CHAR (s->f, face, 0);
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,
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, bufp)
4766 struct scroll_bar *bar;
4767 ControlPartCode part_code;
4768 struct input_event *bufp;
4769 {
4770 int part = control_part_code_to_scroll_bar_part (part_code);
4771
4772 if (part < 0)
4773 return;
4774
4775 if (part != scroll_bar_handle)
4776 {
4777 construct_scroll_bar_click (bar, part, bufp);
4778 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4779 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
4780 }
4781
4782 last_scroll_bar_part = part;
4783 bar->dragging = Qnil;
4784 tracked_scroll_bar = bar;
4785 }
4786
4787 static void
4788 x_scroll_bar_handle_release (bar, bufp)
4789 struct scroll_bar *bar;
4790 struct input_event *bufp;
4791 {
4792 if (last_scroll_bar_part != scroll_bar_handle
4793 || !GC_NILP (bar->dragging))
4794 construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
4795
4796 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4797 set_scroll_bar_timer (kEventDurationForever);
4798
4799 last_scroll_bar_part = -1;
4800 bar->dragging = Qnil;
4801 tracked_scroll_bar = NULL;
4802 }
4803
4804 static void
4805 x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
4806 WindowPtr win;
4807 struct scroll_bar *bar;
4808 Point mouse_pos;
4809 struct input_event *bufp;
4810 {
4811 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4812
4813 if (last_scroll_bar_part == scroll_bar_handle)
4814 {
4815 int top, top_range;
4816 Rect r;
4817
4818 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
4819 kControlIndicatorPart, &r);
4820
4821 if (GC_NILP (bar->dragging))
4822 XSETINT (bar->dragging, mouse_pos.v - r.top);
4823
4824 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
4825 top_range = (XINT (bar->track_height) - (r.bottom - r.top)) *
4826 (1.0 + (float) GetControlViewSize (ch) / GetControl32BitMaximum (ch))
4827 + .5;
4828
4829 if (top < 0)
4830 top = 0;
4831 if (top > top_range)
4832 top = top_range;
4833
4834 construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
4835 XSETINT (bufp->x, top);
4836 XSETINT (bufp->y, top_range);
4837 }
4838 else
4839 {
4840 ControlPartCode part_code;
4841 int unhilite_p = 0, part;
4842
4843 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
4844 unhilite_p = 1;
4845 else
4846 {
4847 part = control_part_code_to_scroll_bar_part (part_code);
4848
4849 switch (last_scroll_bar_part)
4850 {
4851 case scroll_bar_above_handle:
4852 case scroll_bar_below_handle:
4853 if (part != scroll_bar_above_handle
4854 && part != scroll_bar_below_handle)
4855 unhilite_p = 1;
4856 break;
4857
4858 case scroll_bar_up_arrow:
4859 case scroll_bar_down_arrow:
4860 if (part != scroll_bar_up_arrow
4861 && part != scroll_bar_down_arrow)
4862 unhilite_p = 1;
4863 break;
4864 }
4865 }
4866
4867 if (unhilite_p)
4868 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4869 else if (part != last_scroll_bar_part
4870 || scroll_bar_timer_event_posted_p)
4871 {
4872 construct_scroll_bar_click (bar, part, bufp);
4873 last_scroll_bar_part = part;
4874 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4875 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
4876 }
4877 }
4878 }
4879
4880 /* Set the thumb size and position of scroll bar BAR. We are currently
4881 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4882
4883 static void
4884 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4885 struct scroll_bar *bar;
4886 int portion, position, whole;
4887 {
4888 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4889 int value, viewsize, maximum;
4890
4891 if (XINT (bar->track_height) == 0)
4892 return;
4893
4894 if (whole == 0)
4895 value = 0, viewsize = 1, maximum = 0;
4896 else
4897 {
4898 value = position;
4899 viewsize = portion;
4900 maximum = max (0, whole - portion);
4901 }
4902
4903 BLOCK_INPUT;
4904
4905 if (GetControlViewSize (ch) != viewsize
4906 || GetControl32BitValue (ch) != value
4907 || GetControl32BitMaximum (ch) != maximum)
4908 {
4909 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4910 SetControlVisibility (ch, false, false);
4911
4912 SetControl32BitMaximum (ch, maximum);
4913 SetControl32BitValue (ch, value);
4914 SetControlViewSize (ch, viewsize);
4915
4916 SetControlVisibility (ch, true, true);
4917 }
4918
4919 UNBLOCK_INPUT;
4920 }
4921
4922 #endif /* USE_TOOLKIT_SCROLL_BARS */
4923
4924
4925 \f
4926 /************************************************************************
4927 Scroll bars, general
4928 ************************************************************************/
4929
4930 /* Create a scroll bar and return the scroll bar vector for it. W is
4931 the Emacs window on which to create the scroll bar. TOP, LEFT,
4932 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4933 scroll bar. */
4934
4935 static struct scroll_bar *
4936 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4937 struct window *w;
4938 int top, left, width, height, disp_top, disp_height;
4939 {
4940 struct frame *f = XFRAME (w->frame);
4941 struct scroll_bar *bar
4942 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4943 Rect r;
4944 ControlHandle ch;
4945
4946 BLOCK_INPUT;
4947
4948 r.left = left;
4949 r.top = disp_top;
4950 r.right = left + width;
4951 r.bottom = disp_top + disp_height;
4952
4953 #if USE_CG_DRAWING
4954 mac_prepare_for_quickdraw (f);
4955 #endif
4956 #if TARGET_API_MAC_CARBON
4957 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
4958 #if USE_TOOLKIT_SCROLL_BARS
4959 false,
4960 #else
4961 width < disp_height,
4962 #endif
4963 0, 0, 0, kControlScrollBarProc, (long) bar);
4964 #else
4965 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
4966 0, 0, 0, scrollBarProc, (long) bar);
4967 #endif
4968 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4969
4970 XSETWINDOW (bar->window, w);
4971 XSETINT (bar->top, top);
4972 XSETINT (bar->left, left);
4973 XSETINT (bar->width, width);
4974 XSETINT (bar->height, height);
4975 XSETINT (bar->start, 0);
4976 XSETINT (bar->end, 0);
4977 bar->dragging = Qnil;
4978 #ifdef USE_TOOLKIT_SCROLL_BARS
4979 bar->track_top = Qnil;
4980 bar->track_height = Qnil;
4981 #endif
4982
4983 /* Add bar to its frame's list of scroll bars. */
4984 bar->next = FRAME_SCROLL_BARS (f);
4985 bar->prev = Qnil;
4986 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4987 if (!NILP (bar->next))
4988 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4989
4990 UNBLOCK_INPUT;
4991 return bar;
4992 }
4993
4994
4995 /* Draw BAR's handle in the proper position.
4996
4997 If the handle is already drawn from START to END, don't bother
4998 redrawing it, unless REBUILD is non-zero; in that case, always
4999 redraw it. (REBUILD is handy for drawing the handle after expose
5000 events.)
5001
5002 Normally, we want to constrain the start and end of the handle to
5003 fit inside its rectangle, but if the user is dragging the scroll
5004 bar handle, we want to let them drag it down all the way, so that
5005 the bar's top is as far down as it goes; otherwise, there's no way
5006 to move to the very end of the buffer. */
5007
5008 #ifndef USE_TOOLKIT_SCROLL_BARS
5009
5010 static void
5011 x_scroll_bar_set_handle (bar, start, end, rebuild)
5012 struct scroll_bar *bar;
5013 int start, end;
5014 int rebuild;
5015 {
5016 int dragging = ! NILP (bar->dragging);
5017 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5018 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5019 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5020 int length = end - start;
5021
5022 /* If the display is already accurate, do nothing. */
5023 if (! rebuild
5024 && start == XINT (bar->start)
5025 && end == XINT (bar->end))
5026 return;
5027
5028 BLOCK_INPUT;
5029
5030 /* Make sure the values are reasonable, and try to preserve the
5031 distance between start and end. */
5032 if (start < 0)
5033 start = 0;
5034 else if (start > top_range)
5035 start = top_range;
5036 end = start + length;
5037
5038 if (end < start)
5039 end = start;
5040 else if (end > top_range && ! dragging)
5041 end = top_range;
5042
5043 /* Store the adjusted setting in the scroll bar. */
5044 XSETINT (bar->start, start);
5045 XSETINT (bar->end, end);
5046
5047 /* Clip the end position, just for display. */
5048 if (end > top_range)
5049 end = top_range;
5050
5051 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5052 top positions, to make sure the handle is always at least that
5053 many pixels tall. */
5054 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
5055
5056 SetControlMinimum (ch, 0);
5057 /* Don't inadvertently activate deactivated scroll bars */
5058 if (GetControlMaximum (ch) != -1)
5059 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
5060 - (end - start));
5061 SetControlValue (ch, start);
5062 #if TARGET_API_MAC_CARBON
5063 SetControlViewSize (ch, end - start);
5064 #endif
5065
5066 UNBLOCK_INPUT;
5067 }
5068
5069 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5070
5071 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5072 nil. */
5073
5074 static void
5075 x_scroll_bar_remove (bar)
5076 struct scroll_bar *bar;
5077 {
5078 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5079
5080 BLOCK_INPUT;
5081
5082 #if USE_CG_DRAWING
5083 mac_prepare_for_quickdraw (f);
5084 #endif
5085 /* Destroy the Mac scroll bar control */
5086 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
5087
5088 /* Disassociate this scroll bar from its window. */
5089 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5090
5091 UNBLOCK_INPUT;
5092 }
5093
5094
5095 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5096 that we are displaying PORTION characters out of a total of WHOLE
5097 characters, starting at POSITION. If WINDOW has no scroll bar,
5098 create one. */
5099
5100 static void
5101 XTset_vertical_scroll_bar (w, portion, whole, position)
5102 struct window *w;
5103 int portion, whole, position;
5104 {
5105 struct frame *f = XFRAME (w->frame);
5106 struct scroll_bar *bar;
5107 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
5108 int window_y, window_height;
5109
5110 /* Get window dimensions. */
5111 window_box (w, -1, 0, &window_y, 0, &window_height);
5112 top = window_y;
5113 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5114 height = window_height;
5115
5116 /* Compute the left edge of the scroll bar area. */
5117 left = WINDOW_SCROLL_BAR_AREA_X (w);
5118
5119 /* Compute the width of the scroll bar which might be less than
5120 the width of the area reserved for the scroll bar. */
5121 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5122 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5123 else
5124 sb_width = width;
5125
5126 /* Compute the left edge of the scroll bar. */
5127 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5128 sb_left = left;
5129 else
5130 sb_left = left + width - sb_width;
5131
5132 /* Adjustments according to Inside Macintosh to make it look nice */
5133 disp_top = top;
5134 disp_height = height;
5135 #ifdef MAC_OS8
5136 if (disp_top == 0)
5137 {
5138 disp_top = -1;
5139 disp_height++;
5140 }
5141 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
5142 {
5143 disp_top++;
5144 disp_height--;
5145 }
5146
5147 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
5148 sb_left++;
5149 #endif
5150
5151 /* Does the scroll bar exist yet? */
5152 if (NILP (w->vertical_scroll_bar))
5153 {
5154 BLOCK_INPUT;
5155 mac_clear_area (f, left, top, width, height);
5156 UNBLOCK_INPUT;
5157 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
5158 disp_height);
5159 XSETVECTOR (w->vertical_scroll_bar, bar);
5160 }
5161 else
5162 {
5163 /* It may just need to be moved and resized. */
5164 ControlHandle ch;
5165
5166 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5167 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5168
5169 BLOCK_INPUT;
5170
5171 /* If already correctly positioned, do nothing. */
5172 if (!(XINT (bar->left) == sb_left
5173 && XINT (bar->top) == top
5174 && XINT (bar->width) == sb_width
5175 && XINT (bar->height) == height))
5176 {
5177 /* Since toolkit scroll bars are smaller than the space reserved
5178 for them on the frame, we have to clear "under" them. */
5179 mac_clear_area (f, left, top, width, height);
5180
5181 #if USE_CG_DRAWING
5182 mac_prepare_for_quickdraw (f);
5183 #endif
5184 HideControl (ch);
5185 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
5186 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5187 disp_height);
5188 #ifndef USE_TOOLKIT_SCROLL_BARS
5189 if (sb_width < disp_height)
5190 ShowControl (ch);
5191 #endif
5192
5193 /* Remember new settings. */
5194 XSETINT (bar->left, sb_left);
5195 XSETINT (bar->top, top);
5196 XSETINT (bar->width, sb_width);
5197 XSETINT (bar->height, height);
5198 #ifdef USE_TOOLKIT_SCROLL_BARS
5199 bar->track_top = Qnil;
5200 bar->track_height = Qnil;
5201 #endif
5202 }
5203
5204 UNBLOCK_INPUT;
5205 }
5206
5207 #ifdef USE_TOOLKIT_SCROLL_BARS
5208 if (NILP (bar->track_top))
5209 {
5210 if (sb_width >= disp_height)
5211 {
5212 XSETINT (bar->track_top, 0);
5213 XSETINT (bar->track_height, 0);
5214 }
5215 else
5216 {
5217 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5218 Rect r0, r1;
5219
5220 BLOCK_INPUT;
5221
5222 SetControl32BitMinimum (ch, 0);
5223 SetControl32BitMaximum (ch, 1);
5224 SetControlViewSize (ch, 1);
5225
5226 /* Move the scroll bar thumb to the top. */
5227 SetControl32BitValue (ch, 0);
5228 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
5229
5230 /* Move the scroll bar thumb to the bottom. */
5231 SetControl32BitValue (ch, 1);
5232 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
5233
5234 UnionRect (&r0, &r1, &r0);
5235 XSETINT (bar->track_top, r0.top);
5236 XSETINT (bar->track_height, r0.bottom - r0.top);
5237
5238 /* Don't show the scroll bar if its height is not enough to
5239 display the scroll bar thumb. */
5240 if (r0.bottom - r0.top > 0)
5241 ShowControl (ch);
5242
5243 UNBLOCK_INPUT;
5244 }
5245 }
5246
5247 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5248 #else /* not USE_TOOLKIT_SCROLL_BARS */
5249 /* Set the scroll bar's current state, unless we're currently being
5250 dragged. */
5251 if (NILP (bar->dragging))
5252 {
5253 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5254
5255 if (whole == 0)
5256 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5257 else
5258 {
5259 int start = ((double) position * top_range) / whole;
5260 int end = ((double) (position + portion) * top_range) / whole;
5261 x_scroll_bar_set_handle (bar, start, end, 0);
5262 }
5263 }
5264 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5265 }
5266
5267
5268 /* The following three hooks are used when we're doing a thorough
5269 redisplay of the frame. We don't explicitly know which scroll bars
5270 are going to be deleted, because keeping track of when windows go
5271 away is a real pain - "Can you say set-window-configuration, boys
5272 and girls?" Instead, we just assert at the beginning of redisplay
5273 that *all* scroll bars are to be removed, and then save a scroll bar
5274 from the fiery pit when we actually redisplay its window. */
5275
5276 /* Arrange for all scroll bars on FRAME to be removed at the next call
5277 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5278 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5279
5280 static void
5281 XTcondemn_scroll_bars (frame)
5282 FRAME_PTR frame;
5283 {
5284 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5285 while (! NILP (FRAME_SCROLL_BARS (frame)))
5286 {
5287 Lisp_Object bar;
5288 bar = FRAME_SCROLL_BARS (frame);
5289 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5290 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5291 XSCROLL_BAR (bar)->prev = Qnil;
5292 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5293 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5294 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5295 }
5296 }
5297
5298
5299 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5300 Note that WINDOW isn't necessarily condemned at all. */
5301
5302 static void
5303 XTredeem_scroll_bar (window)
5304 struct window *window;
5305 {
5306 struct scroll_bar *bar;
5307 struct frame *f;
5308
5309 /* We can't redeem this window's scroll bar if it doesn't have one. */
5310 if (NILP (window->vertical_scroll_bar))
5311 abort ();
5312
5313 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5314
5315 /* Unlink it from the condemned list. */
5316 f = XFRAME (WINDOW_FRAME (window));
5317 if (NILP (bar->prev))
5318 {
5319 /* If the prev pointer is nil, it must be the first in one of
5320 the lists. */
5321 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5322 /* It's not condemned. Everything's fine. */
5323 return;
5324 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5325 window->vertical_scroll_bar))
5326 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5327 else
5328 /* If its prev pointer is nil, it must be at the front of
5329 one or the other! */
5330 abort ();
5331 }
5332 else
5333 XSCROLL_BAR (bar->prev)->next = bar->next;
5334
5335 if (! NILP (bar->next))
5336 XSCROLL_BAR (bar->next)->prev = bar->prev;
5337
5338 bar->next = FRAME_SCROLL_BARS (f);
5339 bar->prev = Qnil;
5340 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5341 if (! NILP (bar->next))
5342 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5343 }
5344
5345 /* Remove all scroll bars on FRAME that haven't been saved since the
5346 last call to `*condemn_scroll_bars_hook'. */
5347
5348 static void
5349 XTjudge_scroll_bars (f)
5350 FRAME_PTR f;
5351 {
5352 Lisp_Object bar, next;
5353
5354 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5355
5356 /* Clear out the condemned list now so we won't try to process any
5357 more events on the hapless scroll bars. */
5358 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5359
5360 for (; ! NILP (bar); bar = next)
5361 {
5362 struct scroll_bar *b = XSCROLL_BAR (bar);
5363
5364 x_scroll_bar_remove (b);
5365
5366 next = b->next;
5367 b->next = b->prev = Qnil;
5368 }
5369
5370 /* Now there should be no references to the condemned scroll bars,
5371 and they should get garbage-collected. */
5372 }
5373
5374
5375 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5376 is set to something other than NO_EVENT, it is enqueued.
5377
5378 This may be called from a signal handler, so we have to ignore GC
5379 mark bits. */
5380
5381 static void
5382 x_scroll_bar_handle_click (bar, part_code, er, bufp)
5383 struct scroll_bar *bar;
5384 ControlPartCode part_code;
5385 const EventRecord *er;
5386 struct input_event *bufp;
5387 {
5388 int win_y, top_range;
5389
5390 if (! GC_WINDOWP (bar->window))
5391 abort ();
5392
5393 bufp->kind = SCROLL_BAR_CLICK_EVENT;
5394 bufp->frame_or_window = bar->window;
5395 bufp->arg = Qnil;
5396
5397 bar->dragging = Qnil;
5398
5399 switch (part_code)
5400 {
5401 case kControlUpButtonPart:
5402 bufp->part = scroll_bar_up_arrow;
5403 break;
5404 case kControlDownButtonPart:
5405 bufp->part = scroll_bar_down_arrow;
5406 break;
5407 case kControlPageUpPart:
5408 bufp->part = scroll_bar_above_handle;
5409 break;
5410 case kControlPageDownPart:
5411 bufp->part = scroll_bar_below_handle;
5412 break;
5413 #if TARGET_API_MAC_CARBON
5414 default:
5415 #else
5416 case kControlIndicatorPart:
5417 #endif
5418 if (er->what == mouseDown)
5419 bar->dragging = make_number (0);
5420 XSETVECTOR (last_mouse_scroll_bar, bar);
5421 bufp->part = scroll_bar_handle;
5422 break;
5423 }
5424
5425 win_y = XINT (bufp->y) - XINT (bar->top);
5426 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
5427
5428 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5429
5430 win_y -= 24;
5431
5432 if (! NILP (bar->dragging))
5433 win_y -= XINT (bar->dragging);
5434
5435 if (win_y < 0)
5436 win_y = 0;
5437 if (win_y > top_range)
5438 win_y = top_range;
5439
5440 XSETINT (bufp->x, win_y);
5441 XSETINT (bufp->y, top_range);
5442 }
5443
5444 #ifndef USE_TOOLKIT_SCROLL_BARS
5445
5446 /* Handle some mouse motion while someone is dragging the scroll bar.
5447
5448 This may be called from a signal handler, so we have to ignore GC
5449 mark bits. */
5450
5451 static void
5452 x_scroll_bar_note_movement (bar, y_pos, t)
5453 struct scroll_bar *bar;
5454 int y_pos;
5455 Time t;
5456 {
5457 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5458
5459 last_mouse_movement_time = t;
5460
5461 f->mouse_moved = 1;
5462 XSETVECTOR (last_mouse_scroll_bar, bar);
5463
5464 /* If we're dragging the bar, display it. */
5465 if (! GC_NILP (bar->dragging))
5466 {
5467 /* Where should the handle be now? */
5468 int new_start = y_pos - 24;
5469
5470 if (new_start != XINT (bar->start))
5471 {
5472 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
5473
5474 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5475 }
5476 }
5477 }
5478
5479 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5480
5481 /* Return information to the user about the current position of the mouse
5482 on the scroll bar. */
5483
5484 static void
5485 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
5486 FRAME_PTR *fp;
5487 Lisp_Object *bar_window;
5488 enum scroll_bar_part *part;
5489 Lisp_Object *x, *y;
5490 unsigned long *time;
5491 {
5492 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5493 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5494 #if TARGET_API_MAC_CARBON
5495 WindowPtr wp = GetControlOwner (ch);
5496 #else
5497 WindowPtr wp = (*ch)->contrlOwner;
5498 #endif
5499 Point mouse_pos;
5500 struct frame *f = mac_window_to_frame (wp);
5501 int win_y, top_range;
5502
5503 SetPortWindowPort (wp);
5504
5505 GetMouse (&mouse_pos);
5506
5507 win_y = mouse_pos.v - XINT (bar->top);
5508 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5509
5510 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5511
5512 win_y -= 24;
5513
5514 if (! NILP (bar->dragging))
5515 win_y -= XINT (bar->dragging);
5516
5517 if (win_y < 0)
5518 win_y = 0;
5519 if (win_y > top_range)
5520 win_y = top_range;
5521
5522 *fp = f;
5523 *bar_window = bar->window;
5524
5525 if (! NILP (bar->dragging))
5526 *part = scroll_bar_handle;
5527 else if (win_y < XINT (bar->start))
5528 *part = scroll_bar_above_handle;
5529 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5530 *part = scroll_bar_handle;
5531 else
5532 *part = scroll_bar_below_handle;
5533
5534 XSETINT (*x, win_y);
5535 XSETINT (*y, top_range);
5536
5537 f->mouse_moved = 0;
5538 last_mouse_scroll_bar = Qnil;
5539
5540 *time = last_mouse_movement_time;
5541 }
5542
5543
5544 /* The screen has been cleared so we may have changed foreground or
5545 background colors, and the scroll bars may need to be redrawn.
5546 Clear out the scroll bars, and ask for expose events, so we can
5547 redraw them. */
5548
5549 void
5550 x_scroll_bar_clear (f)
5551 FRAME_PTR f;
5552 {
5553 XTcondemn_scroll_bars (f);
5554 XTjudge_scroll_bars (f);
5555 }
5556
5557 \f
5558 /***********************************************************************
5559 Text Cursor
5560 ***********************************************************************/
5561
5562 /* Set clipping for output in glyph row ROW. W is the window in which
5563 we operate. GC is the graphics context to set clipping in.
5564
5565 ROW may be a text row or, e.g., a mode line. Text rows must be
5566 clipped to the interior of the window dedicated to text display,
5567 mode lines must be clipped to the whole window. */
5568
5569 static void
5570 x_clip_to_row (w, row, area, gc)
5571 struct window *w;
5572 struct glyph_row *row;
5573 int area;
5574 GC gc;
5575 {
5576 struct frame *f = XFRAME (WINDOW_FRAME (w));
5577 Rect clip_rect;
5578 int window_x, window_y, window_width;
5579
5580 window_box (w, area, &window_x, &window_y, &window_width, 0);
5581
5582 clip_rect.left = window_x;
5583 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5584 clip_rect.top = max (clip_rect.top, window_y);
5585 clip_rect.right = clip_rect.left + window_width;
5586 clip_rect.bottom = clip_rect.top + row->visible_height;
5587
5588 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
5589 }
5590
5591
5592 /* Draw a hollow box cursor on window W in glyph row ROW. */
5593
5594 static void
5595 x_draw_hollow_cursor (w, row)
5596 struct window *w;
5597 struct glyph_row *row;
5598 {
5599 struct frame *f = XFRAME (WINDOW_FRAME (w));
5600 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5601 Display *dpy = FRAME_MAC_DISPLAY (f);
5602 int x, y, wd, h;
5603 XGCValues xgcv;
5604 struct glyph *cursor_glyph;
5605 GC gc;
5606
5607 /* Get the glyph the cursor is on. If we can't tell because
5608 the current matrix is invalid or such, give up. */
5609 cursor_glyph = get_phys_cursor_glyph (w);
5610 if (cursor_glyph == NULL)
5611 return;
5612
5613 /* Compute frame-relative coordinates for phys cursor. */
5614 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
5615 wd = w->phys_cursor_width;
5616
5617 /* The foreground of cursor_gc is typically the same as the normal
5618 background color, which can cause the cursor box to be invisible. */
5619 xgcv.foreground = f->output_data.mac->cursor_pixel;
5620 if (dpyinfo->scratch_cursor_gc)
5621 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5622 else
5623 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5624 GCForeground, &xgcv);
5625 gc = dpyinfo->scratch_cursor_gc;
5626
5627 /* Set clipping, draw the rectangle, and reset clipping again. */
5628 x_clip_to_row (w, row, TEXT_AREA, gc);
5629 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
5630 mac_reset_clip_rectangles (dpy, gc);
5631 }
5632
5633
5634 /* Draw a bar cursor on window W in glyph row ROW.
5635
5636 Implementation note: One would like to draw a bar cursor with an
5637 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5638 Unfortunately, I didn't find a font yet that has this property set.
5639 --gerd. */
5640
5641 static void
5642 x_draw_bar_cursor (w, row, width, kind)
5643 struct window *w;
5644 struct glyph_row *row;
5645 int width;
5646 enum text_cursor_kinds kind;
5647 {
5648 struct frame *f = XFRAME (w->frame);
5649 struct glyph *cursor_glyph;
5650
5651 /* If cursor is out of bounds, don't draw garbage. This can happen
5652 in mini-buffer windows when switching between echo area glyphs
5653 and mini-buffer. */
5654 cursor_glyph = get_phys_cursor_glyph (w);
5655 if (cursor_glyph == NULL)
5656 return;
5657
5658 /* If on an image, draw like a normal cursor. That's usually better
5659 visible than drawing a bar, esp. if the image is large so that
5660 the bar might not be in the window. */
5661 if (cursor_glyph->type == IMAGE_GLYPH)
5662 {
5663 struct glyph_row *row;
5664 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5665 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5666 }
5667 else
5668 {
5669 Display *dpy = FRAME_MAC_DISPLAY (f);
5670 Window window = FRAME_MAC_WINDOW (f);
5671 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5672 unsigned long mask = GCForeground | GCBackground;
5673 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5674 XGCValues xgcv;
5675
5676 /* If the glyph's background equals the color we normally draw
5677 the bar cursor in, the bar cursor in its normal color is
5678 invisible. Use the glyph's foreground color instead in this
5679 case, on the assumption that the glyph's colors are chosen so
5680 that the glyph is legible. */
5681 if (face->background == f->output_data.mac->cursor_pixel)
5682 xgcv.background = xgcv.foreground = face->foreground;
5683 else
5684 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5685
5686 if (gc)
5687 XChangeGC (dpy, gc, mask, &xgcv);
5688 else
5689 {
5690 gc = XCreateGC (dpy, window, mask, &xgcv);
5691 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5692 }
5693
5694 if (width < 0)
5695 width = FRAME_CURSOR_WIDTH (f);
5696 width = min (cursor_glyph->pixel_width, width);
5697
5698 w->phys_cursor_width = width;
5699 x_clip_to_row (w, row, TEXT_AREA, gc);
5700
5701 if (kind == BAR_CURSOR)
5702 mac_fill_rectangle (f, gc,
5703 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5704 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5705 width, row->height);
5706 else
5707 mac_fill_rectangle (f, gc,
5708 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5709 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5710 row->height - width),
5711 cursor_glyph->pixel_width,
5712 width);
5713
5714 mac_reset_clip_rectangles (dpy, gc);
5715 }
5716 }
5717
5718
5719 /* RIF: Define cursor CURSOR on frame F. */
5720
5721 static void
5722 mac_define_frame_cursor (f, cursor)
5723 struct frame *f;
5724 Cursor cursor;
5725 {
5726 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5727
5728 if (dpyinfo->x_focus_frame == f)
5729 SetThemeCursor (cursor);
5730 }
5731
5732
5733 /* RIF: Clear area on frame F. */
5734
5735 static void
5736 mac_clear_frame_area (f, x, y, width, height)
5737 struct frame *f;
5738 int x, y, width, height;
5739 {
5740 mac_clear_area (f, x, y, width, height);
5741 }
5742
5743
5744 /* RIF: Draw cursor on window W. */
5745
5746 static void
5747 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5748 struct window *w;
5749 struct glyph_row *glyph_row;
5750 int x, y;
5751 int cursor_type, cursor_width;
5752 int on_p, active_p;
5753 {
5754 if (on_p)
5755 {
5756 w->phys_cursor_type = cursor_type;
5757 w->phys_cursor_on_p = 1;
5758
5759 if (glyph_row->exact_window_width_line_p
5760 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5761 {
5762 glyph_row->cursor_in_fringe_p = 1;
5763 draw_fringe_bitmap (w, glyph_row, 0);
5764 }
5765 else
5766 switch (cursor_type)
5767 {
5768 case HOLLOW_BOX_CURSOR:
5769 x_draw_hollow_cursor (w, glyph_row);
5770 break;
5771
5772 case FILLED_BOX_CURSOR:
5773 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5774 break;
5775
5776 case BAR_CURSOR:
5777 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5778 break;
5779
5780 case HBAR_CURSOR:
5781 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5782 break;
5783
5784 case NO_CURSOR:
5785 w->phys_cursor_width = 0;
5786 break;
5787
5788 default:
5789 abort ();
5790 }
5791 }
5792 }
5793
5794 \f
5795 /* Icons. */
5796
5797 #if 0 /* MAC_TODO: no icon support yet. */
5798 int
5799 x_bitmap_icon (f, icon)
5800 struct frame *f;
5801 Lisp_Object icon;
5802 {
5803 HANDLE hicon;
5804
5805 if (FRAME_W32_WINDOW (f) == 0)
5806 return 1;
5807
5808 if (NILP (icon))
5809 hicon = LoadIcon (hinst, EMACS_CLASS);
5810 else if (STRINGP (icon))
5811 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5812 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5813 else if (SYMBOLP (icon))
5814 {
5815 LPCTSTR name;
5816
5817 if (EQ (icon, intern ("application")))
5818 name = (LPCTSTR) IDI_APPLICATION;
5819 else if (EQ (icon, intern ("hand")))
5820 name = (LPCTSTR) IDI_HAND;
5821 else if (EQ (icon, intern ("question")))
5822 name = (LPCTSTR) IDI_QUESTION;
5823 else if (EQ (icon, intern ("exclamation")))
5824 name = (LPCTSTR) IDI_EXCLAMATION;
5825 else if (EQ (icon, intern ("asterisk")))
5826 name = (LPCTSTR) IDI_ASTERISK;
5827 else if (EQ (icon, intern ("winlogo")))
5828 name = (LPCTSTR) IDI_WINLOGO;
5829 else
5830 return 1;
5831
5832 hicon = LoadIcon (NULL, name);
5833 }
5834 else
5835 return 1;
5836
5837 if (hicon == NULL)
5838 return 1;
5839
5840 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5841 (LPARAM) hicon);
5842
5843 return 0;
5844 }
5845 #endif /* MAC_TODO */
5846 \f
5847 /************************************************************************
5848 Handling X errors
5849 ************************************************************************/
5850
5851 /* Display Error Handling functions not used on W32. Listing them here
5852 helps diff stay in step when comparing w32term.c with xterm.c.
5853
5854 x_error_catcher (display, error)
5855 x_catch_errors (dpy)
5856 x_catch_errors_unwind (old_val)
5857 x_check_errors (dpy, format)
5858 x_had_errors_p (dpy)
5859 x_clear_errors (dpy)
5860 x_uncatch_errors (dpy, count)
5861 x_trace_wire ()
5862 x_connection_signal (signalnum)
5863 x_connection_closed (dpy, error_message)
5864 x_error_quitter (display, error)
5865 x_error_handler (display, error)
5866 x_io_error_quitter (display)
5867
5868 */
5869
5870 \f
5871 /* Changing the font of the frame. */
5872
5873 /* Give frame F the font named FONTNAME as its default font, and
5874 return the full name of that font. FONTNAME may be a wildcard
5875 pattern; in that case, we choose some font that fits the pattern.
5876 The return value shows which font we chose. */
5877
5878 Lisp_Object
5879 x_new_font (f, fontname)
5880 struct frame *f;
5881 register char *fontname;
5882 {
5883 struct font_info *fontp
5884 = FS_LOAD_FONT (f, 0, fontname, -1);
5885
5886 if (!fontp)
5887 return Qnil;
5888
5889 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5890 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5891 FRAME_FONTSET (f) = -1;
5892
5893 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5894 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5895 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5896
5897 compute_fringe_widths (f, 1);
5898
5899 /* Compute the scroll bar width in character columns. */
5900 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5901 {
5902 int wid = FRAME_COLUMN_WIDTH (f);
5903 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5904 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5905 }
5906 else
5907 {
5908 int wid = FRAME_COLUMN_WIDTH (f);
5909 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5910 }
5911
5912 /* Now make the frame display the given font. */
5913 if (FRAME_MAC_WINDOW (f) != 0)
5914 {
5915 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5916 FRAME_FONT (f));
5917 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5918 FRAME_FONT (f));
5919 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5920 FRAME_FONT (f));
5921
5922 /* Don't change the size of a tip frame; there's no point in
5923 doing it because it's done in Fx_show_tip, and it leads to
5924 problems because the tip frame has no widget. */
5925 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5926 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5927 }
5928
5929 return build_string (fontp->full_name);
5930 }
5931
5932 /* Give frame F the fontset named FONTSETNAME as its default font, and
5933 return the full name of that fontset. FONTSETNAME may be a wildcard
5934 pattern; in that case, we choose some fontset that fits the pattern.
5935 The return value shows which fontset we chose. */
5936
5937 Lisp_Object
5938 x_new_fontset (f, fontsetname)
5939 struct frame *f;
5940 char *fontsetname;
5941 {
5942 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5943 Lisp_Object result;
5944
5945 if (fontset < 0)
5946 return Qnil;
5947
5948 if (FRAME_FONTSET (f) == fontset)
5949 /* This fontset is already set in frame F. There's nothing more
5950 to do. */
5951 return fontset_name (fontset);
5952
5953 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5954
5955 if (!STRINGP (result))
5956 /* Can't load ASCII font. */
5957 return Qnil;
5958
5959 /* Since x_new_font doesn't update any fontset information, do it now. */
5960 FRAME_FONTSET (f) = fontset;
5961
5962 return build_string (fontsetname);
5963 }
5964
5965 \f
5966 /***********************************************************************
5967 TODO: W32 Input Methods
5968 ***********************************************************************/
5969 /* Listing missing functions from xterm.c helps diff stay in step.
5970
5971 xim_destroy_callback (xim, client_data, call_data)
5972 xim_open_dpy (dpyinfo, resource_name)
5973 struct xim_inst_t
5974 xim_instantiate_callback (display, client_data, call_data)
5975 xim_initialize (dpyinfo, resource_name)
5976 xim_close_dpy (dpyinfo)
5977
5978 */
5979
5980 \f
5981 void
5982 mac_get_window_bounds (f, inner, outer)
5983 struct frame *f;
5984 Rect *inner, *outer;
5985 {
5986 #if TARGET_API_MAC_CARBON
5987 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5988 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5989 #else /* not TARGET_API_MAC_CARBON */
5990 RgnHandle region = NewRgn ();
5991
5992 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5993 *inner = (*region)->rgnBBox;
5994 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5995 *outer = (*region)->rgnBBox;
5996 DisposeRgn (region);
5997 #endif /* not TARGET_API_MAC_CARBON */
5998 }
5999
6000 static void
6001 mac_handle_origin_change (f)
6002 struct frame *f;
6003 {
6004 x_real_positions (f, &f->left_pos, &f->top_pos);
6005 }
6006
6007 static void
6008 mac_handle_size_change (f, pixelwidth, pixelheight)
6009 struct frame *f;
6010 int pixelwidth, pixelheight;
6011 {
6012 int cols, rows;
6013
6014 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
6015 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
6016
6017 if (cols != FRAME_COLS (f)
6018 || rows != FRAME_LINES (f)
6019 || pixelwidth != FRAME_PIXEL_WIDTH (f)
6020 || pixelheight != FRAME_PIXEL_HEIGHT (f))
6021 {
6022 /* We pass 1 for DELAY since we can't run Lisp code inside of
6023 a BLOCK_INPUT. */
6024 change_frame_size (f, rows, cols, 0, 1, 0);
6025 FRAME_PIXEL_WIDTH (f) = pixelwidth;
6026 FRAME_PIXEL_HEIGHT (f) = pixelheight;
6027 SET_FRAME_GARBAGED (f);
6028
6029 /* If cursor was outside the new size, mark it as off. */
6030 mark_window_cursors_off (XWINDOW (f->root_window));
6031
6032 /* Clear out any recollection of where the mouse highlighting
6033 was, since it might be in a place that's outside the new
6034 frame size. Actually checking whether it is outside is a
6035 pain in the neck, so don't try--just let the highlighting be
6036 done afresh with new size. */
6037 cancel_mouse_face (f);
6038
6039 #if TARGET_API_MAC_CARBON
6040 if (f->output_data.mac->hourglass_control)
6041 {
6042 #if USE_CG_DRAWING
6043 mac_prepare_for_quickdraw (f);
6044 #endif
6045 MoveControl (f->output_data.mac->hourglass_control,
6046 pixelwidth - HOURGLASS_WIDTH, 0);
6047 }
6048 #endif
6049 }
6050 }
6051
6052 \f
6053 /* Calculate the absolute position in frame F
6054 from its current recorded position values and gravity. */
6055
6056 void
6057 x_calc_absolute_position (f)
6058 struct frame *f;
6059 {
6060 int width_diff = 0, height_diff = 0;
6061 int flags = f->size_hint_flags;
6062 Rect inner, outer;
6063
6064 /* We have nothing to do if the current position
6065 is already for the top-left corner. */
6066 if (! ((flags & XNegative) || (flags & YNegative)))
6067 return;
6068
6069 /* Find the offsets of the outside upper-left corner of
6070 the inner window, with respect to the outer window. */
6071 mac_get_window_bounds (f, &inner, &outer);
6072
6073 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
6074 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
6075
6076 /* Treat negative positions as relative to the leftmost bottommost
6077 position that fits on the screen. */
6078 if (flags & XNegative)
6079 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
6080 - width_diff
6081 - FRAME_PIXEL_WIDTH (f)
6082 + f->left_pos);
6083
6084 if (flags & YNegative)
6085 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
6086 - height_diff
6087 - FRAME_PIXEL_HEIGHT (f)
6088 + f->top_pos);
6089
6090 /* The left_pos and top_pos
6091 are now relative to the top and left screen edges,
6092 so the flags should correspond. */
6093 f->size_hint_flags &= ~ (XNegative | YNegative);
6094 }
6095
6096 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6097 to really change the position, and 0 when calling from
6098 x_make_frame_visible (in that case, XOFF and YOFF are the current
6099 position values). It is -1 when calling from x_set_frame_parameters,
6100 which means, do adjust for borders but don't change the gravity. */
6101
6102 void
6103 x_set_offset (f, xoff, yoff, change_gravity)
6104 struct frame *f;
6105 register int xoff, yoff;
6106 int change_gravity;
6107 {
6108 if (change_gravity > 0)
6109 {
6110 f->top_pos = yoff;
6111 f->left_pos = xoff;
6112 f->size_hint_flags &= ~ (XNegative | YNegative);
6113 if (xoff < 0)
6114 f->size_hint_flags |= XNegative;
6115 if (yoff < 0)
6116 f->size_hint_flags |= YNegative;
6117 f->win_gravity = NorthWestGravity;
6118 }
6119 x_calc_absolute_position (f);
6120
6121 BLOCK_INPUT;
6122 x_wm_set_size_hint (f, (long) 0, 0);
6123
6124 #if TARGET_API_MAC_CARBON
6125 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
6126 /* If the title bar is completely outside the screen, adjust the
6127 position. */
6128 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
6129 kWindowConstrainMoveRegardlessOfFit
6130 | kWindowConstrainAllowPartial, NULL, NULL);
6131 #if USE_CARBON_EVENTS
6132 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
6133 #endif
6134 mac_handle_origin_change (f);
6135 #else
6136 {
6137 Rect inner, outer, screen_rect, dummy;
6138 RgnHandle region = NewRgn ();
6139
6140 mac_get_window_bounds (f, &inner, &outer);
6141 f->x_pixels_diff = inner.left - outer.left;
6142 f->y_pixels_diff = inner.top - outer.top;
6143 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6144 f->top_pos + f->y_pixels_diff, false);
6145
6146 /* If the title bar is completely outside the screen, adjust the
6147 position. The variable `outer' holds the title bar rectangle.
6148 The variable `inner' holds slightly smaller one than `outer',
6149 so that the calculation of overlapping may not become too
6150 strict. */
6151 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
6152 outer = (*region)->rgnBBox;
6153 DisposeRgn (region);
6154 inner = outer;
6155 InsetRect (&inner, 8, 8);
6156 screen_rect = qd.screenBits.bounds;
6157 screen_rect.top += GetMBarHeight ();
6158
6159 if (!SectRect (&inner, &screen_rect, &dummy))
6160 {
6161 if (inner.right <= screen_rect.left)
6162 f->left_pos = screen_rect.left;
6163 else if (inner.left >= screen_rect.right)
6164 f->left_pos = screen_rect.right - (outer.right - outer.left);
6165
6166 if (inner.bottom <= screen_rect.top)
6167 f->top_pos = screen_rect.top;
6168 else if (inner.top >= screen_rect.bottom)
6169 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
6170
6171 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6172 f->top_pos + f->y_pixels_diff, false);
6173 }
6174 }
6175 #endif
6176
6177 UNBLOCK_INPUT;
6178 }
6179
6180 /* Call this to change the size of frame F's x-window.
6181 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6182 for this size change and subsequent size changes.
6183 Otherwise we leave the window gravity unchanged. */
6184
6185 void
6186 x_set_window_size (f, change_gravity, cols, rows)
6187 struct frame *f;
6188 int change_gravity;
6189 int cols, rows;
6190 {
6191 int pixelwidth, pixelheight;
6192
6193 BLOCK_INPUT;
6194
6195 check_frame_size (f, &rows, &cols);
6196 f->scroll_bar_actual_width
6197 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
6198
6199 compute_fringe_widths (f, 0);
6200
6201 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
6202 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
6203
6204 f->win_gravity = NorthWestGravity;
6205 x_wm_set_size_hint (f, (long) 0, 0);
6206
6207 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
6208
6209 #if USE_CARBON_EVENTS
6210 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
6211 #endif
6212 mac_handle_size_change (f, pixelwidth, pixelheight);
6213
6214 UNBLOCK_INPUT;
6215 }
6216 \f
6217 /* Mouse warping. */
6218
6219 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
6220
6221 void
6222 x_set_mouse_position (f, x, y)
6223 struct frame *f;
6224 int x, y;
6225 {
6226 int pix_x, pix_y;
6227
6228 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
6229 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
6230
6231 if (pix_x < 0) pix_x = 0;
6232 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
6233
6234 if (pix_y < 0) pix_y = 0;
6235 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
6236
6237 x_set_mouse_pixel_position (f, pix_x, pix_y);
6238 }
6239
6240 void
6241 x_set_mouse_pixel_position (f, pix_x, pix_y)
6242 struct frame *f;
6243 int pix_x, pix_y;
6244 {
6245 #ifdef MAC_OSX
6246 Point p;
6247 CGPoint point;
6248
6249 BLOCK_INPUT;
6250 SetPortWindowPort (FRAME_MAC_WINDOW (f));
6251 p.h = pix_x;
6252 p.v = pix_y;
6253 LocalToGlobal (&p);
6254 point.x = p.h;
6255 point.y = p.v;
6256 CGWarpMouseCursorPosition (point);
6257 UNBLOCK_INPUT;
6258 #else
6259 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6260 BLOCK_INPUT;
6261
6262 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
6263 0, 0, 0, 0, pix_x, pix_y);
6264 UNBLOCK_INPUT;
6265 #endif
6266 #endif
6267 }
6268 \f
6269 /* focus shifting, raising and lowering. */
6270
6271 void
6272 x_focus_on_frame (f)
6273 struct frame *f;
6274 {
6275 #if 0 /* This proves to be unpleasant. */
6276 x_raise_frame (f);
6277 #endif
6278 #if 0
6279 /* I don't think that the ICCCM allows programs to do things like this
6280 without the interaction of the window manager. Whatever you end up
6281 doing with this code, do it to x_unfocus_frame too. */
6282 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6283 RevertToPointerRoot, CurrentTime);
6284 #endif /* ! 0 */
6285 }
6286
6287 void
6288 x_unfocus_frame (f)
6289 struct frame *f;
6290 {
6291 }
6292
6293 /* Raise frame F. */
6294
6295 void
6296 x_raise_frame (f)
6297 struct frame *f;
6298 {
6299 if (f->async_visible)
6300 {
6301 BLOCK_INPUT;
6302 BringToFront (FRAME_MAC_WINDOW (f));
6303 UNBLOCK_INPUT;
6304 }
6305 }
6306
6307 /* Lower frame F. */
6308
6309 void
6310 x_lower_frame (f)
6311 struct frame *f;
6312 {
6313 if (f->async_visible)
6314 {
6315 BLOCK_INPUT;
6316 SendBehind (FRAME_MAC_WINDOW (f), NULL);
6317 UNBLOCK_INPUT;
6318 }
6319 }
6320
6321 static void
6322 XTframe_raise_lower (f, raise_flag)
6323 FRAME_PTR f;
6324 int raise_flag;
6325 {
6326 if (raise_flag)
6327 x_raise_frame (f);
6328 else
6329 x_lower_frame (f);
6330 }
6331 \f
6332 /* Change of visibility. */
6333
6334 static void
6335 mac_handle_visibility_change (f)
6336 struct frame *f;
6337 {
6338 WindowPtr wp = FRAME_MAC_WINDOW (f);
6339 int visible = 0, iconified = 0;
6340 struct input_event buf;
6341
6342 if (IsWindowVisible (wp))
6343 {
6344 if (IsWindowCollapsed (wp))
6345 iconified = 1;
6346 else
6347 visible = 1;
6348 }
6349
6350 if (!f->async_visible && visible)
6351 {
6352 if (f->iconified)
6353 {
6354 /* wait_reading_process_output will notice this and update
6355 the frame's display structures. If we were made
6356 invisible, we should not set garbaged, because that stops
6357 redrawing on Update events. */
6358 SET_FRAME_GARBAGED (f);
6359
6360 EVENT_INIT (buf);
6361 buf.kind = DEICONIFY_EVENT;
6362 XSETFRAME (buf.frame_or_window, f);
6363 buf.arg = Qnil;
6364 kbd_buffer_store_event (&buf);
6365 }
6366 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
6367 /* Force a redisplay sooner or later to update the
6368 frame titles in case this is the second frame. */
6369 record_asynch_buffer_change ();
6370 }
6371 else if (f->async_visible && !visible)
6372 if (iconified)
6373 {
6374 EVENT_INIT (buf);
6375 buf.kind = ICONIFY_EVENT;
6376 XSETFRAME (buf.frame_or_window, f);
6377 buf.arg = Qnil;
6378 kbd_buffer_store_event (&buf);
6379 }
6380
6381 f->async_visible = visible;
6382 f->async_iconified = iconified;
6383 }
6384
6385 /* This tries to wait until the frame is really visible.
6386 However, if the window manager asks the user where to position
6387 the frame, this will return before the user finishes doing that.
6388 The frame will not actually be visible at that time,
6389 but it will become visible later when the window manager
6390 finishes with it. */
6391
6392 void
6393 x_make_frame_visible (f)
6394 struct frame *f;
6395 {
6396 BLOCK_INPUT;
6397
6398 if (! FRAME_VISIBLE_P (f))
6399 {
6400 /* We test FRAME_GARBAGED_P here to make sure we don't
6401 call x_set_offset a second time
6402 if we get to x_make_frame_visible a second time
6403 before the window gets really visible. */
6404 if (! FRAME_ICONIFIED_P (f)
6405 && ! f->output_data.mac->asked_for_visible)
6406 {
6407 #if TARGET_API_MAC_CARBON
6408 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
6409 {
6410 struct frame *sf = SELECTED_FRAME ();
6411 if (!FRAME_MAC_P (sf))
6412 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
6413 kWindowCenterOnMainScreen);
6414 else
6415 RepositionWindow (FRAME_MAC_WINDOW (f),
6416 FRAME_MAC_WINDOW (sf),
6417 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6418 kWindowCascadeStartAtParentWindowScreen
6419 #else
6420 kWindowCascadeOnParentWindowScreen
6421 #endif
6422 );
6423 #if USE_CARBON_EVENTS
6424 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
6425 #endif
6426 mac_handle_origin_change (f);
6427 }
6428 else
6429 #endif
6430 x_set_offset (f, f->left_pos, f->top_pos, 0);
6431 }
6432
6433 f->output_data.mac->asked_for_visible = 1;
6434
6435 CollapseWindow (FRAME_MAC_WINDOW (f), false);
6436 ShowWindow (FRAME_MAC_WINDOW (f));
6437 }
6438
6439 XFlush (FRAME_MAC_DISPLAY (f));
6440
6441 /* Synchronize to ensure Emacs knows the frame is visible
6442 before we do anything else. We do this loop with input not blocked
6443 so that incoming events are handled. */
6444 {
6445 Lisp_Object frame;
6446 int count;
6447
6448 /* This must come after we set COUNT. */
6449 UNBLOCK_INPUT;
6450
6451 XSETFRAME (frame, f);
6452
6453 /* Wait until the frame is visible. Process X events until a
6454 MapNotify event has been seen, or until we think we won't get a
6455 MapNotify at all.. */
6456 for (count = input_signal_count + 10;
6457 input_signal_count < count && !FRAME_VISIBLE_P (f);)
6458 {
6459 /* Force processing of queued events. */
6460 x_sync (f);
6461
6462 /* Machines that do polling rather than SIGIO have been
6463 observed to go into a busy-wait here. So we'll fake an
6464 alarm signal to let the handler know that there's something
6465 to be read. We used to raise a real alarm, but it seems
6466 that the handler isn't always enabled here. This is
6467 probably a bug. */
6468 if (input_polling_used ())
6469 {
6470 /* It could be confusing if a real alarm arrives while
6471 processing the fake one. Turn it off and let the
6472 handler reset it. */
6473 extern void poll_for_input_1 P_ ((void));
6474 int old_poll_suppress_count = poll_suppress_count;
6475 poll_suppress_count = 1;
6476 poll_for_input_1 ();
6477 poll_suppress_count = old_poll_suppress_count;
6478 }
6479
6480 /* See if a MapNotify event has been processed. */
6481 FRAME_SAMPLE_VISIBILITY (f);
6482 }
6483 }
6484 }
6485
6486 /* Change from mapped state to withdrawn state. */
6487
6488 /* Make the frame visible (mapped and not iconified). */
6489
6490 void
6491 x_make_frame_invisible (f)
6492 struct frame *f;
6493 {
6494 /* A deactivate event does not occur when the last visible frame is
6495 made invisible. So if we clear the highlight here, it will not
6496 be rehighlighted when it is made visible. */
6497 #if 0
6498 /* Don't keep the highlight on an invisible frame. */
6499 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6500 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6501 #endif
6502
6503 BLOCK_INPUT;
6504
6505 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6506 that the current position of the window is user-specified, rather than
6507 program-specified, so that when the window is mapped again, it will be
6508 placed at the same location, without forcing the user to position it
6509 by hand again (they have already done that once for this window.) */
6510 x_wm_set_size_hint (f, (long) 0, 1);
6511
6512 HideWindow (FRAME_MAC_WINDOW (f));
6513
6514 UNBLOCK_INPUT;
6515
6516 #if !USE_CARBON_EVENTS
6517 mac_handle_visibility_change (f);
6518 #endif
6519 }
6520
6521 /* Change window state from mapped to iconified. */
6522
6523 void
6524 x_iconify_frame (f)
6525 struct frame *f;
6526 {
6527 OSStatus err;
6528
6529 /* A deactivate event does not occur when the last visible frame is
6530 iconified. So if we clear the highlight here, it will not be
6531 rehighlighted when it is deiconified. */
6532 #if 0
6533 /* Don't keep the highlight on an invisible frame. */
6534 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6535 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6536 #endif
6537
6538 if (f->async_iconified)
6539 return;
6540
6541 BLOCK_INPUT;
6542
6543 FRAME_SAMPLE_VISIBILITY (f);
6544
6545 if (! FRAME_VISIBLE_P (f))
6546 ShowWindow (FRAME_MAC_WINDOW (f));
6547
6548 err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
6549
6550 UNBLOCK_INPUT;
6551
6552 if (err != noErr)
6553 error ("Can't notify window manager of iconification");
6554
6555 #if !USE_CARBON_EVENTS
6556 mac_handle_visibility_change (f);
6557 #endif
6558 }
6559
6560 \f
6561 /* Free X resources of frame F. */
6562
6563 void
6564 x_free_frame_resources (f)
6565 struct frame *f;
6566 {
6567 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6568 WindowPtr wp = FRAME_MAC_WINDOW (f);
6569
6570 BLOCK_INPUT;
6571
6572 if (wp != tip_window)
6573 remove_window_handler (wp);
6574
6575 #if USE_CG_DRAWING
6576 mac_prepare_for_quickdraw (f);
6577 #endif
6578 DisposeWindow (wp);
6579 if (wp == tip_window)
6580 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6581 closed' event. So we reset tip_window here. */
6582 tip_window = NULL;
6583
6584 free_frame_menubar (f);
6585
6586 if (FRAME_FACE_CACHE (f))
6587 free_frame_faces (f);
6588
6589 x_free_gcs (f);
6590
6591 if (FRAME_SIZE_HINTS (f))
6592 xfree (FRAME_SIZE_HINTS (f));
6593
6594 xfree (f->output_data.mac);
6595 f->output_data.mac = NULL;
6596
6597 if (f == dpyinfo->x_focus_frame)
6598 {
6599 dpyinfo->x_focus_frame = 0;
6600 #if USE_MAC_FONT_PANEL
6601 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
6602 #endif
6603 }
6604 if (f == dpyinfo->x_focus_event_frame)
6605 dpyinfo->x_focus_event_frame = 0;
6606 if (f == dpyinfo->x_highlight_frame)
6607 dpyinfo->x_highlight_frame = 0;
6608
6609 if (f == dpyinfo->mouse_face_mouse_frame)
6610 {
6611 dpyinfo->mouse_face_beg_row
6612 = dpyinfo->mouse_face_beg_col = -1;
6613 dpyinfo->mouse_face_end_row
6614 = dpyinfo->mouse_face_end_col = -1;
6615 dpyinfo->mouse_face_window = Qnil;
6616 dpyinfo->mouse_face_deferred_gc = 0;
6617 dpyinfo->mouse_face_mouse_frame = 0;
6618 }
6619
6620 UNBLOCK_INPUT;
6621 }
6622
6623
6624 /* Destroy the X window of frame F. */
6625
6626 void
6627 x_destroy_window (f)
6628 struct frame *f;
6629 {
6630 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6631
6632 x_free_frame_resources (f);
6633
6634 dpyinfo->reference_count--;
6635 }
6636
6637 \f
6638 /* Setting window manager hints. */
6639
6640 /* Set the normal size hints for the window manager, for frame F.
6641 FLAGS is the flags word to use--or 0 meaning preserve the flags
6642 that the window now has.
6643 If USER_POSITION is nonzero, we set the USPosition
6644 flag (this is useful when FLAGS is 0). */
6645 void
6646 x_wm_set_size_hint (f, flags, user_position)
6647 struct frame *f;
6648 long flags;
6649 int user_position;
6650 {
6651 int base_width, base_height, width_inc, height_inc;
6652 int min_rows = 0, min_cols = 0;
6653 XSizeHints *size_hints;
6654
6655 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6656 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6657 width_inc = FRAME_COLUMN_WIDTH (f);
6658 height_inc = FRAME_LINE_HEIGHT (f);
6659
6660 check_frame_size (f, &min_rows, &min_cols);
6661
6662 size_hints = FRAME_SIZE_HINTS (f);
6663 if (size_hints == NULL)
6664 {
6665 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6666 bzero (size_hints, sizeof (XSizeHints));
6667 }
6668
6669 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6670 size_hints->width_inc = width_inc;
6671 size_hints->height_inc = height_inc;
6672 size_hints->min_width = base_width + min_cols * width_inc;
6673 size_hints->min_height = base_height + min_rows * height_inc;
6674 size_hints->base_width = base_width;
6675 size_hints->base_height = base_height;
6676
6677 if (flags)
6678 size_hints->flags = flags;
6679 else if (user_position)
6680 {
6681 size_hints->flags &= ~ PPosition;
6682 size_hints->flags |= USPosition;
6683 }
6684 }
6685
6686 #if 0 /* MAC_TODO: hide application instead of iconify? */
6687 /* Used for IconicState or NormalState */
6688
6689 void
6690 x_wm_set_window_state (f, state)
6691 struct frame *f;
6692 int state;
6693 {
6694 #ifdef USE_X_TOOLKIT
6695 Arg al[1];
6696
6697 XtSetArg (al[0], XtNinitialState, state);
6698 XtSetValues (f->output_data.x->widget, al, 1);
6699 #else /* not USE_X_TOOLKIT */
6700 Window window = FRAME_X_WINDOW (f);
6701
6702 f->output_data.x->wm_hints.flags |= StateHint;
6703 f->output_data.x->wm_hints.initial_state = state;
6704
6705 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6706 #endif /* not USE_X_TOOLKIT */
6707 }
6708
6709 void
6710 x_wm_set_icon_pixmap (f, pixmap_id)
6711 struct frame *f;
6712 int pixmap_id;
6713 {
6714 Pixmap icon_pixmap;
6715
6716 #ifndef USE_X_TOOLKIT
6717 Window window = FRAME_X_WINDOW (f);
6718 #endif
6719
6720 if (pixmap_id > 0)
6721 {
6722 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6723 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6724 }
6725 else
6726 {
6727 /* It seems there is no way to turn off use of an icon pixmap.
6728 The following line does it, only if no icon has yet been created,
6729 for some window managers. But with mwm it crashes.
6730 Some people say it should clear the IconPixmapHint bit in this case,
6731 but that doesn't work, and the X consortium said it isn't the
6732 right thing at all. Since there is no way to win,
6733 best to explicitly give up. */
6734 #if 0
6735 f->output_data.x->wm_hints.icon_pixmap = None;
6736 #else
6737 return;
6738 #endif
6739 }
6740
6741 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6742
6743 {
6744 Arg al[1];
6745 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6746 XtSetValues (f->output_data.x->widget, al, 1);
6747 }
6748
6749 #else /* not USE_X_TOOLKIT */
6750
6751 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6752 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6753
6754 #endif /* not USE_X_TOOLKIT */
6755 }
6756
6757 #endif /* MAC_TODO */
6758
6759 void
6760 x_wm_set_icon_position (f, icon_x, icon_y)
6761 struct frame *f;
6762 int icon_x, icon_y;
6763 {
6764 #if 0 /* MAC_TODO: no icons on Mac */
6765 #ifdef USE_X_TOOLKIT
6766 Window window = XtWindow (f->output_data.x->widget);
6767 #else
6768 Window window = FRAME_X_WINDOW (f);
6769 #endif
6770
6771 f->output_data.x->wm_hints.flags |= IconPositionHint;
6772 f->output_data.x->wm_hints.icon_x = icon_x;
6773 f->output_data.x->wm_hints.icon_y = icon_y;
6774
6775 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6776 #endif /* MAC_TODO */
6777 }
6778
6779 \f
6780 /***********************************************************************
6781 XLFD Pattern Match
6782 ***********************************************************************/
6783
6784 /* An XLFD pattern is divided into blocks delimited by '*'. This
6785 structure holds information for each block. */
6786 struct xlfdpat_block
6787 {
6788 /* Length of the pattern string in this block. Non-zero except for
6789 the first and the last blocks. */
6790 int len;
6791
6792 /* Pattern string except the last character in this block. The last
6793 character is replaced with NUL in order to use it as a
6794 sentinel. */
6795 unsigned char *pattern;
6796
6797 /* Last character of the pattern string. Must not be '?'. */
6798 unsigned char last_char;
6799
6800 /* One of the tables for the Boyer-Moore string search. It
6801 specifies the number of positions to proceed for each character
6802 with which the match fails. */
6803 int skip[256];
6804
6805 /* The skip value for the last character in the above `skip' is
6806 assigned to `infinity' in order to simplify a loop condition.
6807 The original value is saved here. */
6808 int last_char_skip;
6809 };
6810
6811 struct xlfdpat
6812 {
6813 /* Normalized pattern string. "Normalized" means that capital
6814 letters are lowered, blocks are not empty except the first and
6815 the last ones, and trailing '?'s in a block that is not the last
6816 one are moved to the next one. The last character in each block
6817 is replaced with NUL. */
6818 unsigned char *buf;
6819
6820 /* Number of characters except '*'s and trailing '?'s in the
6821 normalized pattern string. */
6822 int nchars;
6823
6824 /* Number of trailing '?'s in the normalized pattern string. */
6825 int trailing_anychars;
6826
6827 /* Number of blocks and information for each block. The latter is
6828 NULL if the pattern is exact (no '*' or '?' in it). */
6829 int nblocks;
6830 struct xlfdpat_block *blocks;
6831 };
6832
6833 static void
6834 xlfdpat_destroy (pat)
6835 struct xlfdpat *pat;
6836 {
6837 if (pat)
6838 {
6839 if (pat->buf)
6840 {
6841 if (pat->blocks)
6842 xfree (pat->blocks);
6843 xfree (pat->buf);
6844 }
6845 xfree (pat);
6846 }
6847 }
6848
6849 static struct xlfdpat *
6850 xlfdpat_create (pattern)
6851 const char *pattern;
6852 {
6853 struct xlfdpat *pat;
6854 int nblocks, i, skip;
6855 unsigned char last_char, *p, *q, *anychar_head;
6856 const unsigned char *ptr;
6857 struct xlfdpat_block *blk;
6858
6859 pat = xmalloc (sizeof (struct xlfdpat));
6860 pat->buf = xmalloc (strlen (pattern) + 1);
6861
6862 /* Normalize the pattern string and store it to `pat->buf'. */
6863 nblocks = 0;
6864 anychar_head = NULL;
6865 q = pat->buf;
6866 last_char = '\0';
6867 for (ptr = pattern; *ptr; ptr++)
6868 {
6869 unsigned char c = *ptr;
6870
6871 if (c == '*')
6872 if (last_char == '*')
6873 /* ...a** -> ...a* */
6874 continue;
6875 else
6876 {
6877 if (last_char == '?')
6878 {
6879 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6880 /* ...*??* -> ...*?? */
6881 continue;
6882 else
6883 /* ...a??* -> ...a*?? */
6884 {
6885 *anychar_head++ = '*';
6886 c = '?';
6887 }
6888 }
6889 nblocks++;
6890 }
6891 else if (c == '?')
6892 {
6893 if (last_char != '?')
6894 anychar_head = q;
6895 }
6896 else
6897 /* On Mac OS X 10.3, tolower also converts non-ASCII
6898 characters for some locales. */
6899 if (isascii (c))
6900 c = tolower (c);
6901
6902 *q++ = last_char = c;
6903 }
6904 *q = '\0';
6905 nblocks++;
6906 pat->nblocks = nblocks;
6907 if (last_char != '?')
6908 pat->trailing_anychars = 0;
6909 else
6910 {
6911 pat->trailing_anychars = q - anychar_head;
6912 q = anychar_head;
6913 }
6914 pat->nchars = q - pat->buf - (nblocks - 1);
6915
6916 if (anychar_head == NULL && nblocks == 1)
6917 {
6918 /* The pattern is exact. */
6919 pat->blocks = NULL;
6920 return pat;
6921 }
6922
6923 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6924
6925 /* Divide the normalized pattern into blocks. */
6926 p = pat->buf;
6927 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6928 {
6929 blk->pattern = p;
6930 while (*p != '*')
6931 p++;
6932 blk->len = p - blk->pattern;
6933 p++;
6934 }
6935 blk->pattern = p;
6936 blk->len = q - blk->pattern;
6937
6938 /* Setup a table for the Boyer-Moore string search. */
6939 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6940 if (blk->len != 0)
6941 {
6942 blk->last_char = blk->pattern[blk->len - 1];
6943 blk->pattern[blk->len - 1] = '\0';
6944
6945 for (skip = 1; skip < blk->len; skip++)
6946 if (blk->pattern[blk->len - skip - 1] == '?')
6947 break;
6948
6949 for (i = 0; i < 256; i++)
6950 blk->skip[i] = skip;
6951
6952 p = blk->pattern + (blk->len - skip);
6953 while (--skip > 0)
6954 blk->skip[*p++] = skip;
6955
6956 blk->last_char_skip = blk->skip[blk->last_char];
6957 }
6958
6959 return pat;
6960 }
6961
6962 static INLINE int
6963 xlfdpat_exact_p (pat)
6964 struct xlfdpat *pat;
6965 {
6966 return pat->blocks == NULL;
6967 }
6968
6969 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6970 that the pattern in *BLK matches with its prefix. Return NULL
6971 there is no such strings. STRING must be lowered in advance. */
6972
6973 static const char *
6974 xlfdpat_block_match_1 (blk, string, start_max)
6975 struct xlfdpat_block *blk;
6976 const unsigned char *string;
6977 int start_max;
6978 {
6979 int start, infinity;
6980 unsigned char *p;
6981 const unsigned char *s;
6982
6983 xassert (blk->len > 0);
6984 xassert (start_max + blk->len <= strlen (string));
6985 xassert (blk->last_char != '?');
6986
6987 /* See the comments in the function `boyer_moore' (search.c) for the
6988 use of `infinity'. */
6989 infinity = start_max + blk->len + 1;
6990 blk->skip[blk->last_char] = infinity;
6991
6992 start = 0;
6993 do
6994 {
6995 /* Check the last character of the pattern. */
6996 s = string + blk->len - 1;
6997 do
6998 {
6999 start += blk->skip[*(s + start)];
7000 }
7001 while (start <= start_max);
7002
7003 if (start < infinity)
7004 /* Couldn't find the last character. */
7005 return NULL;
7006
7007 /* No less than `infinity' means we could find the last
7008 character at `s[start - infinity]'. */
7009 start -= infinity;
7010
7011 /* Check the remaining characters. We prefer making no-'?'
7012 cases faster because the use of '?' is really rare. */
7013 p = blk->pattern;
7014 s = string + start;
7015 do
7016 {
7017 while (*p++ == *s++)
7018 ;
7019 }
7020 while (*(p - 1) == '?');
7021
7022 if (*(p - 1) == '\0')
7023 /* Matched. */
7024 return string + start;
7025
7026 /* Didn't match. */
7027 start += blk->last_char_skip;
7028 }
7029 while (start <= start_max);
7030
7031 return NULL;
7032 }
7033
7034 #define xlfdpat_block_match(b, s, m) \
7035 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7036 : xlfdpat_block_match_1 (b, s, m))
7037
7038 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7039 matches with STRING. STRING must be lowered in advance. */
7040
7041 static int
7042 xlfdpat_match (pat, string)
7043 struct xlfdpat *pat;
7044 const unsigned char *string;
7045 {
7046 int str_len, nblocks, i, start_max;
7047 struct xlfdpat_block *blk;
7048 const unsigned char *s;
7049
7050 xassert (pat->nblocks > 0);
7051
7052 if (xlfdpat_exact_p (pat))
7053 return strcmp (pat->buf, string) == 0;
7054
7055 /* The number of the characters in the string must not be smaller
7056 than that in the pattern. */
7057 str_len = strlen (string);
7058 if (str_len < pat->nchars + pat->trailing_anychars)
7059 return 0;
7060
7061 /* Chop off the trailing '?'s. */
7062 str_len -= pat->trailing_anychars;
7063
7064 /* The last block. When it is non-empty, it must match at the end
7065 of the string. */
7066 nblocks = pat->nblocks;
7067 blk = pat->blocks + (nblocks - 1);
7068 if (nblocks == 1)
7069 /* The last block is also the first one. */
7070 return (str_len == blk->len
7071 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
7072 else if (blk->len != 0)
7073 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
7074 return 0;
7075
7076 /* The first block. When it is non-empty, it must match at the
7077 beginning of the string. */
7078 blk = pat->blocks;
7079 if (blk->len != 0)
7080 {
7081 s = xlfdpat_block_match (blk, string, 0);
7082 if (s == NULL)
7083 return 0;
7084 string = s + blk->len;
7085 }
7086
7087 /* The rest of the blocks. */
7088 start_max = str_len - pat->nchars;
7089 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
7090 {
7091 s = xlfdpat_block_match (blk, string, start_max);
7092 if (s == NULL)
7093 return 0;
7094 start_max -= s - string;
7095 string = s + blk->len;
7096 }
7097
7098 return 1;
7099 }
7100
7101 \f
7102 /***********************************************************************
7103 Fonts
7104 ***********************************************************************/
7105
7106 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7107
7108 struct font_info *
7109 x_get_font_info (f, font_idx)
7110 FRAME_PTR f;
7111 int font_idx;
7112 {
7113 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
7114 }
7115
7116 /* the global font name table */
7117 static char **font_name_table = NULL;
7118 static int font_name_table_size = 0;
7119 static int font_name_count = 0;
7120
7121 /* Alist linking font family names to Font Manager font family
7122 references (which can also be used as QuickDraw font IDs). We use
7123 an alist because hash tables are not ready when the terminal frame
7124 for Mac OS Classic is created. */
7125 static Lisp_Object fm_font_family_alist;
7126 #if USE_ATSUI
7127 /* Hash table linking font family names to ATSU font IDs. */
7128 static Lisp_Object atsu_font_id_hash;
7129 /* Alist linking Font Manager style to face attributes. */
7130 static Lisp_Object fm_style_face_attributes_alist;
7131 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
7132 #endif
7133
7134 /* Alist linking character set strings to Mac text encoding and Emacs
7135 coding system. */
7136 static Lisp_Object Vmac_charset_info_alist;
7137
7138 static Lisp_Object
7139 create_text_encoding_info_alist ()
7140 {
7141 Lisp_Object result = Qnil, rest;
7142
7143 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
7144 {
7145 Lisp_Object charset_info = XCAR (rest);
7146 Lisp_Object charset, coding_system, text_encoding;
7147 Lisp_Object existing_info;
7148
7149 if (!(CONSP (charset_info)
7150 && STRINGP (charset = XCAR (charset_info))
7151 && CONSP (XCDR (charset_info))
7152 && INTEGERP (text_encoding = XCAR (XCDR (charset_info)))
7153 && CONSP (XCDR (XCDR (charset_info)))
7154 && SYMBOLP (coding_system = XCAR (XCDR (XCDR (charset_info))))))
7155 continue;
7156
7157 existing_info = assq_no_quit (text_encoding, result);
7158 if (NILP (existing_info))
7159 result = Fcons (list3 (text_encoding, coding_system, charset),
7160 result);
7161 else
7162 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
7163 XSETCDR (XCDR (existing_info),
7164 Fcons (charset, XCDR (XCDR (existing_info))));
7165 }
7166
7167 return result;
7168 }
7169
7170
7171 static void
7172 decode_mac_font_name (name, size, coding_system)
7173 char *name;
7174 int size;
7175 Lisp_Object coding_system;
7176 {
7177 struct coding_system coding;
7178 char *buf, *p;
7179
7180 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
7181 {
7182 for (p = name; *p; p++)
7183 if (!isascii (*p) || iscntrl (*p))
7184 break;
7185
7186 if (*p)
7187 {
7188 setup_coding_system (coding_system, &coding);
7189 coding.src_multibyte = 0;
7190 coding.dst_multibyte = 1;
7191 coding.mode |= CODING_MODE_LAST_BLOCK;
7192 coding.composing = COMPOSITION_DISABLED;
7193 buf = (char *) alloca (size);
7194
7195 decode_coding (&coding, name, buf, strlen (name), size - 1);
7196 bcopy (buf, name, coding.produced);
7197 name[coding.produced] = '\0';
7198 }
7199 }
7200
7201 /* If there's just one occurrence of '-' in the family name, it is
7202 replaced with '_'. (More than one occurrence of '-' means a
7203 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7204 p = strchr (name, '-');
7205 if (p && strchr (p + 1, '-') == NULL)
7206 *p = '_';
7207
7208 for (p = name; *p; p++)
7209 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7210 for some locales. */
7211 if (isascii (*p))
7212 *p = tolower (*p);
7213 }
7214
7215
7216 static char *
7217 mac_to_x_fontname (name, size, style, charset)
7218 const char *name;
7219 int size;
7220 Style style;
7221 char *charset;
7222 {
7223 Str31 foundry, cs;
7224 Str255 family;
7225 char xf[256], *result;
7226 unsigned char *p;
7227
7228 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
7229 charset = cs;
7230 else
7231 {
7232 strcpy(foundry, "Apple");
7233 strcpy(family, name);
7234 }
7235
7236 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7237 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
7238 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
7239
7240 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
7241 sprintf (result, "-%s-%s-%s", foundry, family, xf);
7242 for (p = result; *p; p++)
7243 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7244 for some locales. */
7245 if (isascii (*p))
7246 *p = tolower (*p);
7247 return result;
7248 }
7249
7250
7251 /* Parse fully-specified and instantiated X11 font spec XF, and store
7252 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7253 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7254 caller must allocate at least 256 and 32 bytes respectively. For
7255 ordinary Mac fonts, the value stored to FAMILY should just be their
7256 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7257 intlfonts collection contain their charset designation in their
7258 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7259 types of font names are handled accordingly. */
7260
7261 const int kDefaultFontSize = 12;
7262
7263 static int
7264 parse_x_font_name (xf, family, size, style, charset)
7265 const char *xf;
7266 char *family;
7267 int *size;
7268 Style *style;
7269 char *charset;
7270 {
7271 Str31 foundry, weight;
7272 int point_size, avgwidth;
7273 char slant[2], *p;
7274
7275 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7276 foundry, family, weight, slant, size,
7277 &point_size, &avgwidth, charset) != 8
7278 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7279 foundry, family, weight, slant, size,
7280 &point_size, &avgwidth, charset) != 8)
7281 return 0;
7282
7283 if (*size == 0)
7284 {
7285 if (point_size > 0)
7286 *size = point_size / 10;
7287 else if (avgwidth > 0)
7288 *size = avgwidth / 10;
7289 }
7290 if (*size == 0)
7291 *size = kDefaultFontSize;
7292
7293 *style = normal;
7294 if (strcmp (weight, "bold") == 0)
7295 *style |= bold;
7296 if (*slant == 'i')
7297 *style |= italic;
7298
7299 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
7300 {
7301 int foundry_len = strlen (foundry), family_len = strlen (family);
7302
7303 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
7304 {
7305 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7306 but take overlap into account. */
7307 memmove (family + foundry_len + 1, family, family_len);
7308 memcpy (family, foundry, foundry_len);
7309 family[foundry_len] = '-';
7310 family[foundry_len + 1 + family_len] = '-';
7311 strcpy (family + foundry_len + 1 + family_len + 1, charset);
7312 }
7313 else
7314 return 0;
7315 }
7316
7317 for (p = family; *p; p++)
7318 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7319 for some locales. */
7320 if (isascii (*p))
7321 *p = tolower (*p);
7322
7323 return 1;
7324 }
7325
7326
7327 static void
7328 add_font_name_table_entry (char *font_name)
7329 {
7330 if (font_name_table_size == 0)
7331 {
7332 font_name_table_size = 256;
7333 font_name_table = (char **)
7334 xmalloc (font_name_table_size * sizeof (char *));
7335 }
7336 else if (font_name_count + 1 >= font_name_table_size)
7337 {
7338 font_name_table_size *= 2;
7339 font_name_table = (char **)
7340 xrealloc (font_name_table,
7341 font_name_table_size * sizeof (char *));
7342 }
7343
7344 font_name_table[font_name_count++] = font_name;
7345 }
7346
7347 static void
7348 add_mac_font_name (name, size, style, charset)
7349 const char *name;
7350 int size;
7351 Style style;
7352 const char *charset;
7353 {
7354 if (size > 0)
7355 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
7356 else
7357 {
7358 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
7359 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
7360 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
7361 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
7362 charset));
7363 }
7364 }
7365
7366 #if USE_ATSUI
7367 static FMFontStyle
7368 fm_get_style_from_font (font)
7369 FMFont font;
7370 {
7371 OSStatus err;
7372 FMFontStyle style = normal;
7373 ByteCount len;
7374 UInt16 mac_style;
7375 FMFontFamily font_family;
7376 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
7377
7378 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
7379 some font (e.g., Optima) even if it is `bold'. */
7380 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
7381 sizeof (mac_style), &mac_style, &len);
7382 if (err == noErr
7383 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
7384 style = EndianU16_BtoN (mac_style);
7385 else
7386 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
7387
7388 return style;
7389 }
7390
7391 static ATSUFontID
7392 atsu_find_font_from_family_name (family)
7393 const char *family;
7394 {
7395 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
7396 unsigned hash_code;
7397 int i;
7398 Lisp_Object rest, best;
7399 FMFontStyle min_style, style;
7400
7401 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
7402 &hash_code);
7403 if (i < 0)
7404 return kATSUInvalidFontID;
7405
7406 rest = HASH_VALUE (h, i);
7407 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
7408 return cons_to_long (rest);
7409
7410 rest = Fnreverse (rest);
7411 best = XCAR (rest);
7412 rest = XCDR (rest);
7413 if (!NILP (rest)
7414 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
7415 do
7416 {
7417 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
7418 if (style < min_style)
7419 {
7420 best = XCAR (rest);
7421 if (style == normal)
7422 break;
7423 else
7424 min_style = style;
7425 }
7426 rest = XCDR (rest);
7427 }
7428 while (!NILP (rest));
7429
7430 HASH_VALUE (h, i) = best;
7431 return cons_to_long (best);
7432 }
7433
7434 static Lisp_Object
7435 fm_style_to_face_attributes (fm_style)
7436 FMFontStyle fm_style;
7437 {
7438 Lisp_Object tem;
7439
7440 fm_style &= (bold | italic);
7441 tem = assq_no_quit (make_number (fm_style),
7442 fm_style_face_attributes_alist);
7443 if (!NILP (tem))
7444 return XCDR (tem);
7445
7446 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
7447 QCslant, fm_style & italic ? Qitalic : Qnormal);
7448 fm_style_face_attributes_alist =
7449 Fcons (Fcons (make_number (fm_style), tem),
7450 fm_style_face_attributes_alist);
7451
7452 return tem;
7453 }
7454
7455 static Lisp_Object
7456 atsu_find_font_family_name (font_id)
7457 ATSUFontID font_id;
7458 {
7459 OSStatus err;
7460 ByteCount len;
7461 Lisp_Object family = Qnil;
7462
7463 err = ATSUFindFontName (font_id, kFontFamilyName,
7464 kFontMacintoshPlatform, kFontNoScript,
7465 kFontNoLanguage, 0, NULL, &len, NULL);
7466 if (err == noErr)
7467 {
7468 family = make_uninit_string (len);
7469 err = ATSUFindFontName (font_id, kFontFamilyName,
7470 kFontMacintoshPlatform, kFontNoScript,
7471 kFontNoLanguage, len, SDATA (family),
7472 NULL, NULL);
7473 }
7474 if (err == noErr)
7475 decode_mac_font_name (SDATA (family), len + 1, Qnil);
7476
7477 return family;
7478 }
7479
7480 Lisp_Object
7481 mac_atsu_font_face_attributes (font_id)
7482 ATSUFontID font_id;
7483 {
7484 Lisp_Object family, style_attrs;
7485
7486 family = atsu_find_font_family_name (font_id);
7487 if (NILP (family))
7488 return Qnil;
7489 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
7490 return Fcons (QCfamily, Fcons (family, style_attrs));
7491 }
7492 #endif
7493
7494 /* Sets up the table font_name_table to contain the list of all fonts
7495 in the system the first time the table is used so that the Resource
7496 Manager need not be accessed every time this information is
7497 needed. */
7498
7499 static void
7500 init_font_name_table ()
7501 {
7502 #if TARGET_API_MAC_CARBON
7503 FMFontFamilyIterator ffi;
7504 FMFontFamilyInstanceIterator ffii;
7505 FMFontFamily ff;
7506 Lisp_Object text_encoding_info_alist;
7507 struct gcpro gcpro1;
7508
7509 text_encoding_info_alist = create_text_encoding_info_alist ();
7510
7511 #if USE_ATSUI
7512 #if USE_CG_TEXT_DRAWING
7513 init_cg_text_anti_aliasing_threshold ();
7514 #endif
7515 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
7516 text_encoding_info_alist)))
7517 {
7518 OSStatus err;
7519 struct Lisp_Hash_Table *h;
7520 unsigned hash_code;
7521 ItemCount nfonts, i;
7522 ATSUFontID *font_ids = NULL;
7523 Lisp_Object prev_family = Qnil;
7524 int j;
7525
7526 atsu_font_id_hash =
7527 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
7528 make_float (DEFAULT_REHASH_SIZE),
7529 make_float (DEFAULT_REHASH_THRESHOLD),
7530 Qnil, Qnil, Qnil);;
7531 h = XHASH_TABLE (atsu_font_id_hash);
7532
7533 err = ATSUFontCount (&nfonts);
7534 if (err == noErr)
7535 {
7536 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
7537 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
7538 }
7539 if (err == noErr)
7540 for (i = 0; i < nfonts; i++)
7541 {
7542 Lisp_Object family;
7543
7544 family = atsu_find_font_family_name (font_ids[i]);
7545 if (NILP (family) || SREF (family, 0) == '.')
7546 continue;
7547 if (!NILP (Fequal (prev_family, family)))
7548 family = prev_family;
7549 else
7550 j = hash_lookup (h, family, &hash_code);
7551 if (j < 0)
7552 {
7553 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
7554 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
7555 Qnil), hash_code);
7556 }
7557 else if (EQ (prev_family, family))
7558 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
7559 HASH_VALUE (h, j));
7560 prev_family = family;
7561 }
7562 if (font_ids)
7563 xfree (font_ids);
7564 }
7565 #endif
7566
7567 /* Create a dummy instance iterator here to avoid creating and
7568 destroying it in the loop. */
7569 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
7570 return;
7571 /* Create an iterator to enumerate the font families. */
7572 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
7573 != noErr)
7574 {
7575 FMDisposeFontFamilyInstanceIterator (&ffii);
7576 return;
7577 }
7578
7579 GCPRO1 (text_encoding_info_alist);
7580
7581 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
7582 {
7583 Str255 name;
7584 FMFont font;
7585 FMFontStyle style;
7586 FMFontSize size;
7587 TextEncoding encoding;
7588 TextEncodingBase sc;
7589 Lisp_Object text_encoding_info, family;
7590
7591 if (FMGetFontFamilyName (ff, name) != noErr)
7592 continue;
7593 p2cstr (name);
7594 if (*name == '.')
7595 continue;
7596
7597 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
7598 continue;
7599 sc = GetTextEncodingBase (encoding);
7600 text_encoding_info = assq_no_quit (make_number (sc),
7601 text_encoding_info_alist);
7602 if (NILP (text_encoding_info))
7603 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
7604 text_encoding_info_alist);
7605 decode_mac_font_name (name, sizeof (name),
7606 XCAR (XCDR (text_encoding_info)));
7607 family = build_string (name);
7608 if (!NILP (Fassoc (family, fm_font_family_alist)))
7609 continue;
7610 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
7611 fm_font_family_alist);
7612
7613 /* Point the instance iterator at the current font family. */
7614 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
7615 continue;
7616
7617 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
7618 == noErr)
7619 {
7620 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7621
7622 if (size > 0 || style == normal)
7623 for (; !NILP (rest); rest = XCDR (rest))
7624 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
7625 }
7626 }
7627
7628 UNGCPRO;
7629
7630 /* Dispose of the iterators. */
7631 FMDisposeFontFamilyIterator (&ffi);
7632 FMDisposeFontFamilyInstanceIterator (&ffii);
7633 #else /* !TARGET_API_MAC_CARBON */
7634 GrafPtr port;
7635 SInt16 fontnum, old_fontnum;
7636 int num_mac_fonts = CountResources('FOND');
7637 int i, j;
7638 Handle font_handle, font_handle_2;
7639 short id, scriptcode;
7640 ResType type;
7641 Str255 name;
7642 struct FontAssoc *fat;
7643 struct AsscEntry *assc_entry;
7644 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
7645 struct gcpro gcpro1;
7646
7647 GetPort (&port); /* save the current font number used */
7648 old_fontnum = port->txFont;
7649
7650 text_encoding_info_alist = create_text_encoding_info_alist ();
7651
7652 GCPRO1 (text_encoding_info_alist);
7653
7654 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
7655 {
7656 font_handle = GetIndResource ('FOND', i);
7657 if (!font_handle)
7658 continue;
7659
7660 GetResInfo (font_handle, &id, &type, name);
7661 GetFNum (name, &fontnum);
7662 p2cstr (name);
7663 if (fontnum == 0 || *name == '.')
7664 continue;
7665
7666 TextFont (fontnum);
7667 scriptcode = FontToScript (fontnum);
7668 text_encoding_info = assq_no_quit (make_number (scriptcode),
7669 text_encoding_info_alist);
7670 if (NILP (text_encoding_info))
7671 text_encoding_info = assq_no_quit (make_number (smRoman),
7672 text_encoding_info_alist);
7673 decode_mac_font_name (name, sizeof (name),
7674 XCAR (XCDR (text_encoding_info)));
7675 family = build_string (name);
7676 if (!NILP (Fassoc (family, fm_font_family_alist)))
7677 continue;
7678 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
7679 fm_font_family_alist);
7680 do
7681 {
7682 HLock (font_handle);
7683
7684 if (GetResourceSizeOnDisk (font_handle)
7685 >= sizeof (struct FamRec))
7686 {
7687 fat = (struct FontAssoc *) (*font_handle
7688 + sizeof (struct FamRec));
7689 assc_entry
7690 = (struct AsscEntry *) (*font_handle
7691 + sizeof (struct FamRec)
7692 + sizeof (struct FontAssoc));
7693
7694 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
7695 {
7696 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7697
7698 for (; !NILP (rest); rest = XCDR (rest))
7699 add_mac_font_name (name, assc_entry->fontSize,
7700 assc_entry->fontStyle,
7701 SDATA (XCAR (rest)));
7702 }
7703 }
7704
7705 HUnlock (font_handle);
7706 font_handle_2 = GetNextFOND (font_handle);
7707 ReleaseResource (font_handle);
7708 font_handle = font_handle_2;
7709 }
7710 while (ResError () == noErr && font_handle);
7711 }
7712
7713 UNGCPRO;
7714
7715 TextFont (old_fontnum);
7716 #endif /* !TARGET_API_MAC_CARBON */
7717 }
7718
7719
7720 void
7721 mac_clear_font_name_table ()
7722 {
7723 int i;
7724
7725 for (i = 0; i < font_name_count; i++)
7726 xfree (font_name_table[i]);
7727 xfree (font_name_table);
7728 font_name_table = NULL;
7729 font_name_table_size = font_name_count = 0;
7730 fm_font_family_alist = Qnil;
7731 }
7732
7733
7734 enum xlfd_scalable_field_index
7735 {
7736 XLFD_SCL_PIXEL_SIZE,
7737 XLFD_SCL_POINT_SIZE,
7738 XLFD_SCL_AVGWIDTH,
7739 XLFD_SCL_LAST
7740 };
7741
7742 static const int xlfd_scalable_fields[] =
7743 {
7744 6, /* PIXEL_SIZE */
7745 7, /* POINT_SIZE */
7746 11, /* AVGWIDTH */
7747 -1
7748 };
7749
7750 static Lisp_Object
7751 mac_do_list_fonts (pattern, maxnames)
7752 const char *pattern;
7753 int maxnames;
7754 {
7755 int i, n_fonts = 0;
7756 Lisp_Object font_list = Qnil;
7757 struct xlfdpat *pat;
7758 char *scaled;
7759 const char *ptr;
7760 int scl_val[XLFD_SCL_LAST], *val;
7761 const int *field;
7762 int exact;
7763
7764 if (font_name_table == NULL) /* Initialize when first used. */
7765 init_font_name_table ();
7766
7767 for (i = 0; i < XLFD_SCL_LAST; i++)
7768 scl_val[i] = -1;
7769
7770 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7771 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7772 fonts are scaled according to the specified size. */
7773 ptr = pattern;
7774 i = 0;
7775 field = xlfd_scalable_fields;
7776 val = scl_val;
7777 if (*ptr == '-')
7778 do
7779 {
7780 ptr++;
7781 if (i == *field)
7782 {
7783 if ('0' <= *ptr && *ptr <= '9')
7784 {
7785 *val = *ptr++ - '0';
7786 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7787 *val = *val * 10 + *ptr++ - '0';
7788 if (*ptr != '-')
7789 *val = -1;
7790 }
7791 field++;
7792 val++;
7793 }
7794 ptr = strchr (ptr, '-');
7795 i++;
7796 }
7797 while (ptr && i < 14);
7798
7799 if (i == 14 && ptr == NULL)
7800 {
7801 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7802 scl_val[XLFD_SCL_PIXEL_SIZE] =
7803 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7804 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7805 : -1));
7806 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7807 scl_val[XLFD_SCL_POINT_SIZE] =
7808 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7809 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7810 : -1));
7811 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7812 scl_val[XLFD_SCL_AVGWIDTH] =
7813 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7814 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7815 : -1));
7816 }
7817 else
7818 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7819
7820 pat = xlfdpat_create (pattern);
7821 if (pat == NULL)
7822 return Qnil;
7823
7824 exact = xlfdpat_exact_p (pat);
7825
7826 for (i = 0; i < font_name_count; i++)
7827 {
7828 if (xlfdpat_match (pat, font_name_table[i]))
7829 {
7830 font_list = Fcons (build_string (font_name_table[i]), font_list);
7831 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7832 break;
7833 }
7834 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
7835 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
7836 {
7837 int former_len = ptr - font_name_table[i];
7838
7839 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
7840 memcpy (scaled, font_name_table[i], former_len);
7841 sprintf (scaled + former_len,
7842 "-%d-%d-72-72-m-%d-%s",
7843 scl_val[XLFD_SCL_PIXEL_SIZE],
7844 scl_val[XLFD_SCL_POINT_SIZE],
7845 scl_val[XLFD_SCL_AVGWIDTH],
7846 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
7847
7848 if (xlfdpat_match (pat, scaled))
7849 {
7850 font_list = Fcons (build_string (scaled), font_list);
7851 xfree (scaled);
7852 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7853 break;
7854 }
7855 else
7856 xfree (scaled);
7857 }
7858 }
7859
7860 xlfdpat_destroy (pat);
7861
7862 return font_list;
7863 }
7864
7865 /* Return a list of names of available fonts matching PATTERN on frame F.
7866
7867 Frame F null means we have not yet created any frame on Mac, and
7868 consult the first display in x_display_list. MAXNAMES sets a limit
7869 on how many fonts to match. */
7870
7871 Lisp_Object
7872 x_list_fonts (f, pattern, size, maxnames)
7873 struct frame *f;
7874 Lisp_Object pattern;
7875 int size, maxnames;
7876 {
7877 Lisp_Object list = Qnil, patterns, tem, key;
7878 struct mac_display_info *dpyinfo
7879 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
7880
7881 xassert (size <= 0);
7882
7883 patterns = Fassoc (pattern, Valternate_fontname_alist);
7884 if (NILP (patterns))
7885 patterns = Fcons (pattern, Qnil);
7886
7887 for (; CONSP (patterns); patterns = XCDR (patterns))
7888 {
7889 pattern = XCAR (patterns);
7890
7891 if (!STRINGP (pattern))
7892 continue;
7893
7894 tem = XCAR (XCDR (dpyinfo->name_list_element));
7895 key = Fcons (pattern, make_number (maxnames));
7896
7897 list = Fassoc (key, tem);
7898 if (!NILP (list))
7899 {
7900 list = Fcdr_safe (list);
7901 /* We have a cashed list. Don't have to get the list again. */
7902 goto label_cached;
7903 }
7904
7905 BLOCK_INPUT;
7906 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7907 UNBLOCK_INPUT;
7908
7909 /* MAC_TODO: add code for matching outline fonts here */
7910
7911 /* Now store the result in the cache. */
7912 XSETCAR (XCDR (dpyinfo->name_list_element),
7913 Fcons (Fcons (key, list),
7914 XCAR (XCDR (dpyinfo->name_list_element))));
7915
7916 label_cached:
7917 if (NILP (list)) continue; /* Try the remaining alternatives. */
7918 }
7919
7920 return list;
7921 }
7922
7923
7924 #if GLYPH_DEBUG
7925
7926 /* Check that FONT is valid on frame F. It is if it can be found in F's
7927 font table. */
7928
7929 static void
7930 x_check_font (f, font)
7931 struct frame *f;
7932 XFontStruct *font;
7933 {
7934 int i;
7935 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7936
7937 xassert (font != NULL);
7938
7939 for (i = 0; i < dpyinfo->n_fonts; i++)
7940 if (dpyinfo->font_table[i].name
7941 && font == dpyinfo->font_table[i].font)
7942 break;
7943
7944 xassert (i < dpyinfo->n_fonts);
7945 }
7946
7947 #endif /* GLYPH_DEBUG != 0 */
7948
7949 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7950 Note: There are (broken) X fonts out there with invalid XFontStruct
7951 min_bounds contents. For example, handa@etl.go.jp reports that
7952 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7953 have font->min_bounds.width == 0. */
7954
7955 static INLINE void
7956 x_font_min_bounds (font, w, h)
7957 MacFontStruct *font;
7958 int *w, *h;
7959 {
7960 *h = FONT_HEIGHT (font);
7961 *w = font->min_bounds.width;
7962 }
7963
7964
7965 /* Compute the smallest character width and smallest font height over
7966 all fonts available on frame F. Set the members smallest_char_width
7967 and smallest_font_height in F's x_display_info structure to
7968 the values computed. Value is non-zero if smallest_font_height or
7969 smallest_char_width become smaller than they were before. */
7970
7971 static int
7972 x_compute_min_glyph_bounds (f)
7973 struct frame *f;
7974 {
7975 int i;
7976 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7977 MacFontStruct *font;
7978 int old_width = dpyinfo->smallest_char_width;
7979 int old_height = dpyinfo->smallest_font_height;
7980
7981 dpyinfo->smallest_font_height = 100000;
7982 dpyinfo->smallest_char_width = 100000;
7983
7984 for (i = 0; i < dpyinfo->n_fonts; ++i)
7985 if (dpyinfo->font_table[i].name)
7986 {
7987 struct font_info *fontp = dpyinfo->font_table + i;
7988 int w, h;
7989
7990 font = (MacFontStruct *) fontp->font;
7991 xassert (font != (MacFontStruct *) ~0);
7992 x_font_min_bounds (font, &w, &h);
7993
7994 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
7995 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
7996 }
7997
7998 xassert (dpyinfo->smallest_char_width > 0
7999 && dpyinfo->smallest_font_height > 0);
8000
8001 return (dpyinfo->n_fonts == 1
8002 || dpyinfo->smallest_char_width < old_width
8003 || dpyinfo->smallest_font_height < old_height);
8004 }
8005
8006
8007 /* Determine whether given string is a fully-specified XLFD: all 14
8008 fields are present, none is '*'. */
8009
8010 static int
8011 is_fully_specified_xlfd (p)
8012 const char *p;
8013 {
8014 int i;
8015 char *q;
8016
8017 if (*p != '-')
8018 return 0;
8019
8020 for (i = 0; i < 13; i++)
8021 {
8022 q = strchr (p + 1, '-');
8023 if (q == NULL)
8024 return 0;
8025 if (q - p == 2 && *(p + 1) == '*')
8026 return 0;
8027 p = q;
8028 }
8029
8030 if (strchr (p + 1, '-') != NULL)
8031 return 0;
8032
8033 if (*(p + 1) == '*' && *(p + 2) == '\0')
8034 return 0;
8035
8036 return 1;
8037 }
8038
8039
8040 /* mac_load_query_font creates and returns an internal representation
8041 for a font in a MacFontStruct struct. There is really no concept
8042 corresponding to "loading" a font on the Mac. But we check its
8043 existence and find the font number and all other information for it
8044 and store them in the returned MacFontStruct. */
8045
8046 static MacFontStruct *
8047 mac_load_query_font (f, fontname)
8048 struct frame *f;
8049 char *fontname;
8050 {
8051 int size;
8052 char *name;
8053 Str255 family;
8054 Str31 charset;
8055 SInt16 fontnum;
8056 #if USE_ATSUI
8057 static ATSUFontID font_id;
8058 ATSUStyle mac_style = NULL;
8059 #endif
8060 Style fontface;
8061 #if TARGET_API_MAC_CARBON
8062 TextEncoding encoding;
8063 int scriptcode;
8064 #else
8065 short scriptcode;
8066 #endif
8067 MacFontStruct *font;
8068 XCharStruct *space_bounds = NULL, *pcm;
8069
8070 if (is_fully_specified_xlfd (fontname))
8071 name = fontname;
8072 else
8073 {
8074 Lisp_Object matched_fonts;
8075
8076 matched_fonts = mac_do_list_fonts (fontname, 1);
8077 if (NILP (matched_fonts))
8078 return NULL;
8079 name = SDATA (XCAR (matched_fonts));
8080 }
8081
8082 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
8083 return NULL;
8084
8085 #if USE_ATSUI
8086 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
8087 {
8088 OSStatus err;
8089 static const ATSUAttributeTag tags[] =
8090 {kATSUFontTag, kATSUSizeTag,
8091 kATSUQDBoldfaceTag, kATSUQDItalicTag};
8092 static const ByteCount sizes[] =
8093 {sizeof (ATSUFontID), sizeof (Fixed),
8094 sizeof (Boolean), sizeof (Boolean)};
8095 static Fixed size_fixed;
8096 static Boolean bold_p, italic_p;
8097 static const ATSUAttributeValuePtr values[] =
8098 {&font_id, &size_fixed,
8099 &bold_p, &italic_p};
8100 static const ATSUFontFeatureType types[] =
8101 {kAllTypographicFeaturesType, kDiacriticsType};
8102 static const ATSUFontFeatureSelector selectors[] =
8103 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
8104 FMFontStyle style;
8105
8106 font_id = atsu_find_font_from_family_name (family);
8107 if (font_id == kATSUInvalidFontID)
8108 return;
8109 size_fixed = Long2Fix (size);
8110 bold_p = (fontface & bold) != 0;
8111 italic_p = (fontface & italic) != 0;
8112 err = ATSUCreateStyle (&mac_style);
8113 if (err != noErr)
8114 return NULL;
8115 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
8116 types, selectors);
8117 if (err != noErr)
8118 return NULL;
8119 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
8120 tags, sizes, values);
8121 if (err != noErr)
8122 return NULL;
8123 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
8124 if (err != noErr)
8125 fontnum = -1;
8126 scriptcode = kTextEncodingMacUnicode;
8127 }
8128 else
8129 #endif
8130 {
8131 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
8132
8133 if (NILP (tmp))
8134 return NULL;
8135 fontnum = XINT (XCDR (tmp));
8136 #if TARGET_API_MAC_CARBON
8137 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
8138 return NULL;
8139 scriptcode = GetTextEncodingBase (encoding);
8140 #else
8141 scriptcode = FontToScript (fontnum);
8142 #endif
8143 }
8144
8145 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
8146
8147 font->mac_fontnum = fontnum;
8148 font->mac_fontsize = size;
8149 font->mac_fontface = fontface;
8150 font->mac_scriptcode = scriptcode;
8151 #if USE_ATSUI
8152 font->mac_style = mac_style;
8153 #if USE_CG_TEXT_DRAWING
8154 font->cg_font = NULL;
8155 font->cg_glyphs = NULL;
8156 #endif
8157 #endif
8158
8159 /* Apple Japanese (SJIS) font is listed as both
8160 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8161 (Roman script) in init_font_name_table (). The latter should be
8162 treated as a one-byte font. */
8163 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
8164 font->mac_scriptcode = smRoman;
8165
8166 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
8167
8168 #if USE_ATSUI
8169 if (font->mac_style)
8170 {
8171 OSStatus err;
8172 UniChar c;
8173
8174 font->min_byte1 = 0;
8175 font->max_byte1 = 0xff;
8176 font->min_char_or_byte2 = 0;
8177 font->max_char_or_byte2 = 0xff;
8178
8179 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
8180 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
8181 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
8182 pcm_init (font->bounds.rows[0], 0x100);
8183
8184 #if USE_CG_TEXT_DRAWING
8185 if (fontnum != -1)
8186 {
8187 FMFontStyle style;
8188 ATSFontRef ats_font;
8189
8190 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
8191 &font_id, &style);
8192 /* Use CG text drawing if italic/bold is not synthesized. */
8193 if (err == noErr && style == fontface)
8194 {
8195 ats_font = FMGetATSFontRefFromFont (font_id);
8196 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
8197 }
8198 }
8199
8200 if (font->cg_font)
8201 {
8202 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
8203 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
8204 }
8205 #endif
8206 space_bounds = font->bounds.rows[0] + 0x20;
8207 err = mac_query_char_extents (font->mac_style, 0x20,
8208 &font->ascent, &font->descent,
8209 space_bounds,
8210 #if USE_CG_TEXT_DRAWING
8211 (font->cg_glyphs ? font->cg_glyphs + 0x20
8212 : NULL)
8213 #else
8214 NULL
8215 #endif
8216 );
8217 if (err != noErr
8218 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
8219 {
8220 mac_unload_font (&one_mac_display_info, font);
8221 return NULL;
8222 }
8223
8224 pcm = font->bounds.rows[0];
8225 for (c = 0x21; c <= 0xff; c++)
8226 {
8227 if (c == 0xad)
8228 /* Soft hyphen is not supported in ATSUI. */
8229 continue;
8230 else if (c == 0x7f)
8231 {
8232 #if USE_CG_TEXT_DRAWING
8233 if (font->cg_glyphs)
8234 {
8235 c = 0x9f;
8236 pcm = NULL;
8237 continue;
8238 }
8239 #endif
8240 break;
8241 }
8242
8243 mac_query_char_extents (font->mac_style, c, NULL, NULL,
8244 pcm ? pcm + c : NULL,
8245 #if USE_CG_TEXT_DRAWING
8246 (font->cg_glyphs ? font->cg_glyphs + c
8247 : NULL)
8248 #else
8249 NULL
8250 #endif
8251 );
8252
8253 #if USE_CG_TEXT_DRAWING
8254 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
8255 {
8256 /* Don't use CG text drawing if font substitution occurs in
8257 ASCII or Latin-1 characters. */
8258 CGFontRelease (font->cg_font);
8259 font->cg_font = NULL;
8260 xfree (font->cg_glyphs);
8261 font->cg_glyphs = NULL;
8262 if (pcm == NULL)
8263 break;
8264 }
8265 #endif
8266 }
8267 }
8268 else
8269 #endif
8270 {
8271 OSStatus err;
8272 FontInfo the_fontinfo;
8273 int is_two_byte_font;
8274
8275 #if USE_CG_DRAWING
8276 mac_prepare_for_quickdraw (f);
8277 #endif
8278 SetPortWindowPort (FRAME_MAC_WINDOW (f));
8279
8280 TextFont (fontnum);
8281 TextSize (size);
8282 TextFace (fontface);
8283
8284 GetFontInfo (&the_fontinfo);
8285
8286 font->ascent = the_fontinfo.ascent;
8287 font->descent = the_fontinfo.descent;
8288
8289 is_two_byte_font = (font->mac_scriptcode == smJapanese
8290 || font->mac_scriptcode == smTradChinese
8291 || font->mac_scriptcode == smSimpChinese
8292 || font->mac_scriptcode == smKorean);
8293
8294 if (is_two_byte_font)
8295 {
8296 int char_width;
8297
8298 font->min_byte1 = 0xa1;
8299 font->max_byte1 = 0xfe;
8300 font->min_char_or_byte2 = 0xa1;
8301 font->max_char_or_byte2 = 0xfe;
8302
8303 /* Use the width of an "ideographic space" of that font
8304 because the_fontinfo.widMax returns the wrong width for
8305 some fonts. */
8306 switch (font->mac_scriptcode)
8307 {
8308 case smJapanese:
8309 font->min_byte1 = 0x81;
8310 font->max_byte1 = 0xfc;
8311 font->min_char_or_byte2 = 0x40;
8312 font->max_char_or_byte2 = 0xfc;
8313 char_width = StringWidth("\p\x81\x40");
8314 break;
8315 case smTradChinese:
8316 font->min_char_or_byte2 = 0x40;
8317 char_width = StringWidth("\p\xa1\x40");
8318 break;
8319 case smSimpChinese:
8320 char_width = StringWidth("\p\xa1\xa1");
8321 break;
8322 case smKorean:
8323 char_width = StringWidth("\p\xa1\xa1");
8324 break;
8325 }
8326
8327 font->bounds.per_char = NULL;
8328
8329 if (fontface & italic)
8330 font->max_bounds.rbearing = char_width + 1;
8331 else
8332 font->max_bounds.rbearing = char_width;
8333 font->max_bounds.lbearing = 0;
8334 font->max_bounds.width = char_width;
8335 font->max_bounds.ascent = the_fontinfo.ascent;
8336 font->max_bounds.descent = the_fontinfo.descent;
8337
8338 font->min_bounds = font->max_bounds;
8339 }
8340 else
8341 {
8342 int c;
8343
8344 font->min_byte1 = font->max_byte1 = 0;
8345 font->min_char_or_byte2 = 0x20;
8346 font->max_char_or_byte2 = 0xff;
8347
8348 font->bounds.per_char =
8349 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
8350 bzero (font->bounds.per_char,
8351 sizeof (XCharStruct) * (0xff - 0x20 + 1));
8352
8353 space_bounds = font->bounds.per_char;
8354 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
8355 &font->descent, space_bounds, NULL);
8356 if (err != noErr || space_bounds->width <= 0)
8357 {
8358 mac_unload_font (&one_mac_display_info, font);
8359 return NULL;
8360 }
8361
8362 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
8363 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
8364 }
8365 }
8366
8367 if (space_bounds)
8368 {
8369 int c;
8370
8371 font->min_bounds = font->max_bounds = *space_bounds;
8372 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
8373 if (pcm->width > 0)
8374 {
8375 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
8376 pcm->lbearing);
8377 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
8378 pcm->rbearing);
8379 font->min_bounds.width = min (font->min_bounds.width,
8380 pcm->width);
8381 font->min_bounds.ascent = min (font->min_bounds.ascent,
8382 pcm->ascent);
8383 font->min_bounds.descent = min (font->min_bounds.descent,
8384 pcm->descent);
8385
8386 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
8387 pcm->lbearing);
8388 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
8389 pcm->rbearing);
8390 font->max_bounds.width = max (font->max_bounds.width,
8391 pcm->width);
8392 font->max_bounds.ascent = max (font->max_bounds.ascent,
8393 pcm->ascent);
8394 font->max_bounds.descent = max (font->max_bounds.descent,
8395 pcm->descent);
8396 }
8397 if (
8398 #if USE_ATSUI
8399 font->mac_style == NULL &&
8400 #endif
8401 font->max_bounds.width == font->min_bounds.width
8402 && font->min_bounds.lbearing >= 0
8403 && font->max_bounds.rbearing <= font->max_bounds.width)
8404 {
8405 /* Fixed width and no overhangs. */
8406 xfree (font->bounds.per_char);
8407 font->bounds.per_char = NULL;
8408 }
8409 }
8410
8411 #if !defined (MAC_OS8) || USE_ATSUI
8412 /* AppKit and WebKit do some adjustment to the heights of Courier,
8413 Helvetica, and Times. This only works on the environments where
8414 srcCopy text transfer mode is never used. */
8415 if (
8416 #ifdef MAC_OS8 /* implies USE_ATSUI */
8417 font->mac_style &&
8418 #endif
8419 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
8420 || strcmp (family, "times") == 0))
8421 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
8422 #endif
8423
8424 return font;
8425 }
8426
8427
8428 void
8429 mac_unload_font (dpyinfo, font)
8430 struct mac_display_info *dpyinfo;
8431 XFontStruct *font;
8432 {
8433 xfree (font->full_name);
8434 #if USE_ATSUI
8435 if (font->mac_style)
8436 {
8437 int i;
8438
8439 for (i = font->min_byte1; i <= font->max_byte1; i++)
8440 if (font->bounds.rows[i])
8441 xfree (font->bounds.rows[i]);
8442 xfree (font->bounds.rows);
8443 ATSUDisposeStyle (font->mac_style);
8444 }
8445 else
8446 #endif
8447 if (font->bounds.per_char)
8448 xfree (font->bounds.per_char);
8449 #if USE_CG_TEXT_DRAWING
8450 if (font->cg_font)
8451 CGFontRelease (font->cg_font);
8452 if (font->cg_glyphs)
8453 xfree (font->cg_glyphs);
8454 #endif
8455 xfree (font);
8456 }
8457
8458
8459 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8460 pointer to the structure font_info while allocating it dynamically.
8461 If SIZE is 0, load any size of font.
8462 If loading is failed, return NULL. */
8463
8464 struct font_info *
8465 x_load_font (f, fontname, size)
8466 struct frame *f;
8467 register char *fontname;
8468 int size;
8469 {
8470 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8471 Lisp_Object font_names;
8472
8473 /* Get a list of all the fonts that match this name. Once we
8474 have a list of matching fonts, we compare them against the fonts
8475 we already have by comparing names. */
8476 font_names = x_list_fonts (f, build_string (fontname), size, 1);
8477
8478 if (!NILP (font_names))
8479 {
8480 Lisp_Object tail;
8481 int i;
8482
8483 for (i = 0; i < dpyinfo->n_fonts; i++)
8484 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
8485 if (dpyinfo->font_table[i].name
8486 && (!strcmp (dpyinfo->font_table[i].name,
8487 SDATA (XCAR (tail)))
8488 || !strcmp (dpyinfo->font_table[i].full_name,
8489 SDATA (XCAR (tail)))))
8490 return (dpyinfo->font_table + i);
8491 }
8492 else
8493 return NULL;
8494
8495 /* Load the font and add it to the table. */
8496 {
8497 struct MacFontStruct *font;
8498 struct font_info *fontp;
8499 int i;
8500
8501 fontname = (char *) SDATA (XCAR (font_names));
8502
8503 BLOCK_INPUT;
8504 font = mac_load_query_font (f, fontname);
8505 UNBLOCK_INPUT;
8506 if (!font)
8507 return NULL;
8508
8509 /* Find a free slot in the font table. */
8510 for (i = 0; i < dpyinfo->n_fonts; ++i)
8511 if (dpyinfo->font_table[i].name == NULL)
8512 break;
8513
8514 /* If no free slot found, maybe enlarge the font table. */
8515 if (i == dpyinfo->n_fonts
8516 && dpyinfo->n_fonts == dpyinfo->font_table_size)
8517 {
8518 int sz;
8519 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
8520 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
8521 dpyinfo->font_table
8522 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
8523 }
8524
8525 fontp = dpyinfo->font_table + i;
8526 if (i == dpyinfo->n_fonts)
8527 ++dpyinfo->n_fonts;
8528
8529 /* Now fill in the slots of *FONTP. */
8530 BLOCK_INPUT;
8531 bzero (fontp, sizeof (*fontp));
8532 fontp->font = font;
8533 fontp->font_idx = i;
8534 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
8535 bcopy (fontname, fontp->name, strlen (fontname) + 1);
8536
8537 if (font->min_bounds.width == font->max_bounds.width)
8538 {
8539 /* Fixed width font. */
8540 fontp->average_width = fontp->space_width = font->min_bounds.width;
8541 }
8542 else
8543 {
8544 XChar2b char2b;
8545 XCharStruct *pcm;
8546
8547 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
8548 pcm = mac_per_char_metric (font, &char2b, 0);
8549 if (pcm)
8550 fontp->space_width = pcm->width;
8551 else
8552 fontp->space_width = FONT_WIDTH (font);
8553
8554 if (pcm)
8555 {
8556 int width = pcm->width;
8557 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
8558 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
8559 width += pcm->width;
8560 fontp->average_width = width / 95;
8561 }
8562 else
8563 fontp->average_width = FONT_WIDTH (font);
8564 }
8565
8566 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
8567 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
8568
8569 fontp->size = font->max_bounds.width;
8570 fontp->height = FONT_HEIGHT (font);
8571 {
8572 /* For some font, ascent and descent in max_bounds field is
8573 larger than the above value. */
8574 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
8575 if (max_height > fontp->height)
8576 fontp->height = max_height;
8577 }
8578
8579 /* The slot `encoding' specifies how to map a character
8580 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8581 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8582 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8583 2:0xA020..0xFF7F). For the moment, we don't know which charset
8584 uses this font. So, we set information in fontp->encoding[1]
8585 which is never used by any charset. If mapping can't be
8586 decided, set FONT_ENCODING_NOT_DECIDED. */
8587 if (font->mac_scriptcode == smJapanese)
8588 fontp->encoding[1] = 4;
8589 else
8590 {
8591 fontp->encoding[1]
8592 = (font->max_byte1 == 0
8593 /* 1-byte font */
8594 ? (font->min_char_or_byte2 < 0x80
8595 ? (font->max_char_or_byte2 < 0x80
8596 ? 0 /* 0x20..0x7F */
8597 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
8598 : 1) /* 0xA0..0xFF */
8599 /* 2-byte font */
8600 : (font->min_byte1 < 0x80
8601 ? (font->max_byte1 < 0x80
8602 ? (font->min_char_or_byte2 < 0x80
8603 ? (font->max_char_or_byte2 < 0x80
8604 ? 0 /* 0x2020..0x7F7F */
8605 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
8606 : 3) /* 0x20A0..0x7FFF */
8607 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
8608 : (font->min_char_or_byte2 < 0x80
8609 ? (font->max_char_or_byte2 < 0x80
8610 ? 2 /* 0xA020..0xFF7F */
8611 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
8612 : 1))); /* 0xA0A0..0xFFFF */
8613 }
8614
8615 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8616 fontp->baseline_offset
8617 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
8618 ? (long) value : 0);
8619 fontp->relative_compose
8620 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8621 ? (long) value : 0);
8622 fontp->default_ascent
8623 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8624 ? (long) value : 0);
8625 #else
8626 fontp->baseline_offset = 0;
8627 fontp->relative_compose = 0;
8628 fontp->default_ascent = 0;
8629 #endif
8630
8631 /* Set global flag fonts_changed_p to non-zero if the font loaded
8632 has a character with a smaller width than any other character
8633 before, or if the font loaded has a smaller height than any
8634 other font loaded before. If this happens, it will make a
8635 glyph matrix reallocation necessary. */
8636 fonts_changed_p |= x_compute_min_glyph_bounds (f);
8637 UNBLOCK_INPUT;
8638 return fontp;
8639 }
8640 }
8641
8642
8643 /* Return a pointer to struct font_info of a font named FONTNAME for
8644 frame F. If no such font is loaded, return NULL. */
8645
8646 struct font_info *
8647 x_query_font (f, fontname)
8648 struct frame *f;
8649 register char *fontname;
8650 {
8651 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8652 int i;
8653
8654 for (i = 0; i < dpyinfo->n_fonts; i++)
8655 if (dpyinfo->font_table[i].name
8656 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
8657 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
8658 return (dpyinfo->font_table + i);
8659 return NULL;
8660 }
8661
8662
8663 /* Find a CCL program for a font specified by FONTP, and set the member
8664 `encoder' of the structure. */
8665
8666 void
8667 x_find_ccl_program (fontp)
8668 struct font_info *fontp;
8669 {
8670 Lisp_Object list, elt;
8671
8672 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8673 {
8674 elt = XCAR (list);
8675 if (CONSP (elt)
8676 && STRINGP (XCAR (elt))
8677 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8678 >= 0))
8679 break;
8680 }
8681 if (! NILP (list))
8682 {
8683 struct ccl_program *ccl
8684 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8685
8686 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8687 xfree (ccl);
8688 else
8689 fontp->font_encoder = ccl;
8690 }
8691 }
8692
8693 #if USE_MAC_FONT_PANEL
8694 /* Whether Font Panel has been shown before. The first call to font
8695 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8696 slow. This variable is used for deferring such a call as much as
8697 possible. */
8698 static int font_panel_shown_p = 0;
8699
8700 int
8701 mac_font_panel_visible_p ()
8702 {
8703 return font_panel_shown_p && FPIsFontPanelVisible ();
8704 }
8705
8706 OSStatus
8707 mac_show_hide_font_panel ()
8708 {
8709 font_panel_shown_p = 1;
8710
8711 return FPShowHideFontPanel ();
8712 }
8713
8714 OSStatus
8715 mac_set_font_info_for_selection (f, face_id, c)
8716 struct frame *f;
8717 int face_id, c;
8718 {
8719 OSStatus err;
8720 EventTargetRef target = NULL;
8721 XFontStruct *font = NULL;
8722
8723 if (!mac_font_panel_visible_p ())
8724 return noErr;
8725
8726 if (f)
8727 {
8728 target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
8729
8730 if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
8731 {
8732 struct face *face;
8733
8734 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
8735 face = FACE_FROM_ID (f, face_id);
8736 font = face->font;
8737 }
8738 }
8739
8740 if (font == NULL)
8741 err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
8742 else
8743 {
8744 if (font->mac_fontnum != -1)
8745 {
8746 FontSelectionQDStyle qd_style;
8747
8748 qd_style.version = kFontSelectionQDStyleVersionZero;
8749 qd_style.instance.fontFamily = font->mac_fontnum;
8750 qd_style.instance.fontStyle = font->mac_fontface;
8751 qd_style.size = font->mac_fontsize;
8752 qd_style.hasColor = false;
8753
8754 err = SetFontInfoForSelection (kFontSelectionQDType,
8755 1, &qd_style, target);
8756 }
8757 else
8758 err = SetFontInfoForSelection (kFontSelectionATSUIType,
8759 1, &font->mac_style, target);
8760 }
8761
8762 return err;
8763 }
8764 #endif
8765
8766 \f
8767 /* The Mac Event loop code */
8768
8769 #if !TARGET_API_MAC_CARBON
8770 #include <Events.h>
8771 #include <Quickdraw.h>
8772 #include <Balloons.h>
8773 #include <Devices.h>
8774 #include <Fonts.h>
8775 #include <Gestalt.h>
8776 #include <Menus.h>
8777 #include <Processes.h>
8778 #include <Sound.h>
8779 #include <ToolUtils.h>
8780 #include <TextUtils.h>
8781 #include <Dialogs.h>
8782 #include <Script.h>
8783 #include <Types.h>
8784 #include <Resources.h>
8785
8786 #if __MWERKS__
8787 #include <unix.h>
8788 #endif
8789 #endif /* ! TARGET_API_MAC_CARBON */
8790
8791 #define M_APPLE 234
8792 #define I_ABOUT 1
8793
8794 #define WINDOW_RESOURCE 128
8795 #define TERM_WINDOW_RESOURCE 129
8796
8797 #define DEFAULT_NUM_COLS 80
8798
8799 #define MIN_DOC_SIZE 64
8800 #define MAX_DOC_SIZE 32767
8801
8802 #define EXTRA_STACK_ALLOC (256 * 1024)
8803
8804 #define ARGV_STRING_LIST_ID 129
8805 #define ABOUT_ALERT_ID 128
8806 #define RAM_TOO_LARGE_ALERT_ID 129
8807
8808 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8809 Lisp_Object Qreverse;
8810
8811
8812 /* Modifier associated with the control key, or nil to ignore. */
8813 Lisp_Object Vmac_control_modifier;
8814
8815 /* Modifier associated with the option key, or nil to ignore. */
8816 Lisp_Object Vmac_option_modifier;
8817
8818 /* Modifier associated with the command key, or nil to ignore. */
8819 Lisp_Object Vmac_command_modifier;
8820
8821 /* Modifier associated with the function key, or nil to ignore. */
8822 Lisp_Object Vmac_function_modifier;
8823
8824 /* True if the option and command modifiers should be used to emulate
8825 a three button mouse */
8826 Lisp_Object Vmac_emulate_three_button_mouse;
8827
8828 #if USE_CARBON_EVENTS
8829 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8830 mouse-2, instead of mouse-3. */
8831 int mac_wheel_button_is_mouse_2;
8832
8833 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8834 for processing before Emacs sees it. */
8835 int mac_pass_command_to_system;
8836
8837 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8838 for processing before Emacs sees it. */
8839 int mac_pass_control_to_system;
8840 #endif
8841
8842 /* Points to the variable `inev' in the function XTread_socket. It is
8843 used for passing an input event to the function back from
8844 Carbon/Apple event handlers. */
8845 static struct input_event *read_socket_inev = NULL;
8846
8847 Point saved_menu_event_location;
8848
8849 /* Apple Events */
8850 #if USE_CARBON_EVENTS
8851 static Lisp_Object Qhi_command;
8852 #ifdef MAC_OSX
8853 extern Lisp_Object Qwindow;
8854 static Lisp_Object Qtoolbar_switch_mode;
8855 #endif
8856 #if USE_MAC_FONT_PANEL
8857 extern Lisp_Object Qfont;
8858 static Lisp_Object Qpanel_closed, Qselection;
8859 #endif
8860 #if USE_MAC_TSM
8861 static TSMDocumentID tsm_document_id;
8862 static Lisp_Object Qtext_input;
8863 static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
8864 static Lisp_Object Vmac_ts_active_input_overlay;
8865 extern Lisp_Object Qbefore_string;
8866 static Lisp_Object Vmac_ts_script_language_on_focus;
8867 static Lisp_Object saved_ts_script_language_on_focus;
8868 static ScriptLanguageRecord saved_ts_language;
8869 static Component saved_ts_component;
8870 #endif
8871 #endif
8872 extern int mac_ready_for_apple_events;
8873 extern Lisp_Object Qundefined;
8874 extern void init_apple_event_handler P_ ((void));
8875 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8876 Lisp_Object *, Lisp_Object *,
8877 Lisp_Object *));
8878 extern OSErr init_coercion_handler P_ ((void));
8879
8880 /* Drag and Drop */
8881 extern OSErr install_drag_handler P_ ((WindowRef));
8882 extern void remove_drag_handler P_ ((WindowRef));
8883
8884 /* Showing help echo string during menu tracking */
8885 extern OSStatus install_menu_target_item_handler P_ ((WindowPtr));
8886
8887 #if USE_CARBON_EVENTS
8888 #ifdef MAC_OSX
8889 extern void init_service_handler ();
8890 static Lisp_Object Qservice, Qpaste, Qperform;
8891 #endif
8892
8893 /* Window Event Handler */
8894 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
8895 EventRef, void *);
8896 #endif
8897 OSStatus install_window_handler (WindowPtr);
8898
8899 extern void init_emacs_passwd_dir ();
8900 extern int emacs_main (int, char **, char **);
8901
8902 extern void initialize_applescript();
8903 extern void terminate_applescript();
8904
8905 /* Table for translating Mac keycode to X keysym values. Contributed
8906 by Sudhir Shenoy.
8907 Mapping for special keys is now identical to that in Apple X11
8908 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8909 on the right of the Cmd key on laptops, and fn + `enter' (->
8910 <linefeed>). */
8911 static const unsigned char keycode_to_xkeysym_table[] = {
8912 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8913 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8914 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8915
8916 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8917 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8918 /*0x38*/ 0, 0, 0, 0,
8919 /*0x3C*/ 0, 0, 0, 0,
8920
8921 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8922 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8923 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8924 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8925
8926 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8927 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8928 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8929 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8930
8931 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8932 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8933 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8934 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8935
8936 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8937 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8938 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8939 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8940 };
8941
8942 #ifdef MAC_OSX
8943 /* Table for translating Mac keycode with the laptop `fn' key to that
8944 without it. Destination symbols in comments are keys on US
8945 keyboard, and they may not be the same on other types of keyboards.
8946 If the destination is identical to the source (f1 ... f12), it
8947 doesn't map `fn' key to a modifier. */
8948 static const unsigned char fn_keycode_to_keycode_table[] = {
8949 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8950 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8951 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8952
8953 /*0x30*/ 0, 0, 0, 0,
8954 /*0x34*/ 0, 0, 0, 0,
8955 /*0x38*/ 0, 0, 0, 0,
8956 /*0x3C*/ 0, 0, 0, 0,
8957
8958 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8959 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8960 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8961 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8962
8963 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8964 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8965 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8966 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8967
8968 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8969 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8970 /*0x68*/ 0, 0, 0, 0,
8971 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8972
8973 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
8974 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8975 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
8976 /*0x7C*/ 0, 0, 0, 0
8977 };
8978 #endif /* MAC_OSX */
8979
8980 static int
8981 #if USE_CARBON_EVENTS
8982 mac_to_emacs_modifiers (UInt32 mods)
8983 #else
8984 mac_to_emacs_modifiers (EventModifiers mods)
8985 #endif
8986 {
8987 unsigned int result = 0;
8988 if (mods & shiftKey)
8989 result |= shift_modifier;
8990
8991 /* Deactivated to simplify configuration:
8992 if Vmac_option_modifier is non-NIL, we fully process the Option
8993 key. Otherwise, we only process it if an additional Ctrl or Command
8994 is pressed. That way the system may convert the character to a
8995 composed one.
8996 if ((mods & optionKey) &&
8997 (( !NILP(Vmac_option_modifier) ||
8998 ((mods & cmdKey) || (mods & controlKey))))) */
8999
9000 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
9001 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
9002 if (INTEGERP(val))
9003 result |= XUINT(val);
9004 }
9005 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
9006 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
9007 if (INTEGERP(val))
9008 result |= XUINT(val);
9009 }
9010 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
9011 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
9012 if (INTEGERP(val))
9013 result |= XUINT(val);
9014 }
9015
9016 #ifdef MAC_OSX
9017 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
9018 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
9019 if (INTEGERP(val))
9020 result |= XUINT(val);
9021 }
9022 #endif
9023
9024 return result;
9025 }
9026
9027 static UInt32
9028 mac_mapped_modifiers (modifiers)
9029 UInt32 modifiers;
9030 {
9031 UInt32 mapped_modifiers_all =
9032 (NILP (Vmac_control_modifier) ? 0 : controlKey)
9033 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
9034 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
9035
9036 #ifdef MAC_OSX
9037 mapped_modifiers_all |=
9038 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
9039 #endif
9040
9041 return mapped_modifiers_all & modifiers;
9042 }
9043
9044 static int
9045 mac_get_emulated_btn ( UInt32 modifiers )
9046 {
9047 int result = 0;
9048 if (!NILP (Vmac_emulate_three_button_mouse)) {
9049 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
9050 if (modifiers & cmdKey)
9051 result = cmdIs3 ? 2 : 1;
9052 else if (modifiers & optionKey)
9053 result = cmdIs3 ? 1 : 2;
9054 }
9055 return result;
9056 }
9057
9058 #if TARGET_API_MAC_CARBON
9059 /***** Code to handle C-g testing *****/
9060 extern int quit_char;
9061 extern int make_ctrl_char P_ ((int));
9062
9063 int
9064 mac_quit_char_key_p (modifiers, key_code)
9065 UInt32 modifiers, key_code;
9066 {
9067 UInt32 char_code;
9068 unsigned long some_state = 0;
9069 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9070 int c, emacs_modifiers;
9071
9072 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9073 key_code |= (modifiers & ~(mac_mapped_modifiers (modifiers)));
9074 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
9075 if (char_code & ~0xff)
9076 return 0;
9077
9078 emacs_modifiers = mac_to_emacs_modifiers (modifiers);
9079 if (emacs_modifiers & ctrl_modifier)
9080 c = make_ctrl_char (char_code);
9081
9082 c |= (emacs_modifiers
9083 & (meta_modifier | alt_modifier
9084 | hyper_modifier | super_modifier));
9085
9086 return c == quit_char;
9087 }
9088 #endif
9089
9090 #if USE_CARBON_EVENTS
9091 /* Obtains the event modifiers from the event ref and then calls
9092 mac_to_emacs_modifiers. */
9093 static int
9094 mac_event_to_emacs_modifiers (EventRef eventRef)
9095 {
9096 UInt32 mods = 0;
9097 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
9098 sizeof (UInt32), NULL, &mods);
9099 if (!NILP (Vmac_emulate_three_button_mouse) &&
9100 GetEventClass(eventRef) == kEventClassMouse)
9101 {
9102 mods &= ~(optionKey | cmdKey);
9103 }
9104 return mac_to_emacs_modifiers (mods);
9105 }
9106
9107 /* Given an event ref, return the code to use for the mouse button
9108 code in the emacs input_event. */
9109 static int
9110 mac_get_mouse_btn (EventRef ref)
9111 {
9112 EventMouseButton result = kEventMouseButtonPrimary;
9113 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
9114 sizeof (EventMouseButton), NULL, &result);
9115 switch (result)
9116 {
9117 case kEventMouseButtonPrimary:
9118 if (NILP (Vmac_emulate_three_button_mouse))
9119 return 0;
9120 else {
9121 UInt32 mods = 0;
9122 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
9123 sizeof (UInt32), NULL, &mods);
9124 return mac_get_emulated_btn(mods);
9125 }
9126 case kEventMouseButtonSecondary:
9127 return mac_wheel_button_is_mouse_2 ? 2 : 1;
9128 case kEventMouseButtonTertiary:
9129 case 4: /* 4 is the number for the mouse wheel button */
9130 return mac_wheel_button_is_mouse_2 ? 1 : 2;
9131 default:
9132 return 0;
9133 }
9134 }
9135
9136 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9137 events. However the click of the mouse wheel is not converted to a
9138 mouseDown or mouseUp event. Likewise for dead key down events.
9139 This calls ConvertEventRef, but then checks to see if it is a mouse
9140 up/down, or a dead key down carbon event that has not been
9141 converted, and if so, converts it by hand (to be picked up in the
9142 XTread_socket loop). */
9143 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
9144 {
9145 OSStatus err;
9146 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
9147
9148 if (result)
9149 return result;
9150
9151 switch (GetEventClass (eventRef))
9152 {
9153 case kEventClassMouse:
9154 switch (GetEventKind (eventRef))
9155 {
9156 case kEventMouseDown:
9157 eventRec->what = mouseDown;
9158 result = 1;
9159 break;
9160
9161 case kEventMouseUp:
9162 eventRec->what = mouseUp;
9163 result = 1;
9164 break;
9165
9166 default:
9167 break;
9168 }
9169 break;
9170
9171 case kEventClassKeyboard:
9172 switch (GetEventKind (eventRef))
9173 {
9174 case kEventRawKeyDown:
9175 {
9176 unsigned char char_codes;
9177 UInt32 key_code;
9178
9179 err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
9180 typeChar, NULL, sizeof (char),
9181 NULL, &char_codes);
9182 if (err == noErr)
9183 err = GetEventParameter (eventRef, kEventParamKeyCode,
9184 typeUInt32, NULL, sizeof (UInt32),
9185 NULL, &key_code);
9186 if (err == noErr)
9187 {
9188 eventRec->what = keyDown;
9189 eventRec->message = char_codes | ((key_code & 0xff) << 8);
9190 result = 1;
9191 }
9192 }
9193 break;
9194
9195 default:
9196 break;
9197 }
9198 break;
9199
9200 default:
9201 break;
9202 }
9203
9204 if (result)
9205 {
9206 /* Need where and when. */
9207 UInt32 mods = 0;
9208
9209 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
9210 NULL, sizeof (Point), NULL, &eventRec->where);
9211 /* Use two step process because new event modifiers are 32-bit
9212 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9213 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
9214 NULL, sizeof (UInt32), NULL, &mods);
9215 eventRec->modifiers = mods;
9216
9217 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
9218 }
9219
9220 return result;
9221 }
9222
9223 #endif
9224
9225 #ifdef MAC_OS8
9226 static void
9227 do_get_menus (void)
9228 {
9229 Handle menubar_handle;
9230 MenuHandle menu_handle;
9231
9232 menubar_handle = GetNewMBar (128);
9233 if(menubar_handle == NULL)
9234 abort ();
9235 SetMenuBar (menubar_handle);
9236 DrawMenuBar ();
9237
9238 #if !TARGET_API_MAC_CARBON
9239 menu_handle = GetMenuHandle (M_APPLE);
9240 if(menu_handle != NULL)
9241 AppendResMenu (menu_handle,'DRVR');
9242 else
9243 abort ();
9244 #endif
9245 }
9246
9247
9248 static void
9249 do_init_managers (void)
9250 {
9251 #if !TARGET_API_MAC_CARBON
9252 InitGraf (&qd.thePort);
9253 InitFonts ();
9254 FlushEvents (everyEvent, 0);
9255 InitWindows ();
9256 InitMenus ();
9257 TEInit ();
9258 InitDialogs (NULL);
9259 #endif /* !TARGET_API_MAC_CARBON */
9260 InitCursor ();
9261
9262 #if !TARGET_API_MAC_CARBON
9263 /* set up some extra stack space for use by emacs */
9264 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
9265
9266 /* MaxApplZone must be called for AppleScript to execute more
9267 complicated scripts */
9268 MaxApplZone ();
9269 MoreMasters ();
9270 #endif /* !TARGET_API_MAC_CARBON */
9271 }
9272
9273 static void
9274 do_check_ram_size (void)
9275 {
9276 SInt32 physical_ram_size, logical_ram_size;
9277
9278 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
9279 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
9280 || physical_ram_size > (1 << VALBITS)
9281 || logical_ram_size > (1 << VALBITS))
9282 {
9283 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
9284 exit (1);
9285 }
9286 }
9287 #endif /* MAC_OS8 */
9288
9289 static void
9290 do_window_update (WindowPtr win)
9291 {
9292 struct frame *f = mac_window_to_frame (win);
9293
9294 BeginUpdate (win);
9295
9296 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
9297 below. */
9298 if (win != tip_window)
9299 {
9300 if (f->async_visible == 0)
9301 {
9302 /* Update events may occur when a frame gets iconified. */
9303 #if 0
9304 f->async_visible = 1;
9305 f->async_iconified = 0;
9306 SET_FRAME_GARBAGED (f);
9307 #endif
9308 }
9309 else
9310 {
9311 Rect r;
9312 #if TARGET_API_MAC_CARBON
9313 RgnHandle region = NewRgn ();
9314
9315 GetPortVisibleRegion (GetWindowPort (win), region);
9316 GetRegionBounds (region, &r);
9317 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
9318 #if USE_CG_DRAWING
9319 mac_prepare_for_quickdraw (f);
9320 #endif
9321 UpdateControls (win, region);
9322 DisposeRgn (region);
9323 #else
9324 r = (*win->visRgn)->rgnBBox;
9325 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
9326 UpdateControls (win, win->visRgn);
9327 #endif
9328 }
9329 }
9330
9331 EndUpdate (win);
9332 }
9333
9334 static int
9335 is_emacs_window (WindowPtr win)
9336 {
9337 Lisp_Object tail, frame;
9338
9339 if (!win)
9340 return 0;
9341
9342 FOR_EACH_FRAME (tail, frame)
9343 if (FRAME_MAC_P (XFRAME (frame)))
9344 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
9345 return 1;
9346
9347 return 0;
9348 }
9349
9350 #if USE_MAC_TSM
9351 static OSStatus
9352 mac_tsm_resume ()
9353 {
9354 OSStatus err;
9355 ScriptLanguageRecord slrec, *slptr = NULL;
9356
9357 err = ActivateTSMDocument (tsm_document_id);
9358
9359 if (err == noErr)
9360 {
9361 if (EQ (Vmac_ts_script_language_on_focus, Qt)
9362 && EQ (saved_ts_script_language_on_focus, Qt))
9363 slptr = &saved_ts_language;
9364 else if (CONSP (Vmac_ts_script_language_on_focus)
9365 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
9366 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
9367 && CONSP (saved_ts_script_language_on_focus)
9368 && EQ (XCAR (saved_ts_script_language_on_focus),
9369 XCAR (Vmac_ts_script_language_on_focus))
9370 && EQ (XCDR (saved_ts_script_language_on_focus),
9371 XCDR (Vmac_ts_script_language_on_focus)))
9372 {
9373 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
9374 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
9375 slptr = &slrec;
9376 }
9377 }
9378
9379 if (slptr)
9380 {
9381 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9382 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
9383 kKeyboardInputMethodClass);
9384 #else
9385 err = SetDefaultInputMethod (saved_ts_component, slptr);
9386 #endif
9387 if (err == noErr)
9388 err = SetTextServiceLanguage (slptr);
9389
9390 /* Seems to be needed on Mac OS X 10.2. */
9391 if (err == noErr)
9392 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
9393 }
9394
9395 return err;
9396 }
9397
9398 static OSStatus
9399 mac_tsm_suspend ()
9400 {
9401 OSStatus err;
9402 ScriptLanguageRecord slrec, *slptr = NULL;
9403
9404 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
9405
9406 if (EQ (Vmac_ts_script_language_on_focus, Qt))
9407 {
9408 err = GetTextServiceLanguage (&saved_ts_language);
9409 if (err == noErr)
9410 slptr = &saved_ts_language;
9411 }
9412 else if (CONSP (Vmac_ts_script_language_on_focus)
9413 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
9414 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
9415 {
9416 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
9417 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
9418 slptr = &slrec;
9419 }
9420
9421 if (slptr)
9422 {
9423 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9424 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
9425 kKeyboardInputMethodClass);
9426 #else
9427 GetDefaultInputMethod (&saved_ts_component, slptr);
9428 #endif
9429 }
9430
9431 err = DeactivateTSMDocument (tsm_document_id);
9432
9433 return err;
9434 }
9435 #endif
9436
9437 #if !TARGET_API_MAC_CARBON
9438 void
9439 do_apple_menu (SInt16 menu_item)
9440 {
9441 Str255 item_name;
9442 SInt16 da_driver_refnum;
9443
9444 if (menu_item == I_ABOUT)
9445 NoteAlert (ABOUT_ALERT_ID, NULL);
9446 else
9447 {
9448 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
9449 da_driver_refnum = OpenDeskAcc (item_name);
9450 }
9451 }
9452 #endif /* !TARGET_API_MAC_CARBON */
9453
9454 /* Handle drags in size box. Based on code contributed by Ben
9455 Mesander and IM - Window Manager A. */
9456
9457 static void
9458 do_grow_window (w, e)
9459 WindowPtr w;
9460 const EventRecord *e;
9461 {
9462 Rect limit_rect;
9463 int rows, columns, width, height;
9464 struct frame *f = mac_window_to_frame (w);
9465 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
9466 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
9467 #if TARGET_API_MAC_CARBON
9468 Rect new_rect;
9469 #else
9470 long grow_size;
9471 #endif
9472
9473 if (size_hints->flags & PMinSize)
9474 {
9475 min_width = size_hints->min_width;
9476 min_height = size_hints->min_height;
9477 }
9478 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
9479
9480 #if TARGET_API_MAC_CARBON
9481 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
9482 return;
9483 height = new_rect.bottom - new_rect.top;
9484 width = new_rect.right - new_rect.left;
9485 #else
9486 grow_size = GrowWindow (w, e->where, &limit_rect);
9487 /* see if it really changed size */
9488 if (grow_size == 0)
9489 return;
9490 height = HiWord (grow_size);
9491 width = LoWord (grow_size);
9492 #endif
9493
9494 if (width != FRAME_PIXEL_WIDTH (f)
9495 || height != FRAME_PIXEL_HEIGHT (f))
9496 {
9497 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
9498 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
9499
9500 x_set_window_size (f, 0, columns, rows);
9501 }
9502 }
9503
9504
9505 #if TARGET_API_MAC_CARBON
9506 static Point
9507 mac_get_ideal_size (f)
9508 struct frame *f;
9509 {
9510 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9511 WindowPtr w = FRAME_MAC_WINDOW (f);
9512 Point ideal_size;
9513 Rect standard_rect;
9514 int height, width, columns, rows;
9515
9516 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
9517 ideal_size.v = dpyinfo->height;
9518 IsWindowInStandardState (w, &ideal_size, &standard_rect);
9519 /* Adjust the standard size according to character boundaries. */
9520 width = standard_rect.right - standard_rect.left;
9521 height = standard_rect.bottom - standard_rect.top;
9522 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
9523 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
9524 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
9525 ideal_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
9526
9527 return ideal_size;
9528 }
9529 #endif
9530
9531 /* Handle clicks in zoom box. Calculation of "standard state" based
9532 on code in IM - Window Manager A and code contributed by Ben
9533 Mesander. The standard state of an Emacs window is 80-characters
9534 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9535
9536 static void
9537 do_zoom_window (WindowPtr w, int zoom_in_or_out)
9538 {
9539 Rect zoom_rect, port_rect;
9540 int width, height;
9541 struct frame *f = mac_window_to_frame (w);
9542 #if TARGET_API_MAC_CARBON
9543 Point ideal_size = mac_get_ideal_size (f);
9544
9545 GetWindowBounds (w, kWindowContentRgn, &port_rect);
9546 if (IsWindowInStandardState (w, &ideal_size, &zoom_rect)
9547 && port_rect.left == zoom_rect.left
9548 && port_rect.top == zoom_rect.top)
9549 zoom_in_or_out = inZoomIn;
9550 else
9551 zoom_in_or_out = inZoomOut;
9552
9553 #ifdef MAC_OS8
9554 mac_clear_window (f);
9555 #endif
9556 ZoomWindowIdeal (w, zoom_in_or_out, &ideal_size);
9557 #else /* not TARGET_API_MAC_CARBON */
9558 GrafPtr save_port;
9559 Point top_left;
9560 int w_title_height, rows;
9561 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9562
9563 GetPort (&save_port);
9564
9565 SetPortWindowPort (w);
9566
9567 /* Clear window to avoid flicker. */
9568 EraseRect (&(w->portRect));
9569 if (zoom_in_or_out == inZoomOut)
9570 {
9571 SetPt (&top_left, w->portRect.left, w->portRect.top);
9572 LocalToGlobal (&top_left);
9573
9574 /* calculate height of window's title bar */
9575 w_title_height = top_left.v - 1
9576 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
9577
9578 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9579 zoom_rect = qd.screenBits.bounds;
9580 zoom_rect.top += w_title_height;
9581 InsetRect (&zoom_rect, 8, 4); /* not too tight */
9582
9583 zoom_rect.right = zoom_rect.left
9584 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
9585
9586 /* Adjust the standard size according to character boundaries. */
9587 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
9588 zoom_rect.bottom =
9589 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
9590
9591 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
9592 = zoom_rect;
9593 }
9594
9595 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
9596
9597 SetPort (save_port);
9598 #endif /* not TARGET_API_MAC_CARBON */
9599
9600 #if !USE_CARBON_EVENTS
9601 /* retrieve window size and update application values */
9602 #if TARGET_API_MAC_CARBON
9603 GetWindowPortBounds (w, &port_rect);
9604 #else
9605 port_rect = w->portRect;
9606 #endif
9607 height = port_rect.bottom - port_rect.top;
9608 width = port_rect.right - port_rect.left;
9609
9610 mac_handle_size_change (f, width, height);
9611 mac_handle_origin_change (f);
9612 #endif
9613 }
9614
9615 void
9616 mac_store_apple_event (class, id, desc)
9617 Lisp_Object class, id;
9618 const AEDesc *desc;
9619 {
9620 struct input_event buf;
9621
9622 EVENT_INIT (buf);
9623
9624 buf.kind = MAC_APPLE_EVENT;
9625 buf.x = class;
9626 buf.y = id;
9627 XSETFRAME (buf.frame_or_window,
9628 mac_focus_frame (&one_mac_display_info));
9629 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9630 is safe to use them during read_socket_hook. */
9631 buf.arg = mac_aedesc_to_lisp (desc);
9632 kbd_buffer_store_event (&buf);
9633 }
9634
9635 #if TARGET_API_MAC_CARBON
9636 static OSStatus
9637 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
9638 event, num_params, names, types)
9639 AEEventClass class;
9640 AEEventID id;
9641 Lisp_Object class_key, id_key;
9642 EventRef event;
9643 UInt32 num_params;
9644 const EventParamName *names;
9645 const EventParamType *types;
9646 {
9647 OSStatus err = eventNotHandledErr;
9648 Lisp_Object binding;
9649
9650 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
9651 if (!NILP (binding) && !EQ (binding, Qundefined))
9652 {
9653 if (INTEGERP (binding))
9654 err = XINT (binding);
9655 else
9656 {
9657 AppleEvent apple_event;
9658 err = create_apple_event_from_event_ref (event, num_params,
9659 names, types,
9660 &apple_event);
9661 if (err == noErr)
9662 {
9663 mac_store_apple_event (class_key, id_key, &apple_event);
9664 AEDisposeDesc (&apple_event);
9665 mac_wakeup_from_rne ();
9666 }
9667 }
9668 }
9669
9670 return err;
9671 }
9672
9673 void
9674 mac_store_drag_event (window, mouse_pos, modifiers, desc)
9675 WindowRef window;
9676 Point mouse_pos;
9677 SInt16 modifiers;
9678 const AEDesc *desc;
9679 {
9680 struct input_event buf;
9681
9682 EVENT_INIT (buf);
9683
9684 buf.kind = DRAG_N_DROP_EVENT;
9685 buf.modifiers = mac_to_emacs_modifiers (modifiers);
9686 buf.timestamp = TickCount () * (1000 / 60);
9687 XSETINT (buf.x, mouse_pos.h);
9688 XSETINT (buf.y, mouse_pos.v);
9689 XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
9690 buf.arg = mac_aedesc_to_lisp (desc);
9691 kbd_buffer_store_event (&buf);
9692 }
9693 #endif
9694
9695 #if USE_CARBON_EVENTS
9696 static pascal OSStatus
9697 mac_handle_command_event (next_handler, event, data)
9698 EventHandlerCallRef next_handler;
9699 EventRef event;
9700 void *data;
9701 {
9702 OSStatus result, err;
9703 HICommand command;
9704 static const EventParamName names[] =
9705 {kEventParamDirectObject, kEventParamKeyModifiers};
9706 static const EventParamType types[] =
9707 {typeHICommand, typeUInt32};
9708 int num_params = sizeof (names) / sizeof (names[0]);
9709
9710 result = CallNextEventHandler (next_handler, event);
9711 if (result != eventNotHandledErr)
9712 return result;
9713
9714 err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
9715 NULL, sizeof (HICommand), NULL, &command);
9716
9717 if (err != noErr || command.commandID == 0)
9718 return eventNotHandledErr;
9719
9720 /* A HI command event is mapped to an Apple event whose event class
9721 symbol is `hi-command' and event ID is its command ID. */
9722 err = mac_store_event_ref_as_apple_event (0, command.commandID,
9723 Qhi_command, Qnil,
9724 event, num_params, names, types);
9725 return err == noErr ? noErr : eventNotHandledErr;
9726 }
9727
9728 static OSStatus
9729 init_command_handler ()
9730 {
9731 static const EventTypeSpec specs[] =
9732 {{kEventClassCommand, kEventCommandProcess}};
9733 static EventHandlerUPP handle_command_eventUPP = NULL;
9734
9735 if (handle_command_eventUPP == NULL)
9736 handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event);
9737 return InstallApplicationEventHandler (handle_command_eventUPP,
9738 GetEventTypeCount (specs), specs,
9739 NULL, NULL);
9740 }
9741
9742 static pascal OSStatus
9743 mac_handle_window_event (next_handler, event, data)
9744 EventHandlerCallRef next_handler;
9745 EventRef event;
9746 void *data;
9747 {
9748 WindowPtr wp;
9749 OSStatus result, err;
9750 struct frame *f;
9751 UInt32 attributes;
9752 XSizeHints *size_hints;
9753
9754 err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
9755 NULL, sizeof (WindowPtr), NULL, &wp);
9756 if (err != noErr)
9757 return eventNotHandledErr;
9758
9759 f = mac_window_to_frame (wp);
9760 switch (GetEventKind (event))
9761 {
9762 case kEventWindowUpdate:
9763 result = CallNextEventHandler (next_handler, event);
9764 if (result != eventNotHandledErr)
9765 return result;
9766
9767 do_window_update (wp);
9768 return noErr;
9769
9770 case kEventWindowGetIdealSize:
9771 result = CallNextEventHandler (next_handler, event);
9772 if (result != eventNotHandledErr)
9773 return result;
9774
9775 {
9776 Point ideal_size = mac_get_ideal_size (f);
9777
9778 err = SetEventParameter (event, kEventParamDimensions,
9779 typeQDPoint, sizeof (Point), &ideal_size);
9780 if (err == noErr)
9781 return noErr;
9782 }
9783 break;
9784
9785 case kEventWindowBoundsChanging:
9786 result = CallNextEventHandler (next_handler, event);
9787 if (result != eventNotHandledErr)
9788 return result;
9789
9790 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
9791 NULL, sizeof (UInt32), NULL, &attributes);
9792 if (err != noErr)
9793 break;
9794
9795 size_hints = FRAME_SIZE_HINTS (f);
9796 if ((attributes & kWindowBoundsChangeUserResize)
9797 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
9798 == (PResizeInc | PBaseSize | PMinSize)))
9799 {
9800 Rect bounds;
9801 int width, height;
9802
9803 err = GetEventParameter (event, kEventParamCurrentBounds,
9804 typeQDRectangle, NULL, sizeof (Rect),
9805 NULL, &bounds);
9806 if (err != noErr)
9807 break;
9808
9809 width = bounds.right - bounds.left;
9810 height = bounds.bottom - bounds.top;
9811
9812 if (width < size_hints->min_width)
9813 width = size_hints->min_width;
9814 else
9815 width = size_hints->base_width
9816 + (int) ((width - size_hints->base_width)
9817 / (float) size_hints->width_inc + .5)
9818 * size_hints->width_inc;
9819
9820 if (height < size_hints->min_height)
9821 height = size_hints->min_height;
9822 else
9823 height = size_hints->base_height
9824 + (int) ((height - size_hints->base_height)
9825 / (float) size_hints->height_inc + .5)
9826 * size_hints->height_inc;
9827
9828 bounds.right = bounds.left + width;
9829 bounds.bottom = bounds.top + height;
9830 SetEventParameter (event, kEventParamCurrentBounds,
9831 typeQDRectangle, sizeof (Rect), &bounds);
9832 return noErr;
9833 }
9834 break;
9835
9836 case kEventWindowBoundsChanged:
9837 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
9838 NULL, sizeof (UInt32), NULL, &attributes);
9839 if (err != noErr)
9840 break;
9841
9842 if (attributes & kWindowBoundsChangeSizeChanged)
9843 {
9844 Rect bounds;
9845
9846 err = GetEventParameter (event, kEventParamCurrentBounds,
9847 typeQDRectangle, NULL, sizeof (Rect),
9848 NULL, &bounds);
9849 if (err == noErr)
9850 {
9851 int width, height;
9852
9853 width = bounds.right - bounds.left;
9854 height = bounds.bottom - bounds.top;
9855 mac_handle_size_change (f, width, height);
9856 }
9857 }
9858
9859 if (attributes & kWindowBoundsChangeOriginChanged)
9860 mac_handle_origin_change (f);
9861
9862 return noErr;
9863
9864 case kEventWindowShown:
9865 case kEventWindowHidden:
9866 case kEventWindowExpanded:
9867 case kEventWindowCollapsed:
9868 result = CallNextEventHandler (next_handler, event);
9869
9870 mac_handle_visibility_change (f);
9871 return noErr;
9872
9873 break;
9874
9875 case kEventWindowClose:
9876 result = CallNextEventHandler (next_handler, event);
9877 {
9878 struct input_event buf;
9879
9880 EVENT_INIT (buf);
9881 buf.kind = DELETE_WINDOW_EVENT;
9882 XSETFRAME (buf.frame_or_window, f);
9883 buf.arg = Qnil;
9884 kbd_buffer_store_event (&buf);
9885 }
9886 return noErr;
9887
9888 #ifdef MAC_OSX
9889 case kEventWindowToolbarSwitchMode:
9890 result = CallNextEventHandler (next_handler, event);
9891 {
9892 static const EventParamName names[] = {kEventParamDirectObject,
9893 kEventParamWindowMouseLocation,
9894 kEventParamKeyModifiers,
9895 kEventParamMouseButton,
9896 kEventParamClickCount,
9897 kEventParamMouseChord};
9898 static const EventParamType types[] = {typeWindowRef,
9899 typeQDPoint,
9900 typeUInt32,
9901 typeMouseButton,
9902 typeUInt32,
9903 typeUInt32};
9904 int num_params = sizeof (names) / sizeof (names[0]);
9905
9906 err = mac_store_event_ref_as_apple_event (0, 0,
9907 Qwindow,
9908 Qtoolbar_switch_mode,
9909 event, num_params,
9910 names, types);
9911 }
9912 return err == noErr ? noErr : result;
9913 #endif
9914
9915 #if USE_MAC_TSM
9916 case kEventWindowFocusAcquired:
9917 result = CallNextEventHandler (next_handler, event);
9918 err = mac_tsm_resume ();
9919 return err == noErr ? noErr : result;
9920
9921 case kEventWindowFocusRelinquish:
9922 result = CallNextEventHandler (next_handler, event);
9923 err = mac_tsm_suspend ();
9924 return err == noErr ? noErr : result;
9925 #endif
9926 }
9927
9928 return eventNotHandledErr;
9929 }
9930
9931 static pascal OSStatus
9932 mac_handle_mouse_event (next_handler, event, data)
9933 EventHandlerCallRef next_handler;
9934 EventRef event;
9935 void *data;
9936 {
9937 OSStatus result, err;
9938
9939 switch (GetEventKind (event))
9940 {
9941 case kEventMouseWheelMoved:
9942 {
9943 WindowPtr wp;
9944 struct frame *f;
9945 EventMouseWheelAxis axis;
9946 SInt32 delta;
9947 Point point;
9948
9949 result = CallNextEventHandler (next_handler, event);
9950 if (result != eventNotHandledErr || read_socket_inev == NULL)
9951 return result;
9952
9953 err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
9954 NULL, sizeof (WindowRef), NULL, &wp);
9955 if (err != noErr)
9956 break;
9957
9958 f = mac_window_to_frame (wp);
9959 if (f != mac_focus_frame (&one_mac_display_info))
9960 break;
9961
9962 err = GetEventParameter (event, kEventParamMouseWheelAxis,
9963 typeMouseWheelAxis, NULL,
9964 sizeof (EventMouseWheelAxis), NULL, &axis);
9965 if (err != noErr || axis != kEventMouseWheelAxisY)
9966 break;
9967
9968 err = GetEventParameter (event, kEventParamMouseWheelDelta,
9969 typeSInt32, NULL, sizeof (SInt32),
9970 NULL, &delta);
9971 if (err != noErr)
9972 break;
9973 err = GetEventParameter (event, kEventParamMouseLocation,
9974 typeQDPoint, NULL, sizeof (Point),
9975 NULL, &point);
9976 if (err != noErr)
9977 break;
9978 read_socket_inev->kind = WHEEL_EVENT;
9979 read_socket_inev->code = 0;
9980 read_socket_inev->modifiers =
9981 (mac_event_to_emacs_modifiers (event)
9982 | ((delta < 0) ? down_modifier : up_modifier));
9983 SetPortWindowPort (wp);
9984 GlobalToLocal (&point);
9985 XSETINT (read_socket_inev->x, point.h);
9986 XSETINT (read_socket_inev->y, point.v);
9987 XSETFRAME (read_socket_inev->frame_or_window, f);
9988
9989 return noErr;
9990 }
9991 break;
9992
9993 default:
9994 break;
9995 }
9996
9997 return eventNotHandledErr;
9998 }
9999
10000 #if USE_MAC_FONT_PANEL
10001 static pascal OSStatus
10002 mac_handle_font_event (next_handler, event, data)
10003 EventHandlerCallRef next_handler;
10004 EventRef event;
10005 void *data;
10006 {
10007 OSStatus result, err;
10008 Lisp_Object id_key;
10009 int num_params;
10010 const EventParamName *names;
10011 const EventParamType *types;
10012 static const EventParamName names_sel[] = {kEventParamATSUFontID,
10013 kEventParamATSUFontSize,
10014 kEventParamFMFontFamily,
10015 kEventParamFMFontSize,
10016 kEventParamFontColor};
10017 static const EventParamType types_sel[] = {typeATSUFontID,
10018 typeATSUSize,
10019 typeFMFontFamily,
10020 typeFMFontSize,
10021 typeFontColor};
10022
10023 result = CallNextEventHandler (next_handler, event);
10024 if (result != eventNotHandledErr)
10025 return result;
10026
10027 switch (GetEventKind (event))
10028 {
10029 case kEventFontPanelClosed:
10030 id_key = Qpanel_closed;
10031 num_params = 0;
10032 names = NULL;
10033 types = NULL;
10034 break;
10035
10036 case kEventFontSelection:
10037 id_key = Qselection;
10038 num_params = sizeof (names_sel) / sizeof (names_sel[0]);
10039 names = names_sel;
10040 types = types_sel;
10041 break;
10042 }
10043
10044 err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
10045 event, num_params,
10046 names, types);
10047
10048 return err == noErr ? noErr : eventNotHandledErr;
10049 }
10050 #endif
10051
10052 #if USE_MAC_TSM
10053 static pascal OSStatus
10054 mac_handle_text_input_event (next_handler, event, data)
10055 EventHandlerCallRef next_handler;
10056 EventRef event;
10057 void *data;
10058 {
10059 OSStatus result, err = noErr;
10060 Lisp_Object id_key = Qnil;
10061 int num_params;
10062 const EventParamName *names;
10063 const EventParamType *types;
10064 static UInt32 seqno_uaia = 0;
10065 static const EventParamName names_uaia[] =
10066 {kEventParamTextInputSendComponentInstance,
10067 kEventParamTextInputSendRefCon,
10068 kEventParamTextInputSendSLRec,
10069 kEventParamTextInputSendFixLen,
10070 kEventParamTextInputSendText,
10071 kEventParamTextInputSendUpdateRng,
10072 kEventParamTextInputSendHiliteRng,
10073 kEventParamTextInputSendClauseRng,
10074 kEventParamTextInputSendPinRng,
10075 kEventParamTextInputSendTextServiceEncoding,
10076 kEventParamTextInputSendTextServiceMacEncoding,
10077 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
10078 static const EventParamType types_uaia[] =
10079 {typeComponentInstance,
10080 typeLongInteger,
10081 typeIntlWritingCode,
10082 typeLongInteger,
10083 #ifdef MAC_OSX
10084 typeUnicodeText,
10085 #else
10086 typeChar,
10087 #endif
10088 typeTextRangeArray,
10089 typeTextRangeArray,
10090 typeOffsetArray,
10091 typeTextRange,
10092 typeUInt32,
10093 typeUInt32,
10094 typeUInt32};
10095 static const EventParamName names_ufke[] =
10096 {kEventParamTextInputSendComponentInstance,
10097 kEventParamTextInputSendRefCon,
10098 kEventParamTextInputSendSLRec,
10099 kEventParamTextInputSendText};
10100 static const EventParamType types_ufke[] =
10101 {typeComponentInstance,
10102 typeLongInteger,
10103 typeIntlWritingCode,
10104 typeUnicodeText};
10105
10106 result = CallNextEventHandler (next_handler, event);
10107
10108 switch (GetEventKind (event))
10109 {
10110 case kEventTextInputUpdateActiveInputArea:
10111 id_key = Qupdate_active_input_area;
10112 num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
10113 names = names_uaia;
10114 types = types_uaia;
10115 SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
10116 typeUInt32, sizeof (UInt32), &seqno_uaia);
10117 seqno_uaia++;
10118 break;
10119
10120 case kEventTextInputUnicodeForKeyEvent:
10121 {
10122 EventRef kbd_event;
10123 UInt32 actual_size, modifiers, mapped_modifiers;
10124
10125 err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
10126 typeEventRef, NULL, sizeof (EventRef), NULL,
10127 &kbd_event);
10128 if (err == noErr)
10129 err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
10130 typeUInt32, NULL,
10131 sizeof (UInt32), NULL, &modifiers);
10132 if (err == noErr && mac_mapped_modifiers (modifiers))
10133 /* There're mapped modifier keys. Process it in
10134 XTread_socket. */
10135 return eventNotHandledErr;
10136 if (err == noErr)
10137 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
10138 typeUnicodeText, NULL, 0, &actual_size,
10139 NULL);
10140 if (err == noErr && actual_size == sizeof (UniChar))
10141 {
10142 UniChar code;
10143
10144 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
10145 typeUnicodeText, NULL,
10146 sizeof (UniChar), NULL, &code);
10147 if (err == noErr && code < 0x80)
10148 {
10149 /* ASCII character. Process it in XTread_socket. */
10150 if (read_socket_inev && code >= 0x20 && code <= 0x7e)
10151 {
10152 UInt32 key_code;
10153
10154 err = GetEventParameter (kbd_event, kEventParamKeyCode,
10155 typeUInt32, NULL, sizeof (UInt32),
10156 NULL, &key_code);
10157 if (!(err == noErr && key_code <= 0x7f
10158 && keycode_to_xkeysym_table [key_code]))
10159 {
10160 struct frame *f =
10161 mac_focus_frame (&one_mac_display_info);
10162
10163 read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
10164 read_socket_inev->code = code;
10165 read_socket_inev->modifiers =
10166 mac_to_emacs_modifiers (modifiers);
10167 read_socket_inev->modifiers |=
10168 (extra_keyboard_modifiers
10169 & (meta_modifier | alt_modifier
10170 | hyper_modifier | super_modifier));
10171 XSETFRAME (read_socket_inev->frame_or_window, f);
10172 }
10173 }
10174 return eventNotHandledErr;
10175 }
10176 }
10177 }
10178 /* Non-ASCII keystrokes without mapped modifiers are processed
10179 at the Lisp level. */
10180 id_key = Qunicode_for_key_event;
10181 num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
10182 names = names_ufke;
10183 types = types_ufke;
10184 break;
10185
10186 case kEventTextInputOffsetToPos:
10187 {
10188 struct frame *f;
10189 struct window *w;
10190 Point p;
10191
10192 if (!OVERLAYP (Vmac_ts_active_input_overlay))
10193 return eventNotHandledErr;
10194
10195 /* Strictly speaking, this is not always correct because
10196 previous events may change some states about display. */
10197 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
10198 {
10199 /* Active input area is displayed in the echo area. */
10200 w = XWINDOW (echo_area_window);
10201 f = WINDOW_XFRAME (w);
10202 }
10203 else
10204 {
10205 /* Active input area is displayed around the current point. */
10206 f = SELECTED_FRAME ();
10207 w = XWINDOW (f->selected_window);
10208 }
10209
10210 p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
10211 + WINDOW_LEFT_FRINGE_WIDTH (w));
10212 p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
10213 + FONT_BASE (FRAME_FONT (f)));
10214 SetPortWindowPort (FRAME_MAC_WINDOW (f));
10215 LocalToGlobal (&p);
10216 err = SetEventParameter (event, kEventParamTextInputReplyPoint,
10217 typeQDPoint, sizeof (typeQDPoint), &p);
10218 }
10219 break;
10220
10221 default:
10222 abort ();
10223 }
10224
10225 if (!NILP (id_key))
10226 err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
10227 event, num_params,
10228 names, types);
10229
10230 return err == noErr ? noErr : result;
10231 }
10232 #endif
10233
10234 #ifdef MAC_OSX
10235 OSStatus
10236 mac_store_service_event (event)
10237 EventRef event;
10238 {
10239 OSStatus err;
10240 Lisp_Object id_key;
10241 int num_params;
10242 const EventParamName *names;
10243 const EventParamType *types;
10244 static const EventParamName names_pfm[] =
10245 {kEventParamServiceMessageName, kEventParamServiceUserData};
10246 static const EventParamType types_pfm[] =
10247 {typeCFStringRef, typeCFStringRef};
10248
10249 switch (GetEventKind (event))
10250 {
10251 case kEventServicePaste:
10252 id_key = Qpaste;
10253 num_params = 0;
10254 names = NULL;
10255 types = NULL;
10256 break;
10257
10258 case kEventServicePerform:
10259 id_key = Qperform;
10260 num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
10261 names = names_pfm;
10262 types = types_pfm;
10263 break;
10264
10265 default:
10266 abort ();
10267 }
10268
10269 err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
10270 event, num_params,
10271 names, types);
10272
10273 return err;
10274 }
10275 #endif /* MAC_OSX */
10276 #endif /* USE_CARBON_EVENTS */
10277
10278
10279 OSStatus
10280 install_window_handler (window)
10281 WindowPtr window;
10282 {
10283 OSStatus err = noErr;
10284 #if USE_CARBON_EVENTS
10285 static const EventTypeSpec specs_window[] =
10286 {{kEventClassWindow, kEventWindowUpdate},
10287 {kEventClassWindow, kEventWindowGetIdealSize},
10288 {kEventClassWindow, kEventWindowBoundsChanging},
10289 {kEventClassWindow, kEventWindowBoundsChanged},
10290 {kEventClassWindow, kEventWindowShown},
10291 {kEventClassWindow, kEventWindowHidden},
10292 {kEventClassWindow, kEventWindowExpanded},
10293 {kEventClassWindow, kEventWindowCollapsed},
10294 {kEventClassWindow, kEventWindowClose},
10295 #ifdef MAC_OSX
10296 {kEventClassWindow, kEventWindowToolbarSwitchMode},
10297 #endif
10298 #if USE_MAC_TSM
10299 {kEventClassWindow, kEventWindowFocusAcquired},
10300 {kEventClassWindow, kEventWindowFocusRelinquish},
10301 #endif
10302 };
10303 static const EventTypeSpec specs_mouse[] =
10304 {{kEventClassMouse, kEventMouseWheelMoved}};
10305 static EventHandlerUPP handle_window_eventUPP = NULL;
10306 static EventHandlerUPP handle_mouse_eventUPP = NULL;
10307 #if USE_MAC_FONT_PANEL
10308 static const EventTypeSpec specs_font[] =
10309 {{kEventClassFont, kEventFontPanelClosed},
10310 {kEventClassFont, kEventFontSelection}};
10311 static EventHandlerUPP handle_font_eventUPP = NULL;
10312 #endif
10313 #if USE_MAC_TSM
10314 static const EventTypeSpec specs_text_input[] =
10315 {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
10316 {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
10317 {kEventClassTextInput, kEventTextInputOffsetToPos}};
10318 static EventHandlerUPP handle_text_input_eventUPP = NULL;
10319 #endif
10320
10321 if (handle_window_eventUPP == NULL)
10322 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
10323 if (handle_mouse_eventUPP == NULL)
10324 handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
10325 #if USE_MAC_FONT_PANEL
10326 if (handle_font_eventUPP == NULL)
10327 handle_font_eventUPP = NewEventHandlerUPP (mac_handle_font_event);
10328 #endif
10329 #if USE_MAC_TSM
10330 if (handle_text_input_eventUPP == NULL)
10331 handle_text_input_eventUPP =
10332 NewEventHandlerUPP (mac_handle_text_input_event);
10333 #endif
10334 err = InstallWindowEventHandler (window, handle_window_eventUPP,
10335 GetEventTypeCount (specs_window),
10336 specs_window, NULL, NULL);
10337 if (err == noErr)
10338 err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
10339 GetEventTypeCount (specs_mouse),
10340 specs_mouse, NULL, NULL);
10341 #if USE_MAC_FONT_PANEL
10342 if (err == noErr)
10343 err = InstallWindowEventHandler (window, handle_font_eventUPP,
10344 GetEventTypeCount (specs_font),
10345 specs_font, NULL, NULL);
10346 #endif
10347 #if USE_MAC_TSM
10348 if (err == noErr)
10349 err = InstallWindowEventHandler (window, handle_text_input_eventUPP,
10350 GetEventTypeCount (specs_text_input),
10351 specs_text_input, window, NULL);
10352 #endif
10353 #endif
10354 if (err == noErr)
10355 err = install_drag_handler (window);
10356 if (err == noErr)
10357 err = install_menu_target_item_handler (window);
10358
10359 return err;
10360 }
10361
10362 void
10363 remove_window_handler (window)
10364 WindowPtr window;
10365 {
10366 remove_drag_handler (window);
10367 }
10368
10369
10370 #if __profile__
10371 void
10372 profiler_exit_proc ()
10373 {
10374 ProfilerDump ("\pEmacs.prof");
10375 ProfilerTerm ();
10376 }
10377 #endif
10378
10379 /* These few functions implement Emacs as a normal Mac application
10380 (almost): set up the heap and the Toolbox, handle necessary system
10381 events plus a few simple menu events. They also set up Emacs's
10382 access to functions defined in the rest of this file. Emacs uses
10383 function hooks to perform all its terminal I/O. A complete list of
10384 these functions appear in termhooks.h. For what they do, read the
10385 comments there and see also w32term.c and xterm.c. What's
10386 noticeably missing here is the event loop, which is normally
10387 present in most Mac application. After performing the necessary
10388 Mac initializations, main passes off control to emacs_main
10389 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10390 (defined further below) to read input. This is where
10391 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10392
10393 #ifdef MAC_OS8
10394 #undef main
10395 int
10396 main (void)
10397 {
10398 #if __profile__ /* is the profiler on? */
10399 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
10400 exit(1);
10401 #endif
10402
10403 #if __MWERKS__
10404 /* set creator and type for files created by MSL */
10405 _fcreator = MAC_EMACS_CREATOR_CODE;
10406 _ftype = 'TEXT';
10407 #endif
10408
10409 do_init_managers ();
10410
10411 do_get_menus ();
10412
10413 #ifndef USE_LSB_TAG
10414 do_check_ram_size ();
10415 #endif
10416
10417 init_emacs_passwd_dir ();
10418
10419 init_environ ();
10420
10421 init_coercion_handler ();
10422
10423 initialize_applescript ();
10424
10425 init_apple_event_handler ();
10426
10427 {
10428 char **argv;
10429 int argc = 0;
10430
10431 /* set up argv array from STR# resource */
10432 get_string_list (&argv, ARGV_STRING_LIST_ID);
10433 while (argv[argc])
10434 argc++;
10435
10436 /* free up AppleScript resources on exit */
10437 atexit (terminate_applescript);
10438
10439 #if __profile__ /* is the profiler on? */
10440 atexit (profiler_exit_proc);
10441 #endif
10442
10443 /* 3rd param "envp" never used in emacs_main */
10444 (void) emacs_main (argc, argv, 0);
10445 }
10446
10447 /* Never reached - real exit in Fkill_emacs */
10448 return 0;
10449 }
10450 #endif
10451
10452 #if !USE_CARBON_EVENTS
10453 static RgnHandle mouse_region = NULL;
10454
10455 Boolean
10456 mac_wait_next_event (er, sleep_time, dequeue)
10457 EventRecord *er;
10458 UInt32 sleep_time;
10459 Boolean dequeue;
10460 {
10461 static EventRecord er_buf = {nullEvent};
10462 UInt32 target_tick, current_tick;
10463 EventMask event_mask;
10464
10465 if (mouse_region == NULL)
10466 mouse_region = NewRgn ();
10467
10468 event_mask = everyEvent;
10469 if (!mac_ready_for_apple_events)
10470 event_mask -= highLevelEventMask;
10471
10472 current_tick = TickCount ();
10473 target_tick = current_tick + sleep_time;
10474
10475 if (er_buf.what == nullEvent)
10476 while (!WaitNextEvent (event_mask, &er_buf,
10477 target_tick - current_tick, mouse_region))
10478 {
10479 current_tick = TickCount ();
10480 if (target_tick <= current_tick)
10481 return false;
10482 }
10483
10484 *er = er_buf;
10485 if (dequeue)
10486 er_buf.what = nullEvent;
10487 return true;
10488 }
10489 #endif /* not USE_CARBON_EVENTS */
10490
10491 #if TARGET_API_MAC_CARBON
10492 OSStatus
10493 mac_post_mouse_moved_event ()
10494 {
10495 EventRef event = NULL;
10496 OSStatus err;
10497
10498 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
10499 kEventAttributeNone, &event);
10500 if (err == noErr)
10501 {
10502 Point mouse_pos;
10503
10504 GetMouse (&mouse_pos);
10505 LocalToGlobal (&mouse_pos);
10506 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
10507 sizeof (Point), &mouse_pos);
10508 }
10509 if (err == noErr)
10510 {
10511 UInt32 modifiers = GetCurrentKeyModifiers ();
10512
10513 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
10514 sizeof (UInt32), &modifiers);
10515 }
10516 if (err == noErr)
10517 err = PostEventToQueue (GetCurrentEventQueue (), event,
10518 kEventPriorityStandard);
10519 if (event)
10520 ReleaseEvent (event);
10521
10522 return err;
10523 }
10524
10525 static void
10526 mac_set_unicode_keystroke_event (code, buf)
10527 UniChar code;
10528 struct input_event *buf;
10529 {
10530 int charset_id, c1, c2;
10531
10532 if (code < 0x80)
10533 {
10534 buf->kind = ASCII_KEYSTROKE_EVENT;
10535 buf->code = code;
10536 }
10537 else if (code < 0x100)
10538 {
10539 if (code < 0xA0)
10540 charset_id = CHARSET_8_BIT_CONTROL;
10541 else
10542 charset_id = charset_latin_iso8859_1;
10543 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10544 buf->code = MAKE_CHAR (charset_id, code, 0);
10545 }
10546 else
10547 {
10548 if (code < 0x2500)
10549 charset_id = charset_mule_unicode_0100_24ff,
10550 code -= 0x100;
10551 else if (code < 0x33FF)
10552 charset_id = charset_mule_unicode_2500_33ff,
10553 code -= 0x2500;
10554 else if (code >= 0xE000)
10555 charset_id = charset_mule_unicode_e000_ffff,
10556 code -= 0xE000;
10557 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
10558 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10559 buf->code = MAKE_CHAR (charset_id, c1, c2);
10560 }
10561 }
10562 #endif
10563
10564 /* Emacs calls this whenever it wants to read an input event from the
10565 user. */
10566 int
10567 XTread_socket (sd, expected, hold_quit)
10568 int sd, expected;
10569 struct input_event *hold_quit;
10570 {
10571 struct input_event inev;
10572 int count = 0;
10573 #if USE_CARBON_EVENTS
10574 EventRef eventRef;
10575 EventTargetRef toolbox_dispatcher;
10576 #endif
10577 EventRecord er;
10578 struct mac_display_info *dpyinfo = &one_mac_display_info;
10579
10580 if (interrupt_input_blocked)
10581 {
10582 interrupt_input_pending = 1;
10583 return -1;
10584 }
10585
10586 interrupt_input_pending = 0;
10587 BLOCK_INPUT;
10588
10589 /* So people can tell when we have read the available input. */
10590 input_signal_count++;
10591
10592 ++handling_signal;
10593
10594 #if USE_CARBON_EVENTS
10595 toolbox_dispatcher = GetEventDispatcherTarget ();
10596
10597 while (
10598 #if USE_CG_DRAWING
10599 mac_prepare_for_quickdraw (NULL),
10600 #endif
10601 !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
10602 kEventRemoveFromQueue, &eventRef))
10603 #else /* !USE_CARBON_EVENTS */
10604 while (mac_wait_next_event (&er, 0, true))
10605 #endif /* !USE_CARBON_EVENTS */
10606 {
10607 int do_help = 0;
10608 struct frame *f;
10609 unsigned long timestamp;
10610
10611 EVENT_INIT (inev);
10612 inev.kind = NO_EVENT;
10613 inev.arg = Qnil;
10614
10615 #if USE_CARBON_EVENTS
10616 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
10617 #else
10618 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
10619 #endif
10620
10621 #if USE_CARBON_EVENTS
10622 /* Handle new events */
10623 if (!mac_convert_event_ref (eventRef, &er))
10624 {
10625 /* There used to be a handler for the kEventMouseWheelMoved
10626 event here. But as of Mac OS X 10.4, this kind of event
10627 is not directly posted to the main event queue by
10628 two-finger scrolling on the trackpad. Instead, some
10629 private event is posted and it is converted to a wheel
10630 event by the default handler for the application target.
10631 The converted one can be received by a Carbon event
10632 handler installed on a window target. */
10633 read_socket_inev = &inev;
10634 SendEventToEventTarget (eventRef, toolbox_dispatcher);
10635 read_socket_inev = NULL;
10636 }
10637 else
10638 #endif /* USE_CARBON_EVENTS */
10639 switch (er.what)
10640 {
10641 case mouseDown:
10642 case mouseUp:
10643 {
10644 WindowPtr window_ptr;
10645 ControlPartCode part_code;
10646 int tool_bar_p = 0;
10647
10648 #if USE_CARBON_EVENTS
10649 /* This is needed to send mouse events like aqua window
10650 buttons to the correct handler. */
10651 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10652 != eventNotHandledErr)
10653 break;
10654 #endif
10655 last_mouse_glyph_frame = 0;
10656
10657 if (dpyinfo->grabbed && last_mouse_frame
10658 && FRAME_LIVE_P (last_mouse_frame))
10659 {
10660 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
10661 part_code = inContent;
10662 }
10663 else
10664 {
10665 part_code = FindWindow (er.where, &window_ptr);
10666 if (tip_window && window_ptr == tip_window)
10667 {
10668 HideWindow (tip_window);
10669 part_code = FindWindow (er.where, &window_ptr);
10670 }
10671 }
10672
10673 if (er.what != mouseDown &&
10674 (part_code != inContent || dpyinfo->grabbed == 0))
10675 break;
10676
10677 switch (part_code)
10678 {
10679 case inMenuBar:
10680 f = mac_focus_frame (dpyinfo);
10681 saved_menu_event_location = er.where;
10682 inev.kind = MENU_BAR_ACTIVATE_EVENT;
10683 XSETFRAME (inev.frame_or_window, f);
10684 break;
10685
10686 case inContent:
10687 if (
10688 #if TARGET_API_MAC_CARBON
10689 FrontNonFloatingWindow ()
10690 #else
10691 FrontWindow ()
10692 #endif
10693 != window_ptr
10694 || (mac_window_to_frame (window_ptr)
10695 != dpyinfo->x_focus_frame))
10696 SelectWindow (window_ptr);
10697 else
10698 {
10699 ControlPartCode control_part_code;
10700 ControlHandle ch;
10701 Point mouse_loc = er.where;
10702 #ifdef MAC_OSX
10703 ControlKind control_kind;
10704 #endif
10705
10706 f = mac_window_to_frame (window_ptr);
10707 /* convert to local coordinates of new window */
10708 SetPortWindowPort (window_ptr);
10709
10710 GlobalToLocal (&mouse_loc);
10711 #if TARGET_API_MAC_CARBON
10712 ch = FindControlUnderMouse (mouse_loc, window_ptr,
10713 &control_part_code);
10714 #ifdef MAC_OSX
10715 if (ch)
10716 GetControlKind (ch, &control_kind);
10717 #endif
10718 #else
10719 control_part_code = FindControl (mouse_loc, window_ptr,
10720 &ch);
10721 #endif
10722
10723 #if USE_CARBON_EVENTS
10724 inev.code = mac_get_mouse_btn (eventRef);
10725 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
10726 #else
10727 inev.code = mac_get_emulated_btn (er.modifiers);
10728 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
10729 #endif
10730 XSETINT (inev.x, mouse_loc.h);
10731 XSETINT (inev.y, mouse_loc.v);
10732
10733 if ((dpyinfo->grabbed && tracked_scroll_bar)
10734 || (ch != 0
10735 #ifndef USE_TOOLKIT_SCROLL_BARS
10736 /* control_part_code becomes kControlNoPart if
10737 a progress indicator is clicked. */
10738 && control_part_code != kControlNoPart
10739 #else /* USE_TOOLKIT_SCROLL_BARS */
10740 #ifdef MAC_OSX
10741 && control_kind.kind == kControlKindScrollBar
10742 #endif /* MAC_OSX */
10743 #endif /* USE_TOOLKIT_SCROLL_BARS */
10744 ))
10745 {
10746 struct scroll_bar *bar;
10747
10748 if (dpyinfo->grabbed && tracked_scroll_bar)
10749 {
10750 bar = tracked_scroll_bar;
10751 #ifndef USE_TOOLKIT_SCROLL_BARS
10752 control_part_code = kControlIndicatorPart;
10753 #endif
10754 }
10755 else
10756 bar = (struct scroll_bar *) GetControlReference (ch);
10757 #ifdef USE_TOOLKIT_SCROLL_BARS
10758 /* Make the "Ctrl-Mouse-2 splits window" work
10759 for toolkit scroll bars. */
10760 if (er.modifiers & controlKey)
10761 x_scroll_bar_handle_click (bar, control_part_code,
10762 &er, &inev);
10763 else if (er.what == mouseDown)
10764 x_scroll_bar_handle_press (bar, control_part_code,
10765 &inev);
10766 else
10767 x_scroll_bar_handle_release (bar, &inev);
10768 #else /* not USE_TOOLKIT_SCROLL_BARS */
10769 x_scroll_bar_handle_click (bar, control_part_code,
10770 &er, &inev);
10771 if (er.what == mouseDown
10772 && control_part_code == kControlIndicatorPart)
10773 tracked_scroll_bar = bar;
10774 else
10775 tracked_scroll_bar = NULL;
10776 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10777 }
10778 else
10779 {
10780 Lisp_Object window;
10781 int x = mouse_loc.h;
10782 int y = mouse_loc.v;
10783
10784 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
10785 if (EQ (window, f->tool_bar_window))
10786 {
10787 if (er.what == mouseDown)
10788 handle_tool_bar_click (f, x, y, 1, 0);
10789 else
10790 handle_tool_bar_click (f, x, y, 0,
10791 inev.modifiers);
10792 tool_bar_p = 1;
10793 }
10794 else
10795 {
10796 XSETFRAME (inev.frame_or_window, f);
10797 inev.kind = MOUSE_CLICK_EVENT;
10798 }
10799 }
10800
10801 if (er.what == mouseDown)
10802 {
10803 dpyinfo->grabbed |= (1 << inev.code);
10804 last_mouse_frame = f;
10805
10806 if (!tool_bar_p)
10807 last_tool_bar_item = -1;
10808 }
10809 else
10810 {
10811 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
10812 /* If a button is released though it was not
10813 previously pressed, that would be because
10814 of multi-button emulation. */
10815 dpyinfo->grabbed = 0;
10816 else
10817 dpyinfo->grabbed &= ~(1 << inev.code);
10818 }
10819
10820 /* Ignore any mouse motion that happened before
10821 this event; any subsequent mouse-movement Emacs
10822 events should reflect only motion after the
10823 ButtonPress. */
10824 if (f != 0)
10825 f->mouse_moved = 0;
10826
10827 #ifdef USE_TOOLKIT_SCROLL_BARS
10828 if (inev.kind == MOUSE_CLICK_EVENT)
10829 #endif
10830 switch (er.what)
10831 {
10832 case mouseDown:
10833 inev.modifiers |= down_modifier;
10834 break;
10835 case mouseUp:
10836 inev.modifiers |= up_modifier;
10837 break;
10838 }
10839 }
10840 break;
10841
10842 case inDrag:
10843 #if TARGET_API_MAC_CARBON
10844 case inProxyIcon:
10845 if (IsWindowPathSelectClick (window_ptr, &er))
10846 {
10847 WindowPathSelect (window_ptr, NULL, NULL);
10848 break;
10849 }
10850 if (part_code == inProxyIcon
10851 && (TrackWindowProxyDrag (window_ptr, er.where)
10852 != errUserWantsToDragWindow))
10853 break;
10854 DragWindow (window_ptr, er.where, NULL);
10855 #else /* not TARGET_API_MAC_CARBON */
10856 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
10857 #endif /* not TARGET_API_MAC_CARBON */
10858 /* Update the frame parameters. */
10859 #if !USE_CARBON_EVENTS
10860 {
10861 struct frame *f = mac_window_to_frame (window_ptr);
10862
10863 if (f && !f->async_iconified)
10864 mac_handle_origin_change (f);
10865 }
10866 #endif
10867 break;
10868
10869 case inGoAway:
10870 if (TrackGoAway (window_ptr, er.where))
10871 {
10872 inev.kind = DELETE_WINDOW_EVENT;
10873 XSETFRAME (inev.frame_or_window,
10874 mac_window_to_frame (window_ptr));
10875 }
10876 break;
10877
10878 /* window resize handling added --ben */
10879 case inGrow:
10880 do_grow_window (window_ptr, &er);
10881 break;
10882
10883 /* window zoom handling added --ben */
10884 case inZoomIn:
10885 case inZoomOut:
10886 if (TrackBox (window_ptr, er.where, part_code))
10887 do_zoom_window (window_ptr, part_code);
10888 break;
10889
10890 default:
10891 break;
10892 }
10893 }
10894 break;
10895
10896 case updateEvt:
10897 #if USE_CARBON_EVENTS
10898 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10899 != eventNotHandledErr)
10900 break;
10901 #else
10902 do_window_update ((WindowPtr) er.message);
10903 #endif
10904 break;
10905
10906 case osEvt:
10907 #if USE_CARBON_EVENTS
10908 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10909 != eventNotHandledErr)
10910 break;
10911 #endif
10912 switch ((er.message >> 24) & 0x000000FF)
10913 {
10914 case suspendResumeMessage:
10915 #if USE_MAC_TSM
10916 if (er.message & resumeFlag)
10917 mac_tsm_resume ();
10918 else
10919 mac_tsm_suspend ();
10920 #endif
10921 break;
10922
10923 case mouseMovedMessage:
10924 #if !USE_CARBON_EVENTS
10925 SetRectRgn (mouse_region, er.where.h, er.where.v,
10926 er.where.h + 1, er.where.v + 1);
10927 #endif
10928 previous_help_echo_string = help_echo_string;
10929 help_echo_string = Qnil;
10930
10931 if (dpyinfo->grabbed && last_mouse_frame
10932 && FRAME_LIVE_P (last_mouse_frame))
10933 f = last_mouse_frame;
10934 else
10935 f = dpyinfo->x_focus_frame;
10936
10937 if (dpyinfo->mouse_face_hidden)
10938 {
10939 dpyinfo->mouse_face_hidden = 0;
10940 clear_mouse_face (dpyinfo);
10941 }
10942
10943 if (f)
10944 {
10945 WindowPtr wp = FRAME_MAC_WINDOW (f);
10946 Point mouse_pos = er.where;
10947
10948 SetPortWindowPort (wp);
10949
10950 GlobalToLocal (&mouse_pos);
10951
10952 if (dpyinfo->grabbed && tracked_scroll_bar)
10953 #ifdef USE_TOOLKIT_SCROLL_BARS
10954 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
10955 mouse_pos, &inev);
10956 #else /* not USE_TOOLKIT_SCROLL_BARS */
10957 x_scroll_bar_note_movement (tracked_scroll_bar,
10958 mouse_pos.v
10959 - XINT (tracked_scroll_bar->top),
10960 er.when * (1000 / 60));
10961 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10962 else
10963 {
10964 /* Generate SELECT_WINDOW_EVENTs when needed. */
10965 if (!NILP (Vmouse_autoselect_window))
10966 {
10967 Lisp_Object window;
10968
10969 window = window_from_coordinates (f,
10970 mouse_pos.h,
10971 mouse_pos.v,
10972 0, 0, 0, 0);
10973
10974 /* Window will be selected only when it is
10975 not selected now and last mouse movement
10976 event was not in it. Minibuffer window
10977 will be selected iff it is active. */
10978 if (WINDOWP (window)
10979 && !EQ (window, last_window)
10980 && !EQ (window, selected_window))
10981 {
10982 inev.kind = SELECT_WINDOW_EVENT;
10983 inev.frame_or_window = window;
10984 }
10985
10986 last_window=window;
10987 }
10988 if (!note_mouse_movement (f, &mouse_pos))
10989 help_echo_string = previous_help_echo_string;
10990 }
10991 }
10992
10993 /* If the contents of the global variable
10994 help_echo_string has changed, generate a
10995 HELP_EVENT. */
10996 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
10997 do_help = 1;
10998 break;
10999 }
11000 break;
11001
11002 case activateEvt:
11003 {
11004 WindowPtr window_ptr = (WindowPtr) er.message;
11005
11006 #if USE_CARBON_EVENTS
11007 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
11008 != eventNotHandledErr)
11009 break;
11010 #endif
11011 if (window_ptr == tip_window)
11012 {
11013 HideWindow (tip_window);
11014 break;
11015 }
11016
11017 if (!is_emacs_window (window_ptr))
11018 break;
11019
11020 if ((er.modifiers & activeFlag) != 0)
11021 {
11022 /* A window has been activated */
11023 Point mouse_loc = er.where;
11024
11025 x_detect_focus_change (dpyinfo, &er, &inev);
11026
11027 SetPortWindowPort (window_ptr);
11028 GlobalToLocal (&mouse_loc);
11029 /* Window-activated event counts as mouse movement,
11030 so update things that depend on mouse position. */
11031 note_mouse_movement (mac_window_to_frame (window_ptr),
11032 &mouse_loc);
11033 }
11034 else
11035 {
11036 /* A window has been deactivated */
11037 #if USE_TOOLKIT_SCROLL_BARS
11038 if (dpyinfo->grabbed && tracked_scroll_bar)
11039 {
11040 struct input_event event;
11041
11042 EVENT_INIT (event);
11043 event.kind = NO_EVENT;
11044 x_scroll_bar_handle_release (tracked_scroll_bar, &event);
11045 if (event.kind != NO_EVENT)
11046 {
11047 event.timestamp = timestamp;
11048 kbd_buffer_store_event_hold (&event, hold_quit);
11049 count++;
11050 }
11051 }
11052 #endif
11053 dpyinfo->grabbed = 0;
11054
11055 x_detect_focus_change (dpyinfo, &er, &inev);
11056
11057 f = mac_window_to_frame (window_ptr);
11058 if (f == dpyinfo->mouse_face_mouse_frame)
11059 {
11060 /* If we move outside the frame, then we're
11061 certainly no longer on any text in the
11062 frame. */
11063 clear_mouse_face (dpyinfo);
11064 dpyinfo->mouse_face_mouse_frame = 0;
11065 }
11066
11067 /* Generate a nil HELP_EVENT to cancel a help-echo.
11068 Do it only if there's something to cancel.
11069 Otherwise, the startup message is cleared when the
11070 mouse leaves the frame. */
11071 if (any_help_event_p)
11072 do_help = -1;
11073 }
11074 }
11075 break;
11076
11077 case keyDown:
11078 case keyUp:
11079 case autoKey:
11080 {
11081 int keycode = (er.message & keyCodeMask) >> 8;
11082 static SInt16 last_key_script = -1;
11083 SInt16 current_key_script;
11084 UInt32 modifiers = er.modifiers, mapped_modifiers;
11085
11086 #if USE_CARBON_EVENTS && defined (MAC_OSX)
11087 GetEventParameter (eventRef, kEventParamKeyModifiers,
11088 typeUInt32, NULL,
11089 sizeof (UInt32), NULL, &modifiers);
11090 #endif
11091 mapped_modifiers = mac_mapped_modifiers (modifiers);
11092
11093 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
11094 /* When using Carbon Events, we need to pass raw keyboard
11095 events to the TSM ourselves. If TSM handles it, it
11096 will pass back noErr, otherwise it will pass back
11097 "eventNotHandledErr" and we can process it
11098 normally. */
11099 if (!(mapped_modifiers
11100 & ~(mac_pass_command_to_system ? cmdKey : 0)
11101 & ~(mac_pass_control_to_system ? controlKey : 0)))
11102 {
11103 OSStatus err;
11104
11105 read_socket_inev = &inev;
11106 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
11107 read_socket_inev = NULL;
11108 if (err != eventNotHandledErr)
11109 break;
11110 }
11111 #endif
11112 if (er.what == keyUp)
11113 break;
11114
11115 ObscureCursor ();
11116
11117 f = mac_focus_frame (dpyinfo);
11118
11119 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
11120 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
11121 {
11122 clear_mouse_face (dpyinfo);
11123 dpyinfo->mouse_face_hidden = 1;
11124 }
11125
11126 current_key_script = GetScriptManagerVariable (smKeyScript);
11127 if (last_key_script != current_key_script)
11128 {
11129 struct input_event event;
11130
11131 EVENT_INIT (event);
11132 event.kind = LANGUAGE_CHANGE_EVENT;
11133 event.arg = Qnil;
11134 event.code = current_key_script;
11135 event.timestamp = timestamp;
11136 kbd_buffer_store_event (&event);
11137 count++;
11138 last_key_script = current_key_script;
11139 }
11140
11141 #if USE_MAC_TSM
11142 if (inev.kind != NO_EVENT)
11143 break;
11144 #endif
11145
11146 #ifdef MAC_OSX
11147 if (mapped_modifiers & kEventKeyModifierFnMask
11148 && keycode <= 0x7f
11149 && fn_keycode_to_keycode_table[keycode])
11150 keycode = fn_keycode_to_keycode_table[keycode];
11151 #endif
11152 if (keycode <= 0x7f && keycode_to_xkeysym_table [keycode])
11153 {
11154 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
11155 inev.code = 0xff00 | keycode_to_xkeysym_table [keycode];
11156 #ifdef MAC_OSX
11157 if (modifiers & kEventKeyModifierFnMask
11158 && keycode <= 0x7f
11159 && fn_keycode_to_keycode_table[keycode] == keycode)
11160 modifiers &= ~kEventKeyModifierFnMask;
11161 #endif
11162 }
11163 else if (mapped_modifiers)
11164 {
11165 /* translate the keycode back to determine the
11166 original key */
11167 #ifdef MAC_OSX
11168 static SInt16 last_key_layout_id = 0;
11169 static Handle uchr_handle = (Handle)-1;
11170 SInt16 current_key_layout_id =
11171 GetScriptVariable (current_key_script, smScriptKeys);
11172
11173 if (uchr_handle == (Handle)-1
11174 || last_key_layout_id != current_key_layout_id)
11175 {
11176 uchr_handle = GetResource ('uchr', current_key_layout_id);
11177 last_key_layout_id = current_key_layout_id;
11178 }
11179
11180 if (uchr_handle)
11181 {
11182 OSStatus status;
11183 UInt16 key_action = er.what - keyDown;
11184 UInt32 modifier_key_state =
11185 (modifiers & ~mapped_modifiers) >> 8;
11186 UInt32 keyboard_type = LMGetKbdType ();
11187 SInt32 dead_key_state = 0;
11188 UniChar code;
11189 UniCharCount actual_length;
11190
11191 status = UCKeyTranslate ((UCKeyboardLayout *)*uchr_handle,
11192 keycode, key_action,
11193 modifier_key_state,
11194 keyboard_type,
11195 kUCKeyTranslateNoDeadKeysMask,
11196 &dead_key_state,
11197 1, &actual_length, &code);
11198 if (status == noErr && actual_length == 1)
11199 mac_set_unicode_keystroke_event (code, &inev);
11200 }
11201 #endif /* MAC_OSX */
11202
11203 if (inev.kind == NO_EVENT)
11204 {
11205 /* This code comes from Keyboard Resource,
11206 Appendix C of IM - Text. This is necessary
11207 since shift is ignored in KCHR table
11208 translation when option or command is pressed.
11209 It also does not translate correctly
11210 control-shift chars like C-% so mask off shift
11211 here also. */
11212 /* Mask off modifier keys that are mapped to some
11213 Emacs modifiers. */
11214 int new_modifiers = er.modifiers & ~mapped_modifiers;
11215 /* set high byte of keycode to modifier high byte*/
11216 int new_keycode = keycode | new_modifiers;
11217 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
11218 unsigned long some_state = 0;
11219 UInt32 new_char_code;
11220
11221 new_char_code = KeyTranslate (kchr_ptr, new_keycode,
11222 &some_state);
11223 if (new_char_code == 0)
11224 /* Seems like a dead key. Append up-stroke. */
11225 new_char_code = KeyTranslate (kchr_ptr,
11226 new_keycode | 0x80,
11227 &some_state);
11228 if (new_char_code)
11229 {
11230 inev.kind = ASCII_KEYSTROKE_EVENT;
11231 inev.code = new_char_code & 0xff;
11232 }
11233 }
11234 }
11235
11236 if (inev.kind == NO_EVENT)
11237 {
11238 inev.kind = ASCII_KEYSTROKE_EVENT;
11239 inev.code = er.message & charCodeMask;
11240 }
11241
11242 inev.modifiers = mac_to_emacs_modifiers (modifiers);
11243 inev.modifiers |= (extra_keyboard_modifiers
11244 & (meta_modifier | alt_modifier
11245 | hyper_modifier | super_modifier));
11246 XSETFRAME (inev.frame_or_window, f);
11247
11248 #if TARGET_API_MAC_CARBON
11249 if (inev.kind == ASCII_KEYSTROKE_EVENT
11250 && inev.code >= 0x80 && inev.modifiers)
11251 {
11252 OSStatus err;
11253 TextEncoding encoding = kTextEncodingMacRoman;
11254 TextToUnicodeInfo ttu_info;
11255
11256 UpgradeScriptInfoToTextEncoding (current_key_script,
11257 kTextLanguageDontCare,
11258 kTextRegionDontCare,
11259 NULL, &encoding);
11260 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
11261 if (err == noErr)
11262 {
11263 UniChar code;
11264 Str255 pstr;
11265 ByteCount unicode_len;
11266
11267 pstr[0] = 1;
11268 pstr[1] = inev.code;
11269 err = ConvertFromPStringToUnicode (ttu_info, pstr,
11270 sizeof (UniChar),
11271 &unicode_len, &code);
11272 if (err == noErr && unicode_len == sizeof (UniChar))
11273 mac_set_unicode_keystroke_event (code, &inev);
11274 DisposeTextToUnicodeInfo (&ttu_info);
11275 }
11276 }
11277 #endif
11278 }
11279 break;
11280
11281 case kHighLevelEvent:
11282 AEProcessAppleEvent (&er);
11283 break;
11284
11285 default:
11286 break;
11287 }
11288 #if USE_CARBON_EVENTS
11289 ReleaseEvent (eventRef);
11290 #endif
11291
11292 if (inev.kind != NO_EVENT)
11293 {
11294 inev.timestamp = timestamp;
11295 kbd_buffer_store_event_hold (&inev, hold_quit);
11296 count++;
11297 }
11298
11299 if (do_help
11300 && !(hold_quit && hold_quit->kind != NO_EVENT))
11301 {
11302 Lisp_Object frame;
11303
11304 if (f)
11305 XSETFRAME (frame, f);
11306 else
11307 frame = Qnil;
11308
11309 if (do_help > 0)
11310 {
11311 any_help_event_p = 1;
11312 gen_help_event (help_echo_string, frame, help_echo_window,
11313 help_echo_object, help_echo_pos);
11314 }
11315 else
11316 {
11317 help_echo_string = Qnil;
11318 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
11319 }
11320 count++;
11321 }
11322
11323 }
11324
11325 /* If the focus was just given to an autoraising frame,
11326 raise it now. */
11327 /* ??? This ought to be able to handle more than one such frame. */
11328 if (pending_autoraise_frame)
11329 {
11330 x_raise_frame (pending_autoraise_frame);
11331 pending_autoraise_frame = 0;
11332 }
11333
11334 #if !USE_CARBON_EVENTS
11335 /* Check which frames are still visible. We do this here because
11336 there doesn't seem to be any direct notification from the Window
11337 Manager that the visibility of a window has changed (at least,
11338 not in all cases). */
11339 {
11340 Lisp_Object tail, frame;
11341
11342 FOR_EACH_FRAME (tail, frame)
11343 {
11344 struct frame *f = XFRAME (frame);
11345
11346 /* The tooltip has been drawn already. Avoid the
11347 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11348 if (EQ (frame, tip_frame))
11349 continue;
11350
11351 if (FRAME_MAC_P (f))
11352 mac_handle_visibility_change (f);
11353 }
11354 }
11355 #endif
11356
11357 --handling_signal;
11358 UNBLOCK_INPUT;
11359 return count;
11360 }
11361
11362
11363 /* Need to override CodeWarrior's input function so no conversion is
11364 done on newlines Otherwise compiled functions in .elc files will be
11365 read incorrectly. Defined in ...:MSL C:MSL
11366 Common:Source:buffer_io.c. */
11367 #ifdef __MWERKS__
11368 void
11369 __convert_to_newlines (unsigned char * p, size_t * n)
11370 {
11371 #pragma unused(p,n)
11372 }
11373
11374 void
11375 __convert_from_newlines (unsigned char * p, size_t * n)
11376 {
11377 #pragma unused(p,n)
11378 }
11379 #endif
11380
11381 #ifdef MAC_OS8
11382 void
11383 make_mac_terminal_frame (struct frame *f)
11384 {
11385 Lisp_Object frame;
11386 Rect r;
11387
11388 XSETFRAME (frame, f);
11389
11390 f->output_method = output_mac;
11391 f->output_data.mac = (struct mac_output *)
11392 xmalloc (sizeof (struct mac_output));
11393 bzero (f->output_data.mac, sizeof (struct mac_output));
11394
11395 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
11396
11397 FRAME_COLS (f) = 96;
11398 FRAME_LINES (f) = 4;
11399
11400 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
11401 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
11402
11403 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
11404
11405 f->output_data.mac->cursor_pixel = 0;
11406 f->output_data.mac->border_pixel = 0x00ff00;
11407 f->output_data.mac->mouse_pixel = 0xff00ff;
11408 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
11409
11410 f->output_data.mac->text_cursor = kThemeIBeamCursor;
11411 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
11412 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
11413 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
11414 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
11415 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
11416
11417 FRAME_FONTSET (f) = -1;
11418 f->output_data.mac->explicit_parent = 0;
11419 f->left_pos = 8;
11420 f->top_pos = 32;
11421 f->border_width = 0;
11422
11423 f->internal_border_width = 0;
11424
11425 f->auto_raise = 1;
11426 f->auto_lower = 1;
11427
11428 f->new_text_cols = 0;
11429 f->new_text_lines = 0;
11430
11431 SetRect (&r, f->left_pos, f->top_pos,
11432 f->left_pos + FRAME_PIXEL_WIDTH (f),
11433 f->top_pos + FRAME_PIXEL_HEIGHT (f));
11434
11435 BLOCK_INPUT;
11436
11437 if (!(FRAME_MAC_WINDOW (f) =
11438 NewCWindow (NULL, &r, "\p", true, dBoxProc,
11439 (WindowPtr) -1, 1, (long) f->output_data.mac)))
11440 abort ();
11441 /* so that update events can find this mac_output struct */
11442 f->output_data.mac->mFP = f; /* point back to emacs frame */
11443
11444 UNBLOCK_INPUT;
11445
11446 x_make_gc (f);
11447
11448 /* Need to be initialized for unshow_buffer in window.c. */
11449 selected_window = f->selected_window;
11450
11451 Fmodify_frame_parameters (frame,
11452 Fcons (Fcons (Qfont,
11453 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
11454 Fmodify_frame_parameters (frame,
11455 Fcons (Fcons (Qforeground_color,
11456 build_string ("black")), Qnil));
11457 Fmodify_frame_parameters (frame,
11458 Fcons (Fcons (Qbackground_color,
11459 build_string ("white")), Qnil));
11460 }
11461 #endif
11462
11463 \f
11464 /***********************************************************************
11465 Initialization
11466 ***********************************************************************/
11467
11468 int mac_initialized = 0;
11469
11470 void
11471 mac_initialize_display_info ()
11472 {
11473 struct mac_display_info *dpyinfo = &one_mac_display_info;
11474
11475 bzero (dpyinfo, sizeof (*dpyinfo));
11476
11477 #ifdef MAC_OSX
11478 dpyinfo->mac_id_name
11479 = (char *) xmalloc (SCHARS (Vinvocation_name)
11480 + SCHARS (Vsystem_name)
11481 + 2);
11482 sprintf (dpyinfo->mac_id_name, "%s@%s",
11483 SDATA (Vinvocation_name), SDATA (Vsystem_name));
11484 #else
11485 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
11486 strcpy (dpyinfo->mac_id_name, "Mac Display");
11487 #endif
11488
11489 dpyinfo->reference_count = 0;
11490 dpyinfo->resx = 72.0;
11491 dpyinfo->resy = 72.0;
11492 #ifdef MAC_OSX
11493 /* HasDepth returns true if it is possible to have a 32 bit display,
11494 but this may not be what is actually used. Mac OSX can do better. */
11495 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
11496 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
11497 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
11498 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
11499 #else
11500 {
11501 GDHandle main_device_handle = LMGetMainDevice();
11502
11503 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
11504 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
11505 if (HasDepth (main_device_handle, dpyinfo->n_planes,
11506 gdDevType, dpyinfo->color_p))
11507 break;
11508 dpyinfo->height = (**main_device_handle).gdRect.bottom;
11509 dpyinfo->width = (**main_device_handle).gdRect.right;
11510 }
11511 #endif
11512 dpyinfo->grabbed = 0;
11513 dpyinfo->root_window = NULL;
11514 dpyinfo->image_cache = make_image_cache ();
11515
11516 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
11517 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
11518 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
11519 dpyinfo->mouse_face_window = Qnil;
11520 dpyinfo->mouse_face_overlay = Qnil;
11521 dpyinfo->mouse_face_hidden = 0;
11522 }
11523
11524
11525 static XrmDatabase
11526 mac_make_rdb (xrm_option)
11527 const char *xrm_option;
11528 {
11529 XrmDatabase database;
11530
11531 database = xrm_get_preference_database (NULL);
11532 if (xrm_option)
11533 xrm_merge_string_database (database, xrm_option);
11534
11535 return database;
11536 }
11537
11538 struct mac_display_info *
11539 mac_term_init (display_name, xrm_option, resource_name)
11540 Lisp_Object display_name;
11541 char *xrm_option;
11542 char *resource_name;
11543 {
11544 struct mac_display_info *dpyinfo;
11545
11546 BLOCK_INPUT;
11547
11548 if (!mac_initialized)
11549 {
11550 mac_initialize ();
11551 mac_initialized = 1;
11552 }
11553
11554 if (x_display_list)
11555 error ("Sorry, this version can only handle one display");
11556
11557 mac_initialize_display_info ();
11558
11559 dpyinfo = &one_mac_display_info;
11560
11561 dpyinfo->xrdb = mac_make_rdb (xrm_option);
11562
11563 /* Put this display on the chain. */
11564 dpyinfo->next = x_display_list;
11565 x_display_list = dpyinfo;
11566
11567 /* Put it on x_display_name_list. */
11568 x_display_name_list = Fcons (Fcons (display_name,
11569 Fcons (Qnil, dpyinfo->xrdb)),
11570 x_display_name_list);
11571 dpyinfo->name_list_element = XCAR (x_display_name_list);
11572
11573 UNBLOCK_INPUT;
11574
11575 return dpyinfo;
11576 }
11577 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11578
11579 void
11580 x_delete_display (dpyinfo)
11581 struct mac_display_info *dpyinfo;
11582 {
11583 int i;
11584
11585 /* Discard this display from x_display_name_list and x_display_list.
11586 We can't use Fdelq because that can quit. */
11587 if (! NILP (x_display_name_list)
11588 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
11589 x_display_name_list = XCDR (x_display_name_list);
11590 else
11591 {
11592 Lisp_Object tail;
11593
11594 tail = x_display_name_list;
11595 while (CONSP (tail) && CONSP (XCDR (tail)))
11596 {
11597 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
11598 {
11599 XSETCDR (tail, XCDR (XCDR (tail)));
11600 break;
11601 }
11602 tail = XCDR (tail);
11603 }
11604 }
11605
11606 if (x_display_list == dpyinfo)
11607 x_display_list = dpyinfo->next;
11608 else
11609 {
11610 struct x_display_info *tail;
11611
11612 for (tail = x_display_list; tail; tail = tail->next)
11613 if (tail->next == dpyinfo)
11614 tail->next = tail->next->next;
11615 }
11616
11617 /* Free the font names in the font table. */
11618 for (i = 0; i < dpyinfo->n_fonts; i++)
11619 if (dpyinfo->font_table[i].name)
11620 {
11621 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
11622 xfree (dpyinfo->font_table[i].full_name);
11623 xfree (dpyinfo->font_table[i].name);
11624 }
11625
11626 if (dpyinfo->font_table)
11627 {
11628 if (dpyinfo->font_table->font_encoder)
11629 xfree (dpyinfo->font_table->font_encoder);
11630 xfree (dpyinfo->font_table);
11631 }
11632 if (dpyinfo->mac_id_name)
11633 xfree (dpyinfo->mac_id_name);
11634
11635 if (x_display_list == 0)
11636 {
11637 mac_clear_font_name_table ();
11638 bzero (dpyinfo, sizeof (*dpyinfo));
11639 }
11640 }
11641
11642 \f
11643 #ifdef MAC_OSX
11644 void
11645 MakeMeTheFrontProcess ()
11646 {
11647 ProcessSerialNumber psn;
11648 OSErr err;
11649
11650 err = GetCurrentProcess (&psn);
11651 if (err == noErr)
11652 (void) SetFrontProcess (&psn);
11653 }
11654 #endif /* MAC_OSX */
11655
11656 static void
11657 init_menu_bar ()
11658 {
11659 #ifdef MAC_OSX
11660 OSStatus err;
11661 MenuRef menu;
11662 MenuItemIndex menu_index;
11663
11664 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
11665 &menu, &menu_index);
11666 if (err == noErr)
11667 SetMenuItemCommandKey (menu, menu_index, false, 0);
11668 #if USE_CARBON_EVENTS
11669 EnableMenuCommand (NULL, kHICommandPreferences);
11670 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
11671 &menu, &menu_index);
11672 if (err == noErr)
11673 {
11674 SetMenuItemCommandKey (menu, menu_index, false, 0);
11675 InsertMenuItemTextWithCFString (menu, NULL,
11676 0, kMenuItemAttrSeparator, 0);
11677 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
11678 0, 0, kHICommandAbout);
11679 }
11680 #endif /* USE_CARBON_EVENTS */
11681 #else /* !MAC_OSX */
11682 #if USE_CARBON_EVENTS
11683 SetMenuItemCommandID (GetMenuHandle (M_APPLE), I_ABOUT, kHICommandAbout);
11684 #endif
11685 #endif
11686 }
11687
11688 #if USE_MAC_TSM
11689 static void
11690 init_tsm ()
11691 {
11692 #ifdef MAC_OSX
11693 static InterfaceTypeList types = {kUnicodeDocument};
11694 #else
11695 static InterfaceTypeList types = {kTextService};
11696 #endif
11697
11698 NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
11699 &tsm_document_id, 0);
11700 }
11701 #endif
11702
11703 /* Set up use of X before we make the first connection. */
11704
11705 extern frame_parm_handler mac_frame_parm_handlers[];
11706
11707 static struct redisplay_interface x_redisplay_interface =
11708 {
11709 mac_frame_parm_handlers,
11710 x_produce_glyphs,
11711 x_write_glyphs,
11712 x_insert_glyphs,
11713 x_clear_end_of_line,
11714 x_scroll_run,
11715 x_after_update_window_line,
11716 x_update_window_begin,
11717 x_update_window_end,
11718 x_cursor_to,
11719 x_flush,
11720 0, /* flush_display_optional */
11721 x_clear_window_mouse_face,
11722 x_get_glyph_overhangs,
11723 x_fix_overlapping_area,
11724 x_draw_fringe_bitmap,
11725 #if USE_CG_DRAWING
11726 mac_define_fringe_bitmap,
11727 mac_destroy_fringe_bitmap,
11728 #else
11729 0, /* define_fringe_bitmap */
11730 0, /* destroy_fringe_bitmap */
11731 #endif
11732 mac_per_char_metric,
11733 mac_encode_char,
11734 mac_compute_glyph_string_overhangs,
11735 x_draw_glyph_string,
11736 mac_define_frame_cursor,
11737 mac_clear_frame_area,
11738 mac_draw_window_cursor,
11739 mac_draw_vertical_window_border,
11740 mac_shift_glyphs_for_insert
11741 };
11742
11743 void
11744 mac_initialize ()
11745 {
11746 rif = &x_redisplay_interface;
11747
11748 clear_frame_hook = x_clear_frame;
11749 ins_del_lines_hook = x_ins_del_lines;
11750 delete_glyphs_hook = x_delete_glyphs;
11751 ring_bell_hook = XTring_bell;
11752 reset_terminal_modes_hook = XTreset_terminal_modes;
11753 set_terminal_modes_hook = XTset_terminal_modes;
11754 update_begin_hook = x_update_begin;
11755 update_end_hook = x_update_end;
11756 set_terminal_window_hook = XTset_terminal_window;
11757 read_socket_hook = XTread_socket;
11758 frame_up_to_date_hook = XTframe_up_to_date;
11759 mouse_position_hook = XTmouse_position;
11760 frame_rehighlight_hook = XTframe_rehighlight;
11761 frame_raise_lower_hook = XTframe_raise_lower;
11762
11763 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
11764 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
11765 redeem_scroll_bar_hook = XTredeem_scroll_bar;
11766 judge_scroll_bars_hook = XTjudge_scroll_bars;
11767
11768 scroll_region_ok = 1; /* we'll scroll partial frames */
11769 char_ins_del_ok = 1;
11770 line_ins_del_ok = 1; /* we'll just blt 'em */
11771 fast_clear_end_of_line = 1; /* X does this well */
11772 memory_below_frame = 0; /* we don't remember what scrolls
11773 off the bottom */
11774 baud_rate = 19200;
11775
11776 last_tool_bar_item = -1;
11777 any_help_event_p = 0;
11778
11779 /* Try to use interrupt input; if we can't, then start polling. */
11780 Fset_input_mode (Qt, Qnil, Qt, Qnil);
11781
11782 BLOCK_INPUT;
11783
11784 #if TARGET_API_MAC_CARBON
11785
11786 #if USE_CARBON_EVENTS
11787 #ifdef MAC_OSX
11788 init_service_handler ();
11789 #endif /* MAC_OSX */
11790
11791 init_command_handler ();
11792
11793 init_menu_bar ();
11794
11795 #if USE_MAC_TSM
11796 init_tsm ();
11797 #endif
11798 #endif /* USE_CARBON_EVENTS */
11799
11800 #ifdef MAC_OSX
11801 init_coercion_handler ();
11802
11803 init_apple_event_handler ();
11804
11805 if (!inhibit_window_system)
11806 MakeMeTheFrontProcess ();
11807 #endif
11808 #endif
11809
11810 #if USE_CG_DRAWING
11811 init_cg_color ();
11812
11813 mac_init_fringe ();
11814 #endif
11815
11816 UNBLOCK_INPUT;
11817 }
11818
11819
11820 void
11821 syms_of_macterm ()
11822 {
11823 #if 0
11824 staticpro (&x_error_message_string);
11825 x_error_message_string = Qnil;
11826 #endif
11827
11828 Qcontrol = intern ("control"); staticpro (&Qcontrol);
11829 Qmeta = intern ("meta"); staticpro (&Qmeta);
11830 Qalt = intern ("alt"); staticpro (&Qalt);
11831 Qhyper = intern ("hyper"); staticpro (&Qhyper);
11832 Qsuper = intern ("super"); staticpro (&Qsuper);
11833 Qmodifier_value = intern ("modifier-value");
11834 staticpro (&Qmodifier_value);
11835
11836 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
11837 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
11838 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
11839 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
11840 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
11841
11842 #if USE_CARBON_EVENTS
11843 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
11844 #ifdef MAC_OSX
11845 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
11846 staticpro (&Qtoolbar_switch_mode);
11847 #if USE_MAC_FONT_PANEL
11848 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
11849 Qselection = intern ("selection"); staticpro (&Qselection);
11850 #endif
11851
11852 Qservice = intern ("service"); staticpro (&Qservice);
11853 Qpaste = intern ("paste"); staticpro (&Qpaste);
11854 Qperform = intern ("perform"); staticpro (&Qperform);
11855 #endif
11856 #if USE_MAC_TSM
11857 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
11858 Qupdate_active_input_area = intern ("update-active-input-area");
11859 staticpro (&Qupdate_active_input_area);
11860 Qunicode_for_key_event = intern ("unicode-for-key-event");
11861 staticpro (&Qunicode_for_key_event);
11862 #endif
11863 #endif
11864
11865 #ifdef MAC_OSX
11866 Fprovide (intern ("mac-carbon"), Qnil);
11867 #endif
11868
11869 staticpro (&Qreverse);
11870 Qreverse = intern ("reverse");
11871
11872 staticpro (&x_display_name_list);
11873 x_display_name_list = Qnil;
11874
11875 staticpro (&last_mouse_scroll_bar);
11876 last_mouse_scroll_bar = Qnil;
11877
11878 staticpro (&fm_font_family_alist);
11879 fm_font_family_alist = Qnil;
11880
11881 #if USE_ATSUI
11882 staticpro (&atsu_font_id_hash);
11883 atsu_font_id_hash = Qnil;
11884
11885 staticpro (&fm_style_face_attributes_alist);
11886 fm_style_face_attributes_alist = Qnil;
11887 #endif
11888
11889 #if USE_MAC_TSM
11890 staticpro (&saved_ts_script_language_on_focus);
11891 saved_ts_script_language_on_focus = Qnil;
11892 #endif
11893
11894 /* We don't yet support this, but defining this here avoids whining
11895 from cus-start.el and other places, like "M-x set-variable". */
11896 DEFVAR_BOOL ("x-use-underline-position-properties",
11897 &x_use_underline_position_properties,
11898 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11899 A value of nil means ignore them. If you encounter fonts with bogus
11900 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11901 to 4.1, set this to nil.
11902
11903 NOTE: Not supported on Mac yet. */);
11904 x_use_underline_position_properties = 0;
11905
11906 DEFVAR_BOOL ("x-underline-at-descent-line",
11907 &x_underline_at_descent_line,
11908 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
11909 A value of nil means to draw the underline according to the value of the
11910 variable `x-use-underline-position-properties', which is usually at the
11911 baseline level. The default value is nil. */);
11912 x_underline_at_descent_line = 0;
11913
11914 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
11915 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
11916 #ifdef USE_TOOLKIT_SCROLL_BARS
11917 Vx_toolkit_scroll_bars = Qt;
11918 #else
11919 Vx_toolkit_scroll_bars = Qnil;
11920 #endif
11921
11922 staticpro (&last_mouse_motion_frame);
11923 last_mouse_motion_frame = Qnil;
11924
11925 /* Variables to configure modifier key assignment. */
11926
11927 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
11928 doc: /* *Modifier key assumed when the Mac control key is pressed.
11929 The value can be `control', `meta', `alt', `hyper', or `super' for the
11930 respective modifier. The default is `control'. */);
11931 Vmac_control_modifier = Qcontrol;
11932
11933 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
11934 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
11935 The value can be `control', `meta', `alt', `hyper', or `super' for the
11936 respective modifier. If the value is nil then the key will act as the
11937 normal Mac control modifier, and the option key can be used to compose
11938 characters depending on the chosen Mac keyboard setting. */);
11939 Vmac_option_modifier = Qnil;
11940
11941 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
11942 doc: /* *Modifier key assumed when the Mac command key is pressed.
11943 The value can be `control', `meta', `alt', `hyper', or `super' for the
11944 respective modifier. The default is `meta'. */);
11945 Vmac_command_modifier = Qmeta;
11946
11947 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
11948 doc: /* *Modifier key assumed when the Mac function key is pressed.
11949 The value can be `control', `meta', `alt', `hyper', or `super' for the
11950 respective modifier. Note that remapping the function key may lead to
11951 unexpected results for some keys on non-US/GB keyboards. */);
11952 Vmac_function_modifier = Qnil;
11953
11954 DEFVAR_LISP ("mac-emulate-three-button-mouse",
11955 &Vmac_emulate_three_button_mouse,
11956 doc: /* *Specify a way of three button mouse emulation.
11957 The value can be nil, t, or the symbol `reverse'.
11958 A value of nil means that no emulation should be done and the modifiers
11959 should be placed on the mouse-1 event.
11960 t means that when the option-key is held down while pressing the mouse
11961 button, the click will register as mouse-2 and while the command-key
11962 is held down, the click will register as mouse-3.
11963 The symbol `reverse' means that the option-key will register for
11964 mouse-3 and the command-key will register for mouse-2. */);
11965 Vmac_emulate_three_button_mouse = Qnil;
11966
11967 #if USE_CARBON_EVENTS
11968 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
11969 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
11970 Otherwise, the right click will be treated as mouse-2 and the wheel
11971 button will be mouse-3. */);
11972 mac_wheel_button_is_mouse_2 = 1;
11973
11974 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
11975 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
11976 mac_pass_command_to_system = 1;
11977
11978 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
11979 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
11980 mac_pass_control_to_system = 1;
11981
11982 #endif
11983
11984 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
11985 doc: /* *If non-nil, allow anti-aliasing.
11986 The text will be rendered using Core Graphics text rendering which
11987 may anti-alias the text. */);
11988 #if USE_CG_DRAWING
11989 mac_use_core_graphics = 1;
11990 #else
11991 mac_use_core_graphics = 0;
11992 #endif
11993
11994 /* Register an entry for `mac-roman' so that it can be used when
11995 creating the terminal frame on Mac OS 9 before loading
11996 term/mac-win.elc. */
11997 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
11998 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
11999 Each entry should be of the form:
12000
12001 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12002
12003 where CHARSET-NAME is a string used in font names to identify the
12004 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12005 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
12006 Vmac_charset_info_alist =
12007 Fcons (list3 (build_string ("mac-roman"),
12008 make_number (smRoman), Qnil), Qnil);
12009
12010 #if USE_MAC_TSM
12011 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
12012 doc: /* Overlay used to display Mac TSM active input area. */);
12013 Vmac_ts_active_input_overlay = Qnil;
12014
12015 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
12016 doc: /* *How to change Mac TSM script/language when a frame gets focus.
12017 If the value is t, the input script and language are restored to those
12018 used in the last focus frame. If the value is a pair of integers, the
12019 input script and language codes, which are defined in the Script
12020 Manager, are set to its car and cdr parts, respectively. Otherwise,
12021 Emacs doesn't set them and thus follows the system default behavior. */);
12022 Vmac_ts_script_language_on_focus = Qnil;
12023 #endif
12024 }
12025
12026 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
12027 (do not change this comment) */