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