]> code.delx.au - gnu-emacs/blob - src/macterm.c
Remove generic fringe code.
[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 /* Enumeration for overriding/changing the face to use for drawing
304 glyphs in x_draw_glyphs. */
305
306 enum draw_glyphs_face
307 {
308 DRAW_NORMAL_TEXT,
309 DRAW_INVERSE_VIDEO,
310 DRAW_CURSOR,
311 DRAW_MOUSE_FACE,
312 DRAW_IMAGE_RAISED,
313 DRAW_IMAGE_SUNKEN
314 };
315
316 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
317 struct mac_display_info *mac_display_info_for_display (Display *);
318 static void x_update_window_end P_ ((struct window *, int, int));
319 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
320 static int fast_find_position P_ ((struct window *, int, int *, int *,
321 int *, int *, Lisp_Object));
322 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
323 int *, int *, int *, int *, int));
324 static void set_output_cursor P_ ((struct cursor_pos *));
325 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
326 int *, int *, int *, int));
327 static void note_mode_line_highlight P_ ((struct window *, int, int));
328 static void note_mouse_highlight P_ ((struct frame *, int, int));
329 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
330 static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
331 static void show_mouse_face P_ ((struct x_display_info *,
332 enum draw_glyphs_face));
333 static int cursor_in_mouse_face_p P_ ((struct window *));
334 static int clear_mouse_face P_ ((struct mac_display_info *));
335 static int x_io_error_quitter P_ ((Display *));
336 int x_catch_errors P_ ((Display *));
337 void x_uncatch_errors P_ ((Display *, int));
338 void x_lower_frame P_ ((struct frame *));
339 void x_scroll_bar_clear P_ ((struct frame *));
340 int x_had_errors_p P_ ((Display *));
341 void x_wm_set_size_hint P_ ((struct frame *, long, int));
342 void x_raise_frame P_ ((struct frame *));
343 void x_set_window_size P_ ((struct frame *, int, int, int));
344 void x_wm_set_window_state P_ ((struct frame *, int));
345 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
346 void mac_initialize P_ ((void));
347 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
348 static int x_compute_min_glyph_bounds P_ ((struct frame *));
349 static void x_draw_phys_cursor_glyph P_ ((struct window *,
350 struct glyph_row *,
351 enum draw_glyphs_face));
352 static void x_update_end P_ ((struct frame *));
353 static void XTframe_up_to_date P_ ((struct frame *));
354 static void XTreassert_line_highlight P_ ((int, int));
355 static void x_change_line_highlight P_ ((int, int, int, int));
356 static void XTset_terminal_modes P_ ((void));
357 static void XTreset_terminal_modes P_ ((void));
358 static void XTcursor_to P_ ((int, int, int, int));
359 static void x_write_glyphs P_ ((struct glyph *, int));
360 static void x_clear_end_of_line P_ ((int));
361 static void x_clear_frame P_ ((void));
362 static void x_clear_cursor P_ ((struct window *));
363 static void frame_highlight P_ ((struct frame *));
364 static void frame_unhighlight P_ ((struct frame *));
365 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
366 static void XTframe_rehighlight P_ ((struct frame *));
367 static void x_frame_rehighlight P_ ((struct x_display_info *));
368 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
369 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
370 static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
371 static void expose_frame P_ ((struct frame *, int, int, int, int));
372 static int expose_window_tree P_ ((struct window *, Rect *));
373 static void expose_overlaps P_ ((struct window *, struct glyph_row *,
374 struct glyph_row *));
375 static int expose_window P_ ((struct window *, Rect *));
376 static void expose_area P_ ((struct window *, struct glyph_row *,
377 Rect *, enum glyph_row_area));
378 static int expose_line P_ ((struct window *, struct glyph_row *,
379 Rect *));
380 void x_display_cursor (struct window *, int, int, int, int, int);
381 void x_update_cursor P_ ((struct frame *, int));
382 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
383 static void x_update_window_cursor P_ ((struct window *, int));
384 static void x_erase_phys_cursor P_ ((struct window *));
385 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
386 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
387 GC, int));
388 static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
389 static void notice_overwritten_cursor P_ ((struct window *,
390 enum glyph_row_area,
391 int, int, int, int));
392 static void x_flush P_ ((struct frame *f));
393 static void x_update_begin P_ ((struct frame *));
394 static void x_update_window_begin P_ ((struct window *));
395 static void x_draw_vertical_border P_ ((struct window *));
396 static void x_after_update_window_line P_ ((struct glyph_row *));
397 static INLINE void take_vertical_position_into_account P_ ((struct it *));
398 static void x_produce_stretch_glyph P_ ((struct it *));
399
400 static void activate_scroll_bars (FRAME_PTR);
401 static void deactivate_scroll_bars (FRAME_PTR);
402
403 static int is_emacs_window (WindowPtr);
404
405 extern int image_ascent (struct image *, struct face *);
406 void x_set_offset (struct frame *, int, int, int);
407 int x_bitmap_icon (struct frame *, Lisp_Object);
408 void x_make_frame_visible (struct frame *);
409
410 extern void window_scroll (Lisp_Object, int, int, int);
411
412 /* Defined in macmenu.h. */
413 extern void menubar_selection_callback (FRAME_PTR, int);
414 extern void set_frame_menubar (FRAME_PTR, int, int);
415
416 /* X display function emulation */
417
418 /* Structure borrowed from Xlib.h to represent two-byte characters in
419 dumpglyphs. */
420
421 typedef struct {
422 unsigned char byte1;
423 unsigned char byte2;
424 } XChar2b;
425
426 static void
427 XFreePixmap (display, pixmap)
428 Display *display;
429 Pixmap pixmap;
430 {
431 PixMap *p = (PixMap *) pixmap;
432
433 xfree (p->baseAddr);
434 xfree (p);
435 }
436
437
438 /* Set foreground color for subsequent QuickDraw commands. Assume
439 graphic port has already been set. */
440
441 static void
442 mac_set_forecolor (unsigned long color)
443 {
444 RGBColor fg_color;
445
446 fg_color.red = RED_FROM_ULONG (color) * 256;
447 fg_color.green = GREEN_FROM_ULONG (color) * 256;
448 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
449
450 RGBForeColor (&fg_color);
451 }
452
453
454 /* Set background color for subsequent QuickDraw commands. Assume
455 graphic port has already been set. */
456
457 static void
458 mac_set_backcolor (unsigned long color)
459 {
460 RGBColor bg_color;
461
462 bg_color.red = RED_FROM_ULONG (color) * 256;
463 bg_color.green = GREEN_FROM_ULONG (color) * 256;
464 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
465
466 RGBBackColor (&bg_color);
467 }
468
469 /* Set foreground and background color for subsequent QuickDraw
470 commands. Assume that the graphic port has already been set. */
471
472 static void
473 mac_set_colors (GC gc)
474 {
475 mac_set_forecolor (gc->foreground);
476 mac_set_backcolor (gc->background);
477 }
478
479 /* Mac version of XDrawLine. */
480
481 static void
482 XDrawLine (display, w, gc, x1, y1, x2, y2)
483 Display *display;
484 WindowPtr w;
485 GC gc;
486 int x1, y1, x2, y2;
487 {
488 #if TARGET_API_MAC_CARBON
489 SetPort (GetWindowPort (w));
490 #else
491 SetPort (w);
492 #endif
493
494 mac_set_colors (gc);
495
496 MoveTo (x1, y1);
497 LineTo (x2, y2);
498 }
499
500 /* Mac version of XClearArea. */
501
502 void
503 XClearArea (display, w, x, y, width, height, exposures)
504 Display *display;
505 WindowPtr w;
506 int x, y;
507 unsigned int width, height;
508 int exposures;
509 {
510 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
511 Rect r;
512 XGCValues xgc;
513
514 xgc.foreground = mwp->x_compatible.foreground_pixel;
515 xgc.background = mwp->x_compatible.background_pixel;
516
517 #if TARGET_API_MAC_CARBON
518 SetPort (GetWindowPort (w));
519 #else
520 SetPort (w);
521 #endif
522
523 mac_set_colors (&xgc);
524 SetRect (&r, x, y, x + width, y + height);
525
526 EraseRect (&r);
527 }
528
529 /* Mac version of XClearWindow. */
530
531 static void
532 XClearWindow (display, w)
533 Display *display;
534 WindowPtr w;
535 {
536 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
537 XGCValues xgc;
538
539 xgc.foreground = mwp->x_compatible.foreground_pixel;
540 xgc.background = mwp->x_compatible.background_pixel;
541
542 #if TARGET_API_MAC_CARBON
543 SetPort (GetWindowPort (w));
544 #else
545 SetPort (w);
546 #endif
547
548 mac_set_colors (&xgc);
549
550 #if TARGET_API_MAC_CARBON
551 {
552 Rect r;
553
554 GetWindowPortBounds (w, &r);
555 EraseRect (&r);
556 }
557 #else /* not TARGET_API_MAC_CARBON */
558 EraseRect (&(w->portRect));
559 #endif /* not TARGET_API_MAC_CARBON */
560 }
561
562
563 /* Mac replacement for XCopyArea. */
564
565 static void
566 mac_draw_bitmap (display, w, gc, x, y, bitmap)
567 Display *display;
568 WindowPtr w;
569 GC gc;
570 int x, y;
571 BitMap *bitmap;
572 {
573 Rect r;
574
575 #if TARGET_API_MAC_CARBON
576 SetPort (GetWindowPort (w));
577 #else
578 SetPort (w);
579 #endif
580
581 mac_set_colors (gc);
582 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
583
584 #if TARGET_API_MAC_CARBON
585 {
586 PixMapHandle pmh;
587
588 LockPortBits (GetWindowPort (w));
589 pmh = GetPortPixMap (GetWindowPort (w));
590 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
591 UnlockPortBits (GetWindowPort (w));
592 }
593 #else /* not TARGET_API_MAC_CARBON */
594 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
595 #endif /* not TARGET_API_MAC_CARBON */
596 }
597
598
599 /* Mac replacement for XSetClipRectangles. */
600
601 static void
602 mac_set_clip_rectangle (display, w, r)
603 Display *display;
604 WindowPtr w;
605 Rect *r;
606 {
607 #if TARGET_API_MAC_CARBON
608 SetPort (GetWindowPort (w));
609 #else
610 SetPort (w);
611 #endif
612
613 ClipRect (r);
614 }
615
616
617 /* Mac replacement for XSetClipMask. */
618
619 static void
620 mac_reset_clipping (display, w)
621 Display *display;
622 WindowPtr w;
623 {
624 Rect r;
625
626 #if TARGET_API_MAC_CARBON
627 SetPort (GetWindowPort (w));
628 #else
629 SetPort (w);
630 #endif
631
632 SetRect (&r, -32767, -32767, 32767, 32767);
633 ClipRect (&r);
634 }
635
636
637 /* Mac replacement for XCreateBitmapFromBitmapData. */
638
639 static void
640 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
641 BitMap *bitmap;
642 char *bits;
643 int w, h;
644 {
645 int bytes_per_row, i, j;
646
647 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
648 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
649 if (!bitmap->baseAddr)
650 abort ();
651
652 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
653 for (i = 0; i < h; i++)
654 for (j = 0; j < w; j++)
655 if (BitTst (bits, i * w + j))
656 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
657
658 SetRect (&(bitmap->bounds), 0, 0, w, h);
659 }
660
661
662 static void
663 mac_free_bitmap (bitmap)
664 BitMap *bitmap;
665 {
666 xfree (bitmap->baseAddr);
667 }
668
669 /* Mac replacement for XFillRectangle. */
670
671 static void
672 XFillRectangle (display, w, gc, x, y, width, height)
673 Display *display;
674 WindowPtr w;
675 GC gc;
676 int x, y;
677 unsigned int width, height;
678 {
679 Rect r;
680
681 #if TARGET_API_MAC_CARBON
682 SetPort (GetWindowPort (w));
683 #else
684 SetPort (w);
685 #endif
686
687 mac_set_colors (gc);
688 SetRect (&r, x, y, x + width, y + height);
689
690 PaintRect (&r); /* using foreground color of gc */
691 }
692
693
694 /* Mac replacement for XDrawRectangle: dest is a window. */
695
696 static void
697 mac_draw_rectangle (display, w, gc, x, y, width, height)
698 Display *display;
699 WindowPtr w;
700 GC gc;
701 int x, y;
702 unsigned int width, height;
703 {
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 + 1, y + height + 1);
714
715 FrameRect (&r); /* using foreground color of gc */
716 }
717
718
719 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
720
721 static void
722 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
723 Display *display;
724 Pixmap p;
725 GC gc;
726 int x, y;
727 unsigned int width, height;
728 {
729 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
730 Rect r;
731
732 #if TARGET_API_MAC_CARBON
733 SetPort (GetWindowPort (w));
734 #else
735 SetPort (w);
736 #endif
737
738 mac_set_colors (gc);
739 SetRect (&r, x, y, x + width, y + height);
740
741 FrameRect (&r); /* using foreground color of gc */
742 #endif /* 0 */
743 }
744
745
746 static void
747 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
748 bytes_per_char)
749 Display *display;
750 WindowPtr w;
751 GC gc;
752 int x, y;
753 char *buf;
754 int nchars, mode, bytes_per_char;
755 {
756 #if TARGET_API_MAC_CARBON
757 SetPort (GetWindowPort (w));
758 #else
759 SetPort (w);
760 #endif
761
762 mac_set_colors (gc);
763
764 TextFont (gc->font->mac_fontnum);
765 TextSize (gc->font->mac_fontsize);
766 TextFace (gc->font->mac_fontface);
767 TextMode (mode);
768
769 MoveTo (x, y);
770 DrawText (buf, 0, nchars * bytes_per_char);
771 }
772
773
774 /* Mac replacement for XDrawString. */
775
776 static void
777 XDrawString (display, w, gc, x, y, buf, nchars)
778 Display *display;
779 WindowPtr w;
780 GC gc;
781 int x, y;
782 char *buf;
783 int nchars;
784 {
785 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
786 }
787
788
789 /* Mac replacement for XDrawString16. */
790
791 static void
792 XDrawString16 (display, w, gc, x, y, buf, nchars)
793 Display *display;
794 WindowPtr w;
795 GC gc;
796 int x, y;
797 XChar2b *buf;
798 int nchars;
799 {
800 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
801 2);
802 }
803
804
805 /* Mac replacement for XDrawImageString. */
806
807 static void
808 XDrawImageString (display, w, gc, x, y, buf, nchars)
809 Display *display;
810 WindowPtr w;
811 GC gc;
812 int x, y;
813 char *buf;
814 int nchars;
815 {
816 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
817 }
818
819
820 /* Mac replacement for XDrawString16. */
821
822 static void
823 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
824 Display *display;
825 WindowPtr w;
826 GC gc;
827 int x, y;
828 XChar2b *buf;
829 int nchars;
830 {
831 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
832 2);
833 }
834
835
836 /* Mac replacement for XCopyArea: dest must be window. */
837
838 static void
839 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
840 dest_y)
841 Display *display;
842 Pixmap src;
843 WindowPtr dest;
844 GC gc;
845 int src_x, src_y;
846 unsigned int width, height;
847 int dest_x, dest_y;
848 {
849 Rect src_r, dest_r;
850
851 #if TARGET_API_MAC_CARBON
852 SetPort (GetWindowPort (dest));
853 #else
854 SetPort (dest);
855 #endif
856
857 mac_set_colors (gc);
858
859 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
860 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
861
862 #if TARGET_API_MAC_CARBON
863 {
864 PixMapHandle pmh;
865
866 LockPortBits (GetWindowPort (dest));
867 pmh = GetPortPixMap (GetWindowPort (dest));
868 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
869 UnlockPortBits (GetWindowPort (dest));
870 }
871 #else /* not TARGET_API_MAC_CARBON */
872 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
873 #endif /* not TARGET_API_MAC_CARBON */
874 }
875
876
877 #if 0
878 /* Convert a pair of local coordinates to global (screen) coordinates.
879 Assume graphic port has been properly set. */
880 static void
881 local_to_global_coord (short *h, short *v)
882 {
883 Point p;
884
885 p.h = *h;
886 p.v = *v;
887
888 LocalToGlobal (&p);
889
890 *h = p.h;
891 *v = p.v;
892 }
893 #endif
894
895 /* Mac replacement for XCopyArea: used only for scrolling. */
896
897 static void
898 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
899 Display *display;
900 WindowPtr w;
901 GC gc;
902 int src_x, src_y;
903 unsigned int width, height;
904 int dest_x, dest_y;
905 {
906 #if TARGET_API_MAC_CARBON
907 Rect gw_r, src_r, dest_r;
908 PixMapHandle pmh;
909
910 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
911 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
912
913 SetPort (GetWindowPort (w));
914
915 ForeColor (blackColor);
916 BackColor (whiteColor);
917
918 LockPortBits (GetWindowPort (w));
919 pmh = GetPortPixMap (GetWindowPort (w));
920 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
921 UnlockPortBits (GetWindowPort (w));
922
923 mac_set_colors (gc);
924 #else /* not TARGET_API_MAC_CARBON */
925 Rect src_r, dest_r;
926
927 SetPort (w);
928 #if 0
929 mac_set_colors (gc);
930 #endif
931
932 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
933 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
934
935 #if 0
936 /* Need to use global coordinates and screenBits since src and dest
937 areas overlap in general. */
938 local_to_global_coord (&src_r.left, &src_r.top);
939 local_to_global_coord (&src_r.right, &src_r.bottom);
940 local_to_global_coord (&dest_r.left, &dest_r.top);
941 local_to_global_coord (&dest_r.right, &dest_r.bottom);
942
943 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
944 #else
945 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
946 color mapping in CopyBits. Otherwise, it will be slow. */
947 ForeColor (blackColor);
948 BackColor (whiteColor);
949 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
950
951 mac_set_colors (gc);
952 #endif
953 #endif /* not TARGET_API_MAC_CARBON */
954 }
955
956
957 /* Mac replacement for XCopyArea: dest must be Pixmap. */
958
959 static void
960 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
961 dest_x, dest_y)
962 Display *display;
963 Pixmap src;
964 Pixmap dest;
965 GC gc;
966 int src_x, src_y;
967 unsigned int width, height;
968 int dest_x, dest_y;
969 {
970 Rect src_r, dest_r;
971 int src_right = ((PixMap *) src)->bounds.right;
972 int src_bottom = ((PixMap *) src)->bounds.bottom;
973 int w = src_right - src_x;
974 int h = src_bottom - src_y;
975
976 mac_set_colors (gc);
977
978 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
979 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
980
981 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
982 }
983
984
985 /* Mac replacement for XChangeGC. */
986
987 static void
988 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
989 XGCValues *xgcv)
990 {
991 if (mask & GCForeground)
992 gc->foreground = xgcv->foreground;
993 if (mask & GCBackground)
994 gc->background = xgcv->background;
995 if (mask & GCFont)
996 gc->font = xgcv->font;
997 }
998
999
1000 /* Mac replacement for XCreateGC. */
1001
1002 XGCValues *
1003 XCreateGC (void * ignore, Window window, unsigned long mask,
1004 XGCValues *xgcv)
1005 {
1006 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1007 bzero (gc, sizeof (XGCValues));
1008
1009 XChangeGC (ignore, gc, mask, xgcv);
1010
1011 return gc;
1012 }
1013
1014
1015 /* Used in xfaces.c. */
1016
1017 void
1018 XFreeGC (display, gc)
1019 Display *display;
1020 GC gc;
1021 {
1022 xfree (gc);
1023 }
1024
1025
1026 /* Mac replacement for XGetGCValues. */
1027
1028 static void
1029 XGetGCValues (void* ignore, XGCValues *gc,
1030 unsigned long mask, XGCValues *xgcv)
1031 {
1032 XChangeGC (ignore, xgcv, mask, gc);
1033 }
1034
1035
1036 /* Mac replacement for XSetForeground. */
1037
1038 static void
1039 XSetForeground (display, gc, color)
1040 Display *display;
1041 GC gc;
1042 unsigned long color;
1043 {
1044 gc->foreground = color;
1045 }
1046
1047
1048 /* Mac replacement for XSetFont. */
1049
1050 static void
1051 XSetFont (display, gc, font)
1052 Display *display;
1053 GC gc;
1054 XFontStruct *font;
1055 {
1056 gc->font = font;
1057 }
1058
1059
1060 static void
1061 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1062 int *direction,int *font_ascent,
1063 int *font_descent, XCharStruct *cs)
1064 {
1065 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1066 }
1067
1068
1069 /* x_sync is a no-op on Mac. */
1070 void
1071 x_sync (f)
1072 void *f;
1073 {
1074 }
1075
1076
1077 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1078 Calls to XFlush should be unnecessary because the X output buffer
1079 is flushed automatically as needed by calls to XPending,
1080 XNextEvent, or XWindowEvent according to the XFlush man page.
1081 XTread_socket calls XPending. Removing XFlush improves
1082 performance. */
1083
1084 #if TARGET_API_MAC_CARBON
1085 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1086 #else
1087 #define XFlush(DISPLAY) (void) 0
1088 #endif
1089
1090 /* Flush display of frame F, or of all frames if F is null. */
1091
1092 void
1093 x_flush (f)
1094 struct frame *f;
1095 {
1096 #if TARGET_API_MAC_CARBON
1097 BLOCK_INPUT;
1098 if (f == NULL)
1099 {
1100 Lisp_Object rest, frame;
1101 FOR_EACH_FRAME (rest, frame)
1102 x_flush (XFRAME (frame));
1103 }
1104 else if (FRAME_X_P (f))
1105 XFlush (FRAME_MAC_DISPLAY (f));
1106 UNBLOCK_INPUT;
1107 #endif /* TARGET_API_MAC_CARBON */
1108 }
1109
1110
1111 \f
1112 /* Return the struct mac_display_info corresponding to DPY. There's
1113 only one. */
1114
1115 struct mac_display_info *
1116 mac_display_info_for_display (dpy)
1117 Display *dpy;
1118 {
1119 return &one_mac_display_info;
1120 }
1121
1122
1123 \f
1124 /***********************************************************************
1125 Starting and ending an update
1126 ***********************************************************************/
1127
1128 /* Start an update of frame F. This function is installed as a hook
1129 for update_begin, i.e. it is called when update_begin is called.
1130 This function is called prior to calls to x_update_window_begin for
1131 each window being updated. */
1132
1133 static void
1134 x_update_begin (f)
1135 struct frame *f;
1136 {
1137 /* Nothing to do. */
1138 }
1139
1140
1141 /* Start update of window W. Set the global variable updated_window
1142 to the window being updated and set output_cursor to the cursor
1143 position of W. */
1144
1145 static void
1146 x_update_window_begin (w)
1147 struct window *w;
1148 {
1149 struct frame *f = XFRAME (WINDOW_FRAME (w));
1150 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1151
1152 updated_window = w;
1153 set_output_cursor (&w->cursor);
1154
1155 BLOCK_INPUT;
1156
1157 if (f == display_info->mouse_face_mouse_frame)
1158 {
1159 /* Don't do highlighting for mouse motion during the update. */
1160 display_info->mouse_face_defer = 1;
1161
1162 /* If F needs to be redrawn, simply forget about any prior mouse
1163 highlighting. */
1164 if (FRAME_GARBAGED_P (f))
1165 display_info->mouse_face_window = Qnil;
1166
1167 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1168 their mouse_face_p flag set, which means that they are always
1169 unequal to rows in a desired matrix which never have that
1170 flag set. So, rows containing mouse-face glyphs are never
1171 scrolled, and we don't have to switch the mouse highlight off
1172 here to prevent it from being scrolled. */
1173
1174 /* Can we tell that this update does not affect the window
1175 where the mouse highlight is? If so, no need to turn off.
1176 Likewise, don't do anything if the frame is garbaged;
1177 in that case, the frame's current matrix that we would use
1178 is all wrong, and we will redisplay that line anyway. */
1179 if (!NILP (display_info->mouse_face_window)
1180 && w == XWINDOW (display_info->mouse_face_window))
1181 {
1182 int i;
1183
1184 for (i = 0; i < w->desired_matrix->nrows; ++i)
1185 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1186 break;
1187
1188 if (i < w->desired_matrix->nrows)
1189 clear_mouse_face (display_info);
1190 }
1191 #endif /* 0 */
1192 }
1193
1194 UNBLOCK_INPUT;
1195 }
1196
1197
1198 /* Draw a vertical window border to the right of window W if W doesn't
1199 have vertical scroll bars. */
1200
1201 static void
1202 x_draw_vertical_border (w)
1203 struct window *w;
1204 {
1205 struct frame *f = XFRAME (WINDOW_FRAME (w));
1206
1207 /* Redraw borders between horizontally adjacent windows. Don't
1208 do it for frames with vertical scroll bars because either the
1209 right scroll bar of a window, or the left scroll bar of its
1210 neighbor will suffice as a border. */
1211 if (!WINDOW_RIGHTMOST_P (w)
1212 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1213 {
1214 int x0, x1, y0, y1;
1215
1216 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1217 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1218 y1 -= 1;
1219
1220 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1221 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1222 }
1223 }
1224
1225
1226 /* End update of window W (which is equal to updated_window).
1227
1228 Draw vertical borders between horizontally adjacent windows, and
1229 display W's cursor if CURSOR_ON_P is non-zero.
1230
1231 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1232 glyphs in mouse-face were overwritten. In that case we have to
1233 make sure that the mouse-highlight is properly redrawn.
1234
1235 W may be a menu bar pseudo-window in case we don't have X toolkit
1236 support. Such windows don't have a cursor, so don't display it
1237 here. */
1238
1239 static void
1240 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1241 struct window *w;
1242 int cursor_on_p, mouse_face_overwritten_p;
1243 {
1244 struct mac_display_info *dpyinfo
1245 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1246
1247 if (!w->pseudo_window_p)
1248 {
1249 BLOCK_INPUT;
1250
1251 if (cursor_on_p)
1252 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1253 output_cursor.vpos,
1254 output_cursor.x, output_cursor.y);
1255
1256 x_draw_vertical_border (w);
1257 UNBLOCK_INPUT;
1258 }
1259
1260 /* If a row with mouse-face was overwritten, arrange for
1261 XTframe_up_to_date to redisplay the mouse highlight. */
1262 if (mouse_face_overwritten_p)
1263 {
1264 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1265 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1266 dpyinfo->mouse_face_window = Qnil;
1267 }
1268
1269 #if 0
1270 /* Unhide the caret. This won't actually show the cursor, unless it
1271 was visible before the corresponding call to HideCaret in
1272 x_update_window_begin. */
1273 if (w32_use_visible_system_caret)
1274 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1275 #endif
1276
1277 updated_window = NULL;
1278 }
1279
1280
1281 /* End update of frame F. This function is installed as a hook in
1282 update_end. */
1283
1284 static void
1285 x_update_end (f)
1286 struct frame *f;
1287 {
1288 /* Reset the background color of Mac OS Window to that of the frame after
1289 update so that it is used by Mac Toolbox to clear the update region before
1290 an update event is generated. */
1291 #if TARGET_API_MAC_CARBON
1292 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1293 #else
1294 SetPort (FRAME_MAC_WINDOW (f));
1295 #endif
1296
1297 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1298
1299 /* Mouse highlight may be displayed again. */
1300 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1301
1302 BLOCK_INPUT;
1303 XFlush (FRAME_MAC_DISPLAY (f));
1304 UNBLOCK_INPUT;
1305 }
1306
1307
1308 /* This function is called from various places in xdisp.c whenever a
1309 complete update has been performed. The global variable
1310 updated_window is not available here. */
1311
1312 static void
1313 XTframe_up_to_date (f)
1314 struct frame *f;
1315 {
1316 if (FRAME_X_P (f))
1317 {
1318 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1319
1320 if (dpyinfo->mouse_face_deferred_gc
1321 || f == dpyinfo->mouse_face_mouse_frame)
1322 {
1323 BLOCK_INPUT;
1324 if (dpyinfo->mouse_face_mouse_frame)
1325 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1326 dpyinfo->mouse_face_mouse_x,
1327 dpyinfo->mouse_face_mouse_y);
1328 dpyinfo->mouse_face_deferred_gc = 0;
1329 UNBLOCK_INPUT;
1330 }
1331 }
1332 }
1333
1334
1335 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1336 arrow bitmaps, or clear the fringes if no bitmaps are required
1337 before DESIRED_ROW is made current. The window being updated is
1338 found in updated_window. This function is called from
1339 update_window_line only if it is known that there are differences
1340 between bitmaps to be drawn between current row and DESIRED_ROW. */
1341
1342 static void
1343 x_after_update_window_line (desired_row)
1344 struct glyph_row *desired_row;
1345 {
1346 struct window *w = updated_window;
1347 struct frame *f;
1348 int width, height;
1349
1350 xassert (w);
1351
1352 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1353 {
1354 BLOCK_INPUT;
1355 draw_row_fringe_bitmaps (w, desired_row);
1356 UNBLOCK_INPUT;
1357 }
1358
1359 /* When a window has disappeared, make sure that no rest of
1360 full-width rows stays visible in the internal border. Could
1361 check here if updated_window is the leftmost/rightmost window,
1362 but I guess it's not worth doing since vertically split windows
1363 are almost never used, internal border is rarely set, and the
1364 overhead is very small. */
1365 if (windows_or_buffers_changed
1366 && desired_row->full_width_p
1367 && (f = XFRAME (w->frame),
1368 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1369 width != 0)
1370 && (height = desired_row->visible_height,
1371 height > 0))
1372 {
1373 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1374 /* Internal border is drawn below the tool bar. */
1375 if (WINDOWP (f->tool_bar_window)
1376 && w == XWINDOW (f->tool_bar_window))
1377 y -= width;
1378
1379 BLOCK_INPUT;
1380
1381 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1382 0, y, width, height, 0);
1383 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1384 f->output_data.mac->pixel_width - width, y,
1385 width, height, 0);
1386
1387 UNBLOCK_INPUT;
1388 }
1389 }
1390
1391
1392 /* Draw the bitmap WHICH in one of the left or right fringes of
1393 window W. ROW is the glyph row for which to display the bitmap; it
1394 determines the vertical position at which the bitmap has to be
1395 drawn. */
1396
1397 static void
1398 x_draw_fringe_bitmap (w, row, p)
1399 struct window *w;
1400 struct glyph_row *row;
1401 struct draw_fringe_bitmap_params *p;
1402 {
1403 struct frame *f = XFRAME (WINDOW_FRAME (w));
1404 Display *display = FRAME_MAC_DISPLAY (f);
1405 WindowPtr window = FRAME_MAC_WINDOW (f);
1406 XGCValues gcv;
1407 GC gc = f->output_data.mac->normal_gc;
1408 struct face *face = p->face;
1409
1410 /* Must clip because of partially visible lines. */
1411 x_clip_to_row (w, row, gc, 1);
1412
1413 if (p->bx >= 0)
1414 {
1415 XGCValues gcv;
1416 gcv.foreground = face->background;
1417
1418 #if 0 /* MAC_TODO: stipple */
1419 /* In case the same realized face is used for fringes and
1420 for something displayed in the text (e.g. face `region' on
1421 mono-displays, the fill style may have been changed to
1422 FillSolid in x_draw_glyph_string_background. */
1423 if (face->stipple)
1424 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1425 else
1426 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1427 #endif
1428
1429 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1430 &gcv,
1431 p->bx, p->by, p->nx, p->ny);
1432
1433 #if 0 /* MAC_TODO: stipple */
1434 if (!face->stipple)
1435 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1436 #endif
1437 }
1438
1439 if (p->which != NO_FRINGE_BITMAP)
1440 {
1441 unsigned char *bits = fringe_bitmaps[p->which].bits + p->dh;
1442 BitMap bitmap;
1443
1444 mac_create_bitmap_from_bitmap_data (&bitmap, bits, p->wd, p->h);
1445 gcv.foreground = face->foreground;
1446 gcv.background = face->background;
1447
1448 mac_draw_bitmap (display, window, &gcv, p->x, p->y, &bitmap);
1449
1450 mac_free_bitmap (&bitmap);
1451 }
1452
1453 mac_reset_clipping (display, window);
1454 }
1455
1456 \f
1457 /* This is called when starting Emacs and when restarting after
1458 suspend. When starting Emacs, no window is mapped. And nothing
1459 must be done to Emacs's own window if it is suspended (though that
1460 rarely happens). */
1461
1462 static void
1463 XTset_terminal_modes ()
1464 {
1465 }
1466
1467 /* This is called when exiting or suspending Emacs. Exiting will make
1468 the windows go away, and suspending requires no action. */
1469
1470 static void
1471 XTreset_terminal_modes ()
1472 {
1473 }
1474
1475
1476 \f
1477 /***********************************************************************
1478 Output Cursor
1479 ***********************************************************************/
1480
1481 /* Set the global variable output_cursor to CURSOR. All cursor
1482 positions are relative to updated_window. */
1483
1484 static void
1485 set_output_cursor (cursor)
1486 struct cursor_pos *cursor;
1487 {
1488 output_cursor.hpos = cursor->hpos;
1489 output_cursor.vpos = cursor->vpos;
1490 output_cursor.x = cursor->x;
1491 output_cursor.y = cursor->y;
1492 }
1493
1494
1495 /* Set a nominal cursor position.
1496
1497 HPOS and VPOS are column/row positions in a window glyph matrix. X
1498 and Y are window text area relative pixel positions.
1499
1500 If this is done during an update, updated_window will contain the
1501 window that is being updated and the position is the future output
1502 cursor position for that window. If updated_window is null, use
1503 selected_window and display the cursor at the given position. */
1504
1505 static void
1506 XTcursor_to (vpos, hpos, y, x)
1507 int vpos, hpos, y, x;
1508 {
1509 struct window *w;
1510
1511 /* If updated_window is not set, work on selected_window. */
1512 if (updated_window)
1513 w = updated_window;
1514 else
1515 w = XWINDOW (selected_window);
1516
1517 /* Set the output cursor. */
1518 output_cursor.hpos = hpos;
1519 output_cursor.vpos = vpos;
1520 output_cursor.x = x;
1521 output_cursor.y = y;
1522
1523 /* If not called as part of an update, really display the cursor.
1524 This will also set the cursor position of W. */
1525 if (updated_window == NULL)
1526 {
1527 BLOCK_INPUT;
1528 x_display_cursor (w, 1, hpos, vpos, x, y);
1529 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1530 UNBLOCK_INPUT;
1531 }
1532 }
1533
1534
1535 \f
1536 /***********************************************************************
1537 Display Iterator
1538 ***********************************************************************/
1539
1540 /* Function prototypes of this page. */
1541
1542 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1543 struct glyph *,
1544 XChar2b *,
1545 int *));
1546 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1547 int, XChar2b *, int));
1548 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1549 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1550 static void x_append_glyph P_ ((struct it *));
1551 static void x_append_composite_glyph P_ ((struct it *));
1552 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1553 int, int, double));
1554 static void x_produce_glyphs P_ ((struct it *));
1555 static void x_produce_image_glyph P_ ((struct it *it));
1556
1557
1558 /* Return a pointer to per-char metric information in FONT of a
1559 character pointed by B which is a pointer to an XChar2b. */
1560
1561 #define PER_CHAR_METRIC(font, b) \
1562 ((font)->per_char \
1563 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1564 + (((font)->min_byte1 || (font)->max_byte1) \
1565 ? (((b)->byte1 - (font)->min_byte1) \
1566 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1567 : 0)) \
1568 : &((font)->max_bounds))
1569
1570
1571 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1572 is not contained in the font. */
1573
1574 static INLINE XCharStruct *
1575 x_per_char_metric (font, char2b)
1576 XFontStruct *font;
1577 XChar2b *char2b;
1578 {
1579 /* The result metric information. */
1580 XCharStruct *pcm = NULL;
1581
1582 xassert (font && char2b);
1583
1584 if (font->per_char != NULL)
1585 {
1586 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1587 {
1588 /* min_char_or_byte2 specifies the linear character index
1589 corresponding to the first element of the per_char array,
1590 max_char_or_byte2 is the index of the last character. A
1591 character with non-zero CHAR2B->byte1 is not in the font.
1592 A character with byte2 less than min_char_or_byte2 or
1593 greater max_char_or_byte2 is not in the font. */
1594 if (char2b->byte1 == 0
1595 && char2b->byte2 >= font->min_char_or_byte2
1596 && char2b->byte2 <= font->max_char_or_byte2)
1597 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1598 }
1599 else
1600 {
1601 /* If either min_byte1 or max_byte1 are nonzero, both
1602 min_char_or_byte2 and max_char_or_byte2 are less than
1603 256, and the 2-byte character index values corresponding
1604 to the per_char array element N (counting from 0) are:
1605
1606 byte1 = N/D + min_byte1
1607 byte2 = N\D + min_char_or_byte2
1608
1609 where:
1610
1611 D = max_char_or_byte2 - min_char_or_byte2 + 1
1612 / = integer division
1613 \ = integer modulus */
1614 if (char2b->byte1 >= font->min_byte1
1615 && char2b->byte1 <= font->max_byte1
1616 && char2b->byte2 >= font->min_char_or_byte2
1617 && char2b->byte2 <= font->max_char_or_byte2)
1618 {
1619 pcm = (font->per_char
1620 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1621 * (char2b->byte1 - font->min_byte1))
1622 + (char2b->byte2 - font->min_char_or_byte2));
1623 }
1624 }
1625 }
1626 else
1627 {
1628 /* If the per_char pointer is null, all glyphs between the first
1629 and last character indexes inclusive have the same
1630 information, as given by both min_bounds and max_bounds. */
1631 if (char2b->byte2 >= font->min_char_or_byte2
1632 && char2b->byte2 <= font->max_char_or_byte2)
1633 pcm = &font->max_bounds;
1634 }
1635
1636 return ((pcm == NULL
1637 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1638 ? NULL : pcm);
1639 }
1640
1641
1642 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1643 the two-byte form of C. Encoding is returned in *CHAR2B. */
1644
1645 static INLINE void
1646 x_encode_char (c, char2b, font_info)
1647 int c;
1648 XChar2b *char2b;
1649 struct font_info *font_info;
1650 {
1651 int charset = CHAR_CHARSET (c);
1652 XFontStruct *font = font_info->font;
1653
1654 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1655 This may be either a program in a special encoder language or a
1656 fixed encoding. */
1657 if (font_info->font_encoder)
1658 {
1659 /* It's a program. */
1660 struct ccl_program *ccl = font_info->font_encoder;
1661
1662 if (CHARSET_DIMENSION (charset) == 1)
1663 {
1664 ccl->reg[0] = charset;
1665 ccl->reg[1] = char2b->byte2;
1666 }
1667 else
1668 {
1669 ccl->reg[0] = charset;
1670 ccl->reg[1] = char2b->byte1;
1671 ccl->reg[2] = char2b->byte2;
1672 }
1673
1674 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1675
1676 /* We assume that MSBs are appropriately set/reset by CCL
1677 program. */
1678 if (font->max_byte1 == 0) /* 1-byte font */
1679 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1680 else
1681 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1682 }
1683 else if (font_info->encoding[charset])
1684 {
1685 /* Fixed encoding scheme. See fontset.h for the meaning of the
1686 encoding numbers. */
1687 int enc = font_info->encoding[charset];
1688
1689 if ((enc == 1 || enc == 2)
1690 && CHARSET_DIMENSION (charset) == 2)
1691 char2b->byte1 |= 0x80;
1692
1693 if (enc == 1 || enc == 3)
1694 char2b->byte2 |= 0x80;
1695
1696 if (enc == 4)
1697 {
1698 int sjis1, sjis2;
1699
1700 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1701 char2b->byte1 = sjis1;
1702 char2b->byte2 = sjis2;
1703 }
1704 }
1705 }
1706
1707
1708 /* Get face and two-byte form of character C in face FACE_ID on frame
1709 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1710 means we want to display multibyte text. Value is a pointer to a
1711 realized face that is ready for display. */
1712
1713 static INLINE struct face *
1714 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1715 struct frame *f;
1716 int c, face_id;
1717 XChar2b *char2b;
1718 int multibyte_p;
1719 {
1720 struct face *face = FACE_FROM_ID (f, face_id);
1721
1722 if (!multibyte_p)
1723 {
1724 /* Unibyte case. We don't have to encode, but we have to make
1725 sure to use a face suitable for unibyte. */
1726 char2b->byte1 = 0;
1727 char2b->byte2 = c;
1728 face_id = FACE_FOR_CHAR (f, face, c);
1729 face = FACE_FROM_ID (f, face_id);
1730 }
1731 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1732 {
1733 /* Case of ASCII in a face known to fit ASCII. */
1734 char2b->byte1 = 0;
1735 char2b->byte2 = c;
1736 }
1737 else
1738 {
1739 int c1, c2, charset;
1740
1741 /* Split characters into bytes. If c2 is -1 afterwards, C is
1742 really a one-byte character so that byte1 is zero. */
1743 SPLIT_CHAR (c, charset, c1, c2);
1744 if (c2 > 0)
1745 char2b->byte1 = c1, char2b->byte2 = c2;
1746 else
1747 char2b->byte1 = 0, char2b->byte2 = c1;
1748
1749 /* Maybe encode the character in *CHAR2B. */
1750 if (face->font != NULL)
1751 {
1752 struct font_info *font_info
1753 = FONT_INFO_FROM_ID (f, face->font_info_id);
1754 if (font_info)
1755 x_encode_char (c, char2b, font_info);
1756 }
1757 }
1758
1759 /* Make sure X resources of the face are allocated. */
1760 xassert (face != NULL);
1761 PREPARE_FACE_FOR_DISPLAY (f, face);
1762
1763 return face;
1764 }
1765
1766
1767 /* Get face and two-byte form of character glyph GLYPH on frame F.
1768 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1769 a pointer to a realized face that is ready for display. */
1770
1771 static INLINE struct face *
1772 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1773 struct frame *f;
1774 struct glyph *glyph;
1775 XChar2b *char2b;
1776 int *two_byte_p;
1777 {
1778 struct face *face;
1779
1780 xassert (glyph->type == CHAR_GLYPH);
1781 face = FACE_FROM_ID (f, glyph->face_id);
1782
1783 if (two_byte_p)
1784 *two_byte_p = 0;
1785
1786 if (!glyph->multibyte_p)
1787 {
1788 /* Unibyte case. We don't have to encode, but we have to make
1789 sure to use a face suitable for unibyte. */
1790 char2b->byte1 = 0;
1791 char2b->byte2 = glyph->u.ch;
1792 }
1793 else if (glyph->u.ch < 128
1794 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1795 {
1796 /* Case of ASCII in a face known to fit ASCII. */
1797 char2b->byte1 = 0;
1798 char2b->byte2 = glyph->u.ch;
1799 }
1800 else
1801 {
1802 int c1, c2, charset;
1803
1804 /* Split characters into bytes. If c2 is -1 afterwards, C is
1805 really a one-byte character so that byte1 is zero. */
1806 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1807 if (c2 > 0)
1808 char2b->byte1 = c1, char2b->byte2 = c2;
1809 else
1810 char2b->byte1 = 0, char2b->byte2 = c1;
1811
1812 /* Maybe encode the character in *CHAR2B. */
1813 if (charset != CHARSET_ASCII)
1814 {
1815 struct font_info *font_info
1816 = FONT_INFO_FROM_ID (f, face->font_info_id);
1817 if (font_info)
1818 {
1819 x_encode_char (glyph->u.ch, char2b, font_info);
1820 if (two_byte_p)
1821 *two_byte_p
1822 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1823 }
1824 }
1825 }
1826
1827 /* Make sure X resources of the face are allocated. */
1828 xassert (face != NULL);
1829 PREPARE_FACE_FOR_DISPLAY (f, face);
1830 return face;
1831 }
1832
1833
1834 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1835 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1836
1837 static INLINE void
1838 x_append_glyph (it)
1839 struct it *it;
1840 {
1841 struct glyph *glyph;
1842 enum glyph_row_area area = it->area;
1843
1844 xassert (it->glyph_row);
1845 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1846
1847 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1848 if (glyph < it->glyph_row->glyphs[area + 1])
1849 {
1850 glyph->charpos = CHARPOS (it->position);
1851 glyph->object = it->object;
1852 glyph->pixel_width = it->pixel_width;
1853 glyph->voffset = it->voffset;
1854 glyph->type = CHAR_GLYPH;
1855 glyph->multibyte_p = it->multibyte_p;
1856 glyph->left_box_line_p = it->start_of_box_run_p;
1857 glyph->right_box_line_p = it->end_of_box_run_p;
1858 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1859 || it->phys_descent > it->descent);
1860 glyph->padding_p = 0;
1861 glyph->glyph_not_available_p = it->glyph_not_available_p;
1862 glyph->face_id = it->face_id;
1863 glyph->u.ch = it->char_to_display;
1864 ++it->glyph_row->used[area];
1865 }
1866 }
1867
1868 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1869 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1870
1871 static INLINE void
1872 x_append_composite_glyph (it)
1873 struct it *it;
1874 {
1875 struct glyph *glyph;
1876 enum glyph_row_area area = it->area;
1877
1878 xassert (it->glyph_row);
1879
1880 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1881 if (glyph < it->glyph_row->glyphs[area + 1])
1882 {
1883 glyph->charpos = CHARPOS (it->position);
1884 glyph->object = it->object;
1885 glyph->pixel_width = it->pixel_width;
1886 glyph->voffset = it->voffset;
1887 glyph->type = COMPOSITE_GLYPH;
1888 glyph->multibyte_p = it->multibyte_p;
1889 glyph->left_box_line_p = it->start_of_box_run_p;
1890 glyph->right_box_line_p = it->end_of_box_run_p;
1891 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1892 || it->phys_descent > it->descent);
1893 glyph->padding_p = 0;
1894 glyph->glyph_not_available_p = 0;
1895 glyph->face_id = it->face_id;
1896 glyph->u.cmp_id = it->cmp_id;
1897 ++it->glyph_row->used[area];
1898 }
1899 }
1900
1901
1902 /* Change IT->ascent and IT->height according to the setting of
1903 IT->voffset. */
1904
1905 static INLINE void
1906 take_vertical_position_into_account (it)
1907 struct it *it;
1908 {
1909 if (it->voffset)
1910 {
1911 if (it->voffset < 0)
1912 /* Increase the ascent so that we can display the text higher
1913 in the line. */
1914 it->ascent += abs (it->voffset);
1915 else
1916 /* Increase the descent so that we can display the text lower
1917 in the line. */
1918 it->descent += it->voffset;
1919 }
1920 }
1921
1922
1923 /* Produce glyphs/get display metrics for the image IT is loaded with.
1924 See the description of struct display_iterator in dispextern.h for
1925 an overview of struct display_iterator. */
1926
1927 static void
1928 x_produce_image_glyph (it)
1929 struct it *it;
1930 {
1931 struct image *img;
1932 struct face *face;
1933
1934 xassert (it->what == IT_IMAGE);
1935
1936 face = FACE_FROM_ID (it->f, it->face_id);
1937 img = IMAGE_FROM_ID (it->f, it->image_id);
1938 xassert (img);
1939
1940 /* Make sure X resources of the face and image are loaded. */
1941 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1942 prepare_image_for_display (it->f, img);
1943
1944 it->ascent = it->phys_ascent = image_ascent (img, face);
1945 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1946 it->pixel_width = img->width + 2 * img->hmargin;
1947
1948 it->nglyphs = 1;
1949
1950 if (face->box != FACE_NO_BOX)
1951 {
1952 if (face->box_line_width > 0)
1953 {
1954 it->ascent += face->box_line_width;
1955 it->descent += face->box_line_width;
1956 }
1957
1958 if (it->start_of_box_run_p)
1959 it->pixel_width += abs (face->box_line_width);
1960 if (it->end_of_box_run_p)
1961 it->pixel_width += abs (face->box_line_width);
1962 }
1963
1964 take_vertical_position_into_account (it);
1965
1966 if (it->glyph_row)
1967 {
1968 struct glyph *glyph;
1969 enum glyph_row_area area = it->area;
1970
1971 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1972 if (glyph < it->glyph_row->glyphs[area + 1])
1973 {
1974 glyph->charpos = CHARPOS (it->position);
1975 glyph->object = it->object;
1976 glyph->pixel_width = it->pixel_width;
1977 glyph->voffset = it->voffset;
1978 glyph->type = IMAGE_GLYPH;
1979 glyph->multibyte_p = it->multibyte_p;
1980 glyph->left_box_line_p = it->start_of_box_run_p;
1981 glyph->right_box_line_p = it->end_of_box_run_p;
1982 glyph->overlaps_vertically_p = 0;
1983 glyph->padding_p = 0;
1984 glyph->glyph_not_available_p = 0;
1985 glyph->face_id = it->face_id;
1986 glyph->u.img_id = img->id;
1987 ++it->glyph_row->used[area];
1988 }
1989 }
1990 }
1991
1992
1993 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1994 of the glyph, WIDTH and HEIGHT are the width and height of the
1995 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1996 ascent of the glyph (0 <= ASCENT <= 1). */
1997
1998 static void
1999 x_append_stretch_glyph (it, object, width, height, ascent)
2000 struct it *it;
2001 Lisp_Object object;
2002 int width, height;
2003 double ascent;
2004 {
2005 struct glyph *glyph;
2006 enum glyph_row_area area = it->area;
2007
2008 xassert (ascent >= 0 && ascent <= 1);
2009
2010 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2011 if (glyph < it->glyph_row->glyphs[area + 1])
2012 {
2013 glyph->charpos = CHARPOS (it->position);
2014 glyph->object = object;
2015 glyph->pixel_width = width;
2016 glyph->voffset = it->voffset;
2017 glyph->type = STRETCH_GLYPH;
2018 glyph->multibyte_p = it->multibyte_p;
2019 glyph->left_box_line_p = it->start_of_box_run_p;
2020 glyph->right_box_line_p = it->end_of_box_run_p;
2021 glyph->overlaps_vertically_p = 0;
2022 glyph->padding_p = 0;
2023 glyph->glyph_not_available_p = 0;
2024 glyph->face_id = it->face_id;
2025 glyph->u.stretch.ascent = height * ascent;
2026 glyph->u.stretch.height = height;
2027 ++it->glyph_row->used[area];
2028 }
2029 }
2030
2031
2032 /* Produce a stretch glyph for iterator IT. IT->object is the value
2033 of the glyph property displayed. The value must be a list
2034 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2035 being recognized:
2036
2037 1. `:width WIDTH' specifies that the space should be WIDTH *
2038 canonical char width wide. WIDTH may be an integer or floating
2039 point number.
2040
2041 2. `:relative-width FACTOR' specifies that the width of the stretch
2042 should be computed from the width of the first character having the
2043 `glyph' property, and should be FACTOR times that width.
2044
2045 3. `:align-to HPOS' specifies that the space should be wide enough
2046 to reach HPOS, a value in canonical character units.
2047
2048 Exactly one of the above pairs must be present.
2049
2050 4. `:height HEIGHT' specifies that the height of the stretch produced
2051 should be HEIGHT, measured in canonical character units.
2052
2053 5. `:relative-height FACTOR' specifies that the height of the
2054 stretch should be FACTOR times the height of the characters having
2055 the glyph property.
2056
2057 Either none or exactly one of 4 or 5 must be present.
2058
2059 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2060 of the stretch should be used for the ascent of the stretch.
2061 ASCENT must be in the range 0 <= ASCENT <= 100. */
2062
2063 #define NUMVAL(X) \
2064 ((INTEGERP (X) || FLOATP (X)) \
2065 ? XFLOATINT (X) \
2066 : - 1)
2067
2068
2069 static void
2070 x_produce_stretch_glyph (it)
2071 struct it *it;
2072 {
2073 /* (space :width WIDTH :height HEIGHT. */
2074 #if GLYPH_DEBUG
2075 extern Lisp_Object Qspace;
2076 #endif
2077 extern Lisp_Object QCwidth, QCheight, QCascent;
2078 extern Lisp_Object QCrelative_width, QCrelative_height;
2079 extern Lisp_Object QCalign_to;
2080 Lisp_Object prop, plist;
2081 double width = 0, height = 0, ascent = 0;
2082 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2083 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2084
2085 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2086
2087 /* List should start with `space'. */
2088 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2089 plist = XCDR (it->object);
2090
2091 /* Compute the width of the stretch. */
2092 if (prop = Fplist_get (plist, QCwidth),
2093 NUMVAL (prop) > 0)
2094 /* Absolute width `:width WIDTH' specified and valid. */
2095 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2096 else if (prop = Fplist_get (plist, QCrelative_width),
2097 NUMVAL (prop) > 0)
2098 {
2099 /* Relative width `:relative-width FACTOR' specified and valid.
2100 Compute the width of the characters having the `glyph'
2101 property. */
2102 struct it it2;
2103 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2104
2105 it2 = *it;
2106 if (it->multibyte_p)
2107 {
2108 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2109 - IT_BYTEPOS (*it));
2110 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2111 }
2112 else
2113 it2.c = *p, it2.len = 1;
2114
2115 it2.glyph_row = NULL;
2116 it2.what = IT_CHARACTER;
2117 x_produce_glyphs (&it2);
2118 width = NUMVAL (prop) * it2.pixel_width;
2119 }
2120 else if (prop = Fplist_get (plist, QCalign_to),
2121 NUMVAL (prop) > 0)
2122 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2123 else
2124 /* Nothing specified -> width defaults to canonical char width. */
2125 width = CANON_X_UNIT (it->f);
2126
2127 /* Compute height. */
2128 if (prop = Fplist_get (plist, QCheight),
2129 NUMVAL (prop) > 0)
2130 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2131 else if (prop = Fplist_get (plist, QCrelative_height),
2132 NUMVAL (prop) > 0)
2133 height = FONT_HEIGHT (font) * NUMVAL (prop);
2134 else
2135 height = FONT_HEIGHT (font);
2136
2137 /* Compute percentage of height used for ascent. If
2138 `:ascent ASCENT' is present and valid, use that. Otherwise,
2139 derive the ascent from the font in use. */
2140 if (prop = Fplist_get (plist, QCascent),
2141 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2142 ascent = NUMVAL (prop) / 100.0;
2143 else
2144 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
2145
2146 if (width <= 0)
2147 width = 1;
2148 if (height <= 0)
2149 height = 1;
2150
2151 if (it->glyph_row)
2152 {
2153 Lisp_Object object = it->stack[it->sp - 1].string;
2154 if (!STRINGP (object))
2155 object = it->w->buffer;
2156 x_append_stretch_glyph (it, object, width, height, ascent);
2157 }
2158
2159 it->pixel_width = width;
2160 it->ascent = it->phys_ascent = height * ascent;
2161 it->descent = it->phys_descent = height - it->ascent;
2162 it->nglyphs = 1;
2163
2164 if (face->box != FACE_NO_BOX)
2165 {
2166 if (face->box_line_width > 0)
2167 {
2168 it->ascent += face->box_line_width;
2169 it->descent += face->box_line_width;
2170 }
2171
2172 if (it->start_of_box_run_p)
2173 it->pixel_width += abs (face->box_line_width);
2174 if (it->end_of_box_run_p)
2175 it->pixel_width += abs (face->box_line_width);
2176 }
2177
2178 take_vertical_position_into_account (it);
2179 }
2180
2181 /* Return proper value to be used as baseline offset of font that has
2182 ASCENT and DESCENT to draw characters by the font at the vertical
2183 center of the line of frame F.
2184
2185 Here, out task is to find the value of BOFF in the following figure;
2186
2187 -------------------------+-----------+-
2188 -+-+---------+-+ | |
2189 | | | | | |
2190 | | | | F_ASCENT F_HEIGHT
2191 | | | ASCENT | |
2192 HEIGHT | | | | |
2193 | | |-|-+------+-----------|------- baseline
2194 | | | | BOFF | |
2195 | |---------|-+-+ | |
2196 | | | DESCENT | |
2197 -+-+---------+-+ F_DESCENT |
2198 -------------------------+-----------+-
2199
2200 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2201 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2202 DESCENT = FONT->descent
2203 HEIGHT = FONT_HEIGHT (FONT)
2204 F_DESCENT = (F->output_data.x->font->descent
2205 - F->output_data.x->baseline_offset)
2206 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2207 */
2208
2209 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2210 (FONT_DESCENT (FONT) \
2211 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2212 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2213 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2214
2215 /* Produce glyphs/get display metrics for the display element IT is
2216 loaded with. See the description of struct display_iterator in
2217 dispextern.h for an overview of struct display_iterator. */
2218
2219 static void
2220 x_produce_glyphs (it)
2221 struct it *it;
2222 {
2223 it->glyph_not_available_p = 0;
2224
2225 if (it->what == IT_CHARACTER)
2226 {
2227 XChar2b char2b;
2228 XFontStruct *font;
2229 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2230 XCharStruct *pcm;
2231 int font_not_found_p;
2232 struct font_info *font_info;
2233 int boff; /* baseline offset */
2234 /* We may change it->multibyte_p upon unibyte<->multibyte
2235 conversion. So, save the current value now and restore it
2236 later.
2237
2238 Note: It seems that we don't have to record multibyte_p in
2239 struct glyph because the character code itself tells if or
2240 not the character is multibyte. Thus, in the future, we must
2241 consider eliminating the field `multibyte_p' in the struct
2242 glyph.
2243 */
2244 int saved_multibyte_p = it->multibyte_p;
2245
2246 /* Maybe translate single-byte characters to multibyte, or the
2247 other way. */
2248 it->char_to_display = it->c;
2249 if (!ASCII_BYTE_P (it->c))
2250 {
2251 if (unibyte_display_via_language_environment
2252 && SINGLE_BYTE_CHAR_P (it->c)
2253 && (it->c >= 0240
2254 || !NILP (Vnonascii_translation_table)))
2255 {
2256 it->char_to_display = unibyte_char_to_multibyte (it->c);
2257 it->multibyte_p = 1;
2258 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2259 face = FACE_FROM_ID (it->f, it->face_id);
2260 }
2261 else if (!SINGLE_BYTE_CHAR_P (it->c)
2262 && !it->multibyte_p)
2263 {
2264 it->multibyte_p = 1;
2265 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2266 face = FACE_FROM_ID (it->f, it->face_id);
2267 }
2268 }
2269
2270 /* Get font to use. Encode IT->char_to_display. */
2271 x_get_char_face_and_encoding (it->f, it->char_to_display,
2272 it->face_id, &char2b,
2273 it->multibyte_p);
2274 font = face->font;
2275
2276 /* When no suitable font found, use the default font. */
2277 font_not_found_p = font == NULL;
2278 if (font_not_found_p)
2279 {
2280 font = FRAME_FONT (it->f);
2281 boff = it->f->output_data.mac->baseline_offset;
2282 font_info = NULL;
2283 }
2284 else
2285 {
2286 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2287 boff = font_info->baseline_offset;
2288 if (font_info->vertical_centering)
2289 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2290 }
2291
2292 if (it->char_to_display >= ' '
2293 && (!it->multibyte_p || it->char_to_display < 128))
2294 {
2295 /* Either unibyte or ASCII. */
2296 int stretched_p;
2297
2298 it->nglyphs = 1;
2299
2300 pcm = x_per_char_metric (font, &char2b);
2301 it->ascent = FONT_BASE (font) + boff;
2302 it->descent = FONT_DESCENT (font) - boff;
2303
2304 if (pcm)
2305 {
2306 it->phys_ascent = pcm->ascent + boff;
2307 it->phys_descent = pcm->descent - boff;
2308 it->pixel_width = pcm->width;
2309 }
2310 else
2311 {
2312 it->glyph_not_available_p = 1;
2313 it->phys_ascent = FONT_BASE (font) + boff;
2314 it->phys_descent = FONT_DESCENT (font) - boff;
2315 it->pixel_width = FONT_WIDTH (font);
2316 }
2317
2318 /* If this is a space inside a region of text with
2319 `space-width' property, change its width. */
2320 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2321 if (stretched_p)
2322 it->pixel_width *= XFLOATINT (it->space_width);
2323
2324 /* If face has a box, add the box thickness to the character
2325 height. If character has a box line to the left and/or
2326 right, add the box line width to the character's width. */
2327 if (face->box != FACE_NO_BOX)
2328 {
2329 int thick = face->box_line_width;
2330
2331 if (thick > 0)
2332 {
2333 it->ascent += thick;
2334 it->descent += thick;
2335 }
2336 else
2337 thick = -thick;
2338
2339 if (it->start_of_box_run_p)
2340 it->pixel_width += thick;
2341 if (it->end_of_box_run_p)
2342 it->pixel_width += thick;
2343 }
2344
2345 /* If face has an overline, add the height of the overline
2346 (1 pixel) and a 1 pixel margin to the character height. */
2347 if (face->overline_p)
2348 it->ascent += 2;
2349
2350 take_vertical_position_into_account (it);
2351
2352 /* If we have to actually produce glyphs, do it. */
2353 if (it->glyph_row)
2354 {
2355 if (stretched_p)
2356 {
2357 /* Translate a space with a `space-width' property
2358 into a stretch glyph. */
2359 double ascent = (double) FONT_BASE (font)
2360 / FONT_HEIGHT (font);
2361 x_append_stretch_glyph (it, it->object, it->pixel_width,
2362 it->ascent + it->descent, ascent);
2363 }
2364 else
2365 x_append_glyph (it);
2366
2367 /* If characters with lbearing or rbearing are displayed
2368 in this line, record that fact in a flag of the
2369 glyph row. This is used to optimize X output code. */
2370 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2371 it->glyph_row->contains_overlapping_glyphs_p = 1;
2372 }
2373 }
2374 else if (it->char_to_display == '\n')
2375 {
2376 /* A newline has no width but we need the height of the line. */
2377 it->pixel_width = 0;
2378 it->nglyphs = 0;
2379 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2380 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2381
2382 if (face->box != FACE_NO_BOX
2383 && face->box_line_width > 0)
2384 {
2385 it->ascent += face->box_line_width;
2386 it->descent += face->box_line_width;
2387 }
2388 }
2389 else if (it->char_to_display == '\t')
2390 {
2391 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2392 int x = it->current_x + it->continuation_lines_width;
2393 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2394
2395 /* If the distance from the current position to the next tab
2396 stop is less than a canonical character width, use the
2397 tab stop after that. */
2398 if (next_tab_x - x < CANON_X_UNIT (it->f))
2399 next_tab_x += tab_width;
2400
2401 it->pixel_width = next_tab_x - x;
2402 it->nglyphs = 1;
2403 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2404 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2405
2406 if (it->glyph_row)
2407 {
2408 double ascent = (double) it->ascent / (it->ascent + it->descent);
2409 x_append_stretch_glyph (it, it->object, it->pixel_width,
2410 it->ascent + it->descent, ascent);
2411 }
2412 }
2413 else
2414 {
2415 /* A multi-byte character. Assume that the display width of the
2416 character is the width of the character multiplied by the
2417 width of the font. */
2418
2419 /* If we found a font, this font should give us the right
2420 metrics. If we didn't find a font, use the frame's
2421 default font and calculate the width of the character
2422 from the charset width; this is what old redisplay code
2423 did. */
2424 pcm = x_per_char_metric (font, &char2b);
2425 if (font_not_found_p || !pcm)
2426 {
2427 int charset = CHAR_CHARSET (it->char_to_display);
2428
2429 it->glyph_not_available_p = 1;
2430 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2431 * CHARSET_WIDTH (charset));
2432 it->phys_ascent = FONT_BASE (font) + boff;
2433 it->phys_descent = FONT_DESCENT (font) - boff;
2434 }
2435 else
2436 {
2437 it->pixel_width = pcm->width;
2438 it->phys_ascent = pcm->ascent + boff;
2439 it->phys_descent = pcm->descent - boff;
2440 if (it->glyph_row
2441 && (pcm->lbearing < 0
2442 || pcm->rbearing > pcm->width))
2443 it->glyph_row->contains_overlapping_glyphs_p = 1;
2444 }
2445 it->nglyphs = 1;
2446 it->ascent = FONT_BASE (font) + boff;
2447 it->descent = FONT_DESCENT (font) - boff;
2448 if (face->box != FACE_NO_BOX)
2449 {
2450 int thick = face->box_line_width;
2451
2452 if (thick > 0)
2453 {
2454 it->ascent += thick;
2455 it->descent += thick;
2456 }
2457 else
2458 thick = - thick;
2459
2460 if (it->start_of_box_run_p)
2461 it->pixel_width += thick;
2462 if (it->end_of_box_run_p)
2463 it->pixel_width += thick;
2464 }
2465
2466 /* If face has an overline, add the height of the overline
2467 (1 pixel) and a 1 pixel margin to the character height. */
2468 if (face->overline_p)
2469 it->ascent += 2;
2470
2471 take_vertical_position_into_account (it);
2472
2473 if (it->glyph_row)
2474 x_append_glyph (it);
2475 }
2476 it->multibyte_p = saved_multibyte_p;
2477 }
2478 else if (it->what == IT_COMPOSITION)
2479 {
2480 /* Note: A composition is represented as one glyph in the
2481 glyph matrix. There are no padding glyphs. */
2482 XChar2b char2b;
2483 XFontStruct *font;
2484 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2485 XCharStruct *pcm;
2486 int font_not_found_p;
2487 struct font_info *font_info;
2488 int boff; /* baseline offset */
2489 struct composition *cmp = composition_table[it->cmp_id];
2490
2491 /* Maybe translate single-byte characters to multibyte. */
2492 it->char_to_display = it->c;
2493 if (unibyte_display_via_language_environment
2494 && SINGLE_BYTE_CHAR_P (it->c)
2495 && (it->c >= 0240
2496 || (it->c >= 0200
2497 && !NILP (Vnonascii_translation_table))))
2498 {
2499 it->char_to_display = unibyte_char_to_multibyte (it->c);
2500 }
2501
2502 /* Get face and font to use. Encode IT->char_to_display. */
2503 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2504 face = FACE_FROM_ID (it->f, it->face_id);
2505 x_get_char_face_and_encoding (it->f, it->char_to_display,
2506 it->face_id, &char2b, it->multibyte_p);
2507 font = face->font;
2508
2509 /* When no suitable font found, use the default font. */
2510 font_not_found_p = font == NULL;
2511 if (font_not_found_p)
2512 {
2513 font = FRAME_FONT (it->f);
2514 boff = it->f->output_data.mac->baseline_offset;
2515 font_info = NULL;
2516 }
2517 else
2518 {
2519 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2520 boff = font_info->baseline_offset;
2521 if (font_info->vertical_centering)
2522 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2523 }
2524
2525 /* There are no padding glyphs, so there is only one glyph to
2526 produce for the composition. Important is that pixel_width,
2527 ascent and descent are the values of what is drawn by
2528 draw_glyphs (i.e. the values of the overall glyphs composed). */
2529 it->nglyphs = 1;
2530
2531 /* If we have not yet calculated pixel size data of glyphs of
2532 the composition for the current face font, calculate them
2533 now. Theoretically, we have to check all fonts for the
2534 glyphs, but that requires much time and memory space. So,
2535 here we check only the font of the first glyph. This leads
2536 to incorrect display very rarely, and C-l (recenter) can
2537 correct the display anyway. */
2538 if (cmp->font != (void *) font)
2539 {
2540 /* Ascent and descent of the font of the first character of
2541 this composition (adjusted by baseline offset). Ascent
2542 and descent of overall glyphs should not be less than
2543 them respectively. */
2544 int font_ascent = FONT_BASE (font) + boff;
2545 int font_descent = FONT_DESCENT (font) - boff;
2546 /* Bounding box of the overall glyphs. */
2547 int leftmost, rightmost, lowest, highest;
2548 int i, width, ascent, descent;
2549
2550 cmp->font = (void *) font;
2551
2552 /* Initialize the bounding box. */
2553 pcm = x_per_char_metric (font, &char2b);
2554 if (pcm)
2555 {
2556 width = pcm->width;
2557 ascent = pcm->ascent;
2558 descent = pcm->descent;
2559 }
2560 else
2561 {
2562 width = FONT_WIDTH (font);
2563 ascent = FONT_BASE (font);
2564 descent = FONT_DESCENT (font);
2565 }
2566
2567 rightmost = width;
2568 lowest = - descent + boff;
2569 highest = ascent + boff;
2570 leftmost = 0;
2571
2572 if (font_info
2573 && font_info->default_ascent
2574 && CHAR_TABLE_P (Vuse_default_ascent)
2575 && !NILP (Faref (Vuse_default_ascent,
2576 make_number (it->char_to_display))))
2577 highest = font_info->default_ascent + boff;
2578
2579 /* Draw the first glyph at the normal position. It may be
2580 shifted to right later if some other glyphs are drawn at
2581 the left. */
2582 cmp->offsets[0] = 0;
2583 cmp->offsets[1] = boff;
2584
2585 /* Set cmp->offsets for the remaining glyphs. */
2586 for (i = 1; i < cmp->glyph_len; i++)
2587 {
2588 int left, right, btm, top;
2589 int ch = COMPOSITION_GLYPH (cmp, i);
2590 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2591
2592 face = FACE_FROM_ID (it->f, face_id);
2593 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2594 it->multibyte_p);
2595 font = face->font;
2596 if (font == NULL)
2597 {
2598 font = FRAME_FONT (it->f);
2599 boff = it->f->output_data.mac->baseline_offset;
2600 font_info = NULL;
2601 }
2602 else
2603 {
2604 font_info
2605 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2606 boff = font_info->baseline_offset;
2607 if (font_info->vertical_centering)
2608 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2609 }
2610
2611 pcm = x_per_char_metric (font, &char2b);
2612 if (pcm)
2613 {
2614 width = pcm->width;
2615 ascent = pcm->ascent;
2616 descent = pcm->descent;
2617 }
2618 else
2619 {
2620 width = FONT_WIDTH (font);
2621 ascent = 1;
2622 descent = 0;
2623 }
2624
2625 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2626 {
2627 /* Relative composition with or without
2628 alternate chars. */
2629 left = (leftmost + rightmost - width) / 2;
2630 btm = - descent + boff;
2631 if (font_info && font_info->relative_compose
2632 && (! CHAR_TABLE_P (Vignore_relative_composition)
2633 || NILP (Faref (Vignore_relative_composition,
2634 make_number (ch)))))
2635 {
2636
2637 if (- descent >= font_info->relative_compose)
2638 /* One extra pixel between two glyphs. */
2639 btm = highest + 1;
2640 else if (ascent <= 0)
2641 /* One extra pixel between two glyphs. */
2642 btm = lowest - 1 - ascent - descent;
2643 }
2644 }
2645 else
2646 {
2647 /* A composition rule is specified by an integer
2648 value that encodes global and new reference
2649 points (GREF and NREF). GREF and NREF are
2650 specified by numbers as below:
2651
2652 0---1---2 -- ascent
2653 | |
2654 | |
2655 | |
2656 9--10--11 -- center
2657 | |
2658 ---3---4---5--- baseline
2659 | |
2660 6---7---8 -- descent
2661 */
2662 int rule = COMPOSITION_RULE (cmp, i);
2663 int gref, nref, grefx, grefy, nrefx, nrefy;
2664
2665 COMPOSITION_DECODE_RULE (rule, gref, nref);
2666 grefx = gref % 3, nrefx = nref % 3;
2667 grefy = gref / 3, nrefy = nref / 3;
2668
2669 left = (leftmost
2670 + grefx * (rightmost - leftmost) / 2
2671 - nrefx * width / 2);
2672 btm = ((grefy == 0 ? highest
2673 : grefy == 1 ? 0
2674 : grefy == 2 ? lowest
2675 : (highest + lowest) / 2)
2676 - (nrefy == 0 ? ascent + descent
2677 : nrefy == 1 ? descent - boff
2678 : nrefy == 2 ? 0
2679 : (ascent + descent) / 2));
2680 }
2681
2682 cmp->offsets[i * 2] = left;
2683 cmp->offsets[i * 2 + 1] = btm + descent;
2684
2685 /* Update the bounding box of the overall glyphs. */
2686 right = left + width;
2687 top = btm + descent + ascent;
2688 if (left < leftmost)
2689 leftmost = left;
2690 if (right > rightmost)
2691 rightmost = right;
2692 if (top > highest)
2693 highest = top;
2694 if (btm < lowest)
2695 lowest = btm;
2696 }
2697
2698 /* If there are glyphs whose x-offsets are negative,
2699 shift all glyphs to the right and make all x-offsets
2700 non-negative. */
2701 if (leftmost < 0)
2702 {
2703 for (i = 0; i < cmp->glyph_len; i++)
2704 cmp->offsets[i * 2] -= leftmost;
2705 rightmost -= leftmost;
2706 }
2707
2708 cmp->pixel_width = rightmost;
2709 cmp->ascent = highest;
2710 cmp->descent = - lowest;
2711 if (cmp->ascent < font_ascent)
2712 cmp->ascent = font_ascent;
2713 if (cmp->descent < font_descent)
2714 cmp->descent = font_descent;
2715 }
2716
2717 it->pixel_width = cmp->pixel_width;
2718 it->ascent = it->phys_ascent = cmp->ascent;
2719 it->descent = it->phys_descent = cmp->descent;
2720
2721 if (face->box != FACE_NO_BOX)
2722 {
2723 int thick = face->box_line_width;
2724
2725 if (thick > 0)
2726 {
2727 it->ascent += thick;
2728 it->descent += thick;
2729 }
2730 else
2731 thick = - thick;
2732
2733 if (it->start_of_box_run_p)
2734 it->pixel_width += thick;
2735 if (it->end_of_box_run_p)
2736 it->pixel_width += thick;
2737 }
2738
2739 /* If face has an overline, add the height of the overline
2740 (1 pixel) and a 1 pixel margin to the character height. */
2741 if (face->overline_p)
2742 it->ascent += 2;
2743
2744 take_vertical_position_into_account (it);
2745
2746 if (it->glyph_row)
2747 x_append_composite_glyph (it);
2748 }
2749 else if (it->what == IT_IMAGE)
2750 x_produce_image_glyph (it);
2751 else if (it->what == IT_STRETCH)
2752 x_produce_stretch_glyph (it);
2753
2754 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2755 because this isn't true for images with `:ascent 100'. */
2756 xassert (it->ascent >= 0 && it->descent >= 0);
2757 if (it->area == TEXT_AREA)
2758 it->current_x += it->pixel_width;
2759
2760 it->descent += it->extra_line_spacing;
2761
2762 it->max_ascent = max (it->max_ascent, it->ascent);
2763 it->max_descent = max (it->max_descent, it->descent);
2764 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2765 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2766 }
2767
2768
2769 /* Estimate the pixel height of the mode or top line on frame F.
2770 FACE_ID specifies what line's height to estimate. */
2771
2772 int
2773 x_estimate_mode_line_height (f, face_id)
2774 struct frame *f;
2775 enum face_id face_id;
2776 {
2777 int height = FONT_HEIGHT (FRAME_FONT (f));
2778
2779 /* This function is called so early when Emacs starts that the face
2780 cache and mode line face are not yet initialized. */
2781 if (FRAME_FACE_CACHE (f))
2782 {
2783 struct face *face = FACE_FROM_ID (f, face_id);
2784 if (face)
2785 {
2786 if (face->font)
2787 height = FONT_HEIGHT (face->font);
2788 if (face->box_line_width > 0)
2789 height += 2 * face->box_line_width;
2790 }
2791 }
2792
2793 return height;
2794 }
2795
2796 \f
2797 /***********************************************************************
2798 Glyph display
2799 ***********************************************************************/
2800
2801 /* A sequence of glyphs to be drawn in the same face.
2802
2803 This data structure is not really completely X specific, so it
2804 could possibly, at least partially, be useful for other systems. It
2805 is currently not part of the external redisplay interface because
2806 it's not clear what other systems will need. */
2807
2808 struct glyph_string
2809 {
2810 /* X-origin of the string. */
2811 int x;
2812
2813 /* Y-origin and y-position of the base line of this string. */
2814 int y, ybase;
2815
2816 /* The width of the string, not including a face extension. */
2817 int width;
2818
2819 /* The width of the string, including a face extension. */
2820 int background_width;
2821
2822 /* The height of this string. This is the height of the line this
2823 string is drawn in, and can be different from the height of the
2824 font the string is drawn in. */
2825 int height;
2826
2827 /* Number of pixels this string overwrites in front of its x-origin.
2828 This number is zero if the string has an lbearing >= 0; it is
2829 -lbearing, if the string has an lbearing < 0. */
2830 int left_overhang;
2831
2832 /* Number of pixels this string overwrites past its right-most
2833 nominal x-position, i.e. x + width. Zero if the string's
2834 rbearing is <= its nominal width, rbearing - width otherwise. */
2835 int right_overhang;
2836
2837 /* The frame on which the glyph string is drawn. */
2838 struct frame *f;
2839
2840 /* The window on which the glyph string is drawn. */
2841 struct window *w;
2842
2843 /* X display and window for convenience. */
2844 Display *display;
2845 Window window;
2846
2847 /* The glyph row for which this string was built. It determines the
2848 y-origin and height of the string. */
2849 struct glyph_row *row;
2850
2851 /* The area within row. */
2852 enum glyph_row_area area;
2853
2854 /* Characters to be drawn, and number of characters. */
2855 XChar2b *char2b;
2856 int nchars;
2857
2858 /* A face-override for drawing cursors, mouse face and similar. */
2859 enum draw_glyphs_face hl;
2860
2861 /* Face in which this string is to be drawn. */
2862 struct face *face;
2863
2864 /* Font in which this string is to be drawn. */
2865 XFontStruct *font;
2866
2867 /* Font info for this string. */
2868 struct font_info *font_info;
2869
2870 /* Non-null means this string describes (part of) a composition.
2871 All characters from char2b are drawn composed. */
2872 struct composition *cmp;
2873
2874 /* Index of this glyph string's first character in the glyph
2875 definition of CMP. If this is zero, this glyph string describes
2876 the first character of a composition. */
2877 int gidx;
2878
2879 /* 1 means this glyph strings face has to be drawn to the right end
2880 of the window's drawing area. */
2881 unsigned extends_to_end_of_line_p : 1;
2882
2883 /* 1 means the background of this string has been drawn. */
2884 unsigned background_filled_p : 1;
2885
2886 /* 1 means glyph string must be drawn with 16-bit functions. */
2887 unsigned two_byte_p : 1;
2888
2889 /* 1 means that the original font determined for drawing this glyph
2890 string could not be loaded. The member `font' has been set to
2891 the frame's default font in this case. */
2892 unsigned font_not_found_p : 1;
2893
2894 /* 1 means that the face in which this glyph string is drawn has a
2895 stipple pattern. */
2896 unsigned stippled_p : 1;
2897
2898 /* 1 means only the foreground of this glyph string must be drawn,
2899 and we should use the physical height of the line this glyph
2900 string appears in as clip rect. */
2901 unsigned for_overlaps_p : 1;
2902
2903 /* The GC to use for drawing this glyph string. */
2904 GC gc;
2905
2906 /* A pointer to the first glyph in the string. This glyph
2907 corresponds to char2b[0]. Needed to draw rectangles if
2908 font_not_found_p is 1. */
2909 struct glyph *first_glyph;
2910
2911 /* Image, if any. */
2912 struct image *img;
2913
2914 struct glyph_string *next, *prev;
2915 };
2916
2917
2918 #if 0
2919
2920 static void
2921 x_dump_glyph_string (s)
2922 struct glyph_string *s;
2923 {
2924 fprintf (stderr, "glyph string\n");
2925 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2926 s->x, s->y, s->width, s->height);
2927 fprintf (stderr, " ybase = %d\n", s->ybase);
2928 fprintf (stderr, " hl = %d\n", s->hl);
2929 fprintf (stderr, " left overhang = %d, right = %d\n",
2930 s->left_overhang, s->right_overhang);
2931 fprintf (stderr, " nchars = %d\n", s->nchars);
2932 fprintf (stderr, " extends to end of line = %d\n",
2933 s->extends_to_end_of_line_p);
2934 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2935 fprintf (stderr, " bg width = %d\n", s->background_width);
2936 }
2937
2938 #endif /* GLYPH_DEBUG */
2939
2940
2941
2942 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2943 struct glyph_string **,
2944 struct glyph_string *,
2945 struct glyph_string *));
2946 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2947 struct glyph_string **,
2948 struct glyph_string *,
2949 struct glyph_string *));
2950 static void x_append_glyph_string P_ ((struct glyph_string **,
2951 struct glyph_string **,
2952 struct glyph_string *));
2953 static int x_left_overwritten P_ ((struct glyph_string *));
2954 static int x_left_overwriting P_ ((struct glyph_string *));
2955 static int x_right_overwritten P_ ((struct glyph_string *));
2956 static int x_right_overwriting P_ ((struct glyph_string *));
2957 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2958 int));
2959 static void x_init_glyph_string P_ ((struct glyph_string *,
2960 XChar2b *, struct window *,
2961 struct glyph_row *,
2962 enum glyph_row_area, int,
2963 enum draw_glyphs_face));
2964 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2965 enum glyph_row_area, int, int,
2966 enum draw_glyphs_face, int));
2967 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2968 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2969 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2970 int));
2971 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2972 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2973 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2974 static void x_draw_glyph_string P_ ((struct glyph_string *));
2975 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2976 static void x_set_cursor_gc P_ ((struct glyph_string *));
2977 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2978 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2979 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2980 int *, int *));
2981 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2982 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2983 unsigned long *, double, int));*/
2984 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2985 double, int, unsigned long));
2986 static void x_setup_relief_colors P_ ((struct glyph_string *));
2987 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2988 static void x_draw_image_relief P_ ((struct glyph_string *));
2989 static void x_draw_image_foreground P_ ((struct glyph_string *));
2990 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2991 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2992 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2993 int, int, int));
2994 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2995 int, int, int, int, Rect *));
2996 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2997 int, int, int, Rect *));
2998 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2999 enum glyph_row_area));
3000 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3001 struct glyph_row *,
3002 enum glyph_row_area, int, int));
3003
3004 #if GLYPH_DEBUG
3005 static void x_check_font P_ ((struct frame *, XFontStruct *));
3006 #endif
3007
3008
3009 /* Append the list of glyph strings with head H and tail T to the list
3010 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3011
3012 static INLINE void
3013 x_append_glyph_string_lists (head, tail, h, t)
3014 struct glyph_string **head, **tail;
3015 struct glyph_string *h, *t;
3016 {
3017 if (h)
3018 {
3019 if (*head)
3020 (*tail)->next = h;
3021 else
3022 *head = h;
3023 h->prev = *tail;
3024 *tail = t;
3025 }
3026 }
3027
3028
3029 /* Prepend the list of glyph strings with head H and tail T to the
3030 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3031 result. */
3032
3033 static INLINE void
3034 x_prepend_glyph_string_lists (head, tail, h, t)
3035 struct glyph_string **head, **tail;
3036 struct glyph_string *h, *t;
3037 {
3038 if (h)
3039 {
3040 if (*head)
3041 (*head)->prev = t;
3042 else
3043 *tail = t;
3044 t->next = *head;
3045 *head = h;
3046 }
3047 }
3048
3049
3050 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3051 Set *HEAD and *TAIL to the resulting list. */
3052
3053 static INLINE void
3054 x_append_glyph_string (head, tail, s)
3055 struct glyph_string **head, **tail;
3056 struct glyph_string *s;
3057 {
3058 s->next = s->prev = NULL;
3059 x_append_glyph_string_lists (head, tail, s, s);
3060 }
3061
3062
3063 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3064 face. */
3065
3066 static void
3067 x_set_cursor_gc (s)
3068 struct glyph_string *s;
3069 {
3070 if (s->font == FRAME_FONT (s->f)
3071 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3072 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3073 && !s->cmp)
3074 s->gc = s->f->output_data.mac->cursor_gc;
3075 else
3076 {
3077 /* Cursor on non-default face: must merge. */
3078 XGCValues xgcv;
3079 unsigned long mask;
3080
3081 xgcv.background = s->f->output_data.mac->cursor_pixel;
3082 xgcv.foreground = s->face->background;
3083
3084 /* If the glyph would be invisible, try a different foreground. */
3085 if (xgcv.foreground == xgcv.background)
3086 xgcv.foreground = s->face->foreground;
3087 if (xgcv.foreground == xgcv.background)
3088 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3089 if (xgcv.foreground == xgcv.background)
3090 xgcv.foreground = s->face->foreground;
3091
3092 /* Make sure the cursor is distinct from text in this face. */
3093 if (xgcv.background == s->face->background
3094 && xgcv.foreground == s->face->foreground)
3095 {
3096 xgcv.background = s->face->foreground;
3097 xgcv.foreground = s->face->background;
3098 }
3099
3100 IF_DEBUG (x_check_font (s->f, s->font));
3101 xgcv.font = s->font;
3102 mask = GCForeground | GCBackground | GCFont;
3103
3104 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3105 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3106 mask, &xgcv);
3107 else
3108 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3109 = XCreateGC (s->display, s->window, mask, &xgcv);
3110
3111 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3112 }
3113 }
3114
3115
3116 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3117
3118 static void
3119 x_set_mouse_face_gc (s)
3120 struct glyph_string *s;
3121 {
3122 int face_id;
3123 struct face *face;
3124
3125 /* What face has to be used last for the mouse face? */
3126 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3127 face = FACE_FROM_ID (s->f, face_id);
3128 if (face == NULL)
3129 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3130
3131 if (s->first_glyph->type == CHAR_GLYPH)
3132 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3133 else
3134 face_id = FACE_FOR_CHAR (s->f, face, 0);
3135 s->face = FACE_FROM_ID (s->f, face_id);
3136 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3137
3138 /* If font in this face is same as S->font, use it. */
3139 if (s->font == s->face->font)
3140 s->gc = s->face->gc;
3141 else
3142 {
3143 /* Otherwise construct scratch_cursor_gc with values from FACE
3144 but font FONT. */
3145 XGCValues xgcv;
3146 unsigned long mask;
3147
3148 xgcv.background = s->face->background;
3149 xgcv.foreground = s->face->foreground;
3150 IF_DEBUG (x_check_font (s->f, s->font));
3151 xgcv.font = s->font;
3152 mask = GCForeground | GCBackground | GCFont;
3153
3154 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3155 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3156 mask, &xgcv);
3157 else
3158 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3159 = XCreateGC (s->display, s->window, mask, &xgcv);
3160
3161 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3162 }
3163
3164 xassert (s->gc != 0);
3165 }
3166
3167
3168 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3169 Faces to use in the mode line have already been computed when the
3170 matrix was built, so there isn't much to do, here. */
3171
3172 static INLINE void
3173 x_set_mode_line_face_gc (s)
3174 struct glyph_string *s;
3175 {
3176 s->gc = s->face->gc;
3177 }
3178
3179
3180 /* Set S->gc of glyph string S for drawing that glyph string. Set
3181 S->stippled_p to a non-zero value if the face of S has a stipple
3182 pattern. */
3183
3184 static INLINE void
3185 x_set_glyph_string_gc (s)
3186 struct glyph_string *s;
3187 {
3188 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3189
3190 if (s->hl == DRAW_NORMAL_TEXT)
3191 {
3192 s->gc = s->face->gc;
3193 s->stippled_p = s->face->stipple != 0;
3194 }
3195 else if (s->hl == DRAW_INVERSE_VIDEO)
3196 {
3197 x_set_mode_line_face_gc (s);
3198 s->stippled_p = s->face->stipple != 0;
3199 }
3200 else if (s->hl == DRAW_CURSOR)
3201 {
3202 x_set_cursor_gc (s);
3203 s->stippled_p = 0;
3204 }
3205 else if (s->hl == DRAW_MOUSE_FACE)
3206 {
3207 x_set_mouse_face_gc (s);
3208 s->stippled_p = s->face->stipple != 0;
3209 }
3210 else if (s->hl == DRAW_IMAGE_RAISED
3211 || s->hl == DRAW_IMAGE_SUNKEN)
3212 {
3213 s->gc = s->face->gc;
3214 s->stippled_p = s->face->stipple != 0;
3215 }
3216 else
3217 {
3218 s->gc = s->face->gc;
3219 s->stippled_p = s->face->stipple != 0;
3220 }
3221
3222 /* GC must have been set. */
3223 xassert (s->gc != 0);
3224 }
3225
3226
3227 /* Return in *R the clipping rectangle for glyph string S. */
3228
3229 static void
3230 x_get_glyph_string_clip_rect (s, r)
3231 struct glyph_string *s;
3232 Rect *r;
3233 {
3234 int r_height, r_width;
3235
3236 if (s->row->full_width_p)
3237 {
3238 /* Draw full-width. X coordinates are relative to S->w->left. */
3239 int canon_x = CANON_X_UNIT (s->f);
3240
3241 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3242 r_width = XFASTINT (s->w->width) * canon_x;
3243
3244 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3245 {
3246 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3247 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3248 r->left -= width;
3249 }
3250
3251 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3252
3253 /* Unless displaying a mode or menu bar line, which are always
3254 fully visible, clip to the visible part of the row. */
3255 if (s->w->pseudo_window_p)
3256 r_height = s->row->visible_height;
3257 else
3258 r_height = s->height;
3259 }
3260 else
3261 {
3262 /* This is a text line that may be partially visible. */
3263 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3264 r_width = window_box_width (s->w, s->area);
3265 r_height = s->row->visible_height;
3266 }
3267
3268 /* If S draws overlapping rows, it's sufficient to use the top and
3269 bottom of the window for clipping because this glyph string
3270 intentionally draws over other lines. */
3271 if (s->for_overlaps_p)
3272 {
3273 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3274 r_height = window_text_bottom_y (s->w) - r->top;
3275 }
3276 else
3277 {
3278 /* Don't use S->y for clipping because it doesn't take partially
3279 visible lines into account. For example, it can be negative for
3280 partially visible lines at the top of a window. */
3281 if (!s->row->full_width_p
3282 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3283 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3284 else
3285 r->top = max (0, s->row->y);
3286
3287 /* If drawing a tool-bar window, draw it over the internal border
3288 at the top of the window. */
3289 if (s->w == XWINDOW (s->f->tool_bar_window))
3290 r->top -= s->f->output_data.mac->internal_border_width;
3291 }
3292
3293 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3294
3295 r->bottom = r->top + r_height;
3296 r->right = r->left + r_width;
3297 }
3298
3299
3300 /* Set clipping for output of glyph string S. S may be part of a mode
3301 line or menu if we don't have X toolkit support. */
3302
3303 static INLINE void
3304 x_set_glyph_string_clipping (s)
3305 struct glyph_string *s;
3306 {
3307 Rect r;
3308 x_get_glyph_string_clip_rect (s, &r);
3309 mac_set_clip_rectangle (s->display, s->window, &r);
3310 }
3311
3312
3313 /* Compute left and right overhang of glyph string S. If S is a glyph
3314 string for a composition, assume overhangs don't exist. */
3315
3316 static INLINE void
3317 x_compute_glyph_string_overhangs (s)
3318 struct glyph_string *s;
3319 {
3320 if (s->cmp == NULL
3321 && s->first_glyph->type == CHAR_GLYPH)
3322 {
3323 XCharStruct cs;
3324 int direction, font_ascent, font_descent;
3325 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3326 &font_ascent, &font_descent, &cs);
3327 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3328 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3329 }
3330 }
3331
3332
3333 /* Compute overhangs and x-positions for glyph string S and its
3334 predecessors, or successors. X is the starting x-position for S.
3335 BACKWARD_P non-zero means process predecessors. */
3336
3337 static void
3338 x_compute_overhangs_and_x (s, x, backward_p)
3339 struct glyph_string *s;
3340 int x;
3341 int backward_p;
3342 {
3343 if (backward_p)
3344 {
3345 while (s)
3346 {
3347 x_compute_glyph_string_overhangs (s);
3348 x -= s->width;
3349 s->x = x;
3350 s = s->prev;
3351 }
3352 }
3353 else
3354 {
3355 while (s)
3356 {
3357 x_compute_glyph_string_overhangs (s);
3358 s->x = x;
3359 x += s->width;
3360 s = s->next;
3361 }
3362 }
3363 }
3364
3365
3366 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3367 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3368 assumed to be zero. */
3369
3370 void
3371 x_get_glyph_overhangs (glyph, f, left, right)
3372 struct glyph *glyph;
3373 struct frame *f;
3374 int *left, *right;
3375 {
3376 *left = *right = 0;
3377
3378 if (glyph->type == CHAR_GLYPH)
3379 {
3380 XFontStruct *font;
3381 struct face *face;
3382 struct font_info *font_info;
3383 XChar2b char2b;
3384 XCharStruct *pcm;
3385
3386 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3387 font = face->font;
3388 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3389 if (font
3390 && (pcm = x_per_char_metric (font, &char2b)))
3391 {
3392 if (pcm->rbearing > pcm->width)
3393 *right = pcm->rbearing - pcm->width;
3394 if (pcm->lbearing < 0)
3395 *left = -pcm->lbearing;
3396 }
3397 }
3398 }
3399
3400
3401 /* Return the index of the first glyph preceding glyph string S that
3402 is overwritten by S because of S's left overhang. Value is -1
3403 if no glyphs are overwritten. */
3404
3405 static int
3406 x_left_overwritten (s)
3407 struct glyph_string *s;
3408 {
3409 int k;
3410
3411 if (s->left_overhang)
3412 {
3413 int x = 0, i;
3414 struct glyph *glyphs = s->row->glyphs[s->area];
3415 int first = s->first_glyph - glyphs;
3416
3417 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3418 x -= glyphs[i].pixel_width;
3419
3420 k = i + 1;
3421 }
3422 else
3423 k = -1;
3424
3425 return k;
3426 }
3427
3428
3429 /* Return the index of the first glyph preceding glyph string S that
3430 is overwriting S because of its right overhang. Value is -1 if no
3431 glyph in front of S overwrites S. */
3432
3433 static int
3434 x_left_overwriting (s)
3435 struct glyph_string *s;
3436 {
3437 int i, k, x;
3438 struct glyph *glyphs = s->row->glyphs[s->area];
3439 int first = s->first_glyph - glyphs;
3440
3441 k = -1;
3442 x = 0;
3443 for (i = first - 1; i >= 0; --i)
3444 {
3445 int left, right;
3446 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3447 if (x + right > 0)
3448 k = i;
3449 x -= glyphs[i].pixel_width;
3450 }
3451
3452 return k;
3453 }
3454
3455
3456 /* Return the index of the last glyph following glyph string S that is
3457 not overwritten by S because of S's right overhang. Value is -1 if
3458 no such glyph is found. */
3459
3460 static int
3461 x_right_overwritten (s)
3462 struct glyph_string *s;
3463 {
3464 int k = -1;
3465
3466 if (s->right_overhang)
3467 {
3468 int x = 0, i;
3469 struct glyph *glyphs = s->row->glyphs[s->area];
3470 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3471 int end = s->row->used[s->area];
3472
3473 for (i = first; i < end && s->right_overhang > x; ++i)
3474 x += glyphs[i].pixel_width;
3475
3476 k = i;
3477 }
3478
3479 return k;
3480 }
3481
3482
3483 /* Return the index of the last glyph following glyph string S that
3484 overwrites S because of its left overhang. Value is negative
3485 if no such glyph is found. */
3486
3487 static int
3488 x_right_overwriting (s)
3489 struct glyph_string *s;
3490 {
3491 int i, k, x;
3492 int end = s->row->used[s->area];
3493 struct glyph *glyphs = s->row->glyphs[s->area];
3494 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3495
3496 k = -1;
3497 x = 0;
3498 for (i = first; i < end; ++i)
3499 {
3500 int left, right;
3501 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3502 if (x - left < 0)
3503 k = i;
3504 x += glyphs[i].pixel_width;
3505 }
3506
3507 return k;
3508 }
3509
3510
3511 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3512
3513 static INLINE void
3514 x_clear_glyph_string_rect (s, x, y, w, h)
3515 struct glyph_string *s;
3516 int x, y, w, h;
3517 {
3518 XGCValues xgcv;
3519
3520 xgcv.foreground = s->gc->background;
3521 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3522 }
3523
3524
3525 /* Draw the background of glyph_string S. If S->background_filled_p
3526 is non-zero don't draw it. FORCE_P non-zero means draw the
3527 background even if it wouldn't be drawn normally. This is used
3528 when a string preceding S draws into the background of S, or S
3529 contains the first component of a composition. */
3530
3531 static void
3532 x_draw_glyph_string_background (s, force_p)
3533 struct glyph_string *s;
3534 int force_p;
3535 {
3536 /* Nothing to do if background has already been drawn or if it
3537 shouldn't be drawn in the first place. */
3538 if (!s->background_filled_p)
3539 {
3540 int box_line_width = max (s->face->box_line_width, 0);
3541
3542 #if 0 /* MAC_TODO: stipple */
3543 if (s->stippled_p)
3544 {
3545 /* Fill background with a stipple pattern. */
3546 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3547 XFillRectangle (s->display, s->window, s->gc, s->x,
3548 s->y + box_line_width,
3549 s->background_width,
3550 s->height - 2 * box_line_width);
3551 XSetFillStyle (s->display, s->gc, FillSolid);
3552 s->background_filled_p = 1;
3553 }
3554 else
3555 #endif
3556 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3557 || s->font_not_found_p
3558 || s->extends_to_end_of_line_p
3559 || force_p)
3560 {
3561 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3562 s->background_width,
3563 s->height - 2 * box_line_width);
3564 s->background_filled_p = 1;
3565 }
3566 }
3567 }
3568
3569
3570 /* Draw the foreground of glyph string S. */
3571
3572 static void
3573 x_draw_glyph_string_foreground (s)
3574 struct glyph_string *s;
3575 {
3576 int i, x;
3577
3578 /* If first glyph of S has a left box line, start drawing the text
3579 of S to the right of that box line. */
3580 if (s->face->box != FACE_NO_BOX
3581 && s->first_glyph->left_box_line_p)
3582 x = s->x + abs (s->face->box_line_width);
3583 else
3584 x = s->x;
3585
3586 /* Draw characters of S as rectangles if S's font could not be
3587 loaded. */
3588 if (s->font_not_found_p)
3589 {
3590 for (i = 0; i < s->nchars; ++i)
3591 {
3592 struct glyph *g = s->first_glyph + i;
3593 mac_draw_rectangle (s->display, s->window,
3594 s->gc, x, s->y, g->pixel_width - 1,
3595 s->height - 1);
3596 x += g->pixel_width;
3597 }
3598 }
3599 else
3600 {
3601 char *char1b = (char *) s->char2b;
3602 int boff = s->font_info->baseline_offset;
3603
3604 if (s->font_info->vertical_centering)
3605 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3606
3607 /* If we can use 8-bit functions, condense S->char2b. */
3608 if (!s->two_byte_p)
3609 for (i = 0; i < s->nchars; ++i)
3610 char1b[i] = s->char2b[i].byte2;
3611
3612 /* Draw text with XDrawString if background has already been
3613 filled. Otherwise, use XDrawImageString. (Note that
3614 XDrawImageString is usually faster than XDrawString.) Always
3615 use XDrawImageString when drawing the cursor so that there is
3616 no chance that characters under a box cursor are invisible. */
3617 if (s->for_overlaps_p
3618 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3619 {
3620 /* Draw characters with 16-bit or 8-bit functions. */
3621 if (s->two_byte_p)
3622 XDrawString16 (s->display, s->window, s->gc, x,
3623 s->ybase - boff, s->char2b, s->nchars);
3624 else
3625 XDrawString (s->display, s->window, s->gc, x,
3626 s->ybase - boff, char1b, s->nchars);
3627 }
3628 else
3629 {
3630 if (s->two_byte_p)
3631 XDrawImageString16 (s->display, s->window, s->gc, x,
3632 s->ybase - boff, s->char2b, s->nchars);
3633 else
3634 XDrawImageString (s->display, s->window, s->gc, x,
3635 s->ybase - boff, char1b, s->nchars);
3636 }
3637 }
3638 }
3639
3640 /* Draw the foreground of composite glyph string S. */
3641
3642 static void
3643 x_draw_composite_glyph_string_foreground (s)
3644 struct glyph_string *s;
3645 {
3646 int i, x;
3647
3648 /* If first glyph of S has a left box line, start drawing the text
3649 of S to the right of that box line. */
3650 if (s->face->box != FACE_NO_BOX
3651 && s->first_glyph->left_box_line_p)
3652 x = s->x + abs (s->face->box_line_width);
3653 else
3654 x = s->x;
3655
3656 /* S is a glyph string for a composition. S->gidx is the index of
3657 the first character drawn for glyphs of this composition.
3658 S->gidx == 0 means we are drawing the very first character of
3659 this composition. */
3660
3661 /* Draw a rectangle for the composition if the font for the very
3662 first character of the composition could not be loaded. */
3663 if (s->font_not_found_p)
3664 {
3665 if (s->gidx == 0)
3666 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3667 s->width - 1, s->height - 1);
3668 }
3669 else
3670 {
3671 for (i = 0; i < s->nchars; i++, ++s->gidx)
3672 XDrawString16 (s->display, s->window, s->gc,
3673 x + s->cmp->offsets[s->gidx * 2],
3674 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3675 s->char2b + i, 1);
3676 }
3677 }
3678
3679
3680 #ifdef USE_X_TOOLKIT
3681
3682 static struct frame *x_frame_of_widget P_ ((Widget));
3683
3684
3685 /* Return the frame on which widget WIDGET is used.. Abort if frame
3686 cannot be determined. */
3687
3688 static struct frame *
3689 x_frame_of_widget (widget)
3690 Widget widget;
3691 {
3692 struct x_display_info *dpyinfo;
3693 Lisp_Object tail;
3694 struct frame *f;
3695
3696 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3697
3698 /* Find the top-level shell of the widget. Note that this function
3699 can be called when the widget is not yet realized, so XtWindow
3700 (widget) == 0. That's the reason we can't simply use
3701 x_any_window_to_frame. */
3702 while (!XtIsTopLevelShell (widget))
3703 widget = XtParent (widget);
3704
3705 /* Look for a frame with that top-level widget. Allocate the color
3706 on that frame to get the right gamma correction value. */
3707 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3708 if (GC_FRAMEP (XCAR (tail))
3709 && (f = XFRAME (XCAR (tail)),
3710 (f->output_data.nothing != 1
3711 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3712 && f->output_data.x->widget == widget)
3713 return f;
3714
3715 abort ();
3716 }
3717
3718
3719 /* Allocate the color COLOR->pixel on the screen and display of
3720 widget WIDGET in colormap CMAP. If an exact match cannot be
3721 allocated, try the nearest color available. Value is non-zero
3722 if successful. This is called from lwlib. */
3723
3724 int
3725 x_alloc_nearest_color_for_widget (widget, cmap, color)
3726 Widget widget;
3727 Colormap cmap;
3728 XColor *color;
3729 {
3730 struct frame *f = x_frame_of_widget (widget);
3731 return x_alloc_nearest_color (f, cmap, color);
3732 }
3733
3734
3735 #endif /* USE_X_TOOLKIT */
3736
3737 #if 0 /* MAC_TODO */
3738
3739 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3740 CMAP. If an exact match can't be allocated, try the nearest color
3741 available. Value is non-zero if successful. Set *COLOR to the
3742 color allocated. */
3743
3744 int
3745 x_alloc_nearest_color (f, cmap, color)
3746 struct frame *f;
3747 Colormap cmap;
3748 XColor *color;
3749 {
3750 Display *display = FRAME_X_DISPLAY (f);
3751 Screen *screen = FRAME_X_SCREEN (f);
3752 int rc;
3753
3754 gamma_correct (f, color);
3755 rc = XAllocColor (display, cmap, color);
3756 if (rc == 0)
3757 {
3758 /* If we got to this point, the colormap is full, so we're going
3759 to try to get the next closest color. The algorithm used is
3760 a least-squares matching, which is what X uses for closest
3761 color matching with StaticColor visuals. */
3762 int nearest, i;
3763 unsigned long nearest_delta = ~0;
3764 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3765 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3766
3767 for (i = 0; i < ncells; ++i)
3768 cells[i].pixel = i;
3769 XQueryColors (display, cmap, cells, ncells);
3770
3771 for (nearest = i = 0; i < ncells; ++i)
3772 {
3773 long dred = (color->red >> 8) - (cells[i].red >> 8);
3774 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3775 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3776 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3777
3778 if (delta < nearest_delta)
3779 {
3780 nearest = i;
3781 nearest_delta = delta;
3782 }
3783 }
3784
3785 color->red = cells[nearest].red;
3786 color->green = cells[nearest].green;
3787 color->blue = cells[nearest].blue;
3788 rc = XAllocColor (display, cmap, color);
3789 }
3790
3791 #ifdef DEBUG_X_COLORS
3792 if (rc)
3793 register_color (color->pixel);
3794 #endif /* DEBUG_X_COLORS */
3795
3796 return rc;
3797 }
3798
3799
3800 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3801 It's necessary to do this instead of just using PIXEL directly to
3802 get color reference counts right. */
3803
3804 unsigned long
3805 x_copy_color (f, pixel)
3806 struct frame *f;
3807 unsigned long pixel;
3808 {
3809 XColor color;
3810
3811 color.pixel = pixel;
3812 BLOCK_INPUT;
3813 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3814 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3815 UNBLOCK_INPUT;
3816 #ifdef DEBUG_X_COLORS
3817 register_color (pixel);
3818 #endif
3819 return color.pixel;
3820 }
3821
3822
3823 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3824 It's necessary to do this instead of just using PIXEL directly to
3825 get color reference counts right. */
3826
3827 unsigned long
3828 x_copy_dpy_color (dpy, cmap, pixel)
3829 Display *dpy;
3830 Colormap cmap;
3831 unsigned long pixel;
3832 {
3833 XColor color;
3834
3835 color.pixel = pixel;
3836 BLOCK_INPUT;
3837 XQueryColor (dpy, cmap, &color);
3838 XAllocColor (dpy, cmap, &color);
3839 UNBLOCK_INPUT;
3840 #ifdef DEBUG_X_COLORS
3841 register_color (pixel);
3842 #endif
3843 return color.pixel;
3844 }
3845
3846 #endif /* MAC_TODO */
3847
3848 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3849 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3850 If this produces the same color as COLOR, try a color where all RGB
3851 values have DELTA added. Return the allocated color in *COLOR.
3852 DISPLAY is the X display, CMAP is the colormap to operate on.
3853 Value is non-zero if successful. */
3854
3855 static int
3856 mac_alloc_lighter_color (f, color, factor, delta)
3857 struct frame *f;
3858 unsigned long *color;
3859 double factor;
3860 int delta;
3861 {
3862 unsigned long new;
3863
3864 /* Change RGB values by specified FACTOR. Avoid overflow! */
3865 xassert (factor >= 0);
3866 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3867 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3868 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3869 if (new == *color)
3870 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3871 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3872 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3873
3874 /* MAC_TODO: Map to palette and retry with delta if same? */
3875 /* MAC_TODO: Free colors (if using palette)? */
3876
3877 if (new == *color)
3878 return 0;
3879
3880 *color = new;
3881
3882 return 1;
3883 }
3884
3885
3886 /* Set up the foreground color for drawing relief lines of glyph
3887 string S. RELIEF is a pointer to a struct relief containing the GC
3888 with which lines will be drawn. Use a color that is FACTOR or
3889 DELTA lighter or darker than the relief's background which is found
3890 in S->f->output_data.x->relief_background. If such a color cannot
3891 be allocated, use DEFAULT_PIXEL, instead. */
3892
3893 static void
3894 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3895 struct frame *f;
3896 struct relief *relief;
3897 double factor;
3898 int delta;
3899 unsigned long default_pixel;
3900 {
3901 XGCValues xgcv;
3902 struct mac_output *di = f->output_data.mac;
3903 unsigned long mask = GCForeground;
3904 unsigned long pixel;
3905 unsigned long background = di->relief_background;
3906 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3907
3908 /* MAC_TODO: Free colors (if using palette)? */
3909
3910 /* Allocate new color. */
3911 xgcv.foreground = default_pixel;
3912 pixel = background;
3913 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
3914 {
3915 relief->allocated_p = 1;
3916 xgcv.foreground = relief->pixel = pixel;
3917 }
3918
3919 if (relief->gc == 0)
3920 {
3921 #if 0 /* MAC_TODO: stipple */
3922 xgcv.stipple = dpyinfo->gray;
3923 mask |= GCStipple;
3924 #endif
3925 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3926 }
3927 else
3928 XChangeGC (NULL, relief->gc, mask, &xgcv);
3929 }
3930
3931
3932 /* Set up colors for the relief lines around glyph string S. */
3933
3934 static void
3935 x_setup_relief_colors (s)
3936 struct glyph_string *s;
3937 {
3938 struct mac_output *di = s->f->output_data.mac;
3939 unsigned long color;
3940
3941 if (s->face->use_box_color_for_shadows_p)
3942 color = s->face->box_color;
3943 else
3944 {
3945 XGCValues xgcv;
3946
3947 /* Get the background color of the face. */
3948 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3949 color = xgcv.background;
3950 }
3951
3952 if (di->white_relief.gc == 0
3953 || color != di->relief_background)
3954 {
3955 di->relief_background = color;
3956 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3957 WHITE_PIX_DEFAULT (s->f));
3958 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3959 BLACK_PIX_DEFAULT (s->f));
3960 }
3961 }
3962
3963
3964 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3965 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3966 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3967 relief. LEFT_P non-zero means draw a relief on the left side of
3968 the rectangle. RIGHT_P non-zero means draw a relief on the right
3969 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3970 when drawing. */
3971
3972 static void
3973 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3974 raised_p, left_p, right_p, clip_rect)
3975 struct frame *f;
3976 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3977 Rect *clip_rect;
3978 {
3979 int i;
3980 GC gc;
3981
3982 if (raised_p)
3983 gc = f->output_data.mac->white_relief.gc;
3984 else
3985 gc = f->output_data.mac->black_relief.gc;
3986 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
3987
3988 /* Top. */
3989 for (i = 0; i < width; ++i)
3990 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
3991 left_x + i * left_p, top_y + i,
3992 right_x + 1 - i * right_p, top_y + i);
3993
3994 /* Left. */
3995 if (left_p)
3996 for (i = 0; i < width; ++i)
3997 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
3998 left_x + i, top_y + i, left_x + i, bottom_y - i);
3999
4000 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4001 if (raised_p)
4002 gc = f->output_data.mac->black_relief.gc;
4003 else
4004 gc = f->output_data.mac->white_relief.gc;
4005 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4006 clip_rect);
4007
4008 /* Bottom. */
4009 for (i = 0; i < width; ++i)
4010 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4011 left_x + i * left_p, bottom_y - i,
4012 right_x + 1 - i * right_p, bottom_y - i);
4013
4014 /* Right. */
4015 if (right_p)
4016 for (i = 0; i < width; ++i)
4017 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4018 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4019
4020 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4021 }
4022
4023
4024 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4025 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4026 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4027 left side of the rectangle. RIGHT_P non-zero means draw a line
4028 on the right side of the rectangle. CLIP_RECT is the clipping
4029 rectangle to use when drawing. */
4030
4031 static void
4032 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4033 left_p, right_p, clip_rect)
4034 struct glyph_string *s;
4035 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4036 Rect *clip_rect;
4037 {
4038 XGCValues xgcv;
4039
4040 xgcv.foreground = s->face->box_color;
4041 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4042
4043 /* Top. */
4044 XFillRectangle (s->display, s->window, &xgcv,
4045 left_x, top_y, right_x - left_x, width);
4046
4047 /* Left. */
4048 if (left_p)
4049 XFillRectangle (s->display, s->window, &xgcv,
4050 left_x, top_y, width, bottom_y - top_y);
4051
4052 /* Bottom. */
4053 XFillRectangle (s->display, s->window, &xgcv,
4054 left_x, bottom_y - width, right_x - left_x, width);
4055
4056 /* Right. */
4057 if (right_p)
4058 XFillRectangle (s->display, s->window, &xgcv,
4059 right_x - width, top_y, width, bottom_y - top_y);
4060
4061 mac_reset_clipping (s->display, s->window);
4062 }
4063
4064
4065 /* Draw a box around glyph string S. */
4066
4067 static void
4068 x_draw_glyph_string_box (s)
4069 struct glyph_string *s;
4070 {
4071 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4072 int left_p, right_p;
4073 struct glyph *last_glyph;
4074 Rect clip_rect;
4075
4076 last_x = window_box_right (s->w, s->area);
4077 if (s->row->full_width_p
4078 && !s->w->pseudo_window_p)
4079 {
4080 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4081 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4082 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4083 }
4084
4085 /* The glyph that may have a right box line. */
4086 last_glyph = (s->cmp || s->img
4087 ? s->first_glyph
4088 : s->first_glyph + s->nchars - 1);
4089
4090 width = abs (s->face->box_line_width);
4091 raised_p = s->face->box == FACE_RAISED_BOX;
4092 left_x = s->x;
4093 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
4094 ? last_x - 1
4095 : min (last_x, s->x + s->background_width) - 1));
4096 top_y = s->y;
4097 bottom_y = top_y + s->height - 1;
4098
4099 left_p = (s->first_glyph->left_box_line_p
4100 || (s->hl == DRAW_MOUSE_FACE
4101 && (s->prev == NULL
4102 || s->prev->hl != s->hl)));
4103 right_p = (last_glyph->right_box_line_p
4104 || (s->hl == DRAW_MOUSE_FACE
4105 && (s->next == NULL
4106 || s->next->hl != s->hl)));
4107
4108 x_get_glyph_string_clip_rect (s, &clip_rect);
4109
4110 if (s->face->box == FACE_SIMPLE_BOX)
4111 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4112 left_p, right_p, &clip_rect);
4113 else
4114 {
4115 x_setup_relief_colors (s);
4116 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4117 width, raised_p, left_p, right_p, &clip_rect);
4118 }
4119 }
4120
4121
4122 /* Draw foreground of image glyph string S. */
4123
4124 static void
4125 x_draw_image_foreground (s)
4126 struct glyph_string *s;
4127 {
4128 int x;
4129 int y = s->ybase - image_ascent (s->img, s->face);
4130
4131 /* If first glyph of S has a left box line, start drawing it to the
4132 right of that line. */
4133 if (s->face->box != FACE_NO_BOX
4134 && s->first_glyph->left_box_line_p)
4135 x = s->x + abs (s->face->box_line_width);
4136 else
4137 x = s->x;
4138
4139 /* If there is a margin around the image, adjust x- and y-position
4140 by that margin. */
4141 x += s->img->hmargin;
4142 y += s->img->vmargin;
4143
4144 if (s->img->pixmap)
4145 {
4146 #if 0 /* MAC_TODO: image mask */
4147 if (s->img->mask)
4148 {
4149 /* We can't set both a clip mask and use XSetClipRectangles
4150 because the latter also sets a clip mask. We also can't
4151 trust on the shape extension to be available
4152 (XShapeCombineRegion). So, compute the rectangle to draw
4153 manually. */
4154 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4155 | GCFunction);
4156 XGCValues xgcv;
4157 XRectangle clip_rect, image_rect, r;
4158
4159 xgcv.clip_mask = s->img->mask;
4160 xgcv.clip_x_origin = x;
4161 xgcv.clip_y_origin = y;
4162 xgcv.function = GXcopy;
4163 XChangeGC (s->display, s->gc, mask, &xgcv);
4164
4165 x_get_glyph_string_clip_rect (s, &clip_rect);
4166 image_rect.x = x;
4167 image_rect.y = y;
4168 image_rect.width = s->img->width;
4169 image_rect.height = s->img->height;
4170 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4171 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4172 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4173 }
4174 else
4175 #endif /* MAC_TODO */
4176 {
4177 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4178 0, 0, s->img->width, s->img->height, x, y);
4179
4180 /* When the image has a mask, we can expect that at
4181 least part of a mouse highlight or a block cursor will
4182 be visible. If the image doesn't have a mask, make
4183 a block cursor visible by drawing a rectangle around
4184 the image. I believe it's looking better if we do
4185 nothing here for mouse-face. */
4186 if (s->hl == DRAW_CURSOR)
4187 {
4188 int r = s->img->relief;
4189 if (r < 0) r = -r;
4190 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4191 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4192 }
4193 }
4194 }
4195 else
4196 /* Draw a rectangle if image could not be loaded. */
4197 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4198 s->img->width - 1, s->img->height - 1);
4199 }
4200
4201
4202
4203 /* Draw a relief around the image glyph string S. */
4204
4205 static void
4206 x_draw_image_relief (s)
4207 struct glyph_string *s;
4208 {
4209 int x0, y0, x1, y1, thick, raised_p;
4210 Rect r;
4211 int x;
4212 int y = s->ybase - image_ascent (s->img, s->face);
4213
4214 /* If first glyph of S has a left box line, start drawing it to the
4215 right of that line. */
4216 if (s->face->box != FACE_NO_BOX
4217 && s->first_glyph->left_box_line_p)
4218 x = s->x + abs (s->face->box_line_width);
4219 else
4220 x = s->x;
4221
4222 /* If there is a margin around the image, adjust x- and y-position
4223 by that margin. */
4224 x += s->img->hmargin;
4225 y += s->img->vmargin;
4226
4227 if (s->hl == DRAW_IMAGE_SUNKEN
4228 || s->hl == DRAW_IMAGE_RAISED)
4229 {
4230 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4231 raised_p = s->hl == DRAW_IMAGE_RAISED;
4232 }
4233 else
4234 {
4235 thick = abs (s->img->relief);
4236 raised_p = s->img->relief > 0;
4237 }
4238
4239 x0 = x - thick;
4240 y0 = y - thick;
4241 x1 = x + s->img->width + thick - 1;
4242 y1 = y + s->img->height + thick - 1;
4243
4244 x_setup_relief_colors (s);
4245 x_get_glyph_string_clip_rect (s, &r);
4246 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4247 }
4248
4249
4250 /* Draw the foreground of image glyph string S to PIXMAP. */
4251
4252 static void
4253 x_draw_image_foreground_1 (s, pixmap)
4254 struct glyph_string *s;
4255 Pixmap pixmap;
4256 {
4257 int x;
4258 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4259
4260 /* If first glyph of S has a left box line, start drawing it to the
4261 right of that line. */
4262 if (s->face->box != FACE_NO_BOX
4263 && s->first_glyph->left_box_line_p)
4264 x = abs (s->face->box_line_width);
4265 else
4266 x = 0;
4267
4268 /* If there is a margin around the image, adjust x- and y-position
4269 by that margin. */
4270 x += s->img->hmargin;
4271 y += s->img->vmargin;
4272
4273 if (s->img->pixmap)
4274 {
4275 #if 0 /* MAC_TODO: image mask */
4276 if (s->img->mask)
4277 {
4278 /* We can't set both a clip mask and use XSetClipRectangles
4279 because the latter also sets a clip mask. We also can't
4280 trust on the shape extension to be available
4281 (XShapeCombineRegion). So, compute the rectangle to draw
4282 manually. */
4283 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4284 | GCFunction);
4285 XGCValues xgcv;
4286
4287 xgcv.clip_mask = s->img->mask;
4288 xgcv.clip_x_origin = x;
4289 xgcv.clip_y_origin = y;
4290 xgcv.function = GXcopy;
4291 XChangeGC (s->display, s->gc, mask, &xgcv);
4292
4293 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4294 0, 0, s->img->width, s->img->height, x, y);
4295 XSetClipMask (s->display, s->gc, None);
4296 }
4297 else
4298 #endif /* MAC_TODO */
4299 {
4300 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4301 0, 0, s->img->width, s->img->height, x, y);
4302
4303 /* When the image has a mask, we can expect that at
4304 least part of a mouse highlight or a block cursor will
4305 be visible. If the image doesn't have a mask, make
4306 a block cursor visible by drawing a rectangle around
4307 the image. I believe it's looking better if we do
4308 nothing here for mouse-face. */
4309 if (s->hl == DRAW_CURSOR)
4310 {
4311 int r = s->img->relief;
4312 if (r < 0) r = -r;
4313 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4314 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4315 }
4316 }
4317 }
4318 else
4319 /* Draw a rectangle if image could not be loaded. */
4320 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4321 s->img->width - 1, s->img->height - 1);
4322 }
4323
4324
4325 /* Draw part of the background of glyph string S. X, Y, W, and H
4326 give the rectangle to draw. */
4327
4328 static void
4329 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4330 struct glyph_string *s;
4331 int x, y, w, h;
4332 {
4333 #if 0 /* MAC_TODO: stipple */
4334 if (s->stippled_p)
4335 {
4336 /* Fill background with a stipple pattern. */
4337 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4338 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4339 XSetFillStyle (s->display, s->gc, FillSolid);
4340 }
4341 else
4342 #endif /* MAC_TODO */
4343 x_clear_glyph_string_rect (s, x, y, w, h);
4344 }
4345
4346
4347 /* Draw image glyph string S.
4348
4349 s->y
4350 s->x +-------------------------
4351 | s->face->box
4352 |
4353 | +-------------------------
4354 | | s->img->vmargin
4355 | |
4356 | | +-------------------
4357 | | | the image
4358
4359 */
4360
4361 static void
4362 x_draw_image_glyph_string (s)
4363 struct glyph_string *s;
4364 {
4365 int x, y;
4366 int box_line_hwidth = abs (s->face->box_line_width);
4367 int box_line_vwidth = max (s->face->box_line_width, 0);
4368 int height;
4369 Pixmap pixmap = 0;
4370
4371 height = s->height - 2 * box_line_vwidth;
4372
4373 /* Fill background with face under the image. Do it only if row is
4374 taller than image or if image has a clip mask to reduce
4375 flickering. */
4376 s->stippled_p = s->face->stipple != 0;
4377 if (height > s->img->height
4378 || s->img->hmargin
4379 || s->img->vmargin
4380 #if 0 /* TODO: image mask */
4381 || s->img->mask
4382 #endif
4383 || s->img->pixmap == 0
4384 || s->width != s->background_width)
4385 {
4386 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4387 x = s->x + box_line_hwidth;
4388 else
4389 x = s->x;
4390
4391 y = s->y + box_line_vwidth;
4392 #if 0 /* TODO: image mask */
4393 if (s->img->mask)
4394 {
4395 /* Create a pixmap as large as the glyph string. Fill it
4396 with the background color. Copy the image to it, using
4397 its mask. Copy the temporary pixmap to the display. */
4398 Screen *screen = FRAME_X_SCREEN (s->f);
4399 int depth = DefaultDepthOfScreen (screen);
4400
4401 /* Create a pixmap as large as the glyph string. */
4402 pixmap = XCreatePixmap (s->display, s->window,
4403 s->background_width,
4404 s->height, depth);
4405
4406 /* Don't clip in the following because we're working on the
4407 pixmap. */
4408 XSetClipMask (s->display, s->gc, None);
4409
4410 /* Fill the pixmap with the background color/stipple. */
4411 if (s->stippled_p)
4412 {
4413 /* Fill background with a stipple pattern. */
4414 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4415 XFillRectangle (s->display, pixmap, s->gc,
4416 0, 0, s->background_width, s->height);
4417 XSetFillStyle (s->display, s->gc, FillSolid);
4418 }
4419 else
4420 {
4421 XGCValues xgcv;
4422 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4423 &xgcv);
4424 XSetForeground (s->display, s->gc, xgcv.background);
4425 XFillRectangle (s->display, pixmap, s->gc,
4426 0, 0, s->background_width, s->height);
4427 XSetForeground (s->display, s->gc, xgcv.foreground);
4428 }
4429 }
4430 else
4431 #endif
4432 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4433
4434 s->background_filled_p = 1;
4435 }
4436
4437 /* Draw the foreground. */
4438 if (pixmap != 0)
4439 {
4440 x_draw_image_foreground_1 (s, pixmap);
4441 x_set_glyph_string_clipping (s);
4442 mac_copy_area (s->display, pixmap, s->window, s->gc,
4443 0, 0, s->background_width, s->height, s->x, s->y);
4444 mac_reset_clipping (s->display, s->window);
4445 XFreePixmap (s->display, pixmap);
4446 }
4447 else
4448 x_draw_image_foreground (s);
4449
4450 /* If we must draw a relief around the image, do it. */
4451 if (s->img->relief
4452 || s->hl == DRAW_IMAGE_RAISED
4453 || s->hl == DRAW_IMAGE_SUNKEN)
4454 x_draw_image_relief (s);
4455 }
4456
4457
4458 /* Draw stretch glyph string S. */
4459
4460 static void
4461 x_draw_stretch_glyph_string (s)
4462 struct glyph_string *s;
4463 {
4464 xassert (s->first_glyph->type == STRETCH_GLYPH);
4465 s->stippled_p = s->face->stipple != 0;
4466
4467 if (s->hl == DRAW_CURSOR
4468 && !x_stretch_cursor_p)
4469 {
4470 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4471 as wide as the stretch glyph. */
4472 int width = min (CANON_X_UNIT (s->f), s->background_width);
4473
4474 /* Draw cursor. */
4475 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4476
4477 /* Clear rest using the GC of the original non-cursor face. */
4478 if (width < s->background_width)
4479 {
4480 GC gc = s->face->gc;
4481 int x = s->x + width, y = s->y;
4482 int w = s->background_width - width, h = s->height;
4483 Rect r;
4484
4485 if (s->row->mouse_face_p
4486 && cursor_in_mouse_face_p (s->w))
4487 {
4488 x_set_mouse_face_gc (s);
4489 gc = s->gc;
4490 }
4491 else
4492 gc = s->face->gc;
4493
4494 x_get_glyph_string_clip_rect (s, &r);
4495 mac_set_clip_rectangle (s->display, s->window, &r);
4496
4497 #if 0 /* MAC_TODO: stipple */
4498 if (s->face->stipple)
4499 {
4500 /* Fill background with a stipple pattern. */
4501 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4502 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4503 XSetFillStyle (s->display, gc, FillSolid);
4504 }
4505 else
4506 #endif /* MAC_TODO */
4507 {
4508 XGCValues xgcv;
4509 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4510 XSetForeground (s->display, gc, xgcv.background);
4511 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4512 XSetForeground (s->display, gc, xgcv.foreground);
4513 }
4514
4515 mac_reset_clipping (s->display, s->window);
4516 }
4517 }
4518 else if (!s->background_filled_p)
4519 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4520 s->height);
4521
4522 s->background_filled_p = 1;
4523 }
4524
4525
4526 /* Draw glyph string S. */
4527
4528 static void
4529 x_draw_glyph_string (s)
4530 struct glyph_string *s;
4531 {
4532 int relief_drawn_p = 0;
4533
4534 /* If S draws into the background of its successor, draw the
4535 background of the successor first so that S can draw into it.
4536 This makes S->next use XDrawString instead of XDrawImageString. */
4537 if (s->next && s->right_overhang && !s->for_overlaps_p)
4538 {
4539 xassert (s->next->img == NULL);
4540 x_set_glyph_string_gc (s->next);
4541 x_set_glyph_string_clipping (s->next);
4542 x_draw_glyph_string_background (s->next, 1);
4543
4544 }
4545
4546 /* Set up S->gc, set clipping and draw S. */
4547 x_set_glyph_string_gc (s);
4548
4549 /* Draw relief (if any) in advance for char/composition so that the
4550 glyph string can be drawn over it. */
4551 if (!s->for_overlaps_p
4552 && s->face->box != FACE_NO_BOX
4553 && (s->first_glyph->type == CHAR_GLYPH
4554 || s->first_glyph->type == COMPOSITE_GLYPH))
4555
4556 {
4557 x_set_glyph_string_clipping (s);
4558 x_draw_glyph_string_background (s, 1);
4559 x_draw_glyph_string_box (s);
4560 x_set_glyph_string_clipping (s);
4561 relief_drawn_p = 1;
4562 }
4563 else
4564 x_set_glyph_string_clipping (s);
4565
4566 switch (s->first_glyph->type)
4567 {
4568 case IMAGE_GLYPH:
4569 x_draw_image_glyph_string (s);
4570 break;
4571
4572 case STRETCH_GLYPH:
4573 x_draw_stretch_glyph_string (s);
4574 break;
4575
4576 case CHAR_GLYPH:
4577 if (s->for_overlaps_p)
4578 s->background_filled_p = 1;
4579 else
4580 x_draw_glyph_string_background (s, 0);
4581 x_draw_glyph_string_foreground (s);
4582 break;
4583
4584 case COMPOSITE_GLYPH:
4585 if (s->for_overlaps_p || s->gidx > 0)
4586 s->background_filled_p = 1;
4587 else
4588 x_draw_glyph_string_background (s, 1);
4589 x_draw_composite_glyph_string_foreground (s);
4590 break;
4591
4592 default:
4593 abort ();
4594 }
4595
4596 if (!s->for_overlaps_p)
4597 {
4598 /* Draw underline. */
4599 if (s->face->underline_p)
4600 {
4601 unsigned long h = 1;
4602 unsigned long dy = s->height - h;
4603
4604 if (s->face->underline_defaulted_p)
4605 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4606 s->width, h);
4607 else
4608 {
4609 XGCValues xgcv;
4610 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4611 XSetForeground (s->display, s->gc, s->face->underline_color);
4612 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4613 s->width, h);
4614 XSetForeground (s->display, s->gc, xgcv.foreground);
4615 }
4616 }
4617
4618 /* Draw overline. */
4619 if (s->face->overline_p)
4620 {
4621 unsigned long dy = 0, h = 1;
4622
4623 if (s->face->overline_color_defaulted_p)
4624 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4625 s->width, h);
4626 else
4627 {
4628 XGCValues xgcv;
4629 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4630 XSetForeground (s->display, s->gc, s->face->overline_color);
4631 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4632 s->width, h);
4633 XSetForeground (s->display, s->gc, xgcv.foreground);
4634 }
4635 }
4636
4637 /* Draw strike-through. */
4638 if (s->face->strike_through_p)
4639 {
4640 unsigned long h = 1;
4641 unsigned long dy = (s->height - h) / 2;
4642
4643 if (s->face->strike_through_color_defaulted_p)
4644 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4645 s->width, h);
4646 else
4647 {
4648 XGCValues xgcv;
4649 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4650 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4651 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4652 s->width, h);
4653 XSetForeground (s->display, s->gc, xgcv.foreground);
4654 }
4655 }
4656
4657 /* Draw relief. */
4658 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4659 x_draw_glyph_string_box (s);
4660 }
4661
4662 /* Reset clipping. */
4663 mac_reset_clipping (s->display, s->window);
4664 }
4665
4666
4667 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4668 struct face **, int));
4669
4670
4671 /* Fill glyph string S with composition components specified by S->cmp.
4672
4673 FACES is an array of faces for all components of this composition.
4674 S->gidx is the index of the first component for S.
4675 OVERLAPS_P non-zero means S should draw the foreground only, and
4676 use its physical height for clipping.
4677
4678 Value is the index of a component not in S. */
4679
4680 static int
4681 x_fill_composite_glyph_string (s, faces, overlaps_p)
4682 struct glyph_string *s;
4683 struct face **faces;
4684 int overlaps_p;
4685 {
4686 int i;
4687
4688 xassert (s);
4689
4690 s->for_overlaps_p = overlaps_p;
4691
4692 s->face = faces[s->gidx];
4693 s->font = s->face->font;
4694 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4695
4696 /* For all glyphs of this composition, starting at the offset
4697 S->gidx, until we reach the end of the definition or encounter a
4698 glyph that requires the different face, add it to S. */
4699 ++s->nchars;
4700 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4701 ++s->nchars;
4702
4703 /* All glyph strings for the same composition has the same width,
4704 i.e. the width set for the first component of the composition. */
4705
4706 s->width = s->first_glyph->pixel_width;
4707
4708 /* If the specified font could not be loaded, use the frame's
4709 default font, but record the fact that we couldn't load it in
4710 the glyph string so that we can draw rectangles for the
4711 characters of the glyph string. */
4712 if (s->font == NULL)
4713 {
4714 s->font_not_found_p = 1;
4715 s->font = FRAME_FONT (s->f);
4716 }
4717
4718 /* Adjust base line for subscript/superscript text. */
4719 s->ybase += s->first_glyph->voffset;
4720
4721 xassert (s->face && s->face->gc);
4722
4723 /* This glyph string must always be drawn with 16-bit functions. */
4724 s->two_byte_p = 1;
4725
4726 return s->gidx + s->nchars;
4727 }
4728
4729
4730 /* Fill glyph string S from a sequence of character glyphs.
4731
4732 FACE_ID is the face id of the string. START is the index of the
4733 first glyph to consider, END is the index of the last + 1.
4734 OVERLAPS_P non-zero means S should draw the foreground only, and
4735 use its physical height for clipping.
4736
4737 Value is the index of the first glyph not in S. */
4738
4739 static int
4740 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4741 struct glyph_string *s;
4742 int face_id;
4743 int start, end, overlaps_p;
4744 {
4745 struct glyph *glyph, *last;
4746 int voffset;
4747 int glyph_not_available_p;
4748
4749 xassert (s->f == XFRAME (s->w->frame));
4750 xassert (s->nchars == 0);
4751 xassert (start >= 0 && end > start);
4752
4753 s->for_overlaps_p = overlaps_p;
4754 glyph = s->row->glyphs[s->area] + start;
4755 last = s->row->glyphs[s->area] + end;
4756 voffset = glyph->voffset;
4757
4758 glyph_not_available_p = glyph->glyph_not_available_p;
4759
4760 while (glyph < last
4761 && glyph->type == CHAR_GLYPH
4762 && glyph->voffset == voffset
4763 /* Same face id implies same font, nowadays. */
4764 && glyph->face_id == face_id
4765 && glyph->glyph_not_available_p == glyph_not_available_p)
4766 {
4767 int two_byte_p;
4768
4769 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4770 s->char2b + s->nchars,
4771 &two_byte_p);
4772 s->two_byte_p = two_byte_p;
4773 ++s->nchars;
4774 xassert (s->nchars <= end - start);
4775 s->width += glyph->pixel_width;
4776 ++glyph;
4777 }
4778
4779 s->font = s->face->font;
4780 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4781
4782 /* If the specified font could not be loaded, use the frame's font,
4783 but record the fact that we couldn't load it in
4784 S->font_not_found_p so that we can draw rectangles for the
4785 characters of the glyph string. */
4786 if (s->font == NULL || glyph_not_available_p)
4787 {
4788 s->font_not_found_p = 1;
4789 s->font = FRAME_FONT (s->f);
4790 }
4791
4792 /* Adjust base line for subscript/superscript text. */
4793 s->ybase += voffset;
4794
4795 xassert (s->face && s->face->gc);
4796 return glyph - s->row->glyphs[s->area];
4797 }
4798
4799
4800 /* Fill glyph string S from image glyph S->first_glyph. */
4801
4802 static void
4803 x_fill_image_glyph_string (s)
4804 struct glyph_string *s;
4805 {
4806 xassert (s->first_glyph->type == IMAGE_GLYPH);
4807 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4808 xassert (s->img);
4809 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4810 s->font = s->face->font;
4811 s->width = s->first_glyph->pixel_width;
4812
4813 /* Adjust base line for subscript/superscript text. */
4814 s->ybase += s->first_glyph->voffset;
4815 }
4816
4817
4818 /* Fill glyph string S from a sequence of stretch glyphs.
4819
4820 ROW is the glyph row in which the glyphs are found, AREA is the
4821 area within the row. START is the index of the first glyph to
4822 consider, END is the index of the last + 1.
4823
4824 Value is the index of the first glyph not in S. */
4825
4826 static int
4827 x_fill_stretch_glyph_string (s, row, area, start, end)
4828 struct glyph_string *s;
4829 struct glyph_row *row;
4830 enum glyph_row_area area;
4831 int start, end;
4832 {
4833 struct glyph *glyph, *last;
4834 int voffset, face_id;
4835
4836 xassert (s->first_glyph->type == STRETCH_GLYPH);
4837
4838 glyph = s->row->glyphs[s->area] + start;
4839 last = s->row->glyphs[s->area] + end;
4840 face_id = glyph->face_id;
4841 s->face = FACE_FROM_ID (s->f, face_id);
4842 s->font = s->face->font;
4843 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4844 s->width = glyph->pixel_width;
4845 voffset = glyph->voffset;
4846
4847 for (++glyph;
4848 (glyph < last
4849 && glyph->type == STRETCH_GLYPH
4850 && glyph->voffset == voffset
4851 && glyph->face_id == face_id);
4852 ++glyph)
4853 s->width += glyph->pixel_width;
4854
4855 /* Adjust base line for subscript/superscript text. */
4856 s->ybase += voffset;
4857
4858 xassert (s->face);
4859 return glyph - s->row->glyphs[s->area];
4860 }
4861
4862
4863 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4864 of XChar2b structures for S; it can't be allocated in
4865 x_init_glyph_string because it must be allocated via `alloca'. W
4866 is the window on which S is drawn. ROW and AREA are the glyph row
4867 and area within the row from which S is constructed. START is the
4868 index of the first glyph structure covered by S. HL is a
4869 face-override for drawing S. */
4870
4871 static void
4872 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4873 struct glyph_string *s;
4874 XChar2b *char2b;
4875 struct window *w;
4876 struct glyph_row *row;
4877 enum glyph_row_area area;
4878 int start;
4879 enum draw_glyphs_face hl;
4880 {
4881 bzero (s, sizeof *s);
4882 s->w = w;
4883 s->f = XFRAME (w->frame);
4884 s->display = FRAME_MAC_DISPLAY (s->f);
4885 s->window = FRAME_MAC_WINDOW (s->f);
4886 s->char2b = char2b;
4887 s->hl = hl;
4888 s->row = row;
4889 s->area = area;
4890 s->first_glyph = row->glyphs[area] + start;
4891 s->height = row->height;
4892 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4893
4894 /* Display the internal border below the tool-bar window. */
4895 if (s->w == XWINDOW (s->f->tool_bar_window))
4896 s->y -= s->f->output_data.mac->internal_border_width;
4897
4898 s->ybase = s->y + row->ascent;
4899 }
4900
4901
4902 /* Set background width of glyph string S. START is the index of the
4903 first glyph following S. LAST_X is the right-most x-position + 1
4904 in the drawing area. */
4905
4906 static INLINE void
4907 x_set_glyph_string_background_width (s, start, last_x)
4908 struct glyph_string *s;
4909 int start;
4910 int last_x;
4911 {
4912 /* If the face of this glyph string has to be drawn to the end of
4913 the drawing area, set S->extends_to_end_of_line_p. */
4914 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4915
4916 if (start == s->row->used[s->area]
4917 && s->area == TEXT_AREA
4918 && ((s->hl == DRAW_NORMAL_TEXT
4919 && (s->row->fill_line_p
4920 || s->face->background != default_face->background
4921 || s->face->stipple != default_face->stipple
4922 || s->row->mouse_face_p))
4923 || s->hl == DRAW_MOUSE_FACE
4924 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
4925 && s->row->fill_line_p)))
4926 s->extends_to_end_of_line_p = 1;
4927
4928 /* If S extends its face to the end of the line, set its
4929 background_width to the distance to the right edge of the drawing
4930 area. */
4931 if (s->extends_to_end_of_line_p)
4932 s->background_width = last_x - s->x + 1;
4933 else
4934 s->background_width = s->width;
4935 }
4936
4937
4938 /* Add a glyph string for a stretch glyph to the list of strings
4939 between HEAD and TAIL. START is the index of the stretch glyph in
4940 row area AREA of glyph row ROW. END is the index of the last glyph
4941 in that glyph row area. X is the current output position assigned
4942 to the new glyph string constructed. HL overrides that face of the
4943 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4944 is the right-most x-position of the drawing area. */
4945
4946 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4947 and below -- keep them on one line. */
4948 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4949 do \
4950 { \
4951 s = (struct glyph_string *) alloca (sizeof *s); \
4952 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4953 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4954 x_append_glyph_string (&HEAD, &TAIL, s); \
4955 s->x = (X); \
4956 } \
4957 while (0)
4958
4959
4960 /* Add a glyph string for an image glyph to the list of strings
4961 between HEAD and TAIL. START is the index of the image glyph in
4962 row area AREA of glyph row ROW. END is the index of the last glyph
4963 in that glyph row area. X is the current output position assigned
4964 to the new glyph string constructed. HL overrides that face of the
4965 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4966 is the right-most x-position of the drawing area. */
4967
4968 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4969 do \
4970 { \
4971 s = (struct glyph_string *) alloca (sizeof *s); \
4972 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4973 x_fill_image_glyph_string (s); \
4974 x_append_glyph_string (&HEAD, &TAIL, s); \
4975 ++START; \
4976 s->x = (X); \
4977 } \
4978 while (0)
4979
4980
4981 /* Add a glyph string for a sequence of character glyphs to the list
4982 of strings between HEAD and TAIL. START is the index of the first
4983 glyph in row area AREA of glyph row ROW that is part of the new
4984 glyph string. END is the index of the last glyph in that glyph row
4985 area. X is the current output position assigned to the new glyph
4986 string constructed. HL overrides that face of the glyph; e.g. it
4987 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4988 right-most x-position of the drawing area. */
4989
4990 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4991 do \
4992 { \
4993 int c, face_id; \
4994 XChar2b *char2b; \
4995 \
4996 c = (ROW)->glyphs[AREA][START].u.ch; \
4997 face_id = (ROW)->glyphs[AREA][START].face_id; \
4998 \
4999 s = (struct glyph_string *) alloca (sizeof *s); \
5000 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5001 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5002 x_append_glyph_string (&HEAD, &TAIL, s); \
5003 s->x = (X); \
5004 START = x_fill_glyph_string (s, face_id, START, END, \
5005 OVERLAPS_P); \
5006 } \
5007 while (0)
5008
5009
5010 /* Add a glyph string for a composite sequence to the list of strings
5011 between HEAD and TAIL. START is the index of the first glyph in
5012 row area AREA of glyph row ROW that is part of the new glyph
5013 string. END is the index of the last glyph in that glyph row area.
5014 X is the current output position assigned to the new glyph string
5015 constructed. HL overrides that face of the glyph; e.g. it is
5016 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5017 x-position of the drawing area. */
5018
5019 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5020 do { \
5021 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5022 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5023 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5024 struct composition *cmp = composition_table[cmp_id]; \
5025 int glyph_len = cmp->glyph_len; \
5026 XChar2b *char2b; \
5027 struct face **faces; \
5028 struct glyph_string *first_s = NULL; \
5029 int n; \
5030 \
5031 base_face = base_face->ascii_face; \
5032 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5033 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5034 /* At first, fill in `char2b' and `faces'. */ \
5035 for (n = 0; n < glyph_len; n++) \
5036 { \
5037 int c = COMPOSITION_GLYPH (cmp, n); \
5038 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5039 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5040 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5041 this_face_id, char2b + n, 1); \
5042 } \
5043 \
5044 /* Make glyph_strings for each glyph sequence that is drawable by \
5045 the same face, and append them to HEAD/TAIL. */ \
5046 for (n = 0; n < cmp->glyph_len;) \
5047 { \
5048 s = (struct glyph_string *) alloca (sizeof *s); \
5049 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5050 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5051 s->cmp = cmp; \
5052 s->gidx = n; \
5053 s->x = (X); \
5054 \
5055 if (n == 0) \
5056 first_s = s; \
5057 \
5058 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5059 } \
5060 \
5061 ++START; \
5062 s = first_s; \
5063 } while (0)
5064
5065
5066 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5067 of AREA of glyph row ROW on window W between indices START and END.
5068 HL overrides the face for drawing glyph strings, e.g. it is
5069 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5070 x-positions of the drawing area.
5071
5072 This is an ugly monster macro construct because we must use alloca
5073 to allocate glyph strings (because x_draw_glyphs can be called
5074 asynchronously). */
5075
5076 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5077 do \
5078 { \
5079 HEAD = TAIL = NULL; \
5080 while (START < END) \
5081 { \
5082 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5083 switch (first_glyph->type) \
5084 { \
5085 case CHAR_GLYPH: \
5086 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5087 TAIL, HL, X, LAST_X, \
5088 OVERLAPS_P); \
5089 break; \
5090 \
5091 case COMPOSITE_GLYPH: \
5092 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5093 HEAD, TAIL, HL, X, LAST_X,\
5094 OVERLAPS_P); \
5095 break; \
5096 \
5097 case STRETCH_GLYPH: \
5098 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5099 HEAD, TAIL, HL, X, LAST_X); \
5100 break; \
5101 \
5102 case IMAGE_GLYPH: \
5103 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5104 TAIL, HL, X, LAST_X); \
5105 break; \
5106 \
5107 default: \
5108 abort (); \
5109 } \
5110 \
5111 x_set_glyph_string_background_width (s, START, LAST_X); \
5112 (X) += s->width; \
5113 } \
5114 } \
5115 while (0)
5116
5117
5118 /* Draw glyphs between START and END in AREA of ROW on window W,
5119 starting at x-position X. X is relative to AREA in W. HL is a
5120 face-override with the following meaning:
5121
5122 DRAW_NORMAL_TEXT draw normally
5123 DRAW_CURSOR draw in cursor face
5124 DRAW_MOUSE_FACE draw in mouse face.
5125 DRAW_INVERSE_VIDEO draw in mode line face
5126 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5127 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5128
5129 If OVERLAPS_P is non-zero, draw only the foreground of characters
5130 and clip to the physical height of ROW.
5131
5132 Value is the x-position reached, relative to AREA of W. */
5133
5134 static int
5135 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5136 struct window *w;
5137 int x;
5138 struct glyph_row *row;
5139 enum glyph_row_area area;
5140 int start, end;
5141 enum draw_glyphs_face hl;
5142 int overlaps_p;
5143 {
5144 struct glyph_string *head, *tail;
5145 struct glyph_string *s;
5146 int last_x, area_width;
5147 int x_reached;
5148 int i, j;
5149
5150 /* Let's rather be paranoid than getting a SEGV. */
5151 end = min (end, row->used[area]);
5152 start = max (0, start);
5153 start = min (end, start);
5154
5155 /* Translate X to frame coordinates. Set last_x to the right
5156 end of the drawing area. */
5157 if (row->full_width_p)
5158 {
5159 /* X is relative to the left edge of W, without scroll bars
5160 or fringes. */
5161 struct frame *f = XFRAME (WINDOW_FRAME (w));
5162 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5163
5164 x += window_left_x;
5165 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5166 last_x = window_left_x + area_width;
5167
5168 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5169 {
5170 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5171 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5172 last_x += width;
5173 else
5174 x -= width;
5175 }
5176
5177 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5178 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5179 }
5180 else
5181 {
5182 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5183 area_width = window_box_width (w, area);
5184 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5185 }
5186
5187 /* Build a doubly-linked list of glyph_string structures between
5188 head and tail from what we have to draw. Note that the macro
5189 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5190 the reason we use a separate variable `i'. */
5191 i = start;
5192 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5193 overlaps_p);
5194 if (tail)
5195 x_reached = tail->x + tail->background_width;
5196 else
5197 x_reached = x;
5198
5199 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5200 the row, redraw some glyphs in front or following the glyph
5201 strings built above. */
5202 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5203 {
5204 int dummy_x = 0;
5205 struct glyph_string *h, *t;
5206
5207 /* Compute overhangs for all glyph strings. */
5208 for (s = head; s; s = s->next)
5209 x_compute_glyph_string_overhangs (s);
5210
5211 /* Prepend glyph strings for glyphs in front of the first glyph
5212 string that are overwritten because of the first glyph
5213 string's left overhang. The background of all strings
5214 prepended must be drawn because the first glyph string
5215 draws over it. */
5216 i = x_left_overwritten (head);
5217 if (i >= 0)
5218 {
5219 j = i;
5220 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5221 DRAW_NORMAL_TEXT, dummy_x, last_x,
5222 overlaps_p);
5223 start = i;
5224 x_compute_overhangs_and_x (t, head->x, 1);
5225 x_prepend_glyph_string_lists (&head, &tail, h, t);
5226 }
5227
5228 /* Prepend glyph strings for glyphs in front of the first glyph
5229 string that overwrite that glyph string because of their
5230 right overhang. For these strings, only the foreground must
5231 be drawn, because it draws over the glyph string at `head'.
5232 The background must not be drawn because this would overwrite
5233 right overhangs of preceding glyphs for which no glyph
5234 strings exist. */
5235 i = x_left_overwriting (head);
5236 if (i >= 0)
5237 {
5238 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5239 DRAW_NORMAL_TEXT, dummy_x, last_x,
5240 overlaps_p);
5241 for (s = h; s; s = s->next)
5242 s->background_filled_p = 1;
5243 x_compute_overhangs_and_x (t, head->x, 1);
5244 x_prepend_glyph_string_lists (&head, &tail, h, t);
5245 }
5246
5247 /* Append glyphs strings for glyphs following the last glyph
5248 string tail that are overwritten by tail. The background of
5249 these strings has to be drawn because tail's foreground draws
5250 over it. */
5251 i = x_right_overwritten (tail);
5252 if (i >= 0)
5253 {
5254 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5255 DRAW_NORMAL_TEXT, x, last_x,
5256 overlaps_p);
5257 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5258 x_append_glyph_string_lists (&head, &tail, h, t);
5259 }
5260
5261 /* Append glyph strings for glyphs following the last glyph
5262 string tail that overwrite tail. The foreground of such
5263 glyphs has to be drawn because it writes into the background
5264 of tail. The background must not be drawn because it could
5265 paint over the foreground of following glyphs. */
5266 i = x_right_overwriting (tail);
5267 if (i >= 0)
5268 {
5269 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5270 DRAW_NORMAL_TEXT, x, last_x,
5271 overlaps_p);
5272 for (s = h; s; s = s->next)
5273 s->background_filled_p = 1;
5274 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5275 x_append_glyph_string_lists (&head, &tail, h, t);
5276 }
5277 }
5278
5279 /* Draw all strings. */
5280 for (s = head; s; s = s->next)
5281 x_draw_glyph_string (s);
5282
5283 if (area == TEXT_AREA
5284 && !row->full_width_p
5285 /* When drawing overlapping rows, only the glyph strings'
5286 foreground is drawn, which doesn't erase a cursor
5287 completely. */
5288 && !overlaps_p)
5289 {
5290 int x0 = head ? head->x : x;
5291 int x1 = tail ? tail->x + tail->background_width : x;
5292
5293 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5294 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5295
5296 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5297 {
5298 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5299 x0 -= left_area_width;
5300 x1 -= left_area_width;
5301 }
5302
5303 notice_overwritten_cursor (w, area, x0, x1,
5304 row->y, MATRIX_ROW_BOTTOM_Y (row));
5305 }
5306
5307 /* Value is the x-position up to which drawn, relative to AREA of W.
5308 This doesn't include parts drawn because of overhangs. */
5309 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5310 if (!row->full_width_p)
5311 {
5312 if (area > LEFT_MARGIN_AREA)
5313 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5314 if (area > TEXT_AREA)
5315 x_reached -= window_box_width (w, TEXT_AREA);
5316 }
5317
5318 return x_reached;
5319 }
5320
5321
5322 /* Fix the display of area AREA of overlapping row ROW in window W. */
5323
5324 static void
5325 x_fix_overlapping_area (w, row, area)
5326 struct window *w;
5327 struct glyph_row *row;
5328 enum glyph_row_area area;
5329 {
5330 int i, x;
5331
5332 BLOCK_INPUT;
5333
5334 if (area == LEFT_MARGIN_AREA)
5335 x = 0;
5336 else if (area == TEXT_AREA)
5337 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5338 else
5339 x = (window_box_width (w, LEFT_MARGIN_AREA)
5340 + window_box_width (w, TEXT_AREA));
5341
5342 for (i = 0; i < row->used[area];)
5343 {
5344 if (row->glyphs[area][i].overlaps_vertically_p)
5345 {
5346 int start = i, start_x = x;
5347
5348 do
5349 {
5350 x += row->glyphs[area][i].pixel_width;
5351 ++i;
5352 }
5353 while (i < row->used[area]
5354 && row->glyphs[area][i].overlaps_vertically_p);
5355
5356 x_draw_glyphs (w, start_x, row, area, start, i,
5357 DRAW_NORMAL_TEXT, 1);
5358 }
5359 else
5360 {
5361 x += row->glyphs[area][i].pixel_width;
5362 ++i;
5363 }
5364 }
5365
5366 UNBLOCK_INPUT;
5367 }
5368
5369
5370 /* Output LEN glyphs starting at START at the nominal cursor position.
5371 Advance the nominal cursor over the text. The global variable
5372 updated_window contains the window being updated, updated_row is
5373 the glyph row being updated, and updated_area is the area of that
5374 row being updated. */
5375
5376 static void
5377 x_write_glyphs (start, len)
5378 struct glyph *start;
5379 int len;
5380 {
5381 int x, hpos;
5382
5383 xassert (updated_window && updated_row);
5384 BLOCK_INPUT;
5385
5386 /* Write glyphs. */
5387
5388 hpos = start - updated_row->glyphs[updated_area];
5389 x = x_draw_glyphs (updated_window, output_cursor.x,
5390 updated_row, updated_area,
5391 hpos, hpos + len,
5392 DRAW_NORMAL_TEXT, 0);
5393
5394 UNBLOCK_INPUT;
5395
5396 /* Advance the output cursor. */
5397 output_cursor.hpos += len;
5398 output_cursor.x = x;
5399 }
5400
5401
5402 /* Insert LEN glyphs from START at the nominal cursor position. */
5403
5404 static void
5405 x_insert_glyphs (start, len)
5406 struct glyph *start;
5407 register int len;
5408 {
5409 struct frame *f;
5410 struct window *w;
5411 int line_height, shift_by_width, shifted_region_width;
5412 struct glyph_row *row;
5413 struct glyph *glyph;
5414 int frame_x, frame_y, hpos;
5415
5416 xassert (updated_window && updated_row);
5417 BLOCK_INPUT;
5418 w = updated_window;
5419 f = XFRAME (WINDOW_FRAME (w));
5420
5421 /* Get the height of the line we are in. */
5422 row = updated_row;
5423 line_height = row->height;
5424
5425 /* Get the width of the glyphs to insert. */
5426 shift_by_width = 0;
5427 for (glyph = start; glyph < start + len; ++glyph)
5428 shift_by_width += glyph->pixel_width;
5429
5430 /* Get the width of the region to shift right. */
5431 shifted_region_width = (window_box_width (w, updated_area)
5432 - output_cursor.x
5433 - shift_by_width);
5434
5435 /* Shift right. */
5436 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5437 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5438
5439 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5440 f->output_data.mac->normal_gc,
5441 frame_x, frame_y,
5442 shifted_region_width, line_height,
5443 frame_x + shift_by_width, frame_y);
5444
5445 /* Write the glyphs. */
5446 hpos = start - row->glyphs[updated_area];
5447 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5448 DRAW_NORMAL_TEXT, 0);
5449
5450 /* Advance the output cursor. */
5451 output_cursor.hpos += len;
5452 output_cursor.x += shift_by_width;
5453 UNBLOCK_INPUT;
5454 }
5455
5456
5457 /* Delete N glyphs at the nominal cursor position. Not implemented
5458 for X frames. */
5459
5460 static void
5461 x_delete_glyphs (n)
5462 register int n;
5463 {
5464 abort ();
5465 }
5466
5467
5468 /* Erase the current text line from the nominal cursor position
5469 (inclusive) to pixel column TO_X (exclusive). The idea is that
5470 everything from TO_X onward is already erased.
5471
5472 TO_X is a pixel position relative to updated_area of
5473 updated_window. TO_X == -1 means clear to the end of this area. */
5474
5475 static void
5476 x_clear_end_of_line (to_x)
5477 int to_x;
5478 {
5479 struct frame *f;
5480 struct window *w = updated_window;
5481 int max_x, min_y, max_y;
5482 int from_x, from_y, to_y;
5483
5484 xassert (updated_window && updated_row);
5485 f = XFRAME (w->frame);
5486
5487 if (updated_row->full_width_p)
5488 {
5489 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5490 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5491 && !w->pseudo_window_p)
5492 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5493 }
5494 else
5495 max_x = window_box_width (w, updated_area);
5496 max_y = window_text_bottom_y (w);
5497
5498 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5499 of window. For TO_X > 0, truncate to end of drawing area. */
5500 if (to_x == 0)
5501 return;
5502 else if (to_x < 0)
5503 to_x = max_x;
5504 else
5505 to_x = min (to_x, max_x);
5506
5507 to_y = min (max_y, output_cursor.y + updated_row->height);
5508
5509 /* Notice if the cursor will be cleared by this operation. */
5510 if (!updated_row->full_width_p)
5511 notice_overwritten_cursor (w, updated_area,
5512 output_cursor.x, -1,
5513 updated_row->y,
5514 MATRIX_ROW_BOTTOM_Y (updated_row));
5515
5516 from_x = output_cursor.x;
5517
5518 /* Translate to frame coordinates. */
5519 if (updated_row->full_width_p)
5520 {
5521 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5522 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5523 }
5524 else
5525 {
5526 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5527 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5528 }
5529
5530 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5531 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5532 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5533
5534 /* Prevent inadvertently clearing to end of the X window. */
5535 if (to_x > from_x && to_y > from_y)
5536 {
5537 BLOCK_INPUT;
5538 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5539 from_x, from_y, to_x - from_x, to_y - from_y,
5540 0);
5541 UNBLOCK_INPUT;
5542 }
5543 }
5544
5545
5546 /* Clear entire frame. If updating_frame is non-null, clear that
5547 frame. Otherwise clear the selected frame. */
5548
5549 static void
5550 x_clear_frame ()
5551 {
5552 struct frame *f;
5553
5554 if (updating_frame)
5555 f = updating_frame;
5556 else
5557 f = SELECTED_FRAME ();
5558
5559 /* Clearing the frame will erase any cursor, so mark them all as no
5560 longer visible. */
5561 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5562 output_cursor.hpos = output_cursor.vpos = 0;
5563 output_cursor.x = -1;
5564
5565 /* We don't set the output cursor here because there will always
5566 follow an explicit cursor_to. */
5567 BLOCK_INPUT;
5568 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5569
5570 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5571 /* We have to clear the scroll bars, too. If we have changed
5572 colors or something like that, then they should be notified. */
5573 x_scroll_bar_clear (f);
5574 #endif
5575
5576 XFlush (FRAME_MAC_DISPLAY (f));
5577 UNBLOCK_INPUT;
5578 }
5579
5580
5581 \f
5582 /* Invert the middle quarter of the frame for .15 sec. */
5583
5584 /* We use the select system call to do the waiting, so we have to make
5585 sure it's available. If it isn't, we just won't do visual bells. */
5586
5587 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5588
5589 /* Subtract the `struct timeval' values X and Y, storing the result in
5590 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5591
5592 static int
5593 timeval_subtract (result, x, y)
5594 struct timeval *result, x, y;
5595 {
5596 /* Perform the carry for the later subtraction by updating y. This
5597 is safer because on some systems the tv_sec member is unsigned. */
5598 if (x.tv_usec < y.tv_usec)
5599 {
5600 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5601 y.tv_usec -= 1000000 * nsec;
5602 y.tv_sec += nsec;
5603 }
5604
5605 if (x.tv_usec - y.tv_usec > 1000000)
5606 {
5607 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5608 y.tv_usec += 1000000 * nsec;
5609 y.tv_sec -= nsec;
5610 }
5611
5612 /* Compute the time remaining to wait. tv_usec is certainly
5613 positive. */
5614 result->tv_sec = x.tv_sec - y.tv_sec;
5615 result->tv_usec = x.tv_usec - y.tv_usec;
5616
5617 /* Return indication of whether the result should be considered
5618 negative. */
5619 return x.tv_sec < y.tv_sec;
5620 }
5621
5622 void
5623 XTflash (f)
5624 struct frame *f;
5625 {
5626 BLOCK_INPUT;
5627
5628 FlashMenuBar (0);
5629
5630 {
5631 struct timeval wakeup;
5632
5633 EMACS_GET_TIME (wakeup);
5634
5635 /* Compute time to wait until, propagating carry from usecs. */
5636 wakeup.tv_usec += 150000;
5637 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5638 wakeup.tv_usec %= 1000000;
5639
5640 /* Keep waiting until past the time wakeup. */
5641 while (1)
5642 {
5643 struct timeval timeout;
5644
5645 EMACS_GET_TIME (timeout);
5646
5647 /* In effect, timeout = wakeup - timeout.
5648 Break if result would be negative. */
5649 if (timeval_subtract (&timeout, wakeup, timeout))
5650 break;
5651
5652 /* Try to wait that long--but we might wake up sooner. */
5653 select (0, NULL, NULL, NULL, &timeout);
5654 }
5655 }
5656
5657 FlashMenuBar (0);
5658
5659 UNBLOCK_INPUT;
5660 }
5661
5662 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5663
5664
5665 /* Make audible bell. */
5666
5667 void
5668 XTring_bell ()
5669 {
5670 struct frame *f = SELECTED_FRAME ();
5671
5672 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5673 if (visible_bell)
5674 XTflash (f);
5675 else
5676 #endif
5677 {
5678 BLOCK_INPUT;
5679 SysBeep (1);
5680 XFlush (FRAME_MAC_DISPLAY (f));
5681 UNBLOCK_INPUT;
5682 }
5683 }
5684
5685
5686 \f
5687 /* Specify how many text lines, from the top of the window,
5688 should be affected by insert-lines and delete-lines operations.
5689 This, and those operations, are used only within an update
5690 that is bounded by calls to x_update_begin and x_update_end. */
5691
5692 void
5693 XTset_terminal_window (n)
5694 register int n;
5695 {
5696 /* This function intentionally left blank. */
5697 }
5698
5699
5700 \f
5701 /***********************************************************************
5702 Line Dance
5703 ***********************************************************************/
5704
5705 /* Perform an insert-lines or delete-lines operation, inserting N
5706 lines or deleting -N lines at vertical position VPOS. */
5707
5708 static void
5709 x_ins_del_lines (vpos, n)
5710 int vpos, n;
5711 {
5712 abort ();
5713 }
5714
5715
5716 /* Scroll part of the display as described by RUN. */
5717
5718 static void
5719 x_scroll_run (w, run)
5720 struct window *w;
5721 struct run *run;
5722 {
5723 struct frame *f = XFRAME (w->frame);
5724 int x, y, width, height, from_y, to_y, bottom_y;
5725
5726 /* Get frame-relative bounding box of the text display area of W,
5727 without mode lines. Include in this box the left and right
5728 fringes of W. */
5729 window_box (w, -1, &x, &y, &width, &height);
5730 width += FRAME_X_FRINGE_WIDTH (f);
5731 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5732
5733 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5734 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5735 bottom_y = y + height;
5736
5737 if (to_y < from_y)
5738 {
5739 /* Scrolling up. Make sure we don't copy part of the mode
5740 line at the bottom. */
5741 if (from_y + run->height > bottom_y)
5742 height = bottom_y - from_y;
5743 else
5744 height = run->height;
5745 }
5746 else
5747 {
5748 /* Scolling down. Make sure we don't copy over the mode line.
5749 at the bottom. */
5750 if (to_y + run->height > bottom_y)
5751 height = bottom_y - to_y;
5752 else
5753 height = run->height;
5754 }
5755
5756 BLOCK_INPUT;
5757
5758 /* Cursor off. Will be switched on again in x_update_window_end. */
5759 updated_window = w;
5760 x_clear_cursor (w);
5761
5762 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5763 f->output_data.mac->normal_gc,
5764 x, from_y,
5765 width, height,
5766 x, to_y);
5767
5768 UNBLOCK_INPUT;
5769 }
5770
5771
5772 \f
5773 /***********************************************************************
5774 Exposure Events
5775 ***********************************************************************/
5776
5777 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5778 corner of the exposed rectangle. W and H are width and height of
5779 the exposed area. All are pixel values. W or H zero means redraw
5780 the entire frame. */
5781
5782 static void
5783 expose_frame (f, x, y, w, h)
5784 struct frame *f;
5785 int x, y, w, h;
5786 {
5787 Rect r;
5788 int mouse_face_overwritten_p = 0;
5789
5790 TRACE ((stderr, "expose_frame "));
5791
5792 /* No need to redraw if frame will be redrawn soon. */
5793 if (FRAME_GARBAGED_P (f))
5794 {
5795 TRACE ((stderr, " garbaged\n"));
5796 return;
5797 }
5798
5799 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
5800 or deactivated here, for unknown reasons, activated scroll bars
5801 are shown in deactivated frames in some instances. */
5802 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
5803 activate_scroll_bars (f);
5804 else
5805 deactivate_scroll_bars (f);
5806
5807 /* If basic faces haven't been realized yet, there is no point in
5808 trying to redraw anything. This can happen when we get an expose
5809 event while Emacs is starting, e.g. by moving another window. */
5810 if (FRAME_FACE_CACHE (f) == NULL
5811 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5812 {
5813 TRACE ((stderr, " no faces\n"));
5814 return;
5815 }
5816
5817 if (w == 0 || h == 0)
5818 {
5819 r.left = r.top = 0;
5820 r.right = CANON_X_UNIT (f) * f->width;
5821 r.bottom = CANON_Y_UNIT (f) * f->height;
5822 }
5823 else
5824 {
5825 r.left = x;
5826 r.top = y;
5827 r.right = x + w;
5828 r.bottom = y + h;
5829 }
5830
5831 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
5832 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5833
5834 if (WINDOWP (f->tool_bar_window))
5835 mouse_face_overwritten_p
5836 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5837
5838 /* Some window managers support a focus-follows-mouse style with
5839 delayed raising of frames. Imagine a partially obscured frame,
5840 and moving the mouse into partially obscured mouse-face on that
5841 frame. The visible part of the mouse-face will be highlighted,
5842 then the WM raises the obscured frame. With at least one WM, KDE
5843 2.1, Emacs is not getting any event for the raising of the frame
5844 (even tried with SubstructureRedirectMask), only Expose events.
5845 These expose events will draw text normally, i.e. not
5846 highlighted. Which means we must redo the highlight here.
5847 Subsume it under ``we love X''. --gerd 2001-08-15 */
5848 /* Included in Windows version because Windows most likely does not
5849 do the right thing if any third party tool offers
5850 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
5851 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5852 {
5853 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5854 if (f == dpyinfo->mouse_face_mouse_frame)
5855 {
5856 int x = dpyinfo->mouse_face_mouse_x;
5857 int y = dpyinfo->mouse_face_mouse_y;
5858 clear_mouse_face (dpyinfo);
5859 note_mouse_highlight (f, x, y);
5860 }
5861 }
5862 }
5863
5864
5865 /* Redraw (parts) of all windows in the window tree rooted at W that
5866 intersect R. R contains frame pixel coordinates. */
5867
5868 static int
5869 expose_window_tree (w, r)
5870 struct window *w;
5871 Rect *r;
5872 {
5873 struct frame *f = XFRAME (w->frame);
5874 int mouse_face_overwritten_p = 0;
5875
5876 while (w && !FRAME_GARBAGED_P (f))
5877 {
5878 if (!NILP (w->hchild))
5879 mouse_face_overwritten_p
5880 |= expose_window_tree (XWINDOW (w->hchild), r);
5881 else if (!NILP (w->vchild))
5882 mouse_face_overwritten_p
5883 |= expose_window_tree (XWINDOW (w->vchild), r);
5884 else
5885 mouse_face_overwritten_p |= expose_window (w, r);
5886
5887 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5888 }
5889
5890 return mouse_face_overwritten_p;
5891 }
5892
5893
5894 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5895 which intersects rectangle R. R is in window-relative coordinates. */
5896
5897 static void
5898 expose_area (w, row, r, area)
5899 struct window *w;
5900 struct glyph_row *row;
5901 Rect *r;
5902 enum glyph_row_area area;
5903 {
5904 struct glyph *first = row->glyphs[area];
5905 struct glyph *end = row->glyphs[area] + row->used[area];
5906 struct glyph *last;
5907 int first_x, start_x, x;
5908
5909 if (area == TEXT_AREA && row->fill_line_p)
5910 /* If row extends face to end of line write the whole line. */
5911 x_draw_glyphs (w, 0, row, area,
5912 0, row->used[area],
5913 DRAW_NORMAL_TEXT, 0);
5914 else
5915 {
5916 /* Set START_X to the window-relative start position for drawing glyphs of
5917 AREA. The first glyph of the text area can be partially visible.
5918 The first glyphs of other areas cannot. */
5919 if (area == LEFT_MARGIN_AREA)
5920 start_x = 0;
5921 else if (area == TEXT_AREA)
5922 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5923 else
5924 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5925 + window_box_width (w, TEXT_AREA));
5926 x = start_x;
5927
5928 /* Find the first glyph that must be redrawn. */
5929 while (first < end
5930 && x + first->pixel_width < r->left)
5931 {
5932 x += first->pixel_width;
5933 ++first;
5934 }
5935
5936 /* Find the last one. */
5937 last = first;
5938 first_x = x;
5939 while (last < end
5940 && x < r->right)
5941 {
5942 x += last->pixel_width;
5943 ++last;
5944 }
5945
5946 /* Repaint. */
5947 if (last > first)
5948 x_draw_glyphs (w, first_x - start_x, row, area,
5949 first - row->glyphs[area],
5950 last - row->glyphs[area],
5951 DRAW_NORMAL_TEXT, 0);
5952 }
5953 }
5954
5955
5956 /* Redraw the parts of the glyph row ROW on window W intersecting
5957 rectangle R. R is in window-relative coordinates. Value is
5958 non-zero if mouse face was overwritten. */
5959
5960 static int
5961 expose_line (w, row, r)
5962 struct window *w;
5963 struct glyph_row *row;
5964 Rect *r;
5965 {
5966 xassert (row->enabled_p);
5967
5968 if (row->mode_line_p || w->pseudo_window_p)
5969 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5970 DRAW_NORMAL_TEXT, 0);
5971 else
5972 {
5973 if (row->used[LEFT_MARGIN_AREA])
5974 expose_area (w, row, r, LEFT_MARGIN_AREA);
5975 if (row->used[TEXT_AREA])
5976 expose_area (w, row, r, TEXT_AREA);
5977 if (row->used[RIGHT_MARGIN_AREA])
5978 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5979 draw_row_fringe_bitmaps (w, row);
5980 }
5981
5982 return row->mouse_face_p;
5983 }
5984
5985
5986 /* Return non-zero if W's cursor intersects rectangle R. */
5987
5988 static int
5989 x_phys_cursor_in_rect_p (w, r)
5990 struct window *w;
5991 Rect *r;
5992 {
5993 Rect cr, result;
5994 struct glyph *cursor_glyph;
5995
5996 cursor_glyph = get_phys_cursor_glyph (w);
5997 if (cursor_glyph)
5998 {
5999 cr.left = w->phys_cursor.x;
6000 cr.top = w->phys_cursor.y;
6001 cr.right = cr.left + cursor_glyph->pixel_width;
6002 cr.bottom = cr.top + w->phys_cursor_height;
6003 return x_intersect_rectangles (&cr, r, &result);
6004 }
6005 else
6006 return 0;
6007 }
6008
6009
6010 /* Redraw those parts of glyphs rows during expose event handling that
6011 overlap other rows. Redrawing of an exposed line writes over parts
6012 of lines overlapping that exposed line; this function fixes that.
6013
6014 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
6015 row in W's current matrix that is exposed and overlaps other rows.
6016 LAST_OVERLAPPING_ROW is the last such row. */
6017
6018 static void
6019 expose_overlaps (w, first_overlapping_row, last_overlapping_row)
6020 struct window *w;
6021 struct glyph_row *first_overlapping_row;
6022 struct glyph_row *last_overlapping_row;
6023 {
6024 struct glyph_row *row;
6025
6026 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
6027 if (row->overlapping_p)
6028 {
6029 xassert (row->enabled_p && !row->mode_line_p);
6030
6031 if (row->used[LEFT_MARGIN_AREA])
6032 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
6033
6034 if (row->used[TEXT_AREA])
6035 x_fix_overlapping_area (w, row, TEXT_AREA);
6036
6037 if (row->used[RIGHT_MARGIN_AREA])
6038 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
6039 }
6040 }
6041
6042
6043 /* Redraw the part of window W intersection rectangle FR. Pixel
6044 coordinates in FR are frame-relative. Call this function with
6045 input blocked. Value is non-zero if the exposure overwrites
6046 mouse-face. */
6047
6048 static int
6049 expose_window (w, fr)
6050 struct window *w;
6051 Rect *fr;
6052 {
6053 struct frame *f = XFRAME (w->frame);
6054 Rect wr, r;
6055 int mouse_face_overwritten_p = 0;
6056
6057 /* If window is not yet fully initialized, do nothing. This can
6058 happen when toolkit scroll bars are used and a window is split.
6059 Reconfiguring the scroll bar will generate an expose for a newly
6060 created window. */
6061 if (w->current_matrix == NULL)
6062 return 0;
6063
6064 /* When we're currently updating the window, display and current
6065 matrix usually don't agree. Arrange for a thorough display
6066 later. */
6067 if (w == updated_window)
6068 {
6069 SET_FRAME_GARBAGED (f);
6070 return 0;
6071 }
6072
6073 /* Frame-relative pixel rectangle of W. */
6074 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6075 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6076 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6077 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6078
6079 if (x_intersect_rectangles (fr, &wr, &r))
6080 {
6081 int yb = window_text_bottom_y (w);
6082 struct glyph_row *row;
6083 int cursor_cleared_p;
6084 struct glyph_row *first_overlapping_row, *last_overlapping_row;
6085
6086 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6087 r.left, r.top, r.right, r.bottom));
6088
6089 /* Convert to window coordinates. */
6090 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6091 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6092 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6093 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6094
6095 /* Turn off the cursor. */
6096 if (!w->pseudo_window_p
6097 && x_phys_cursor_in_rect_p (w, &r))
6098 {
6099 x_clear_cursor (w);
6100 cursor_cleared_p = 1;
6101 }
6102 else
6103 cursor_cleared_p = 0;
6104
6105 /* Update lines intersecting rectangle R. */
6106 first_overlapping_row = last_overlapping_row = NULL;
6107 for (row = w->current_matrix->rows;
6108 row->enabled_p;
6109 ++row)
6110 {
6111 int y0 = row->y;
6112 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6113
6114 if ((y0 >= r.top && y0 < r.bottom)
6115 || (y1 > r.top && y1 < r.bottom)
6116 || (r.top >= y0 && r.top < y1)
6117 || (r.bottom > y0 && r.bottom < y1))
6118 {
6119 if (row->overlapping_p)
6120 {
6121 if (first_overlapping_row == NULL)
6122 first_overlapping_row = row;
6123 last_overlapping_row = row;
6124 }
6125
6126 if (expose_line (w, row, &r))
6127 mouse_face_overwritten_p = 1;
6128 }
6129
6130 if (y1 >= yb)
6131 break;
6132 }
6133
6134 /* Display the mode line if there is one. */
6135 if (WINDOW_WANTS_MODELINE_P (w)
6136 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6137 row->enabled_p)
6138 && row->y < r.bottom)
6139 {
6140 if (expose_line (w, row, &r))
6141 mouse_face_overwritten_p = 1;
6142 }
6143
6144 if (!w->pseudo_window_p)
6145 {
6146 /* Fix the display of overlapping rows. */
6147 if (first_overlapping_row)
6148 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
6149
6150 /* Draw border between windows. */
6151 x_draw_vertical_border (w);
6152
6153 /* Turn the cursor on again. */
6154 if (cursor_cleared_p)
6155 x_update_window_cursor (w, 1);
6156 }
6157 }
6158
6159 /* Display scroll bar for this window. */
6160 if (!NILP (w->vertical_scroll_bar))
6161 {
6162 ControlHandle ch
6163 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6164
6165 Draw1Control (ch);
6166 }
6167
6168 return mouse_face_overwritten_p;
6169 }
6170
6171 static int
6172 x_intersect_rectangles (r1, r2, result)
6173 Rect *r1, *r2, *result;
6174 {
6175 Rect *left, *right;
6176 Rect *upper, *lower;
6177 int intersection_p = 0;
6178
6179 /* Rerrange so that R1 is the left-most rectangle. */
6180 if (r1->left < r2->left)
6181 left = r1, right = r2;
6182 else
6183 left = r2, right = r1;
6184
6185 /* X0 of the intersection is right.x0, if this is inside R1,
6186 otherwise there is no intersection. */
6187 if (right->left <= left->right)
6188 {
6189 result->left = right->left;
6190
6191 /* The right end of the intersection is the minimum of the
6192 the right ends of left and right. */
6193 result->right = min (left->right, right->right);
6194
6195 /* Same game for Y. */
6196 if (r1->top < r2->top)
6197 upper = r1, lower = r2;
6198 else
6199 upper = r2, lower = r1;
6200
6201 /* The upper end of the intersection is lower.y0, if this is inside
6202 of upper. Otherwise, there is no intersection. */
6203 if (lower->top <= upper->bottom)
6204 {
6205 result->top = lower->top;
6206
6207 /* The lower end of the intersection is the minimum of the lower
6208 ends of upper and lower. */
6209 result->bottom = min (lower->bottom, upper->bottom);
6210 intersection_p = 1;
6211 }
6212 }
6213
6214 return intersection_p;
6215 }
6216
6217
6218
6219
6220 \f
6221 static void
6222 frame_highlight (f)
6223 struct frame *f;
6224 {
6225 x_update_cursor (f, 1);
6226 }
6227
6228 static void
6229 frame_unhighlight (f)
6230 struct frame *f;
6231 {
6232 x_update_cursor (f, 1);
6233 }
6234
6235 /* The focus has changed. Update the frames as necessary to reflect
6236 the new situation. Note that we can't change the selected frame
6237 here, because the Lisp code we are interrupting might become confused.
6238 Each event gets marked with the frame in which it occurred, so the
6239 Lisp code can tell when the switch took place by examining the events. */
6240
6241 static void
6242 x_new_focus_frame (dpyinfo, frame)
6243 struct x_display_info *dpyinfo;
6244 struct frame *frame;
6245 {
6246 struct frame *old_focus = dpyinfo->x_focus_frame;
6247
6248 if (frame != dpyinfo->x_focus_frame)
6249 {
6250 /* Set this before calling other routines, so that they see
6251 the correct value of x_focus_frame. */
6252 dpyinfo->x_focus_frame = frame;
6253
6254 if (old_focus && old_focus->auto_lower)
6255 x_lower_frame (old_focus);
6256
6257 #if 0
6258 selected_frame = frame;
6259 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6260 selected_frame);
6261 Fselect_window (selected_frame->selected_window);
6262 choose_minibuf_frame ();
6263 #endif /* ! 0 */
6264
6265 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6266 pending_autoraise_frame = dpyinfo->x_focus_frame;
6267 else
6268 pending_autoraise_frame = 0;
6269 }
6270
6271 x_frame_rehighlight (dpyinfo);
6272 }
6273
6274 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6275
6276 void
6277 x_mouse_leave (dpyinfo)
6278 struct x_display_info *dpyinfo;
6279 {
6280 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6281 }
6282
6283 /* The focus has changed, or we have redirected a frame's focus to
6284 another frame (this happens when a frame uses a surrogate
6285 mini-buffer frame). Shift the highlight as appropriate.
6286
6287 The FRAME argument doesn't necessarily have anything to do with which
6288 frame is being highlighted or un-highlighted; we only use it to find
6289 the appropriate X display info. */
6290
6291 static void
6292 XTframe_rehighlight (frame)
6293 struct frame *frame;
6294 {
6295 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6296 }
6297
6298 static void
6299 x_frame_rehighlight (dpyinfo)
6300 struct x_display_info *dpyinfo;
6301 {
6302 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6303
6304 if (dpyinfo->x_focus_frame)
6305 {
6306 dpyinfo->x_highlight_frame
6307 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6308 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6309 : dpyinfo->x_focus_frame);
6310 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6311 {
6312 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6313 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6314 }
6315 }
6316 else
6317 dpyinfo->x_highlight_frame = 0;
6318
6319 if (dpyinfo->x_highlight_frame != old_highlight)
6320 {
6321 if (old_highlight)
6322 frame_unhighlight (old_highlight);
6323 if (dpyinfo->x_highlight_frame)
6324 frame_highlight (dpyinfo->x_highlight_frame);
6325 }
6326 }
6327
6328
6329 \f
6330 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6331
6332 #if 0 /* MAC_TODO */
6333 /* Initialize mode_switch_bit and modifier_meaning. */
6334 static void
6335 x_find_modifier_meanings (dpyinfo)
6336 struct x_display_info *dpyinfo;
6337 {
6338 int min_code, max_code;
6339 KeySym *syms;
6340 int syms_per_code;
6341 XModifierKeymap *mods;
6342
6343 dpyinfo->meta_mod_mask = 0;
6344 dpyinfo->shift_lock_mask = 0;
6345 dpyinfo->alt_mod_mask = 0;
6346 dpyinfo->super_mod_mask = 0;
6347 dpyinfo->hyper_mod_mask = 0;
6348
6349 #ifdef HAVE_X11R4
6350 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6351 #else
6352 min_code = dpyinfo->display->min_keycode;
6353 max_code = dpyinfo->display->max_keycode;
6354 #endif
6355
6356 syms = XGetKeyboardMapping (dpyinfo->display,
6357 min_code, max_code - min_code + 1,
6358 &syms_per_code);
6359 mods = XGetModifierMapping (dpyinfo->display);
6360
6361 /* Scan the modifier table to see which modifier bits the Meta and
6362 Alt keysyms are on. */
6363 {
6364 int row, col; /* The row and column in the modifier table. */
6365
6366 for (row = 3; row < 8; row++)
6367 for (col = 0; col < mods->max_keypermod; col++)
6368 {
6369 KeyCode code
6370 = mods->modifiermap[(row * mods->max_keypermod) + col];
6371
6372 /* Zeroes are used for filler. Skip them. */
6373 if (code == 0)
6374 continue;
6375
6376 /* Are any of this keycode's keysyms a meta key? */
6377 {
6378 int code_col;
6379
6380 for (code_col = 0; code_col < syms_per_code; code_col++)
6381 {
6382 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6383
6384 switch (sym)
6385 {
6386 case XK_Meta_L:
6387 case XK_Meta_R:
6388 dpyinfo->meta_mod_mask |= (1 << row);
6389 break;
6390
6391 case XK_Alt_L:
6392 case XK_Alt_R:
6393 dpyinfo->alt_mod_mask |= (1 << row);
6394 break;
6395
6396 case XK_Hyper_L:
6397 case XK_Hyper_R:
6398 dpyinfo->hyper_mod_mask |= (1 << row);
6399 break;
6400
6401 case XK_Super_L:
6402 case XK_Super_R:
6403 dpyinfo->super_mod_mask |= (1 << row);
6404 break;
6405
6406 case XK_Shift_Lock:
6407 /* Ignore this if it's not on the lock modifier. */
6408 if ((1 << row) == LockMask)
6409 dpyinfo->shift_lock_mask = LockMask;
6410 break;
6411 }
6412 }
6413 }
6414 }
6415 }
6416
6417 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6418 if (! dpyinfo->meta_mod_mask)
6419 {
6420 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6421 dpyinfo->alt_mod_mask = 0;
6422 }
6423
6424 /* If some keys are both alt and meta,
6425 make them just meta, not alt. */
6426 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6427 {
6428 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6429 }
6430
6431 XFree ((char *) syms);
6432 XFreeModifiermap (mods);
6433 }
6434
6435 #endif /* MAC_TODO */
6436
6437 /* Convert between the modifier bits X uses and the modifier bits
6438 Emacs uses. */
6439
6440 static unsigned int
6441 x_mac_to_emacs_modifiers (dpyinfo, state)
6442 struct x_display_info *dpyinfo;
6443 unsigned short state;
6444 {
6445 return (((state & shiftKey) ? shift_modifier : 0)
6446 | ((state & controlKey) ? ctrl_modifier : 0)
6447 | ((state & cmdKey) ? meta_modifier : 0)
6448 | ((state & optionKey) ? alt_modifier : 0));
6449 }
6450
6451 #if 0 /* MAC_TODO */
6452 static unsigned short
6453 x_emacs_to_x_modifiers (dpyinfo, state)
6454 struct x_display_info *dpyinfo;
6455 unsigned int state;
6456 {
6457 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6458 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6459 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6460 | ((state & shift_modifier) ? ShiftMask : 0)
6461 | ((state & ctrl_modifier) ? ControlMask : 0)
6462 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6463 }
6464 #endif /* MAC_TODO */
6465
6466 /* Convert a keysym to its name. */
6467
6468 char *
6469 x_get_keysym_name (keysym)
6470 int keysym;
6471 {
6472 char *value;
6473
6474 BLOCK_INPUT;
6475 #if 0
6476 value = XKeysymToString (keysym);
6477 #else
6478 value = 0;
6479 #endif
6480 UNBLOCK_INPUT;
6481
6482 return value;
6483 }
6484
6485
6486 \f
6487 /* Mouse clicks and mouse movement. Rah. */
6488
6489 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6490 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6491 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6492 not force the value into range. */
6493
6494 void
6495 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6496 FRAME_PTR f;
6497 register int pix_x, pix_y;
6498 register int *x, *y;
6499 Rect *bounds;
6500 int noclip;
6501 {
6502 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6503 if (NILP (Vwindow_system))
6504 {
6505 *x = pix_x;
6506 *y = pix_y;
6507 return;
6508 }
6509
6510 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6511 even for negative values. */
6512 if (pix_x < 0)
6513 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6514 if (pix_y < 0)
6515 pix_y -= (f)->output_data.mac->line_height - 1;
6516
6517 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6518 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6519
6520 if (bounds)
6521 {
6522 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6523 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6524 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6525 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
6526 }
6527
6528 if (!noclip)
6529 {
6530 if (pix_x < 0)
6531 pix_x = 0;
6532 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6533 pix_x = FRAME_WINDOW_WIDTH (f);
6534
6535 if (pix_y < 0)
6536 pix_y = 0;
6537 else if (pix_y > f->height)
6538 pix_y = f->height;
6539 }
6540
6541 *x = pix_x;
6542 *y = pix_y;
6543 }
6544
6545
6546 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6547 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6548 can't tell the positions because W's display is not up to date,
6549 return 0. */
6550
6551 int
6552 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6553 struct window *w;
6554 int hpos, vpos;
6555 int *frame_x, *frame_y;
6556 {
6557 int success_p;
6558
6559 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6560 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6561
6562 if (display_completed)
6563 {
6564 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6565 struct glyph *glyph = row->glyphs[TEXT_AREA];
6566 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6567
6568 *frame_y = row->y;
6569 *frame_x = row->x;
6570 while (glyph < end)
6571 {
6572 *frame_x += glyph->pixel_width;
6573 ++glyph;
6574 }
6575
6576 success_p = 1;
6577 }
6578 else
6579 {
6580 *frame_y = *frame_x = 0;
6581 success_p = 0;
6582 }
6583
6584 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6585 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6586 return success_p;
6587 }
6588
6589
6590 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6591
6592 If the event is a button press, then note that we have grabbed
6593 the mouse. */
6594
6595 static Lisp_Object
6596 construct_mouse_click (result, event, f)
6597 struct input_event *result;
6598 EventRecord *event;
6599 struct frame *f;
6600 {
6601 Point mouseLoc;
6602
6603 result->kind = MOUSE_CLICK_EVENT;
6604 result->code = 0; /* only one mouse button */
6605 result->timestamp = event->when;
6606 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6607
6608 mouseLoc = event->where;
6609
6610 #if TARGET_API_MAC_CARBON
6611 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6612 #else
6613 SetPort (FRAME_MAC_WINDOW (f));
6614 #endif
6615
6616 GlobalToLocal (&mouseLoc);
6617 XSETINT (result->x, mouseLoc.h);
6618 XSETINT (result->y, mouseLoc.v);
6619
6620 XSETFRAME (result->frame_or_window, f);
6621
6622 result->arg = Qnil;
6623 return Qnil;
6624 }
6625
6626 \f
6627 /* Function to report a mouse movement to the mainstream Emacs code.
6628 The input handler calls this.
6629
6630 We have received a mouse movement event, which is given in *event.
6631 If the mouse is over a different glyph than it was last time, tell
6632 the mainstream emacs code by setting mouse_moved. If not, ask for
6633 another motion event, so we can check again the next time it moves. */
6634
6635 static Point last_mouse_motion_position;
6636 static Lisp_Object last_mouse_motion_frame;
6637
6638 static void
6639 note_mouse_movement (frame, pos)
6640 FRAME_PTR frame;
6641 Point *pos;
6642 {
6643 #if TARGET_API_MAC_CARBON
6644 Rect r;
6645 #endif
6646
6647 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6648 last_mouse_motion_position = *pos;
6649 XSETFRAME (last_mouse_motion_frame, frame);
6650
6651 #if TARGET_API_MAC_CARBON
6652 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6653 #else
6654 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6655 #endif
6656 {
6657 frame->mouse_moved = 1;
6658 last_mouse_scroll_bar = Qnil;
6659 note_mouse_highlight (frame, -1, -1);
6660 }
6661 /* Has the mouse moved off the glyph it was on at the last sighting? */
6662 else if (pos->h < last_mouse_glyph.left
6663 || pos->h >= last_mouse_glyph.right
6664 || pos->v < last_mouse_glyph.top
6665 || pos->v >= last_mouse_glyph.bottom)
6666 {
6667 frame->mouse_moved = 1;
6668 last_mouse_scroll_bar = Qnil;
6669 note_mouse_highlight (frame, pos->h, pos->v);
6670 }
6671 }
6672
6673 /* This is used for debugging, to turn off note_mouse_highlight. */
6674
6675 int disable_mouse_highlight;
6676
6677
6678 \f
6679 /************************************************************************
6680 Mouse Face
6681 ************************************************************************/
6682
6683 /* Find the glyph under window-relative coordinates X/Y in window W.
6684 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6685 strings. Return in *HPOS and *VPOS the row and column number of
6686 the glyph found. Return in *AREA the glyph area containing X.
6687 Value is a pointer to the glyph found or null if X/Y is not on
6688 text, or we can't tell because W's current matrix is not up to
6689 date. */
6690
6691 static struct glyph *
6692 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6693 struct window *w;
6694 int x, y;
6695 int *hpos, *vpos, *area;
6696 int buffer_only_p;
6697 {
6698 struct glyph *glyph, *end;
6699 struct glyph_row *row = NULL;
6700 int x0, i, left_area_width;
6701
6702 /* Find row containing Y. Give up if some row is not enabled. */
6703 for (i = 0; i < w->current_matrix->nrows; ++i)
6704 {
6705 row = MATRIX_ROW (w->current_matrix, i);
6706 if (!row->enabled_p)
6707 return NULL;
6708 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6709 break;
6710 }
6711
6712 *vpos = i;
6713 *hpos = 0;
6714
6715 /* Give up if Y is not in the window. */
6716 if (i == w->current_matrix->nrows)
6717 return NULL;
6718
6719 /* Get the glyph area containing X. */
6720 if (w->pseudo_window_p)
6721 {
6722 *area = TEXT_AREA;
6723 x0 = 0;
6724 }
6725 else
6726 {
6727 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6728 if (x < left_area_width)
6729 {
6730 *area = LEFT_MARGIN_AREA;
6731 x0 = 0;
6732 }
6733 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6734 {
6735 *area = TEXT_AREA;
6736 x0 = row->x + left_area_width;
6737 }
6738 else
6739 {
6740 *area = RIGHT_MARGIN_AREA;
6741 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6742 }
6743 }
6744
6745 /* Find glyph containing X. */
6746 glyph = row->glyphs[*area];
6747 end = glyph + row->used[*area];
6748 while (glyph < end)
6749 {
6750 if (x < x0 + glyph->pixel_width)
6751 {
6752 if (w->pseudo_window_p)
6753 break;
6754 else if (!buffer_only_p || BUFFERP (glyph->object))
6755 break;
6756 }
6757
6758 x0 += glyph->pixel_width;
6759 ++glyph;
6760 }
6761
6762 if (glyph == end)
6763 return NULL;
6764
6765 *hpos = glyph - row->glyphs[*area];
6766 return glyph;
6767 }
6768
6769
6770 /* Convert frame-relative x/y to coordinates relative to window W.
6771 Takes pseudo-windows into account. */
6772
6773 static void
6774 frame_to_window_pixel_xy (w, x, y)
6775 struct window *w;
6776 int *x, *y;
6777 {
6778 if (w->pseudo_window_p)
6779 {
6780 /* A pseudo-window is always full-width, and starts at the
6781 left edge of the frame, plus a frame border. */
6782 struct frame *f = XFRAME (w->frame);
6783 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6784 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6785 }
6786 else
6787 {
6788 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6789 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6790 }
6791 }
6792
6793
6794 /* Take proper action when mouse has moved to the mode or header line of
6795 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6796 mode line. X is relative to the start of the text display area of
6797 W, so the width of fringes and scroll bars must be subtracted
6798 to get a position relative to the start of the mode line. */
6799
6800 static void
6801 note_mode_line_highlight (w, x, mode_line_p)
6802 struct window *w;
6803 int x, mode_line_p;
6804 {
6805 struct frame *f = XFRAME (w->frame);
6806 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6807 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
6808 struct glyph_row *row;
6809
6810 if (mode_line_p)
6811 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6812 else
6813 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6814
6815 if (row->enabled_p)
6816 {
6817 struct glyph *glyph, *end;
6818 Lisp_Object help, map;
6819 int x0;
6820
6821 /* Find the glyph under X. */
6822 glyph = row->glyphs[TEXT_AREA];
6823 end = glyph + row->used[TEXT_AREA];
6824 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6825 + FRAME_X_LEFT_FRINGE_WIDTH (f));
6826
6827 while (glyph < end
6828 && x >= x0 + glyph->pixel_width)
6829 {
6830 x0 += glyph->pixel_width;
6831 ++glyph;
6832 }
6833
6834 if (glyph < end
6835 && STRINGP (glyph->object)
6836 && STRING_INTERVALS (glyph->object)
6837 && glyph->charpos >= 0
6838 && glyph->charpos < SCHARS (glyph->object))
6839 {
6840 /* If we're on a string with `help-echo' text property,
6841 arrange for the help to be displayed. This is done by
6842 setting the global variable help_echo to the help string. */
6843 help = Fget_text_property (make_number (glyph->charpos),
6844 Qhelp_echo, glyph->object);
6845 if (!NILP (help))
6846 {
6847 help_echo = help;
6848 XSETWINDOW (help_echo_window, w);
6849 help_echo_object = glyph->object;
6850 help_echo_pos = glyph->charpos;
6851 }
6852
6853 /* Change the mouse pointer according to what is under X/Y. */
6854 map = Fget_text_property (make_number (glyph->charpos),
6855 Qlocal_map, glyph->object);
6856 if (KEYMAPP (map))
6857 cursor = f->output_data.mac->nontext_cursor;
6858 else
6859 {
6860 map = Fget_text_property (make_number (glyph->charpos),
6861 Qkeymap, glyph->object);
6862 if (KEYMAPP (map))
6863 cursor = f->output_data.mac->nontext_cursor;
6864 }
6865 }
6866 }
6867
6868 #if 0 /* MAC_TODO: mouse cursor */
6869 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6870 #endif
6871 }
6872
6873
6874 /* Take proper action when the mouse has moved to position X, Y on
6875 frame F as regards highlighting characters that have mouse-face
6876 properties. Also de-highlighting chars where the mouse was before.
6877 X and Y can be negative or out of range. */
6878
6879 static void
6880 note_mouse_highlight (f, x, y)
6881 struct frame *f;
6882 int x, y;
6883 {
6884 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6885 int portion;
6886 Lisp_Object window;
6887 struct window *w;
6888 struct buffer *b;
6889
6890 #if 0
6891 /* When a menu is active, don't highlight because this looks odd. */
6892 if (popup_activated ())
6893 return;
6894 #endif
6895
6896 if (NILP (Vmouse_highlight)
6897 || !f->glyphs_initialized_p)
6898 return;
6899
6900 dpyinfo->mouse_face_mouse_x = x;
6901 dpyinfo->mouse_face_mouse_y = y;
6902 dpyinfo->mouse_face_mouse_frame = f;
6903
6904 if (dpyinfo->mouse_face_defer)
6905 return;
6906
6907 if (gc_in_progress)
6908 {
6909 dpyinfo->mouse_face_deferred_gc = 1;
6910 return;
6911 }
6912
6913 /* Which window is that in? */
6914 window = window_from_coordinates (f, x, y, &portion, 1);
6915
6916 /* If we were displaying active text in another window, clear that. */
6917 if (! EQ (window, dpyinfo->mouse_face_window))
6918 clear_mouse_face (dpyinfo);
6919
6920 /* Not on a window -> return. */
6921 if (!WINDOWP (window))
6922 return;
6923
6924 /* Reset help_echo. It will get recomputed below. */
6925 help_echo = Qnil;
6926
6927 /* Convert to window-relative pixel coordinates. */
6928 w = XWINDOW (window);
6929 frame_to_window_pixel_xy (w, &x, &y);
6930
6931 /* Handle tool-bar window differently since it doesn't display a
6932 buffer. */
6933 if (EQ (window, f->tool_bar_window))
6934 {
6935 note_tool_bar_highlight (f, x, y);
6936 return;
6937 }
6938
6939 /* Mouse is on the mode or header line? */
6940 if (portion == 1 || portion == 3)
6941 {
6942 note_mode_line_highlight (w, x, portion == 1);
6943 return;
6944 }
6945 #if 0 /* TODO: mouse cursor */
6946 if (portion == 2)
6947 cursor = f->output_data.x->horizontal_drag_cursor;
6948 else
6949 cursor = f->output_data.x->text_cursor;
6950 #endif
6951 /* Are we in a window whose display is up to date?
6952 And verify the buffer's text has not changed. */
6953 b = XBUFFER (w->buffer);
6954 if (/* Within text portion of the window. */
6955 portion == 0
6956 && EQ (w->window_end_valid, w->buffer)
6957 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6958 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
6959 {
6960 int hpos, vpos, pos, i, area;
6961 struct glyph *glyph;
6962 Lisp_Object object;
6963 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6964 Lisp_Object *overlay_vec = NULL;
6965 int len, noverlays;
6966 struct buffer *obuf;
6967 int obegv, ozv, same_region;
6968
6969 /* Find the glyph under X/Y. */
6970 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6971
6972 /* Clear mouse face if X/Y not over text. */
6973 if (glyph == NULL
6974 || area != TEXT_AREA
6975 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6976 {
6977 clear_mouse_face (dpyinfo);
6978 /* TODO: mouse cursor */
6979 goto set_cursor;
6980 }
6981
6982 pos = glyph->charpos;
6983 object = glyph->object;
6984 if (!STRINGP (object) && !BUFFERP (object))
6985 goto set_cursor;
6986
6987 /* If we get an out-of-range value, return now; avoid an error. */
6988 if (BUFFERP (object) && pos > BUF_Z (b))
6989 goto set_cursor;
6990
6991 /* Make the window's buffer temporarily current for
6992 overlays_at and compute_char_face. */
6993 obuf = current_buffer;
6994 current_buffer = b;
6995 obegv = BEGV;
6996 ozv = ZV;
6997 BEGV = BEG;
6998 ZV = Z;
6999
7000 /* Is this char mouse-active or does it have help-echo? */
7001 position = make_number (pos);
7002
7003 if (BUFFERP (object))
7004 {
7005 /* Put all the overlays we want in a vector in overlay_vec.
7006 Store the length in len. If there are more than 10, make
7007 enough space for all, and try again. */
7008 len = 10;
7009 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7010 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7011 if (noverlays > len)
7012 {
7013 len = noverlays;
7014 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7015 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7016 }
7017
7018 /* Sort overlays into increasing priority order. */
7019 noverlays = sort_overlays (overlay_vec, noverlays, w);
7020 }
7021 else
7022 noverlays = 0;
7023
7024 same_region = (EQ (window, dpyinfo->mouse_face_window)
7025 && vpos >= dpyinfo->mouse_face_beg_row
7026 && vpos <= dpyinfo->mouse_face_end_row
7027 && (vpos > dpyinfo->mouse_face_beg_row
7028 || hpos >= dpyinfo->mouse_face_beg_col)
7029 && (vpos < dpyinfo->mouse_face_end_row
7030 || hpos < dpyinfo->mouse_face_end_col
7031 || dpyinfo->mouse_face_past_end));
7032
7033 /* TODO: if (same_region)
7034 mouse cursor */
7035
7036 /* Check mouse-face highlighting. */
7037 if (! same_region
7038 /* If there exists an overlay with mouse-face overlapping
7039 the one we are currently highlighting, we have to
7040 check if we enter the overlapping overlay, and then
7041 highlight that. */
7042 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7043 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7044 {
7045 /* Find the highest priority overlay that has a mouse-face
7046 property. */
7047 overlay = Qnil;
7048 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7049 {
7050 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7051 if (!NILP (mouse_face))
7052 overlay = overlay_vec[i];
7053 }
7054
7055 /* If we're actually highlighting the same overlay as
7056 before, there's no need to do that again. */
7057 if (!NILP (overlay)
7058 && EQ (overlay, dpyinfo->mouse_face_overlay))
7059 goto check_help_echo;
7060
7061 dpyinfo->mouse_face_overlay = overlay;
7062
7063 /* Clear the display of the old active region, if any. */
7064 clear_mouse_face (dpyinfo);
7065 /* TODO: mouse cursor changes. */
7066
7067 /* If no overlay applies, get a text property. */
7068 if (NILP (overlay))
7069 mouse_face = Fget_text_property (position, Qmouse_face, object);
7070
7071 /* Handle the overlay case. */
7072 if (!NILP (overlay))
7073 {
7074 /* Find the range of text around this char that
7075 should be active. */
7076 Lisp_Object before, after;
7077 int ignore;
7078
7079 before = Foverlay_start (overlay);
7080 after = Foverlay_end (overlay);
7081 /* Record this as the current active region. */
7082 fast_find_position (w, XFASTINT (before),
7083 &dpyinfo->mouse_face_beg_col,
7084 &dpyinfo->mouse_face_beg_row,
7085 &dpyinfo->mouse_face_beg_x,
7086 &dpyinfo->mouse_face_beg_y, Qnil);
7087
7088 dpyinfo->mouse_face_past_end
7089 = !fast_find_position (w, XFASTINT (after),
7090 &dpyinfo->mouse_face_end_col,
7091 &dpyinfo->mouse_face_end_row,
7092 &dpyinfo->mouse_face_end_x,
7093 &dpyinfo->mouse_face_end_y, Qnil);
7094 dpyinfo->mouse_face_window = window;
7095
7096 dpyinfo->mouse_face_face_id
7097 = face_at_buffer_position (w, pos, 0, 0,
7098 &ignore, pos + 1,
7099 !dpyinfo->mouse_face_hidden);
7100
7101 /* Display it as active. */
7102 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7103 /* TODO: mouse cursor changes. */
7104 }
7105 /* Handle the text property case. */
7106 else if (! NILP (mouse_face) && BUFFERP (object))
7107 {
7108 /* Find the range of text around this char that
7109 should be active. */
7110 Lisp_Object before, after, beginning, end;
7111 int ignore;
7112
7113 beginning = Fmarker_position (w->start);
7114 end = make_number (BUF_Z (XBUFFER (object))
7115 - XFASTINT (w->window_end_pos));
7116 before
7117 = Fprevious_single_property_change (make_number (pos + 1),
7118 Qmouse_face,
7119 object, beginning);
7120 after
7121 = Fnext_single_property_change (position, Qmouse_face,
7122 object, end);
7123
7124 /* Record this as the current active region. */
7125 fast_find_position (w, XFASTINT (before),
7126 &dpyinfo->mouse_face_beg_col,
7127 &dpyinfo->mouse_face_beg_row,
7128 &dpyinfo->mouse_face_beg_x,
7129 &dpyinfo->mouse_face_beg_y, Qnil);
7130 dpyinfo->mouse_face_past_end
7131 = !fast_find_position (w, XFASTINT (after),
7132 &dpyinfo->mouse_face_end_col,
7133 &dpyinfo->mouse_face_end_row,
7134 &dpyinfo->mouse_face_end_x,
7135 &dpyinfo->mouse_face_end_y, Qnil);
7136 dpyinfo->mouse_face_window = window;
7137
7138 if (BUFFERP (object))
7139 dpyinfo->mouse_face_face_id
7140 = face_at_buffer_position (w, pos, 0, 0,
7141 &ignore, pos + 1,
7142 !dpyinfo->mouse_face_hidden);
7143
7144 /* Display it as active. */
7145 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7146 /* TODO: mouse cursor changes. */
7147 }
7148 else if (!NILP (mouse_face) && STRINGP (object))
7149 {
7150 Lisp_Object b, e;
7151 int ignore;
7152
7153 b = Fprevious_single_property_change (make_number (pos + 1),
7154 Qmouse_face,
7155 object, Qnil);
7156 e = Fnext_single_property_change (position, Qmouse_face,
7157 object, Qnil);
7158 if (NILP (b))
7159 b = make_number (0);
7160 if (NILP (e))
7161 e = make_number (SCHARS (object) - 1);
7162 fast_find_string_pos (w, XINT (b), object,
7163 &dpyinfo->mouse_face_beg_col,
7164 &dpyinfo->mouse_face_beg_row,
7165 &dpyinfo->mouse_face_beg_x,
7166 &dpyinfo->mouse_face_beg_y, 0);
7167 fast_find_string_pos (w, XINT (e), object,
7168 &dpyinfo->mouse_face_end_col,
7169 &dpyinfo->mouse_face_end_row,
7170 &dpyinfo->mouse_face_end_x,
7171 &dpyinfo->mouse_face_end_y, 1);
7172 dpyinfo->mouse_face_past_end = 0;
7173 dpyinfo->mouse_face_window = window;
7174 dpyinfo->mouse_face_face_id
7175 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7176 glyph->face_id, 1);
7177 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7178 /* TODO: mouse cursor changes. */
7179 }
7180 else if (STRINGP (object) && NILP (mouse_face))
7181 {
7182 /* A string which doesn't have mouse-face, but
7183 the text ``under'' it might have. */
7184 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7185 int start = MATRIX_ROW_START_CHARPOS (r);
7186
7187 pos = string_buffer_position (w, object, start);
7188 if (pos > 0)
7189 mouse_face = get_char_property_and_overlay (make_number (pos),
7190 Qmouse_face,
7191 w->buffer,
7192 &overlay);
7193 if (!NILP (mouse_face) && !NILP (overlay))
7194 {
7195 Lisp_Object before = Foverlay_start (overlay);
7196 Lisp_Object after = Foverlay_end (overlay);
7197 int ignore;
7198
7199 /* Note that we might not be able to find position
7200 BEFORE in the glyph matrix if the overlay is
7201 entirely covered by a `display' property. In
7202 this case, we overshoot. So let's stop in
7203 the glyph matrix before glyphs for OBJECT. */
7204 fast_find_position (w, XFASTINT (before),
7205 &dpyinfo->mouse_face_beg_col,
7206 &dpyinfo->mouse_face_beg_row,
7207 &dpyinfo->mouse_face_beg_x,
7208 &dpyinfo->mouse_face_beg_y,
7209 object);
7210
7211 dpyinfo->mouse_face_past_end
7212 = !fast_find_position (w, XFASTINT (after),
7213 &dpyinfo->mouse_face_end_col,
7214 &dpyinfo->mouse_face_end_row,
7215 &dpyinfo->mouse_face_end_x,
7216 &dpyinfo->mouse_face_end_y,
7217 Qnil);
7218 dpyinfo->mouse_face_window = window;
7219 dpyinfo->mouse_face_face_id
7220 = face_at_buffer_position (w, pos, 0, 0,
7221 &ignore, pos + 1,
7222 !dpyinfo->mouse_face_hidden);
7223
7224 /* Display it as active. */
7225 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7226 /* TODO: mouse cursor changes. */
7227 }
7228 }
7229 }
7230
7231 check_help_echo:
7232
7233 /* Look for a `help-echo' property. */
7234 {
7235 Lisp_Object help, overlay;
7236
7237 /* Check overlays first. */
7238 help = overlay = Qnil;
7239 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7240 {
7241 overlay = overlay_vec[i];
7242 help = Foverlay_get (overlay, Qhelp_echo);
7243 }
7244
7245 if (!NILP (help))
7246 {
7247 help_echo = help;
7248 help_echo_window = window;
7249 help_echo_object = overlay;
7250 help_echo_pos = pos;
7251 }
7252 else
7253 {
7254 Lisp_Object object = glyph->object;
7255 int charpos = glyph->charpos;
7256
7257 /* Try text properties. */
7258 if (STRINGP (object)
7259 && charpos >= 0
7260 && charpos < SCHARS (object))
7261 {
7262 help = Fget_text_property (make_number (charpos),
7263 Qhelp_echo, object);
7264 if (NILP (help))
7265 {
7266 /* If the string itself doesn't specify a help-echo,
7267 see if the buffer text ``under'' it does. */
7268 struct glyph_row *r
7269 = MATRIX_ROW (w->current_matrix, vpos);
7270 int start = MATRIX_ROW_START_CHARPOS (r);
7271 int pos = string_buffer_position (w, object, start);
7272 if (pos > 0)
7273 {
7274 help = Fget_char_property (make_number (pos),
7275 Qhelp_echo, w->buffer);
7276 if (!NILP (help))
7277 {
7278 charpos = pos;
7279 object = w->buffer;
7280 }
7281 }
7282 }
7283 }
7284 else if (BUFFERP (object)
7285 && charpos >= BEGV
7286 && charpos < ZV)
7287 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7288 object);
7289
7290 if (!NILP (help))
7291 {
7292 help_echo = help;
7293 help_echo_window = window;
7294 help_echo_object = object;
7295 help_echo_pos = charpos;
7296 }
7297 }
7298 }
7299
7300 BEGV = obegv;
7301 ZV = ozv;
7302 current_buffer = obuf;
7303 }
7304
7305 set_cursor:
7306 /* TODO: mouse cursor changes. */
7307 ;
7308 }
7309
7310 static void
7311 redo_mouse_highlight ()
7312 {
7313 if (!NILP (last_mouse_motion_frame)
7314 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7315 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7316 last_mouse_motion_position.h,
7317 last_mouse_motion_position.v);
7318 }
7319
7320
7321 \f
7322 /***********************************************************************
7323 Tool-bars
7324 ***********************************************************************/
7325
7326 static int x_tool_bar_item P_ ((struct frame *, int, int,
7327 struct glyph **, int *, int *, int *));
7328
7329 /* Tool-bar item index of the item on which a mouse button was pressed
7330 or -1. */
7331
7332 static int last_tool_bar_item;
7333
7334
7335 /* Get information about the tool-bar item at position X/Y on frame F.
7336 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7337 the current matrix of the tool-bar window of F, or NULL if not
7338 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7339 item in F->current_tool_bar_items. Value is
7340
7341 -1 if X/Y is not on a tool-bar item
7342 0 if X/Y is on the same item that was highlighted before.
7343 1 otherwise. */
7344
7345 static int
7346 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7347 struct frame *f;
7348 int x, y;
7349 struct glyph **glyph;
7350 int *hpos, *vpos, *prop_idx;
7351 {
7352 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7353 struct window *w = XWINDOW (f->tool_bar_window);
7354 int area;
7355
7356 /* Find the glyph under X/Y. */
7357 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7358 if (*glyph == NULL)
7359 return -1;
7360
7361 /* Get the start of this tool-bar item's properties in
7362 f->current_tool_bar_items. */
7363 if (!tool_bar_item_info (f, *glyph, prop_idx))
7364 return -1;
7365
7366 /* Is mouse on the highlighted item? */
7367 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7368 && *vpos >= dpyinfo->mouse_face_beg_row
7369 && *vpos <= dpyinfo->mouse_face_end_row
7370 && (*vpos > dpyinfo->mouse_face_beg_row
7371 || *hpos >= dpyinfo->mouse_face_beg_col)
7372 && (*vpos < dpyinfo->mouse_face_end_row
7373 || *hpos < dpyinfo->mouse_face_end_col
7374 || dpyinfo->mouse_face_past_end))
7375 return 0;
7376
7377 return 1;
7378 }
7379
7380
7381 /* Handle mouse button event on the tool-bar of frame F, at
7382 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7383 or ButtonRelase. */
7384
7385 static void
7386 x_handle_tool_bar_click (f, button_event)
7387 struct frame *f;
7388 EventRecord *button_event;
7389 {
7390 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7391 struct window *w = XWINDOW (f->tool_bar_window);
7392 int hpos, vpos, prop_idx;
7393 struct glyph *glyph;
7394 Lisp_Object enabled_p;
7395 int x = button_event->where.h;
7396 int y = button_event->where.v;
7397
7398 /* If not on the highlighted tool-bar item, return. */
7399 frame_to_window_pixel_xy (w, &x, &y);
7400 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7401 return;
7402
7403 /* If item is disabled, do nothing. */
7404 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7405 if (NILP (enabled_p))
7406 return;
7407
7408 if (button_event->what == mouseDown)
7409 {
7410 /* Show item in pressed state. */
7411 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7412 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7413 last_tool_bar_item = prop_idx;
7414 }
7415 else
7416 {
7417 Lisp_Object key, frame;
7418 struct input_event event;
7419
7420 /* Show item in released state. */
7421 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7422 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7423
7424 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7425
7426 XSETFRAME (frame, f);
7427 event.kind = TOOL_BAR_EVENT;
7428 event.frame_or_window = frame;
7429 event.arg = frame;
7430 kbd_buffer_store_event (&event);
7431
7432 event.kind = TOOL_BAR_EVENT;
7433 event.frame_or_window = frame;
7434 event.arg = key;
7435 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7436 button_event->modifiers);
7437 kbd_buffer_store_event (&event);
7438 last_tool_bar_item = -1;
7439 }
7440 }
7441
7442
7443 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7444 tool-bar window-relative coordinates X/Y. Called from
7445 note_mouse_highlight. */
7446
7447 static void
7448 note_tool_bar_highlight (f, x, y)
7449 struct frame *f;
7450 int x, y;
7451 {
7452 Lisp_Object window = f->tool_bar_window;
7453 struct window *w = XWINDOW (window);
7454 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7455 int hpos, vpos;
7456 struct glyph *glyph;
7457 struct glyph_row *row;
7458 int i;
7459 Lisp_Object enabled_p;
7460 int prop_idx;
7461 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7462 int mouse_down_p, rc;
7463
7464 /* Function note_mouse_highlight is called with negative x(y
7465 values when mouse moves outside of the frame. */
7466 if (x <= 0 || y <= 0)
7467 {
7468 clear_mouse_face (dpyinfo);
7469 return;
7470 }
7471
7472 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7473 if (rc < 0)
7474 {
7475 /* Not on tool-bar item. */
7476 clear_mouse_face (dpyinfo);
7477 return;
7478 }
7479 else if (rc == 0)
7480 /* On same tool-bar item as before. */
7481 goto set_help_echo;
7482
7483 clear_mouse_face (dpyinfo);
7484
7485 /* Mouse is down, but on different tool-bar item? */
7486 mouse_down_p = (dpyinfo->grabbed
7487 && f == last_mouse_frame
7488 && FRAME_LIVE_P (f));
7489 if (mouse_down_p
7490 && last_tool_bar_item != prop_idx)
7491 return;
7492
7493 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7494 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7495
7496 /* If tool-bar item is not enabled, don't highlight it. */
7497 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7498 if (!NILP (enabled_p))
7499 {
7500 /* Compute the x-position of the glyph. In front and past the
7501 image is a space. We include this is the highlighted area. */
7502 row = MATRIX_ROW (w->current_matrix, vpos);
7503 for (i = x = 0; i < hpos; ++i)
7504 x += row->glyphs[TEXT_AREA][i].pixel_width;
7505
7506 /* Record this as the current active region. */
7507 dpyinfo->mouse_face_beg_col = hpos;
7508 dpyinfo->mouse_face_beg_row = vpos;
7509 dpyinfo->mouse_face_beg_x = x;
7510 dpyinfo->mouse_face_beg_y = row->y;
7511 dpyinfo->mouse_face_past_end = 0;
7512
7513 dpyinfo->mouse_face_end_col = hpos + 1;
7514 dpyinfo->mouse_face_end_row = vpos;
7515 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7516 dpyinfo->mouse_face_end_y = row->y;
7517 dpyinfo->mouse_face_window = window;
7518 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7519
7520 /* Display it as active. */
7521 show_mouse_face (dpyinfo, draw);
7522 dpyinfo->mouse_face_image_state = draw;
7523 }
7524
7525 set_help_echo:
7526
7527 /* Set help_echo to a help string.to display for this tool-bar item.
7528 XTread_socket does the rest. */
7529 help_echo_object = help_echo_window = Qnil;
7530 help_echo_pos = -1;
7531 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7532 if (NILP (help_echo))
7533 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7534 }
7535
7536
7537 \f
7538 /* Find the glyph matrix position of buffer position CHARPOS in window
7539 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7540 current glyphs must be up to date. If CHARPOS is above window
7541 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7542 of last line in W. In the row containing CHARPOS, stop before glyphs
7543 having STOP as object. */
7544
7545 #if 0 /* This is a version of fast_find_position that's more correct
7546 in the presence of hscrolling, for example. I didn't install
7547 it right away because the problem fixed is minor, it failed
7548 in 20.x as well, and I think it's too risky to install
7549 so near the release of 21.1. 2001-09-25 gerd. */
7550
7551 static int
7552 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7553 struct window *w;
7554 int charpos;
7555 int *hpos, *vpos, *x, *y;
7556 Lisp_Object stop;
7557 {
7558 struct glyph_row *row, *first;
7559 struct glyph *glyph, *end;
7560 int i, past_end = 0;
7561
7562 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7563 row = row_containing_pos (w, charpos, first, NULL, 0);
7564 if (row == NULL)
7565 {
7566 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7567 {
7568 *x = *y = *hpos = *vpos = 0;
7569 return 0;
7570 }
7571 else
7572 {
7573 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7574 past_end = 1;
7575 }
7576 }
7577
7578 *x = row->x;
7579 *y = row->y;
7580 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7581
7582 glyph = row->glyphs[TEXT_AREA];
7583 end = glyph + row->used[TEXT_AREA];
7584
7585 /* Skip over glyphs not having an object at the start of the row.
7586 These are special glyphs like truncation marks on terminal
7587 frames. */
7588 if (row->displays_text_p)
7589 while (glyph < end
7590 && INTEGERP (glyph->object)
7591 && !EQ (stop, glyph->object)
7592 && glyph->charpos < 0)
7593 {
7594 *x += glyph->pixel_width;
7595 ++glyph;
7596 }
7597
7598 while (glyph < end
7599 && !INTEGERP (glyph->object)
7600 && !EQ (stop, glyph->object)
7601 && (!BUFFERP (glyph->object)
7602 || glyph->charpos < charpos))
7603 {
7604 *x += glyph->pixel_width;
7605 ++glyph;
7606 }
7607
7608 *hpos = glyph - row->glyphs[TEXT_AREA];
7609 return past_end;
7610 }
7611
7612 #else /* not 0 */
7613
7614 static int
7615 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7616 struct window *w;
7617 int pos;
7618 int *hpos, *vpos, *x, *y;
7619 Lisp_Object stop;
7620 {
7621 int i;
7622 int lastcol;
7623 int maybe_next_line_p = 0;
7624 int line_start_position;
7625 int yb = window_text_bottom_y (w);
7626 struct glyph_row *row, *best_row;
7627 int row_vpos, best_row_vpos;
7628 int current_x;
7629
7630 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7631 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7632
7633 while (row->y < yb)
7634 {
7635 if (row->used[TEXT_AREA])
7636 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7637 else
7638 line_start_position = 0;
7639
7640 if (line_start_position > pos)
7641 break;
7642 /* If the position sought is the end of the buffer,
7643 don't include the blank lines at the bottom of the window. */
7644 else if (line_start_position == pos
7645 && pos == BUF_ZV (XBUFFER (w->buffer)))
7646 {
7647 maybe_next_line_p = 1;
7648 break;
7649 }
7650 else if (line_start_position > 0)
7651 {
7652 best_row = row;
7653 best_row_vpos = row_vpos;
7654 }
7655
7656 if (row->y + row->height >= yb)
7657 break;
7658
7659 ++row;
7660 ++row_vpos;
7661 }
7662
7663 /* Find the right column within BEST_ROW. */
7664 lastcol = 0;
7665 current_x = best_row->x;
7666 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7667 {
7668 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7669 int charpos = glyph->charpos;
7670
7671 if (BUFFERP (glyph->object))
7672 {
7673 if (charpos == pos)
7674 {
7675 *hpos = i;
7676 *vpos = best_row_vpos;
7677 *x = current_x;
7678 *y = best_row->y;
7679 return 1;
7680 }
7681 else if (charpos > pos)
7682 break;
7683 }
7684 else if (EQ (glyph->object, stop))
7685 break;
7686
7687 if (charpos > 0)
7688 lastcol = i;
7689 current_x += glyph->pixel_width;
7690 }
7691
7692 /* If we're looking for the end of the buffer,
7693 and we didn't find it in the line we scanned,
7694 use the start of the following line. */
7695 if (maybe_next_line_p)
7696 {
7697 ++best_row;
7698 ++best_row_vpos;
7699 lastcol = 0;
7700 current_x = best_row->x;
7701 }
7702
7703 *vpos = best_row_vpos;
7704 *hpos = lastcol + 1;
7705 *x = current_x;
7706 *y = best_row->y;
7707 return 0;
7708 }
7709
7710 #endif /* not 0 */
7711
7712
7713 /* Find the position of the glyph for position POS in OBJECT in
7714 window W's current matrix, and return in *X/*Y the pixel
7715 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7716
7717 RIGHT_P non-zero means return the position of the right edge of the
7718 glyph, RIGHT_P zero means return the left edge position.
7719
7720 If no glyph for POS exists in the matrix, return the position of
7721 the glyph with the next smaller position that is in the matrix, if
7722 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7723 exists in the matrix, return the position of the glyph with the
7724 next larger position in OBJECT.
7725
7726 Value is non-zero if a glyph was found. */
7727
7728 static int
7729 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7730 struct window *w;
7731 int pos;
7732 Lisp_Object object;
7733 int *hpos, *vpos, *x, *y;
7734 int right_p;
7735 {
7736 int yb = window_text_bottom_y (w);
7737 struct glyph_row *r;
7738 struct glyph *best_glyph = NULL;
7739 struct glyph_row *best_row = NULL;
7740 int best_x = 0;
7741
7742 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7743 r->enabled_p && r->y < yb;
7744 ++r)
7745 {
7746 struct glyph *g = r->glyphs[TEXT_AREA];
7747 struct glyph *e = g + r->used[TEXT_AREA];
7748 int gx;
7749
7750 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7751 if (EQ (g->object, object))
7752 {
7753 if (g->charpos == pos)
7754 {
7755 best_glyph = g;
7756 best_x = gx;
7757 best_row = r;
7758 goto found;
7759 }
7760 else if (best_glyph == NULL
7761 || ((abs (g->charpos - pos)
7762 < abs (best_glyph->charpos - pos))
7763 && (right_p
7764 ? g->charpos < pos
7765 : g->charpos > pos)))
7766 {
7767 best_glyph = g;
7768 best_x = gx;
7769 best_row = r;
7770 }
7771 }
7772 }
7773
7774 found:
7775
7776 if (best_glyph)
7777 {
7778 *x = best_x;
7779 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7780
7781 if (right_p)
7782 {
7783 *x += best_glyph->pixel_width;
7784 ++*hpos;
7785 }
7786
7787 *y = best_row->y;
7788 *vpos = best_row - w->current_matrix->rows;
7789 }
7790
7791 return best_glyph != NULL;
7792 }
7793
7794
7795 /* Display the active region described by mouse_face_*
7796 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7797
7798 static void
7799 show_mouse_face (dpyinfo, draw)
7800 struct mac_display_info *dpyinfo;
7801 enum draw_glyphs_face draw;
7802 {
7803 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7804 struct frame *f = XFRAME (WINDOW_FRAME (w));
7805
7806 if (/* If window is in the process of being destroyed, don't bother
7807 to do anything. */
7808 w->current_matrix != NULL
7809 /* Don't update mouse highlight if hidden */
7810 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7811 /* Recognize when we are called to operate on rows that don't exist
7812 anymore. This can happen when a window is split. */
7813 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7814 {
7815 int phys_cursor_on_p = w->phys_cursor_on_p;
7816 struct glyph_row *row, *first, *last;
7817
7818 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7819 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7820
7821 for (row = first; row <= last && row->enabled_p; ++row)
7822 {
7823 int start_hpos, end_hpos, start_x;
7824
7825 /* For all but the first row, the highlight starts at column 0. */
7826 if (row == first)
7827 {
7828 start_hpos = dpyinfo->mouse_face_beg_col;
7829 start_x = dpyinfo->mouse_face_beg_x;
7830 }
7831 else
7832 {
7833 start_hpos = 0;
7834 start_x = 0;
7835 }
7836
7837 if (row == last)
7838 end_hpos = dpyinfo->mouse_face_end_col;
7839 else
7840 end_hpos = row->used[TEXT_AREA];
7841
7842 if (end_hpos > start_hpos)
7843 {
7844 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7845 start_hpos, end_hpos, draw, 0);
7846
7847 row->mouse_face_p
7848 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
7849 }
7850 }
7851
7852 /* When we've written over the cursor, arrange for it to
7853 be displayed again. */
7854 if (phys_cursor_on_p && !w->phys_cursor_on_p)
7855 x_display_cursor (w, 1,
7856 w->phys_cursor.hpos, w->phys_cursor.vpos,
7857 w->phys_cursor.x, w->phys_cursor.y);
7858 }
7859
7860 #if 0 /* MAC_TODO: mouse cursor */
7861 /* Change the mouse cursor. */
7862 if (draw == DRAW_NORMAL_TEXT)
7863 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7864 f->output_data.x->text_cursor);
7865 else if (draw == DRAW_MOUSE_FACE)
7866 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7867 f->output_data.x->cross_cursor);
7868 else
7869 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7870 f->output_data.x->nontext_cursor);
7871 #endif
7872 }
7873
7874 /* Clear out the mouse-highlighted active region.
7875 Redraw it un-highlighted first. */
7876
7877 static int
7878 clear_mouse_face (dpyinfo)
7879 struct mac_display_info *dpyinfo;
7880 {
7881 int cleared = 0;
7882
7883 if (! NILP (dpyinfo->mouse_face_window))
7884 {
7885 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7886 cleared = 1;
7887 }
7888
7889 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7890 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7891 dpyinfo->mouse_face_window = Qnil;
7892 dpyinfo->mouse_face_overlay = Qnil;
7893 return cleared;
7894 }
7895
7896
7897 /* Clear any mouse-face on window W. This function is part of the
7898 redisplay interface, and is called from try_window_id and similar
7899 functions to ensure the mouse-highlight is off. */
7900
7901 static void
7902 x_clear_mouse_face (w)
7903 struct window *w;
7904 {
7905 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
7906 Lisp_Object window;
7907
7908 BLOCK_INPUT;
7909 XSETWINDOW (window, w);
7910 if (EQ (window, dpyinfo->mouse_face_window))
7911 clear_mouse_face (dpyinfo);
7912 UNBLOCK_INPUT;
7913 }
7914
7915
7916 /* Just discard the mouse face information for frame F, if any.
7917 This is used when the size of F is changed. */
7918
7919 void
7920 cancel_mouse_face (f)
7921 FRAME_PTR f;
7922 {
7923 Lisp_Object window;
7924 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7925
7926 window = dpyinfo->mouse_face_window;
7927 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7928 {
7929 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7930 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7931 dpyinfo->mouse_face_window = Qnil;
7932 }
7933 }
7934 \f
7935 static struct scroll_bar *x_window_to_scroll_bar ();
7936 static void x_scroll_bar_report_motion ();
7937 static void x_check_fullscreen P_ ((struct frame *));
7938 static void x_check_fullscreen_move P_ ((struct frame *));
7939 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
7940
7941
7942 /* Try to determine frame pixel position and size of the glyph under
7943 frame pixel coordinates X/Y on frame F . Return the position and
7944 size in *RECT. Value is non-zero if we could compute these
7945 values. */
7946
7947 static int
7948 glyph_rect (f, x, y, rect)
7949 struct frame *f;
7950 int x, y;
7951 Rect *rect;
7952 {
7953 Lisp_Object window;
7954 int part;
7955
7956 window = window_from_coordinates (f, x, y, &part, 0);
7957 if (!NILP (window))
7958 {
7959 struct window *w = XWINDOW (window);
7960 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7961 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7962
7963 frame_to_window_pixel_xy (w, &x, &y);
7964
7965 for (; r < end && r->enabled_p; ++r)
7966 if (r->y <= y && r->y + r->height > y)
7967 {
7968 /* Found the row at y. */
7969 struct glyph *g = r->glyphs[TEXT_AREA];
7970 struct glyph *end = g + r->used[TEXT_AREA];
7971 int gx;
7972
7973 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7974 rect->bottom = rect->top + r->height;
7975
7976 if (x < r->x)
7977 {
7978 /* x is to the left of the first glyph in the row. */
7979 rect->left = XINT (w->left);
7980 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
7981 return 1;
7982 }
7983
7984 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
7985 if (gx <= x && gx + g->pixel_width > x)
7986 {
7987 /* x is on a glyph. */
7988 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7989 rect->right = rect->left + g->pixel_width;
7990 return 1;
7991 }
7992
7993 /* x is to the right of the last glyph in the row. */
7994 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7995 rect->right = XINT (w->left) + XINT (w->width);
7996 return 1;
7997 }
7998 }
7999
8000 /* The y is not on any row. */
8001 return 0;
8002 }
8003
8004 /* Record the position of the mouse in last_mouse_glyph. */
8005 static void
8006 remember_mouse_glyph (f1, gx, gy)
8007 struct frame * f1;
8008 int gx, gy;
8009 {
8010 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8011 {
8012 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8013 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8014
8015 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8016 round down even for negative values. */
8017 if (gx < 0)
8018 gx -= width - 1;
8019 if (gy < 0)
8020 gy -= height - 1;
8021 #if 0
8022 /* This was the original code from XTmouse_position, but it seems
8023 to give the position of the glyph diagonally next to the one
8024 the mouse is over. */
8025 gx = (gx + width - 1) / width * width;
8026 gy = (gy + height - 1) / height * height;
8027 #else
8028 gx = gx / width * width;
8029 gy = gy / height * height;
8030 #endif
8031
8032 last_mouse_glyph.left = gx;
8033 last_mouse_glyph.top = gy;
8034 last_mouse_glyph.right = gx + width;
8035 last_mouse_glyph.bottom = gy + height;
8036 }
8037 }
8038
8039 /* Return the current position of the mouse.
8040 *fp should be a frame which indicates which display to ask about.
8041
8042 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8043 and *part to the frame, window, and scroll bar part that the mouse
8044 is over. Set *x and *y to the portion and whole of the mouse's
8045 position on the scroll bar.
8046
8047 If the mouse movement started elsewhere, set *fp to the frame the
8048 mouse is on, *bar_window to nil, and *x and *y to the character cell
8049 the mouse is over.
8050
8051 Set *time to the server time-stamp for the time at which the mouse
8052 was at this position.
8053
8054 Don't store anything if we don't have a valid set of values to report.
8055
8056 This clears the mouse_moved flag, so we can wait for the next mouse
8057 movement. */
8058
8059 static void
8060 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8061 FRAME_PTR *fp;
8062 int insist;
8063 Lisp_Object *bar_window;
8064 enum scroll_bar_part *part;
8065 Lisp_Object *x, *y;
8066 unsigned long *time;
8067 {
8068 Point mouse_pos;
8069 int ignore1, ignore2;
8070 WindowPtr wp = FrontWindow ();
8071 struct frame *f;
8072 Lisp_Object frame, tail;
8073
8074 if (is_emacs_window(wp))
8075 f = ((mac_output *) GetWRefCon (wp))->mFP;
8076
8077 BLOCK_INPUT;
8078
8079 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8080 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8081 else
8082 {
8083 /* Clear the mouse-moved flag for every frame on this display. */
8084 FOR_EACH_FRAME (tail, frame)
8085 XFRAME (frame)->mouse_moved = 0;
8086
8087 last_mouse_scroll_bar = Qnil;
8088
8089 #if TARGET_API_MAC_CARBON
8090 SetPort (GetWindowPort (wp));
8091 #else
8092 SetPort (wp);
8093 #endif
8094
8095 GetMouse (&mouse_pos);
8096
8097 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8098 &last_mouse_glyph, insist);
8099
8100 *bar_window = Qnil;
8101 *part = scroll_bar_handle;
8102 *fp = f;
8103 XSETINT (*x, mouse_pos.h);
8104 XSETINT (*y, mouse_pos.v);
8105 *time = last_mouse_movement_time;
8106 }
8107
8108 UNBLOCK_INPUT;
8109 }
8110
8111 \f
8112 /************************************************************************
8113 Scroll bars, general
8114 ************************************************************************/
8115
8116 /* Create a scroll bar and return the scroll bar vector for it. W is
8117 the Emacs window on which to create the scroll bar. TOP, LEFT,
8118 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8119 scroll bar. */
8120
8121 static struct scroll_bar *
8122 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8123 struct window *w;
8124 int top, left, width, height, disp_top, disp_height;
8125 {
8126 struct frame *f = XFRAME (w->frame);
8127 struct scroll_bar *bar
8128 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8129 Rect r;
8130 ControlHandle ch;
8131
8132 BLOCK_INPUT;
8133
8134 r.left = left;
8135 r.top = disp_top;
8136 r.right = left + width;
8137 r.bottom = disp_top + disp_height;
8138
8139 #ifdef TARGET_API_MAC_CARBON
8140 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8141 kControlScrollBarProc, 0L);
8142 #else
8143 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8144 0L);
8145 #endif
8146 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8147 SetControlReference (ch, (long) bar);
8148
8149 XSETWINDOW (bar->window, w);
8150 XSETINT (bar->top, top);
8151 XSETINT (bar->left, left);
8152 XSETINT (bar->width, width);
8153 XSETINT (bar->height, height);
8154 XSETINT (bar->start, 0);
8155 XSETINT (bar->end, 0);
8156 bar->dragging = Qnil;
8157
8158 /* Add bar to its frame's list of scroll bars. */
8159 bar->next = FRAME_SCROLL_BARS (f);
8160 bar->prev = Qnil;
8161 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8162 if (!NILP (bar->next))
8163 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8164
8165 UNBLOCK_INPUT;
8166 return bar;
8167 }
8168
8169
8170 /* Draw BAR's handle in the proper position.
8171
8172 If the handle is already drawn from START to END, don't bother
8173 redrawing it, unless REBUILD is non-zero; in that case, always
8174 redraw it. (REBUILD is handy for drawing the handle after expose
8175 events.)
8176
8177 Normally, we want to constrain the start and end of the handle to
8178 fit inside its rectangle, but if the user is dragging the scroll
8179 bar handle, we want to let them drag it down all the way, so that
8180 the bar's top is as far down as it goes; otherwise, there's no way
8181 to move to the very end of the buffer. */
8182
8183 static void
8184 x_scroll_bar_set_handle (bar, start, end, rebuild)
8185 struct scroll_bar *bar;
8186 int start, end;
8187 int rebuild;
8188 {
8189 int dragging = ! NILP (bar->dragging);
8190 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8191 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8192 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8193 int length = end - start;
8194
8195 /* If the display is already accurate, do nothing. */
8196 if (! rebuild
8197 && start == XINT (bar->start)
8198 && end == XINT (bar->end))
8199 return;
8200
8201 BLOCK_INPUT;
8202
8203 /* Make sure the values are reasonable, and try to preserve the
8204 distance between start and end. */
8205 if (start < 0)
8206 start = 0;
8207 else if (start > top_range)
8208 start = top_range;
8209 end = start + length;
8210
8211 if (end < start)
8212 end = start;
8213 else if (end > top_range && ! dragging)
8214 end = top_range;
8215
8216 /* Store the adjusted setting in the scroll bar. */
8217 XSETINT (bar->start, start);
8218 XSETINT (bar->end, end);
8219
8220 /* Clip the end position, just for display. */
8221 if (end > top_range)
8222 end = top_range;
8223
8224 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8225 top positions, to make sure the handle is always at least that
8226 many pixels tall. */
8227 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8228
8229 SetControlMinimum (ch, 0);
8230 /* Don't inadvertently activate deactivated scroll bars */
8231 if (GetControlMaximum (ch) != -1)
8232 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8233 - (end - start));
8234 SetControlValue (ch, start);
8235 #if TARGET_API_MAC_CARBON
8236 SetControlViewSize (ch, end - start);
8237 #endif
8238
8239 UNBLOCK_INPUT;
8240 }
8241
8242
8243 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8244 nil. */
8245
8246 static void
8247 x_scroll_bar_remove (bar)
8248 struct scroll_bar *bar;
8249 {
8250 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8251
8252 BLOCK_INPUT;
8253
8254 /* Destroy the Mac scroll bar control */
8255 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8256
8257 /* Disassociate this scroll bar from its window. */
8258 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8259
8260 UNBLOCK_INPUT;
8261 }
8262
8263 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8264 that we are displaying PORTION characters out of a total of WHOLE
8265 characters, starting at POSITION. If WINDOW has no scroll bar,
8266 create one. */
8267 static void
8268 XTset_vertical_scroll_bar (w, portion, whole, position)
8269 struct window *w;
8270 int portion, whole, position;
8271 {
8272 struct frame *f = XFRAME (w->frame);
8273 struct scroll_bar *bar;
8274 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8275 int window_x, window_y, window_width, window_height;
8276
8277 /* Get window dimensions. */
8278 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8279 top = window_y;
8280 #ifdef MAC_OSX
8281 width = 16;
8282 #else
8283 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8284 #endif
8285 height = window_height;
8286
8287 /* Compute the left edge of the scroll bar area. */
8288 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8289 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8290 else
8291 left = XFASTINT (w->left);
8292 left *= CANON_X_UNIT (f);
8293 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8294
8295 /* Compute the width of the scroll bar which might be less than
8296 the width of the area reserved for the scroll bar. */
8297 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8298 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8299 else
8300 sb_width = width;
8301
8302 /* Compute the left edge of the scroll bar. */
8303 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8304 sb_left = left + width - sb_width - (width - sb_width) / 2;
8305 else
8306 sb_left = left + (width - sb_width) / 2;
8307
8308 /* Adjustments according to Inside Macintosh to make it look nice */
8309 disp_top = top;
8310 disp_height = height;
8311 if (disp_top == 0)
8312 {
8313 disp_top = -1;
8314 disp_height++;
8315 }
8316 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8317 {
8318 disp_top++;
8319 disp_height--;
8320 }
8321
8322 if (sb_left + sb_width == PIXEL_WIDTH (f))
8323 sb_left++;
8324
8325 /* Does the scroll bar exist yet? */
8326 if (NILP (w->vertical_scroll_bar))
8327 {
8328 BLOCK_INPUT;
8329 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8330 left, top, width, height, 0);
8331 UNBLOCK_INPUT;
8332 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8333 disp_height);
8334 XSETVECTOR (w->vertical_scroll_bar, bar);
8335 }
8336 else
8337 {
8338 /* It may just need to be moved and resized. */
8339 ControlHandle ch;
8340
8341 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8342 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8343
8344 BLOCK_INPUT;
8345
8346 /* If already correctly positioned, do nothing. */
8347 if (XINT (bar->left) == sb_left
8348 && XINT (bar->top) == top
8349 && XINT (bar->width) == sb_width
8350 && XINT (bar->height) == height)
8351 Draw1Control (ch);
8352 else
8353 {
8354 /* Clear areas not covered by the scroll bar because it's not as
8355 wide as the area reserved for it . This makes sure a
8356 previous mode line display is cleared after C-x 2 C-x 1, for
8357 example. */
8358 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8359 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8360 left, top, area_width, height, 0);
8361
8362 #if 0
8363 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8364 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8365 sb_left - 1, top, 1, height, 0);
8366 #endif
8367
8368 HideControl (ch);
8369 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8370 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8371 disp_height);
8372 ShowControl (ch);
8373
8374 /* Remember new settings. */
8375 XSETINT (bar->left, sb_left);
8376 XSETINT (bar->top, top);
8377 XSETINT (bar->width, sb_width);
8378 XSETINT (bar->height, height);
8379 }
8380
8381 UNBLOCK_INPUT;
8382 }
8383
8384 /* Set the scroll bar's current state, unless we're currently being
8385 dragged. */
8386 if (NILP (bar->dragging))
8387 {
8388 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8389
8390 if (whole == 0)
8391 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8392 else
8393 {
8394 int start = ((double) position * top_range) / whole;
8395 int end = ((double) (position + portion) * top_range) / whole;
8396 x_scroll_bar_set_handle (bar, start, end, 0);
8397 }
8398 }
8399 }
8400
8401
8402 /* The following three hooks are used when we're doing a thorough
8403 redisplay of the frame. We don't explicitly know which scroll bars
8404 are going to be deleted, because keeping track of when windows go
8405 away is a real pain - "Can you say set-window-configuration, boys
8406 and girls?" Instead, we just assert at the beginning of redisplay
8407 that *all* scroll bars are to be removed, and then save a scroll bar
8408 from the fiery pit when we actually redisplay its window. */
8409
8410 /* Arrange for all scroll bars on FRAME to be removed at the next call
8411 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8412 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8413
8414 static void
8415 XTcondemn_scroll_bars (frame)
8416 FRAME_PTR frame;
8417 {
8418 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8419 while (! NILP (FRAME_SCROLL_BARS (frame)))
8420 {
8421 Lisp_Object bar;
8422 bar = FRAME_SCROLL_BARS (frame);
8423 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8424 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8425 XSCROLL_BAR (bar)->prev = Qnil;
8426 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8427 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8428 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8429 }
8430 }
8431
8432
8433 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8434 Note that WINDOW isn't necessarily condemned at all. */
8435
8436 static void
8437 XTredeem_scroll_bar (window)
8438 struct window *window;
8439 {
8440 struct scroll_bar *bar;
8441
8442 /* We can't redeem this window's scroll bar if it doesn't have one. */
8443 if (NILP (window->vertical_scroll_bar))
8444 abort ();
8445
8446 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8447
8448 /* Unlink it from the condemned list. */
8449 {
8450 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8451
8452 if (NILP (bar->prev))
8453 {
8454 /* If the prev pointer is nil, it must be the first in one of
8455 the lists. */
8456 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8457 /* It's not condemned. Everything's fine. */
8458 return;
8459 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8460 window->vertical_scroll_bar))
8461 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8462 else
8463 /* If its prev pointer is nil, it must be at the front of
8464 one or the other! */
8465 abort ();
8466 }
8467 else
8468 XSCROLL_BAR (bar->prev)->next = bar->next;
8469
8470 if (! NILP (bar->next))
8471 XSCROLL_BAR (bar->next)->prev = bar->prev;
8472
8473 bar->next = FRAME_SCROLL_BARS (f);
8474 bar->prev = Qnil;
8475 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8476 if (! NILP (bar->next))
8477 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8478 }
8479 }
8480
8481 /* Remove all scroll bars on FRAME that haven't been saved since the
8482 last call to `*condemn_scroll_bars_hook'. */
8483
8484 static void
8485 XTjudge_scroll_bars (f)
8486 FRAME_PTR f;
8487 {
8488 Lisp_Object bar, next;
8489
8490 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8491
8492 /* Clear out the condemned list now so we won't try to process any
8493 more events on the hapless scroll bars. */
8494 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8495
8496 for (; ! NILP (bar); bar = next)
8497 {
8498 struct scroll_bar *b = XSCROLL_BAR (bar);
8499
8500 x_scroll_bar_remove (b);
8501
8502 next = b->next;
8503 b->next = b->prev = Qnil;
8504 }
8505
8506 /* Now there should be no references to the condemned scroll bars,
8507 and they should get garbage-collected. */
8508 }
8509
8510
8511 static void
8512 activate_scroll_bars (frame)
8513 FRAME_PTR frame;
8514 {
8515 Lisp_Object bar;
8516 ControlHandle ch;
8517
8518 bar = FRAME_SCROLL_BARS (frame);
8519 while (! NILP (bar))
8520 {
8521 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8522 #ifdef TARGET_API_MAC_CARBON
8523 ActivateControl (ch);
8524 #else
8525 SetControlMaximum (ch,
8526 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8527 XINT (XSCROLL_BAR (bar)
8528 ->height)) - 1);
8529 #endif
8530 bar = XSCROLL_BAR (bar)->next;
8531 }
8532 }
8533
8534
8535 static void
8536 deactivate_scroll_bars (frame)
8537 FRAME_PTR frame;
8538 {
8539 Lisp_Object bar;
8540 ControlHandle ch;
8541
8542 bar = FRAME_SCROLL_BARS (frame);
8543 while (! NILP (bar))
8544 {
8545 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8546 #ifdef TARGET_API_MAC_CARBON
8547 DeactivateControl (ch);
8548 #else
8549 SetControlMaximum (ch, XINT (-1));
8550 #endif
8551 bar = XSCROLL_BAR (bar)->next;
8552 }
8553 }
8554
8555 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8556 is set to something other than NO_EVENT, it is enqueued.
8557
8558 This may be called from a signal handler, so we have to ignore GC
8559 mark bits. */
8560
8561 static void
8562 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8563 struct scroll_bar *bar;
8564 int part_code;
8565 EventRecord *er;
8566 struct input_event *bufp;
8567 {
8568 if (! GC_WINDOWP (bar->window))
8569 abort ();
8570
8571 bufp->kind = SCROLL_BAR_CLICK_EVENT;
8572 bufp->frame_or_window = bar->window;
8573 bufp->arg = Qnil;
8574
8575 bar->dragging = Qnil;
8576
8577 switch (part_code)
8578 {
8579 case kControlUpButtonPart:
8580 bufp->part = scroll_bar_up_arrow;
8581 break;
8582 case kControlDownButtonPart:
8583 bufp->part = scroll_bar_down_arrow;
8584 break;
8585 case kControlPageUpPart:
8586 bufp->part = scroll_bar_above_handle;
8587 break;
8588 case kControlPageDownPart:
8589 bufp->part = scroll_bar_below_handle;
8590 break;
8591 #ifdef TARGET_API_MAC_CARBON
8592 default:
8593 #else
8594 case kControlIndicatorPart:
8595 #endif
8596 if (er->what == mouseDown)
8597 bar->dragging = make_number (0);
8598 XSETVECTOR (last_mouse_scroll_bar, bar);
8599 bufp->part = scroll_bar_handle;
8600 break;
8601 }
8602 }
8603
8604
8605 /* Handle some mouse motion while someone is dragging the scroll bar.
8606
8607 This may be called from a signal handler, so we have to ignore GC
8608 mark bits. */
8609
8610 static void
8611 x_scroll_bar_note_movement (bar, y_pos, t)
8612 struct scroll_bar *bar;
8613 int y_pos;
8614 Time t;
8615 {
8616 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8617
8618 last_mouse_movement_time = t;
8619
8620 f->mouse_moved = 1;
8621 XSETVECTOR (last_mouse_scroll_bar, bar);
8622
8623 /* If we're dragging the bar, display it. */
8624 if (! GC_NILP (bar->dragging))
8625 {
8626 /* Where should the handle be now? */
8627 int new_start = y_pos - 24;
8628
8629 if (new_start != XINT (bar->start))
8630 {
8631 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8632
8633 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8634 }
8635 }
8636 }
8637
8638
8639 /* Return information to the user about the current position of the
8640 mouse on the scroll bar. */
8641
8642 static void
8643 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8644 FRAME_PTR *fp;
8645 Lisp_Object *bar_window;
8646 enum scroll_bar_part *part;
8647 Lisp_Object *x, *y;
8648 unsigned long *time;
8649 {
8650 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8651 WindowPtr wp = FrontWindow ();
8652 Point mouse_pos;
8653 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8654 int win_y, top_range;
8655
8656 #if TARGET_API_MAC_CARBON
8657 SetPort (GetWindowPort (wp));
8658 #else
8659 SetPort (wp);
8660 #endif
8661
8662 GetMouse (&mouse_pos);
8663
8664 win_y = mouse_pos.v - XINT (bar->top);
8665 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8666
8667 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8668
8669 win_y -= 24;
8670
8671 if (! NILP (bar->dragging))
8672 win_y -= XINT (bar->dragging);
8673
8674 if (win_y < 0)
8675 win_y = 0;
8676 if (win_y > top_range)
8677 win_y = top_range;
8678
8679 *fp = f;
8680 *bar_window = bar->window;
8681
8682 if (! NILP (bar->dragging))
8683 *part = scroll_bar_handle;
8684 else if (win_y < XINT (bar->start))
8685 *part = scroll_bar_above_handle;
8686 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8687 *part = scroll_bar_handle;
8688 else
8689 *part = scroll_bar_below_handle;
8690
8691 XSETINT (*x, win_y);
8692 XSETINT (*y, top_range);
8693
8694 f->mouse_moved = 0;
8695 last_mouse_scroll_bar = Qnil;
8696
8697 *time = last_mouse_movement_time;
8698 }
8699 \f
8700 /***********************************************************************
8701 Text Cursor
8702 ***********************************************************************/
8703
8704 /* Notice if the text cursor of window W has been overwritten by a
8705 drawing operation that outputs glyphs starting at START_X and
8706 ending at END_X in the line given by output_cursor.vpos.
8707 Coordinates are area-relative. END_X < 0 means all the rest
8708 of the line after START_X has been written. */
8709
8710 static void
8711 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
8712 struct window *w;
8713 enum glyph_row_area area;
8714 int x0, x1, y0, y1;
8715 {
8716 if (area == TEXT_AREA
8717 && w->phys_cursor_on_p
8718 && y0 <= w->phys_cursor.y
8719 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8720 && x0 <= w->phys_cursor.x
8721 && (x1 < 0 || x1 > w->phys_cursor.x))
8722 w->phys_cursor_on_p = 0;
8723 }
8724
8725
8726 /* Set clipping for output in glyph row ROW. W is the window in which
8727 we operate. GC is the graphics context to set clipping in.
8728 WHOLE_LINE_P non-zero means include the areas used for truncation
8729 mark display and alike in the clipping rectangle.
8730
8731 ROW may be a text row or, e.g., a mode line. Text rows must be
8732 clipped to the interior of the window dedicated to text display,
8733 mode lines must be clipped to the whole window. */
8734
8735 static void
8736 x_clip_to_row (w, row, gc, whole_line_p)
8737 struct window *w;
8738 struct glyph_row *row;
8739 GC gc;
8740 int whole_line_p;
8741 {
8742 struct frame *f = XFRAME (WINDOW_FRAME (w));
8743 Rect clip_rect;
8744 int window_x, window_y, window_width, window_height;
8745
8746 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8747
8748 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8749 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8750 clip_rect.top = max (clip_rect.top, window_y);
8751 clip_rect.right = clip_rect.left + window_width;
8752 clip_rect.bottom = clip_rect.top + row->visible_height;
8753
8754 /* If clipping to the whole line, including trunc marks, extend
8755 the rectangle to the left and increase its width. */
8756 if (whole_line_p)
8757 {
8758 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8759 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
8760 }
8761
8762 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8763 }
8764
8765
8766 /* Draw a hollow box cursor on window W in glyph row ROW. */
8767
8768 static void
8769 x_draw_hollow_cursor (w, row)
8770 struct window *w;
8771 struct glyph_row *row;
8772 {
8773 struct frame *f = XFRAME (WINDOW_FRAME (w));
8774 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8775 Display *dpy = FRAME_MAC_DISPLAY (f);
8776 int x, y, wd, h;
8777 XGCValues xgcv;
8778 struct glyph *cursor_glyph;
8779 GC gc;
8780
8781 /* Compute frame-relative coordinates from window-relative
8782 coordinates. */
8783 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8784 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8785 + row->ascent - w->phys_cursor_ascent);
8786 h = row->height - 1;
8787
8788 /* Get the glyph the cursor is on. If we can't tell because
8789 the current matrix is invalid or such, give up. */
8790 cursor_glyph = get_phys_cursor_glyph (w);
8791 if (cursor_glyph == NULL)
8792 return;
8793
8794 /* Compute the width of the rectangle to draw. If on a stretch
8795 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8796 rectangle as wide as the glyph, but use a canonical character
8797 width instead. */
8798 wd = cursor_glyph->pixel_width - 1;
8799 if (cursor_glyph->type == STRETCH_GLYPH
8800 && !x_stretch_cursor_p)
8801 wd = min (CANON_X_UNIT (f), wd);
8802
8803 /* The foreground of cursor_gc is typically the same as the normal
8804 background color, which can cause the cursor box to be invisible. */
8805 xgcv.foreground = f->output_data.mac->cursor_pixel;
8806 if (dpyinfo->scratch_cursor_gc)
8807 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8808 else
8809 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8810 GCForeground, &xgcv);
8811 gc = dpyinfo->scratch_cursor_gc;
8812
8813 /* Set clipping, draw the rectangle, and reset clipping again. */
8814 x_clip_to_row (w, row, gc, 0);
8815 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
8816 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8817 }
8818
8819
8820 /* Draw a bar cursor on window W in glyph row ROW.
8821
8822 Implementation note: One would like to draw a bar cursor with an
8823 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8824 Unfortunately, I didn't find a font yet that has this property set.
8825 --gerd. */
8826
8827 static void
8828 x_draw_bar_cursor (w, row, width)
8829 struct window *w;
8830 struct glyph_row *row;
8831 int width;
8832 {
8833 /* If cursor hpos is out of bounds, don't draw garbage. This can
8834 happen in mini-buffer windows when switching between echo area
8835 glyphs and mini-buffer. */
8836 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8837 {
8838 struct frame *f = XFRAME (w->frame);
8839 struct glyph *cursor_glyph;
8840 GC gc;
8841 int x;
8842 unsigned long mask;
8843 XGCValues xgcv;
8844 Display *dpy;
8845 Window window;
8846
8847 cursor_glyph = get_phys_cursor_glyph (w);
8848 if (cursor_glyph == NULL)
8849 return;
8850
8851 xgcv.background = f->output_data.mac->cursor_pixel;
8852 xgcv.foreground = f->output_data.mac->cursor_pixel;
8853 mask = GCForeground | GCBackground;
8854 dpy = FRAME_MAC_DISPLAY (f);
8855 window = FRAME_MAC_WINDOW (f);
8856 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
8857
8858 if (gc)
8859 XChangeGC (dpy, gc, mask, &xgcv);
8860 else
8861 {
8862 gc = XCreateGC (dpy, window, mask, &xgcv);
8863 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
8864 }
8865
8866 if (width < 0)
8867 width = FRAME_CURSOR_WIDTH (f);
8868
8869 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8870 x_clip_to_row (w, row, gc, 0);
8871 XFillRectangle (dpy, window, gc,
8872 x,
8873 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
8874 min (cursor_glyph->pixel_width, width),
8875 row->height);
8876 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8877 }
8878 }
8879
8880
8881 /* Clear the cursor of window W to background color, and mark the
8882 cursor as not shown. This is used when the text where the cursor
8883 is is about to be rewritten. */
8884
8885 static void
8886 x_clear_cursor (w)
8887 struct window *w;
8888 {
8889 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
8890 x_update_window_cursor (w, 0);
8891 }
8892
8893
8894 /* Draw the cursor glyph of window W in glyph row ROW. See the
8895 comment of x_draw_glyphs for the meaning of HL. */
8896
8897 static void
8898 x_draw_phys_cursor_glyph (w, row, hl)
8899 struct window *w;
8900 struct glyph_row *row;
8901 enum draw_glyphs_face hl;
8902 {
8903 /* If cursor hpos is out of bounds, don't draw garbage. This can
8904 happen in mini-buffer windows when switching between echo area
8905 glyphs and mini-buffer. */
8906 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8907 {
8908 int on_p = w->phys_cursor_on_p;
8909 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
8910 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
8911 hl, 0);
8912 w->phys_cursor_on_p = on_p;
8913
8914 /* When we erase the cursor, and ROW is overlapped by other
8915 rows, make sure that these overlapping parts of other rows
8916 are redrawn. */
8917 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
8918 {
8919 if (row > w->current_matrix->rows
8920 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
8921 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
8922
8923 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
8924 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
8925 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
8926 }
8927 }
8928 }
8929
8930
8931 /* Erase the image of a cursor of window W from the screen. */
8932
8933 static void
8934 x_erase_phys_cursor (w)
8935 struct window *w;
8936 {
8937 struct frame *f = XFRAME (w->frame);
8938 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8939 int hpos = w->phys_cursor.hpos;
8940 int vpos = w->phys_cursor.vpos;
8941 int mouse_face_here_p = 0;
8942 struct glyph_matrix *active_glyphs = w->current_matrix;
8943 struct glyph_row *cursor_row;
8944 struct glyph *cursor_glyph;
8945 enum draw_glyphs_face hl;
8946
8947 /* No cursor displayed or row invalidated => nothing to do on the
8948 screen. */
8949 if (w->phys_cursor_type == NO_CURSOR)
8950 goto mark_cursor_off;
8951
8952 /* VPOS >= active_glyphs->nrows means that window has been resized.
8953 Don't bother to erase the cursor. */
8954 if (vpos >= active_glyphs->nrows)
8955 goto mark_cursor_off;
8956
8957 /* If row containing cursor is marked invalid, there is nothing we
8958 can do. */
8959 cursor_row = MATRIX_ROW (active_glyphs, vpos);
8960 if (!cursor_row->enabled_p)
8961 goto mark_cursor_off;
8962
8963 /* If row is completely invisible, don't attempt to delete a cursor which
8964 isn't there. This may happen if cursor is at top of window, and
8965 we switch to a buffer with a header line in that window. */
8966 if (cursor_row->visible_height <= 0)
8967 goto mark_cursor_off;
8968
8969 /* This can happen when the new row is shorter than the old one.
8970 In this case, either x_draw_glyphs or clear_end_of_line
8971 should have cleared the cursor. Note that we wouldn't be
8972 able to erase the cursor in this case because we don't have a
8973 cursor glyph at hand. */
8974 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
8975 goto mark_cursor_off;
8976
8977 /* If the cursor is in the mouse face area, redisplay that when
8978 we clear the cursor. */
8979 if (! NILP (dpyinfo->mouse_face_window)
8980 && w == XWINDOW (dpyinfo->mouse_face_window)
8981 && (vpos > dpyinfo->mouse_face_beg_row
8982 || (vpos == dpyinfo->mouse_face_beg_row
8983 && hpos >= dpyinfo->mouse_face_beg_col))
8984 && (vpos < dpyinfo->mouse_face_end_row
8985 || (vpos == dpyinfo->mouse_face_end_row
8986 && hpos < dpyinfo->mouse_face_end_col))
8987 /* Don't redraw the cursor's spot in mouse face if it is at the
8988 end of a line (on a newline). The cursor appears there, but
8989 mouse highlighting does not. */
8990 && cursor_row->used[TEXT_AREA] > hpos)
8991 mouse_face_here_p = 1;
8992
8993 /* Maybe clear the display under the cursor. */
8994 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
8995 {
8996 int x;
8997 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
8998
8999 cursor_glyph = get_phys_cursor_glyph (w);
9000 if (cursor_glyph == NULL)
9001 goto mark_cursor_off;
9002
9003 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9004
9005 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9006 x,
9007 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9008 cursor_row->y)),
9009 cursor_glyph->pixel_width,
9010 cursor_row->visible_height,
9011 0);
9012 }
9013
9014 /* Erase the cursor by redrawing the character underneath it. */
9015 if (mouse_face_here_p)
9016 hl = DRAW_MOUSE_FACE;
9017 else
9018 hl = DRAW_NORMAL_TEXT;
9019 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9020
9021 mark_cursor_off:
9022 w->phys_cursor_on_p = 0;
9023 w->phys_cursor_type = NO_CURSOR;
9024 }
9025
9026
9027 /* Non-zero if physical cursor of window W is within mouse face. */
9028
9029 static int
9030 cursor_in_mouse_face_p (w)
9031 struct window *w;
9032 {
9033 struct mac_display_info *dpyinfo
9034 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9035 int in_mouse_face = 0;
9036
9037 if (WINDOWP (dpyinfo->mouse_face_window)
9038 && XWINDOW (dpyinfo->mouse_face_window) == w)
9039 {
9040 int hpos = w->phys_cursor.hpos;
9041 int vpos = w->phys_cursor.vpos;
9042
9043 if (vpos >= dpyinfo->mouse_face_beg_row
9044 && vpos <= dpyinfo->mouse_face_end_row
9045 && (vpos > dpyinfo->mouse_face_beg_row
9046 || hpos >= dpyinfo->mouse_face_beg_col)
9047 && (vpos < dpyinfo->mouse_face_end_row
9048 || hpos < dpyinfo->mouse_face_end_col
9049 || dpyinfo->mouse_face_past_end))
9050 in_mouse_face = 1;
9051 }
9052
9053 return in_mouse_face;
9054 }
9055
9056
9057 /* Display or clear cursor of window W. If ON is zero, clear the
9058 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9059 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9060
9061 void
9062 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9063 struct window *w;
9064 int on, hpos, vpos, x, y;
9065 {
9066 struct frame *f = XFRAME (w->frame);
9067 int new_cursor_type;
9068 int new_cursor_width;
9069 int active_cursor;
9070 struct glyph_matrix *current_glyphs;
9071 struct glyph_row *glyph_row;
9072 struct glyph *glyph;
9073
9074 /* This is pointless on invisible frames, and dangerous on garbaged
9075 windows and frames; in the latter case, the frame or window may
9076 be in the midst of changing its size, and x and y may be off the
9077 window. */
9078 if (! FRAME_VISIBLE_P (f)
9079 || FRAME_GARBAGED_P (f)
9080 || vpos >= w->current_matrix->nrows
9081 || hpos >= w->current_matrix->matrix_w)
9082 return;
9083
9084 /* If cursor is off and we want it off, return quickly. */
9085 if (!on && !w->phys_cursor_on_p)
9086 return;
9087
9088 current_glyphs = w->current_matrix;
9089 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9090 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9091
9092 /* If cursor row is not enabled, we don't really know where to
9093 display the cursor. */
9094 if (!glyph_row->enabled_p)
9095 {
9096 w->phys_cursor_on_p = 0;
9097 return;
9098 }
9099
9100 xassert (interrupt_input_blocked);
9101
9102 /* Set new_cursor_type to the cursor we want to be displayed. */
9103 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
9104
9105
9106 /* If cursor is currently being shown and we don't want it to be or
9107 it is in the wrong place, or the cursor type is not what we want,
9108 erase it. */
9109 if (w->phys_cursor_on_p
9110 && (!on
9111 || w->phys_cursor.x != x
9112 || w->phys_cursor.y != y
9113 || new_cursor_type != w->phys_cursor_type
9114 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
9115 && new_cursor_width != w->phys_cursor_width)))
9116 x_erase_phys_cursor (w);
9117
9118 /* If the cursor is now invisible and we want it to be visible,
9119 display it. */
9120 if (on && !w->phys_cursor_on_p)
9121 {
9122 w->phys_cursor_ascent = glyph_row->ascent;
9123 w->phys_cursor_height = glyph_row->height;
9124
9125 /* Set phys_cursor_.* before x_draw_.* is called because some
9126 of them may need the information. */
9127 w->phys_cursor.x = x;
9128 w->phys_cursor.y = glyph_row->y;
9129 w->phys_cursor.hpos = hpos;
9130 w->phys_cursor.vpos = vpos;
9131 w->phys_cursor_type = new_cursor_type;
9132 w->phys_cursor_width = new_cursor_width;
9133 w->phys_cursor_on_p = 1;
9134
9135 switch (new_cursor_type)
9136 {
9137 case HOLLOW_BOX_CURSOR:
9138 x_draw_hollow_cursor (w, glyph_row);
9139 break;
9140
9141 case FILLED_BOX_CURSOR:
9142 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9143 break;
9144
9145 case HBAR_CURSOR:
9146 /* TODO. For now, just draw bar cursor. */
9147 case BAR_CURSOR:
9148 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9149 break;
9150
9151 case NO_CURSOR:
9152 break;
9153
9154 default:
9155 abort ();
9156 }
9157 }
9158 }
9159
9160
9161 /* Display the cursor on window W, or clear it. X and Y are window
9162 relative pixel coordinates. HPOS and VPOS are glyph matrix
9163 positions. If W is not the selected window, display a hollow
9164 cursor. ON non-zero means display the cursor at X, Y which
9165 correspond to HPOS, VPOS, otherwise it is cleared. */
9166
9167 void
9168 x_display_cursor (w, on, hpos, vpos, x, y)
9169 struct window *w;
9170 int on, hpos, vpos, x, y;
9171 {
9172 BLOCK_INPUT;
9173 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9174 UNBLOCK_INPUT;
9175 }
9176
9177
9178 /* Display the cursor on window W, or clear it, according to ON_P.
9179 Don't change the cursor's position. */
9180
9181 void
9182 x_update_cursor (f, on_p)
9183 struct frame *f;
9184 int on_p;
9185 {
9186 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9187 }
9188
9189
9190 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9191 in the window tree rooted at W. */
9192
9193 static void
9194 x_update_cursor_in_window_tree (w, on_p)
9195 struct window *w;
9196 int on_p;
9197 {
9198 while (w)
9199 {
9200 if (!NILP (w->hchild))
9201 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9202 else if (!NILP (w->vchild))
9203 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9204 else
9205 x_update_window_cursor (w, on_p);
9206
9207 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9208 }
9209 }
9210
9211
9212 /* Switch the display of W's cursor on or off, according to the value
9213 of ON. */
9214
9215 static void
9216 x_update_window_cursor (w, on)
9217 struct window *w;
9218 int on;
9219 {
9220 /* Don't update cursor in windows whose frame is in the process
9221 of being deleted. */
9222 if (w->current_matrix)
9223 {
9224 BLOCK_INPUT;
9225 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9226 w->phys_cursor.vpos, w->phys_cursor.x,
9227 w->phys_cursor.y);
9228 UNBLOCK_INPUT;
9229 }
9230 }
9231
9232
9233
9234 \f
9235 /* Icons. */
9236
9237 #if 0 /* MAC_TODO: no icon support yet. */
9238 int
9239 x_bitmap_icon (f, icon)
9240 struct frame *f;
9241 Lisp_Object icon;
9242 {
9243 HANDLE hicon;
9244
9245 if (FRAME_W32_WINDOW (f) == 0)
9246 return 1;
9247
9248 if (NILP (icon))
9249 hicon = LoadIcon (hinst, EMACS_CLASS);
9250 else if (STRINGP (icon))
9251 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
9252 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9253 else if (SYMBOLP (icon))
9254 {
9255 LPCTSTR name;
9256
9257 if (EQ (icon, intern ("application")))
9258 name = (LPCTSTR) IDI_APPLICATION;
9259 else if (EQ (icon, intern ("hand")))
9260 name = (LPCTSTR) IDI_HAND;
9261 else if (EQ (icon, intern ("question")))
9262 name = (LPCTSTR) IDI_QUESTION;
9263 else if (EQ (icon, intern ("exclamation")))
9264 name = (LPCTSTR) IDI_EXCLAMATION;
9265 else if (EQ (icon, intern ("asterisk")))
9266 name = (LPCTSTR) IDI_ASTERISK;
9267 else if (EQ (icon, intern ("winlogo")))
9268 name = (LPCTSTR) IDI_WINLOGO;
9269 else
9270 return 1;
9271
9272 hicon = LoadIcon (NULL, name);
9273 }
9274 else
9275 return 1;
9276
9277 if (hicon == NULL)
9278 return 1;
9279
9280 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9281 (LPARAM) hicon);
9282
9283 return 0;
9284 }
9285 #endif /* MAC_TODO */
9286 \f
9287 /************************************************************************
9288 Handling X errors
9289 ************************************************************************/
9290
9291 /* Display Error Handling functions not used on W32. Listing them here
9292 helps diff stay in step when comparing w32term.c with xterm.c.
9293
9294 x_error_catcher (display, error)
9295 x_catch_errors (dpy)
9296 x_catch_errors_unwind (old_val)
9297 x_check_errors (dpy, format)
9298 x_had_errors_p (dpy)
9299 x_clear_errors (dpy)
9300 x_uncatch_errors (dpy, count)
9301 x_trace_wire ()
9302 x_connection_signal (signalnum)
9303 x_connection_closed (dpy, error_message)
9304 x_error_quitter (display, error)
9305 x_error_handler (display, error)
9306 x_io_error_quitter (display)
9307
9308 */
9309
9310 \f
9311 /* Changing the font of the frame. */
9312
9313 /* Give frame F the font named FONTNAME as its default font, and
9314 return the full name of that font. FONTNAME may be a wildcard
9315 pattern; in that case, we choose some font that fits the pattern.
9316 The return value shows which font we chose. */
9317
9318 Lisp_Object
9319 x_new_font (f, fontname)
9320 struct frame *f;
9321 register char *fontname;
9322 {
9323 struct font_info *fontp
9324 = FS_LOAD_FONT (f, 0, fontname, -1);
9325
9326 if (!fontp)
9327 return Qnil;
9328
9329 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9330 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9331 FRAME_FONTSET (f) = -1;
9332
9333 /* Compute the scroll bar width in character columns. */
9334 if (f->scroll_bar_pixel_width > 0)
9335 {
9336 int wid = FONT_WIDTH (FRAME_FONT (f));
9337 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9338 }
9339 else
9340 {
9341 int wid = FONT_WIDTH (FRAME_FONT (f));
9342 f->scroll_bar_cols = (14 + wid - 1) / wid;
9343 }
9344
9345 /* Now make the frame display the given font. */
9346 if (FRAME_MAC_WINDOW (f) != 0)
9347 {
9348 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9349 f->output_data.mac->font);
9350 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9351 f->output_data.mac->font);
9352 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9353 f->output_data.mac->font);
9354
9355 frame_update_line_height (f);
9356 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9357 x_set_window_size (f, 0, f->width, f->height);
9358 }
9359 else
9360 /* If we are setting a new frame's font for the first time,
9361 there are no faces yet, so this font's height is the line height. */
9362 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
9363
9364 return build_string (fontp->full_name);
9365 }
9366 \f
9367 /* Give frame F the fontset named FONTSETNAME as its default font, and
9368 return the full name of that fontset. FONTSETNAME may be a wildcard
9369 pattern; in that case, we choose some fontset that fits the pattern.
9370 The return value shows which fontset we chose. */
9371
9372 Lisp_Object
9373 x_new_fontset (f, fontsetname)
9374 struct frame *f;
9375 char *fontsetname;
9376 {
9377 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9378 Lisp_Object result;
9379
9380 if (fontset < 0)
9381 return Qnil;
9382
9383 if (FRAME_FONTSET (f) == fontset)
9384 /* This fontset is already set in frame F. There's nothing more
9385 to do. */
9386 return fontset_name (fontset);
9387
9388 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
9389
9390 if (!STRINGP (result))
9391 /* Can't load ASCII font. */
9392 return Qnil;
9393
9394 /* Since x_new_font doesn't update any fontset information, do it now. */
9395 FRAME_FONTSET(f) = fontset;
9396
9397 return build_string (fontsetname);
9398 }
9399
9400 \f
9401 /***********************************************************************
9402 TODO: W32 Input Methods
9403 ***********************************************************************/
9404 /* Listing missing functions from xterm.c helps diff stay in step.
9405
9406 xim_destroy_callback (xim, client_data, call_data)
9407 xim_open_dpy (dpyinfo, resource_name)
9408 struct xim_inst_t
9409 xim_instantiate_callback (display, client_data, call_data)
9410 xim_initialize (dpyinfo, resource_name)
9411 xim_close_dpy (dpyinfo)
9412
9413 */
9414
9415 \f
9416 /* Calculate the absolute position in frame F
9417 from its current recorded position values and gravity. */
9418
9419 void
9420 x_calc_absolute_position (f)
9421 struct frame *f;
9422 {
9423 Point pt;
9424 int flags = f->output_data.mac->size_hint_flags;
9425
9426 pt.h = pt.v = 0;
9427
9428 /* Find the position of the outside upper-left corner of
9429 the inner window, with respect to the outer window. */
9430 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9431 {
9432 GrafPtr savePort;
9433 GetPort (&savePort);
9434
9435 #if TARGET_API_MAC_CARBON
9436 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9437 #else
9438 SetPort (FRAME_MAC_WINDOW (f));
9439 #endif
9440
9441 #if TARGET_API_MAC_CARBON
9442 {
9443 Rect r;
9444
9445 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9446 SetPt(&pt, r.left, r.top);
9447 }
9448 #else /* not TARGET_API_MAC_CARBON */
9449 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
9450 #endif /* not TARGET_API_MAC_CARBON */
9451 LocalToGlobal (&pt);
9452 SetPort (savePort);
9453 }
9454
9455 /* Treat negative positions as relative to the leftmost bottommost
9456 position that fits on the screen. */
9457 if (flags & XNegative)
9458 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9459 - 2 * f->output_data.mac->border_width - pt.h
9460 - PIXEL_WIDTH (f)
9461 + f->output_data.mac->left_pos);
9462 /* NTEMACS_TODO: Subtract menubar height? */
9463 if (flags & YNegative)
9464 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9465 - 2 * f->output_data.mac->border_width - pt.v
9466 - PIXEL_HEIGHT (f)
9467 + f->output_data.mac->top_pos);
9468 /* The left_pos and top_pos
9469 are now relative to the top and left screen edges,
9470 so the flags should correspond. */
9471 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9472 }
9473
9474 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9475 to really change the position, and 0 when calling from
9476 x_make_frame_visible (in that case, XOFF and YOFF are the current
9477 position values). It is -1 when calling from x_set_frame_parameters,
9478 which means, do adjust for borders but don't change the gravity. */
9479
9480 void
9481 x_set_offset (f, xoff, yoff, change_gravity)
9482 struct frame *f;
9483 register int xoff, yoff;
9484 int change_gravity;
9485 {
9486 int modified_top, modified_left;
9487
9488 if (change_gravity > 0)
9489 {
9490 f->output_data.mac->top_pos = yoff;
9491 f->output_data.mac->left_pos = xoff;
9492 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9493 if (xoff < 0)
9494 f->output_data.mac->size_hint_flags |= XNegative;
9495 if (yoff < 0)
9496 f->output_data.mac->size_hint_flags |= YNegative;
9497 f->output_data.mac->win_gravity = NorthWestGravity;
9498 }
9499 x_calc_absolute_position (f);
9500
9501 BLOCK_INPUT;
9502 x_wm_set_size_hint (f, (long) 0, 0);
9503
9504 modified_left = f->output_data.mac->left_pos;
9505 modified_top = f->output_data.mac->top_pos;
9506
9507 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9508 modified_top + 42, false);
9509
9510 UNBLOCK_INPUT;
9511 }
9512
9513 /* Call this to change the size of frame F's x-window.
9514 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9515 for this size change and subsequent size changes.
9516 Otherwise we leave the window gravity unchanged. */
9517
9518 void
9519 x_set_window_size (f, change_gravity, cols, rows)
9520 struct frame *f;
9521 int change_gravity;
9522 int cols, rows;
9523 {
9524 int pixelwidth, pixelheight;
9525
9526 BLOCK_INPUT;
9527
9528 check_frame_size (f, &rows, &cols);
9529 f->output_data.mac->vertical_scroll_bar_extra
9530 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9531 ? 0
9532 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
9533
9534 compute_fringe_widths (f, 0);
9535
9536 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9537 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9538
9539 f->output_data.mac->win_gravity = NorthWestGravity;
9540 x_wm_set_size_hint (f, (long) 0, 0);
9541
9542 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9543
9544 /* Now, strictly speaking, we can't be sure that this is accurate,
9545 but the window manager will get around to dealing with the size
9546 change request eventually, and we'll hear how it went when the
9547 ConfigureNotify event gets here.
9548
9549 We could just not bother storing any of this information here,
9550 and let the ConfigureNotify event set everything up, but that
9551 might be kind of confusing to the Lisp code, since size changes
9552 wouldn't be reported in the frame parameters until some random
9553 point in the future when the ConfigureNotify event arrives.
9554
9555 We pass 1 for DELAY since we can't run Lisp code inside of
9556 a BLOCK_INPUT. */
9557 change_frame_size (f, rows, cols, 0, 1, 0);
9558 PIXEL_WIDTH (f) = pixelwidth;
9559 PIXEL_HEIGHT (f) = pixelheight;
9560
9561 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9562 receive in the ConfigureNotify event; if we get what we asked
9563 for, then the event won't cause the screen to become garbaged, so
9564 we have to make sure to do it here. */
9565 SET_FRAME_GARBAGED (f);
9566
9567 XFlush (FRAME_X_DISPLAY (f));
9568
9569 /* If cursor was outside the new size, mark it as off. */
9570 mark_window_cursors_off (XWINDOW (f->root_window));
9571
9572 /* Clear out any recollection of where the mouse highlighting was,
9573 since it might be in a place that's outside the new frame size.
9574 Actually checking whether it is outside is a pain in the neck,
9575 so don't try--just let the highlighting be done afresh with new size. */
9576 cancel_mouse_face (f);
9577
9578 UNBLOCK_INPUT;
9579 }
9580 \f
9581 /* Mouse warping. */
9582
9583 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9584
9585 void
9586 x_set_mouse_position (f, x, y)
9587 struct frame *f;
9588 int x, y;
9589 {
9590 int pix_x, pix_y;
9591
9592 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9593 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9594
9595 if (pix_x < 0) pix_x = 0;
9596 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9597
9598 if (pix_y < 0) pix_y = 0;
9599 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9600
9601 x_set_mouse_pixel_position (f, pix_x, pix_y);
9602 }
9603
9604 void
9605 x_set_mouse_pixel_position (f, pix_x, pix_y)
9606 struct frame *f;
9607 int pix_x, pix_y;
9608 {
9609 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9610 BLOCK_INPUT;
9611
9612 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9613 0, 0, 0, 0, pix_x, pix_y);
9614 UNBLOCK_INPUT;
9615 #endif
9616 }
9617
9618 \f
9619 /* focus shifting, raising and lowering. */
9620
9621 void
9622 x_focus_on_frame (f)
9623 struct frame *f;
9624 {
9625 #if 0 /* This proves to be unpleasant. */
9626 x_raise_frame (f);
9627 #endif
9628 #if 0
9629 /* I don't think that the ICCCM allows programs to do things like this
9630 without the interaction of the window manager. Whatever you end up
9631 doing with this code, do it to x_unfocus_frame too. */
9632 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9633 RevertToPointerRoot, CurrentTime);
9634 #endif /* ! 0 */
9635 }
9636
9637 void
9638 x_unfocus_frame (f)
9639 struct frame *f;
9640 {
9641 }
9642
9643 /* Raise frame F. */
9644 void
9645 x_raise_frame (f)
9646 struct frame *f;
9647 {
9648 if (f->async_visible)
9649 SelectWindow (FRAME_MAC_WINDOW (f));
9650 }
9651
9652 /* Lower frame F. */
9653 void
9654 x_lower_frame (f)
9655 struct frame *f;
9656 {
9657 if (f->async_visible)
9658 SendBehind (FRAME_MAC_WINDOW (f), nil);
9659 }
9660
9661 static void
9662 XTframe_raise_lower (f, raise_flag)
9663 FRAME_PTR f;
9664 int raise_flag;
9665 {
9666 if (raise_flag)
9667 x_raise_frame (f);
9668 else
9669 x_lower_frame (f);
9670 }
9671 \f
9672 /* Change of visibility. */
9673
9674 /* This tries to wait until the frame is really visible.
9675 However, if the window manager asks the user where to position
9676 the frame, this will return before the user finishes doing that.
9677 The frame will not actually be visible at that time,
9678 but it will become visible later when the window manager
9679 finishes with it. */
9680
9681 void
9682 x_make_frame_visible (f)
9683 struct frame *f;
9684 {
9685 Lisp_Object type;
9686 int original_top, original_left;
9687
9688 BLOCK_INPUT;
9689
9690 if (! FRAME_VISIBLE_P (f))
9691 {
9692 /* We test FRAME_GARBAGED_P here to make sure we don't
9693 call x_set_offset a second time
9694 if we get to x_make_frame_visible a second time
9695 before the window gets really visible. */
9696 if (! FRAME_ICONIFIED_P (f)
9697 && ! f->output_data.mac->asked_for_visible)
9698 x_set_offset (f, f->output_data.mac->left_pos,
9699 f->output_data.mac->top_pos, 0);
9700
9701 f->output_data.mac->asked_for_visible = 1;
9702
9703 ShowWindow (FRAME_MAC_WINDOW (f));
9704 }
9705
9706 XFlush (FRAME_MAC_DISPLAY (f));
9707
9708 #if 0 /* MAC_TODO */
9709 /* Synchronize to ensure Emacs knows the frame is visible
9710 before we do anything else. We do this loop with input not blocked
9711 so that incoming events are handled. */
9712 {
9713 Lisp_Object frame;
9714 int count;
9715
9716 /* This must come after we set COUNT. */
9717 UNBLOCK_INPUT;
9718
9719 XSETFRAME (frame, f);
9720
9721 /* Wait until the frame is visible. Process X events until a
9722 MapNotify event has been seen, or until we think we won't get a
9723 MapNotify at all.. */
9724 for (count = input_signal_count + 10;
9725 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9726 {
9727 /* Force processing of queued events. */
9728 x_sync (f);
9729
9730 /* Machines that do polling rather than SIGIO have been
9731 observed to go into a busy-wait here. So we'll fake an
9732 alarm signal to let the handler know that there's something
9733 to be read. We used to raise a real alarm, but it seems
9734 that the handler isn't always enabled here. This is
9735 probably a bug. */
9736 if (input_polling_used ())
9737 {
9738 /* It could be confusing if a real alarm arrives while
9739 processing the fake one. Turn it off and let the
9740 handler reset it. */
9741 extern void poll_for_input_1 P_ ((void));
9742 int old_poll_suppress_count = poll_suppress_count;
9743 poll_suppress_count = 1;
9744 poll_for_input_1 ();
9745 poll_suppress_count = old_poll_suppress_count;
9746 }
9747
9748 /* See if a MapNotify event has been processed. */
9749 FRAME_SAMPLE_VISIBILITY (f);
9750 }
9751 }
9752 #endif /* MAC_TODO */
9753 }
9754
9755 /* Change from mapped state to withdrawn state. */
9756
9757 /* Make the frame visible (mapped and not iconified). */
9758
9759 void
9760 x_make_frame_invisible (f)
9761 struct frame *f;
9762 {
9763 /* Don't keep the highlight on an invisible frame. */
9764 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
9765 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
9766
9767 BLOCK_INPUT;
9768
9769 HideWindow (FRAME_MAC_WINDOW (f));
9770
9771 /* We can't distinguish this from iconification
9772 just by the event that we get from the server.
9773 So we can't win using the usual strategy of letting
9774 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9775 and synchronize with the server to make sure we agree. */
9776 f->visible = 0;
9777 FRAME_ICONIFIED_P (f) = 0;
9778 f->async_visible = 0;
9779 f->async_iconified = 0;
9780
9781 UNBLOCK_INPUT;
9782 }
9783
9784 /* Change window state from mapped to iconified. */
9785
9786 void
9787 x_iconify_frame (f)
9788 struct frame *f;
9789 {
9790 /* Don't keep the highlight on an invisible frame. */
9791 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
9792 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
9793
9794 #if 0
9795 /* Review: Since window is still visible in dock, still allow updates? */
9796 if (f->async_iconified)
9797 return;
9798 #endif
9799
9800 BLOCK_INPUT;
9801
9802 CollapseWindow (FRAME_MAC_WINDOW (f), true);
9803
9804 UNBLOCK_INPUT;
9805 }
9806
9807 \f
9808 /* Destroy the X window of frame F. */
9809
9810 void
9811 x_destroy_window (f)
9812 struct frame *f;
9813 {
9814 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9815
9816 BLOCK_INPUT;
9817
9818 DisposeWindow (FRAME_MAC_WINDOW (f));
9819
9820 free_frame_menubar (f);
9821 free_frame_faces (f);
9822
9823 xfree (f->output_data.mac);
9824 f->output_data.mac = 0;
9825 if (f == dpyinfo->x_focus_frame)
9826 dpyinfo->x_focus_frame = 0;
9827 if (f == dpyinfo->x_focus_event_frame)
9828 dpyinfo->x_focus_event_frame = 0;
9829 if (f == dpyinfo->x_highlight_frame)
9830 dpyinfo->x_highlight_frame = 0;
9831
9832 dpyinfo->reference_count--;
9833
9834 if (f == dpyinfo->mouse_face_mouse_frame)
9835 {
9836 dpyinfo->mouse_face_beg_row
9837 = dpyinfo->mouse_face_beg_col = -1;
9838 dpyinfo->mouse_face_end_row
9839 = dpyinfo->mouse_face_end_col = -1;
9840 dpyinfo->mouse_face_window = Qnil;
9841 dpyinfo->mouse_face_deferred_gc = 0;
9842 dpyinfo->mouse_face_mouse_frame = 0;
9843 }
9844
9845 UNBLOCK_INPUT;
9846 }
9847 \f
9848 /* Setting window manager hints. */
9849
9850 /* Set the normal size hints for the window manager, for frame F.
9851 FLAGS is the flags word to use--or 0 meaning preserve the flags
9852 that the window now has.
9853 If USER_POSITION is nonzero, we set the USPosition
9854 flag (this is useful when FLAGS is 0). */
9855 void
9856 x_wm_set_size_hint (f, flags, user_position)
9857 struct frame *f;
9858 long flags;
9859 int user_position;
9860 {
9861 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
9862 XSizeHints size_hints;
9863
9864 #ifdef USE_X_TOOLKIT
9865 Arg al[2];
9866 int ac = 0;
9867 Dimension widget_width, widget_height;
9868 Window window = XtWindow (f->output_data.x->widget);
9869 #else /* not USE_X_TOOLKIT */
9870 Window window = FRAME_X_WINDOW (f);
9871 #endif /* not USE_X_TOOLKIT */
9872
9873 /* Setting PMaxSize caused various problems. */
9874 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
9875
9876 size_hints.x = f->output_data.x->left_pos;
9877 size_hints.y = f->output_data.x->top_pos;
9878
9879 #ifdef USE_X_TOOLKIT
9880 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
9881 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
9882 XtGetValues (f->output_data.x->widget, al, ac);
9883 size_hints.height = widget_height;
9884 size_hints.width = widget_width;
9885 #else /* not USE_X_TOOLKIT */
9886 size_hints.height = PIXEL_HEIGHT (f);
9887 size_hints.width = PIXEL_WIDTH (f);
9888 #endif /* not USE_X_TOOLKIT */
9889
9890 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
9891 size_hints.height_inc = f->output_data.x->line_height;
9892 size_hints.max_width
9893 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
9894 size_hints.max_height
9895 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
9896
9897 /* Calculate the base and minimum sizes.
9898
9899 (When we use the X toolkit, we don't do it here.
9900 Instead we copy the values that the widgets are using, below.) */
9901 #ifndef USE_X_TOOLKIT
9902 {
9903 int base_width, base_height;
9904 int min_rows = 0, min_cols = 0;
9905
9906 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
9907 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
9908
9909 check_frame_size (f, &min_rows, &min_cols);
9910
9911 /* The window manager uses the base width hints to calculate the
9912 current number of rows and columns in the frame while
9913 resizing; min_width and min_height aren't useful for this
9914 purpose, since they might not give the dimensions for a
9915 zero-row, zero-column frame.
9916
9917 We use the base_width and base_height members if we have
9918 them; otherwise, we set the min_width and min_height members
9919 to the size for a zero x zero frame. */
9920
9921 #ifdef HAVE_X11R4
9922 size_hints.flags |= PBaseSize;
9923 size_hints.base_width = base_width;
9924 size_hints.base_height = base_height;
9925 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
9926 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
9927 #else
9928 size_hints.min_width = base_width;
9929 size_hints.min_height = base_height;
9930 #endif
9931 }
9932
9933 /* If we don't need the old flags, we don't need the old hint at all. */
9934 if (flags)
9935 {
9936 size_hints.flags |= flags;
9937 goto no_read;
9938 }
9939 #endif /* not USE_X_TOOLKIT */
9940
9941 {
9942 XSizeHints hints; /* Sometimes I hate X Windows... */
9943 long supplied_return;
9944 int value;
9945
9946 #ifdef HAVE_X11R4
9947 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
9948 &supplied_return);
9949 #else
9950 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
9951 #endif
9952
9953 #ifdef USE_X_TOOLKIT
9954 size_hints.base_height = hints.base_height;
9955 size_hints.base_width = hints.base_width;
9956 size_hints.min_height = hints.min_height;
9957 size_hints.min_width = hints.min_width;
9958 #endif
9959
9960 if (flags)
9961 size_hints.flags |= flags;
9962 else
9963 {
9964 if (value == 0)
9965 hints.flags = 0;
9966 if (hints.flags & PSize)
9967 size_hints.flags |= PSize;
9968 if (hints.flags & PPosition)
9969 size_hints.flags |= PPosition;
9970 if (hints.flags & USPosition)
9971 size_hints.flags |= USPosition;
9972 if (hints.flags & USSize)
9973 size_hints.flags |= USSize;
9974 }
9975 }
9976
9977 #ifndef USE_X_TOOLKIT
9978 no_read:
9979 #endif
9980
9981 #ifdef PWinGravity
9982 size_hints.win_gravity = f->output_data.x->win_gravity;
9983 size_hints.flags |= PWinGravity;
9984
9985 if (user_position)
9986 {
9987 size_hints.flags &= ~ PPosition;
9988 size_hints.flags |= USPosition;
9989 }
9990 #endif /* PWinGravity */
9991
9992 #ifdef HAVE_X11R4
9993 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
9994 #else
9995 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
9996 #endif
9997 #endif /* MAC_TODO */
9998 }
9999
10000 #if 0 /* MAC_TODO: hide application instead of iconify? */
10001 /* Used for IconicState or NormalState */
10002
10003 void
10004 x_wm_set_window_state (f, state)
10005 struct frame *f;
10006 int state;
10007 {
10008 #ifdef USE_X_TOOLKIT
10009 Arg al[1];
10010
10011 XtSetArg (al[0], XtNinitialState, state);
10012 XtSetValues (f->output_data.x->widget, al, 1);
10013 #else /* not USE_X_TOOLKIT */
10014 Window window = FRAME_X_WINDOW (f);
10015
10016 f->output_data.x->wm_hints.flags |= StateHint;
10017 f->output_data.x->wm_hints.initial_state = state;
10018
10019 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10020 #endif /* not USE_X_TOOLKIT */
10021 }
10022
10023 void
10024 x_wm_set_icon_pixmap (f, pixmap_id)
10025 struct frame *f;
10026 int pixmap_id;
10027 {
10028 Pixmap icon_pixmap;
10029
10030 #ifndef USE_X_TOOLKIT
10031 Window window = FRAME_X_WINDOW (f);
10032 #endif
10033
10034 if (pixmap_id > 0)
10035 {
10036 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10037 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10038 }
10039 else
10040 {
10041 /* It seems there is no way to turn off use of an icon pixmap.
10042 The following line does it, only if no icon has yet been created,
10043 for some window managers. But with mwm it crashes.
10044 Some people say it should clear the IconPixmapHint bit in this case,
10045 but that doesn't work, and the X consortium said it isn't the
10046 right thing at all. Since there is no way to win,
10047 best to explicitly give up. */
10048 #if 0
10049 f->output_data.x->wm_hints.icon_pixmap = None;
10050 #else
10051 return;
10052 #endif
10053 }
10054
10055 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10056
10057 {
10058 Arg al[1];
10059 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10060 XtSetValues (f->output_data.x->widget, al, 1);
10061 }
10062
10063 #else /* not USE_X_TOOLKIT */
10064
10065 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10066 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10067
10068 #endif /* not USE_X_TOOLKIT */
10069 }
10070
10071 #endif /* MAC_TODO */
10072
10073 void
10074 x_wm_set_icon_position (f, icon_x, icon_y)
10075 struct frame *f;
10076 int icon_x, icon_y;
10077 {
10078 #if 0 /* MAC_TODO: no icons on Mac */
10079 #ifdef USE_X_TOOLKIT
10080 Window window = XtWindow (f->output_data.x->widget);
10081 #else
10082 Window window = FRAME_X_WINDOW (f);
10083 #endif
10084
10085 f->output_data.x->wm_hints.flags |= IconPositionHint;
10086 f->output_data.x->wm_hints.icon_x = icon_x;
10087 f->output_data.x->wm_hints.icon_y = icon_y;
10088
10089 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10090 #endif /* MAC_TODO */
10091 }
10092
10093 \f
10094 /***********************************************************************
10095 Fonts
10096 ***********************************************************************/
10097
10098 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10099
10100 struct font_info *
10101 x_get_font_info (f, font_idx)
10102 FRAME_PTR f;
10103 int font_idx;
10104 {
10105 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10106 }
10107
10108 /* the global font name table */
10109 char **font_name_table = NULL;
10110 int font_name_table_size = 0;
10111 int font_name_count = 0;
10112
10113 /* compare two strings ignoring case */
10114 static int
10115 stricmp (const char *s, const char *t)
10116 {
10117 for ( ; tolower (*s) == tolower (*t); s++, t++)
10118 if (*s == '\0')
10119 return 0;
10120 return tolower (*s) - tolower (*t);
10121 }
10122
10123 /* compare two strings ignoring case and handling wildcard */
10124 static int
10125 wildstrieq (char *s1, char *s2)
10126 {
10127 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10128 return true;
10129
10130 return stricmp (s1, s2) == 0;
10131 }
10132
10133 /* Assume parameter 1 is fully qualified, no wildcards. */
10134 static int
10135 mac_font_pattern_match (fontname, pattern)
10136 char * fontname;
10137 char * pattern;
10138 {
10139 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
10140 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10141 char *ptr;
10142
10143 /* Copy fontname so we can modify it during comparison. */
10144 strcpy (font_name_copy, fontname);
10145
10146 ptr = regex;
10147 *ptr++ = '^';
10148
10149 /* Turn pattern into a regexp and do a regexp match. */
10150 for (; *pattern; pattern++)
10151 {
10152 if (*pattern == '?')
10153 *ptr++ = '.';
10154 else if (*pattern == '*')
10155 {
10156 *ptr++ = '.';
10157 *ptr++ = '*';
10158 }
10159 else
10160 *ptr++ = *pattern;
10161 }
10162 *ptr = '$';
10163 *(ptr + 1) = '\0';
10164
10165 return (fast_c_string_match_ignore_case (build_string (regex),
10166 font_name_copy) >= 0);
10167 }
10168
10169 /* Two font specs are considered to match if their foundry, family,
10170 weight, slant, and charset match. */
10171 static int
10172 mac_font_match (char *mf, char *xf)
10173 {
10174 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10175 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10176
10177 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10178 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10179 return mac_font_pattern_match (mf, xf);
10180
10181 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10182 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10183 return mac_font_pattern_match (mf, xf);
10184
10185 return (wildstrieq (m_foundry, x_foundry)
10186 && wildstrieq (m_family, x_family)
10187 && wildstrieq (m_weight, x_weight)
10188 && wildstrieq (m_slant, x_slant)
10189 && wildstrieq (m_charset, x_charset))
10190 || mac_font_pattern_match (mf, xf);
10191 }
10192
10193
10194 static char *
10195 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10196 {
10197 char foundry[32], family[32], cs[32];
10198 char xf[255], *result, *p;
10199
10200 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10201 {
10202 strcpy(foundry, "Apple");
10203 strcpy(family, name);
10204
10205 switch (scriptcode)
10206 {
10207 case smTradChinese:
10208 strcpy(cs, "big5-0");
10209 break;
10210 case smSimpChinese:
10211 strcpy(cs, "gb2312.1980-0");
10212 break;
10213 case smJapanese:
10214 strcpy(cs, "jisx0208.1983-sjis");
10215 break;
10216 case -smJapanese:
10217 /* Each Apple Japanese font is entered into the font table
10218 twice: once as a jisx0208.1983-sjis font and once as a
10219 jisx0201.1976-0 font. The latter can be used to display
10220 the ascii charset and katakana-jisx0201 charset. A
10221 negative script code signals that the name of this latter
10222 font is being built. */
10223 strcpy(cs, "jisx0201.1976-0");
10224 break;
10225 case smKorean:
10226 strcpy(cs, "ksc5601.1989-0");
10227 break;
10228 default:
10229 strcpy(cs, "mac-roman");
10230 break;
10231 }
10232 }
10233
10234 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10235 foundry, family, style & bold ? "bold" : "medium",
10236 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10237
10238 result = (char *) xmalloc (strlen (xf) + 1);
10239 strcpy (result, xf);
10240 for (p = result; *p; p++)
10241 *p = tolower(*p);
10242 return result;
10243 }
10244
10245
10246 /* Convert an X font spec to the corresponding mac font name, which
10247 can then be passed to GetFNum after conversion to a Pascal string.
10248 For ordinary Mac fonts, this should just be their names, like
10249 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10250 collection contain their charset designation in their names, like
10251 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10252 names are handled accordingly. */
10253 static void
10254 x_font_name_to_mac_font_name (char *xf, char *mf)
10255 {
10256 char foundry[32], family[32], weight[20], slant[2], cs[32];
10257
10258 strcpy (mf, "");
10259
10260 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10261 foundry, family, weight, slant, cs) != 5 &&
10262 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10263 foundry, family, weight, slant, cs) != 5)
10264 return;
10265
10266 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
10267 || strcmp (cs, "jisx0208.1983-sjis") == 0
10268 || strcmp (cs, "jisx0201.1976-0") == 0
10269 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
10270 strcpy(mf, family);
10271 else
10272 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10273 }
10274
10275
10276 static void
10277 add_font_name_table_entry (char *font_name)
10278 {
10279 if (font_name_table_size == 0)
10280 {
10281 font_name_table_size = 16;
10282 font_name_table = (char **)
10283 xmalloc (font_name_table_size * sizeof (char *));
10284 }
10285 else if (font_name_count + 1 >= font_name_table_size)
10286 {
10287 font_name_table_size += 16;
10288 font_name_table = (char **)
10289 xrealloc (font_name_table,
10290 font_name_table_size * sizeof (char *));
10291 }
10292
10293 font_name_table[font_name_count++] = font_name;
10294 }
10295
10296 /* Sets up the table font_name_table to contain the list of all fonts
10297 in the system the first time the table is used so that the Resource
10298 Manager need not be accessed every time this information is
10299 needed. */
10300
10301 static void
10302 init_font_name_table ()
10303 {
10304 #if TARGET_API_MAC_CARBON
10305 SInt32 sv;
10306
10307 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10308 {
10309 FMFontFamilyIterator ffi;
10310 FMFontFamilyInstanceIterator ffii;
10311 FMFontFamily ff;
10312
10313 /* Create a dummy instance iterator here to avoid creating and
10314 destroying it in the loop. */
10315 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10316 return;
10317 /* Create an iterator to enumerate the font families. */
10318 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10319 != noErr)
10320 {
10321 FMDisposeFontFamilyInstanceIterator (&ffii);
10322 return;
10323 }
10324
10325 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10326 {
10327 Str255 name;
10328 FMFont font;
10329 FMFontStyle style;
10330 FMFontSize size;
10331 SInt16 sc;
10332
10333 if (FMGetFontFamilyName (ff, name) != noErr)
10334 break;
10335 p2cstr (name);
10336
10337 sc = FontToScript (ff);
10338
10339 /* Point the instance iterator at the current font family. */
10340 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10341 break;
10342
10343 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10344 == noErr)
10345 if (size == 0)
10346 {
10347 add_font_name_table_entry (mac_to_x_fontname (name, size,
10348 style, sc));
10349 add_font_name_table_entry (mac_to_x_fontname (name, size,
10350 italic, sc));
10351 add_font_name_table_entry (mac_to_x_fontname (name, size,
10352 bold, sc));
10353 add_font_name_table_entry (mac_to_x_fontname (name, size,
10354 italic | bold,
10355 sc));
10356 }
10357 else
10358 {
10359 add_font_name_table_entry (mac_to_x_fontname (name, size,
10360 style, sc));
10361 if (smJapanese == sc)
10362 add_font_name_table_entry (mac_to_x_fontname (name, size,
10363 style,
10364 -smJapanese));
10365 }
10366 }
10367
10368 /* Dispose of the iterators. */
10369 FMDisposeFontFamilyIterator (&ffi);
10370 FMDisposeFontFamilyInstanceIterator (&ffii);
10371 }
10372 else
10373 {
10374 #endif /* TARGET_API_MAC_CARBON */
10375 GrafPtr port;
10376 SInt16 fontnum, old_fontnum;
10377 int num_mac_fonts = CountResources('FOND');
10378 int i, j;
10379 Handle font_handle, font_handle_2;
10380 short id, scriptcode;
10381 ResType type;
10382 Str32 name;
10383 struct FontAssoc *fat;
10384 struct AsscEntry *assc_entry;
10385
10386 GetPort (&port); /* save the current font number used */
10387 #if TARGET_API_MAC_CARBON
10388 old_fontnum = GetPortTextFont (port);
10389 #else
10390 old_fontnum = port->txFont;
10391 #endif
10392
10393 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10394 {
10395 font_handle = GetIndResource ('FOND', i);
10396 if (!font_handle)
10397 continue;
10398
10399 GetResInfo (font_handle, &id, &type, name);
10400 GetFNum (name, &fontnum);
10401 p2cstr (name);
10402 if (fontnum == 0)
10403 continue;
10404
10405 TextFont (fontnum);
10406 scriptcode = FontToScript (fontnum);
10407 do
10408 {
10409 HLock (font_handle);
10410
10411 if (GetResourceSizeOnDisk (font_handle)
10412 >= sizeof (struct FamRec))
10413 {
10414 fat = (struct FontAssoc *) (*font_handle
10415 + sizeof (struct FamRec));
10416 assc_entry
10417 = (struct AsscEntry *) (*font_handle
10418 + sizeof (struct FamRec)
10419 + sizeof (struct FontAssoc));
10420
10421 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
10422 {
10423 if (font_name_table_size == 0)
10424 {
10425 font_name_table_size = 16;
10426 font_name_table = (char **)
10427 xmalloc (font_name_table_size * sizeof (char *));
10428 }
10429 else if (font_name_count >= font_name_table_size)
10430 {
10431 font_name_table_size += 16;
10432 font_name_table = (char **)
10433 xrealloc (font_name_table,
10434 font_name_table_size * sizeof (char *));
10435 }
10436 font_name_table[font_name_count++]
10437 = mac_to_x_fontname (name,
10438 assc_entry->fontSize,
10439 assc_entry->fontStyle,
10440 scriptcode);
10441 /* Both jisx0208.1983-sjis and
10442 jisx0201.1976-sjis parts are contained in
10443 Apple Japanese (SJIS) font. */
10444 if (smJapanese == scriptcode)
10445 {
10446 font_name_table[font_name_count++]
10447 = mac_to_x_fontname (name,
10448 assc_entry->fontSize,
10449 assc_entry->fontStyle,
10450 -smJapanese);
10451 }
10452 }
10453 }
10454
10455 HUnlock (font_handle);
10456 font_handle_2 = GetNextFOND (font_handle);
10457 ReleaseResource (font_handle);
10458 font_handle = font_handle_2;
10459 }
10460 while (ResError () == noErr && font_handle);
10461 }
10462
10463 TextFont (old_fontnum);
10464 #if TARGET_API_MAC_CARBON
10465 }
10466 #endif /* TARGET_API_MAC_CARBON */
10467 }
10468
10469
10470 /* Return a list of at most MAXNAMES font specs matching the one in
10471 PATTERN. Cache matching fonts for patterns in
10472 dpyinfo->name_list_element to avoid looking them up again by
10473 calling mac_font_pattern_match (slow). */
10474
10475 Lisp_Object
10476 x_list_fonts (struct frame *f,
10477 Lisp_Object pattern,
10478 int size,
10479 int maxnames)
10480 {
10481 char *ptnstr;
10482 Lisp_Object newlist = Qnil, tem, key;
10483 int n_fonts = 0;
10484 int i;
10485 struct gcpro gcpro1, gcpro2;
10486 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
10487
10488 if (font_name_table == NULL) /* Initialize when first used. */
10489 init_font_name_table ();
10490
10491 if (dpyinfo)
10492 {
10493 tem = XCDR (dpyinfo->name_list_element);
10494 key = Fcons (pattern, make_number (maxnames));
10495
10496 newlist = Fassoc (key, tem);
10497 if (!NILP (newlist))
10498 {
10499 newlist = Fcdr_safe (newlist);
10500 goto label_cached;
10501 }
10502 }
10503
10504 ptnstr = SDATA (pattern);
10505
10506 GCPRO2 (pattern, newlist);
10507
10508 /* Scan and matching bitmap fonts. */
10509 for (i = 0; i < font_name_count; i++)
10510 {
10511 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10512 {
10513 newlist = Fcons (build_string (font_name_table[i]), newlist);
10514
10515 n_fonts++;
10516 if (n_fonts >= maxnames)
10517 break;
10518 }
10519 }
10520
10521 /* MAC_TODO: add code for matching outline fonts here */
10522
10523 UNGCPRO;
10524
10525 if (dpyinfo)
10526 {
10527 XSETCDR (dpyinfo->name_list_element,
10528 Fcons (Fcons (key, newlist),
10529 XCDR (dpyinfo->name_list_element)));
10530 }
10531 label_cached:
10532
10533 return newlist;
10534 }
10535
10536
10537 #if GLYPH_DEBUG
10538
10539 /* Check that FONT is valid on frame F. It is if it can be found in F's
10540 font table. */
10541
10542 static void
10543 x_check_font (f, font)
10544 struct frame *f;
10545 XFontStruct *font;
10546 {
10547 int i;
10548 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10549
10550 xassert (font != NULL);
10551
10552 for (i = 0; i < dpyinfo->n_fonts; i++)
10553 if (dpyinfo->font_table[i].name
10554 && font == dpyinfo->font_table[i].font)
10555 break;
10556
10557 xassert (i < dpyinfo->n_fonts);
10558 }
10559
10560 #endif /* GLYPH_DEBUG != 0 */
10561
10562 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10563 Note: There are (broken) X fonts out there with invalid XFontStruct
10564 min_bounds contents. For example, handa@etl.go.jp reports that
10565 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10566 have font->min_bounds.width == 0. */
10567
10568 static INLINE void
10569 x_font_min_bounds (font, w, h)
10570 MacFontStruct *font;
10571 int *w, *h;
10572 {
10573 /*
10574 * TODO: Windows does not appear to offer min bound, only
10575 * average and maximum width, and maximum height.
10576 */
10577 *h = FONT_HEIGHT (font);
10578 *w = FONT_WIDTH (font);
10579 }
10580
10581
10582 /* Compute the smallest character width and smallest font height over
10583 all fonts available on frame F. Set the members smallest_char_width
10584 and smallest_font_height in F's x_display_info structure to
10585 the values computed. Value is non-zero if smallest_font_height or
10586 smallest_char_width become smaller than they were before. */
10587
10588 int
10589 x_compute_min_glyph_bounds (f)
10590 struct frame *f;
10591 {
10592 int i;
10593 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10594 MacFontStruct *font;
10595 int old_width = dpyinfo->smallest_char_width;
10596 int old_height = dpyinfo->smallest_font_height;
10597
10598 dpyinfo->smallest_font_height = 100000;
10599 dpyinfo->smallest_char_width = 100000;
10600
10601 for (i = 0; i < dpyinfo->n_fonts; ++i)
10602 if (dpyinfo->font_table[i].name)
10603 {
10604 struct font_info *fontp = dpyinfo->font_table + i;
10605 int w, h;
10606
10607 font = (MacFontStruct *) fontp->font;
10608 xassert (font != (MacFontStruct *) ~0);
10609 x_font_min_bounds (font, &w, &h);
10610
10611 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10612 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10613 }
10614
10615 xassert (dpyinfo->smallest_char_width > 0
10616 && dpyinfo->smallest_font_height > 0);
10617
10618 return (dpyinfo->n_fonts == 1
10619 || dpyinfo->smallest_char_width < old_width
10620 || dpyinfo->smallest_font_height < old_height);
10621 }
10622
10623
10624 /* Determine whether given string is a fully-specified XLFD: all 14
10625 fields are present, none is '*'. */
10626
10627 static int
10628 is_fully_specified_xlfd (char *p)
10629 {
10630 int i;
10631 char *q;
10632
10633 if (*p != '-')
10634 return 0;
10635
10636 for (i = 0; i < 13; i++)
10637 {
10638 q = strchr (p + 1, '-');
10639 if (q == NULL)
10640 return 0;
10641 if (q - p == 2 && *(p + 1) == '*')
10642 return 0;
10643 p = q;
10644 }
10645
10646 if (strchr (p + 1, '-') != NULL)
10647 return 0;
10648
10649 if (*(p + 1) == '*' && *(p + 2) == '\0')
10650 return 0;
10651
10652 return 1;
10653 }
10654
10655
10656 const int kDefaultFontSize = 9;
10657
10658
10659 /* XLoadQueryFont creates and returns an internal representation for a
10660 font in a MacFontStruct struct. There is really no concept
10661 corresponding to "loading" a font on the Mac. But we check its
10662 existence and find the font number and all other information for it
10663 and store them in the returned MacFontStruct. */
10664
10665 static MacFontStruct *
10666 XLoadQueryFont (Display *dpy, char *fontname)
10667 {
10668 int i, size, is_two_byte_font, char_width;
10669 char *name;
10670 GrafPtr port;
10671 SInt16 old_fontnum, old_fontsize;
10672 Style old_fontface;
10673 Str32 mfontname;
10674 SInt16 fontnum;
10675 Style fontface = normal;
10676 MacFontStruct *font;
10677 FontInfo the_fontinfo;
10678 char s_weight[7], c_slant;
10679
10680 if (is_fully_specified_xlfd (fontname))
10681 name = fontname;
10682 else
10683 {
10684 for (i = 0; i < font_name_count; i++)
10685 if (mac_font_pattern_match (font_name_table[i], fontname))
10686 break;
10687
10688 if (i >= font_name_count)
10689 return NULL;
10690
10691 name = font_name_table[i];
10692 }
10693
10694 GetPort (&port); /* save the current font number used */
10695 #if TARGET_API_MAC_CARBON
10696 old_fontnum = GetPortTextFont (port);
10697 old_fontsize = GetPortTextSize (port);
10698 old_fontface = GetPortTextFace (port);
10699 #else
10700 old_fontnum = port->txFont;
10701 old_fontsize = port->txSize;
10702 old_fontface = port->txFace;
10703 #endif
10704
10705 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
10706 size = kDefaultFontSize;
10707
10708 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
10709 if (strcmp (s_weight, "bold") == 0)
10710 fontface |= bold;
10711
10712 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
10713 if (c_slant == 'i')
10714 fontface |= italic;
10715
10716 x_font_name_to_mac_font_name (name, mfontname);
10717 c2pstr (mfontname);
10718 GetFNum (mfontname, &fontnum);
10719 if (fontnum == 0)
10720 return NULL;
10721
10722 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
10723
10724 font->fontname = (char *) xmalloc (strlen (name) + 1);
10725 bcopy (name, font->fontname, strlen (name) + 1);
10726
10727 font->mac_fontnum = fontnum;
10728 font->mac_fontsize = size;
10729 font->mac_fontface = fontface;
10730 font->mac_scriptcode = FontToScript (fontnum);
10731
10732 /* Apple Japanese (SJIS) font is listed as both
10733 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
10734 (Roman script) in init_font_name_table (). The latter should be
10735 treated as a one-byte font. */
10736 {
10737 char cs[32];
10738
10739 if (sscanf (name,
10740 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10741 cs) == 1
10742 && 0 == strcmp (cs, "jisx0201.1976-0"))
10743 font->mac_scriptcode = smRoman;
10744 }
10745
10746 is_two_byte_font = font->mac_scriptcode == smJapanese ||
10747 font->mac_scriptcode == smTradChinese ||
10748 font->mac_scriptcode == smSimpChinese ||
10749 font->mac_scriptcode == smKorean;
10750
10751 TextFont (fontnum);
10752 TextSize (size);
10753 TextFace (fontface);
10754
10755 GetFontInfo (&the_fontinfo);
10756
10757 font->ascent = the_fontinfo.ascent;
10758 font->descent = the_fontinfo.descent;
10759
10760 font->min_byte1 = 0;
10761 if (is_two_byte_font)
10762 font->max_byte1 = 1;
10763 else
10764 font->max_byte1 = 0;
10765 font->min_char_or_byte2 = 0x20;
10766 font->max_char_or_byte2 = 0xff;
10767
10768 if (is_two_byte_font)
10769 {
10770 /* Use the width of an "ideographic space" of that font because
10771 the_fontinfo.widMax returns the wrong width for some fonts. */
10772 switch (font->mac_scriptcode)
10773 {
10774 case smJapanese:
10775 char_width = StringWidth("\p\x81\x40");
10776 break;
10777 case smTradChinese:
10778 char_width = StringWidth("\p\xa1\x40");
10779 break;
10780 case smSimpChinese:
10781 char_width = StringWidth("\p\xa1\xa1");
10782 break;
10783 case smKorean:
10784 char_width = StringWidth("\p\xa1\xa1");
10785 break;
10786 }
10787 }
10788 else
10789 /* Do this instead of use the_fontinfo.widMax, which incorrectly
10790 returns 15 for 12-point Monaco! */
10791 char_width = CharWidth ('m');
10792
10793 font->max_bounds.rbearing = char_width;
10794 font->max_bounds.lbearing = 0;
10795 font->max_bounds.width = char_width;
10796 font->max_bounds.ascent = the_fontinfo.ascent;
10797 font->max_bounds.descent = the_fontinfo.descent;
10798
10799 font->min_bounds = font->max_bounds;
10800
10801 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
10802 font->per_char = NULL;
10803 else
10804 {
10805 font->per_char = (XCharStruct *)
10806 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
10807 {
10808 int c;
10809
10810 for (c = 0x20; c <= 0xff; c++)
10811 {
10812 font->per_char[c - 0x20] = font->max_bounds;
10813 font->per_char[c - 0x20].width = CharWidth (c);
10814 }
10815 }
10816 }
10817
10818 TextFont (old_fontnum); /* restore previous font number, size and face */
10819 TextSize (old_fontsize);
10820 TextFace (old_fontface);
10821
10822 return font;
10823 }
10824
10825
10826 /* Load font named FONTNAME of the size SIZE for frame F, and return a
10827 pointer to the structure font_info while allocating it dynamically.
10828 If SIZE is 0, load any size of font.
10829 If loading is failed, return NULL. */
10830
10831 struct font_info *
10832 x_load_font (f, fontname, size)
10833 struct frame *f;
10834 register char *fontname;
10835 int size;
10836 {
10837 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10838 Lisp_Object font_names;
10839
10840 /* Get a list of all the fonts that match this name. Once we
10841 have a list of matching fonts, we compare them against the fonts
10842 we already have by comparing names. */
10843 font_names = x_list_fonts (f, build_string (fontname), size, 1);
10844
10845 if (!NILP (font_names))
10846 {
10847 Lisp_Object tail;
10848 int i;
10849
10850 for (i = 0; i < dpyinfo->n_fonts; i++)
10851 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
10852 if (dpyinfo->font_table[i].name
10853 && (!strcmp (dpyinfo->font_table[i].name,
10854 SDATA (XCAR (tail)))
10855 || !strcmp (dpyinfo->font_table[i].full_name,
10856 SDATA (XCAR (tail)))))
10857 return (dpyinfo->font_table + i);
10858 }
10859
10860 /* Load the font and add it to the table. */
10861 {
10862 char *full_name;
10863 struct MacFontStruct *font;
10864 struct font_info *fontp;
10865 unsigned long value;
10866 int i;
10867
10868 /* If we have found fonts by x_list_font, load one of them. If
10869 not, we still try to load a font by the name given as FONTNAME
10870 because XListFonts (called in x_list_font) of some X server has
10871 a bug of not finding a font even if the font surely exists and
10872 is loadable by XLoadQueryFont. */
10873 if (size > 0 && !NILP (font_names))
10874 fontname = (char *) SDATA (XCAR (font_names));
10875
10876 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
10877 if (!font)
10878 return NULL;
10879
10880 /* Find a free slot in the font table. */
10881 for (i = 0; i < dpyinfo->n_fonts; ++i)
10882 if (dpyinfo->font_table[i].name == NULL)
10883 break;
10884
10885 /* If no free slot found, maybe enlarge the font table. */
10886 if (i == dpyinfo->n_fonts
10887 && dpyinfo->n_fonts == dpyinfo->font_table_size)
10888 {
10889 int sz;
10890 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
10891 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
10892 dpyinfo->font_table
10893 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
10894 }
10895
10896 fontp = dpyinfo->font_table + i;
10897 if (i == dpyinfo->n_fonts)
10898 ++dpyinfo->n_fonts;
10899
10900 /* Now fill in the slots of *FONTP. */
10901 BLOCK_INPUT;
10902 fontp->font = font;
10903 fontp->font_idx = i;
10904 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
10905 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
10906
10907 fontp->full_name = fontp->name;
10908
10909 fontp->size = font->max_bounds.width;
10910 fontp->height = FONT_HEIGHT (font);
10911 {
10912 /* For some font, ascent and descent in max_bounds field is
10913 larger than the above value. */
10914 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
10915 if (max_height > fontp->height)
10916 fontp->height = max_height;
10917 }
10918
10919 /* The slot `encoding' specifies how to map a character
10920 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
10921 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
10922 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
10923 2:0xA020..0xFF7F). For the moment, we don't know which charset
10924 uses this font. So, we set information in fontp->encoding[1]
10925 which is never used by any charset. If mapping can't be
10926 decided, set FONT_ENCODING_NOT_DECIDED. */
10927 if (font->mac_scriptcode == smJapanese)
10928 fontp->encoding[1] = 4;
10929 else
10930 {
10931 fontp->encoding[1]
10932 = (font->max_byte1 == 0
10933 /* 1-byte font */
10934 ? (font->min_char_or_byte2 < 0x80
10935 ? (font->max_char_or_byte2 < 0x80
10936 ? 0 /* 0x20..0x7F */
10937 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
10938 : 1) /* 0xA0..0xFF */
10939 /* 2-byte font */
10940 : (font->min_byte1 < 0x80
10941 ? (font->max_byte1 < 0x80
10942 ? (font->min_char_or_byte2 < 0x80
10943 ? (font->max_char_or_byte2 < 0x80
10944 ? 0 /* 0x2020..0x7F7F */
10945 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
10946 : 3) /* 0x20A0..0x7FFF */
10947 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
10948 : (font->min_char_or_byte2 < 0x80
10949 ? (font->max_char_or_byte2 < 0x80
10950 ? 2 /* 0xA020..0xFF7F */
10951 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
10952 : 1))); /* 0xA0A0..0xFFFF */
10953 }
10954
10955 #if 0 /* MAC_TODO: fill these out with more reasonably values */
10956 fontp->baseline_offset
10957 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
10958 ? (long) value : 0);
10959 fontp->relative_compose
10960 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
10961 ? (long) value : 0);
10962 fontp->default_ascent
10963 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
10964 ? (long) value : 0);
10965 #else
10966 fontp->baseline_offset = 0;
10967 fontp->relative_compose = 0;
10968 fontp->default_ascent = 0;
10969 #endif
10970
10971 /* Set global flag fonts_changed_p to non-zero if the font loaded
10972 has a character with a smaller width than any other character
10973 before, or if the font loaded has a smalle>r height than any
10974 other font loaded before. If this happens, it will make a
10975 glyph matrix reallocation necessary. */
10976 fonts_changed_p = x_compute_min_glyph_bounds (f);
10977 UNBLOCK_INPUT;
10978 return fontp;
10979 }
10980 }
10981
10982
10983 /* Return a pointer to struct font_info of a font named FONTNAME for
10984 frame F. If no such font is loaded, return NULL. */
10985
10986 struct font_info *
10987 x_query_font (f, fontname)
10988 struct frame *f;
10989 register char *fontname;
10990 {
10991 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10992 int i;
10993
10994 for (i = 0; i < dpyinfo->n_fonts; i++)
10995 if (dpyinfo->font_table[i].name
10996 && (!strcmp (dpyinfo->font_table[i].name, fontname)
10997 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
10998 return (dpyinfo->font_table + i);
10999 return NULL;
11000 }
11001
11002
11003 /* Find a CCL program for a font specified by FONTP, and set the member
11004 `encoder' of the structure. */
11005
11006 void
11007 x_find_ccl_program (fontp)
11008 struct font_info *fontp;
11009 {
11010 Lisp_Object list, elt;
11011
11012 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11013 {
11014 elt = XCAR (list);
11015 if (CONSP (elt)
11016 && STRINGP (XCAR (elt))
11017 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11018 >= 0))
11019 break;
11020 }
11021 if (! NILP (list))
11022 {
11023 struct ccl_program *ccl
11024 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11025
11026 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11027 xfree (ccl);
11028 else
11029 fontp->font_encoder = ccl;
11030 }
11031 }
11032
11033
11034 \f
11035 /***********************************************************************
11036 Initialization
11037 ***********************************************************************/
11038
11039 #ifdef USE_X_TOOLKIT
11040 static XrmOptionDescRec emacs_options[] = {
11041 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11042 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11043
11044 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11045 XrmoptionSepArg, NULL},
11046 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11047
11048 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11049 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11050 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11051 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11052 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11053 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11054 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11055 };
11056 #endif /* USE_X_TOOLKIT */
11057
11058 static int x_initialized;
11059
11060 #ifdef MULTI_KBOARD
11061 /* Test whether two display-name strings agree up to the dot that separates
11062 the screen number from the server number. */
11063 static int
11064 same_x_server (name1, name2)
11065 char *name1, *name2;
11066 {
11067 int seen_colon = 0;
11068 unsigned char *system_name = SDATA (Vsystem_name);
11069 int system_name_length = strlen (system_name);
11070 int length_until_period = 0;
11071
11072 while (system_name[length_until_period] != 0
11073 && system_name[length_until_period] != '.')
11074 length_until_period++;
11075
11076 /* Treat `unix' like an empty host name. */
11077 if (! strncmp (name1, "unix:", 5))
11078 name1 += 4;
11079 if (! strncmp (name2, "unix:", 5))
11080 name2 += 4;
11081 /* Treat this host's name like an empty host name. */
11082 if (! strncmp (name1, system_name, system_name_length)
11083 && name1[system_name_length] == ':')
11084 name1 += system_name_length;
11085 if (! strncmp (name2, system_name, system_name_length)
11086 && name2[system_name_length] == ':')
11087 name2 += system_name_length;
11088 /* Treat this host's domainless name like an empty host name. */
11089 if (! strncmp (name1, system_name, length_until_period)
11090 && name1[length_until_period] == ':')
11091 name1 += length_until_period;
11092 if (! strncmp (name2, system_name, length_until_period)
11093 && name2[length_until_period] == ':')
11094 name2 += length_until_period;
11095
11096 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11097 {
11098 if (*name1 == ':')
11099 seen_colon++;
11100 if (seen_colon && *name1 == '.')
11101 return 1;
11102 }
11103 return (seen_colon
11104 && (*name1 == '.' || *name1 == '\0')
11105 && (*name2 == '.' || *name2 == '\0'));
11106 }
11107 #endif
11108
11109
11110 /* The Mac Event loop code */
11111
11112 #ifndef MAC_OSX
11113 #include <Events.h>
11114 #include <Quickdraw.h>
11115 #include <Balloons.h>
11116 #include <Devices.h>
11117 #include <Fonts.h>
11118 #include <Gestalt.h>
11119 #include <Menus.h>
11120 #include <Processes.h>
11121 #include <Sound.h>
11122 #include <ToolUtils.h>
11123 #include <TextUtils.h>
11124 #include <Dialogs.h>
11125 #include <Script.h>
11126 #include <Types.h>
11127 #include <TextEncodingConverter.h>
11128 #include <Resources.h>
11129
11130 #if __MWERKS__
11131 #include <unix.h>
11132 #endif
11133 #endif /* ! MAC_OSX */
11134
11135 #define M_APPLE 128
11136 #define I_ABOUT 1
11137
11138 #define WINDOW_RESOURCE 128
11139 #define TERM_WINDOW_RESOURCE 129
11140
11141 #define DEFAULT_NUM_COLS 80
11142
11143 #define MIN_DOC_SIZE 64
11144 #define MAX_DOC_SIZE 32767
11145
11146 /* sleep time for WaitNextEvent */
11147 #define WNE_SLEEP_AT_SUSPEND 10
11148 #define WNE_SLEEP_AT_RESUME 1
11149
11150 /* true when cannot handle any Mac OS events */
11151 static int handling_window_update = 0;
11152
11153 /* the flag appl_is_suspended is used both for determining the sleep
11154 time to be passed to WaitNextEvent and whether the cursor should be
11155 drawn when updating the display. The cursor is turned off when
11156 Emacs is suspended. Redrawing it is unnecessary and what needs to
11157 be done depends on whether the cursor lies inside or outside the
11158 redraw region. So we might as well skip drawing it when Emacs is
11159 suspended. */
11160 static Boolean app_is_suspended = false;
11161 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11162
11163 #define EXTRA_STACK_ALLOC (256 * 1024)
11164
11165 #define ARGV_STRING_LIST_ID 129
11166 #define ABOUT_ALERT_ID 128
11167 #define RAM_TOO_LARGE_ALERT_ID 129
11168
11169 Boolean terminate_flag = false;
11170
11171 /* True if using command key as meta key. */
11172 Lisp_Object Vmac_command_key_is_meta;
11173
11174 /* True if the ctrl and meta keys should be reversed. */
11175 Lisp_Object Vmac_reverse_ctrl_meta;
11176
11177 #if USE_CARBON_EVENTS
11178 /* True if the mouse wheel button (i.e. button 4) should map to
11179 mouse-2, instead of mouse-3. */
11180 Lisp_Object Vmac_wheel_button_is_mouse_2;
11181
11182 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
11183 for processing before Emacs sees it. */
11184 Lisp_Object Vmac_pass_command_to_system;
11185
11186 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
11187 for processing before Emacs sees it. */
11188 Lisp_Object Vmac_pass_control_to_system;
11189 #endif
11190
11191 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11192 to this text encoding */
11193 int mac_keyboard_text_encoding;
11194 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11195
11196 /* Set in term/mac-win.el to indicate that event loop can now generate
11197 drag and drop events. */
11198 Lisp_Object Qmac_ready_for_drag_n_drop;
11199
11200 Lisp_Object drag_and_drop_file_list;
11201
11202 Point saved_menu_event_location;
11203
11204 /* Apple Events */
11205 static void init_required_apple_events (void);
11206 static pascal OSErr
11207 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
11208 static pascal OSErr
11209 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
11210 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
11211 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
11212
11213 /* Drag and Drop */
11214 static OSErr init_mac_drag_n_drop ();
11215 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
11216
11217 #if USE_CARBON_EVENTS
11218 /* Preliminary Support for the OSX Services Menu */
11219 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
11220 static void init_service_handler ();
11221 #endif
11222
11223 extern void init_emacs_passwd_dir ();
11224 extern int emacs_main (int, char **, char **);
11225 extern void check_alarm ();
11226
11227 extern void initialize_applescript();
11228 extern void terminate_applescript();
11229
11230 static unsigned int
11231 #if USE_CARBON_EVENTS
11232 mac_to_emacs_modifiers (UInt32 mods)
11233 #else
11234 mac_to_emacs_modifiers (EventModifiers mods)
11235 #endif
11236 {
11237 unsigned int result = 0;
11238 if (mods & macShiftKey)
11239 result |= shift_modifier;
11240 if (mods & macCtrlKey)
11241 result |= ctrl_modifier;
11242 if (mods & macMetaKey)
11243 result |= meta_modifier;
11244 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
11245 result |= alt_modifier;
11246 return result;
11247 }
11248
11249 #if USE_CARBON_EVENTS
11250 /* Obtains the event modifiers from the event ref and then calls
11251 mac_to_emacs_modifiers. */
11252 static int
11253 mac_event_to_emacs_modifiers (EventRef eventRef)
11254 {
11255 UInt32 mods = 0;
11256 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
11257 sizeof (UInt32), NULL, &mods);
11258 return mac_to_emacs_modifiers (mods);
11259 }
11260
11261 /* Given an event ref, return the code to use for the mouse button
11262 code in the emacs input_event. */
11263 static int
11264 mac_get_mouse_btn (EventRef ref)
11265 {
11266 EventMouseButton result = kEventMouseButtonPrimary;
11267 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
11268 sizeof (EventMouseButton), NULL, &result);
11269 switch (result)
11270 {
11271 case kEventMouseButtonPrimary:
11272 return 0;
11273 case kEventMouseButtonSecondary:
11274 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
11275 case kEventMouseButtonTertiary:
11276 case 4: /* 4 is the number for the mouse wheel button */
11277 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
11278 default:
11279 return 0;
11280 }
11281 }
11282
11283 /* Normally, ConvertEventRefToEventRecord will correctly handle all
11284 events. However the click of the mouse wheel is not converted to a
11285 mouseDown or mouseUp event. This calls ConvertEventRef, but then
11286 checks to see if it is a mouse up or down carbon event that has not
11287 been converted, and if so, converts it by hand (to be picked up in
11288 the XTread_socket loop). */
11289 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
11290 {
11291 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
11292 /* Do special case for mouse wheel button. */
11293 if (!result && GetEventClass (eventRef) == kEventClassMouse)
11294 {
11295 UInt32 kind = GetEventKind (eventRef);
11296 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
11297 {
11298 eventRec->what = mouseDown;
11299 result=1;
11300 }
11301 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
11302 {
11303 eventRec->what = mouseUp;
11304 result=1;
11305 }
11306 if (result)
11307 {
11308 /* Need where and when. */
11309 UInt32 mods;
11310 GetEventParameter (eventRef, kEventParamMouseLocation,
11311 typeQDPoint, NULL, sizeof (Point),
11312 NULL, &eventRec->where);
11313 /* Use two step process because new event modifiers are
11314 32-bit and old are 16-bit. Currently, only loss is
11315 NumLock & Fn. */
11316 GetEventParameter (eventRef, kEventParamKeyModifiers,
11317 typeUInt32, NULL, sizeof (UInt32),
11318 NULL, &mods);
11319 eventRec->modifiers = mods;
11320
11321 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
11322 }
11323 }
11324 return result;
11325 }
11326
11327 #endif
11328
11329 static void
11330 do_get_menus (void)
11331 {
11332 Handle menubar_handle;
11333 MenuHandle menu_handle;
11334
11335 menubar_handle = GetNewMBar (128);
11336 if(menubar_handle == NULL)
11337 abort ();
11338 SetMenuBar (menubar_handle);
11339 DrawMenuBar ();
11340
11341 menu_handle = GetMenuHandle (M_APPLE);
11342 if(menu_handle != NULL)
11343 AppendResMenu (menu_handle,'DRVR');
11344 else
11345 abort ();
11346 }
11347
11348
11349 static void
11350 do_init_managers (void)
11351 {
11352 #if !TARGET_API_MAC_CARBON
11353 InitGraf (&qd.thePort);
11354 InitFonts ();
11355 FlushEvents (everyEvent, 0);
11356 InitWindows ();
11357 InitMenus ();
11358 TEInit ();
11359 InitDialogs (NULL);
11360 #endif /* !TARGET_API_MAC_CARBON */
11361 InitCursor ();
11362
11363 #if !TARGET_API_MAC_CARBON
11364 /* set up some extra stack space for use by emacs */
11365 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11366
11367 /* MaxApplZone must be called for AppleScript to execute more
11368 complicated scripts */
11369 MaxApplZone ();
11370 MoreMasters ();
11371 #endif /* !TARGET_API_MAC_CARBON */
11372 }
11373
11374 static void
11375 do_check_ram_size (void)
11376 {
11377 SInt32 physical_ram_size, logical_ram_size;
11378
11379 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11380 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11381 || physical_ram_size > 256 * 1024 * 1024
11382 || logical_ram_size > 256 * 1024 * 1024)
11383 {
11384 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11385 exit (1);
11386 }
11387 }
11388
11389 static void
11390 do_window_update (WindowPtr win)
11391 {
11392 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11393 struct frame *f = mwp->mFP;
11394
11395 if (f)
11396 {
11397 if (f->async_visible == 0)
11398 {
11399 f->async_visible = 1;
11400 f->async_iconified = 0;
11401 SET_FRAME_GARBAGED (f);
11402
11403 /* An update event is equivalent to MapNotify on X, so report
11404 visibility changes properly. */
11405 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11406 /* Force a redisplay sooner or later to update the
11407 frame titles in case this is the second frame. */
11408 record_asynch_buffer_change ();
11409 }
11410 else
11411 {
11412 BeginUpdate (win);
11413 handling_window_update = 1;
11414
11415 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
11416
11417 expose_frame (f, 0, 0, 0, 0);
11418
11419 handling_window_update = 0;
11420 EndUpdate (win);
11421 }
11422 }
11423 }
11424
11425 static int
11426 is_emacs_window (WindowPtr win)
11427 {
11428 Lisp_Object tail, frame;
11429
11430 if (!win)
11431 return 0;
11432
11433 FOR_EACH_FRAME (tail, frame)
11434 if (FRAME_MAC_P (XFRAME (frame)))
11435 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11436 return 1;
11437
11438 return 0;
11439 }
11440
11441 static void
11442 do_window_activate (WindowPtr win)
11443 {
11444 mac_output *mwp;
11445 struct frame *f;
11446
11447 if (is_emacs_window (win))
11448 {
11449 mwp = (mac_output *) GetWRefCon (win);
11450 f = mwp->mFP;
11451
11452 if (f)
11453 {
11454 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11455 activate_scroll_bars (f);
11456 }
11457 }
11458 }
11459
11460 static void
11461 do_window_deactivate (WindowPtr win)
11462 {
11463 mac_output *mwp;
11464 struct frame *f;
11465
11466 if (is_emacs_window (win))
11467 {
11468 mwp = (mac_output *) GetWRefCon (win);
11469 f = mwp->mFP;
11470
11471 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11472 {
11473 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11474 deactivate_scroll_bars (f);
11475 }
11476 }
11477 }
11478
11479 static void
11480 do_app_resume ()
11481 {
11482 WindowPtr wp;
11483 mac_output *mwp;
11484 struct frame *f;
11485
11486 wp = FrontWindow();
11487 if (is_emacs_window (wp))
11488 {
11489 mwp = (mac_output *) GetWRefCon (wp);
11490 f = mwp->mFP;
11491
11492 if (f)
11493 {
11494 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11495 activate_scroll_bars (f);
11496 }
11497 }
11498
11499 app_is_suspended = false;
11500 app_sleep_time = WNE_SLEEP_AT_RESUME;
11501 }
11502
11503 static void
11504 do_app_suspend ()
11505 {
11506 WindowPtr wp;
11507 mac_output *mwp;
11508 struct frame *f;
11509
11510 wp = FrontWindow();
11511 if (is_emacs_window (wp))
11512 {
11513 mwp = (mac_output *) GetWRefCon (wp);
11514 f = mwp->mFP;
11515
11516 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11517 {
11518 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11519 deactivate_scroll_bars (f);
11520 }
11521 }
11522
11523 app_is_suspended = true;
11524 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11525 }
11526
11527
11528 static void
11529 do_mouse_moved (Point mouse_pos)
11530 {
11531 WindowPtr wp = FrontWindow ();
11532 struct frame *f;
11533
11534 if (is_emacs_window (wp))
11535 {
11536 f = ((mac_output *) GetWRefCon (wp))->mFP;
11537
11538 #if TARGET_API_MAC_CARBON
11539 SetPort (GetWindowPort (wp));
11540 #else
11541 SetPort (wp);
11542 #endif
11543
11544 GlobalToLocal (&mouse_pos);
11545
11546 note_mouse_movement (f, &mouse_pos);
11547 }
11548 }
11549
11550
11551 static void
11552 do_os_event (EventRecord *erp)
11553 {
11554 switch((erp->message >> 24) & 0x000000FF)
11555 {
11556 case suspendResumeMessage:
11557 if((erp->message & resumeFlag) == 1)
11558 do_app_resume ();
11559 else
11560 do_app_suspend ();
11561 break;
11562
11563 case mouseMovedMessage:
11564 do_mouse_moved (erp->where);
11565 break;
11566 }
11567 }
11568
11569 static void
11570 do_events (EventRecord *erp)
11571 {
11572 switch (erp->what)
11573 {
11574 case updateEvt:
11575 do_window_update ((WindowPtr) erp->message);
11576 break;
11577
11578 case osEvt:
11579 do_os_event (erp);
11580 break;
11581
11582 case activateEvt:
11583 if ((erp->modifiers & activeFlag) != 0)
11584 do_window_activate ((WindowPtr) erp->message);
11585 else
11586 do_window_deactivate ((WindowPtr) erp->message);
11587 break;
11588 }
11589 }
11590
11591 static void
11592 do_apple_menu (SInt16 menu_item)
11593 {
11594 #if !TARGET_API_MAC_CARBON
11595 Str255 item_name;
11596 SInt16 da_driver_refnum;
11597
11598 if (menu_item == I_ABOUT)
11599 NoteAlert (ABOUT_ALERT_ID, NULL);
11600 else
11601 {
11602 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11603 da_driver_refnum = OpenDeskAcc (item_name);
11604 }
11605 #endif /* !TARGET_API_MAC_CARBON */
11606 }
11607
11608 void
11609 do_menu_choice (SInt32 menu_choice)
11610 {
11611 SInt16 menu_id, menu_item;
11612
11613 menu_id = HiWord (menu_choice);
11614 menu_item = LoWord (menu_choice);
11615
11616 if (menu_id == 0)
11617 return;
11618
11619 switch (menu_id)
11620 {
11621 case M_APPLE:
11622 do_apple_menu (menu_item);
11623 break;
11624
11625 default:
11626 {
11627 WindowPtr wp = FrontWindow ();
11628 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11629 MenuHandle menu = GetMenuHandle (menu_id);
11630 if (menu)
11631 {
11632 UInt32 refcon;
11633
11634 GetMenuItemRefCon (menu, menu_item, &refcon);
11635 menubar_selection_callback (f, refcon);
11636 }
11637 }
11638 }
11639
11640 HiliteMenu (0);
11641 }
11642
11643
11644 /* Handle drags in size box. Based on code contributed by Ben
11645 Mesander and IM - Window Manager A. */
11646
11647 static void
11648 do_grow_window (WindowPtr w, EventRecord *e)
11649 {
11650 long grow_size;
11651 Rect limit_rect;
11652 int rows, columns;
11653 mac_output *mwp = (mac_output *) GetWRefCon (w);
11654 struct frame *f = mwp->mFP;
11655
11656 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11657
11658 grow_size = GrowWindow (w, e->where, &limit_rect);
11659
11660 /* see if it really changed size */
11661 if (grow_size != 0)
11662 {
11663 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11664 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11665
11666 x_set_window_size (f, 0, columns, rows);
11667 }
11668 }
11669
11670
11671 /* Handle clicks in zoom box. Calculation of "standard state" based
11672 on code in IM - Window Manager A and code contributed by Ben
11673 Mesander. The standard state of an Emacs window is 80-characters
11674 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11675
11676 static void
11677 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11678 {
11679 GrafPtr save_port;
11680 Rect zoom_rect, port_rect;
11681 Point top_left;
11682 int w_title_height, columns, rows, width, height, dummy, x, y;
11683 mac_output *mwp = (mac_output *) GetWRefCon (w);
11684 struct frame *f = mwp->mFP;
11685
11686 GetPort (&save_port);
11687
11688 #if TARGET_API_MAC_CARBON
11689 SetPort (GetWindowPort (w));
11690 #else
11691 SetPort (w);
11692 #endif
11693
11694 /* Clear window to avoid flicker. */
11695 #if TARGET_API_MAC_CARBON
11696 {
11697 Rect r;
11698 BitMap bm;
11699
11700 GetWindowPortBounds (w, &r);
11701 EraseRect (&r);
11702
11703 if (zoom_in_or_out == inZoomOut)
11704 {
11705 /* calculate height of window's title bar (hard card it for now). */
11706 w_title_height = 20 + GetMBarHeight ();
11707
11708 /* get maximum height of window into zoom_rect.bottom -
11709 zoom_rect.top */
11710 GetQDGlobalsScreenBits (&bm);
11711 zoom_rect = bm.bounds;
11712 zoom_rect.top += w_title_height;
11713 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11714
11715 zoom_rect.right = zoom_rect.left
11716 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11717
11718 SetWindowStandardState (w, &zoom_rect);
11719 }
11720 }
11721 #else /* not TARGET_API_MAC_CARBON */
11722 EraseRect (&(w->portRect));
11723 if (zoom_in_or_out == inZoomOut)
11724 {
11725 SetPt (&top_left, w->portRect.left, w->portRect.top);
11726 LocalToGlobal (&top_left);
11727
11728 /* calculate height of window's title bar */
11729 w_title_height = top_left.v - 1
11730 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
11731
11732 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
11733 zoom_rect = qd.screenBits.bounds;
11734 zoom_rect.top += w_title_height;
11735 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11736
11737 zoom_rect.right = zoom_rect.left
11738 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11739
11740 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
11741 = zoom_rect;
11742 }
11743 #endif /* not TARGET_API_MAC_CARBON */
11744
11745 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
11746
11747 /* retrieve window size and update application values */
11748 #if TARGET_API_MAC_CARBON
11749 GetWindowPortBounds (w, &port_rect);
11750 #else
11751 port_rect = w->portRect;
11752 #endif
11753 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
11754 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
11755 x_set_window_size (mwp->mFP, 0, columns, rows);
11756
11757 SetPort (save_port);
11758 }
11759
11760 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
11761 static OSErr
11762 init_mac_drag_n_drop ()
11763 {
11764 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
11765 return result;
11766 }
11767
11768 /* Intialize AppleEvent dispatcher table for the required events. */
11769 void
11770 init_required_apple_events ()
11771 {
11772 OSErr err;
11773 long result;
11774
11775 /* Make sure we have apple events before starting. */
11776 err = Gestalt (gestaltAppleEventsAttr, &result);
11777 if (err != noErr)
11778 abort ();
11779
11780 if (!(result & (1 << gestaltAppleEventsPresent)))
11781 abort ();
11782
11783 #if TARGET_API_MAC_CARBON
11784 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
11785 NewAEEventHandlerUPP
11786 ((AEEventHandlerProcPtr) do_ae_open_application),
11787 0L, false);
11788 #else
11789 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
11790 NewAEEventHandlerProc
11791 ((AEEventHandlerProcPtr) do_ae_open_application),
11792 0L, false);
11793 #endif
11794 if (err != noErr)
11795 abort ();
11796
11797 #if TARGET_API_MAC_CARBON
11798 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
11799 NewAEEventHandlerUPP
11800 ((AEEventHandlerProcPtr) do_ae_open_documents),
11801 0L, false);
11802 #else
11803 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
11804 NewAEEventHandlerProc
11805 ((AEEventHandlerProcPtr) do_ae_open_documents),
11806 0L, false);
11807 #endif
11808 if (err != noErr)
11809 abort ();
11810
11811 #if TARGET_API_MAC_CARBON
11812 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
11813 NewAEEventHandlerUPP
11814 ((AEEventHandlerProcPtr) do_ae_print_documents),
11815 0L, false);
11816 #else
11817 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
11818 NewAEEventHandlerProc
11819 ((AEEventHandlerProcPtr) do_ae_print_documents),
11820 0L, false);
11821 #endif
11822 if (err != noErr)
11823 abort ();
11824
11825 #if TARGET_API_MAC_CARBON
11826 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
11827 NewAEEventHandlerUPP
11828 ((AEEventHandlerProcPtr) do_ae_quit_application),
11829 0L, false);
11830 #else
11831 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
11832 NewAEEventHandlerProc
11833 ((AEEventHandlerProcPtr) do_ae_quit_application),
11834 0L, false);
11835 #endif
11836 if (err != noErr)
11837 abort ();
11838 }
11839
11840 #if USE_CARBON_EVENTS
11841
11842 void
11843 init_service_handler ()
11844 {
11845 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
11846 {kEventClassService, kEventServiceCopy},
11847 {kEventClassService, kEventServicePaste}};
11848 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
11849 3, specs, NULL, NULL);
11850 }
11851
11852 /*
11853 MAC_TODO: Check to see if this is called by AEProcessDesc...
11854 */
11855 OSStatus
11856 mac_handle_service_event (EventHandlerCallRef callRef,
11857 EventRef event, void *data)
11858 {
11859 OSStatus err = noErr;
11860 switch (GetEventKind (event))
11861 {
11862 case kEventServiceGetTypes:
11863 {
11864 CFMutableArrayRef copyTypes, pasteTypes;
11865 CFStringRef type;
11866 Boolean selection = true;
11867 /*
11868 GetEventParameter(event, kEventParamServicePasteTypes,
11869 typeCFMutableArrayRef, NULL,
11870 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
11871 */
11872 GetEventParameter(event, kEventParamServiceCopyTypes,
11873 typeCFMutableArrayRef, NULL,
11874 sizeof (CFMutableArrayRef), NULL, &copyTypes);
11875 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
11876 if (type) {
11877 CFArrayAppendValue (copyTypes, type);
11878 //CFArrayAppendValue (pasteTypes, type);
11879 CFRelease (type);
11880 }
11881 }
11882 case kEventServiceCopy:
11883 {
11884 ScrapRef currentScrap, specificScrap;
11885 char * buf = "";
11886 Size byteCount = 0;
11887
11888 GetCurrentScrap (&currentScrap);
11889
11890 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
11891 if (err == noErr)
11892 {
11893 void *buffer = xmalloc (byteCount);
11894 if (buffer != NULL)
11895 {
11896 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
11897 sizeof (ScrapRef), NULL, &specificScrap);
11898
11899 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
11900 &byteCount, buffer);
11901 if (err == noErr)
11902 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
11903 kScrapFlavorMaskNone, byteCount, buffer);
11904 xfree (buffer);
11905 }
11906 }
11907 err = noErr;
11908 }
11909 case kEventServicePaste:
11910 {
11911 /*
11912 // Get the current location
11913 Size byteCount;
11914 ScrapRef specificScrap;
11915 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
11916 sizeof(ScrapRef), NULL, &specificScrap);
11917 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
11918 if (err == noErr) {
11919 void * buffer = xmalloc(byteCount);
11920 if (buffer != NULL ) {
11921 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
11922 &byteCount, buffer);
11923 if (err == noErr) {
11924 // Actually place in the buffer
11925 BLOCK_INPUT;
11926 // Get the current "selection" string here
11927 UNBLOCK_INPUT;
11928 }
11929 }
11930 xfree(buffer);
11931 }
11932 */
11933 }
11934 }
11935 return err;
11936 }
11937 #endif
11938
11939 /* Open Application Apple Event */
11940 static pascal OSErr
11941 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
11942 {
11943 return noErr;
11944 }
11945
11946
11947 /* Defined in mac.c. */
11948 extern int
11949 path_from_vol_dir_name (char *, int, short, long, char *);
11950
11951
11952 /* Called when we receive an AppleEvent with an ID of
11953 "kAEOpenDocuments". This routine gets the direct parameter,
11954 extracts the FSSpecs in it, and puts their names on a list. */
11955 static pascal OSErr
11956 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
11957 {
11958 OSErr err, err2;
11959 AEDesc the_desc;
11960 AEKeyword keyword;
11961 DescType actual_type;
11962 Size actual_size;
11963
11964 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
11965 if (err != noErr)
11966 goto descriptor_error_exit;
11967
11968 /* Check to see that we got all of the required parameters from the
11969 event descriptor. For an 'odoc' event this should just be the
11970 file list. */
11971 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
11972 &actual_type, (Ptr) &keyword,
11973 sizeof (keyword), &actual_size);
11974 /* No error means that we found some unused parameters.
11975 errAEDescNotFound means that there are no more parameters. If we
11976 get an error code other than that, flag it. */
11977 if ((err == noErr) || (err != errAEDescNotFound))
11978 {
11979 err = errAEEventNotHandled;
11980 goto error_exit;
11981 }
11982 err = noErr;
11983
11984 /* Got all the parameters we need. Now, go through the direct
11985 object list and parse it up. */
11986 {
11987 long num_files_to_open;
11988
11989 err = AECountItems (&the_desc, &num_files_to_open);
11990 if (err == noErr)
11991 {
11992 int i;
11993
11994 /* AE file list is one based so just use that for indexing here. */
11995 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
11996 {
11997 FSSpec fs;
11998 Str255 path_name, unix_path_name;
11999 #ifdef MAC_OSX
12000 FSRef fref;
12001 #endif
12002
12003 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12004 (Ptr) &fs, sizeof (fs), &actual_size);
12005 if (err != noErr) break;
12006
12007 #ifdef MAC_OSX
12008 err = FSpMakeFSRef (&fs, &fref);
12009 if (err != noErr) break;
12010
12011 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12012 #else
12013 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12014 fs.name) &&
12015 mac_to_posix_pathname (path_name, unix_path_name, 255))
12016 #endif
12017 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12018 drag_and_drop_file_list);
12019 }
12020 }
12021 }
12022
12023 error_exit:
12024 /* Nuke the coerced file list in any case */
12025 err2 = AEDisposeDesc(&the_desc);
12026
12027 descriptor_error_exit:
12028 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12029 return err;
12030 }
12031
12032
12033 static pascal OSErr
12034 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
12035 DragReference theDrag)
12036 {
12037 short items;
12038 short index;
12039 FlavorFlags theFlags;
12040 Point mouse;
12041 OSErr result;
12042 ItemReference theItem;
12043 HFSFlavor data;
12044 FSRef fref;
12045 Size size = sizeof (HFSFlavor);
12046
12047 drag_and_drop_file_list = Qnil;
12048 GetDragMouse (theDrag, &mouse, 0L);
12049 CountDragItems (theDrag, &items);
12050 for (index = 1; index <= items; index++)
12051 {
12052 /* Only handle file references. */
12053 GetDragItemReferenceNumber (theDrag, index, &theItem);
12054 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
12055 if (result == noErr)
12056 {
12057 #ifdef MAC_OSX
12058 FSRef frref;
12059 #else
12060 Str255 path_name;
12061 #endif
12062 Str255 unix_path_name;
12063 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
12064 #ifdef MAC_OSX
12065 /* Use Carbon routines, otherwise it converts the file name
12066 to /Macintosh HD/..., which is not correct. */
12067 FSpMakeFSRef (&data.fileSpec, &fref);
12068 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
12069 #else
12070 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
12071 data.fileSpec.parID, data.fileSpec.name) &&
12072 mac_to_posix_pathname (path_name, unix_path_name, 255))
12073 #endif
12074 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12075 drag_and_drop_file_list);
12076 }
12077 else
12078 return;
12079 }
12080 /* If there are items in the list, construct an event and post it to
12081 the queue like an interrupt using kbd_buffer_store_event. */
12082 if (!NILP (drag_and_drop_file_list))
12083 {
12084 struct input_event event;
12085 Lisp_Object frame;
12086 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
12087 SetPort (GetWindowPort (window));
12088 GlobalToLocal (&mouse);
12089
12090 event.kind = DRAG_N_DROP_EVENT;
12091 event.code = 0;
12092 event.modifiers = 0;
12093 event.timestamp = TickCount () * (1000 / 60);
12094 XSETINT (event.x, mouse.h);
12095 XSETINT (event.y, mouse.v);
12096 XSETFRAME (frame, f);
12097 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
12098 event.arg = Qnil;
12099 /* Post to the interrupt queue */
12100 kbd_buffer_store_event (&event);
12101 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
12102 {
12103 ProcessSerialNumber psn;
12104 GetCurrentProcess (&psn);
12105 SetFrontProcess (&psn);
12106 }
12107 }
12108 }
12109
12110
12111 /* Print Document Apple Event */
12112 static pascal OSErr
12113 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12114 {
12115 return errAEEventNotHandled;
12116 }
12117
12118
12119 static pascal OSErr
12120 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12121 {
12122 /* FixMe: Do we need an unwind-protect or something here? And what
12123 do we do about unsaved files. Currently just forces quit rather
12124 than doing recursive callback to get user input. */
12125
12126 terminate_flag = true;
12127
12128 /* Fkill_emacs doesn't return. We have to return. (TI) */
12129 return noErr;
12130 }
12131
12132
12133 #if __profile__
12134 void
12135 profiler_exit_proc ()
12136 {
12137 ProfilerDump ("\pEmacs.prof");
12138 ProfilerTerm ();
12139 }
12140 #endif
12141
12142 /* These few functions implement Emacs as a normal Mac application
12143 (almost): set up the heap and the Toolbox, handle necessary
12144 system events plus a few simple menu events. They also set up
12145 Emacs's access to functions defined in the rest of this file.
12146 Emacs uses function hooks to perform all its terminal I/O. A
12147 complete list of these functions appear in termhooks.h. For what
12148 they do, read the comments there and see also w32term.c and
12149 xterm.c. What's noticeably missing here is the event loop, which
12150 is normally present in most Mac application. After performing the
12151 necessary Mac initializations, main passes off control to
12152 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12153 mac_read_socket (defined further below) to read input. This is
12154 where WaitNextEvent is called to process Mac events. This is also
12155 where check_alarm in sysdep.c is called to simulate alarm signals.
12156 This makes the cursor jump back to its correct position after
12157 briefly jumping to that of the matching parenthesis, print useful
12158 hints and prompts in the minibuffer after the user stops typing for
12159 a wait, etc. */
12160
12161 #if !TARGET_API_MAC_CARBON
12162 #undef main
12163 int
12164 main (void)
12165 {
12166 #if __profile__ /* is the profiler on? */
12167 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12168 exit(1);
12169 #endif
12170
12171 #if __MWERKS__
12172 /* set creator and type for files created by MSL */
12173 _fcreator = 'EMAx';
12174 _ftype = 'TEXT';
12175 #endif
12176
12177 do_init_managers ();
12178
12179 do_get_menus ();
12180
12181 do_check_ram_size ();
12182
12183 init_emacs_passwd_dir ();
12184
12185 init_environ ();
12186
12187 initialize_applescript ();
12188
12189 init_required_apple_events ();
12190
12191 {
12192 char **argv;
12193 int argc = 0;
12194
12195 /* set up argv array from STR# resource */
12196 get_string_list (&argv, ARGV_STRING_LIST_ID);
12197 while (argv[argc])
12198 argc++;
12199
12200 /* free up AppleScript resources on exit */
12201 atexit (terminate_applescript);
12202
12203 #if __profile__ /* is the profiler on? */
12204 atexit (profiler_exit_proc);
12205 #endif
12206
12207 /* 3rd param "envp" never used in emacs_main */
12208 (void) emacs_main (argc, argv, 0);
12209 }
12210
12211 /* Never reached - real exit in Fkill_emacs */
12212 return 0;
12213 }
12214 #endif
12215
12216 /* Table for translating Mac keycode to X keysym values. Contributed
12217 by Sudhir Shenoy. */
12218 static unsigned char keycode_to_xkeysym_table[] = {
12219 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12220 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12221 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12222
12223 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
12224 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
12225 /*0x38*/ 0, 0, 0, 0,
12226 /*0x3C*/ 0, 0, 0, 0,
12227
12228 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
12229 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
12230 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
12231 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
12232
12233 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
12234 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
12235 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
12236 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
12237
12238 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
12239 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
12240 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
12241 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
12242
12243 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
12244 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
12245 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
12246 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
12247 };
12248
12249 static int
12250 keycode_to_xkeysym (int keyCode, int *xKeySym)
12251 {
12252 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12253 return *xKeySym != 0;
12254 }
12255
12256 /* Emacs calls this whenever it wants to read an input event from the
12257 user. */
12258 int
12259 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12260 {
12261 int count = 0;
12262 #if USE_CARBON_EVENTS
12263 OSStatus rneResult;
12264 EventRef eventRef;
12265 EventMouseButton mouseBtn;
12266 #endif
12267 EventRecord er;
12268 int the_modifiers;
12269 EventMask event_mask;
12270
12271 #if 0
12272 if (interrupt_input_blocked)
12273 {
12274 interrupt_input_pending = 1;
12275 return -1;
12276 }
12277 #endif
12278
12279 interrupt_input_pending = 0;
12280 BLOCK_INPUT;
12281
12282 /* So people can tell when we have read the available input. */
12283 input_signal_count++;
12284
12285 if (numchars <= 0)
12286 abort ();
12287
12288 /* Don't poll for events to process (specifically updateEvt) if
12289 window update currently already in progress. A call to redisplay
12290 (in do_window_update) can be preempted by another call to
12291 redisplay, causing blank regions to be left on the screen and the
12292 cursor to be left at strange places. */
12293 if (handling_window_update)
12294 {
12295 UNBLOCK_INPUT;
12296 return 0;
12297 }
12298
12299 if (terminate_flag)
12300 Fkill_emacs (make_number (1));
12301
12302 /* It is necessary to set this (additional) argument slot of an
12303 event to nil because keyboard.c protects incompletely processed
12304 event from being garbage collected by placing them in the
12305 kbd_buffer_gcpro vector. */
12306 bufp->arg = Qnil;
12307
12308 event_mask = everyEvent;
12309 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
12310 event_mask -= highLevelEventMask;
12311
12312 #if USE_CARBON_EVENTS
12313 rneResult = ReceiveNextEvent (0, NULL,
12314 expected
12315 ? TicksToEventTime (app_sleep_time)
12316 : 0,
12317 kEventRemoveFromQueue, &eventRef);
12318 if (!rneResult)
12319 {
12320 /* Handle new events */
12321 if (!mac_convert_event_ref (eventRef, &er))
12322 switch (GetEventClass (eventRef))
12323 {
12324 case kEventClassMouse:
12325 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
12326 {
12327 SInt32 delta;
12328 Point point;
12329 WindowPtr window_ptr = FrontNonFloatingWindow ();
12330 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12331 if (!IsValidWindowPtr (window_ptr))
12332 {
12333 SysBeep(1);
12334 UNBLOCK_INPUT;
12335 return 0;
12336 }
12337
12338 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
12339 typeSInt32, NULL, sizeof (SInt32),
12340 NULL, &delta);
12341 GetEventParameter(eventRef, kEventParamMouseLocation,
12342 typeQDPoint, NULL, sizeof (Point),
12343 NULL, &point);
12344 bufp->kind = MOUSE_WHEEL_EVENT;
12345 bufp->code = delta;
12346 bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
12347 SetPort (GetWindowPort (window_ptr));
12348 GlobalToLocal (&point);
12349 XSETINT (bufp->x, point.h);
12350 XSETINT (bufp->y, point.v);
12351 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12352 bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
12353 count++;
12354 }
12355 else
12356 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12357
12358 break;
12359 default:
12360 /* Send the event to the appropriate receiver. */
12361 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12362 }
12363 else
12364 #else
12365 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
12366 #endif /* USE_CARBON_EVENTS */
12367 switch (er.what)
12368 {
12369 case mouseDown:
12370 case mouseUp:
12371 {
12372 WindowPtr window_ptr = FrontWindow ();
12373 SInt16 part_code;
12374
12375 #if USE_CARBON_EVENTS
12376 /* This is needed to send mouse events like aqua window buttons
12377 to the correct handler. */
12378 if (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
12379 break;
12380 }
12381
12382 if (!is_emacs_window(window_ptr))
12383 break;
12384 #endif
12385
12386 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12387 && er.what == mouseUp)
12388 {
12389 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12390 Point mouse_loc = er.where;
12391
12392 /* Convert to local coordinates of new window. */
12393 #if TARGET_API_MAC_CARBON
12394 SetPort (GetWindowPort (window_ptr));
12395 #else
12396 SetPort (window_ptr);
12397 #endif
12398
12399 GlobalToLocal (&mouse_loc);
12400
12401 #if USE_CARBON_EVENTS
12402 bufp->code = mac_get_mouse_btn (eventRef);
12403 #else
12404 bufp->code = 0; /* only one mouse button */
12405 #endif
12406 bufp->kind = SCROLL_BAR_CLICK_EVENT;
12407 bufp->frame_or_window = tracked_scroll_bar->window;
12408 bufp->part = scroll_bar_handle;
12409 #if USE_CARBON_EVENTS
12410 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12411 #else
12412 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12413 #endif
12414 bufp->modifiers |= up_modifier;
12415 bufp->timestamp = er.when * (1000 / 60);
12416 /* ticks to milliseconds */
12417
12418 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12419 XSETINT (bufp->y, mouse_loc.v - 24);
12420 tracked_scroll_bar->dragging = Qnil;
12421 mouse_tracking_in_progress = mouse_tracking_none;
12422 tracked_scroll_bar = NULL;
12423 count++;
12424 break;
12425 }
12426
12427 part_code = FindWindow (er.where, &window_ptr);
12428
12429 switch (part_code)
12430 {
12431 case inMenuBar:
12432 {
12433 struct frame *f = ((mac_output *)
12434 GetWRefCon (FrontWindow ()))->mFP;
12435 saved_menu_event_location = er.where;
12436 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
12437 XSETFRAME (bufp->frame_or_window, f);
12438 count++;
12439 }
12440 break;
12441
12442 case inContent:
12443 if (window_ptr != FrontWindow ())
12444 SelectWindow (window_ptr);
12445 else
12446 {
12447 SInt16 control_part_code;
12448 ControlHandle ch;
12449 struct mac_output *mwp = (mac_output *)
12450 GetWRefCon (window_ptr);
12451 Point mouse_loc = er.where;
12452
12453 /* convert to local coordinates of new window */
12454 #if TARGET_API_MAC_CARBON
12455 SetPort (GetWindowPort (window_ptr));
12456 #else
12457 SetPort (window_ptr);
12458 #endif
12459
12460 GlobalToLocal (&mouse_loc);
12461 #if TARGET_API_MAC_CARBON
12462 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12463 &control_part_code);
12464 #else
12465 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
12466 #endif
12467
12468 #if USE_CARBON_EVENTS
12469 bufp->code = mac_get_mouse_btn (eventRef);
12470 #else
12471 bufp->code = 0; /* only one mouse button */
12472 #endif
12473 XSETINT (bufp->x, mouse_loc.h);
12474 XSETINT (bufp->y, mouse_loc.v);
12475 bufp->timestamp = er.when * (1000 / 60);
12476 /* ticks to milliseconds */
12477
12478 #if TARGET_API_MAC_CARBON
12479 if (ch != 0)
12480 #else
12481 if (control_part_code != 0)
12482 #endif
12483 {
12484 struct scroll_bar *bar = (struct scroll_bar *)
12485 GetControlReference (ch);
12486 x_scroll_bar_handle_click (bar, control_part_code, &er,
12487 bufp);
12488 if (er.what == mouseDown
12489 && control_part_code == kControlIndicatorPart)
12490 {
12491 mouse_tracking_in_progress
12492 = mouse_tracking_scroll_bar;
12493 tracked_scroll_bar = bar;
12494 }
12495 else
12496 {
12497 mouse_tracking_in_progress = mouse_tracking_none;
12498 tracked_scroll_bar = NULL;
12499 }
12500 }
12501 else
12502 {
12503 bufp->kind = MOUSE_CLICK_EVENT;
12504 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12505 if (er.what == mouseDown)
12506 mouse_tracking_in_progress
12507 = mouse_tracking_mouse_movement;
12508 else
12509 mouse_tracking_in_progress = mouse_tracking_none;
12510 }
12511
12512 #if USE_CARBON_EVENTS
12513 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12514 #else
12515 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12516 #endif
12517
12518 switch (er.what)
12519 {
12520 case mouseDown:
12521 bufp->modifiers |= down_modifier;
12522 break;
12523 case mouseUp:
12524 bufp->modifiers |= up_modifier;
12525 break;
12526 }
12527
12528 count++;
12529 }
12530 break;
12531
12532 case inDrag:
12533 #if TARGET_API_MAC_CARBON
12534 {
12535 BitMap bm;
12536
12537 GetQDGlobalsScreenBits (&bm);
12538 DragWindow (window_ptr, er.where, &bm.bounds);
12539 }
12540 #else /* not TARGET_API_MAC_CARBON */
12541 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12542 #endif /* not TARGET_API_MAC_CARBON */
12543 break;
12544
12545 case inGoAway:
12546 if (TrackGoAway (window_ptr, er.where))
12547 {
12548 bufp->kind = DELETE_WINDOW_EVENT;
12549 XSETFRAME (bufp->frame_or_window,
12550 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12551 count++;
12552 }
12553 break;
12554
12555 /* window resize handling added --ben */
12556 case inGrow:
12557 do_grow_window(window_ptr, &er);
12558 break;
12559
12560 /* window zoom handling added --ben */
12561 case inZoomIn:
12562 case inZoomOut:
12563 if (TrackBox (window_ptr, er.where, part_code))
12564 do_zoom_window (window_ptr, part_code);
12565 break;
12566
12567 default:
12568 break;
12569 }
12570 }
12571 break;
12572
12573 case updateEvt:
12574 case osEvt:
12575 case activateEvt:
12576 #if USE_CARBON_EVENTS
12577 if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
12578 #endif
12579 do_events (&er);
12580 break;
12581
12582 case keyDown:
12583 case autoKey:
12584 {
12585 int keycode = (er.message & keyCodeMask) >> 8;
12586 int xkeysym;
12587
12588 #if USE_CARBON_EVENTS
12589 /* When using Carbon Events, we need to pass raw keyboard events
12590 to the TSM ourselves. If TSM handles it, it will pass back
12591 noErr, otherwise it will pass back "eventNotHandledErr" and
12592 we can process it normally. */
12593 if ((!NILP (Vmac_pass_command_to_system)
12594 || !(er.modifiers & cmdKey))
12595 && (!NILP (Vmac_pass_control_to_system)
12596 || !(er.modifiers & controlKey)))
12597 {
12598 OSStatus err;
12599 err = SendEventToEventTarget (eventRef,
12600 GetEventDispatcherTarget ());
12601 if (err != eventNotHandledErr)
12602 break;
12603 }
12604 #endif
12605
12606 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
12607 {
12608 SysBeep (1);
12609 UNBLOCK_INPUT;
12610 return 0;
12611 }
12612
12613 ObscureCursor ();
12614
12615 if (keycode_to_xkeysym (keycode, &xkeysym))
12616 {
12617 bufp->code = 0xff00 | xkeysym;
12618 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
12619 }
12620 else
12621 {
12622 if (er.modifiers & (controlKey |
12623 (NILP (Vmac_command_key_is_meta) ? optionKey
12624 : cmdKey)))
12625 {
12626 /* This code comes from Keyboard Resource, Appendix
12627 C of IM - Text. This is necessary since shift is
12628 ignored in KCHR table translation when option or
12629 command is pressed. It also does not translate
12630 correctly control-shift chars like C-% so mask off
12631 shift here also */
12632 int new_modifiers = er.modifiers & 0xe600;
12633 /* mask off option and command */
12634 int new_keycode = keycode | new_modifiers;
12635 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12636 unsigned long some_state = 0;
12637 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12638 &some_state) & 0xff;
12639 }
12640 else
12641 bufp->code = er.message & charCodeMask;
12642 bufp->kind = ASCII_KEYSTROKE_EVENT;
12643 }
12644 }
12645
12646 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12647 convert non-ASCII characters typed at the Mac keyboard
12648 (presumed to be in the Mac Roman encoding) to iso-latin-1
12649 encoding before they are passed to Emacs. This enables the
12650 Mac keyboard to be used to enter non-ASCII iso-latin-1
12651 characters directly. */
12652 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12653 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
12654 {
12655 static TECObjectRef converter = NULL;
12656 OSStatus the_err = noErr;
12657 OSStatus convert_status = noErr;
12658
12659 if (converter == NULL)
12660 {
12661 the_err = TECCreateConverter (&converter,
12662 kTextEncodingMacRoman,
12663 mac_keyboard_text_encoding);
12664 current_mac_keyboard_text_encoding
12665 = mac_keyboard_text_encoding;
12666 }
12667 else if (mac_keyboard_text_encoding
12668 != current_mac_keyboard_text_encoding)
12669 {
12670 /* Free the converter for the current encoding before
12671 creating a new one. */
12672 TECDisposeConverter (converter);
12673 the_err = TECCreateConverter (&converter,
12674 kTextEncodingMacRoman,
12675 mac_keyboard_text_encoding);
12676 current_mac_keyboard_text_encoding
12677 = mac_keyboard_text_encoding;
12678 }
12679
12680 if (the_err == noErr)
12681 {
12682 unsigned char ch = bufp->code;
12683 ByteCount actual_input_length, actual_output_length;
12684 unsigned char outch;
12685
12686 convert_status = TECConvertText (converter, &ch, 1,
12687 &actual_input_length,
12688 &outch, 1,
12689 &actual_output_length);
12690 if (convert_status == noErr
12691 && actual_input_length == 1
12692 && actual_output_length == 1)
12693 bufp->code = outch;
12694 }
12695 }
12696
12697 #if USE_CARBON_EVENTS
12698 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12699 #else
12700 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12701 #endif
12702
12703 {
12704 mac_output *mwp
12705 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
12706 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12707 }
12708
12709 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
12710
12711 count++;
12712 break;
12713
12714 case kHighLevelEvent:
12715 drag_and_drop_file_list = Qnil;
12716
12717 AEProcessAppleEvent(&er);
12718
12719 /* Build a DRAG_N_DROP_EVENT type event as is done in
12720 constuct_drag_n_drop in w32term.c. */
12721 if (!NILP (drag_and_drop_file_list))
12722 {
12723 struct frame *f = NULL;
12724 WindowPtr wp;
12725 Lisp_Object frame;
12726
12727 wp = FrontNonFloatingWindow ();
12728
12729 if (!wp)
12730 {
12731 struct frame *f = XFRAME (XCAR (Vframe_list));
12732 CollapseWindow (FRAME_MAC_WINDOW (f), false);
12733 wp = FrontNonFloatingWindow ();
12734 }
12735
12736 if (wp && is_emacs_window(wp))
12737 f = ((mac_output *) GetWRefCon (wp))->mFP;
12738
12739 bufp->kind = DRAG_N_DROP_EVENT;
12740 bufp->code = 0;
12741 bufp->timestamp = er.when * (1000 / 60);
12742 /* ticks to milliseconds */
12743 #if USE_CARBON_EVENTS
12744 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12745 #else
12746 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12747 #endif
12748
12749 XSETINT (bufp->x, 0);
12750 XSETINT (bufp->y, 0);
12751
12752 XSETFRAME (frame, f);
12753 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
12754
12755 /* Regardless of whether Emacs was suspended or in the
12756 foreground, ask it to redraw its entire screen.
12757 Otherwise parts of the screen can be left in an
12758 inconsistent state. */
12759 if (wp)
12760 #if TARGET_API_MAC_CARBON
12761 {
12762 Rect r;
12763
12764 GetWindowPortBounds (wp, &r);
12765 InvalWindowRect (wp, &r);
12766 }
12767 #else /* not TARGET_API_MAC_CARBON */
12768 InvalRect (&(wp->portRect));
12769 #endif /* not TARGET_API_MAC_CARBON */
12770
12771 count++;
12772 }
12773 default:
12774 break;
12775 }
12776 #if USE_CARBON_EVENTS
12777 ReleaseEvent (eventRef);
12778 }
12779 #endif
12780
12781 /* If the focus was just given to an autoraising frame,
12782 raise it now. */
12783 /* ??? This ought to be able to handle more than one such frame. */
12784 if (pending_autoraise_frame)
12785 {
12786 x_raise_frame (pending_autoraise_frame);
12787 pending_autoraise_frame = 0;
12788 }
12789
12790 #if !TARGET_API_MAC_CARBON
12791 check_alarm (); /* simulate the handling of a SIGALRM */
12792 #endif
12793
12794 {
12795 static Point old_mouse_pos = { -1, -1 };
12796
12797 if (app_is_suspended)
12798 {
12799 old_mouse_pos.h = -1;
12800 old_mouse_pos.v = -1;
12801 }
12802 else
12803 {
12804 Point mouse_pos;
12805 WindowPtr wp;
12806 struct frame *f;
12807 Lisp_Object bar;
12808 struct scroll_bar *sb;
12809
12810 wp = FrontWindow ();
12811 if (is_emacs_window (wp))
12812 {
12813 f = ((mac_output *) GetWRefCon (wp))->mFP;
12814
12815 #if TARGET_API_MAC_CARBON
12816 SetPort (GetWindowPort (wp));
12817 #else
12818 SetPort (wp);
12819 #endif
12820
12821 GetMouse (&mouse_pos);
12822
12823 if (!EqualPt (mouse_pos, old_mouse_pos))
12824 {
12825 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12826 && tracked_scroll_bar)
12827 x_scroll_bar_note_movement (tracked_scroll_bar,
12828 mouse_pos.v
12829 - XINT (tracked_scroll_bar->top),
12830 TickCount() * (1000 / 60));
12831 else
12832 note_mouse_movement (f, &mouse_pos);
12833
12834 old_mouse_pos = mouse_pos;
12835 }
12836 }
12837 }
12838 }
12839
12840 UNBLOCK_INPUT;
12841
12842 return count;
12843 }
12844
12845
12846 /* Need to override CodeWarrior's input function so no conversion is
12847 done on newlines Otherwise compiled functions in .elc files will be
12848 read incorrectly. Defined in ...:MSL C:MSL
12849 Common:Source:buffer_io.c. */
12850 #ifdef __MWERKS__
12851 void
12852 __convert_to_newlines (unsigned char * p, size_t * n)
12853 {
12854 #pragma unused(p,n)
12855 }
12856
12857 void
12858 __convert_from_newlines (unsigned char * p, size_t * n)
12859 {
12860 #pragma unused(p,n)
12861 }
12862 #endif
12863
12864
12865 /* Initialize the struct pointed to by MW to represent a new COLS x
12866 ROWS Macintosh window, using font with name FONTNAME and size
12867 FONTSIZE. */
12868 void
12869 NewMacWindow (FRAME_PTR fp)
12870 {
12871 mac_output *mwp;
12872 #if TARGET_API_MAC_CARBON
12873 static int making_terminal_window = 0;
12874 #else
12875 static int making_terminal_window = 1;
12876 #endif
12877
12878 mwp = fp->output_data.mac;
12879
12880 if (making_terminal_window)
12881 {
12882 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
12883 (WindowPtr) -1)))
12884 abort ();
12885 making_terminal_window = 0;
12886 }
12887 else
12888 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
12889 abort ();
12890
12891 SetWRefCon (mwp->mWP, (long) mwp);
12892 /* so that update events can find this mac_output struct */
12893 mwp->mFP = fp; /* point back to emacs frame */
12894
12895 #if TARGET_API_MAC_CARBON
12896 SetPort (GetWindowPort (mwp->mWP));
12897 #else
12898 SetPort (mwp->mWP);
12899 #endif
12900
12901 mwp->fontset = -1;
12902
12903 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
12904 ShowWindow (mwp->mWP);
12905
12906 }
12907
12908
12909 void
12910 make_mac_frame (struct frame *f)
12911 {
12912 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12913 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12914
12915 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
12916
12917 NewMacWindow(f);
12918
12919 f->output_data.mac->cursor_pixel = 0;
12920 f->output_data.mac->border_pixel = 0x00ff00;
12921 f->output_data.mac->mouse_pixel = 0xff00ff;
12922 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12923
12924 f->output_data.mac->fontset = -1;
12925 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12926 f->output_data.mac->scroll_bar_background_pixel = -1;
12927 f->output_data.mac->left_pos = 4;
12928 f->output_data.mac->top_pos = 4;
12929 f->output_data.mac->border_width = 0;
12930 f->output_data.mac->explicit_parent = 0;
12931
12932 f->output_data.mac->internal_border_width = 0;
12933
12934 f->output_method = output_mac;
12935
12936 f->auto_raise = 1;
12937 f->auto_lower = 1;
12938
12939 f->new_width = 0;
12940 f->new_height = 0;
12941 }
12942
12943 void
12944 make_mac_terminal_frame (struct frame *f)
12945 {
12946 Lisp_Object frame;
12947
12948 XSETFRAME (frame, f);
12949
12950 f->output_method = output_mac;
12951 f->output_data.mac = (struct mac_output *)
12952 xmalloc (sizeof (struct mac_output));
12953 bzero (f->output_data.mac, sizeof (struct mac_output));
12954 f->output_data.mac->fontset = -1;
12955 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12956 f->output_data.mac->scroll_bar_background_pixel = -1;
12957
12958 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12959
12960 f->width = 96;
12961 f->height = 4;
12962
12963 make_mac_frame (f);
12964
12965 x_make_gc (f);
12966
12967 /* Need to be initialized for unshow_buffer in window.c. */
12968 selected_window = f->selected_window;
12969
12970 Fmodify_frame_parameters (frame,
12971 Fcons (Fcons (Qfont,
12972 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12973 Fmodify_frame_parameters (frame,
12974 Fcons (Fcons (Qforeground_color,
12975 build_string ("black")), Qnil));
12976 Fmodify_frame_parameters (frame,
12977 Fcons (Fcons (Qbackground_color,
12978 build_string ("white")), Qnil));
12979 }
12980
12981 \f
12982 /***********************************************************************
12983 Initialization
12984 ***********************************************************************/
12985
12986 #ifdef USE_X_TOOLKIT
12987 static XrmOptionDescRec emacs_options[] = {
12988 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12989 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12990
12991 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12992 XrmoptionSepArg, NULL},
12993 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12994
12995 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12996 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12997 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12998 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12999 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13000 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13001 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13002 };
13003 #endif /* USE_X_TOOLKIT */
13004
13005 #ifdef MULTI_KBOARD
13006 /* Test whether two display-name strings agree up to the dot that separates
13007 the screen number from the server number. */
13008 static int
13009 same_x_server (name1, name2)
13010 char *name1, *name2;
13011 {
13012 int seen_colon = 0;
13013 unsigned char *system_name = SDATA (Vsystem_name);
13014 int system_name_length = strlen (system_name);
13015 int length_until_period = 0;
13016
13017 while (system_name[length_until_period] != 0
13018 && system_name[length_until_period] != '.')
13019 length_until_period++;
13020
13021 /* Treat `unix' like an empty host name. */
13022 if (! strncmp (name1, "unix:", 5))
13023 name1 += 4;
13024 if (! strncmp (name2, "unix:", 5))
13025 name2 += 4;
13026 /* Treat this host's name like an empty host name. */
13027 if (! strncmp (name1, system_name, system_name_length)
13028 && name1[system_name_length] == ':')
13029 name1 += system_name_length;
13030 if (! strncmp (name2, system_name, system_name_length)
13031 && name2[system_name_length] == ':')
13032 name2 += system_name_length;
13033 /* Treat this host's domainless name like an empty host name. */
13034 if (! strncmp (name1, system_name, length_until_period)
13035 && name1[length_until_period] == ':')
13036 name1 += length_until_period;
13037 if (! strncmp (name2, system_name, length_until_period)
13038 && name2[length_until_period] == ':')
13039 name2 += length_until_period;
13040
13041 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13042 {
13043 if (*name1 == ':')
13044 seen_colon++;
13045 if (seen_colon && *name1 == '.')
13046 return 1;
13047 }
13048 return (seen_colon
13049 && (*name1 == '.' || *name1 == '\0')
13050 && (*name2 == '.' || *name2 == '\0'));
13051 }
13052 #endif
13053
13054 int mac_initialized = 0;
13055
13056 void
13057 mac_initialize_display_info ()
13058 {
13059 struct mac_display_info *dpyinfo = &one_mac_display_info;
13060 GDHandle main_device_handle;
13061
13062 bzero (dpyinfo, sizeof (*dpyinfo));
13063
13064 /* Put it on x_display_name_list. */
13065 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13066 x_display_name_list);
13067 dpyinfo->name_list_element = XCAR (x_display_name_list);
13068
13069 #if 0
13070 dpyinfo->mac_id_name
13071 = (char *) xmalloc (SCHARS (Vinvocation_name)
13072 + SCHARS (Vsystem_name)
13073 + 2);
13074 sprintf (dpyinfo->mac_id_name, "%s@%s",
13075 SDATA (Vinvocation_name), SDATA (Vsystem_name));
13076 #else
13077 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13078 strcpy (dpyinfo->mac_id_name, "Mac Display");
13079 #endif
13080
13081 main_device_handle = LMGetMainDevice();
13082
13083 dpyinfo->reference_count = 0;
13084 dpyinfo->resx = 75.0;
13085 dpyinfo->resy = 75.0;
13086 dpyinfo->n_planes = 1;
13087 dpyinfo->n_cbits = 16;
13088 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13089 dpyinfo->width = (**main_device_handle).gdRect.right;
13090 dpyinfo->grabbed = 0;
13091 dpyinfo->root_window = NULL;
13092
13093 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13094 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13095 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13096 dpyinfo->mouse_face_window = Qnil;
13097 }
13098
13099 struct mac_display_info *
13100 mac_term_init (display_name, xrm_option, resource_name)
13101 Lisp_Object display_name;
13102 char *xrm_option;
13103 char *resource_name;
13104 {
13105 struct mac_display_info *dpyinfo;
13106 GDHandle main_device_handle;
13107
13108 if (!mac_initialized)
13109 {
13110 mac_initialize ();
13111 mac_initialized = 1;
13112 }
13113
13114 mac_initialize_display_info (display_name);
13115
13116 dpyinfo = &one_mac_display_info;
13117
13118 main_device_handle = LMGetMainDevice();
13119
13120 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13121 dpyinfo->width = (**main_device_handle).gdRect.right;
13122
13123 return dpyinfo;
13124 }
13125 \f
13126 #ifdef MAC_OSX
13127 void
13128 mac_check_bundle()
13129 {
13130 extern int inhibit_window_system;
13131 extern int noninteractive;
13132 CFBundleRef appsBundle;
13133 pid_t child;
13134
13135 /* No need to test if already -nw*/
13136 if (inhibit_window_system || noninteractive)
13137 return;
13138
13139 appsBundle = CFBundleGetMainBundle();
13140 if (appsBundle != NULL)
13141 {
13142 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
13143 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
13144 /* We found the bundle identifier, now we know we are valid. */
13145 if (res != NULL)
13146 {
13147 CFRelease(res);
13148 return;
13149 }
13150 }
13151 /* MAC_TODO: Have this start the bundled executable */
13152
13153 /* For now, prevent the fatal error by bringing it up in the terminal */
13154 inhibit_window_system = 1;
13155 }
13156
13157 void
13158 MakeMeTheFrontProcess ()
13159 {
13160 ProcessSerialNumber psn;
13161 OSErr err;
13162
13163 err = GetCurrentProcess (&psn);
13164 if (err == noErr)
13165 (void) SetFrontProcess (&psn);
13166 }
13167
13168 /***** Code to handle C-g testing *****/
13169
13170 /* Contains the Mac modifier formed from quit_char */
13171 static mac_quit_char_modifiers = 0;
13172 static mac_quit_char_keycode;
13173 extern int quit_char;
13174
13175 static void
13176 mac_determine_quit_char_modifiers()
13177 {
13178 /* Todo: Determine modifiers from quit_char. */
13179 UInt32 qc_modifiers = ctrl_modifier;
13180
13181 /* Map modifiers */
13182 mac_quit_char_modifiers = 0;
13183 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
13184 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
13185 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
13186 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
13187 }
13188
13189 static void
13190 init_quit_char_handler ()
13191 {
13192 /* TODO: Let this support keys other the 'g' */
13193 mac_quit_char_keycode = 5;
13194 /* Look at <architecture/adb_kb_map.h> for details */
13195 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
13196
13197 mac_determine_quit_char_modifiers();
13198 }
13199
13200 static Boolean
13201 quit_char_comp (EventRef inEvent, void *inCompData)
13202 {
13203 if (GetEventClass(inEvent) != kEventClassKeyboard)
13204 return false;
13205 if (GetEventKind(inEvent) != kEventRawKeyDown)
13206 return false;
13207 {
13208 UInt32 keyCode;
13209 UInt32 keyModifiers;
13210 GetEventParameter(inEvent, kEventParamKeyCode,
13211 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
13212 if (keyCode != mac_quit_char_keycode)
13213 return false;
13214 GetEventParameter(inEvent, kEventParamKeyModifiers,
13215 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
13216 if (keyModifiers != mac_quit_char_modifiers)
13217 return false;
13218 }
13219 return true;
13220 }
13221
13222 void
13223 mac_check_for_quit_char()
13224 {
13225 EventRef event;
13226 /* If windows are not initialized, return immediately (keep it bouncin')*/
13227 if (!mac_quit_char_modifiers)
13228 return;
13229
13230 /* Redetermine modifiers because they are based on lisp variables */
13231 mac_determine_quit_char_modifiers();
13232
13233 /* Fill the queue with events */
13234 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
13235 event = FindSpecificEventInQueue (GetMainEventQueue(), quit_char_comp, NULL);
13236 if (event)
13237 {
13238 struct input_event e;
13239 struct mac_output *mwp = (mac_output*) GetWRefCon (FrontNonFloatingWindow ());
13240 /* Use an input_event to emulate what the interrupt handler does. */
13241 e.kind = ASCII_KEYSTROKE_EVENT;
13242 e.code = quit_char;
13243 e.arg = NULL;
13244 e.modifiers = NULL;
13245 e.timestamp = EventTimeToTicks(GetEventTime(event))*(1000/60);
13246 XSETFRAME(e.frame_or_window, mwp->mFP);
13247 /* Remove event from queue to prevent looping. */
13248 RemoveEventFromQueue(GetMainEventQueue(), event);
13249 ReleaseEvent(event);
13250 kbd_buffer_store_event(&e);
13251 }
13252 }
13253
13254 #endif /* MAC_OSX */
13255
13256 /* Set up use of X before we make the first connection. */
13257
13258 static struct redisplay_interface x_redisplay_interface =
13259 {
13260 x_produce_glyphs,
13261 x_write_glyphs,
13262 x_insert_glyphs,
13263 x_clear_end_of_line,
13264 x_scroll_run,
13265 x_after_update_window_line,
13266 x_update_window_begin,
13267 x_update_window_end,
13268 XTcursor_to,
13269 x_flush,
13270 x_clear_mouse_face,
13271 x_get_glyph_overhangs,
13272 x_fix_overlapping_area,
13273 x_draw_fringe_bitmap
13274 };
13275
13276 void
13277 mac_initialize ()
13278 {
13279 rif = &x_redisplay_interface;
13280
13281 clear_frame_hook = x_clear_frame;
13282 ins_del_lines_hook = x_ins_del_lines;
13283 delete_glyphs_hook = x_delete_glyphs;
13284 ring_bell_hook = XTring_bell;
13285 reset_terminal_modes_hook = XTreset_terminal_modes;
13286 set_terminal_modes_hook = XTset_terminal_modes;
13287 update_begin_hook = x_update_begin;
13288 update_end_hook = x_update_end;
13289 set_terminal_window_hook = XTset_terminal_window;
13290 read_socket_hook = XTread_socket;
13291 frame_up_to_date_hook = XTframe_up_to_date;
13292 mouse_position_hook = XTmouse_position;
13293 frame_rehighlight_hook = XTframe_rehighlight;
13294 frame_raise_lower_hook = XTframe_raise_lower;
13295
13296 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13297 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13298 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13299 judge_scroll_bars_hook = XTjudge_scroll_bars;
13300
13301 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13302
13303 scroll_region_ok = 1; /* we'll scroll partial frames */
13304 char_ins_del_ok = 1;
13305 line_ins_del_ok = 1; /* we'll just blt 'em */
13306 fast_clear_end_of_line = 1; /* X does this well */
13307 memory_below_frame = 0; /* we don't remember what scrolls
13308 off the bottom */
13309 baud_rate = 19200;
13310
13311 x_noop_count = 0;
13312 last_tool_bar_item = -1;
13313 any_help_event_p = 0;
13314
13315 /* Try to use interrupt input; if we can't, then start polling. */
13316 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13317
13318 #ifdef USE_X_TOOLKIT
13319 XtToolkitInitialize ();
13320 Xt_app_con = XtCreateApplicationContext ();
13321 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13322
13323 /* Install an asynchronous timer that processes Xt timeout events
13324 every 0.1s. This is necessary because some widget sets use
13325 timeouts internally, for example the LessTif menu bar, or the
13326 Xaw3d scroll bar. When Xt timouts aren't processed, these
13327 widgets don't behave normally. */
13328 {
13329 EMACS_TIME interval;
13330 EMACS_SET_SECS_USECS (interval, 0, 100000);
13331 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13332 }
13333 #endif
13334
13335 #if USE_TOOLKIT_SCROLL_BARS
13336 xaw3d_arrow_scroll = False;
13337 xaw3d_pick_top = True;
13338 #endif
13339
13340 #if 0
13341 /* Note that there is no real way portable across R3/R4 to get the
13342 original error handler. */
13343 XSetErrorHandler (x_error_handler);
13344 XSetIOErrorHandler (x_io_error_quitter);
13345
13346 /* Disable Window Change signals; they are handled by X events. */
13347 #ifdef SIGWINCH
13348 signal (SIGWINCH, SIG_DFL);
13349 #endif /* ! defined (SIGWINCH) */
13350
13351 signal (SIGPIPE, x_connection_signal);
13352 #endif
13353
13354 mac_initialize_display_info ();
13355
13356 #if TARGET_API_MAC_CARBON
13357 init_required_apple_events ();
13358
13359 init_mac_drag_n_drop ();
13360
13361 #if USE_CARBON_EVENTS
13362 init_service_handler ();
13363
13364 init_quit_char_handler ();
13365 #endif
13366
13367 DisableMenuCommand (NULL, kHICommandQuit);
13368
13369 if (!inhibit_window_system)
13370 MakeMeTheFrontProcess ();
13371 #endif
13372 }
13373
13374
13375 void
13376 syms_of_macterm ()
13377 {
13378 #if 0
13379 staticpro (&x_error_message_string);
13380 x_error_message_string = Qnil;
13381 #endif
13382
13383 Fprovide (intern ("mac-carbon"), Qnil);
13384
13385 staticpro (&x_display_name_list);
13386 x_display_name_list = Qnil;
13387
13388 staticpro (&last_mouse_scroll_bar);
13389 last_mouse_scroll_bar = Qnil;
13390
13391 staticpro (&Qvendor_specific_keysyms);
13392 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13393
13394 staticpro (&last_mouse_press_frame);
13395 last_mouse_press_frame = Qnil;
13396
13397 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13398 staticpro (&Qmac_ready_for_drag_n_drop);
13399
13400 help_echo = Qnil;
13401 staticpro (&help_echo);
13402 help_echo_object = Qnil;
13403 staticpro (&help_echo_object);
13404 help_echo_window = Qnil;
13405 staticpro (&help_echo_window);
13406 previous_help_echo = Qnil;
13407 staticpro (&previous_help_echo);
13408 help_echo_pos = -1;
13409
13410 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13411 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13412 x_autoselect_window_p = 0;
13413
13414 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13415 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13416 For example, if a block cursor is over a tab, it will be drawn as
13417 wide as that tab on the display. */);
13418 x_stretch_cursor_p = 0;
13419
13420 #if 0 /* TODO: Setting underline position from font properties. */
13421 DEFVAR_BOOL ("x-use-underline-position-properties",
13422 &x_use_underline_position_properties,
13423 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13424 nil means ignore them. If you encounter fonts with bogus
13425 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13426 to 4.1, set this to nil. */);
13427 x_use_underline_position_properties = 1;
13428 #endif
13429
13430 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13431 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13432 Vx_toolkit_scroll_bars = Qt;
13433
13434 staticpro (&last_mouse_motion_frame);
13435 last_mouse_motion_frame = Qnil;
13436
13437 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
13438 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13439 Otherwise the option key is used. */);
13440 Vmac_command_key_is_meta = Qt;
13441
13442 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
13443 doc: /* Non-nil means that the control and meta keys are reversed. This is
13444 useful for non-standard keyboard layouts. */);
13445 Vmac_reverse_ctrl_meta = Qnil;
13446
13447 #if USE_CARBON_EVENTS
13448 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
13449 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
13450 the right click will be mouse-3.
13451 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
13452 Vmac_wheel_button_is_mouse_2 = Qt;
13453
13454 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
13455 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
13456 Toolbox for processing before Emacs sees it. */);
13457 Vmac_pass_command_to_system = Qt;
13458
13459 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
13460 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
13461 Toolbox for processing before Emacs sees it. */);
13462 Vmac_pass_control_to_system = Qt;
13463 #endif
13464
13465 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
13466 doc: /* One of the Text Encoding Base constant values defined in the
13467 Basic Text Constants section of Inside Macintosh - Text Encoding
13468 Conversion Manager. Its value determines the encoding characters
13469 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13470 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13471 its default value, no conversion takes place. If it is set to
13472 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13473 characters typed on Mac keyboard are first converted into the
13474 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13475 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13476 command, this enables the Mac keyboard to be used to enter non-ASCII
13477 characters directly. */);
13478 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13479 }