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