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