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