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