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