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