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