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