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