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