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