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