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