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