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