]> code.delx.au - gnu-emacs/blob - src/macterm.c
2002-08-10 Andrew Choi <akochoi@shaw.ca>
[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 /* Fringe bitmaps. */
124
125 enum fringe_bitmap_type
126 {
127 NO_FRINGE_BITMAP,
128 LEFT_TRUNCATION_BITMAP,
129 RIGHT_TRUNCATION_BITMAP,
130 OVERLAY_ARROW_BITMAP,
131 CONTINUED_LINE_BITMAP,
132 CONTINUATION_LINE_BITMAP,
133 ZV_LINE_BITMAP
134 };
135
136 /* Bitmap drawn to indicate lines not displaying text if
137 `indicate-empty-lines' is non-nil. */
138
139 #define zv_width 8
140 #define zv_height 72
141 #define zv_period 3
142 static unsigned char zv_bits[] = {
143 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
144 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
145 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
146 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
147 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
148 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
149 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
150 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
151
152 /* An arrow like this: `<-'. */
153
154 #define left_width 8
155 #define left_height 8
156 static unsigned char left_bits[] = {
157 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
158
159 /* Right truncation arrow bitmap `->'. */
160
161 #define right_width 8
162 #define right_height 8
163 static unsigned char right_bits[] = {
164 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
165
166 /* Marker for continued lines. */
167
168 #define continued_width 8
169 #define continued_height 8
170 static unsigned char continued_bits[] = {
171 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
172
173 /* Marker for continuation lines. */
174
175 #define continuation_width 8
176 #define continuation_height 8
177 static unsigned char continuation_bits[] = {
178 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
179
180 /* Overlay arrow bitmap. */
181
182 #if 0
183 /* A bomb. */
184 #define ov_width 8
185 #define ov_height 8
186 static unsigned char ov_bits[] = {
187 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
188 #else
189 /* A triangular arrow. */
190 #define ov_width 8
191 #define ov_height 8
192 static unsigned char ov_bits[] = {
193 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
194 #endif
195
196 extern Lisp_Object Qhelp_echo;
197
198 \f
199 /* Non-nil means Emacs uses toolkit scroll bars. */
200
201 Lisp_Object Vx_toolkit_scroll_bars;
202
203 /* If a string, XTread_socket generates an event to display that string.
204 (The display is done in read_char.) */
205
206 static Lisp_Object help_echo;
207 static Lisp_Object help_echo_window;
208 static Lisp_Object help_echo_object;
209 static int help_echo_pos;
210
211 /* Temporary variable for XTread_socket. */
212
213 static Lisp_Object previous_help_echo;
214
215 /* Non-zero means that a HELP_EVENT has been generated since Emacs
216 start. */
217
218 static int any_help_event_p;
219
220 /* Non-zero means autoselect window with the mouse cursor. */
221
222 int x_autoselect_window_p;
223
224 /* Non-zero means draw block and hollow cursor as wide as the glyph
225 under it. For example, if a block cursor is over a tab, it will be
226 drawn as wide as that tab on the display. */
227
228 int x_stretch_cursor_p;
229
230 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
231
232 int x_use_underline_position_properties;
233
234 /* This is a chain of structures for all the X displays currently in
235 use. */
236
237 struct x_display_info *x_display_list;
238
239 /* This is a list of cons cells, each of the form (NAME
240 . FONT-LIST-CACHE), one for each element of x_display_list and in
241 the same order. NAME is the name of the frame. FONT-LIST-CACHE
242 records previous values returned by x-list-fonts. */
243
244 Lisp_Object x_display_name_list;
245
246 /* This is display since Mac does not support multiple ones. */
247 struct mac_display_info one_mac_display_info;
248
249 /* Frame being updated by update_frame. This is declared in term.c.
250 This is set by update_begin and looked at by all the XT functions.
251 It is zero while not inside an update. In that case, the XT
252 functions assume that `selected_frame' is the frame to apply to. */
253
254 extern struct frame *updating_frame;
255
256 extern int waiting_for_input;
257
258 /* This is a frame waiting to be auto-raised, within XTread_socket. */
259
260 struct frame *pending_autoraise_frame;
261
262 /* Nominal cursor position -- where to draw output.
263 HPOS and VPOS are window relative glyph matrix coordinates.
264 X and Y are window relative pixel coordinates. */
265
266 struct cursor_pos output_cursor;
267
268 /* Non-zero means user is interacting with a toolkit scroll bar. */
269
270 static int toolkit_scroll_bar_interaction;
271
272 /* Mouse movement.
273
274 Formerly, we used PointerMotionHintMask (in standard_event_mask)
275 so that we would have to call XQueryPointer after each MotionNotify
276 event to ask for another such event. However, this made mouse tracking
277 slow, and there was a bug that made it eventually stop.
278
279 Simply asking for MotionNotify all the time seems to work better.
280
281 In order to avoid asking for motion events and then throwing most
282 of them away or busy-polling the server for mouse positions, we ask
283 the server for pointer motion hints. This means that we get only
284 one event per group of mouse movements. "Groups" are delimited by
285 other kinds of events (focus changes and button clicks, for
286 example), or by XQueryPointer calls; when one of these happens, we
287 get another MotionNotify event the next time the mouse moves. This
288 is at least as efficient as getting motion events when mouse
289 tracking is on, and I suspect only negligibly worse when tracking
290 is off. */
291
292 /* Where the mouse was last time we reported a mouse event. */
293
294 FRAME_PTR last_mouse_frame;
295 static Rect last_mouse_glyph;
296 static Lisp_Object last_mouse_press_frame;
297
298 /* The scroll bar in which the last X motion event occurred.
299
300 If the last X motion event occurred in a scroll bar, we set this so
301 XTmouse_position can know whether to report a scroll bar motion or
302 an ordinary motion.
303
304 If the last X motion event didn't occur in a scroll bar, we set
305 this to Qnil, to tell XTmouse_position to return an ordinary motion
306 event. */
307
308 static Lisp_Object last_mouse_scroll_bar;
309
310 /* This is a hack. We would really prefer that XTmouse_position would
311 return the time associated with the position it returns, but there
312 doesn't seem to be any way to wrest the time-stamp from the server
313 along with the position query. So, we just keep track of the time
314 of the last movement we received, and return that in hopes that
315 it's somewhat accurate. */
316
317 static Time last_mouse_movement_time;
318
319 enum mouse_tracking_type {
320 mouse_tracking_none,
321 mouse_tracking_mouse_movement,
322 mouse_tracking_scroll_bar
323 };
324
325 enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
326
327 struct scroll_bar *tracked_scroll_bar = NULL;
328
329 /* Incremented by XTread_socket whenever it really tries to read
330 events. */
331
332 #ifdef __STDC__
333 static int volatile input_signal_count;
334 #else
335 static int input_signal_count;
336 #endif
337
338 /* Used locally within XTread_socket. */
339
340 static int x_noop_count;
341
342 /* Initial values of argv and argc. */
343
344 extern char **initial_argv;
345 extern int initial_argc;
346
347 extern Lisp_Object Vcommand_line_args, Vsystem_name;
348
349 /* Tells if a window manager is present or not. */
350
351 extern Lisp_Object Vx_no_window_manager;
352
353 extern Lisp_Object Qface, Qmouse_face;
354
355 extern int errno;
356
357 /* A mask of extra modifier bits to put into every keyboard char. */
358
359 extern int extra_keyboard_modifiers;
360
361 static Lisp_Object Qvendor_specific_keysyms;
362
363 #if 0
364 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
365 #endif
366
367 extern Lisp_Object x_icon_type P_ ((struct frame *));
368
369 extern int inhibit_window_system;
370
371 #if __MRC__
372 QDGlobals qd; /* QuickDraw global information structure. */
373 #endif
374
375
376 /* Enumeration for overriding/changing the face to use for drawing
377 glyphs in x_draw_glyphs. */
378
379 enum draw_glyphs_face
380 {
381 DRAW_NORMAL_TEXT,
382 DRAW_INVERSE_VIDEO,
383 DRAW_CURSOR,
384 DRAW_MOUSE_FACE,
385 DRAW_IMAGE_RAISED,
386 DRAW_IMAGE_SUNKEN
387 };
388
389 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
390 struct mac_display_info *mac_display_info_for_display (Display *);
391 static void x_update_window_end P_ ((struct window *, int, int));
392 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
393 static int fast_find_position P_ ((struct window *, int, int *, int *,
394 int *, int *, Lisp_Object));
395 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
396 int *, int *, int *, int *, int));
397 static void set_output_cursor P_ ((struct cursor_pos *));
398 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
399 int *, int *, int *, int));
400 static void note_mode_line_highlight P_ ((struct window *, int, int));
401 static void note_mouse_highlight P_ ((struct frame *, int, int));
402 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
403 static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
404 static void show_mouse_face P_ ((struct x_display_info *,
405 enum draw_glyphs_face));
406 static int cursor_in_mouse_face_p P_ ((struct window *));
407 static int clear_mouse_face P_ ((struct mac_display_info *));
408 static int x_io_error_quitter P_ ((Display *));
409 int x_catch_errors P_ ((Display *));
410 void x_uncatch_errors P_ ((Display *, int));
411 void x_lower_frame P_ ((struct frame *));
412 void x_scroll_bar_clear P_ ((struct frame *));
413 int x_had_errors_p P_ ((Display *));
414 void x_wm_set_size_hint P_ ((struct frame *, long, int));
415 void x_raise_frame P_ ((struct frame *));
416 void x_set_window_size P_ ((struct frame *, int, int, int));
417 void x_wm_set_window_state P_ ((struct frame *, int));
418 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
419 void mac_initialize P_ ((void));
420 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
421 static int x_compute_min_glyph_bounds P_ ((struct frame *));
422 enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
423 static void x_draw_phys_cursor_glyph P_ ((struct window *,
424 struct glyph_row *,
425 enum draw_glyphs_face));
426 static void x_update_end P_ ((struct frame *));
427 static void XTframe_up_to_date P_ ((struct frame *));
428 static void XTreassert_line_highlight P_ ((int, int));
429 static void x_change_line_highlight P_ ((int, int, int, int));
430 static void XTset_terminal_modes P_ ((void));
431 static void XTreset_terminal_modes P_ ((void));
432 static void XTcursor_to P_ ((int, int, int, int));
433 static void x_write_glyphs P_ ((struct glyph *, int));
434 static void x_clear_end_of_line P_ ((int));
435 static void x_clear_frame P_ ((void));
436 static void x_clear_cursor P_ ((struct window *));
437 static void frame_highlight P_ ((struct frame *));
438 static void frame_unhighlight P_ ((struct frame *));
439 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
440 static void XTframe_rehighlight P_ ((struct frame *));
441 static void x_frame_rehighlight P_ ((struct x_display_info *));
442 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
443 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
444 static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
445 static void expose_frame P_ ((struct frame *, int, int, int, int));
446 static int expose_window_tree P_ ((struct window *, Rect *));
447 static int expose_window P_ ((struct window *, Rect *));
448 static void expose_area P_ ((struct window *, struct glyph_row *,
449 Rect *, enum glyph_row_area));
450 static int expose_line P_ ((struct window *, struct glyph_row *,
451 Rect *));
452 void x_display_cursor (struct window *, int, int, int, int, int);
453 void x_update_cursor P_ ((struct frame *, int));
454 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
455 static void x_update_window_cursor P_ ((struct window *, int));
456 static void x_erase_phys_cursor P_ ((struct window *));
457 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
458 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
459 enum fringe_bitmap_type, int left_p));
460 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
461 GC, int));
462 static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
463 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
464 static void notice_overwritten_cursor P_ ((struct window *,
465 enum glyph_row_area,
466 int, int, int, int));
467 static void x_flush P_ ((struct frame *f));
468 static void x_update_begin P_ ((struct frame *));
469 static void x_update_window_begin P_ ((struct window *));
470 static void x_draw_vertical_border P_ ((struct window *));
471 static void x_after_update_window_line P_ ((struct glyph_row *));
472 static INLINE void take_vertical_position_into_account P_ ((struct it *));
473 static void x_produce_stretch_glyph P_ ((struct it *));
474
475 static void activate_scroll_bars (FRAME_PTR);
476 static void deactivate_scroll_bars (FRAME_PTR);
477
478 extern int image_ascent (struct image *, struct face *);
479 void x_set_offset (struct frame *, int, int, int);
480 int x_bitmap_icon (struct frame *, Lisp_Object);
481 void x_make_frame_visible (struct frame *);
482
483 extern void window_scroll (Lisp_Object, int, int, int);
484
485 /* Defined in macmenu.h. */
486 extern void menubar_selection_callback (FRAME_PTR, int);
487 extern void set_frame_menubar (FRAME_PTR, int, int);
488
489 /* X display function emulation */
490
491 /* Structure borrowed from Xlib.h to represent two-byte characters in
492 dumpglyphs. */
493
494 typedef struct {
495 unsigned char byte1;
496 unsigned char byte2;
497 } XChar2b;
498
499 static void
500 XFreePixmap (display, pixmap)
501 Display *display;
502 Pixmap pixmap;
503 {
504 PixMap *p = (PixMap *) pixmap;
505
506 xfree (p->baseAddr);
507 xfree (p);
508 }
509
510
511 /* Set foreground color for subsequent QuickDraw commands. Assume
512 graphic port has already been set. */
513
514 static void
515 mac_set_forecolor (unsigned long color)
516 {
517 RGBColor fg_color;
518
519 fg_color.red = RED_FROM_ULONG (color) * 256;
520 fg_color.green = GREEN_FROM_ULONG (color) * 256;
521 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
522
523 RGBForeColor (&fg_color);
524 }
525
526
527 /* Set background color for subsequent QuickDraw commands. Assume
528 graphic port has already been set. */
529
530 static void
531 mac_set_backcolor (unsigned long color)
532 {
533 RGBColor bg_color;
534
535 bg_color.red = RED_FROM_ULONG (color) * 256;
536 bg_color.green = GREEN_FROM_ULONG (color) * 256;
537 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
538
539 RGBBackColor (&bg_color);
540 }
541
542 /* Set foreground and background color for subsequent QuickDraw
543 commands. Assume that the graphic port has already been set. */
544
545 static void
546 mac_set_colors (GC gc)
547 {
548 mac_set_forecolor (gc->foreground);
549 mac_set_backcolor (gc->background);
550 }
551
552 /* Mac version of XDrawLine. */
553
554 static void
555 XDrawLine (display, w, gc, x1, y1, x2, y2)
556 Display *display;
557 WindowPtr w;
558 GC gc;
559 int x1, y1, x2, y2;
560 {
561 #if TARGET_API_MAC_CARBON
562 SetPort (GetWindowPort (w));
563 #else
564 SetPort (w);
565 #endif
566
567 mac_set_colors (gc);
568
569 MoveTo (x1, y1);
570 LineTo (x2, y2);
571 }
572
573 /* Mac version of XClearArea. */
574
575 void
576 XClearArea (display, w, x, y, width, height, exposures)
577 Display *display;
578 WindowPtr w;
579 int x, y;
580 unsigned int width, height;
581 int exposures;
582 {
583 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
584 Rect r;
585 XGCValues xgc;
586
587 xgc.foreground = mwp->x_compatible.foreground_pixel;
588 xgc.background = mwp->x_compatible.background_pixel;
589
590 #if TARGET_API_MAC_CARBON
591 SetPort (GetWindowPort (w));
592 #else
593 SetPort (w);
594 #endif
595
596 mac_set_colors (&xgc);
597 SetRect (&r, x, y, x + width, y + height);
598
599 EraseRect (&r);
600 }
601
602 /* Mac version of XClearWindow. */
603
604 static void
605 XClearWindow (display, w)
606 Display *display;
607 WindowPtr w;
608 {
609 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
610 XGCValues xgc;
611
612 xgc.foreground = mwp->x_compatible.foreground_pixel;
613 xgc.background = mwp->x_compatible.background_pixel;
614
615 #if TARGET_API_MAC_CARBON
616 SetPort (GetWindowPort (w));
617 #else
618 SetPort (w);
619 #endif
620
621 mac_set_colors (&xgc);
622
623 #if TARGET_API_MAC_CARBON
624 {
625 Rect r;
626
627 GetWindowPortBounds (w, &r);
628 EraseRect (&r);
629 }
630 #else /* not TARGET_API_MAC_CARBON */
631 EraseRect (&(w->portRect));
632 #endif /* not TARGET_API_MAC_CARBON */
633 }
634
635
636 /* Mac replacement for XCopyArea. */
637
638 static void
639 mac_draw_bitmap (display, w, gc, x, y, bitmap)
640 Display *display;
641 WindowPtr w;
642 GC gc;
643 int x, y;
644 BitMap *bitmap;
645 {
646 Rect r;
647
648 #if TARGET_API_MAC_CARBON
649 SetPort (GetWindowPort (w));
650 #else
651 SetPort (w);
652 #endif
653
654 mac_set_colors (gc);
655 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
656
657 #if TARGET_API_MAC_CARBON
658 {
659 PixMapHandle pmh;
660
661 LockPortBits (GetWindowPort (w));
662 pmh = GetPortPixMap (GetWindowPort (w));
663 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
664 UnlockPortBits (GetWindowPort (w));
665 }
666 #else /* not TARGET_API_MAC_CARBON */
667 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
668 #endif /* not TARGET_API_MAC_CARBON */
669 }
670
671
672 /* Mac replacement for XSetClipRectangles. */
673
674 static void
675 mac_set_clip_rectangle (display, w, r)
676 Display *display;
677 WindowPtr w;
678 Rect *r;
679 {
680 #if TARGET_API_MAC_CARBON
681 SetPort (GetWindowPort (w));
682 #else
683 SetPort (w);
684 #endif
685
686 ClipRect (r);
687 }
688
689
690 /* Mac replacement for XSetClipMask. */
691
692 static void
693 mac_reset_clipping (display, w)
694 Display *display;
695 WindowPtr w;
696 {
697 Rect r;
698
699 #if TARGET_API_MAC_CARBON
700 SetPort (GetWindowPort (w));
701 #else
702 SetPort (w);
703 #endif
704
705 SetRect (&r, -32767, -32767, 32767, 32767);
706 ClipRect (&r);
707 }
708
709
710 /* Mac replacement for XCreateBitmapFromBitmapData. */
711
712 static void
713 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
714 BitMap *bitmap;
715 char *bits;
716 int w, h;
717 {
718 int bytes_per_row, i, j;
719
720 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
721 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
722 if (!bitmap->baseAddr)
723 abort ();
724
725 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
726 for (i = 0; i < h; i++)
727 for (j = 0; j < w; j++)
728 if (BitTst (bits, i * w + j))
729 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
730
731 SetRect (&(bitmap->bounds), 0, 0, w, h);
732 }
733
734
735 static void
736 mac_free_bitmap (bitmap)
737 BitMap *bitmap;
738 {
739 xfree (bitmap->baseAddr);
740 }
741
742 /* Mac replacement for XFillRectangle. */
743
744 static void
745 XFillRectangle (display, w, gc, x, y, width, height)
746 Display *display;
747 WindowPtr w;
748 GC gc;
749 int x, y;
750 unsigned int width, height;
751 {
752 Rect r;
753
754 #if TARGET_API_MAC_CARBON
755 SetPort (GetWindowPort (w));
756 #else
757 SetPort (w);
758 #endif
759
760 mac_set_colors (gc);
761 SetRect (&r, x, y, x + width, y + height);
762
763 PaintRect (&r); /* using foreground color of gc */
764 }
765
766
767 /* Mac replacement for XDrawRectangle: dest is a window. */
768
769 static void
770 mac_draw_rectangle (display, w, gc, x, y, width, height)
771 Display *display;
772 WindowPtr w;
773 GC gc;
774 int x, y;
775 unsigned int width, height;
776 {
777 Rect r;
778
779 #if TARGET_API_MAC_CARBON
780 SetPort (GetWindowPort (w));
781 #else
782 SetPort (w);
783 #endif
784
785 mac_set_colors (gc);
786 SetRect (&r, x, y, x + width + 1, y + height + 1);
787
788 FrameRect (&r); /* using foreground color of gc */
789 }
790
791
792 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
793
794 static void
795 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
796 Display *display;
797 Pixmap p;
798 GC gc;
799 int x, y;
800 unsigned int width, height;
801 {
802 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
803 Rect r;
804
805 #if TARGET_API_MAC_CARBON
806 SetPort (GetWindowPort (w));
807 #else
808 SetPort (w);
809 #endif
810
811 mac_set_colors (gc);
812 SetRect (&r, x, y, x + width, y + height);
813
814 FrameRect (&r); /* using foreground color of gc */
815 #endif /* 0 */
816 }
817
818
819 static void
820 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
821 bytes_per_char)
822 Display *display;
823 WindowPtr w;
824 GC gc;
825 int x, y;
826 char *buf;
827 int nchars, mode, bytes_per_char;
828 {
829 #if TARGET_API_MAC_CARBON
830 SetPort (GetWindowPort (w));
831 #else
832 SetPort (w);
833 #endif
834
835 mac_set_colors (gc);
836
837 TextFont (gc->font->mac_fontnum);
838 TextSize (gc->font->mac_fontsize);
839 TextFace (gc->font->mac_fontface);
840 TextMode (mode);
841
842 MoveTo (x, y);
843 DrawText (buf, 0, nchars * bytes_per_char);
844 }
845
846
847 /* Mac replacement for XDrawString. */
848
849 static void
850 XDrawString (display, w, gc, x, y, buf, nchars)
851 Display *display;
852 WindowPtr w;
853 GC gc;
854 int x, y;
855 char *buf;
856 int nchars;
857 {
858 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
859 }
860
861
862 /* Mac replacement for XDrawString16. */
863
864 static void
865 XDrawString16 (display, w, gc, x, y, buf, nchars)
866 Display *display;
867 WindowPtr w;
868 GC gc;
869 int x, y;
870 XChar2b *buf;
871 int nchars;
872 {
873 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
874 2);
875 }
876
877
878 /* Mac replacement for XDrawImageString. */
879
880 static void
881 XDrawImageString (display, w, gc, x, y, buf, nchars)
882 Display *display;
883 WindowPtr w;
884 GC gc;
885 int x, y;
886 char *buf;
887 int nchars;
888 {
889 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
890 }
891
892
893 /* Mac replacement for XDrawString16. */
894
895 static void
896 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
897 Display *display;
898 WindowPtr w;
899 GC gc;
900 int x, y;
901 XChar2b *buf;
902 int nchars;
903 {
904 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
905 2);
906 }
907
908
909 /* Mac replacement for XCopyArea: dest must be window. */
910
911 static void
912 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
913 dest_y)
914 Display *display;
915 Pixmap src;
916 WindowPtr dest;
917 GC gc;
918 int src_x, src_y;
919 unsigned int width, height;
920 int dest_x, dest_y;
921 {
922 Rect src_r, dest_r;
923
924 #if TARGET_API_MAC_CARBON
925 SetPort (GetWindowPort (dest));
926 #else
927 SetPort (dest);
928 #endif
929
930 mac_set_colors (gc);
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 TARGET_API_MAC_CARBON
936 {
937 PixMapHandle pmh;
938
939 LockPortBits (GetWindowPort (dest));
940 pmh = GetPortPixMap (GetWindowPort (dest));
941 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
942 UnlockPortBits (GetWindowPort (dest));
943 }
944 #else /* not TARGET_API_MAC_CARBON */
945 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
946 #endif /* not TARGET_API_MAC_CARBON */
947 }
948
949
950 #if 0
951 /* Convert a pair of local coordinates to global (screen) coordinates.
952 Assume graphic port has been properly set. */
953 static void
954 local_to_global_coord (short *h, short *v)
955 {
956 Point p;
957
958 p.h = *h;
959 p.v = *v;
960
961 LocalToGlobal (&p);
962
963 *h = p.h;
964 *v = p.v;
965 }
966 #endif
967
968 /* Mac replacement for XCopyArea: used only for scrolling. */
969
970 static void
971 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
972 Display *display;
973 WindowPtr w;
974 GC gc;
975 int src_x, src_y;
976 unsigned int width, height;
977 int dest_x, dest_y;
978 {
979 #if TARGET_API_MAC_CARBON
980 Rect gw_r, src_r, dest_r;
981 PixMapHandle pmh;
982
983 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
984 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
985
986 SetPort (GetWindowPort (w));
987
988 ForeColor (blackColor);
989 BackColor (whiteColor);
990
991 LockPortBits (GetWindowPort (w));
992 pmh = GetPortPixMap (GetWindowPort (w));
993 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
994 UnlockPortBits (GetWindowPort (w));
995
996 mac_set_colors (gc);
997 #else /* not TARGET_API_MAC_CARBON */
998 Rect src_r, dest_r;
999
1000 SetPort (w);
1001 #if 0
1002 mac_set_colors (gc);
1003 #endif
1004
1005 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1006 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1007
1008 #if 0
1009 /* Need to use global coordinates and screenBits since src and dest
1010 areas overlap in general. */
1011 local_to_global_coord (&src_r.left, &src_r.top);
1012 local_to_global_coord (&src_r.right, &src_r.bottom);
1013 local_to_global_coord (&dest_r.left, &dest_r.top);
1014 local_to_global_coord (&dest_r.right, &dest_r.bottom);
1015
1016 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
1017 #else
1018 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1019 color mapping in CopyBits. Otherwise, it will be slow. */
1020 ForeColor (blackColor);
1021 BackColor (whiteColor);
1022 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1023
1024 mac_set_colors (gc);
1025 #endif
1026 #endif /* not TARGET_API_MAC_CARBON */
1027 }
1028
1029
1030 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1031
1032 static void
1033 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1034 dest_x, dest_y)
1035 Display *display;
1036 Pixmap src;
1037 Pixmap dest;
1038 GC gc;
1039 int src_x, src_y;
1040 unsigned int width, height;
1041 int dest_x, dest_y;
1042 {
1043 Rect src_r, dest_r;
1044 int src_right = ((PixMap *) src)->bounds.right;
1045 int src_bottom = ((PixMap *) src)->bounds.bottom;
1046 int w = src_right - src_x;
1047 int h = src_bottom - src_y;
1048
1049 mac_set_colors (gc);
1050
1051 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1052 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1053
1054 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1055 }
1056
1057
1058 /* Mac replacement for XChangeGC. */
1059
1060 static void
1061 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1062 XGCValues *xgcv)
1063 {
1064 if (mask & GCForeground)
1065 gc->foreground = xgcv->foreground;
1066 if (mask & GCBackground)
1067 gc->background = xgcv->background;
1068 if (mask & GCFont)
1069 gc->font = xgcv->font;
1070 }
1071
1072
1073 /* Mac replacement for XCreateGC. */
1074
1075 XGCValues *
1076 XCreateGC (void * ignore, Window window, unsigned long mask,
1077 XGCValues *xgcv)
1078 {
1079 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1080 bzero (gc, sizeof (XGCValues));
1081
1082 XChangeGC (ignore, gc, mask, xgcv);
1083
1084 return gc;
1085 }
1086
1087
1088 /* Used in xfaces.c. */
1089
1090 void
1091 XFreeGC (display, gc)
1092 Display *display;
1093 GC gc;
1094 {
1095 xfree (gc);
1096 }
1097
1098
1099 /* Mac replacement for XGetGCValues. */
1100
1101 static void
1102 XGetGCValues (void* ignore, XGCValues *gc,
1103 unsigned long mask, XGCValues *xgcv)
1104 {
1105 XChangeGC (ignore, xgcv, mask, gc);
1106 }
1107
1108
1109 /* Mac replacement for XSetForeground. */
1110
1111 static void
1112 XSetForeground (display, gc, color)
1113 Display *display;
1114 GC gc;
1115 unsigned long color;
1116 {
1117 gc->foreground = color;
1118 }
1119
1120
1121 /* Mac replacement for XSetFont. */
1122
1123 static void
1124 XSetFont (display, gc, font)
1125 Display *display;
1126 GC gc;
1127 XFontStruct *font;
1128 {
1129 gc->font = font;
1130 }
1131
1132
1133 static void
1134 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1135 int *direction,int *font_ascent,
1136 int *font_descent, XCharStruct *cs)
1137 {
1138 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1139 }
1140
1141
1142 /* x_sync is a no-op on Mac. */
1143 void
1144 x_sync (f)
1145 void *f;
1146 {
1147 }
1148
1149
1150 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1151 Calls to XFlush should be unnecessary because the X output buffer
1152 is flushed automatically as needed by calls to XPending,
1153 XNextEvent, or XWindowEvent according to the XFlush man page.
1154 XTread_socket calls XPending. Removing XFlush improves
1155 performance. */
1156
1157 #if TARGET_API_MAC_CARBON
1158 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1159 #else
1160 #define XFlush(DISPLAY) (void) 0
1161 #endif
1162
1163 /* Flush display of frame F, or of all frames if F is null. */
1164
1165 void
1166 x_flush (f)
1167 struct frame *f;
1168 {
1169 #if TARGET_API_MAC_CARBON
1170 BLOCK_INPUT;
1171 if (f == NULL)
1172 {
1173 Lisp_Object rest, frame;
1174 FOR_EACH_FRAME (rest, frame)
1175 x_flush (XFRAME (frame));
1176 }
1177 else if (FRAME_X_P (f))
1178 XFlush (FRAME_MAC_DISPLAY (f));
1179 UNBLOCK_INPUT;
1180 #endif /* TARGET_API_MAC_CARBON */
1181 }
1182
1183
1184 \f
1185 /* Return the struct mac_display_info corresponding to DPY. There's
1186 only one. */
1187
1188 struct mac_display_info *
1189 mac_display_info_for_display (dpy)
1190 Display *dpy;
1191 {
1192 return &one_mac_display_info;
1193 }
1194
1195
1196 \f
1197 /***********************************************************************
1198 Starting and ending an update
1199 ***********************************************************************/
1200
1201 /* Start an update of frame F. This function is installed as a hook
1202 for update_begin, i.e. it is called when update_begin is called.
1203 This function is called prior to calls to x_update_window_begin for
1204 each window being updated. */
1205
1206 static void
1207 x_update_begin (f)
1208 struct frame *f;
1209 {
1210 /* Nothing to do. */
1211 }
1212
1213
1214 /* Start update of window W. Set the global variable updated_window
1215 to the window being updated and set output_cursor to the cursor
1216 position of W. */
1217
1218 static void
1219 x_update_window_begin (w)
1220 struct window *w;
1221 {
1222 struct frame *f = XFRAME (WINDOW_FRAME (w));
1223 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1224
1225 updated_window = w;
1226 set_output_cursor (&w->cursor);
1227
1228 BLOCK_INPUT;
1229
1230 if (f == display_info->mouse_face_mouse_frame)
1231 {
1232 /* Don't do highlighting for mouse motion during the update. */
1233 display_info->mouse_face_defer = 1;
1234
1235 /* If F needs to be redrawn, simply forget about any prior mouse
1236 highlighting. */
1237 if (FRAME_GARBAGED_P (f))
1238 display_info->mouse_face_window = Qnil;
1239
1240 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1241 their mouse_face_p flag set, which means that they are always
1242 unequal to rows in a desired matrix which never have that
1243 flag set. So, rows containing mouse-face glyphs are never
1244 scrolled, and we don't have to switch the mouse highlight off
1245 here to prevent it from being scrolled. */
1246
1247 /* Can we tell that this update does not affect the window
1248 where the mouse highlight is? If so, no need to turn off.
1249 Likewise, don't do anything if the frame is garbaged;
1250 in that case, the frame's current matrix that we would use
1251 is all wrong, and we will redisplay that line anyway. */
1252 if (!NILP (display_info->mouse_face_window)
1253 && w == XWINDOW (display_info->mouse_face_window))
1254 {
1255 int i;
1256
1257 for (i = 0; i < w->desired_matrix->nrows; ++i)
1258 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1259 break;
1260
1261 if (i < w->desired_matrix->nrows)
1262 clear_mouse_face (display_info);
1263 }
1264 #endif /* 0 */
1265 }
1266
1267 UNBLOCK_INPUT;
1268 }
1269
1270
1271 /* Draw a vertical window border to the right of window W if W doesn't
1272 have vertical scroll bars. */
1273
1274 static void
1275 x_draw_vertical_border (w)
1276 struct window *w;
1277 {
1278 struct frame *f = XFRAME (WINDOW_FRAME (w));
1279
1280 /* Redraw borders between horizontally adjacent windows. Don't
1281 do it for frames with vertical scroll bars because either the
1282 right scroll bar of a window, or the left scroll bar of its
1283 neighbor will suffice as a border. */
1284 if (!WINDOW_RIGHTMOST_P (w)
1285 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1286 {
1287 int x0, x1, y0, y1;
1288
1289 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1290 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1291 y1 -= 1;
1292
1293 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1294 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1295 }
1296 }
1297
1298
1299 /* End update of window W (which is equal to updated_window).
1300
1301 Draw vertical borders between horizontally adjacent windows, and
1302 display W's cursor if CURSOR_ON_P is non-zero.
1303
1304 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1305 glyphs in mouse-face were overwritten. In that case we have to
1306 make sure that the mouse-highlight is properly redrawn.
1307
1308 W may be a menu bar pseudo-window in case we don't have X toolkit
1309 support. Such windows don't have a cursor, so don't display it
1310 here. */
1311
1312 static void
1313 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1314 struct window *w;
1315 int cursor_on_p, mouse_face_overwritten_p;
1316 {
1317 struct mac_display_info *dpyinfo
1318 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1319
1320 if (!w->pseudo_window_p)
1321 {
1322 BLOCK_INPUT;
1323
1324 if (cursor_on_p)
1325 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1326 output_cursor.vpos,
1327 output_cursor.x, output_cursor.y);
1328
1329 x_draw_vertical_border (w);
1330 UNBLOCK_INPUT;
1331 }
1332
1333 /* If a row with mouse-face was overwritten, arrange for
1334 XTframe_up_to_date to redisplay the mouse highlight. */
1335 if (mouse_face_overwritten_p)
1336 {
1337 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1338 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1339 dpyinfo->mouse_face_window = Qnil;
1340 }
1341
1342 #if 0
1343 /* Unhide the caret. This won't actually show the cursor, unless it
1344 was visible before the corresponding call to HideCaret in
1345 x_update_window_begin. */
1346 if (w32_use_visible_system_caret)
1347 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1348 #endif
1349
1350 updated_window = NULL;
1351 }
1352
1353
1354 /* End update of frame F. This function is installed as a hook in
1355 update_end. */
1356
1357 static void
1358 x_update_end (f)
1359 struct frame *f;
1360 {
1361 /* Reset the background color of Mac OS Window to that of the frame after
1362 update so that it is used by Mac Toolbox to clear the update region before
1363 an update event is generated. */
1364 #if TARGET_API_MAC_CARBON
1365 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1366 #else
1367 SetPort (FRAME_MAC_WINDOW (f));
1368 #endif
1369
1370 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1371
1372 /* Mouse highlight may be displayed again. */
1373 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1374
1375 BLOCK_INPUT;
1376 XFlush (FRAME_MAC_DISPLAY (f));
1377 UNBLOCK_INPUT;
1378 }
1379
1380
1381 /* This function is called from various places in xdisp.c whenever a
1382 complete update has been performed. The global variable
1383 updated_window is not available here. */
1384
1385 static void
1386 XTframe_up_to_date (f)
1387 struct frame *f;
1388 {
1389 if (FRAME_X_P (f))
1390 {
1391 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1392
1393 if (dpyinfo->mouse_face_deferred_gc
1394 || f == dpyinfo->mouse_face_mouse_frame)
1395 {
1396 BLOCK_INPUT;
1397 if (dpyinfo->mouse_face_mouse_frame)
1398 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1399 dpyinfo->mouse_face_mouse_x,
1400 dpyinfo->mouse_face_mouse_y);
1401 dpyinfo->mouse_face_deferred_gc = 0;
1402 UNBLOCK_INPUT;
1403 }
1404 }
1405 }
1406
1407
1408 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1409 arrow bitmaps, or clear the fringes if no bitmaps are required
1410 before DESIRED_ROW is made current. The window being updated is
1411 found in updated_window. This function is called from
1412 update_window_line only if it is known that there are differences
1413 between bitmaps to be drawn between current row and DESIRED_ROW. */
1414
1415 static void
1416 x_after_update_window_line (desired_row)
1417 struct glyph_row *desired_row;
1418 {
1419 struct window *w = updated_window;
1420 struct frame *f;
1421 int width, height;
1422
1423 xassert (w);
1424
1425 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1426 {
1427 BLOCK_INPUT;
1428 x_draw_row_fringe_bitmaps (w, desired_row);
1429 UNBLOCK_INPUT;
1430 }
1431
1432 /* When a window has disappeared, make sure that no rest of
1433 full-width rows stays visible in the internal border. Could
1434 check here if updated_window is the leftmost/rightmost window,
1435 but I guess it's not worth doing since vertically split windows
1436 are almost never used, internal border is rarely set, and the
1437 overhead is very small. */
1438 if (windows_or_buffers_changed
1439 && desired_row->full_width_p
1440 && (f = XFRAME (w->frame),
1441 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1442 width != 0)
1443 && (height = desired_row->visible_height,
1444 height > 0))
1445 {
1446 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1447 /* Internal border is drawn below the tool bar. */
1448 if (WINDOWP (f->tool_bar_window)
1449 && w == XWINDOW (f->tool_bar_window))
1450 y -= width;
1451
1452 BLOCK_INPUT;
1453
1454 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1455 0, y, width, height, 0);
1456 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1457 f->output_data.mac->pixel_width - width, y,
1458 width, height, 0);
1459
1460 UNBLOCK_INPUT;
1461 }
1462 }
1463
1464
1465 /* Draw the bitmap WHICH in one of the left or right fringes of
1466 window W. ROW is the glyph row for which to display the bitmap; it
1467 determines the vertical position at which the bitmap has to be
1468 drawn. */
1469
1470 static void
1471 x_draw_fringe_bitmap (w, row, which, left_p)
1472 struct window *w;
1473 struct glyph_row *row;
1474 enum fringe_bitmap_type which;
1475 int left_p;
1476 {
1477 struct frame *f = XFRAME (WINDOW_FRAME (w));
1478 Display *display = FRAME_MAC_DISPLAY (f);
1479 WindowPtr window = FRAME_MAC_WINDOW (f);
1480 int x, y, wd, h, dy;
1481 int b1, b2;
1482 unsigned char *bits;
1483 BitMap bitmap;
1484 XGCValues gcv;
1485 GC gc = f->output_data.mac->normal_gc;
1486 struct face *face;
1487
1488 /* Must clip because of partially visible lines. */
1489 x_clip_to_row (w, row, gc, 1);
1490
1491 /* Convert row to frame coordinates. */
1492 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1493
1494 switch (which)
1495 {
1496 case NO_FRINGE_BITMAP:
1497 wd = 0;
1498 h = 0;
1499 break;
1500
1501 case LEFT_TRUNCATION_BITMAP:
1502 wd = left_width;
1503 h = left_height;
1504 bits = left_bits;
1505 break;
1506
1507 case OVERLAY_ARROW_BITMAP:
1508 wd = ov_width;
1509 h = ov_height;
1510 bits = ov_bits;
1511 break;
1512
1513 case RIGHT_TRUNCATION_BITMAP:
1514 wd = right_width;
1515 h = right_height;
1516 bits = right_bits;
1517 break;
1518
1519 case CONTINUED_LINE_BITMAP:
1520 wd = continued_width;
1521 h = continued_height;
1522 bits = continued_bits;
1523 break;
1524
1525 case CONTINUATION_LINE_BITMAP:
1526 wd = continuation_width;
1527 h = continuation_height;
1528 bits = continuation_bits;
1529 break;
1530
1531 case ZV_LINE_BITMAP:
1532 wd = zv_width;
1533 h = zv_height - (y % zv_period);
1534 bits = zv_bits + (y % zv_period);
1535 break;
1536
1537 default:
1538 abort ();
1539 }
1540
1541 /* Clip bitmap if too high. */
1542 if (h > row->height)
1543 h = row->height;
1544
1545 /* Set dy to the offset in the row to start drawing the bitmap. */
1546 dy = (row->height - h) / 2;
1547
1548 /* Draw the bitmap. */
1549 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
1550 PREPARE_FACE_FOR_DISPLAY (f, face);
1551
1552 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1553 the fringe. */
1554 b1 = -1;
1555 if (left_p)
1556 {
1557 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1558 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1559 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1560 - wd
1561 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1562 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1563 {
1564 /* If W has a vertical border to its left, don't draw over it. */
1565 int border = ((XFASTINT (w->left) > 0
1566 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1567 ? 1 : 0);
1568 b1 = (window_box_left (w, -1)
1569 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1570 + border);
1571 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1572 }
1573 }
1574 else
1575 {
1576 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1577 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1578 x = (window_box_right (w, -1)
1579 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1580 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1581 the fringe. */
1582 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1583 {
1584 b1 = window_box_right (w, -1);
1585 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1586 }
1587 }
1588
1589 if (b1 >= 0)
1590 {
1591 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1592 XGCValues gcv;
1593 gcv.foreground = face->background;
1594
1595 #if 0 /* MAC_TODO: stipple */
1596 /* In case the same realized face is used for fringes and
1597 for something displayed in the text (e.g. face `region' on
1598 mono-displays, the fill style may have been changed to
1599 FillSolid in x_draw_glyph_string_background. */
1600 if (face->stipple)
1601 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1602 else
1603 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1604 #endif
1605
1606 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1607 &gcv,
1608 b1,
1609 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1610 row->y)),
1611 b2,
1612 row->visible_height);
1613
1614 #if 0 /* MAC_TODO: stipple */
1615 if (!face->stipple)
1616 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1617 #endif
1618 }
1619
1620 if (which == NO_FRINGE_BITMAP)
1621 {
1622 mac_reset_clipping (display, window);
1623 return;
1624 }
1625
1626 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1627 gcv.foreground = face->foreground;
1628 gcv.background = face->background;
1629
1630 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1631
1632 mac_free_bitmap (&bitmap);
1633 mac_reset_clipping (display, window);
1634 }
1635
1636
1637 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1638 function with input blocked. */
1639
1640 static void
1641 x_draw_row_fringe_bitmaps (w, row)
1642 struct window *w;
1643 struct glyph_row *row;
1644 {
1645 struct frame *f = XFRAME (w->frame);
1646 enum fringe_bitmap_type bitmap;
1647
1648 xassert (interrupt_input_blocked);
1649
1650 /* If row is completely invisible, because of vscrolling, we
1651 don't have to draw anything. */
1652 if (row->visible_height <= 0)
1653 return;
1654
1655 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1656 {
1657 /* Decide which bitmap to draw in the left fringe. */
1658 if (row->overlay_arrow_p)
1659 bitmap = OVERLAY_ARROW_BITMAP;
1660 else if (row->truncated_on_left_p)
1661 bitmap = LEFT_TRUNCATION_BITMAP;
1662 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1663 bitmap = CONTINUATION_LINE_BITMAP;
1664 else if (row->indicate_empty_line_p)
1665 bitmap = ZV_LINE_BITMAP;
1666 else
1667 bitmap = NO_FRINGE_BITMAP;
1668
1669 x_draw_fringe_bitmap (w, row, bitmap, 1);
1670 }
1671
1672 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1673 {
1674 /* Decide which bitmap to draw in the right fringe. */
1675 if (row->truncated_on_right_p)
1676 bitmap = RIGHT_TRUNCATION_BITMAP;
1677 else if (row->continued_p)
1678 bitmap = CONTINUED_LINE_BITMAP;
1679 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1680 bitmap = ZV_LINE_BITMAP;
1681 else
1682 bitmap = NO_FRINGE_BITMAP;
1683
1684 x_draw_fringe_bitmap (w, row, bitmap, 0);
1685 }
1686 }
1687
1688 \f
1689 /* This is called when starting Emacs and when restarting after
1690 suspend. When starting Emacs, no window is mapped. And nothing
1691 must be done to Emacs's own window if it is suspended (though that
1692 rarely happens). */
1693
1694 static void
1695 XTset_terminal_modes ()
1696 {
1697 }
1698
1699 /* This is called when exiting or suspending Emacs. Exiting will make
1700 the windows go away, and suspending requires no action. */
1701
1702 static void
1703 XTreset_terminal_modes ()
1704 {
1705 }
1706
1707
1708 \f
1709 /***********************************************************************
1710 Output Cursor
1711 ***********************************************************************/
1712
1713 /* Set the global variable output_cursor to CURSOR. All cursor
1714 positions are relative to updated_window. */
1715
1716 static void
1717 set_output_cursor (cursor)
1718 struct cursor_pos *cursor;
1719 {
1720 output_cursor.hpos = cursor->hpos;
1721 output_cursor.vpos = cursor->vpos;
1722 output_cursor.x = cursor->x;
1723 output_cursor.y = cursor->y;
1724 }
1725
1726
1727 /* Set a nominal cursor position.
1728
1729 HPOS and VPOS are column/row positions in a window glyph matrix. X
1730 and Y are window text area relative pixel positions.
1731
1732 If this is done during an update, updated_window will contain the
1733 window that is being updated and the position is the future output
1734 cursor position for that window. If updated_window is null, use
1735 selected_window and display the cursor at the given position. */
1736
1737 static void
1738 XTcursor_to (vpos, hpos, y, x)
1739 int vpos, hpos, y, x;
1740 {
1741 struct window *w;
1742
1743 /* If updated_window is not set, work on selected_window. */
1744 if (updated_window)
1745 w = updated_window;
1746 else
1747 w = XWINDOW (selected_window);
1748
1749 /* Set the output cursor. */
1750 output_cursor.hpos = hpos;
1751 output_cursor.vpos = vpos;
1752 output_cursor.x = x;
1753 output_cursor.y = y;
1754
1755 /* If not called as part of an update, really display the cursor.
1756 This will also set the cursor position of W. */
1757 if (updated_window == NULL)
1758 {
1759 BLOCK_INPUT;
1760 x_display_cursor (w, 1, hpos, vpos, x, y);
1761 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1762 UNBLOCK_INPUT;
1763 }
1764 }
1765
1766
1767 \f
1768 /***********************************************************************
1769 Display Iterator
1770 ***********************************************************************/
1771
1772 /* Function prototypes of this page. */
1773
1774 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1775 struct glyph *,
1776 XChar2b *,
1777 int *));
1778 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1779 int, XChar2b *, int));
1780 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1781 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1782 static void x_append_glyph P_ ((struct it *));
1783 static void x_append_composite_glyph P_ ((struct it *));
1784 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1785 int, int, double));
1786 static void x_produce_glyphs P_ ((struct it *));
1787 static void x_produce_image_glyph P_ ((struct it *it));
1788
1789
1790 /* Return a pointer to per-char metric information in FONT of a
1791 character pointed by B which is a pointer to an XChar2b. */
1792
1793 #define PER_CHAR_METRIC(font, b) \
1794 ((font)->per_char \
1795 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1796 + (((font)->min_byte1 || (font)->max_byte1) \
1797 ? (((b)->byte1 - (font)->min_byte1) \
1798 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1799 : 0)) \
1800 : &((font)->max_bounds))
1801
1802
1803 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1804 is not contained in the font. */
1805
1806 static INLINE XCharStruct *
1807 x_per_char_metric (font, char2b)
1808 XFontStruct *font;
1809 XChar2b *char2b;
1810 {
1811 /* The result metric information. */
1812 XCharStruct *pcm = NULL;
1813
1814 xassert (font && char2b);
1815
1816 if (font->per_char != NULL)
1817 {
1818 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1819 {
1820 /* min_char_or_byte2 specifies the linear character index
1821 corresponding to the first element of the per_char array,
1822 max_char_or_byte2 is the index of the last character. A
1823 character with non-zero CHAR2B->byte1 is not in the font.
1824 A character with byte2 less than min_char_or_byte2 or
1825 greater max_char_or_byte2 is not in the font. */
1826 if (char2b->byte1 == 0
1827 && char2b->byte2 >= font->min_char_or_byte2
1828 && char2b->byte2 <= font->max_char_or_byte2)
1829 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1830 }
1831 else
1832 {
1833 /* If either min_byte1 or max_byte1 are nonzero, both
1834 min_char_or_byte2 and max_char_or_byte2 are less than
1835 256, and the 2-byte character index values corresponding
1836 to the per_char array element N (counting from 0) are:
1837
1838 byte1 = N/D + min_byte1
1839 byte2 = N\D + min_char_or_byte2
1840
1841 where:
1842
1843 D = max_char_or_byte2 - min_char_or_byte2 + 1
1844 / = integer division
1845 \ = integer modulus */
1846 if (char2b->byte1 >= font->min_byte1
1847 && char2b->byte1 <= font->max_byte1
1848 && char2b->byte2 >= font->min_char_or_byte2
1849 && char2b->byte2 <= font->max_char_or_byte2)
1850 {
1851 pcm = (font->per_char
1852 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1853 * (char2b->byte1 - font->min_byte1))
1854 + (char2b->byte2 - font->min_char_or_byte2));
1855 }
1856 }
1857 }
1858 else
1859 {
1860 /* If the per_char pointer is null, all glyphs between the first
1861 and last character indexes inclusive have the same
1862 information, as given by both min_bounds and max_bounds. */
1863 if (char2b->byte2 >= font->min_char_or_byte2
1864 && char2b->byte2 <= font->max_char_or_byte2)
1865 pcm = &font->max_bounds;
1866 }
1867
1868 return ((pcm == NULL
1869 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1870 ? NULL : pcm);
1871 }
1872
1873
1874 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1875 the two-byte form of C. Encoding is returned in *CHAR2B. */
1876
1877 static INLINE void
1878 x_encode_char (c, char2b, font_info)
1879 int c;
1880 XChar2b *char2b;
1881 struct font_info *font_info;
1882 {
1883 int charset = CHAR_CHARSET (c);
1884 XFontStruct *font = font_info->font;
1885
1886 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1887 This may be either a program in a special encoder language or a
1888 fixed encoding. */
1889 if (font_info->font_encoder)
1890 {
1891 /* It's a program. */
1892 struct ccl_program *ccl = font_info->font_encoder;
1893
1894 if (CHARSET_DIMENSION (charset) == 1)
1895 {
1896 ccl->reg[0] = charset;
1897 ccl->reg[1] = char2b->byte2;
1898 }
1899 else
1900 {
1901 ccl->reg[0] = charset;
1902 ccl->reg[1] = char2b->byte1;
1903 ccl->reg[2] = char2b->byte2;
1904 }
1905
1906 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1907
1908 /* We assume that MSBs are appropriately set/reset by CCL
1909 program. */
1910 if (font->max_byte1 == 0) /* 1-byte font */
1911 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1912 else
1913 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1914 }
1915 else if (font_info->encoding[charset])
1916 {
1917 /* Fixed encoding scheme. See fontset.h for the meaning of the
1918 encoding numbers. */
1919 int enc = font_info->encoding[charset];
1920
1921 if ((enc == 1 || enc == 2)
1922 && CHARSET_DIMENSION (charset) == 2)
1923 char2b->byte1 |= 0x80;
1924
1925 if (enc == 1 || enc == 3)
1926 char2b->byte2 |= 0x80;
1927
1928 if (enc == 4)
1929 {
1930 int sjis1, sjis2;
1931
1932 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1933 char2b->byte1 = sjis1;
1934 char2b->byte2 = sjis2;
1935 }
1936 }
1937 }
1938
1939
1940 /* Get face and two-byte form of character C in face FACE_ID on frame
1941 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1942 means we want to display multibyte text. Value is a pointer to a
1943 realized face that is ready for display. */
1944
1945 static INLINE struct face *
1946 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1947 struct frame *f;
1948 int c, face_id;
1949 XChar2b *char2b;
1950 int multibyte_p;
1951 {
1952 struct face *face = FACE_FROM_ID (f, face_id);
1953
1954 if (!multibyte_p)
1955 {
1956 /* Unibyte case. We don't have to encode, but we have to make
1957 sure to use a face suitable for unibyte. */
1958 char2b->byte1 = 0;
1959 char2b->byte2 = c;
1960 face_id = FACE_FOR_CHAR (f, face, c);
1961 face = FACE_FROM_ID (f, face_id);
1962 }
1963 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1964 {
1965 /* Case of ASCII in a face known to fit ASCII. */
1966 char2b->byte1 = 0;
1967 char2b->byte2 = c;
1968 }
1969 else
1970 {
1971 int c1, c2, charset;
1972
1973 /* Split characters into bytes. If c2 is -1 afterwards, C is
1974 really a one-byte character so that byte1 is zero. */
1975 SPLIT_CHAR (c, charset, c1, c2);
1976 if (c2 > 0)
1977 char2b->byte1 = c1, char2b->byte2 = c2;
1978 else
1979 char2b->byte1 = 0, char2b->byte2 = c1;
1980
1981 /* Maybe encode the character in *CHAR2B. */
1982 if (face->font != NULL)
1983 {
1984 struct font_info *font_info
1985 = FONT_INFO_FROM_ID (f, face->font_info_id);
1986 if (font_info)
1987 x_encode_char (c, char2b, font_info);
1988 }
1989 }
1990
1991 /* Make sure X resources of the face are allocated. */
1992 xassert (face != NULL);
1993 PREPARE_FACE_FOR_DISPLAY (f, face);
1994
1995 return face;
1996 }
1997
1998
1999 /* Get face and two-byte form of character glyph GLYPH on frame F.
2000 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
2001 a pointer to a realized face that is ready for display. */
2002
2003 static INLINE struct face *
2004 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
2005 struct frame *f;
2006 struct glyph *glyph;
2007 XChar2b *char2b;
2008 int *two_byte_p;
2009 {
2010 struct face *face;
2011
2012 xassert (glyph->type == CHAR_GLYPH);
2013 face = FACE_FROM_ID (f, glyph->face_id);
2014
2015 if (two_byte_p)
2016 *two_byte_p = 0;
2017
2018 if (!glyph->multibyte_p)
2019 {
2020 /* Unibyte case. We don't have to encode, but we have to make
2021 sure to use a face suitable for unibyte. */
2022 char2b->byte1 = 0;
2023 char2b->byte2 = glyph->u.ch;
2024 }
2025 else if (glyph->u.ch < 128
2026 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2027 {
2028 /* Case of ASCII in a face known to fit ASCII. */
2029 char2b->byte1 = 0;
2030 char2b->byte2 = glyph->u.ch;
2031 }
2032 else
2033 {
2034 int c1, c2, charset;
2035
2036 /* Split characters into bytes. If c2 is -1 afterwards, C is
2037 really a one-byte character so that byte1 is zero. */
2038 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2039 if (c2 > 0)
2040 char2b->byte1 = c1, char2b->byte2 = c2;
2041 else
2042 char2b->byte1 = 0, char2b->byte2 = c1;
2043
2044 /* Maybe encode the character in *CHAR2B. */
2045 if (charset != CHARSET_ASCII)
2046 {
2047 struct font_info *font_info
2048 = FONT_INFO_FROM_ID (f, face->font_info_id);
2049 if (font_info)
2050 {
2051 x_encode_char (glyph->u.ch, char2b, font_info);
2052 if (two_byte_p)
2053 *two_byte_p
2054 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2055 }
2056 }
2057 }
2058
2059 /* Make sure X resources of the face are allocated. */
2060 xassert (face != NULL);
2061 PREPARE_FACE_FOR_DISPLAY (f, face);
2062 return face;
2063 }
2064
2065
2066 /* Store one glyph for IT->char_to_display in IT->glyph_row.
2067 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2068
2069 static INLINE void
2070 x_append_glyph (it)
2071 struct it *it;
2072 {
2073 struct glyph *glyph;
2074 enum glyph_row_area area = it->area;
2075
2076 xassert (it->glyph_row);
2077 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2078
2079 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2080 if (glyph < it->glyph_row->glyphs[area + 1])
2081 {
2082 glyph->charpos = CHARPOS (it->position);
2083 glyph->object = it->object;
2084 glyph->pixel_width = it->pixel_width;
2085 glyph->voffset = it->voffset;
2086 glyph->type = CHAR_GLYPH;
2087 glyph->multibyte_p = it->multibyte_p;
2088 glyph->left_box_line_p = it->start_of_box_run_p;
2089 glyph->right_box_line_p = it->end_of_box_run_p;
2090 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2091 || it->phys_descent > it->descent);
2092 glyph->padding_p = 0;
2093 glyph->glyph_not_available_p = it->glyph_not_available_p;
2094 glyph->face_id = it->face_id;
2095 glyph->u.ch = it->char_to_display;
2096 ++it->glyph_row->used[area];
2097 }
2098 }
2099
2100 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2101 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2102
2103 static INLINE void
2104 x_append_composite_glyph (it)
2105 struct it *it;
2106 {
2107 struct glyph *glyph;
2108 enum glyph_row_area area = it->area;
2109
2110 xassert (it->glyph_row);
2111
2112 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2113 if (glyph < it->glyph_row->glyphs[area + 1])
2114 {
2115 glyph->charpos = CHARPOS (it->position);
2116 glyph->object = it->object;
2117 glyph->pixel_width = it->pixel_width;
2118 glyph->voffset = it->voffset;
2119 glyph->type = COMPOSITE_GLYPH;
2120 glyph->multibyte_p = it->multibyte_p;
2121 glyph->left_box_line_p = it->start_of_box_run_p;
2122 glyph->right_box_line_p = it->end_of_box_run_p;
2123 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2124 || it->phys_descent > it->descent);
2125 glyph->padding_p = 0;
2126 glyph->glyph_not_available_p = 0;
2127 glyph->face_id = it->face_id;
2128 glyph->u.cmp_id = it->cmp_id;
2129 ++it->glyph_row->used[area];
2130 }
2131 }
2132
2133
2134 /* Change IT->ascent and IT->height according to the setting of
2135 IT->voffset. */
2136
2137 static INLINE void
2138 take_vertical_position_into_account (it)
2139 struct it *it;
2140 {
2141 if (it->voffset)
2142 {
2143 if (it->voffset < 0)
2144 /* Increase the ascent so that we can display the text higher
2145 in the line. */
2146 it->ascent += abs (it->voffset);
2147 else
2148 /* Increase the descent so that we can display the text lower
2149 in the line. */
2150 it->descent += it->voffset;
2151 }
2152 }
2153
2154
2155 /* Produce glyphs/get display metrics for the image IT is loaded with.
2156 See the description of struct display_iterator in dispextern.h for
2157 an overview of struct display_iterator. */
2158
2159 static void
2160 x_produce_image_glyph (it)
2161 struct it *it;
2162 {
2163 struct image *img;
2164 struct face *face;
2165
2166 xassert (it->what == IT_IMAGE);
2167
2168 face = FACE_FROM_ID (it->f, it->face_id);
2169 img = IMAGE_FROM_ID (it->f, it->image_id);
2170 xassert (img);
2171
2172 /* Make sure X resources of the face and image are loaded. */
2173 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2174 prepare_image_for_display (it->f, img);
2175
2176 it->ascent = it->phys_ascent = image_ascent (img, face);
2177 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2178 it->pixel_width = img->width + 2 * img->hmargin;
2179
2180 it->nglyphs = 1;
2181
2182 if (face->box != FACE_NO_BOX)
2183 {
2184 if (face->box_line_width > 0)
2185 {
2186 it->ascent += face->box_line_width;
2187 it->descent += face->box_line_width;
2188 }
2189
2190 if (it->start_of_box_run_p)
2191 it->pixel_width += abs (face->box_line_width);
2192 if (it->end_of_box_run_p)
2193 it->pixel_width += abs (face->box_line_width);
2194 }
2195
2196 take_vertical_position_into_account (it);
2197
2198 if (it->glyph_row)
2199 {
2200 struct glyph *glyph;
2201 enum glyph_row_area area = it->area;
2202
2203 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2204 if (glyph < it->glyph_row->glyphs[area + 1])
2205 {
2206 glyph->charpos = CHARPOS (it->position);
2207 glyph->object = it->object;
2208 glyph->pixel_width = it->pixel_width;
2209 glyph->voffset = it->voffset;
2210 glyph->type = IMAGE_GLYPH;
2211 glyph->multibyte_p = it->multibyte_p;
2212 glyph->left_box_line_p = it->start_of_box_run_p;
2213 glyph->right_box_line_p = it->end_of_box_run_p;
2214 glyph->overlaps_vertically_p = 0;
2215 glyph->padding_p = 0;
2216 glyph->glyph_not_available_p = 0;
2217 glyph->face_id = it->face_id;
2218 glyph->u.img_id = img->id;
2219 ++it->glyph_row->used[area];
2220 }
2221 }
2222 }
2223
2224
2225 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2226 of the glyph, WIDTH and HEIGHT are the width and height of the
2227 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2228 ascent of the glyph (0 <= ASCENT <= 1). */
2229
2230 static void
2231 x_append_stretch_glyph (it, object, width, height, ascent)
2232 struct it *it;
2233 Lisp_Object object;
2234 int width, height;
2235 double ascent;
2236 {
2237 struct glyph *glyph;
2238 enum glyph_row_area area = it->area;
2239
2240 xassert (ascent >= 0 && ascent <= 1);
2241
2242 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2243 if (glyph < it->glyph_row->glyphs[area + 1])
2244 {
2245 glyph->charpos = CHARPOS (it->position);
2246 glyph->object = object;
2247 glyph->pixel_width = width;
2248 glyph->voffset = it->voffset;
2249 glyph->type = STRETCH_GLYPH;
2250 glyph->multibyte_p = it->multibyte_p;
2251 glyph->left_box_line_p = it->start_of_box_run_p;
2252 glyph->right_box_line_p = it->end_of_box_run_p;
2253 glyph->overlaps_vertically_p = 0;
2254 glyph->padding_p = 0;
2255 glyph->glyph_not_available_p = 0;
2256 glyph->face_id = it->face_id;
2257 glyph->u.stretch.ascent = height * ascent;
2258 glyph->u.stretch.height = height;
2259 ++it->glyph_row->used[area];
2260 }
2261 }
2262
2263
2264 /* Produce a stretch glyph for iterator IT. IT->object is the value
2265 of the glyph property displayed. The value must be a list
2266 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2267 being recognized:
2268
2269 1. `:width WIDTH' specifies that the space should be WIDTH *
2270 canonical char width wide. WIDTH may be an integer or floating
2271 point number.
2272
2273 2. `:relative-width FACTOR' specifies that the width of the stretch
2274 should be computed from the width of the first character having the
2275 `glyph' property, and should be FACTOR times that width.
2276
2277 3. `:align-to HPOS' specifies that the space should be wide enough
2278 to reach HPOS, a value in canonical character units.
2279
2280 Exactly one of the above pairs must be present.
2281
2282 4. `:height HEIGHT' specifies that the height of the stretch produced
2283 should be HEIGHT, measured in canonical character units.
2284
2285 5. `:relative-height FACTOR' specifies that the height of the
2286 stretch should be FACTOR times the height of the characters having
2287 the glyph property.
2288
2289 Either none or exactly one of 4 or 5 must be present.
2290
2291 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2292 of the stretch should be used for the ascent of the stretch.
2293 ASCENT must be in the range 0 <= ASCENT <= 100. */
2294
2295 #define NUMVAL(X) \
2296 ((INTEGERP (X) || FLOATP (X)) \
2297 ? XFLOATINT (X) \
2298 : - 1)
2299
2300
2301 static void
2302 x_produce_stretch_glyph (it)
2303 struct it *it;
2304 {
2305 /* (space :width WIDTH :height HEIGHT. */
2306 #if GLYPH_DEBUG
2307 extern Lisp_Object Qspace;
2308 #endif
2309 extern Lisp_Object QCwidth, QCheight, QCascent;
2310 extern Lisp_Object QCrelative_width, QCrelative_height;
2311 extern Lisp_Object QCalign_to;
2312 Lisp_Object prop, plist;
2313 double width = 0, height = 0, ascent = 0;
2314 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2315 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2316
2317 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2318
2319 /* List should start with `space'. */
2320 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2321 plist = XCDR (it->object);
2322
2323 /* Compute the width of the stretch. */
2324 if (prop = Fplist_get (plist, QCwidth),
2325 NUMVAL (prop) > 0)
2326 /* Absolute width `:width WIDTH' specified and valid. */
2327 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2328 else if (prop = Fplist_get (plist, QCrelative_width),
2329 NUMVAL (prop) > 0)
2330 {
2331 /* Relative width `:relative-width FACTOR' specified and valid.
2332 Compute the width of the characters having the `glyph'
2333 property. */
2334 struct it it2;
2335 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2336
2337 it2 = *it;
2338 if (it->multibyte_p)
2339 {
2340 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2341 - IT_BYTEPOS (*it));
2342 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2343 }
2344 else
2345 it2.c = *p, it2.len = 1;
2346
2347 it2.glyph_row = NULL;
2348 it2.what = IT_CHARACTER;
2349 x_produce_glyphs (&it2);
2350 width = NUMVAL (prop) * it2.pixel_width;
2351 }
2352 else if (prop = Fplist_get (plist, QCalign_to),
2353 NUMVAL (prop) > 0)
2354 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2355 else
2356 /* Nothing specified -> width defaults to canonical char width. */
2357 width = CANON_X_UNIT (it->f);
2358
2359 /* Compute height. */
2360 if (prop = Fplist_get (plist, QCheight),
2361 NUMVAL (prop) > 0)
2362 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2363 else if (prop = Fplist_get (plist, QCrelative_height),
2364 NUMVAL (prop) > 0)
2365 height = FONT_HEIGHT (font) * NUMVAL (prop);
2366 else
2367 height = FONT_HEIGHT (font);
2368
2369 /* Compute percentage of height used for ascent. If
2370 `:ascent ASCENT' is present and valid, use that. Otherwise,
2371 derive the ascent from the font in use. */
2372 if (prop = Fplist_get (plist, QCascent),
2373 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2374 ascent = NUMVAL (prop) / 100.0;
2375 else
2376 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
2377
2378 if (width <= 0)
2379 width = 1;
2380 if (height <= 0)
2381 height = 1;
2382
2383 if (it->glyph_row)
2384 {
2385 Lisp_Object object = it->stack[it->sp - 1].string;
2386 if (!STRINGP (object))
2387 object = it->w->buffer;
2388 x_append_stretch_glyph (it, object, width, height, ascent);
2389 }
2390
2391 it->pixel_width = width;
2392 it->ascent = it->phys_ascent = height * ascent;
2393 it->descent = it->phys_descent = height - it->ascent;
2394 it->nglyphs = 1;
2395
2396 if (face->box != FACE_NO_BOX)
2397 {
2398 if (face->box_line_width > 0)
2399 {
2400 it->ascent += face->box_line_width;
2401 it->descent += face->box_line_width;
2402 }
2403
2404 if (it->start_of_box_run_p)
2405 it->pixel_width += abs (face->box_line_width);
2406 if (it->end_of_box_run_p)
2407 it->pixel_width += abs (face->box_line_width);
2408 }
2409
2410 take_vertical_position_into_account (it);
2411 }
2412
2413 /* Return proper value to be used as baseline offset of font that has
2414 ASCENT and DESCENT to draw characters by the font at the vertical
2415 center of the line of frame F.
2416
2417 Here, out task is to find the value of BOFF in the following figure;
2418
2419 -------------------------+-----------+-
2420 -+-+---------+-+ | |
2421 | | | | | |
2422 | | | | F_ASCENT F_HEIGHT
2423 | | | ASCENT | |
2424 HEIGHT | | | | |
2425 | | |-|-+------+-----------|------- baseline
2426 | | | | BOFF | |
2427 | |---------|-+-+ | |
2428 | | | DESCENT | |
2429 -+-+---------+-+ F_DESCENT |
2430 -------------------------+-----------+-
2431
2432 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2433 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2434 DESCENT = FONT->descent
2435 HEIGHT = FONT_HEIGHT (FONT)
2436 F_DESCENT = (F->output_data.x->font->descent
2437 - F->output_data.x->baseline_offset)
2438 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2439 */
2440
2441 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2442 (FONT_DESCENT (FONT) \
2443 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2444 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2445 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2446
2447 /* Produce glyphs/get display metrics for the display element IT is
2448 loaded with. See the description of struct display_iterator in
2449 dispextern.h for an overview of struct display_iterator. */
2450
2451 static void
2452 x_produce_glyphs (it)
2453 struct it *it;
2454 {
2455 it->glyph_not_available_p = 0;
2456
2457 if (it->what == IT_CHARACTER)
2458 {
2459 XChar2b char2b;
2460 XFontStruct *font;
2461 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2462 XCharStruct *pcm;
2463 int font_not_found_p;
2464 struct font_info *font_info;
2465 int boff; /* baseline offset */
2466 /* We may change it->multibyte_p upon unibyte<->multibyte
2467 conversion. So, save the current value now and restore it
2468 later.
2469
2470 Note: It seems that we don't have to record multibyte_p in
2471 struct glyph because the character code itself tells if or
2472 not the character is multibyte. Thus, in the future, we must
2473 consider eliminating the field `multibyte_p' in the struct
2474 glyph.
2475 */
2476 int saved_multibyte_p = it->multibyte_p;
2477
2478 /* Maybe translate single-byte characters to multibyte, or the
2479 other way. */
2480 it->char_to_display = it->c;
2481 if (!ASCII_BYTE_P (it->c))
2482 {
2483 if (unibyte_display_via_language_environment
2484 && SINGLE_BYTE_CHAR_P (it->c)
2485 && (it->c >= 0240
2486 || !NILP (Vnonascii_translation_table)))
2487 {
2488 it->char_to_display = unibyte_char_to_multibyte (it->c);
2489 it->multibyte_p = 1;
2490 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2491 face = FACE_FROM_ID (it->f, it->face_id);
2492 }
2493 else if (!SINGLE_BYTE_CHAR_P (it->c)
2494 && !it->multibyte_p)
2495 {
2496 it->multibyte_p = 1;
2497 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2498 face = FACE_FROM_ID (it->f, it->face_id);
2499 }
2500 }
2501
2502 /* Get font to use. Encode IT->char_to_display. */
2503 x_get_char_face_and_encoding (it->f, it->char_to_display,
2504 it->face_id, &char2b,
2505 it->multibyte_p);
2506 font = face->font;
2507
2508 /* When no suitable font found, use the default font. */
2509 font_not_found_p = font == NULL;
2510 if (font_not_found_p)
2511 {
2512 font = FRAME_FONT (it->f);
2513 boff = it->f->output_data.mac->baseline_offset;
2514 font_info = NULL;
2515 }
2516 else
2517 {
2518 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2519 boff = font_info->baseline_offset;
2520 if (font_info->vertical_centering)
2521 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2522 }
2523
2524 if (it->char_to_display >= ' '
2525 && (!it->multibyte_p || it->char_to_display < 128))
2526 {
2527 /* Either unibyte or ASCII. */
2528 int stretched_p;
2529
2530 it->nglyphs = 1;
2531
2532 pcm = x_per_char_metric (font, &char2b);
2533 it->ascent = FONT_BASE (font) + boff;
2534 it->descent = FONT_DESCENT (font) - boff;
2535
2536 if (pcm)
2537 {
2538 it->phys_ascent = pcm->ascent + boff;
2539 it->phys_descent = pcm->descent - boff;
2540 it->pixel_width = pcm->width;
2541 }
2542 else
2543 {
2544 it->glyph_not_available_p = 1;
2545 it->phys_ascent = FONT_BASE (font) + boff;
2546 it->phys_descent = FONT_DESCENT (font) - boff;
2547 it->pixel_width = FONT_WIDTH (font);
2548 }
2549
2550 /* If this is a space inside a region of text with
2551 `space-width' property, change its width. */
2552 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2553 if (stretched_p)
2554 it->pixel_width *= XFLOATINT (it->space_width);
2555
2556 /* If face has a box, add the box thickness to the character
2557 height. If character has a box line to the left and/or
2558 right, add the box line width to the character's width. */
2559 if (face->box != FACE_NO_BOX)
2560 {
2561 int thick = face->box_line_width;
2562
2563 if (thick > 0)
2564 {
2565 it->ascent += thick;
2566 it->descent += thick;
2567 }
2568 else
2569 thick = -thick;
2570
2571 if (it->start_of_box_run_p)
2572 it->pixel_width += thick;
2573 if (it->end_of_box_run_p)
2574 it->pixel_width += thick;
2575 }
2576
2577 /* If face has an overline, add the height of the overline
2578 (1 pixel) and a 1 pixel margin to the character height. */
2579 if (face->overline_p)
2580 it->ascent += 2;
2581
2582 take_vertical_position_into_account (it);
2583
2584 /* If we have to actually produce glyphs, do it. */
2585 if (it->glyph_row)
2586 {
2587 if (stretched_p)
2588 {
2589 /* Translate a space with a `space-width' property
2590 into a stretch glyph. */
2591 double ascent = (double) FONT_BASE (font)
2592 / FONT_HEIGHT (font);
2593 x_append_stretch_glyph (it, it->object, it->pixel_width,
2594 it->ascent + it->descent, ascent);
2595 }
2596 else
2597 x_append_glyph (it);
2598
2599 /* If characters with lbearing or rbearing are displayed
2600 in this line, record that fact in a flag of the
2601 glyph row. This is used to optimize X output code. */
2602 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2603 it->glyph_row->contains_overlapping_glyphs_p = 1;
2604 }
2605 }
2606 else if (it->char_to_display == '\n')
2607 {
2608 /* A newline has no width but we need the height of the line. */
2609 it->pixel_width = 0;
2610 it->nglyphs = 0;
2611 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2612 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2613
2614 if (face->box != FACE_NO_BOX
2615 && face->box_line_width > 0)
2616 {
2617 it->ascent += face->box_line_width;
2618 it->descent += face->box_line_width;
2619 }
2620 }
2621 else if (it->char_to_display == '\t')
2622 {
2623 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2624 int x = it->current_x + it->continuation_lines_width;
2625 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2626
2627 /* If the distance from the current position to the next tab
2628 stop is less than a canonical character width, use the
2629 tab stop after that. */
2630 if (next_tab_x - x < CANON_X_UNIT (it->f))
2631 next_tab_x += tab_width;
2632
2633 it->pixel_width = next_tab_x - x;
2634 it->nglyphs = 1;
2635 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2636 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2637
2638 if (it->glyph_row)
2639 {
2640 double ascent = (double) it->ascent / (it->ascent + it->descent);
2641 x_append_stretch_glyph (it, it->object, it->pixel_width,
2642 it->ascent + it->descent, ascent);
2643 }
2644 }
2645 else
2646 {
2647 /* A multi-byte character. Assume that the display width of the
2648 character is the width of the character multiplied by the
2649 width of the font. */
2650
2651 /* If we found a font, this font should give us the right
2652 metrics. If we didn't find a font, use the frame's
2653 default font and calculate the width of the character
2654 from the charset width; this is what old redisplay code
2655 did. */
2656 pcm = x_per_char_metric (font, &char2b);
2657 if (font_not_found_p || !pcm)
2658 {
2659 int charset = CHAR_CHARSET (it->char_to_display);
2660
2661 it->glyph_not_available_p = 1;
2662 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2663 * CHARSET_WIDTH (charset));
2664 it->phys_ascent = FONT_BASE (font) + boff;
2665 it->phys_descent = FONT_DESCENT (font) - boff;
2666 }
2667 else
2668 {
2669 it->pixel_width = pcm->width;
2670 it->phys_ascent = pcm->ascent + boff;
2671 it->phys_descent = pcm->descent - boff;
2672 if (it->glyph_row
2673 && (pcm->lbearing < 0
2674 || pcm->rbearing > pcm->width))
2675 it->glyph_row->contains_overlapping_glyphs_p = 1;
2676 }
2677 it->nglyphs = 1;
2678 it->ascent = FONT_BASE (font) + boff;
2679 it->descent = FONT_DESCENT (font) - boff;
2680 if (face->box != FACE_NO_BOX)
2681 {
2682 int thick = face->box_line_width;
2683
2684 if (thick > 0)
2685 {
2686 it->ascent += thick;
2687 it->descent += thick;
2688 }
2689 else
2690 thick = - thick;
2691
2692 if (it->start_of_box_run_p)
2693 it->pixel_width += thick;
2694 if (it->end_of_box_run_p)
2695 it->pixel_width += thick;
2696 }
2697
2698 /* If face has an overline, add the height of the overline
2699 (1 pixel) and a 1 pixel margin to the character height. */
2700 if (face->overline_p)
2701 it->ascent += 2;
2702
2703 take_vertical_position_into_account (it);
2704
2705 if (it->glyph_row)
2706 x_append_glyph (it);
2707 }
2708 it->multibyte_p = saved_multibyte_p;
2709 }
2710 else if (it->what == IT_COMPOSITION)
2711 {
2712 /* Note: A composition is represented as one glyph in the
2713 glyph matrix. There are no padding glyphs. */
2714 XChar2b char2b;
2715 XFontStruct *font;
2716 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2717 XCharStruct *pcm;
2718 int font_not_found_p;
2719 struct font_info *font_info;
2720 int boff; /* baseline offset */
2721 struct composition *cmp = composition_table[it->cmp_id];
2722
2723 /* Maybe translate single-byte characters to multibyte. */
2724 it->char_to_display = it->c;
2725 if (unibyte_display_via_language_environment
2726 && SINGLE_BYTE_CHAR_P (it->c)
2727 && (it->c >= 0240
2728 || (it->c >= 0200
2729 && !NILP (Vnonascii_translation_table))))
2730 {
2731 it->char_to_display = unibyte_char_to_multibyte (it->c);
2732 }
2733
2734 /* Get face and font to use. Encode IT->char_to_display. */
2735 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2736 face = FACE_FROM_ID (it->f, it->face_id);
2737 x_get_char_face_and_encoding (it->f, it->char_to_display,
2738 it->face_id, &char2b, it->multibyte_p);
2739 font = face->font;
2740
2741 /* When no suitable font found, use the default font. */
2742 font_not_found_p = font == NULL;
2743 if (font_not_found_p)
2744 {
2745 font = FRAME_FONT (it->f);
2746 boff = it->f->output_data.mac->baseline_offset;
2747 font_info = NULL;
2748 }
2749 else
2750 {
2751 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2752 boff = font_info->baseline_offset;
2753 if (font_info->vertical_centering)
2754 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2755 }
2756
2757 /* There are no padding glyphs, so there is only one glyph to
2758 produce for the composition. Important is that pixel_width,
2759 ascent and descent are the values of what is drawn by
2760 draw_glyphs (i.e. the values of the overall glyphs composed). */
2761 it->nglyphs = 1;
2762
2763 /* If we have not yet calculated pixel size data of glyphs of
2764 the composition for the current face font, calculate them
2765 now. Theoretically, we have to check all fonts for the
2766 glyphs, but that requires much time and memory space. So,
2767 here we check only the font of the first glyph. This leads
2768 to incorrect display very rarely, and C-l (recenter) can
2769 correct the display anyway. */
2770 if (cmp->font != (void *) font)
2771 {
2772 /* Ascent and descent of the font of the first character of
2773 this composition (adjusted by baseline offset). Ascent
2774 and descent of overall glyphs should not be less than
2775 them respectively. */
2776 int font_ascent = FONT_BASE (font) + boff;
2777 int font_descent = FONT_DESCENT (font) - boff;
2778 /* Bounding box of the overall glyphs. */
2779 int leftmost, rightmost, lowest, highest;
2780 int i, width, ascent, descent;
2781
2782 cmp->font = (void *) font;
2783
2784 /* Initialize the bounding box. */
2785 pcm = x_per_char_metric (font, &char2b);
2786 if (pcm)
2787 {
2788 width = pcm->width;
2789 ascent = pcm->ascent;
2790 descent = pcm->descent;
2791 }
2792 else
2793 {
2794 width = FONT_WIDTH (font);
2795 ascent = FONT_BASE (font);
2796 descent = FONT_DESCENT (font);
2797 }
2798
2799 rightmost = width;
2800 lowest = - descent + boff;
2801 highest = ascent + boff;
2802 leftmost = 0;
2803
2804 if (font_info
2805 && font_info->default_ascent
2806 && CHAR_TABLE_P (Vuse_default_ascent)
2807 && !NILP (Faref (Vuse_default_ascent,
2808 make_number (it->char_to_display))))
2809 highest = font_info->default_ascent + boff;
2810
2811 /* Draw the first glyph at the normal position. It may be
2812 shifted to right later if some other glyphs are drawn at
2813 the left. */
2814 cmp->offsets[0] = 0;
2815 cmp->offsets[1] = boff;
2816
2817 /* Set cmp->offsets for the remaining glyphs. */
2818 for (i = 1; i < cmp->glyph_len; i++)
2819 {
2820 int left, right, btm, top;
2821 int ch = COMPOSITION_GLYPH (cmp, i);
2822 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2823
2824 face = FACE_FROM_ID (it->f, face_id);
2825 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2826 it->multibyte_p);
2827 font = face->font;
2828 if (font == NULL)
2829 {
2830 font = FRAME_FONT (it->f);
2831 boff = it->f->output_data.mac->baseline_offset;
2832 font_info = NULL;
2833 }
2834 else
2835 {
2836 font_info
2837 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2838 boff = font_info->baseline_offset;
2839 if (font_info->vertical_centering)
2840 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2841 }
2842
2843 pcm = x_per_char_metric (font, &char2b);
2844 if (pcm)
2845 {
2846 width = pcm->width;
2847 ascent = pcm->ascent;
2848 descent = pcm->descent;
2849 }
2850 else
2851 {
2852 width = FONT_WIDTH (font);
2853 ascent = 1;
2854 descent = 0;
2855 }
2856
2857 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2858 {
2859 /* Relative composition with or without
2860 alternate chars. */
2861 left = (leftmost + rightmost - width) / 2;
2862 btm = - descent + boff;
2863 if (font_info && font_info->relative_compose
2864 && (! CHAR_TABLE_P (Vignore_relative_composition)
2865 || NILP (Faref (Vignore_relative_composition,
2866 make_number (ch)))))
2867 {
2868
2869 if (- descent >= font_info->relative_compose)
2870 /* One extra pixel between two glyphs. */
2871 btm = highest + 1;
2872 else if (ascent <= 0)
2873 /* One extra pixel between two glyphs. */
2874 btm = lowest - 1 - ascent - descent;
2875 }
2876 }
2877 else
2878 {
2879 /* A composition rule is specified by an integer
2880 value that encodes global and new reference
2881 points (GREF and NREF). GREF and NREF are
2882 specified by numbers as below:
2883
2884 0---1---2 -- ascent
2885 | |
2886 | |
2887 | |
2888 9--10--11 -- center
2889 | |
2890 ---3---4---5--- baseline
2891 | |
2892 6---7---8 -- descent
2893 */
2894 int rule = COMPOSITION_RULE (cmp, i);
2895 int gref, nref, grefx, grefy, nrefx, nrefy;
2896
2897 COMPOSITION_DECODE_RULE (rule, gref, nref);
2898 grefx = gref % 3, nrefx = nref % 3;
2899 grefy = gref / 3, nrefy = nref / 3;
2900
2901 left = (leftmost
2902 + grefx * (rightmost - leftmost) / 2
2903 - nrefx * width / 2);
2904 btm = ((grefy == 0 ? highest
2905 : grefy == 1 ? 0
2906 : grefy == 2 ? lowest
2907 : (highest + lowest) / 2)
2908 - (nrefy == 0 ? ascent + descent
2909 : nrefy == 1 ? descent - boff
2910 : nrefy == 2 ? 0
2911 : (ascent + descent) / 2));
2912 }
2913
2914 cmp->offsets[i * 2] = left;
2915 cmp->offsets[i * 2 + 1] = btm + descent;
2916
2917 /* Update the bounding box of the overall glyphs. */
2918 right = left + width;
2919 top = btm + descent + ascent;
2920 if (left < leftmost)
2921 leftmost = left;
2922 if (right > rightmost)
2923 rightmost = right;
2924 if (top > highest)
2925 highest = top;
2926 if (btm < lowest)
2927 lowest = btm;
2928 }
2929
2930 /* If there are glyphs whose x-offsets are negative,
2931 shift all glyphs to the right and make all x-offsets
2932 non-negative. */
2933 if (leftmost < 0)
2934 {
2935 for (i = 0; i < cmp->glyph_len; i++)
2936 cmp->offsets[i * 2] -= leftmost;
2937 rightmost -= leftmost;
2938 }
2939
2940 cmp->pixel_width = rightmost;
2941 cmp->ascent = highest;
2942 cmp->descent = - lowest;
2943 if (cmp->ascent < font_ascent)
2944 cmp->ascent = font_ascent;
2945 if (cmp->descent < font_descent)
2946 cmp->descent = font_descent;
2947 }
2948
2949 it->pixel_width = cmp->pixel_width;
2950 it->ascent = it->phys_ascent = cmp->ascent;
2951 it->descent = it->phys_descent = cmp->descent;
2952
2953 if (face->box != FACE_NO_BOX)
2954 {
2955 int thick = face->box_line_width;
2956
2957 if (thick > 0)
2958 {
2959 it->ascent += thick;
2960 it->descent += thick;
2961 }
2962 else
2963 thick = - thick;
2964
2965 if (it->start_of_box_run_p)
2966 it->pixel_width += thick;
2967 if (it->end_of_box_run_p)
2968 it->pixel_width += thick;
2969 }
2970
2971 /* If face has an overline, add the height of the overline
2972 (1 pixel) and a 1 pixel margin to the character height. */
2973 if (face->overline_p)
2974 it->ascent += 2;
2975
2976 take_vertical_position_into_account (it);
2977
2978 if (it->glyph_row)
2979 x_append_composite_glyph (it);
2980 }
2981 else if (it->what == IT_IMAGE)
2982 x_produce_image_glyph (it);
2983 else if (it->what == IT_STRETCH)
2984 x_produce_stretch_glyph (it);
2985
2986 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2987 because this isn't true for images with `:ascent 100'. */
2988 xassert (it->ascent >= 0 && it->descent >= 0);
2989 if (it->area == TEXT_AREA)
2990 it->current_x += it->pixel_width;
2991
2992 it->descent += it->extra_line_spacing;
2993
2994 it->max_ascent = max (it->max_ascent, it->ascent);
2995 it->max_descent = max (it->max_descent, it->descent);
2996 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2997 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2998 }
2999
3000
3001 /* Estimate the pixel height of the mode or top line on frame F.
3002 FACE_ID specifies what line's height to estimate. */
3003
3004 int
3005 x_estimate_mode_line_height (f, face_id)
3006 struct frame *f;
3007 enum face_id face_id;
3008 {
3009 int height = FONT_HEIGHT (FRAME_FONT (f));
3010
3011 /* This function is called so early when Emacs starts that the face
3012 cache and mode line face are not yet initialized. */
3013 if (FRAME_FACE_CACHE (f))
3014 {
3015 struct face *face = FACE_FROM_ID (f, face_id);
3016 if (face)
3017 {
3018 if (face->font)
3019 height = FONT_HEIGHT (face->font);
3020 if (face->box_line_width > 0)
3021 height += 2 * face->box_line_width;
3022 }
3023 }
3024
3025 return height;
3026 }
3027
3028 \f
3029 /***********************************************************************
3030 Glyph display
3031 ***********************************************************************/
3032
3033 /* A sequence of glyphs to be drawn in the same face.
3034
3035 This data structure is not really completely X specific, so it
3036 could possibly, at least partially, be useful for other systems. It
3037 is currently not part of the external redisplay interface because
3038 it's not clear what other systems will need. */
3039
3040 struct glyph_string
3041 {
3042 /* X-origin of the string. */
3043 int x;
3044
3045 /* Y-origin and y-position of the base line of this string. */
3046 int y, ybase;
3047
3048 /* The width of the string, not including a face extension. */
3049 int width;
3050
3051 /* The width of the string, including a face extension. */
3052 int background_width;
3053
3054 /* The height of this string. This is the height of the line this
3055 string is drawn in, and can be different from the height of the
3056 font the string is drawn in. */
3057 int height;
3058
3059 /* Number of pixels this string overwrites in front of its x-origin.
3060 This number is zero if the string has an lbearing >= 0; it is
3061 -lbearing, if the string has an lbearing < 0. */
3062 int left_overhang;
3063
3064 /* Number of pixels this string overwrites past its right-most
3065 nominal x-position, i.e. x + width. Zero if the string's
3066 rbearing is <= its nominal width, rbearing - width otherwise. */
3067 int right_overhang;
3068
3069 /* The frame on which the glyph string is drawn. */
3070 struct frame *f;
3071
3072 /* The window on which the glyph string is drawn. */
3073 struct window *w;
3074
3075 /* X display and window for convenience. */
3076 Display *display;
3077 Window window;
3078
3079 /* The glyph row for which this string was built. It determines the
3080 y-origin and height of the string. */
3081 struct glyph_row *row;
3082
3083 /* The area within row. */
3084 enum glyph_row_area area;
3085
3086 /* Characters to be drawn, and number of characters. */
3087 XChar2b *char2b;
3088 int nchars;
3089
3090 /* A face-override for drawing cursors, mouse face and similar. */
3091 enum draw_glyphs_face hl;
3092
3093 /* Face in which this string is to be drawn. */
3094 struct face *face;
3095
3096 /* Font in which this string is to be drawn. */
3097 XFontStruct *font;
3098
3099 /* Font info for this string. */
3100 struct font_info *font_info;
3101
3102 /* Non-null means this string describes (part of) a composition.
3103 All characters from char2b are drawn composed. */
3104 struct composition *cmp;
3105
3106 /* Index of this glyph string's first character in the glyph
3107 definition of CMP. If this is zero, this glyph string describes
3108 the first character of a composition. */
3109 int gidx;
3110
3111 /* 1 means this glyph strings face has to be drawn to the right end
3112 of the window's drawing area. */
3113 unsigned extends_to_end_of_line_p : 1;
3114
3115 /* 1 means the background of this string has been drawn. */
3116 unsigned background_filled_p : 1;
3117
3118 /* 1 means glyph string must be drawn with 16-bit functions. */
3119 unsigned two_byte_p : 1;
3120
3121 /* 1 means that the original font determined for drawing this glyph
3122 string could not be loaded. The member `font' has been set to
3123 the frame's default font in this case. */
3124 unsigned font_not_found_p : 1;
3125
3126 /* 1 means that the face in which this glyph string is drawn has a
3127 stipple pattern. */
3128 unsigned stippled_p : 1;
3129
3130 /* 1 means only the foreground of this glyph string must be drawn,
3131 and we should use the physical height of the line this glyph
3132 string appears in as clip rect. */
3133 unsigned for_overlaps_p : 1;
3134
3135 /* The GC to use for drawing this glyph string. */
3136 GC gc;
3137
3138 /* A pointer to the first glyph in the string. This glyph
3139 corresponds to char2b[0]. Needed to draw rectangles if
3140 font_not_found_p is 1. */
3141 struct glyph *first_glyph;
3142
3143 /* Image, if any. */
3144 struct image *img;
3145
3146 struct glyph_string *next, *prev;
3147 };
3148
3149
3150 #if 0
3151
3152 static void
3153 x_dump_glyph_string (s)
3154 struct glyph_string *s;
3155 {
3156 fprintf (stderr, "glyph string\n");
3157 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3158 s->x, s->y, s->width, s->height);
3159 fprintf (stderr, " ybase = %d\n", s->ybase);
3160 fprintf (stderr, " hl = %d\n", s->hl);
3161 fprintf (stderr, " left overhang = %d, right = %d\n",
3162 s->left_overhang, s->right_overhang);
3163 fprintf (stderr, " nchars = %d\n", s->nchars);
3164 fprintf (stderr, " extends to end of line = %d\n",
3165 s->extends_to_end_of_line_p);
3166 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3167 fprintf (stderr, " bg width = %d\n", s->background_width);
3168 }
3169
3170 #endif /* GLYPH_DEBUG */
3171
3172
3173
3174 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3175 struct glyph_string **,
3176 struct glyph_string *,
3177 struct glyph_string *));
3178 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3179 struct glyph_string **,
3180 struct glyph_string *,
3181 struct glyph_string *));
3182 static void x_append_glyph_string P_ ((struct glyph_string **,
3183 struct glyph_string **,
3184 struct glyph_string *));
3185 static int x_left_overwritten P_ ((struct glyph_string *));
3186 static int x_left_overwriting P_ ((struct glyph_string *));
3187 static int x_right_overwritten P_ ((struct glyph_string *));
3188 static int x_right_overwriting P_ ((struct glyph_string *));
3189 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3190 int));
3191 static void x_init_glyph_string P_ ((struct glyph_string *,
3192 XChar2b *, struct window *,
3193 struct glyph_row *,
3194 enum glyph_row_area, int,
3195 enum draw_glyphs_face));
3196 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3197 enum glyph_row_area, int, int,
3198 enum draw_glyphs_face, int));
3199 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3200 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3201 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3202 int));
3203 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3204 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3205 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3206 static void x_draw_glyph_string P_ ((struct glyph_string *));
3207 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3208 static void x_set_cursor_gc P_ ((struct glyph_string *));
3209 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3210 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3211 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3212 int *, int *));
3213 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
3214 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3215 unsigned long *, double, int));*/
3216 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3217 double, int, unsigned long));
3218 static void x_setup_relief_colors P_ ((struct glyph_string *));
3219 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3220 static void x_draw_image_relief P_ ((struct glyph_string *));
3221 static void x_draw_image_foreground P_ ((struct glyph_string *));
3222 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3223 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3224 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3225 int, int, int));
3226 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
3227 int, int, int, int, Rect *));
3228 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
3229 int, int, int, Rect *));
3230 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3231 enum glyph_row_area));
3232 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3233 struct glyph_row *,
3234 enum glyph_row_area, int, int));
3235
3236 #if GLYPH_DEBUG
3237 static void x_check_font P_ ((struct frame *, XFontStruct *));
3238 #endif
3239
3240
3241 /* Append the list of glyph strings with head H and tail T to the list
3242 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3243
3244 static INLINE void
3245 x_append_glyph_string_lists (head, tail, h, t)
3246 struct glyph_string **head, **tail;
3247 struct glyph_string *h, *t;
3248 {
3249 if (h)
3250 {
3251 if (*head)
3252 (*tail)->next = h;
3253 else
3254 *head = h;
3255 h->prev = *tail;
3256 *tail = t;
3257 }
3258 }
3259
3260
3261 /* Prepend the list of glyph strings with head H and tail T to the
3262 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3263 result. */
3264
3265 static INLINE void
3266 x_prepend_glyph_string_lists (head, tail, h, t)
3267 struct glyph_string **head, **tail;
3268 struct glyph_string *h, *t;
3269 {
3270 if (h)
3271 {
3272 if (*head)
3273 (*head)->prev = t;
3274 else
3275 *tail = t;
3276 t->next = *head;
3277 *head = h;
3278 }
3279 }
3280
3281
3282 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3283 Set *HEAD and *TAIL to the resulting list. */
3284
3285 static INLINE void
3286 x_append_glyph_string (head, tail, s)
3287 struct glyph_string **head, **tail;
3288 struct glyph_string *s;
3289 {
3290 s->next = s->prev = NULL;
3291 x_append_glyph_string_lists (head, tail, s, s);
3292 }
3293
3294
3295 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3296 face. */
3297
3298 static void
3299 x_set_cursor_gc (s)
3300 struct glyph_string *s;
3301 {
3302 if (s->font == FRAME_FONT (s->f)
3303 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3304 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3305 && !s->cmp)
3306 s->gc = s->f->output_data.mac->cursor_gc;
3307 else
3308 {
3309 /* Cursor on non-default face: must merge. */
3310 XGCValues xgcv;
3311 unsigned long mask;
3312
3313 xgcv.background = s->f->output_data.mac->cursor_pixel;
3314 xgcv.foreground = s->face->background;
3315
3316 /* If the glyph would be invisible, try a different foreground. */
3317 if (xgcv.foreground == xgcv.background)
3318 xgcv.foreground = s->face->foreground;
3319 if (xgcv.foreground == xgcv.background)
3320 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3321 if (xgcv.foreground == xgcv.background)
3322 xgcv.foreground = s->face->foreground;
3323
3324 /* Make sure the cursor is distinct from text in this face. */
3325 if (xgcv.background == s->face->background
3326 && xgcv.foreground == s->face->foreground)
3327 {
3328 xgcv.background = s->face->foreground;
3329 xgcv.foreground = s->face->background;
3330 }
3331
3332 IF_DEBUG (x_check_font (s->f, s->font));
3333 xgcv.font = s->font;
3334 mask = GCForeground | GCBackground | GCFont;
3335
3336 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3337 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3338 mask, &xgcv);
3339 else
3340 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3341 = XCreateGC (s->display, s->window, mask, &xgcv);
3342
3343 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3344 }
3345 }
3346
3347
3348 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3349
3350 static void
3351 x_set_mouse_face_gc (s)
3352 struct glyph_string *s;
3353 {
3354 int face_id;
3355 struct face *face;
3356
3357 /* What face has to be used last for the mouse face? */
3358 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3359 face = FACE_FROM_ID (s->f, face_id);
3360 if (face == NULL)
3361 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3362
3363 if (s->first_glyph->type == CHAR_GLYPH)
3364 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3365 else
3366 face_id = FACE_FOR_CHAR (s->f, face, 0);
3367 s->face = FACE_FROM_ID (s->f, face_id);
3368 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3369
3370 /* If font in this face is same as S->font, use it. */
3371 if (s->font == s->face->font)
3372 s->gc = s->face->gc;
3373 else
3374 {
3375 /* Otherwise construct scratch_cursor_gc with values from FACE
3376 but font FONT. */
3377 XGCValues xgcv;
3378 unsigned long mask;
3379
3380 xgcv.background = s->face->background;
3381 xgcv.foreground = s->face->foreground;
3382 IF_DEBUG (x_check_font (s->f, s->font));
3383 xgcv.font = s->font;
3384 mask = GCForeground | GCBackground | GCFont;
3385
3386 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3387 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3388 mask, &xgcv);
3389 else
3390 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3391 = XCreateGC (s->display, s->window, mask, &xgcv);
3392
3393 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3394 }
3395
3396 xassert (s->gc != 0);
3397 }
3398
3399
3400 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3401 Faces to use in the mode line have already been computed when the
3402 matrix was built, so there isn't much to do, here. */
3403
3404 static INLINE void
3405 x_set_mode_line_face_gc (s)
3406 struct glyph_string *s;
3407 {
3408 s->gc = s->face->gc;
3409 }
3410
3411
3412 /* Set S->gc of glyph string S for drawing that glyph string. Set
3413 S->stippled_p to a non-zero value if the face of S has a stipple
3414 pattern. */
3415
3416 static INLINE void
3417 x_set_glyph_string_gc (s)
3418 struct glyph_string *s;
3419 {
3420 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3421
3422 if (s->hl == DRAW_NORMAL_TEXT)
3423 {
3424 s->gc = s->face->gc;
3425 s->stippled_p = s->face->stipple != 0;
3426 }
3427 else if (s->hl == DRAW_INVERSE_VIDEO)
3428 {
3429 x_set_mode_line_face_gc (s);
3430 s->stippled_p = s->face->stipple != 0;
3431 }
3432 else if (s->hl == DRAW_CURSOR)
3433 {
3434 x_set_cursor_gc (s);
3435 s->stippled_p = 0;
3436 }
3437 else if (s->hl == DRAW_MOUSE_FACE)
3438 {
3439 x_set_mouse_face_gc (s);
3440 s->stippled_p = s->face->stipple != 0;
3441 }
3442 else if (s->hl == DRAW_IMAGE_RAISED
3443 || s->hl == DRAW_IMAGE_SUNKEN)
3444 {
3445 s->gc = s->face->gc;
3446 s->stippled_p = s->face->stipple != 0;
3447 }
3448 else
3449 {
3450 s->gc = s->face->gc;
3451 s->stippled_p = s->face->stipple != 0;
3452 }
3453
3454 /* GC must have been set. */
3455 xassert (s->gc != 0);
3456 }
3457
3458
3459 /* Return in *R the clipping rectangle for glyph string S. */
3460
3461 static void
3462 x_get_glyph_string_clip_rect (s, r)
3463 struct glyph_string *s;
3464 Rect *r;
3465 {
3466 int r_height, r_width;
3467
3468 if (s->row->full_width_p)
3469 {
3470 /* Draw full-width. X coordinates are relative to S->w->left. */
3471 int canon_x = CANON_X_UNIT (s->f);
3472
3473 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3474 r_width = XFASTINT (s->w->width) * canon_x;
3475
3476 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3477 {
3478 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3479 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3480 r->left -= width;
3481 }
3482
3483 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3484
3485 /* Unless displaying a mode or menu bar line, which are always
3486 fully visible, clip to the visible part of the row. */
3487 if (s->w->pseudo_window_p)
3488 r_height = s->row->visible_height;
3489 else
3490 r_height = s->height;
3491 }
3492 else
3493 {
3494 /* This is a text line that may be partially visible. */
3495 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3496 r_width = window_box_width (s->w, s->area);
3497 r_height = s->row->visible_height;
3498 }
3499
3500 /* If S draws overlapping rows, it's sufficient to use the top and
3501 bottom of the window for clipping because this glyph string
3502 intentionally draws over other lines. */
3503 if (s->for_overlaps_p)
3504 {
3505 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3506 r_height = window_text_bottom_y (s->w) - r->top;
3507 }
3508 else
3509 {
3510 /* Don't use S->y for clipping because it doesn't take partially
3511 visible lines into account. For example, it can be negative for
3512 partially visible lines at the top of a window. */
3513 if (!s->row->full_width_p
3514 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3515 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3516 else
3517 r->top = max (0, s->row->y);
3518
3519 /* If drawing a tool-bar window, draw it over the internal border
3520 at the top of the window. */
3521 if (s->w == XWINDOW (s->f->tool_bar_window))
3522 r->top -= s->f->output_data.mac->internal_border_width;
3523 }
3524
3525 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3526
3527 r->bottom = r->top + r_height;
3528 r->right = r->left + r_width;
3529 }
3530
3531
3532 /* Set clipping for output of glyph string S. S may be part of a mode
3533 line or menu if we don't have X toolkit support. */
3534
3535 static INLINE void
3536 x_set_glyph_string_clipping (s)
3537 struct glyph_string *s;
3538 {
3539 Rect r;
3540 x_get_glyph_string_clip_rect (s, &r);
3541 mac_set_clip_rectangle (s->display, s->window, &r);
3542 }
3543
3544
3545 /* Compute left and right overhang of glyph string S. If S is a glyph
3546 string for a composition, assume overhangs don't exist. */
3547
3548 static INLINE void
3549 x_compute_glyph_string_overhangs (s)
3550 struct glyph_string *s;
3551 {
3552 if (s->cmp == NULL
3553 && s->first_glyph->type == CHAR_GLYPH)
3554 {
3555 XCharStruct cs;
3556 int direction, font_ascent, font_descent;
3557 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3558 &font_ascent, &font_descent, &cs);
3559 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3560 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3561 }
3562 }
3563
3564
3565 /* Compute overhangs and x-positions for glyph string S and its
3566 predecessors, or successors. X is the starting x-position for S.
3567 BACKWARD_P non-zero means process predecessors. */
3568
3569 static void
3570 x_compute_overhangs_and_x (s, x, backward_p)
3571 struct glyph_string *s;
3572 int x;
3573 int backward_p;
3574 {
3575 if (backward_p)
3576 {
3577 while (s)
3578 {
3579 x_compute_glyph_string_overhangs (s);
3580 x -= s->width;
3581 s->x = x;
3582 s = s->prev;
3583 }
3584 }
3585 else
3586 {
3587 while (s)
3588 {
3589 x_compute_glyph_string_overhangs (s);
3590 s->x = x;
3591 x += s->width;
3592 s = s->next;
3593 }
3594 }
3595 }
3596
3597
3598 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3599 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3600 assumed to be zero. */
3601
3602 void
3603 x_get_glyph_overhangs (glyph, f, left, right)
3604 struct glyph *glyph;
3605 struct frame *f;
3606 int *left, *right;
3607 {
3608 *left = *right = 0;
3609
3610 if (glyph->type == CHAR_GLYPH)
3611 {
3612 XFontStruct *font;
3613 struct face *face;
3614 struct font_info *font_info;
3615 XChar2b char2b;
3616 XCharStruct *pcm;
3617
3618 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3619 font = face->font;
3620 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3621 if (font
3622 && (pcm = x_per_char_metric (font, &char2b)))
3623 {
3624 if (pcm->rbearing > pcm->width)
3625 *right = pcm->rbearing - pcm->width;
3626 if (pcm->lbearing < 0)
3627 *left = -pcm->lbearing;
3628 }
3629 }
3630 }
3631
3632
3633 /* Return the index of the first glyph preceding glyph string S that
3634 is overwritten by S because of S's left overhang. Value is -1
3635 if no glyphs are overwritten. */
3636
3637 static int
3638 x_left_overwritten (s)
3639 struct glyph_string *s;
3640 {
3641 int k;
3642
3643 if (s->left_overhang)
3644 {
3645 int x = 0, i;
3646 struct glyph *glyphs = s->row->glyphs[s->area];
3647 int first = s->first_glyph - glyphs;
3648
3649 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3650 x -= glyphs[i].pixel_width;
3651
3652 k = i + 1;
3653 }
3654 else
3655 k = -1;
3656
3657 return k;
3658 }
3659
3660
3661 /* Return the index of the first glyph preceding glyph string S that
3662 is overwriting S because of its right overhang. Value is -1 if no
3663 glyph in front of S overwrites S. */
3664
3665 static int
3666 x_left_overwriting (s)
3667 struct glyph_string *s;
3668 {
3669 int i, k, x;
3670 struct glyph *glyphs = s->row->glyphs[s->area];
3671 int first = s->first_glyph - glyphs;
3672
3673 k = -1;
3674 x = 0;
3675 for (i = first - 1; i >= 0; --i)
3676 {
3677 int left, right;
3678 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3679 if (x + right > 0)
3680 k = i;
3681 x -= glyphs[i].pixel_width;
3682 }
3683
3684 return k;
3685 }
3686
3687
3688 /* Return the index of the last glyph following glyph string S that is
3689 not overwritten by S because of S's right overhang. Value is -1 if
3690 no such glyph is found. */
3691
3692 static int
3693 x_right_overwritten (s)
3694 struct glyph_string *s;
3695 {
3696 int k = -1;
3697
3698 if (s->right_overhang)
3699 {
3700 int x = 0, i;
3701 struct glyph *glyphs = s->row->glyphs[s->area];
3702 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3703 int end = s->row->used[s->area];
3704
3705 for (i = first; i < end && s->right_overhang > x; ++i)
3706 x += glyphs[i].pixel_width;
3707
3708 k = i;
3709 }
3710
3711 return k;
3712 }
3713
3714
3715 /* Return the index of the last glyph following glyph string S that
3716 overwrites S because of its left overhang. Value is negative
3717 if no such glyph is found. */
3718
3719 static int
3720 x_right_overwriting (s)
3721 struct glyph_string *s;
3722 {
3723 int i, k, x;
3724 int end = s->row->used[s->area];
3725 struct glyph *glyphs = s->row->glyphs[s->area];
3726 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3727
3728 k = -1;
3729 x = 0;
3730 for (i = first; i < end; ++i)
3731 {
3732 int left, right;
3733 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3734 if (x - left < 0)
3735 k = i;
3736 x += glyphs[i].pixel_width;
3737 }
3738
3739 return k;
3740 }
3741
3742
3743 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3744
3745 static INLINE void
3746 x_clear_glyph_string_rect (s, x, y, w, h)
3747 struct glyph_string *s;
3748 int x, y, w, h;
3749 {
3750 XGCValues xgcv;
3751
3752 xgcv.foreground = s->gc->background;
3753 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3754 }
3755
3756
3757 /* Draw the background of glyph_string S. If S->background_filled_p
3758 is non-zero don't draw it. FORCE_P non-zero means draw the
3759 background even if it wouldn't be drawn normally. This is used
3760 when a string preceding S draws into the background of S, or S
3761 contains the first component of a composition. */
3762
3763 static void
3764 x_draw_glyph_string_background (s, force_p)
3765 struct glyph_string *s;
3766 int force_p;
3767 {
3768 /* Nothing to do if background has already been drawn or if it
3769 shouldn't be drawn in the first place. */
3770 if (!s->background_filled_p)
3771 {
3772 int box_line_width = max (s->face->box_line_width, 0);
3773
3774 #if 0 /* MAC_TODO: stipple */
3775 if (s->stippled_p)
3776 {
3777 /* Fill background with a stipple pattern. */
3778 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3779 XFillRectangle (s->display, s->window, s->gc, s->x,
3780 s->y + box_line_width,
3781 s->background_width,
3782 s->height - 2 * box_line_width);
3783 XSetFillStyle (s->display, s->gc, FillSolid);
3784 s->background_filled_p = 1;
3785 }
3786 else
3787 #endif
3788 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3789 || s->font_not_found_p
3790 || s->extends_to_end_of_line_p
3791 || force_p)
3792 {
3793 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3794 s->background_width,
3795 s->height - 2 * box_line_width);
3796 s->background_filled_p = 1;
3797 }
3798 }
3799 }
3800
3801
3802 /* Draw the foreground of glyph string S. */
3803
3804 static void
3805 x_draw_glyph_string_foreground (s)
3806 struct glyph_string *s;
3807 {
3808 int i, x;
3809
3810 /* If first glyph of S has a left box line, start drawing the text
3811 of S to the right of that box line. */
3812 if (s->face->box != FACE_NO_BOX
3813 && s->first_glyph->left_box_line_p)
3814 x = s->x + abs (s->face->box_line_width);
3815 else
3816 x = s->x;
3817
3818 /* Draw characters of S as rectangles if S's font could not be
3819 loaded. */
3820 if (s->font_not_found_p)
3821 {
3822 for (i = 0; i < s->nchars; ++i)
3823 {
3824 struct glyph *g = s->first_glyph + i;
3825 mac_draw_rectangle (s->display, s->window,
3826 s->gc, x, s->y, g->pixel_width - 1,
3827 s->height - 1);
3828 x += g->pixel_width;
3829 }
3830 }
3831 else
3832 {
3833 char *char1b = (char *) s->char2b;
3834 int boff = s->font_info->baseline_offset;
3835
3836 if (s->font_info->vertical_centering)
3837 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3838
3839 /* If we can use 8-bit functions, condense S->char2b. */
3840 if (!s->two_byte_p)
3841 for (i = 0; i < s->nchars; ++i)
3842 char1b[i] = s->char2b[i].byte2;
3843
3844 /* Draw text with XDrawString if background has already been
3845 filled. Otherwise, use XDrawImageString. (Note that
3846 XDrawImageString is usually faster than XDrawString.) Always
3847 use XDrawImageString when drawing the cursor so that there is
3848 no chance that characters under a box cursor are invisible. */
3849 if (s->for_overlaps_p
3850 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3851 {
3852 /* Draw characters with 16-bit or 8-bit functions. */
3853 if (s->two_byte_p)
3854 XDrawString16 (s->display, s->window, s->gc, x,
3855 s->ybase - boff, s->char2b, s->nchars);
3856 else
3857 XDrawString (s->display, s->window, s->gc, x,
3858 s->ybase - boff, char1b, s->nchars);
3859 }
3860 else
3861 {
3862 if (s->two_byte_p)
3863 XDrawImageString16 (s->display, s->window, s->gc, x,
3864 s->ybase - boff, s->char2b, s->nchars);
3865 else
3866 XDrawImageString (s->display, s->window, s->gc, x,
3867 s->ybase - boff, char1b, s->nchars);
3868 }
3869 }
3870 }
3871
3872 /* Draw the foreground of composite glyph string S. */
3873
3874 static void
3875 x_draw_composite_glyph_string_foreground (s)
3876 struct glyph_string *s;
3877 {
3878 int i, x;
3879
3880 /* If first glyph of S has a left box line, start drawing the text
3881 of S to the right of that box line. */
3882 if (s->face->box != FACE_NO_BOX
3883 && s->first_glyph->left_box_line_p)
3884 x = s->x + abs (s->face->box_line_width);
3885 else
3886 x = s->x;
3887
3888 /* S is a glyph string for a composition. S->gidx is the index of
3889 the first character drawn for glyphs of this composition.
3890 S->gidx == 0 means we are drawing the very first character of
3891 this composition. */
3892
3893 /* Draw a rectangle for the composition if the font for the very
3894 first character of the composition could not be loaded. */
3895 if (s->font_not_found_p)
3896 {
3897 if (s->gidx == 0)
3898 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3899 s->width - 1, s->height - 1);
3900 }
3901 else
3902 {
3903 for (i = 0; i < s->nchars; i++, ++s->gidx)
3904 XDrawString16 (s->display, s->window, s->gc,
3905 x + s->cmp->offsets[s->gidx * 2],
3906 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3907 s->char2b + i, 1);
3908 }
3909 }
3910
3911
3912 #ifdef USE_X_TOOLKIT
3913
3914 static struct frame *x_frame_of_widget P_ ((Widget));
3915
3916
3917 /* Return the frame on which widget WIDGET is used.. Abort if frame
3918 cannot be determined. */
3919
3920 static struct frame *
3921 x_frame_of_widget (widget)
3922 Widget widget;
3923 {
3924 struct x_display_info *dpyinfo;
3925 Lisp_Object tail;
3926 struct frame *f;
3927
3928 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3929
3930 /* Find the top-level shell of the widget. Note that this function
3931 can be called when the widget is not yet realized, so XtWindow
3932 (widget) == 0. That's the reason we can't simply use
3933 x_any_window_to_frame. */
3934 while (!XtIsTopLevelShell (widget))
3935 widget = XtParent (widget);
3936
3937 /* Look for a frame with that top-level widget. Allocate the color
3938 on that frame to get the right gamma correction value. */
3939 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3940 if (GC_FRAMEP (XCAR (tail))
3941 && (f = XFRAME (XCAR (tail)),
3942 (f->output_data.nothing != 1
3943 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3944 && f->output_data.x->widget == widget)
3945 return f;
3946
3947 abort ();
3948 }
3949
3950
3951 /* Allocate the color COLOR->pixel on the screen and display of
3952 widget WIDGET in colormap CMAP. If an exact match cannot be
3953 allocated, try the nearest color available. Value is non-zero
3954 if successful. This is called from lwlib. */
3955
3956 int
3957 x_alloc_nearest_color_for_widget (widget, cmap, color)
3958 Widget widget;
3959 Colormap cmap;
3960 XColor *color;
3961 {
3962 struct frame *f = x_frame_of_widget (widget);
3963 return x_alloc_nearest_color (f, cmap, color);
3964 }
3965
3966
3967 #endif /* USE_X_TOOLKIT */
3968
3969 #if 0 /* MAC_TODO */
3970
3971 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3972 CMAP. If an exact match can't be allocated, try the nearest color
3973 available. Value is non-zero if successful. Set *COLOR to the
3974 color allocated. */
3975
3976 int
3977 x_alloc_nearest_color (f, cmap, color)
3978 struct frame *f;
3979 Colormap cmap;
3980 XColor *color;
3981 {
3982 Display *display = FRAME_X_DISPLAY (f);
3983 Screen *screen = FRAME_X_SCREEN (f);
3984 int rc;
3985
3986 gamma_correct (f, color);
3987 rc = XAllocColor (display, cmap, color);
3988 if (rc == 0)
3989 {
3990 /* If we got to this point, the colormap is full, so we're going
3991 to try to get the next closest color. The algorithm used is
3992 a least-squares matching, which is what X uses for closest
3993 color matching with StaticColor visuals. */
3994 int nearest, i;
3995 unsigned long nearest_delta = ~0;
3996 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3997 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3998
3999 for (i = 0; i < ncells; ++i)
4000 cells[i].pixel = i;
4001 XQueryColors (display, cmap, cells, ncells);
4002
4003 for (nearest = i = 0; i < ncells; ++i)
4004 {
4005 long dred = (color->red >> 8) - (cells[i].red >> 8);
4006 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
4007 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
4008 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
4009
4010 if (delta < nearest_delta)
4011 {
4012 nearest = i;
4013 nearest_delta = delta;
4014 }
4015 }
4016
4017 color->red = cells[nearest].red;
4018 color->green = cells[nearest].green;
4019 color->blue = cells[nearest].blue;
4020 rc = XAllocColor (display, cmap, color);
4021 }
4022
4023 #ifdef DEBUG_X_COLORS
4024 if (rc)
4025 register_color (color->pixel);
4026 #endif /* DEBUG_X_COLORS */
4027
4028 return rc;
4029 }
4030
4031
4032 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4033 It's necessary to do this instead of just using PIXEL directly to
4034 get color reference counts right. */
4035
4036 unsigned long
4037 x_copy_color (f, pixel)
4038 struct frame *f;
4039 unsigned long pixel;
4040 {
4041 XColor color;
4042
4043 color.pixel = pixel;
4044 BLOCK_INPUT;
4045 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4046 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4047 UNBLOCK_INPUT;
4048 #ifdef DEBUG_X_COLORS
4049 register_color (pixel);
4050 #endif
4051 return color.pixel;
4052 }
4053
4054
4055 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4056 It's necessary to do this instead of just using PIXEL directly to
4057 get color reference counts right. */
4058
4059 unsigned long
4060 x_copy_dpy_color (dpy, cmap, pixel)
4061 Display *dpy;
4062 Colormap cmap;
4063 unsigned long pixel;
4064 {
4065 XColor color;
4066
4067 color.pixel = pixel;
4068 BLOCK_INPUT;
4069 XQueryColor (dpy, cmap, &color);
4070 XAllocColor (dpy, cmap, &color);
4071 UNBLOCK_INPUT;
4072 #ifdef DEBUG_X_COLORS
4073 register_color (pixel);
4074 #endif
4075 return color.pixel;
4076 }
4077
4078 #endif /* MAC_TODO */
4079
4080 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
4081 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4082 If this produces the same color as COLOR, try a color where all RGB
4083 values have DELTA added. Return the allocated color in *COLOR.
4084 DISPLAY is the X display, CMAP is the colormap to operate on.
4085 Value is non-zero if successful. */
4086
4087 static int
4088 mac_alloc_lighter_color (f, color, factor, delta)
4089 struct frame *f;
4090 unsigned long *color;
4091 double factor;
4092 int delta;
4093 {
4094 unsigned long new;
4095
4096 /* Change RGB values by specified FACTOR. Avoid overflow! */
4097 xassert (factor >= 0);
4098 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4099 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4100 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4101 if (new == *color)
4102 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4103 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4104 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4105
4106 /* MAC_TODO: Map to palette and retry with delta if same? */
4107 /* MAC_TODO: Free colors (if using palette)? */
4108
4109 if (new == *color)
4110 return 0;
4111
4112 *color = new;
4113
4114 return 1;
4115 }
4116
4117
4118 /* Set up the foreground color for drawing relief lines of glyph
4119 string S. RELIEF is a pointer to a struct relief containing the GC
4120 with which lines will be drawn. Use a color that is FACTOR or
4121 DELTA lighter or darker than the relief's background which is found
4122 in S->f->output_data.x->relief_background. If such a color cannot
4123 be allocated, use DEFAULT_PIXEL, instead. */
4124
4125 static void
4126 x_setup_relief_color (f, relief, factor, delta, default_pixel)
4127 struct frame *f;
4128 struct relief *relief;
4129 double factor;
4130 int delta;
4131 unsigned long default_pixel;
4132 {
4133 XGCValues xgcv;
4134 struct mac_output *di = f->output_data.mac;
4135 unsigned long mask = GCForeground;
4136 unsigned long pixel;
4137 unsigned long background = di->relief_background;
4138 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4139
4140 /* MAC_TODO: Free colors (if using palette)? */
4141
4142 /* Allocate new color. */
4143 xgcv.foreground = default_pixel;
4144 pixel = background;
4145 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4146 {
4147 relief->allocated_p = 1;
4148 xgcv.foreground = relief->pixel = pixel;
4149 }
4150
4151 if (relief->gc == 0)
4152 {
4153 #if 0 /* MAC_TODO: stipple */
4154 xgcv.stipple = dpyinfo->gray;
4155 mask |= GCStipple;
4156 #endif
4157 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4158 }
4159 else
4160 XChangeGC (NULL, relief->gc, mask, &xgcv);
4161 }
4162
4163
4164 /* Set up colors for the relief lines around glyph string S. */
4165
4166 static void
4167 x_setup_relief_colors (s)
4168 struct glyph_string *s;
4169 {
4170 struct mac_output *di = s->f->output_data.mac;
4171 unsigned long color;
4172
4173 if (s->face->use_box_color_for_shadows_p)
4174 color = s->face->box_color;
4175 else
4176 {
4177 XGCValues xgcv;
4178
4179 /* Get the background color of the face. */
4180 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4181 color = xgcv.background;
4182 }
4183
4184 if (di->white_relief.gc == 0
4185 || color != di->relief_background)
4186 {
4187 di->relief_background = color;
4188 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4189 WHITE_PIX_DEFAULT (s->f));
4190 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4191 BLACK_PIX_DEFAULT (s->f));
4192 }
4193 }
4194
4195
4196 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4197 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4198 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4199 relief. LEFT_P non-zero means draw a relief on the left side of
4200 the rectangle. RIGHT_P non-zero means draw a relief on the right
4201 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4202 when drawing. */
4203
4204 static void
4205 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4206 raised_p, left_p, right_p, clip_rect)
4207 struct frame *f;
4208 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4209 Rect *clip_rect;
4210 {
4211 int i;
4212 GC gc;
4213
4214 if (raised_p)
4215 gc = f->output_data.mac->white_relief.gc;
4216 else
4217 gc = f->output_data.mac->black_relief.gc;
4218 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4219
4220 /* Top. */
4221 for (i = 0; i < width; ++i)
4222 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4223 left_x + i * left_p, top_y + i,
4224 right_x + 1 - i * right_p, top_y + i);
4225
4226 /* Left. */
4227 if (left_p)
4228 for (i = 0; i < width; ++i)
4229 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4230 left_x + i, top_y + i, left_x + i, bottom_y - i);
4231
4232 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4233 if (raised_p)
4234 gc = f->output_data.mac->black_relief.gc;
4235 else
4236 gc = f->output_data.mac->white_relief.gc;
4237 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4238 clip_rect);
4239
4240 /* Bottom. */
4241 for (i = 0; i < width; ++i)
4242 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4243 left_x + i * left_p, bottom_y - i,
4244 right_x + 1 - i * right_p, bottom_y - i);
4245
4246 /* Right. */
4247 if (right_p)
4248 for (i = 0; i < width; ++i)
4249 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4250 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4251
4252 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4253 }
4254
4255
4256 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4257 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4258 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4259 left side of the rectangle. RIGHT_P non-zero means draw a line
4260 on the right side of the rectangle. CLIP_RECT is the clipping
4261 rectangle to use when drawing. */
4262
4263 static void
4264 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4265 left_p, right_p, clip_rect)
4266 struct glyph_string *s;
4267 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4268 Rect *clip_rect;
4269 {
4270 XGCValues xgcv;
4271
4272 xgcv.foreground = s->face->box_color;
4273 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4274
4275 /* Top. */
4276 XFillRectangle (s->display, s->window, &xgcv,
4277 left_x, top_y, right_x - left_x, width);
4278
4279 /* Left. */
4280 if (left_p)
4281 XFillRectangle (s->display, s->window, &xgcv,
4282 left_x, top_y, width, bottom_y - top_y);
4283
4284 /* Bottom. */
4285 XFillRectangle (s->display, s->window, &xgcv,
4286 left_x, bottom_y - width, right_x - left_x, width);
4287
4288 /* Right. */
4289 if (right_p)
4290 XFillRectangle (s->display, s->window, &xgcv,
4291 right_x - width, top_y, width, bottom_y - top_y);
4292
4293 mac_reset_clipping (s->display, s->window);
4294 }
4295
4296
4297 /* Draw a box around glyph string S. */
4298
4299 static void
4300 x_draw_glyph_string_box (s)
4301 struct glyph_string *s;
4302 {
4303 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4304 int left_p, right_p;
4305 struct glyph *last_glyph;
4306 Rect clip_rect;
4307
4308 last_x = window_box_right (s->w, s->area);
4309 if (s->row->full_width_p
4310 && !s->w->pseudo_window_p)
4311 {
4312 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4313 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4314 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4315 }
4316
4317 /* The glyph that may have a right box line. */
4318 last_glyph = (s->cmp || s->img
4319 ? s->first_glyph
4320 : s->first_glyph + s->nchars - 1);
4321
4322 width = abs (s->face->box_line_width);
4323 raised_p = s->face->box == FACE_RAISED_BOX;
4324 left_x = s->x;
4325 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
4326 ? last_x - 1
4327 : min (last_x, s->x + s->background_width) - 1));
4328 top_y = s->y;
4329 bottom_y = top_y + s->height - 1;
4330
4331 left_p = (s->first_glyph->left_box_line_p
4332 || (s->hl == DRAW_MOUSE_FACE
4333 && (s->prev == NULL
4334 || s->prev->hl != s->hl)));
4335 right_p = (last_glyph->right_box_line_p
4336 || (s->hl == DRAW_MOUSE_FACE
4337 && (s->next == NULL
4338 || s->next->hl != s->hl)));
4339
4340 x_get_glyph_string_clip_rect (s, &clip_rect);
4341
4342 if (s->face->box == FACE_SIMPLE_BOX)
4343 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4344 left_p, right_p, &clip_rect);
4345 else
4346 {
4347 x_setup_relief_colors (s);
4348 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4349 width, raised_p, left_p, right_p, &clip_rect);
4350 }
4351 }
4352
4353
4354 /* Draw foreground of image glyph string S. */
4355
4356 static void
4357 x_draw_image_foreground (s)
4358 struct glyph_string *s;
4359 {
4360 int x;
4361 int y = s->ybase - image_ascent (s->img, s->face);
4362
4363 /* If first glyph of S has a left box line, start drawing it to the
4364 right of that line. */
4365 if (s->face->box != FACE_NO_BOX
4366 && s->first_glyph->left_box_line_p)
4367 x = s->x + abs (s->face->box_line_width);
4368 else
4369 x = s->x;
4370
4371 /* If there is a margin around the image, adjust x- and y-position
4372 by that margin. */
4373 x += s->img->hmargin;
4374 y += s->img->vmargin;
4375
4376 if (s->img->pixmap)
4377 {
4378 #if 0 /* MAC_TODO: image mask */
4379 if (s->img->mask)
4380 {
4381 /* We can't set both a clip mask and use XSetClipRectangles
4382 because the latter also sets a clip mask. We also can't
4383 trust on the shape extension to be available
4384 (XShapeCombineRegion). So, compute the rectangle to draw
4385 manually. */
4386 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4387 | GCFunction);
4388 XGCValues xgcv;
4389 XRectangle clip_rect, image_rect, r;
4390
4391 xgcv.clip_mask = s->img->mask;
4392 xgcv.clip_x_origin = x;
4393 xgcv.clip_y_origin = y;
4394 xgcv.function = GXcopy;
4395 XChangeGC (s->display, s->gc, mask, &xgcv);
4396
4397 x_get_glyph_string_clip_rect (s, &clip_rect);
4398 image_rect.x = x;
4399 image_rect.y = y;
4400 image_rect.width = s->img->width;
4401 image_rect.height = s->img->height;
4402 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4403 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4404 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4405 }
4406 else
4407 #endif /* MAC_TODO */
4408 {
4409 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4410 0, 0, s->img->width, s->img->height, x, y);
4411
4412 /* When the image has a mask, we can expect that at
4413 least part of a mouse highlight or a block cursor will
4414 be visible. If the image doesn't have a mask, make
4415 a block cursor visible by drawing a rectangle around
4416 the image. I believe it's looking better if we do
4417 nothing here for mouse-face. */
4418 if (s->hl == DRAW_CURSOR)
4419 {
4420 int r = s->img->relief;
4421 if (r < 0) r = -r;
4422 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4423 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4424 }
4425 }
4426 }
4427 else
4428 /* Draw a rectangle if image could not be loaded. */
4429 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4430 s->img->width - 1, s->img->height - 1);
4431 }
4432
4433
4434
4435 /* Draw a relief around the image glyph string S. */
4436
4437 static void
4438 x_draw_image_relief (s)
4439 struct glyph_string *s;
4440 {
4441 int x0, y0, x1, y1, thick, raised_p;
4442 Rect r;
4443 int x;
4444 int y = s->ybase - image_ascent (s->img, s->face);
4445
4446 /* If first glyph of S has a left box line, start drawing it to the
4447 right of that line. */
4448 if (s->face->box != FACE_NO_BOX
4449 && s->first_glyph->left_box_line_p)
4450 x = s->x + abs (s->face->box_line_width);
4451 else
4452 x = s->x;
4453
4454 /* If there is a margin around the image, adjust x- and y-position
4455 by that margin. */
4456 x += s->img->hmargin;
4457 y += s->img->vmargin;
4458
4459 if (s->hl == DRAW_IMAGE_SUNKEN
4460 || s->hl == DRAW_IMAGE_RAISED)
4461 {
4462 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4463 raised_p = s->hl == DRAW_IMAGE_RAISED;
4464 }
4465 else
4466 {
4467 thick = abs (s->img->relief);
4468 raised_p = s->img->relief > 0;
4469 }
4470
4471 x0 = x - thick;
4472 y0 = y - thick;
4473 x1 = x + s->img->width + thick - 1;
4474 y1 = y + s->img->height + thick - 1;
4475
4476 x_setup_relief_colors (s);
4477 x_get_glyph_string_clip_rect (s, &r);
4478 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4479 }
4480
4481
4482 /* Draw the foreground of image glyph string S to PIXMAP. */
4483
4484 static void
4485 x_draw_image_foreground_1 (s, pixmap)
4486 struct glyph_string *s;
4487 Pixmap pixmap;
4488 {
4489 int x;
4490 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4491
4492 /* If first glyph of S has a left box line, start drawing it to the
4493 right of that line. */
4494 if (s->face->box != FACE_NO_BOX
4495 && s->first_glyph->left_box_line_p)
4496 x = abs (s->face->box_line_width);
4497 else
4498 x = 0;
4499
4500 /* If there is a margin around the image, adjust x- and y-position
4501 by that margin. */
4502 x += s->img->hmargin;
4503 y += s->img->vmargin;
4504
4505 if (s->img->pixmap)
4506 {
4507 #if 0 /* MAC_TODO: image mask */
4508 if (s->img->mask)
4509 {
4510 /* We can't set both a clip mask and use XSetClipRectangles
4511 because the latter also sets a clip mask. We also can't
4512 trust on the shape extension to be available
4513 (XShapeCombineRegion). So, compute the rectangle to draw
4514 manually. */
4515 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4516 | GCFunction);
4517 XGCValues xgcv;
4518
4519 xgcv.clip_mask = s->img->mask;
4520 xgcv.clip_x_origin = x;
4521 xgcv.clip_y_origin = y;
4522 xgcv.function = GXcopy;
4523 XChangeGC (s->display, s->gc, mask, &xgcv);
4524
4525 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4526 0, 0, s->img->width, s->img->height, x, y);
4527 XSetClipMask (s->display, s->gc, None);
4528 }
4529 else
4530 #endif /* MAC_TODO */
4531 {
4532 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4533 0, 0, s->img->width, s->img->height, x, y);
4534
4535 /* When the image has a mask, we can expect that at
4536 least part of a mouse highlight or a block cursor will
4537 be visible. If the image doesn't have a mask, make
4538 a block cursor visible by drawing a rectangle around
4539 the image. I believe it's looking better if we do
4540 nothing here for mouse-face. */
4541 if (s->hl == DRAW_CURSOR)
4542 {
4543 int r = s->img->relief;
4544 if (r < 0) r = -r;
4545 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4546 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4547 }
4548 }
4549 }
4550 else
4551 /* Draw a rectangle if image could not be loaded. */
4552 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4553 s->img->width - 1, s->img->height - 1);
4554 }
4555
4556
4557 /* Draw part of the background of glyph string S. X, Y, W, and H
4558 give the rectangle to draw. */
4559
4560 static void
4561 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4562 struct glyph_string *s;
4563 int x, y, w, h;
4564 {
4565 #if 0 /* MAC_TODO: stipple */
4566 if (s->stippled_p)
4567 {
4568 /* Fill background with a stipple pattern. */
4569 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4570 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4571 XSetFillStyle (s->display, s->gc, FillSolid);
4572 }
4573 else
4574 #endif /* MAC_TODO */
4575 x_clear_glyph_string_rect (s, x, y, w, h);
4576 }
4577
4578
4579 /* Draw image glyph string S.
4580
4581 s->y
4582 s->x +-------------------------
4583 | s->face->box
4584 |
4585 | +-------------------------
4586 | | s->img->vmargin
4587 | |
4588 | | +-------------------
4589 | | | the image
4590
4591 */
4592
4593 static void
4594 x_draw_image_glyph_string (s)
4595 struct glyph_string *s;
4596 {
4597 int x, y;
4598 int box_line_hwidth = abs (s->face->box_line_width);
4599 int box_line_vwidth = max (s->face->box_line_width, 0);
4600 int height;
4601 Pixmap pixmap = 0;
4602
4603 height = s->height - 2 * box_line_vwidth;
4604
4605 /* Fill background with face under the image. Do it only if row is
4606 taller than image or if image has a clip mask to reduce
4607 flickering. */
4608 s->stippled_p = s->face->stipple != 0;
4609 if (height > s->img->height
4610 || s->img->hmargin
4611 || s->img->vmargin
4612 #if 0 /* TODO: image mask */
4613 || s->img->mask
4614 #endif
4615 || s->img->pixmap == 0
4616 || s->width != s->background_width)
4617 {
4618 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4619 x = s->x + box_line_hwidth;
4620 else
4621 x = s->x;
4622
4623 y = s->y + box_line_vwidth;
4624 #if 0 /* TODO: image mask */
4625 if (s->img->mask)
4626 {
4627 /* Create a pixmap as large as the glyph string. Fill it
4628 with the background color. Copy the image to it, using
4629 its mask. Copy the temporary pixmap to the display. */
4630 Screen *screen = FRAME_X_SCREEN (s->f);
4631 int depth = DefaultDepthOfScreen (screen);
4632
4633 /* Create a pixmap as large as the glyph string. */
4634 pixmap = XCreatePixmap (s->display, s->window,
4635 s->background_width,
4636 s->height, depth);
4637
4638 /* Don't clip in the following because we're working on the
4639 pixmap. */
4640 XSetClipMask (s->display, s->gc, None);
4641
4642 /* Fill the pixmap with the background color/stipple. */
4643 if (s->stippled_p)
4644 {
4645 /* Fill background with a stipple pattern. */
4646 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4647 XFillRectangle (s->display, pixmap, s->gc,
4648 0, 0, s->background_width, s->height);
4649 XSetFillStyle (s->display, s->gc, FillSolid);
4650 }
4651 else
4652 {
4653 XGCValues xgcv;
4654 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4655 &xgcv);
4656 XSetForeground (s->display, s->gc, xgcv.background);
4657 XFillRectangle (s->display, pixmap, s->gc,
4658 0, 0, s->background_width, s->height);
4659 XSetForeground (s->display, s->gc, xgcv.foreground);
4660 }
4661 }
4662 else
4663 #endif
4664 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4665
4666 s->background_filled_p = 1;
4667 }
4668
4669 /* Draw the foreground. */
4670 if (pixmap != 0)
4671 {
4672 x_draw_image_foreground_1 (s, pixmap);
4673 x_set_glyph_string_clipping (s);
4674 mac_copy_area (s->display, pixmap, s->window, s->gc,
4675 0, 0, s->background_width, s->height, s->x, s->y);
4676 mac_reset_clipping (s->display, s->window);
4677 XFreePixmap (s->display, pixmap);
4678 }
4679 else
4680 x_draw_image_foreground (s);
4681
4682 /* If we must draw a relief around the image, do it. */
4683 if (s->img->relief
4684 || s->hl == DRAW_IMAGE_RAISED
4685 || s->hl == DRAW_IMAGE_SUNKEN)
4686 x_draw_image_relief (s);
4687 }
4688
4689
4690 /* Draw stretch glyph string S. */
4691
4692 static void
4693 x_draw_stretch_glyph_string (s)
4694 struct glyph_string *s;
4695 {
4696 xassert (s->first_glyph->type == STRETCH_GLYPH);
4697 s->stippled_p = s->face->stipple != 0;
4698
4699 if (s->hl == DRAW_CURSOR
4700 && !x_stretch_cursor_p)
4701 {
4702 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4703 as wide as the stretch glyph. */
4704 int width = min (CANON_X_UNIT (s->f), s->background_width);
4705
4706 /* Draw cursor. */
4707 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4708
4709 /* Clear rest using the GC of the original non-cursor face. */
4710 if (width < s->background_width)
4711 {
4712 GC gc = s->face->gc;
4713 int x = s->x + width, y = s->y;
4714 int w = s->background_width - width, h = s->height;
4715 Rect r;
4716
4717 if (s->row->mouse_face_p
4718 && cursor_in_mouse_face_p (s->w))
4719 {
4720 x_set_mouse_face_gc (s);
4721 gc = s->gc;
4722 }
4723 else
4724 gc = s->face->gc;
4725
4726 x_get_glyph_string_clip_rect (s, &r);
4727 mac_set_clip_rectangle (s->display, s->window, &r);
4728
4729 #if 0 /* MAC_TODO: stipple */
4730 if (s->face->stipple)
4731 {
4732 /* Fill background with a stipple pattern. */
4733 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4734 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4735 XSetFillStyle (s->display, gc, FillSolid);
4736 }
4737 else
4738 #endif /* MAC_TODO */
4739 {
4740 XGCValues xgcv;
4741 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4742 XSetForeground (s->display, gc, xgcv.background);
4743 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4744 XSetForeground (s->display, gc, xgcv.foreground);
4745 }
4746
4747 mac_reset_clipping (s->display, s->window);
4748 }
4749 }
4750 else if (!s->background_filled_p)
4751 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4752 s->height);
4753
4754 s->background_filled_p = 1;
4755 }
4756
4757
4758 /* Draw glyph string S. */
4759
4760 static void
4761 x_draw_glyph_string (s)
4762 struct glyph_string *s;
4763 {
4764 int relief_drawn_p = 0;
4765
4766 /* If S draws into the background of its successor, draw the
4767 background of the successor first so that S can draw into it.
4768 This makes S->next use XDrawString instead of XDrawImageString. */
4769 if (s->next && s->right_overhang && !s->for_overlaps_p)
4770 {
4771 xassert (s->next->img == NULL);
4772 x_set_glyph_string_gc (s->next);
4773 x_set_glyph_string_clipping (s->next);
4774 x_draw_glyph_string_background (s->next, 1);
4775
4776 }
4777
4778 /* Set up S->gc, set clipping and draw S. */
4779 x_set_glyph_string_gc (s);
4780
4781 /* Draw relief (if any) in advance for char/composition so that the
4782 glyph string can be drawn over it. */
4783 if (!s->for_overlaps_p
4784 && s->face->box != FACE_NO_BOX
4785 && (s->first_glyph->type == CHAR_GLYPH
4786 || s->first_glyph->type == COMPOSITE_GLYPH))
4787
4788 {
4789 x_set_glyph_string_clipping (s);
4790 x_draw_glyph_string_background (s, 1);
4791 x_draw_glyph_string_box (s);
4792 x_set_glyph_string_clipping (s);
4793 relief_drawn_p = 1;
4794 }
4795 else
4796 x_set_glyph_string_clipping (s);
4797
4798 switch (s->first_glyph->type)
4799 {
4800 case IMAGE_GLYPH:
4801 x_draw_image_glyph_string (s);
4802 break;
4803
4804 case STRETCH_GLYPH:
4805 x_draw_stretch_glyph_string (s);
4806 break;
4807
4808 case CHAR_GLYPH:
4809 if (s->for_overlaps_p)
4810 s->background_filled_p = 1;
4811 else
4812 x_draw_glyph_string_background (s, 0);
4813 x_draw_glyph_string_foreground (s);
4814 break;
4815
4816 case COMPOSITE_GLYPH:
4817 if (s->for_overlaps_p || s->gidx > 0)
4818 s->background_filled_p = 1;
4819 else
4820 x_draw_glyph_string_background (s, 1);
4821 x_draw_composite_glyph_string_foreground (s);
4822 break;
4823
4824 default:
4825 abort ();
4826 }
4827
4828 if (!s->for_overlaps_p)
4829 {
4830 /* Draw underline. */
4831 if (s->face->underline_p)
4832 {
4833 unsigned long h = 1;
4834 unsigned long dy = s->height - h;
4835
4836 if (s->face->underline_defaulted_p)
4837 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4838 s->width, h);
4839 else
4840 {
4841 XGCValues xgcv;
4842 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4843 XSetForeground (s->display, s->gc, s->face->underline_color);
4844 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4845 s->width, h);
4846 XSetForeground (s->display, s->gc, xgcv.foreground);
4847 }
4848 }
4849
4850 /* Draw overline. */
4851 if (s->face->overline_p)
4852 {
4853 unsigned long dy = 0, h = 1;
4854
4855 if (s->face->overline_color_defaulted_p)
4856 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4857 s->width, h);
4858 else
4859 {
4860 XGCValues xgcv;
4861 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4862 XSetForeground (s->display, s->gc, s->face->overline_color);
4863 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4864 s->width, h);
4865 XSetForeground (s->display, s->gc, xgcv.foreground);
4866 }
4867 }
4868
4869 /* Draw strike-through. */
4870 if (s->face->strike_through_p)
4871 {
4872 unsigned long h = 1;
4873 unsigned long dy = (s->height - h) / 2;
4874
4875 if (s->face->strike_through_color_defaulted_p)
4876 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4877 s->width, h);
4878 else
4879 {
4880 XGCValues xgcv;
4881 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4882 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4883 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4884 s->width, h);
4885 XSetForeground (s->display, s->gc, xgcv.foreground);
4886 }
4887 }
4888
4889 /* Draw relief. */
4890 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4891 x_draw_glyph_string_box (s);
4892 }
4893
4894 /* Reset clipping. */
4895 mac_reset_clipping (s->display, s->window);
4896 }
4897
4898
4899 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4900 struct face **, int));
4901
4902
4903 /* Fill glyph string S with composition components specified by S->cmp.
4904
4905 FACES is an array of faces for all components of this composition.
4906 S->gidx is the index of the first component for S.
4907 OVERLAPS_P non-zero means S should draw the foreground only, and
4908 use its physical height for clipping.
4909
4910 Value is the index of a component not in S. */
4911
4912 static int
4913 x_fill_composite_glyph_string (s, faces, overlaps_p)
4914 struct glyph_string *s;
4915 struct face **faces;
4916 int overlaps_p;
4917 {
4918 int i;
4919
4920 xassert (s);
4921
4922 s->for_overlaps_p = overlaps_p;
4923
4924 s->face = faces[s->gidx];
4925 s->font = s->face->font;
4926 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4927
4928 /* For all glyphs of this composition, starting at the offset
4929 S->gidx, until we reach the end of the definition or encounter a
4930 glyph that requires the different face, add it to S. */
4931 ++s->nchars;
4932 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4933 ++s->nchars;
4934
4935 /* All glyph strings for the same composition has the same width,
4936 i.e. the width set for the first component of the composition. */
4937
4938 s->width = s->first_glyph->pixel_width;
4939
4940 /* If the specified font could not be loaded, use the frame's
4941 default font, but record the fact that we couldn't load it in
4942 the glyph string so that we can draw rectangles for the
4943 characters of the glyph string. */
4944 if (s->font == NULL)
4945 {
4946 s->font_not_found_p = 1;
4947 s->font = FRAME_FONT (s->f);
4948 }
4949
4950 /* Adjust base line for subscript/superscript text. */
4951 s->ybase += s->first_glyph->voffset;
4952
4953 xassert (s->face && s->face->gc);
4954
4955 /* This glyph string must always be drawn with 16-bit functions. */
4956 s->two_byte_p = 1;
4957
4958 return s->gidx + s->nchars;
4959 }
4960
4961
4962 /* Fill glyph string S from a sequence of character glyphs.
4963
4964 FACE_ID is the face id of the string. START is the index of the
4965 first glyph to consider, END is the index of the last + 1.
4966 OVERLAPS_P non-zero means S should draw the foreground only, and
4967 use its physical height for clipping.
4968
4969 Value is the index of the first glyph not in S. */
4970
4971 static int
4972 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4973 struct glyph_string *s;
4974 int face_id;
4975 int start, end, overlaps_p;
4976 {
4977 struct glyph *glyph, *last;
4978 int voffset;
4979 int glyph_not_available_p;
4980
4981 xassert (s->f == XFRAME (s->w->frame));
4982 xassert (s->nchars == 0);
4983 xassert (start >= 0 && end > start);
4984
4985 s->for_overlaps_p = overlaps_p;
4986 glyph = s->row->glyphs[s->area] + start;
4987 last = s->row->glyphs[s->area] + end;
4988 voffset = glyph->voffset;
4989
4990 glyph_not_available_p = glyph->glyph_not_available_p;
4991
4992 while (glyph < last
4993 && glyph->type == CHAR_GLYPH
4994 && glyph->voffset == voffset
4995 /* Same face id implies same font, nowadays. */
4996 && glyph->face_id == face_id
4997 && glyph->glyph_not_available_p == glyph_not_available_p)
4998 {
4999 int two_byte_p;
5000
5001 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
5002 s->char2b + s->nchars,
5003 &two_byte_p);
5004 s->two_byte_p = two_byte_p;
5005 ++s->nchars;
5006 xassert (s->nchars <= end - start);
5007 s->width += glyph->pixel_width;
5008 ++glyph;
5009 }
5010
5011 s->font = s->face->font;
5012 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5013
5014 /* If the specified font could not be loaded, use the frame's font,
5015 but record the fact that we couldn't load it in
5016 S->font_not_found_p so that we can draw rectangles for the
5017 characters of the glyph string. */
5018 if (s->font == NULL || glyph_not_available_p)
5019 {
5020 s->font_not_found_p = 1;
5021 s->font = FRAME_FONT (s->f);
5022 }
5023
5024 /* Adjust base line for subscript/superscript text. */
5025 s->ybase += voffset;
5026
5027 xassert (s->face && s->face->gc);
5028 return glyph - s->row->glyphs[s->area];
5029 }
5030
5031
5032 /* Fill glyph string S from image glyph S->first_glyph. */
5033
5034 static void
5035 x_fill_image_glyph_string (s)
5036 struct glyph_string *s;
5037 {
5038 xassert (s->first_glyph->type == IMAGE_GLYPH);
5039 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5040 xassert (s->img);
5041 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5042 s->font = s->face->font;
5043 s->width = s->first_glyph->pixel_width;
5044
5045 /* Adjust base line for subscript/superscript text. */
5046 s->ybase += s->first_glyph->voffset;
5047 }
5048
5049
5050 /* Fill glyph string S from a sequence of stretch glyphs.
5051
5052 ROW is the glyph row in which the glyphs are found, AREA is the
5053 area within the row. START is the index of the first glyph to
5054 consider, END is the index of the last + 1.
5055
5056 Value is the index of the first glyph not in S. */
5057
5058 static int
5059 x_fill_stretch_glyph_string (s, row, area, start, end)
5060 struct glyph_string *s;
5061 struct glyph_row *row;
5062 enum glyph_row_area area;
5063 int start, end;
5064 {
5065 struct glyph *glyph, *last;
5066 int voffset, face_id;
5067
5068 xassert (s->first_glyph->type == STRETCH_GLYPH);
5069
5070 glyph = s->row->glyphs[s->area] + start;
5071 last = s->row->glyphs[s->area] + end;
5072 face_id = glyph->face_id;
5073 s->face = FACE_FROM_ID (s->f, face_id);
5074 s->font = s->face->font;
5075 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5076 s->width = glyph->pixel_width;
5077 voffset = glyph->voffset;
5078
5079 for (++glyph;
5080 (glyph < last
5081 && glyph->type == STRETCH_GLYPH
5082 && glyph->voffset == voffset
5083 && glyph->face_id == face_id);
5084 ++glyph)
5085 s->width += glyph->pixel_width;
5086
5087 /* Adjust base line for subscript/superscript text. */
5088 s->ybase += voffset;
5089
5090 xassert (s->face);
5091 return glyph - s->row->glyphs[s->area];
5092 }
5093
5094
5095 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
5096 of XChar2b structures for S; it can't be allocated in
5097 x_init_glyph_string because it must be allocated via `alloca'. W
5098 is the window on which S is drawn. ROW and AREA are the glyph row
5099 and area within the row from which S is constructed. START is the
5100 index of the first glyph structure covered by S. HL is a
5101 face-override for drawing S. */
5102
5103 static void
5104 x_init_glyph_string (s, char2b, w, row, area, start, hl)
5105 struct glyph_string *s;
5106 XChar2b *char2b;
5107 struct window *w;
5108 struct glyph_row *row;
5109 enum glyph_row_area area;
5110 int start;
5111 enum draw_glyphs_face hl;
5112 {
5113 bzero (s, sizeof *s);
5114 s->w = w;
5115 s->f = XFRAME (w->frame);
5116 s->display = FRAME_MAC_DISPLAY (s->f);
5117 s->window = FRAME_MAC_WINDOW (s->f);
5118 s->char2b = char2b;
5119 s->hl = hl;
5120 s->row = row;
5121 s->area = area;
5122 s->first_glyph = row->glyphs[area] + start;
5123 s->height = row->height;
5124 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5125
5126 /* Display the internal border below the tool-bar window. */
5127 if (s->w == XWINDOW (s->f->tool_bar_window))
5128 s->y -= s->f->output_data.mac->internal_border_width;
5129
5130 s->ybase = s->y + row->ascent;
5131 }
5132
5133
5134 /* Set background width of glyph string S. START is the index of the
5135 first glyph following S. LAST_X is the right-most x-position + 1
5136 in the drawing area. */
5137
5138 static INLINE void
5139 x_set_glyph_string_background_width (s, start, last_x)
5140 struct glyph_string *s;
5141 int start;
5142 int last_x;
5143 {
5144 /* If the face of this glyph string has to be drawn to the end of
5145 the drawing area, set S->extends_to_end_of_line_p. */
5146 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
5147
5148 if (start == s->row->used[s->area]
5149 && s->area == TEXT_AREA
5150 && ((s->hl == DRAW_NORMAL_TEXT
5151 && (s->row->fill_line_p
5152 || s->face->background != default_face->background
5153 || s->face->stipple != default_face->stipple
5154 || s->row->mouse_face_p))
5155 || s->hl == DRAW_MOUSE_FACE
5156 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5157 && s->row->fill_line_p)))
5158 s->extends_to_end_of_line_p = 1;
5159
5160 /* If S extends its face to the end of the line, set its
5161 background_width to the distance to the right edge of the drawing
5162 area. */
5163 if (s->extends_to_end_of_line_p)
5164 s->background_width = last_x - s->x + 1;
5165 else
5166 s->background_width = s->width;
5167 }
5168
5169
5170 /* Add a glyph string for a stretch glyph to the list of strings
5171 between HEAD and TAIL. START is the index of the stretch glyph in
5172 row area AREA of glyph row ROW. END is the index of the last glyph
5173 in that glyph row area. X is the current output position assigned
5174 to the new glyph string constructed. HL overrides that face of the
5175 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5176 is the right-most x-position of the drawing area. */
5177
5178 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5179 and below -- keep them on one line. */
5180 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5181 do \
5182 { \
5183 s = (struct glyph_string *) alloca (sizeof *s); \
5184 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5185 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5186 x_append_glyph_string (&HEAD, &TAIL, s); \
5187 s->x = (X); \
5188 } \
5189 while (0)
5190
5191
5192 /* Add a glyph string for an image glyph to the list of strings
5193 between HEAD and TAIL. START is the index of the image glyph in
5194 row area AREA of glyph row ROW. END is the index of the last glyph
5195 in that glyph row area. X is the current output position assigned
5196 to the new glyph string constructed. HL overrides that face of the
5197 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5198 is the right-most x-position of the drawing area. */
5199
5200 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5201 do \
5202 { \
5203 s = (struct glyph_string *) alloca (sizeof *s); \
5204 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5205 x_fill_image_glyph_string (s); \
5206 x_append_glyph_string (&HEAD, &TAIL, s); \
5207 ++START; \
5208 s->x = (X); \
5209 } \
5210 while (0)
5211
5212
5213 /* Add a glyph string for a sequence of character glyphs to the list
5214 of strings between HEAD and TAIL. START is the index of the first
5215 glyph in row area AREA of glyph row ROW that is part of the new
5216 glyph string. END is the index of the last glyph in that glyph row
5217 area. X is the current output position assigned to the new glyph
5218 string constructed. HL overrides that face of the glyph; e.g. it
5219 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5220 right-most x-position of the drawing area. */
5221
5222 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5223 do \
5224 { \
5225 int c, face_id; \
5226 XChar2b *char2b; \
5227 \
5228 c = (ROW)->glyphs[AREA][START].u.ch; \
5229 face_id = (ROW)->glyphs[AREA][START].face_id; \
5230 \
5231 s = (struct glyph_string *) alloca (sizeof *s); \
5232 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5233 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5234 x_append_glyph_string (&HEAD, &TAIL, s); \
5235 s->x = (X); \
5236 START = x_fill_glyph_string (s, face_id, START, END, \
5237 OVERLAPS_P); \
5238 } \
5239 while (0)
5240
5241
5242 /* Add a glyph string for a composite sequence to the list of strings
5243 between HEAD and TAIL. START is the index of the first glyph in
5244 row area AREA of glyph row ROW that is part of the new glyph
5245 string. END is the index of the last glyph in that glyph row area.
5246 X is the current output position assigned to the new glyph string
5247 constructed. HL overrides that face of the glyph; e.g. it is
5248 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5249 x-position of the drawing area. */
5250
5251 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5252 do { \
5253 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5254 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5255 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5256 struct composition *cmp = composition_table[cmp_id]; \
5257 int glyph_len = cmp->glyph_len; \
5258 XChar2b *char2b; \
5259 struct face **faces; \
5260 struct glyph_string *first_s = NULL; \
5261 int n; \
5262 \
5263 base_face = base_face->ascii_face; \
5264 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5265 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5266 /* At first, fill in `char2b' and `faces'. */ \
5267 for (n = 0; n < glyph_len; n++) \
5268 { \
5269 int c = COMPOSITION_GLYPH (cmp, n); \
5270 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5271 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5272 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5273 this_face_id, char2b + n, 1); \
5274 } \
5275 \
5276 /* Make glyph_strings for each glyph sequence that is drawable by \
5277 the same face, and append them to HEAD/TAIL. */ \
5278 for (n = 0; n < cmp->glyph_len;) \
5279 { \
5280 s = (struct glyph_string *) alloca (sizeof *s); \
5281 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5282 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5283 s->cmp = cmp; \
5284 s->gidx = n; \
5285 s->x = (X); \
5286 \
5287 if (n == 0) \
5288 first_s = s; \
5289 \
5290 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5291 } \
5292 \
5293 ++START; \
5294 s = first_s; \
5295 } while (0)
5296
5297
5298 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5299 of AREA of glyph row ROW on window W between indices START and END.
5300 HL overrides the face for drawing glyph strings, e.g. it is
5301 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5302 x-positions of the drawing area.
5303
5304 This is an ugly monster macro construct because we must use alloca
5305 to allocate glyph strings (because x_draw_glyphs can be called
5306 asynchronously). */
5307
5308 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5309 do \
5310 { \
5311 HEAD = TAIL = NULL; \
5312 while (START < END) \
5313 { \
5314 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5315 switch (first_glyph->type) \
5316 { \
5317 case CHAR_GLYPH: \
5318 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5319 TAIL, HL, X, LAST_X, \
5320 OVERLAPS_P); \
5321 break; \
5322 \
5323 case COMPOSITE_GLYPH: \
5324 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5325 HEAD, TAIL, HL, X, LAST_X,\
5326 OVERLAPS_P); \
5327 break; \
5328 \
5329 case STRETCH_GLYPH: \
5330 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5331 HEAD, TAIL, HL, X, LAST_X); \
5332 break; \
5333 \
5334 case IMAGE_GLYPH: \
5335 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5336 TAIL, HL, X, LAST_X); \
5337 break; \
5338 \
5339 default: \
5340 abort (); \
5341 } \
5342 \
5343 x_set_glyph_string_background_width (s, START, LAST_X); \
5344 (X) += s->width; \
5345 } \
5346 } \
5347 while (0)
5348
5349
5350 /* Draw glyphs between START and END in AREA of ROW on window W,
5351 starting at x-position X. X is relative to AREA in W. HL is a
5352 face-override with the following meaning:
5353
5354 DRAW_NORMAL_TEXT draw normally
5355 DRAW_CURSOR draw in cursor face
5356 DRAW_MOUSE_FACE draw in mouse face.
5357 DRAW_INVERSE_VIDEO draw in mode line face
5358 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5359 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5360
5361 If OVERLAPS_P is non-zero, draw only the foreground of characters
5362 and clip to the physical height of ROW.
5363
5364 Value is the x-position reached, relative to AREA of W. */
5365
5366 static int
5367 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5368 struct window *w;
5369 int x;
5370 struct glyph_row *row;
5371 enum glyph_row_area area;
5372 int start, end;
5373 enum draw_glyphs_face hl;
5374 int overlaps_p;
5375 {
5376 struct glyph_string *head, *tail;
5377 struct glyph_string *s;
5378 int last_x, area_width;
5379 int x_reached;
5380 int i, j;
5381
5382 /* Let's rather be paranoid than getting a SEGV. */
5383 end = min (end, row->used[area]);
5384 start = max (0, start);
5385 start = min (end, start);
5386
5387 /* Translate X to frame coordinates. Set last_x to the right
5388 end of the drawing area. */
5389 if (row->full_width_p)
5390 {
5391 /* X is relative to the left edge of W, without scroll bars
5392 or fringes. */
5393 struct frame *f = XFRAME (WINDOW_FRAME (w));
5394 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5395
5396 x += window_left_x;
5397 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5398 last_x = window_left_x + area_width;
5399
5400 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5401 {
5402 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5403 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5404 last_x += width;
5405 else
5406 x -= width;
5407 }
5408
5409 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5410 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5411 }
5412 else
5413 {
5414 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5415 area_width = window_box_width (w, area);
5416 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5417 }
5418
5419 /* Build a doubly-linked list of glyph_string structures between
5420 head and tail from what we have to draw. Note that the macro
5421 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5422 the reason we use a separate variable `i'. */
5423 i = start;
5424 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5425 overlaps_p);
5426 if (tail)
5427 x_reached = tail->x + tail->background_width;
5428 else
5429 x_reached = x;
5430
5431 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5432 the row, redraw some glyphs in front or following the glyph
5433 strings built above. */
5434 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5435 {
5436 int dummy_x = 0;
5437 struct glyph_string *h, *t;
5438
5439 /* Compute overhangs for all glyph strings. */
5440 for (s = head; s; s = s->next)
5441 x_compute_glyph_string_overhangs (s);
5442
5443 /* Prepend glyph strings for glyphs in front of the first glyph
5444 string that are overwritten because of the first glyph
5445 string's left overhang. The background of all strings
5446 prepended must be drawn because the first glyph string
5447 draws over it. */
5448 i = x_left_overwritten (head);
5449 if (i >= 0)
5450 {
5451 j = i;
5452 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5453 DRAW_NORMAL_TEXT, dummy_x, last_x,
5454 overlaps_p);
5455 start = i;
5456 x_compute_overhangs_and_x (t, head->x, 1);
5457 x_prepend_glyph_string_lists (&head, &tail, h, t);
5458 }
5459
5460 /* Prepend glyph strings for glyphs in front of the first glyph
5461 string that overwrite that glyph string because of their
5462 right overhang. For these strings, only the foreground must
5463 be drawn, because it draws over the glyph string at `head'.
5464 The background must not be drawn because this would overwrite
5465 right overhangs of preceding glyphs for which no glyph
5466 strings exist. */
5467 i = x_left_overwriting (head);
5468 if (i >= 0)
5469 {
5470 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5471 DRAW_NORMAL_TEXT, dummy_x, last_x,
5472 overlaps_p);
5473 for (s = h; s; s = s->next)
5474 s->background_filled_p = 1;
5475 x_compute_overhangs_and_x (t, head->x, 1);
5476 x_prepend_glyph_string_lists (&head, &tail, h, t);
5477 }
5478
5479 /* Append glyphs strings for glyphs following the last glyph
5480 string tail that are overwritten by tail. The background of
5481 these strings has to be drawn because tail's foreground draws
5482 over it. */
5483 i = x_right_overwritten (tail);
5484 if (i >= 0)
5485 {
5486 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5487 DRAW_NORMAL_TEXT, x, last_x,
5488 overlaps_p);
5489 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5490 x_append_glyph_string_lists (&head, &tail, h, t);
5491 }
5492
5493 /* Append glyph strings for glyphs following the last glyph
5494 string tail that overwrite tail. The foreground of such
5495 glyphs has to be drawn because it writes into the background
5496 of tail. The background must not be drawn because it could
5497 paint over the foreground of following glyphs. */
5498 i = x_right_overwriting (tail);
5499 if (i >= 0)
5500 {
5501 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5502 DRAW_NORMAL_TEXT, x, last_x,
5503 overlaps_p);
5504 for (s = h; s; s = s->next)
5505 s->background_filled_p = 1;
5506 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5507 x_append_glyph_string_lists (&head, &tail, h, t);
5508 }
5509 }
5510
5511 /* Draw all strings. */
5512 for (s = head; s; s = s->next)
5513 x_draw_glyph_string (s);
5514
5515 if (area == TEXT_AREA
5516 && !row->full_width_p
5517 /* When drawing overlapping rows, only the glyph strings'
5518 foreground is drawn, which doesn't erase a cursor
5519 completely. */
5520 && !overlaps_p)
5521 {
5522 int x0 = head ? head->x : x;
5523 int x1 = tail ? tail->x + tail->background_width : x;
5524
5525 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5526 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5527
5528 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5529 {
5530 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5531 x0 -= left_area_width;
5532 x1 -= left_area_width;
5533 }
5534
5535 notice_overwritten_cursor (w, area, x0, x1,
5536 row->y, MATRIX_ROW_BOTTOM_Y (row));
5537 }
5538
5539 /* Value is the x-position up to which drawn, relative to AREA of W.
5540 This doesn't include parts drawn because of overhangs. */
5541 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5542 if (!row->full_width_p)
5543 {
5544 if (area > LEFT_MARGIN_AREA)
5545 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5546 if (area > TEXT_AREA)
5547 x_reached -= window_box_width (w, TEXT_AREA);
5548 }
5549
5550 return x_reached;
5551 }
5552
5553
5554 /* Fix the display of area AREA of overlapping row ROW in window W. */
5555
5556 static void
5557 x_fix_overlapping_area (w, row, area)
5558 struct window *w;
5559 struct glyph_row *row;
5560 enum glyph_row_area area;
5561 {
5562 int i, x;
5563
5564 BLOCK_INPUT;
5565
5566 if (area == LEFT_MARGIN_AREA)
5567 x = 0;
5568 else if (area == TEXT_AREA)
5569 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5570 else
5571 x = (window_box_width (w, LEFT_MARGIN_AREA)
5572 + window_box_width (w, TEXT_AREA));
5573
5574 for (i = 0; i < row->used[area];)
5575 {
5576 if (row->glyphs[area][i].overlaps_vertically_p)
5577 {
5578 int start = i, start_x = x;
5579
5580 do
5581 {
5582 x += row->glyphs[area][i].pixel_width;
5583 ++i;
5584 }
5585 while (i < row->used[area]
5586 && row->glyphs[area][i].overlaps_vertically_p);
5587
5588 x_draw_glyphs (w, start_x, row, area, start, i,
5589 DRAW_NORMAL_TEXT, 1);
5590 }
5591 else
5592 {
5593 x += row->glyphs[area][i].pixel_width;
5594 ++i;
5595 }
5596 }
5597
5598 UNBLOCK_INPUT;
5599 }
5600
5601
5602 /* Output LEN glyphs starting at START at the nominal cursor position.
5603 Advance the nominal cursor over the text. The global variable
5604 updated_window contains the window being updated, updated_row is
5605 the glyph row being updated, and updated_area is the area of that
5606 row being updated. */
5607
5608 static void
5609 x_write_glyphs (start, len)
5610 struct glyph *start;
5611 int len;
5612 {
5613 int x, hpos;
5614
5615 xassert (updated_window && updated_row);
5616 BLOCK_INPUT;
5617
5618 /* Write glyphs. */
5619
5620 hpos = start - updated_row->glyphs[updated_area];
5621 x = x_draw_glyphs (updated_window, output_cursor.x,
5622 updated_row, updated_area,
5623 hpos, hpos + len,
5624 DRAW_NORMAL_TEXT, 0);
5625
5626 UNBLOCK_INPUT;
5627
5628 /* Advance the output cursor. */
5629 output_cursor.hpos += len;
5630 output_cursor.x = x;
5631 }
5632
5633
5634 /* Insert LEN glyphs from START at the nominal cursor position. */
5635
5636 static void
5637 x_insert_glyphs (start, len)
5638 struct glyph *start;
5639 register int len;
5640 {
5641 struct frame *f;
5642 struct window *w;
5643 int line_height, shift_by_width, shifted_region_width;
5644 struct glyph_row *row;
5645 struct glyph *glyph;
5646 int frame_x, frame_y, hpos;
5647
5648 xassert (updated_window && updated_row);
5649 BLOCK_INPUT;
5650 w = updated_window;
5651 f = XFRAME (WINDOW_FRAME (w));
5652
5653 /* Get the height of the line we are in. */
5654 row = updated_row;
5655 line_height = row->height;
5656
5657 /* Get the width of the glyphs to insert. */
5658 shift_by_width = 0;
5659 for (glyph = start; glyph < start + len; ++glyph)
5660 shift_by_width += glyph->pixel_width;
5661
5662 /* Get the width of the region to shift right. */
5663 shifted_region_width = (window_box_width (w, updated_area)
5664 - output_cursor.x
5665 - shift_by_width);
5666
5667 /* Shift right. */
5668 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5669 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5670
5671 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5672 f->output_data.mac->normal_gc,
5673 frame_x, frame_y,
5674 shifted_region_width, line_height,
5675 frame_x + shift_by_width, frame_y);
5676
5677 /* Write the glyphs. */
5678 hpos = start - row->glyphs[updated_area];
5679 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5680 DRAW_NORMAL_TEXT, 0);
5681
5682 /* Advance the output cursor. */
5683 output_cursor.hpos += len;
5684 output_cursor.x += shift_by_width;
5685 UNBLOCK_INPUT;
5686 }
5687
5688
5689 /* Delete N glyphs at the nominal cursor position. Not implemented
5690 for X frames. */
5691
5692 static void
5693 x_delete_glyphs (n)
5694 register int n;
5695 {
5696 abort ();
5697 }
5698
5699
5700 /* Erase the current text line from the nominal cursor position
5701 (inclusive) to pixel column TO_X (exclusive). The idea is that
5702 everything from TO_X onward is already erased.
5703
5704 TO_X is a pixel position relative to updated_area of
5705 updated_window. TO_X == -1 means clear to the end of this area. */
5706
5707 static void
5708 x_clear_end_of_line (to_x)
5709 int to_x;
5710 {
5711 struct frame *f;
5712 struct window *w = updated_window;
5713 int max_x, min_y, max_y;
5714 int from_x, from_y, to_y;
5715
5716 xassert (updated_window && updated_row);
5717 f = XFRAME (w->frame);
5718
5719 if (updated_row->full_width_p)
5720 {
5721 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5722 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5723 && !w->pseudo_window_p)
5724 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5725 }
5726 else
5727 max_x = window_box_width (w, updated_area);
5728 max_y = window_text_bottom_y (w);
5729
5730 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5731 of window. For TO_X > 0, truncate to end of drawing area. */
5732 if (to_x == 0)
5733 return;
5734 else if (to_x < 0)
5735 to_x = max_x;
5736 else
5737 to_x = min (to_x, max_x);
5738
5739 to_y = min (max_y, output_cursor.y + updated_row->height);
5740
5741 /* Notice if the cursor will be cleared by this operation. */
5742 if (!updated_row->full_width_p)
5743 notice_overwritten_cursor (w, updated_area,
5744 output_cursor.x, -1,
5745 updated_row->y,
5746 MATRIX_ROW_BOTTOM_Y (updated_row));
5747
5748 from_x = output_cursor.x;
5749
5750 /* Translate to frame coordinates. */
5751 if (updated_row->full_width_p)
5752 {
5753 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5754 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5755 }
5756 else
5757 {
5758 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5759 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5760 }
5761
5762 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5763 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5764 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5765
5766 /* Prevent inadvertently clearing to end of the X window. */
5767 if (to_x > from_x && to_y > from_y)
5768 {
5769 BLOCK_INPUT;
5770 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5771 from_x, from_y, to_x - from_x, to_y - from_y,
5772 0);
5773 UNBLOCK_INPUT;
5774 }
5775 }
5776
5777
5778 /* Clear entire frame. If updating_frame is non-null, clear that
5779 frame. Otherwise clear the selected frame. */
5780
5781 static void
5782 x_clear_frame ()
5783 {
5784 struct frame *f;
5785
5786 if (updating_frame)
5787 f = updating_frame;
5788 else
5789 f = SELECTED_FRAME ();
5790
5791 /* Clearing the frame will erase any cursor, so mark them all as no
5792 longer visible. */
5793 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5794 output_cursor.hpos = output_cursor.vpos = 0;
5795 output_cursor.x = -1;
5796
5797 /* We don't set the output cursor here because there will always
5798 follow an explicit cursor_to. */
5799 BLOCK_INPUT;
5800 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5801
5802 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5803 /* We have to clear the scroll bars, too. If we have changed
5804 colors or something like that, then they should be notified. */
5805 x_scroll_bar_clear (f);
5806 #endif
5807
5808 XFlush (FRAME_MAC_DISPLAY (f));
5809 UNBLOCK_INPUT;
5810 }
5811
5812
5813 \f
5814 /* Invert the middle quarter of the frame for .15 sec. */
5815
5816 /* We use the select system call to do the waiting, so we have to make
5817 sure it's available. If it isn't, we just won't do visual bells. */
5818
5819 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5820
5821 /* Subtract the `struct timeval' values X and Y, storing the result in
5822 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5823
5824 static int
5825 timeval_subtract (result, x, y)
5826 struct timeval *result, x, y;
5827 {
5828 /* Perform the carry for the later subtraction by updating y. This
5829 is safer because on some systems the tv_sec member is unsigned. */
5830 if (x.tv_usec < y.tv_usec)
5831 {
5832 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5833 y.tv_usec -= 1000000 * nsec;
5834 y.tv_sec += nsec;
5835 }
5836
5837 if (x.tv_usec - y.tv_usec > 1000000)
5838 {
5839 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5840 y.tv_usec += 1000000 * nsec;
5841 y.tv_sec -= nsec;
5842 }
5843
5844 /* Compute the time remaining to wait. tv_usec is certainly
5845 positive. */
5846 result->tv_sec = x.tv_sec - y.tv_sec;
5847 result->tv_usec = x.tv_usec - y.tv_usec;
5848
5849 /* Return indication of whether the result should be considered
5850 negative. */
5851 return x.tv_sec < y.tv_sec;
5852 }
5853
5854 void
5855 XTflash (f)
5856 struct frame *f;
5857 {
5858 BLOCK_INPUT;
5859
5860 FlashMenuBar (0);
5861
5862 {
5863 struct timeval wakeup;
5864
5865 EMACS_GET_TIME (wakeup);
5866
5867 /* Compute time to wait until, propagating carry from usecs. */
5868 wakeup.tv_usec += 150000;
5869 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5870 wakeup.tv_usec %= 1000000;
5871
5872 /* Keep waiting until past the time wakeup. */
5873 while (1)
5874 {
5875 struct timeval timeout;
5876
5877 EMACS_GET_TIME (timeout);
5878
5879 /* In effect, timeout = wakeup - timeout.
5880 Break if result would be negative. */
5881 if (timeval_subtract (&timeout, wakeup, timeout))
5882 break;
5883
5884 /* Try to wait that long--but we might wake up sooner. */
5885 select (0, NULL, NULL, NULL, &timeout);
5886 }
5887 }
5888
5889 FlashMenuBar (0);
5890
5891 UNBLOCK_INPUT;
5892 }
5893
5894 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5895
5896
5897 /* Make audible bell. */
5898
5899 void
5900 XTring_bell ()
5901 {
5902 struct frame *f = SELECTED_FRAME ();
5903
5904 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5905 if (visible_bell)
5906 XTflash (f);
5907 else
5908 #endif
5909 {
5910 BLOCK_INPUT;
5911 SysBeep (1);
5912 XFlush (FRAME_MAC_DISPLAY (f));
5913 UNBLOCK_INPUT;
5914 }
5915 }
5916
5917
5918 \f
5919 /* Specify how many text lines, from the top of the window,
5920 should be affected by insert-lines and delete-lines operations.
5921 This, and those operations, are used only within an update
5922 that is bounded by calls to x_update_begin and x_update_end. */
5923
5924 void
5925 XTset_terminal_window (n)
5926 register int n;
5927 {
5928 /* This function intentionally left blank. */
5929 }
5930
5931
5932 \f
5933 /***********************************************************************
5934 Line Dance
5935 ***********************************************************************/
5936
5937 /* Perform an insert-lines or delete-lines operation, inserting N
5938 lines or deleting -N lines at vertical position VPOS. */
5939
5940 static void
5941 x_ins_del_lines (vpos, n)
5942 int vpos, n;
5943 {
5944 abort ();
5945 }
5946
5947
5948 /* Scroll part of the display as described by RUN. */
5949
5950 static void
5951 x_scroll_run (w, run)
5952 struct window *w;
5953 struct run *run;
5954 {
5955 struct frame *f = XFRAME (w->frame);
5956 int x, y, width, height, from_y, to_y, bottom_y;
5957
5958 /* Get frame-relative bounding box of the text display area of W,
5959 without mode lines. Include in this box the left and right
5960 fringes of W. */
5961 window_box (w, -1, &x, &y, &width, &height);
5962 width += FRAME_X_FRINGE_WIDTH (f);
5963 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5964
5965 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5966 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5967 bottom_y = y + height;
5968
5969 if (to_y < from_y)
5970 {
5971 /* Scrolling up. Make sure we don't copy part of the mode
5972 line at the bottom. */
5973 if (from_y + run->height > bottom_y)
5974 height = bottom_y - from_y;
5975 else
5976 height = run->height;
5977 }
5978 else
5979 {
5980 /* Scolling down. Make sure we don't copy over the mode line.
5981 at the bottom. */
5982 if (to_y + run->height > bottom_y)
5983 height = bottom_y - to_y;
5984 else
5985 height = run->height;
5986 }
5987
5988 BLOCK_INPUT;
5989
5990 /* Cursor off. Will be switched on again in x_update_window_end. */
5991 updated_window = w;
5992 x_clear_cursor (w);
5993
5994 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5995 f->output_data.mac->normal_gc,
5996 x, from_y,
5997 width, height,
5998 x, to_y);
5999
6000 UNBLOCK_INPUT;
6001 }
6002
6003
6004 \f
6005 /***********************************************************************
6006 Exposure Events
6007 ***********************************************************************/
6008
6009 /* Redisplay an exposed area of frame F. X and Y are the upper-left
6010 corner of the exposed rectangle. W and H are width and height of
6011 the exposed area. All are pixel values. W or H zero means redraw
6012 the entire frame. */
6013
6014 static void
6015 expose_frame (f, x, y, w, h)
6016 struct frame *f;
6017 int x, y, w, h;
6018 {
6019 Rect r;
6020 int mouse_face_overwritten_p = 0;
6021
6022 TRACE ((stderr, "expose_frame "));
6023
6024 /* No need to redraw if frame will be redrawn soon. */
6025 if (FRAME_GARBAGED_P (f))
6026 {
6027 TRACE ((stderr, " garbaged\n"));
6028 return;
6029 }
6030
6031 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6032 or deactivated here, for unknown reasons, activated scroll bars
6033 are shown in deactivated frames in some instances. */
6034 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6035 activate_scroll_bars (f);
6036 else
6037 deactivate_scroll_bars (f);
6038
6039 /* If basic faces haven't been realized yet, there is no point in
6040 trying to redraw anything. This can happen when we get an expose
6041 event while Emacs is starting, e.g. by moving another window. */
6042 if (FRAME_FACE_CACHE (f) == NULL
6043 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6044 {
6045 TRACE ((stderr, " no faces\n"));
6046 return;
6047 }
6048
6049 if (w == 0 || h == 0)
6050 {
6051 r.left = r.top = 0;
6052 r.right = CANON_X_UNIT (f) * f->width;
6053 r.bottom = CANON_Y_UNIT (f) * f->height;
6054 }
6055 else
6056 {
6057 r.left = x;
6058 r.top = y;
6059 r.right = x + w;
6060 r.bottom = y + h;
6061 }
6062
6063 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
6064 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
6065
6066 if (WINDOWP (f->tool_bar_window))
6067 mouse_face_overwritten_p
6068 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6069
6070 /* Some window managers support a focus-follows-mouse style with
6071 delayed raising of frames. Imagine a partially obscured frame,
6072 and moving the mouse into partially obscured mouse-face on that
6073 frame. The visible part of the mouse-face will be highlighted,
6074 then the WM raises the obscured frame. With at least one WM, KDE
6075 2.1, Emacs is not getting any event for the raising of the frame
6076 (even tried with SubstructureRedirectMask), only Expose events.
6077 These expose events will draw text normally, i.e. not
6078 highlighted. Which means we must redo the highlight here.
6079 Subsume it under ``we love X''. --gerd 2001-08-15 */
6080 /* Included in Windows version because Windows most likely does not
6081 do the right thing if any third party tool offers
6082 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6083 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
6084 {
6085 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6086 if (f == dpyinfo->mouse_face_mouse_frame)
6087 {
6088 int x = dpyinfo->mouse_face_mouse_x;
6089 int y = dpyinfo->mouse_face_mouse_y;
6090 clear_mouse_face (dpyinfo);
6091 note_mouse_highlight (f, x, y);
6092 }
6093 }
6094 }
6095
6096
6097 /* Redraw (parts) of all windows in the window tree rooted at W that
6098 intersect R. R contains frame pixel coordinates. */
6099
6100 static int
6101 expose_window_tree (w, r)
6102 struct window *w;
6103 Rect *r;
6104 {
6105 struct frame *f = XFRAME (w->frame);
6106 int mouse_face_overwritten_p = 0;
6107
6108 while (w && !FRAME_GARBAGED_P (f))
6109 {
6110 if (!NILP (w->hchild))
6111 mouse_face_overwritten_p
6112 |= expose_window_tree (XWINDOW (w->hchild), r);
6113 else if (!NILP (w->vchild))
6114 mouse_face_overwritten_p
6115 |= expose_window_tree (XWINDOW (w->vchild), r);
6116 else
6117 mouse_face_overwritten_p |= expose_window (w, r);
6118
6119 w = NILP (w->next) ? NULL : XWINDOW (w->next);
6120 }
6121
6122 return mouse_face_overwritten_p;
6123 }
6124
6125
6126 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
6127 which intersects rectangle R. R is in window-relative coordinates. */
6128
6129 static void
6130 expose_area (w, row, r, area)
6131 struct window *w;
6132 struct glyph_row *row;
6133 Rect *r;
6134 enum glyph_row_area area;
6135 {
6136 struct glyph *first = row->glyphs[area];
6137 struct glyph *end = row->glyphs[area] + row->used[area];
6138 struct glyph *last;
6139 int first_x, start_x, x;
6140
6141 if (area == TEXT_AREA && row->fill_line_p)
6142 /* If row extends face to end of line write the whole line. */
6143 x_draw_glyphs (w, 0, row, area,
6144 0, row->used[area],
6145 DRAW_NORMAL_TEXT, 0);
6146 else
6147 {
6148 /* Set START_X to the window-relative start position for drawing glyphs of
6149 AREA. The first glyph of the text area can be partially visible.
6150 The first glyphs of other areas cannot. */
6151 if (area == LEFT_MARGIN_AREA)
6152 start_x = 0;
6153 else if (area == TEXT_AREA)
6154 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6155 else
6156 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6157 + window_box_width (w, TEXT_AREA));
6158 x = start_x;
6159
6160 /* Find the first glyph that must be redrawn. */
6161 while (first < end
6162 && x + first->pixel_width < r->left)
6163 {
6164 x += first->pixel_width;
6165 ++first;
6166 }
6167
6168 /* Find the last one. */
6169 last = first;
6170 first_x = x;
6171 while (last < end
6172 && x < r->right)
6173 {
6174 x += last->pixel_width;
6175 ++last;
6176 }
6177
6178 /* Repaint. */
6179 if (last > first)
6180 x_draw_glyphs (w, first_x - start_x, row, area,
6181 first - row->glyphs[area],
6182 last - row->glyphs[area],
6183 DRAW_NORMAL_TEXT, 0);
6184 }
6185 }
6186
6187
6188 /* Redraw the parts of the glyph row ROW on window W intersecting
6189 rectangle R. R is in window-relative coordinates. Value is
6190 non-zero if mouse face was overwritten. */
6191
6192 static int
6193 expose_line (w, row, r)
6194 struct window *w;
6195 struct glyph_row *row;
6196 Rect *r;
6197 {
6198 xassert (row->enabled_p);
6199
6200 if (row->mode_line_p || w->pseudo_window_p)
6201 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6202 DRAW_NORMAL_TEXT, 0);
6203 else
6204 {
6205 if (row->used[LEFT_MARGIN_AREA])
6206 expose_area (w, row, r, LEFT_MARGIN_AREA);
6207 if (row->used[TEXT_AREA])
6208 expose_area (w, row, r, TEXT_AREA);
6209 if (row->used[RIGHT_MARGIN_AREA])
6210 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6211 x_draw_row_fringe_bitmaps (w, row);
6212 }
6213
6214 return row->mouse_face_p;
6215 }
6216
6217
6218 /* Return non-zero if W's cursor intersects rectangle R. */
6219
6220 static int
6221 x_phys_cursor_in_rect_p (w, r)
6222 struct window *w;
6223 Rect *r;
6224 {
6225 Rect cr, result;
6226 struct glyph *cursor_glyph;
6227
6228 cursor_glyph = get_phys_cursor_glyph (w);
6229 if (cursor_glyph)
6230 {
6231 cr.left = w->phys_cursor.x;
6232 cr.top = w->phys_cursor.y;
6233 cr.right = cr.left + cursor_glyph->pixel_width;
6234 cr.bottom = cr.top + w->phys_cursor_height;
6235 return x_intersect_rectangles (&cr, r, &result);
6236 }
6237 else
6238 return 0;
6239 }
6240
6241
6242 /* Redraw the part of window W intersection rectagle FR. Pixel
6243 coordinates in FR are frame relative. Call this function with
6244 input blocked. Value is non-zero if the exposure overwrites
6245 mouse-face. */
6246
6247 static int
6248 expose_window (w, fr)
6249 struct window *w;
6250 Rect *fr;
6251 {
6252 struct frame *f = XFRAME (w->frame);
6253 Rect wr, r;
6254 int mouse_face_overwritten_p = 0;
6255
6256 /* If window is not yet fully initialized, do nothing. This can
6257 happen when toolkit scroll bars are used and a window is split.
6258 Reconfiguring the scroll bar will generate an expose for a newly
6259 created window. */
6260 if (w->current_matrix == NULL)
6261 return 0;
6262
6263 /* When we're currently updating the window, display and current
6264 matrix usually don't agree. Arrange for a thorough display
6265 later. */
6266 if (w == updated_window)
6267 {
6268 SET_FRAME_GARBAGED (f);
6269 return 0;
6270 }
6271
6272 /* Frame-relative pixel rectangle of W. */
6273 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6274 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6275 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6276 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6277
6278 if (x_intersect_rectangles (fr, &wr, &r))
6279 {
6280 int yb = window_text_bottom_y (w);
6281 struct glyph_row *row;
6282 int cursor_cleared_p;
6283
6284 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6285 r.left, r.top, r.right, r.bottom));
6286
6287 /* Convert to window coordinates. */
6288 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6289 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6290 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6291 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6292
6293 /* Turn off the cursor. */
6294 if (!w->pseudo_window_p
6295 && x_phys_cursor_in_rect_p (w, &r))
6296 {
6297 x_clear_cursor (w);
6298 cursor_cleared_p = 1;
6299 }
6300 else
6301 cursor_cleared_p = 0;
6302
6303 /* Find the first row intersecting the rectangle R. */
6304 for (row = w->current_matrix->rows;
6305 row->enabled_p;
6306 ++row)
6307 {
6308 int y0 = row->y;
6309 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6310
6311 if ((y0 >= r.top && y0 < r.bottom)
6312 || (y1 > r.top && y1 < r.bottom)
6313 || (r.top >= y0 && r.top < y1)
6314 || (r.bottom > y0 && r.bottom < y1))
6315 {
6316 if (expose_line (w, row, &r))
6317 mouse_face_overwritten_p = 1;
6318 }
6319
6320 if (y1 >= yb)
6321 break;
6322 }
6323
6324 /* Display the mode line if there is one. */
6325 if (WINDOW_WANTS_MODELINE_P (w)
6326 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6327 row->enabled_p)
6328 && row->y < r.bottom)
6329 {
6330 if (expose_line (w, row, &r))
6331 mouse_face_overwritten_p = 1;
6332 }
6333
6334 if (!w->pseudo_window_p)
6335 {
6336 /* Draw border between windows. */
6337 x_draw_vertical_border (w);
6338
6339 /* Turn the cursor on again. */
6340 if (cursor_cleared_p)
6341 x_update_window_cursor (w, 1);
6342 }
6343 }
6344
6345 /* Display scroll bar for this window. */
6346 if (!NILP (w->vertical_scroll_bar))
6347 {
6348 ControlHandle ch
6349 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6350
6351 Draw1Control (ch);
6352 }
6353
6354 return mouse_face_overwritten_p;
6355 }
6356
6357 static int
6358 x_intersect_rectangles (r1, r2, result)
6359 Rect *r1, *r2, *result;
6360 {
6361 Rect *left, *right;
6362 Rect *upper, *lower;
6363 int intersection_p = 0;
6364
6365 /* Rerrange so that R1 is the left-most rectangle. */
6366 if (r1->left < r2->left)
6367 left = r1, right = r2;
6368 else
6369 left = r2, right = r1;
6370
6371 /* X0 of the intersection is right.x0, if this is inside R1,
6372 otherwise there is no intersection. */
6373 if (right->left <= left->right)
6374 {
6375 result->left = right->left;
6376
6377 /* The right end of the intersection is the minimum of the
6378 the right ends of left and right. */
6379 result->right = min (left->right, right->right);
6380
6381 /* Same game for Y. */
6382 if (r1->top < r2->top)
6383 upper = r1, lower = r2;
6384 else
6385 upper = r2, lower = r1;
6386
6387 /* The upper end of the intersection is lower.y0, if this is inside
6388 of upper. Otherwise, there is no intersection. */
6389 if (lower->top <= upper->bottom)
6390 {
6391 result->top = lower->top;
6392
6393 /* The lower end of the intersection is the minimum of the lower
6394 ends of upper and lower. */
6395 result->bottom = min (lower->bottom, upper->bottom);
6396 intersection_p = 1;
6397 }
6398 }
6399
6400 return intersection_p;
6401 }
6402
6403
6404
6405
6406 \f
6407 static void
6408 frame_highlight (f)
6409 struct frame *f;
6410 {
6411 x_update_cursor (f, 1);
6412 }
6413
6414 static void
6415 frame_unhighlight (f)
6416 struct frame *f;
6417 {
6418 x_update_cursor (f, 1);
6419 }
6420
6421 /* The focus has changed. Update the frames as necessary to reflect
6422 the new situation. Note that we can't change the selected frame
6423 here, because the Lisp code we are interrupting might become confused.
6424 Each event gets marked with the frame in which it occurred, so the
6425 Lisp code can tell when the switch took place by examining the events. */
6426
6427 static void
6428 x_new_focus_frame (dpyinfo, frame)
6429 struct x_display_info *dpyinfo;
6430 struct frame *frame;
6431 {
6432 struct frame *old_focus = dpyinfo->x_focus_frame;
6433
6434 if (frame != dpyinfo->x_focus_frame)
6435 {
6436 /* Set this before calling other routines, so that they see
6437 the correct value of x_focus_frame. */
6438 dpyinfo->x_focus_frame = frame;
6439
6440 if (old_focus && old_focus->auto_lower)
6441 x_lower_frame (old_focus);
6442
6443 #if 0
6444 selected_frame = frame;
6445 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6446 selected_frame);
6447 Fselect_window (selected_frame->selected_window);
6448 choose_minibuf_frame ();
6449 #endif /* ! 0 */
6450
6451 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6452 pending_autoraise_frame = dpyinfo->x_focus_frame;
6453 else
6454 pending_autoraise_frame = 0;
6455 }
6456
6457 x_frame_rehighlight (dpyinfo);
6458 }
6459
6460 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6461
6462 void
6463 x_mouse_leave (dpyinfo)
6464 struct x_display_info *dpyinfo;
6465 {
6466 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6467 }
6468
6469 /* The focus has changed, or we have redirected a frame's focus to
6470 another frame (this happens when a frame uses a surrogate
6471 mini-buffer frame). Shift the highlight as appropriate.
6472
6473 The FRAME argument doesn't necessarily have anything to do with which
6474 frame is being highlighted or un-highlighted; we only use it to find
6475 the appropriate X display info. */
6476
6477 static void
6478 XTframe_rehighlight (frame)
6479 struct frame *frame;
6480 {
6481 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6482 }
6483
6484 static void
6485 x_frame_rehighlight (dpyinfo)
6486 struct x_display_info *dpyinfo;
6487 {
6488 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6489
6490 if (dpyinfo->x_focus_frame)
6491 {
6492 dpyinfo->x_highlight_frame
6493 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6494 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6495 : dpyinfo->x_focus_frame);
6496 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6497 {
6498 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6499 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6500 }
6501 }
6502 else
6503 dpyinfo->x_highlight_frame = 0;
6504
6505 if (dpyinfo->x_highlight_frame != old_highlight)
6506 {
6507 if (old_highlight)
6508 frame_unhighlight (old_highlight);
6509 if (dpyinfo->x_highlight_frame)
6510 frame_highlight (dpyinfo->x_highlight_frame);
6511 }
6512 }
6513
6514
6515 \f
6516 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6517
6518 #if 0 /* MAC_TODO */
6519 /* Initialize mode_switch_bit and modifier_meaning. */
6520 static void
6521 x_find_modifier_meanings (dpyinfo)
6522 struct x_display_info *dpyinfo;
6523 {
6524 int min_code, max_code;
6525 KeySym *syms;
6526 int syms_per_code;
6527 XModifierKeymap *mods;
6528
6529 dpyinfo->meta_mod_mask = 0;
6530 dpyinfo->shift_lock_mask = 0;
6531 dpyinfo->alt_mod_mask = 0;
6532 dpyinfo->super_mod_mask = 0;
6533 dpyinfo->hyper_mod_mask = 0;
6534
6535 #ifdef HAVE_X11R4
6536 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6537 #else
6538 min_code = dpyinfo->display->min_keycode;
6539 max_code = dpyinfo->display->max_keycode;
6540 #endif
6541
6542 syms = XGetKeyboardMapping (dpyinfo->display,
6543 min_code, max_code - min_code + 1,
6544 &syms_per_code);
6545 mods = XGetModifierMapping (dpyinfo->display);
6546
6547 /* Scan the modifier table to see which modifier bits the Meta and
6548 Alt keysyms are on. */
6549 {
6550 int row, col; /* The row and column in the modifier table. */
6551
6552 for (row = 3; row < 8; row++)
6553 for (col = 0; col < mods->max_keypermod; col++)
6554 {
6555 KeyCode code
6556 = mods->modifiermap[(row * mods->max_keypermod) + col];
6557
6558 /* Zeroes are used for filler. Skip them. */
6559 if (code == 0)
6560 continue;
6561
6562 /* Are any of this keycode's keysyms a meta key? */
6563 {
6564 int code_col;
6565
6566 for (code_col = 0; code_col < syms_per_code; code_col++)
6567 {
6568 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6569
6570 switch (sym)
6571 {
6572 case XK_Meta_L:
6573 case XK_Meta_R:
6574 dpyinfo->meta_mod_mask |= (1 << row);
6575 break;
6576
6577 case XK_Alt_L:
6578 case XK_Alt_R:
6579 dpyinfo->alt_mod_mask |= (1 << row);
6580 break;
6581
6582 case XK_Hyper_L:
6583 case XK_Hyper_R:
6584 dpyinfo->hyper_mod_mask |= (1 << row);
6585 break;
6586
6587 case XK_Super_L:
6588 case XK_Super_R:
6589 dpyinfo->super_mod_mask |= (1 << row);
6590 break;
6591
6592 case XK_Shift_Lock:
6593 /* Ignore this if it's not on the lock modifier. */
6594 if ((1 << row) == LockMask)
6595 dpyinfo->shift_lock_mask = LockMask;
6596 break;
6597 }
6598 }
6599 }
6600 }
6601 }
6602
6603 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6604 if (! dpyinfo->meta_mod_mask)
6605 {
6606 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6607 dpyinfo->alt_mod_mask = 0;
6608 }
6609
6610 /* If some keys are both alt and meta,
6611 make them just meta, not alt. */
6612 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6613 {
6614 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6615 }
6616
6617 XFree ((char *) syms);
6618 XFreeModifiermap (mods);
6619 }
6620
6621 #endif /* MAC_TODO */
6622
6623 /* Convert between the modifier bits X uses and the modifier bits
6624 Emacs uses. */
6625
6626 static unsigned int
6627 x_mac_to_emacs_modifiers (dpyinfo, state)
6628 struct x_display_info *dpyinfo;
6629 unsigned short state;
6630 {
6631 return (((state & shiftKey) ? shift_modifier : 0)
6632 | ((state & controlKey) ? ctrl_modifier : 0)
6633 | ((state & cmdKey) ? meta_modifier : 0)
6634 | ((state & optionKey) ? alt_modifier : 0));
6635 }
6636
6637 #if 0 /* MAC_TODO */
6638 static unsigned short
6639 x_emacs_to_x_modifiers (dpyinfo, state)
6640 struct x_display_info *dpyinfo;
6641 unsigned int state;
6642 {
6643 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6644 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6645 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6646 | ((state & shift_modifier) ? ShiftMask : 0)
6647 | ((state & ctrl_modifier) ? ControlMask : 0)
6648 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6649 }
6650 #endif /* MAC_TODO */
6651
6652 /* Convert a keysym to its name. */
6653
6654 char *
6655 x_get_keysym_name (keysym)
6656 int keysym;
6657 {
6658 char *value;
6659
6660 BLOCK_INPUT;
6661 #if 0
6662 value = XKeysymToString (keysym);
6663 #else
6664 value = 0;
6665 #endif
6666 UNBLOCK_INPUT;
6667
6668 return value;
6669 }
6670
6671
6672 \f
6673 /* Mouse clicks and mouse movement. Rah. */
6674
6675 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6676 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6677 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6678 not force the value into range. */
6679
6680 void
6681 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6682 FRAME_PTR f;
6683 register int pix_x, pix_y;
6684 register int *x, *y;
6685 Rect *bounds;
6686 int noclip;
6687 {
6688 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6689 if (NILP (Vwindow_system))
6690 {
6691 *x = pix_x;
6692 *y = pix_y;
6693 return;
6694 }
6695
6696 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6697 even for negative values. */
6698 if (pix_x < 0)
6699 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6700 if (pix_y < 0)
6701 pix_y -= (f)->output_data.mac->line_height - 1;
6702
6703 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6704 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6705
6706 if (bounds)
6707 {
6708 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6709 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6710 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6711 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
6712 }
6713
6714 if (!noclip)
6715 {
6716 if (pix_x < 0)
6717 pix_x = 0;
6718 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6719 pix_x = FRAME_WINDOW_WIDTH (f);
6720
6721 if (pix_y < 0)
6722 pix_y = 0;
6723 else if (pix_y > f->height)
6724 pix_y = f->height;
6725 }
6726
6727 *x = pix_x;
6728 *y = pix_y;
6729 }
6730
6731
6732 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6733 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6734 can't tell the positions because W's display is not up to date,
6735 return 0. */
6736
6737 int
6738 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6739 struct window *w;
6740 int hpos, vpos;
6741 int *frame_x, *frame_y;
6742 {
6743 int success_p;
6744
6745 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6746 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6747
6748 if (display_completed)
6749 {
6750 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6751 struct glyph *glyph = row->glyphs[TEXT_AREA];
6752 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6753
6754 *frame_y = row->y;
6755 *frame_x = row->x;
6756 while (glyph < end)
6757 {
6758 *frame_x += glyph->pixel_width;
6759 ++glyph;
6760 }
6761
6762 success_p = 1;
6763 }
6764 else
6765 {
6766 *frame_y = *frame_x = 0;
6767 success_p = 0;
6768 }
6769
6770 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6771 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6772 return success_p;
6773 }
6774
6775
6776 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6777
6778 If the event is a button press, then note that we have grabbed
6779 the mouse. */
6780
6781 static Lisp_Object
6782 construct_mouse_click (result, event, f)
6783 struct input_event *result;
6784 EventRecord *event;
6785 struct frame *f;
6786 {
6787 Point mouseLoc;
6788
6789 result->kind = MOUSE_CLICK_EVENT;
6790 result->code = 0; /* only one mouse button */
6791 result->timestamp = event->when;
6792 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6793
6794 mouseLoc = event->where;
6795
6796 #if TARGET_API_MAC_CARBON
6797 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6798 #else
6799 SetPort (FRAME_MAC_WINDOW (f));
6800 #endif
6801
6802 GlobalToLocal (&mouseLoc);
6803 XSETINT (result->x, mouseLoc.h);
6804 XSETINT (result->y, mouseLoc.v);
6805
6806 XSETFRAME (result->frame_or_window, f);
6807
6808 result->arg = Qnil;
6809 return Qnil;
6810 }
6811
6812 \f
6813 /* Function to report a mouse movement to the mainstream Emacs code.
6814 The input handler calls this.
6815
6816 We have received a mouse movement event, which is given in *event.
6817 If the mouse is over a different glyph than it was last time, tell
6818 the mainstream emacs code by setting mouse_moved. If not, ask for
6819 another motion event, so we can check again the next time it moves. */
6820
6821 static Point last_mouse_motion_position;
6822 static Lisp_Object last_mouse_motion_frame;
6823
6824 static void
6825 note_mouse_movement (frame, pos)
6826 FRAME_PTR frame;
6827 Point *pos;
6828 {
6829 #if TARGET_API_MAC_CARBON
6830 Rect r;
6831 #endif
6832
6833 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6834 last_mouse_motion_position = *pos;
6835 XSETFRAME (last_mouse_motion_frame, frame);
6836
6837 #if TARGET_API_MAC_CARBON
6838 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6839 #else
6840 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6841 #endif
6842 {
6843 frame->mouse_moved = 1;
6844 last_mouse_scroll_bar = Qnil;
6845 note_mouse_highlight (frame, -1, -1);
6846 }
6847 /* Has the mouse moved off the glyph it was on at the last sighting? */
6848 else if (pos->h < last_mouse_glyph.left
6849 || pos->h >= last_mouse_glyph.right
6850 || pos->v < last_mouse_glyph.top
6851 || pos->v >= last_mouse_glyph.bottom)
6852 {
6853 frame->mouse_moved = 1;
6854 last_mouse_scroll_bar = Qnil;
6855 note_mouse_highlight (frame, pos->h, pos->v);
6856 }
6857 }
6858
6859 /* This is used for debugging, to turn off note_mouse_highlight. */
6860
6861 int disable_mouse_highlight;
6862
6863
6864 \f
6865 /************************************************************************
6866 Mouse Face
6867 ************************************************************************/
6868
6869 /* Find the glyph under window-relative coordinates X/Y in window W.
6870 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6871 strings. Return in *HPOS and *VPOS the row and column number of
6872 the glyph found. Return in *AREA the glyph area containing X.
6873 Value is a pointer to the glyph found or null if X/Y is not on
6874 text, or we can't tell because W's current matrix is not up to
6875 date. */
6876
6877 static struct glyph *
6878 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6879 struct window *w;
6880 int x, y;
6881 int *hpos, *vpos, *area;
6882 int buffer_only_p;
6883 {
6884 struct glyph *glyph, *end;
6885 struct glyph_row *row = NULL;
6886 int x0, i, left_area_width;
6887
6888 /* Find row containing Y. Give up if some row is not enabled. */
6889 for (i = 0; i < w->current_matrix->nrows; ++i)
6890 {
6891 row = MATRIX_ROW (w->current_matrix, i);
6892 if (!row->enabled_p)
6893 return NULL;
6894 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6895 break;
6896 }
6897
6898 *vpos = i;
6899 *hpos = 0;
6900
6901 /* Give up if Y is not in the window. */
6902 if (i == w->current_matrix->nrows)
6903 return NULL;
6904
6905 /* Get the glyph area containing X. */
6906 if (w->pseudo_window_p)
6907 {
6908 *area = TEXT_AREA;
6909 x0 = 0;
6910 }
6911 else
6912 {
6913 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6914 if (x < left_area_width)
6915 {
6916 *area = LEFT_MARGIN_AREA;
6917 x0 = 0;
6918 }
6919 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6920 {
6921 *area = TEXT_AREA;
6922 x0 = row->x + left_area_width;
6923 }
6924 else
6925 {
6926 *area = RIGHT_MARGIN_AREA;
6927 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6928 }
6929 }
6930
6931 /* Find glyph containing X. */
6932 glyph = row->glyphs[*area];
6933 end = glyph + row->used[*area];
6934 while (glyph < end)
6935 {
6936 if (x < x0 + glyph->pixel_width)
6937 {
6938 if (w->pseudo_window_p)
6939 break;
6940 else if (!buffer_only_p || BUFFERP (glyph->object))
6941 break;
6942 }
6943
6944 x0 += glyph->pixel_width;
6945 ++glyph;
6946 }
6947
6948 if (glyph == end)
6949 return NULL;
6950
6951 *hpos = glyph - row->glyphs[*area];
6952 return glyph;
6953 }
6954
6955
6956 /* Convert frame-relative x/y to coordinates relative to window W.
6957 Takes pseudo-windows into account. */
6958
6959 static void
6960 frame_to_window_pixel_xy (w, x, y)
6961 struct window *w;
6962 int *x, *y;
6963 {
6964 if (w->pseudo_window_p)
6965 {
6966 /* A pseudo-window is always full-width, and starts at the
6967 left edge of the frame, plus a frame border. */
6968 struct frame *f = XFRAME (w->frame);
6969 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6970 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6971 }
6972 else
6973 {
6974 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6975 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6976 }
6977 }
6978
6979
6980 /* Take proper action when mouse has moved to the mode or header line of
6981 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6982 mode line. X is relative to the start of the text display area of
6983 W, so the width of fringes and scroll bars must be subtracted
6984 to get a position relative to the start of the mode line. */
6985
6986 static void
6987 note_mode_line_highlight (w, x, mode_line_p)
6988 struct window *w;
6989 int x, mode_line_p;
6990 {
6991 struct frame *f = XFRAME (w->frame);
6992 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6993 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
6994 struct glyph_row *row;
6995
6996 if (mode_line_p)
6997 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6998 else
6999 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
7000
7001 if (row->enabled_p)
7002 {
7003 struct glyph *glyph, *end;
7004 Lisp_Object help, map;
7005 int x0;
7006
7007 /* Find the glyph under X. */
7008 glyph = row->glyphs[TEXT_AREA];
7009 end = glyph + row->used[TEXT_AREA];
7010 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
7011 + FRAME_X_LEFT_FRINGE_WIDTH (f));
7012
7013 while (glyph < end
7014 && x >= x0 + glyph->pixel_width)
7015 {
7016 x0 += glyph->pixel_width;
7017 ++glyph;
7018 }
7019
7020 if (glyph < end
7021 && STRINGP (glyph->object)
7022 && STRING_INTERVALS (glyph->object)
7023 && glyph->charpos >= 0
7024 && glyph->charpos < SCHARS (glyph->object))
7025 {
7026 /* If we're on a string with `help-echo' text property,
7027 arrange for the help to be displayed. This is done by
7028 setting the global variable help_echo to the help string. */
7029 help = Fget_text_property (make_number (glyph->charpos),
7030 Qhelp_echo, glyph->object);
7031 if (!NILP (help))
7032 {
7033 help_echo = help;
7034 XSETWINDOW (help_echo_window, w);
7035 help_echo_object = glyph->object;
7036 help_echo_pos = glyph->charpos;
7037 }
7038
7039 /* Change the mouse pointer according to what is under X/Y. */
7040 map = Fget_text_property (make_number (glyph->charpos),
7041 Qlocal_map, glyph->object);
7042 if (KEYMAPP (map))
7043 cursor = f->output_data.mac->nontext_cursor;
7044 else
7045 {
7046 map = Fget_text_property (make_number (glyph->charpos),
7047 Qkeymap, glyph->object);
7048 if (KEYMAPP (map))
7049 cursor = f->output_data.mac->nontext_cursor;
7050 }
7051 }
7052 }
7053
7054 #if 0 /* MAC_TODO: mouse cursor */
7055 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7056 #endif
7057 }
7058
7059
7060 /* Take proper action when the mouse has moved to position X, Y on
7061 frame F as regards highlighting characters that have mouse-face
7062 properties. Also de-highlighting chars where the mouse was before.
7063 X and Y can be negative or out of range. */
7064
7065 static void
7066 note_mouse_highlight (f, x, y)
7067 struct frame *f;
7068 int x, y;
7069 {
7070 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7071 int portion;
7072 Lisp_Object window;
7073 struct window *w;
7074 struct buffer *b;
7075
7076 #if 0
7077 /* When a menu is active, don't highlight because this looks odd. */
7078 if (popup_activated ())
7079 return;
7080 #endif
7081
7082 if (NILP (Vmouse_highlight)
7083 || !f->glyphs_initialized_p)
7084 return;
7085
7086 dpyinfo->mouse_face_mouse_x = x;
7087 dpyinfo->mouse_face_mouse_y = y;
7088 dpyinfo->mouse_face_mouse_frame = f;
7089
7090 if (dpyinfo->mouse_face_defer)
7091 return;
7092
7093 if (gc_in_progress)
7094 {
7095 dpyinfo->mouse_face_deferred_gc = 1;
7096 return;
7097 }
7098
7099 /* Which window is that in? */
7100 window = window_from_coordinates (f, x, y, &portion, 1);
7101
7102 /* If we were displaying active text in another window, clear that. */
7103 if (! EQ (window, dpyinfo->mouse_face_window))
7104 clear_mouse_face (dpyinfo);
7105
7106 /* Not on a window -> return. */
7107 if (!WINDOWP (window))
7108 return;
7109
7110 /* Reset help_echo. It will get recomputed below. */
7111 help_echo = Qnil;
7112
7113 /* Convert to window-relative pixel coordinates. */
7114 w = XWINDOW (window);
7115 frame_to_window_pixel_xy (w, &x, &y);
7116
7117 /* Handle tool-bar window differently since it doesn't display a
7118 buffer. */
7119 if (EQ (window, f->tool_bar_window))
7120 {
7121 note_tool_bar_highlight (f, x, y);
7122 return;
7123 }
7124
7125 /* Mouse is on the mode or header line? */
7126 if (portion == 1 || portion == 3)
7127 {
7128 note_mode_line_highlight (w, x, portion == 1);
7129 return;
7130 }
7131 #if 0 /* TODO: mouse cursor */
7132 if (portion == 2)
7133 cursor = f->output_data.x->horizontal_drag_cursor;
7134 else
7135 cursor = f->output_data.x->text_cursor;
7136 #endif
7137 /* Are we in a window whose display is up to date?
7138 And verify the buffer's text has not changed. */
7139 b = XBUFFER (w->buffer);
7140 if (/* Within text portion of the window. */
7141 portion == 0
7142 && EQ (w->window_end_valid, w->buffer)
7143 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7144 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7145 {
7146 int hpos, vpos, pos, i, area;
7147 struct glyph *glyph;
7148 Lisp_Object object;
7149 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7150 Lisp_Object *overlay_vec = NULL;
7151 int len, noverlays;
7152 struct buffer *obuf;
7153 int obegv, ozv, same_region;
7154
7155 /* Find the glyph under X/Y. */
7156 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7157
7158 /* Clear mouse face if X/Y not over text. */
7159 if (glyph == NULL
7160 || area != TEXT_AREA
7161 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7162 {
7163 clear_mouse_face (dpyinfo);
7164 /* TODO: mouse cursor */
7165 goto set_cursor;
7166 }
7167
7168 pos = glyph->charpos;
7169 object = glyph->object;
7170 if (!STRINGP (object) && !BUFFERP (object))
7171 goto set_cursor;
7172
7173 /* If we get an out-of-range value, return now; avoid an error. */
7174 if (BUFFERP (object) && pos > BUF_Z (b))
7175 goto set_cursor;
7176
7177 /* Make the window's buffer temporarily current for
7178 overlays_at and compute_char_face. */
7179 obuf = current_buffer;
7180 current_buffer = b;
7181 obegv = BEGV;
7182 ozv = ZV;
7183 BEGV = BEG;
7184 ZV = Z;
7185
7186 /* Is this char mouse-active or does it have help-echo? */
7187 position = make_number (pos);
7188
7189 if (BUFFERP (object))
7190 {
7191 /* Put all the overlays we want in a vector in overlay_vec.
7192 Store the length in len. If there are more than 10, make
7193 enough space for all, and try again. */
7194 len = 10;
7195 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7196 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7197 if (noverlays > len)
7198 {
7199 len = noverlays;
7200 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7201 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7202 }
7203
7204 /* Sort overlays into increasing priority order. */
7205 noverlays = sort_overlays (overlay_vec, noverlays, w);
7206 }
7207 else
7208 noverlays = 0;
7209
7210 same_region = (EQ (window, dpyinfo->mouse_face_window)
7211 && vpos >= dpyinfo->mouse_face_beg_row
7212 && vpos <= dpyinfo->mouse_face_end_row
7213 && (vpos > dpyinfo->mouse_face_beg_row
7214 || hpos >= dpyinfo->mouse_face_beg_col)
7215 && (vpos < dpyinfo->mouse_face_end_row
7216 || hpos < dpyinfo->mouse_face_end_col
7217 || dpyinfo->mouse_face_past_end));
7218
7219 /* TODO: if (same_region)
7220 mouse cursor */
7221
7222 /* Check mouse-face highlighting. */
7223 if (! same_region
7224 /* If there exists an overlay with mouse-face overlapping
7225 the one we are currently highlighting, we have to
7226 check if we enter the overlapping overlay, and then
7227 highlight that. */
7228 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7229 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7230 {
7231 /* Find the highest priority overlay that has a mouse-face
7232 property. */
7233 overlay = Qnil;
7234 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7235 {
7236 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7237 if (!NILP (mouse_face))
7238 overlay = overlay_vec[i];
7239 }
7240
7241 /* If we're actually highlighting the same overlay as
7242 before, there's no need to do that again. */
7243 if (!NILP (overlay)
7244 && EQ (overlay, dpyinfo->mouse_face_overlay))
7245 goto check_help_echo;
7246
7247 dpyinfo->mouse_face_overlay = overlay;
7248
7249 /* Clear the display of the old active region, if any. */
7250 clear_mouse_face (dpyinfo);
7251 /* TODO: mouse cursor changes. */
7252
7253 /* If no overlay applies, get a text property. */
7254 if (NILP (overlay))
7255 mouse_face = Fget_text_property (position, Qmouse_face, object);
7256
7257 /* Handle the overlay case. */
7258 if (!NILP (overlay))
7259 {
7260 /* Find the range of text around this char that
7261 should be active. */
7262 Lisp_Object before, after;
7263 int ignore;
7264
7265 before = Foverlay_start (overlay);
7266 after = Foverlay_end (overlay);
7267 /* Record this as the current active region. */
7268 fast_find_position (w, XFASTINT (before),
7269 &dpyinfo->mouse_face_beg_col,
7270 &dpyinfo->mouse_face_beg_row,
7271 &dpyinfo->mouse_face_beg_x,
7272 &dpyinfo->mouse_face_beg_y, Qnil);
7273
7274 dpyinfo->mouse_face_past_end
7275 = !fast_find_position (w, XFASTINT (after),
7276 &dpyinfo->mouse_face_end_col,
7277 &dpyinfo->mouse_face_end_row,
7278 &dpyinfo->mouse_face_end_x,
7279 &dpyinfo->mouse_face_end_y, Qnil);
7280 dpyinfo->mouse_face_window = window;
7281
7282 dpyinfo->mouse_face_face_id
7283 = face_at_buffer_position (w, pos, 0, 0,
7284 &ignore, pos + 1, 1);
7285
7286 /* Display it as active. */
7287 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7288 /* TODO: mouse cursor changes. */
7289 }
7290 /* Handle the text property case. */
7291 else if (! NILP (mouse_face) && BUFFERP (object))
7292 {
7293 /* Find the range of text around this char that
7294 should be active. */
7295 Lisp_Object before, after, beginning, end;
7296 int ignore;
7297
7298 beginning = Fmarker_position (w->start);
7299 end = make_number (BUF_Z (XBUFFER (object))
7300 - XFASTINT (w->window_end_pos));
7301 before
7302 = Fprevious_single_property_change (make_number (pos + 1),
7303 Qmouse_face,
7304 object, beginning);
7305 after
7306 = Fnext_single_property_change (position, Qmouse_face,
7307 object, end);
7308
7309 /* Record this as the current active region. */
7310 fast_find_position (w, XFASTINT (before),
7311 &dpyinfo->mouse_face_beg_col,
7312 &dpyinfo->mouse_face_beg_row,
7313 &dpyinfo->mouse_face_beg_x,
7314 &dpyinfo->mouse_face_beg_y, Qnil);
7315 dpyinfo->mouse_face_past_end
7316 = !fast_find_position (w, XFASTINT (after),
7317 &dpyinfo->mouse_face_end_col,
7318 &dpyinfo->mouse_face_end_row,
7319 &dpyinfo->mouse_face_end_x,
7320 &dpyinfo->mouse_face_end_y, Qnil);
7321 dpyinfo->mouse_face_window = window;
7322
7323 if (BUFFERP (object))
7324 dpyinfo->mouse_face_face_id
7325 = face_at_buffer_position (w, pos, 0, 0,
7326 &ignore, pos + 1, 1);
7327
7328 /* Display it as active. */
7329 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7330 /* TODO: mouse cursor changes. */
7331 }
7332 else if (!NILP (mouse_face) && STRINGP (object))
7333 {
7334 Lisp_Object b, e;
7335 int ignore;
7336
7337 b = Fprevious_single_property_change (make_number (pos + 1),
7338 Qmouse_face,
7339 object, Qnil);
7340 e = Fnext_single_property_change (position, Qmouse_face,
7341 object, Qnil);
7342 if (NILP (b))
7343 b = make_number (0);
7344 if (NILP (e))
7345 e = make_number (SCHARS (object) - 1);
7346 fast_find_string_pos (w, XINT (b), object,
7347 &dpyinfo->mouse_face_beg_col,
7348 &dpyinfo->mouse_face_beg_row,
7349 &dpyinfo->mouse_face_beg_x,
7350 &dpyinfo->mouse_face_beg_y, 0);
7351 fast_find_string_pos (w, XINT (e), object,
7352 &dpyinfo->mouse_face_end_col,
7353 &dpyinfo->mouse_face_end_row,
7354 &dpyinfo->mouse_face_end_x,
7355 &dpyinfo->mouse_face_end_y, 1);
7356 dpyinfo->mouse_face_past_end = 0;
7357 dpyinfo->mouse_face_window = window;
7358 dpyinfo->mouse_face_face_id
7359 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7360 glyph->face_id, 1);
7361 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7362 /* TODO: mouse cursor changes. */
7363 }
7364 else if (STRINGP (object) && NILP (mouse_face))
7365 {
7366 /* A string which doesn't have mouse-face, but
7367 the text ``under'' it might have. */
7368 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7369 int start = MATRIX_ROW_START_CHARPOS (r);
7370
7371 pos = string_buffer_position (w, object, start);
7372 if (pos > 0)
7373 mouse_face = get_char_property_and_overlay (make_number (pos),
7374 Qmouse_face,
7375 w->buffer,
7376 &overlay);
7377 if (!NILP (mouse_face) && !NILP (overlay))
7378 {
7379 Lisp_Object before = Foverlay_start (overlay);
7380 Lisp_Object after = Foverlay_end (overlay);
7381 int ignore;
7382
7383 /* Note that we might not be able to find position
7384 BEFORE in the glyph matrix if the overlay is
7385 entirely covered by a `display' property. In
7386 this case, we overshoot. So let's stop in
7387 the glyph matrix before glyphs for OBJECT. */
7388 fast_find_position (w, XFASTINT (before),
7389 &dpyinfo->mouse_face_beg_col,
7390 &dpyinfo->mouse_face_beg_row,
7391 &dpyinfo->mouse_face_beg_x,
7392 &dpyinfo->mouse_face_beg_y,
7393 object);
7394
7395 dpyinfo->mouse_face_past_end
7396 = !fast_find_position (w, XFASTINT (after),
7397 &dpyinfo->mouse_face_end_col,
7398 &dpyinfo->mouse_face_end_row,
7399 &dpyinfo->mouse_face_end_x,
7400 &dpyinfo->mouse_face_end_y,
7401 Qnil);
7402 dpyinfo->mouse_face_window = window;
7403 dpyinfo->mouse_face_face_id
7404 = face_at_buffer_position (w, pos, 0, 0,
7405 &ignore, pos + 1, 1);
7406
7407 /* Display it as active. */
7408 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7409 /* TODO: mouse cursor changes. */
7410 }
7411 }
7412 }
7413
7414 check_help_echo:
7415
7416 /* Look for a `help-echo' property. */
7417 {
7418 Lisp_Object help, overlay;
7419
7420 /* Check overlays first. */
7421 help = overlay = Qnil;
7422 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7423 {
7424 overlay = overlay_vec[i];
7425 help = Foverlay_get (overlay, Qhelp_echo);
7426 }
7427
7428 if (!NILP (help))
7429 {
7430 help_echo = help;
7431 help_echo_window = window;
7432 help_echo_object = overlay;
7433 help_echo_pos = pos;
7434 }
7435 else
7436 {
7437 Lisp_Object object = glyph->object;
7438 int charpos = glyph->charpos;
7439
7440 /* Try text properties. */
7441 if (STRINGP (object)
7442 && charpos >= 0
7443 && charpos < SCHARS (object))
7444 {
7445 help = Fget_text_property (make_number (charpos),
7446 Qhelp_echo, object);
7447 if (NILP (help))
7448 {
7449 /* If the string itself doesn't specify a help-echo,
7450 see if the buffer text ``under'' it does. */
7451 struct glyph_row *r
7452 = MATRIX_ROW (w->current_matrix, vpos);
7453 int start = MATRIX_ROW_START_CHARPOS (r);
7454 int pos = string_buffer_position (w, object, start);
7455 if (pos > 0)
7456 {
7457 help = Fget_char_property (make_number (pos),
7458 Qhelp_echo, w->buffer);
7459 if (!NILP (help))
7460 {
7461 charpos = pos;
7462 object = w->buffer;
7463 }
7464 }
7465 }
7466 }
7467 else if (BUFFERP (object)
7468 && charpos >= BEGV
7469 && charpos < ZV)
7470 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7471 object);
7472
7473 if (!NILP (help))
7474 {
7475 help_echo = help;
7476 help_echo_window = window;
7477 help_echo_object = object;
7478 help_echo_pos = charpos;
7479 }
7480 }
7481 }
7482
7483 BEGV = obegv;
7484 ZV = ozv;
7485 current_buffer = obuf;
7486 }
7487
7488 set_cursor:
7489 /* TODO: mouse cursor changes. */
7490 ;
7491 }
7492
7493 static void
7494 redo_mouse_highlight ()
7495 {
7496 if (!NILP (last_mouse_motion_frame)
7497 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7498 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7499 last_mouse_motion_position.h,
7500 last_mouse_motion_position.v);
7501 }
7502
7503
7504 \f
7505 /***********************************************************************
7506 Tool-bars
7507 ***********************************************************************/
7508
7509 static int x_tool_bar_item P_ ((struct frame *, int, int,
7510 struct glyph **, int *, int *, int *));
7511
7512 /* Tool-bar item index of the item on which a mouse button was pressed
7513 or -1. */
7514
7515 static int last_tool_bar_item;
7516
7517
7518 /* Get information about the tool-bar item at position X/Y on frame F.
7519 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7520 the current matrix of the tool-bar window of F, or NULL if not
7521 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7522 item in F->current_tool_bar_items. Value is
7523
7524 -1 if X/Y is not on a tool-bar item
7525 0 if X/Y is on the same item that was highlighted before.
7526 1 otherwise. */
7527
7528 static int
7529 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7530 struct frame *f;
7531 int x, y;
7532 struct glyph **glyph;
7533 int *hpos, *vpos, *prop_idx;
7534 {
7535 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7536 struct window *w = XWINDOW (f->tool_bar_window);
7537 int area;
7538
7539 /* Find the glyph under X/Y. */
7540 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7541 if (*glyph == NULL)
7542 return -1;
7543
7544 /* Get the start of this tool-bar item's properties in
7545 f->current_tool_bar_items. */
7546 if (!tool_bar_item_info (f, *glyph, prop_idx))
7547 return -1;
7548
7549 /* Is mouse on the highlighted item? */
7550 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7551 && *vpos >= dpyinfo->mouse_face_beg_row
7552 && *vpos <= dpyinfo->mouse_face_end_row
7553 && (*vpos > dpyinfo->mouse_face_beg_row
7554 || *hpos >= dpyinfo->mouse_face_beg_col)
7555 && (*vpos < dpyinfo->mouse_face_end_row
7556 || *hpos < dpyinfo->mouse_face_end_col
7557 || dpyinfo->mouse_face_past_end))
7558 return 0;
7559
7560 return 1;
7561 }
7562
7563
7564 /* Handle mouse button event on the tool-bar of frame F, at
7565 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7566 or ButtonRelase. */
7567
7568 static void
7569 x_handle_tool_bar_click (f, button_event)
7570 struct frame *f;
7571 EventRecord *button_event;
7572 {
7573 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7574 struct window *w = XWINDOW (f->tool_bar_window);
7575 int hpos, vpos, prop_idx;
7576 struct glyph *glyph;
7577 Lisp_Object enabled_p;
7578 int x = button_event->where.h;
7579 int y = button_event->where.v;
7580
7581 /* If not on the highlighted tool-bar item, return. */
7582 frame_to_window_pixel_xy (w, &x, &y);
7583 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7584 return;
7585
7586 /* If item is disabled, do nothing. */
7587 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7588 if (NILP (enabled_p))
7589 return;
7590
7591 if (button_event->what == mouseDown)
7592 {
7593 /* Show item in pressed state. */
7594 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7595 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7596 last_tool_bar_item = prop_idx;
7597 }
7598 else
7599 {
7600 Lisp_Object key, frame;
7601 struct input_event event;
7602
7603 /* Show item in released state. */
7604 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7605 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7606
7607 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7608
7609 XSETFRAME (frame, f);
7610 event.kind = TOOL_BAR_EVENT;
7611 event.frame_or_window = frame;
7612 event.arg = frame;
7613 kbd_buffer_store_event (&event);
7614
7615 event.kind = TOOL_BAR_EVENT;
7616 event.frame_or_window = frame;
7617 event.arg = key;
7618 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7619 button_event->modifiers);
7620 kbd_buffer_store_event (&event);
7621 last_tool_bar_item = -1;
7622 }
7623 }
7624
7625
7626 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7627 tool-bar window-relative coordinates X/Y. Called from
7628 note_mouse_highlight. */
7629
7630 static void
7631 note_tool_bar_highlight (f, x, y)
7632 struct frame *f;
7633 int x, y;
7634 {
7635 Lisp_Object window = f->tool_bar_window;
7636 struct window *w = XWINDOW (window);
7637 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7638 int hpos, vpos;
7639 struct glyph *glyph;
7640 struct glyph_row *row;
7641 int i;
7642 Lisp_Object enabled_p;
7643 int prop_idx;
7644 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7645 int mouse_down_p, rc;
7646
7647 /* Function note_mouse_highlight is called with negative x(y
7648 values when mouse moves outside of the frame. */
7649 if (x <= 0 || y <= 0)
7650 {
7651 clear_mouse_face (dpyinfo);
7652 return;
7653 }
7654
7655 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7656 if (rc < 0)
7657 {
7658 /* Not on tool-bar item. */
7659 clear_mouse_face (dpyinfo);
7660 return;
7661 }
7662 else if (rc == 0)
7663 /* On same tool-bar item as before. */
7664 goto set_help_echo;
7665
7666 clear_mouse_face (dpyinfo);
7667
7668 /* Mouse is down, but on different tool-bar item? */
7669 mouse_down_p = (dpyinfo->grabbed
7670 && f == last_mouse_frame
7671 && FRAME_LIVE_P (f));
7672 if (mouse_down_p
7673 && last_tool_bar_item != prop_idx)
7674 return;
7675
7676 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7677 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7678
7679 /* If tool-bar item is not enabled, don't highlight it. */
7680 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7681 if (!NILP (enabled_p))
7682 {
7683 /* Compute the x-position of the glyph. In front and past the
7684 image is a space. We include this is the highlighted area. */
7685 row = MATRIX_ROW (w->current_matrix, vpos);
7686 for (i = x = 0; i < hpos; ++i)
7687 x += row->glyphs[TEXT_AREA][i].pixel_width;
7688
7689 /* Record this as the current active region. */
7690 dpyinfo->mouse_face_beg_col = hpos;
7691 dpyinfo->mouse_face_beg_row = vpos;
7692 dpyinfo->mouse_face_beg_x = x;
7693 dpyinfo->mouse_face_beg_y = row->y;
7694 dpyinfo->mouse_face_past_end = 0;
7695
7696 dpyinfo->mouse_face_end_col = hpos + 1;
7697 dpyinfo->mouse_face_end_row = vpos;
7698 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7699 dpyinfo->mouse_face_end_y = row->y;
7700 dpyinfo->mouse_face_window = window;
7701 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7702
7703 /* Display it as active. */
7704 show_mouse_face (dpyinfo, draw);
7705 dpyinfo->mouse_face_image_state = draw;
7706 }
7707
7708 set_help_echo:
7709
7710 /* Set help_echo to a help string.to display for this tool-bar item.
7711 XTread_socket does the rest. */
7712 help_echo_object = help_echo_window = Qnil;
7713 help_echo_pos = -1;
7714 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7715 if (NILP (help_echo))
7716 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7717 }
7718
7719
7720 \f
7721 /* Find the glyph matrix position of buffer position CHARPOS in window
7722 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7723 current glyphs must be up to date. If CHARPOS is above window
7724 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7725 of last line in W. In the row containing CHARPOS, stop before glyphs
7726 having STOP as object. */
7727
7728 #if 0 /* This is a version of fast_find_position that's more correct
7729 in the presence of hscrolling, for example. I didn't install
7730 it right away because the problem fixed is minor, it failed
7731 in 20.x as well, and I think it's too risky to install
7732 so near the release of 21.1. 2001-09-25 gerd. */
7733
7734 static int
7735 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7736 struct window *w;
7737 int charpos;
7738 int *hpos, *vpos, *x, *y;
7739 Lisp_Object stop;
7740 {
7741 struct glyph_row *row, *first;
7742 struct glyph *glyph, *end;
7743 int i, past_end = 0;
7744
7745 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7746 row = row_containing_pos (w, charpos, first, NULL, 0);
7747 if (row == NULL)
7748 {
7749 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7750 {
7751 *x = *y = *hpos = *vpos = 0;
7752 return 0;
7753 }
7754 else
7755 {
7756 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7757 past_end = 1;
7758 }
7759 }
7760
7761 *x = row->x;
7762 *y = row->y;
7763 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7764
7765 glyph = row->glyphs[TEXT_AREA];
7766 end = glyph + row->used[TEXT_AREA];
7767
7768 /* Skip over glyphs not having an object at the start of the row.
7769 These are special glyphs like truncation marks on terminal
7770 frames. */
7771 if (row->displays_text_p)
7772 while (glyph < end
7773 && INTEGERP (glyph->object)
7774 && !EQ (stop, glyph->object)
7775 && glyph->charpos < 0)
7776 {
7777 *x += glyph->pixel_width;
7778 ++glyph;
7779 }
7780
7781 while (glyph < end
7782 && !INTEGERP (glyph->object)
7783 && !EQ (stop, glyph->object)
7784 && (!BUFFERP (glyph->object)
7785 || glyph->charpos < charpos))
7786 {
7787 *x += glyph->pixel_width;
7788 ++glyph;
7789 }
7790
7791 *hpos = glyph - row->glyphs[TEXT_AREA];
7792 return past_end;
7793 }
7794
7795 #else /* not 0 */
7796
7797 static int
7798 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7799 struct window *w;
7800 int pos;
7801 int *hpos, *vpos, *x, *y;
7802 Lisp_Object stop;
7803 {
7804 int i;
7805 int lastcol;
7806 int maybe_next_line_p = 0;
7807 int line_start_position;
7808 int yb = window_text_bottom_y (w);
7809 struct glyph_row *row, *best_row;
7810 int row_vpos, best_row_vpos;
7811 int current_x;
7812
7813 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7814 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7815
7816 while (row->y < yb)
7817 {
7818 if (row->used[TEXT_AREA])
7819 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7820 else
7821 line_start_position = 0;
7822
7823 if (line_start_position > pos)
7824 break;
7825 /* If the position sought is the end of the buffer,
7826 don't include the blank lines at the bottom of the window. */
7827 else if (line_start_position == pos
7828 && pos == BUF_ZV (XBUFFER (w->buffer)))
7829 {
7830 maybe_next_line_p = 1;
7831 break;
7832 }
7833 else if (line_start_position > 0)
7834 {
7835 best_row = row;
7836 best_row_vpos = row_vpos;
7837 }
7838
7839 if (row->y + row->height >= yb)
7840 break;
7841
7842 ++row;
7843 ++row_vpos;
7844 }
7845
7846 /* Find the right column within BEST_ROW. */
7847 lastcol = 0;
7848 current_x = best_row->x;
7849 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7850 {
7851 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7852 int charpos = glyph->charpos;
7853
7854 if (BUFFERP (glyph->object))
7855 {
7856 if (charpos == pos)
7857 {
7858 *hpos = i;
7859 *vpos = best_row_vpos;
7860 *x = current_x;
7861 *y = best_row->y;
7862 return 1;
7863 }
7864 else if (charpos > pos)
7865 break;
7866 }
7867 else if (EQ (glyph->object, stop))
7868 break;
7869
7870 if (charpos > 0)
7871 lastcol = i;
7872 current_x += glyph->pixel_width;
7873 }
7874
7875 /* If we're looking for the end of the buffer,
7876 and we didn't find it in the line we scanned,
7877 use the start of the following line. */
7878 if (maybe_next_line_p)
7879 {
7880 ++best_row;
7881 ++best_row_vpos;
7882 lastcol = 0;
7883 current_x = best_row->x;
7884 }
7885
7886 *vpos = best_row_vpos;
7887 *hpos = lastcol + 1;
7888 *x = current_x;
7889 *y = best_row->y;
7890 return 0;
7891 }
7892
7893 #endif /* not 0 */
7894
7895
7896 /* Find the position of the glyph for position POS in OBJECT in
7897 window W's current matrix, and return in *X/*Y the pixel
7898 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7899
7900 RIGHT_P non-zero means return the position of the right edge of the
7901 glyph, RIGHT_P zero means return the left edge position.
7902
7903 If no glyph for POS exists in the matrix, return the position of
7904 the glyph with the next smaller position that is in the matrix, if
7905 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7906 exists in the matrix, return the position of the glyph with the
7907 next larger position in OBJECT.
7908
7909 Value is non-zero if a glyph was found. */
7910
7911 static int
7912 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7913 struct window *w;
7914 int pos;
7915 Lisp_Object object;
7916 int *hpos, *vpos, *x, *y;
7917 int right_p;
7918 {
7919 int yb = window_text_bottom_y (w);
7920 struct glyph_row *r;
7921 struct glyph *best_glyph = NULL;
7922 struct glyph_row *best_row = NULL;
7923 int best_x = 0;
7924
7925 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7926 r->enabled_p && r->y < yb;
7927 ++r)
7928 {
7929 struct glyph *g = r->glyphs[TEXT_AREA];
7930 struct glyph *e = g + r->used[TEXT_AREA];
7931 int gx;
7932
7933 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7934 if (EQ (g->object, object))
7935 {
7936 if (g->charpos == pos)
7937 {
7938 best_glyph = g;
7939 best_x = gx;
7940 best_row = r;
7941 goto found;
7942 }
7943 else if (best_glyph == NULL
7944 || ((abs (g->charpos - pos)
7945 < abs (best_glyph->charpos - pos))
7946 && (right_p
7947 ? g->charpos < pos
7948 : g->charpos > pos)))
7949 {
7950 best_glyph = g;
7951 best_x = gx;
7952 best_row = r;
7953 }
7954 }
7955 }
7956
7957 found:
7958
7959 if (best_glyph)
7960 {
7961 *x = best_x;
7962 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7963
7964 if (right_p)
7965 {
7966 *x += best_glyph->pixel_width;
7967 ++*hpos;
7968 }
7969
7970 *y = best_row->y;
7971 *vpos = best_row - w->current_matrix->rows;
7972 }
7973
7974 return best_glyph != NULL;
7975 }
7976
7977
7978 /* Display the active region described by mouse_face_*
7979 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7980
7981 static void
7982 show_mouse_face (dpyinfo, draw)
7983 struct mac_display_info *dpyinfo;
7984 enum draw_glyphs_face draw;
7985 {
7986 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7987 struct frame *f = XFRAME (WINDOW_FRAME (w));
7988
7989 if (/* If window is in the process of being destroyed, don't bother
7990 to do anything. */
7991 w->current_matrix != NULL
7992 /* Don't update mouse highlight if hidden */
7993 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7994 /* Recognize when we are called to operate on rows that don't exist
7995 anymore. This can happen when a window is split. */
7996 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7997 {
7998 int phys_cursor_on_p = w->phys_cursor_on_p;
7999 struct glyph_row *row, *first, *last;
8000
8001 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
8002 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
8003
8004 for (row = first; row <= last && row->enabled_p; ++row)
8005 {
8006 int start_hpos, end_hpos, start_x;
8007
8008 /* For all but the first row, the highlight starts at column 0. */
8009 if (row == first)
8010 {
8011 start_hpos = dpyinfo->mouse_face_beg_col;
8012 start_x = dpyinfo->mouse_face_beg_x;
8013 }
8014 else
8015 {
8016 start_hpos = 0;
8017 start_x = 0;
8018 }
8019
8020 if (row == last)
8021 end_hpos = dpyinfo->mouse_face_end_col;
8022 else
8023 end_hpos = row->used[TEXT_AREA];
8024
8025 if (end_hpos > start_hpos)
8026 {
8027 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8028 start_hpos, end_hpos, draw, 0);
8029
8030 row->mouse_face_p
8031 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8032 }
8033 }
8034
8035 /* When we've written over the cursor, arrange for it to
8036 be displayed again. */
8037 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8038 x_display_cursor (w, 1,
8039 w->phys_cursor.hpos, w->phys_cursor.vpos,
8040 w->phys_cursor.x, w->phys_cursor.y);
8041 }
8042
8043 #if 0 /* MAC_TODO: mouse cursor */
8044 /* Change the mouse cursor. */
8045 if (draw == DRAW_NORMAL_TEXT)
8046 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8047 f->output_data.x->text_cursor);
8048 else if (draw == DRAW_MOUSE_FACE)
8049 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8050 f->output_data.x->cross_cursor);
8051 else
8052 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8053 f->output_data.x->nontext_cursor);
8054 #endif
8055 }
8056
8057 /* Clear out the mouse-highlighted active region.
8058 Redraw it un-highlighted first. */
8059
8060 static int
8061 clear_mouse_face (dpyinfo)
8062 struct mac_display_info *dpyinfo;
8063 {
8064 int cleared = 0;
8065
8066 if (! NILP (dpyinfo->mouse_face_window))
8067 {
8068 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8069 cleared = 1;
8070 }
8071
8072 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8073 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8074 dpyinfo->mouse_face_window = Qnil;
8075 dpyinfo->mouse_face_overlay = Qnil;
8076 return cleared;
8077 }
8078
8079
8080 /* Clear any mouse-face on window W. This function is part of the
8081 redisplay interface, and is called from try_window_id and similar
8082 functions to ensure the mouse-highlight is off. */
8083
8084 static void
8085 x_clear_mouse_face (w)
8086 struct window *w;
8087 {
8088 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8089 Lisp_Object window;
8090
8091 BLOCK_INPUT;
8092 XSETWINDOW (window, w);
8093 if (EQ (window, dpyinfo->mouse_face_window))
8094 clear_mouse_face (dpyinfo);
8095 UNBLOCK_INPUT;
8096 }
8097
8098
8099 /* Just discard the mouse face information for frame F, if any.
8100 This is used when the size of F is changed. */
8101
8102 void
8103 cancel_mouse_face (f)
8104 FRAME_PTR f;
8105 {
8106 Lisp_Object window;
8107 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8108
8109 window = dpyinfo->mouse_face_window;
8110 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8111 {
8112 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8113 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8114 dpyinfo->mouse_face_window = Qnil;
8115 }
8116 }
8117 \f
8118 static struct scroll_bar *x_window_to_scroll_bar ();
8119 static void x_scroll_bar_report_motion ();
8120 static void x_check_fullscreen P_ ((struct frame *));
8121 static void x_check_fullscreen_move P_ ((struct frame *));
8122 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8123
8124
8125 /* Try to determine frame pixel position and size of the glyph under
8126 frame pixel coordinates X/Y on frame F . Return the position and
8127 size in *RECT. Value is non-zero if we could compute these
8128 values. */
8129
8130 static int
8131 glyph_rect (f, x, y, rect)
8132 struct frame *f;
8133 int x, y;
8134 Rect *rect;
8135 {
8136 Lisp_Object window;
8137 int part;
8138
8139 window = window_from_coordinates (f, x, y, &part, 0);
8140 if (!NILP (window))
8141 {
8142 struct window *w = XWINDOW (window);
8143 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8144 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8145
8146 frame_to_window_pixel_xy (w, &x, &y);
8147
8148 for (; r < end && r->enabled_p; ++r)
8149 if (r->y <= y && r->y + r->height > y)
8150 {
8151 /* Found the row at y. */
8152 struct glyph *g = r->glyphs[TEXT_AREA];
8153 struct glyph *end = g + r->used[TEXT_AREA];
8154 int gx;
8155
8156 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8157 rect->bottom = rect->top + r->height;
8158
8159 if (x < r->x)
8160 {
8161 /* x is to the left of the first glyph in the row. */
8162 rect->left = XINT (w->left);
8163 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8164 return 1;
8165 }
8166
8167 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8168 if (gx <= x && gx + g->pixel_width > x)
8169 {
8170 /* x is on a glyph. */
8171 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8172 rect->right = rect->left + g->pixel_width;
8173 return 1;
8174 }
8175
8176 /* x is to the right of the last glyph in the row. */
8177 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8178 rect->right = XINT (w->left) + XINT (w->width);
8179 return 1;
8180 }
8181 }
8182
8183 /* The y is not on any row. */
8184 return 0;
8185 }
8186
8187 /* Record the position of the mouse in last_mouse_glyph. */
8188 static void
8189 remember_mouse_glyph (f1, gx, gy)
8190 struct frame * f1;
8191 int gx, gy;
8192 {
8193 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8194 {
8195 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8196 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8197
8198 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8199 round down even for negative values. */
8200 if (gx < 0)
8201 gx -= width - 1;
8202 if (gy < 0)
8203 gy -= height - 1;
8204 #if 0
8205 /* This was the original code from XTmouse_position, but it seems
8206 to give the position of the glyph diagonally next to the one
8207 the mouse is over. */
8208 gx = (gx + width - 1) / width * width;
8209 gy = (gy + height - 1) / height * height;
8210 #else
8211 gx = gx / width * width;
8212 gy = gy / height * height;
8213 #endif
8214
8215 last_mouse_glyph.left = gx;
8216 last_mouse_glyph.top = gy;
8217 last_mouse_glyph.right = gx + width;
8218 last_mouse_glyph.bottom = gy + height;
8219 }
8220 }
8221
8222 /* Return the current position of the mouse.
8223 *fp should be a frame which indicates which display to ask about.
8224
8225 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8226 and *part to the frame, window, and scroll bar part that the mouse
8227 is over. Set *x and *y to the portion and whole of the mouse's
8228 position on the scroll bar.
8229
8230 If the mouse movement started elsewhere, set *fp to the frame the
8231 mouse is on, *bar_window to nil, and *x and *y to the character cell
8232 the mouse is over.
8233
8234 Set *time to the server time-stamp for the time at which the mouse
8235 was at this position.
8236
8237 Don't store anything if we don't have a valid set of values to report.
8238
8239 This clears the mouse_moved flag, so we can wait for the next mouse
8240 movement. */
8241
8242 static void
8243 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8244 FRAME_PTR *fp;
8245 int insist;
8246 Lisp_Object *bar_window;
8247 enum scroll_bar_part *part;
8248 Lisp_Object *x, *y;
8249 unsigned long *time;
8250 {
8251 Point mouse_pos;
8252 int ignore1, ignore2;
8253 WindowPtr wp = FrontWindow ();
8254 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8255 Lisp_Object frame, tail;
8256
8257 BLOCK_INPUT;
8258
8259 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8260 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8261 else
8262 {
8263 /* Clear the mouse-moved flag for every frame on this display. */
8264 FOR_EACH_FRAME (tail, frame)
8265 XFRAME (frame)->mouse_moved = 0;
8266
8267 last_mouse_scroll_bar = Qnil;
8268
8269 #if TARGET_API_MAC_CARBON
8270 SetPort (GetWindowPort (wp));
8271 #else
8272 SetPort (wp);
8273 #endif
8274
8275 GetMouse (&mouse_pos);
8276
8277 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8278 &last_mouse_glyph, insist);
8279
8280 *bar_window = Qnil;
8281 *part = scroll_bar_handle;
8282 *fp = f;
8283 XSETINT (*x, mouse_pos.h);
8284 XSETINT (*y, mouse_pos.v);
8285 *time = last_mouse_movement_time;
8286 }
8287
8288 UNBLOCK_INPUT;
8289 }
8290
8291 \f
8292 /************************************************************************
8293 Scroll bars, general
8294 ************************************************************************/
8295
8296 /* Create a scroll bar and return the scroll bar vector for it. W is
8297 the Emacs window on which to create the scroll bar. TOP, LEFT,
8298 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8299 scroll bar. */
8300
8301 static struct scroll_bar *
8302 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8303 struct window *w;
8304 int top, left, width, height, disp_top, disp_height;
8305 {
8306 struct frame *f = XFRAME (w->frame);
8307 struct scroll_bar *bar
8308 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8309 Rect r;
8310 ControlHandle ch;
8311
8312 BLOCK_INPUT;
8313
8314 r.left = left;
8315 r.top = disp_top;
8316 r.right = left + width;
8317 r.bottom = disp_top + disp_height;
8318
8319 #ifdef TARGET_API_MAC_CARBON
8320 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8321 kControlScrollBarProc, 0L);
8322 #else
8323 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8324 0L);
8325 #endif
8326 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8327 SetControlReference (ch, (long) bar);
8328
8329 XSETWINDOW (bar->window, w);
8330 XSETINT (bar->top, top);
8331 XSETINT (bar->left, left);
8332 XSETINT (bar->width, width);
8333 XSETINT (bar->height, height);
8334 XSETINT (bar->start, 0);
8335 XSETINT (bar->end, 0);
8336 bar->dragging = Qnil;
8337
8338 /* Add bar to its frame's list of scroll bars. */
8339 bar->next = FRAME_SCROLL_BARS (f);
8340 bar->prev = Qnil;
8341 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8342 if (!NILP (bar->next))
8343 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8344
8345 UNBLOCK_INPUT;
8346 return bar;
8347 }
8348
8349
8350 /* Draw BAR's handle in the proper position.
8351
8352 If the handle is already drawn from START to END, don't bother
8353 redrawing it, unless REBUILD is non-zero; in that case, always
8354 redraw it. (REBUILD is handy for drawing the handle after expose
8355 events.)
8356
8357 Normally, we want to constrain the start and end of the handle to
8358 fit inside its rectangle, but if the user is dragging the scroll
8359 bar handle, we want to let them drag it down all the way, so that
8360 the bar's top is as far down as it goes; otherwise, there's no way
8361 to move to the very end of the buffer. */
8362
8363 static void
8364 x_scroll_bar_set_handle (bar, start, end, rebuild)
8365 struct scroll_bar *bar;
8366 int start, end;
8367 int rebuild;
8368 {
8369 int dragging = ! NILP (bar->dragging);
8370 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8371 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8372 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8373 int length = end - start;
8374
8375 /* If the display is already accurate, do nothing. */
8376 if (! rebuild
8377 && start == XINT (bar->start)
8378 && end == XINT (bar->end))
8379 return;
8380
8381 BLOCK_INPUT;
8382
8383 /* Make sure the values are reasonable, and try to preserve the
8384 distance between start and end. */
8385 if (start < 0)
8386 start = 0;
8387 else if (start > top_range)
8388 start = top_range;
8389 end = start + length;
8390
8391 if (end < start)
8392 end = start;
8393 else if (end > top_range && ! dragging)
8394 end = top_range;
8395
8396 /* Store the adjusted setting in the scroll bar. */
8397 XSETINT (bar->start, start);
8398 XSETINT (bar->end, end);
8399
8400 /* Clip the end position, just for display. */
8401 if (end > top_range)
8402 end = top_range;
8403
8404 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8405 top positions, to make sure the handle is always at least that
8406 many pixels tall. */
8407 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8408
8409 SetControlMinimum (ch, 0);
8410 /* Don't inadvertently activate deactivated scroll bars */
8411 if (GetControlMaximum (ch) != -1)
8412 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8413 - (end - start));
8414 SetControlValue (ch, start);
8415 #if TARGET_API_MAC_CARBON
8416 SetControlViewSize (ch, end - start);
8417 #endif
8418
8419 UNBLOCK_INPUT;
8420 }
8421
8422
8423 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8424 nil. */
8425
8426 static void
8427 x_scroll_bar_remove (bar)
8428 struct scroll_bar *bar;
8429 {
8430 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8431
8432 BLOCK_INPUT;
8433
8434 /* Destroy the Mac scroll bar control */
8435 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8436
8437 /* Disassociate this scroll bar from its window. */
8438 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8439
8440 UNBLOCK_INPUT;
8441 }
8442
8443 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8444 that we are displaying PORTION characters out of a total of WHOLE
8445 characters, starting at POSITION. If WINDOW has no scroll bar,
8446 create one. */
8447 static void
8448 XTset_vertical_scroll_bar (w, portion, whole, position)
8449 struct window *w;
8450 int portion, whole, position;
8451 {
8452 struct frame *f = XFRAME (w->frame);
8453 struct scroll_bar *bar;
8454 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8455 int window_x, window_y, window_width, window_height;
8456
8457 /* Get window dimensions. */
8458 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8459 top = window_y;
8460 #ifdef MAC_OSX
8461 width = 16;
8462 #else
8463 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8464 #endif
8465 height = window_height;
8466
8467 /* Compute the left edge of the scroll bar area. */
8468 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8469 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8470 else
8471 left = XFASTINT (w->left);
8472 left *= CANON_X_UNIT (f);
8473 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8474
8475 /* Compute the width of the scroll bar which might be less than
8476 the width of the area reserved for the scroll bar. */
8477 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8478 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8479 else
8480 sb_width = width;
8481
8482 /* Compute the left edge of the scroll bar. */
8483 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8484 sb_left = left + width - sb_width - (width - sb_width) / 2;
8485 else
8486 sb_left = left + (width - sb_width) / 2;
8487
8488 /* Adjustments according to Inside Macintosh to make it look nice */
8489 disp_top = top;
8490 disp_height = height;
8491 if (disp_top == 0)
8492 {
8493 disp_top = -1;
8494 disp_height++;
8495 }
8496 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8497 {
8498 disp_top++;
8499 disp_height--;
8500 }
8501
8502 if (sb_left + sb_width == PIXEL_WIDTH (f))
8503 sb_left++;
8504
8505 /* Does the scroll bar exist yet? */
8506 if (NILP (w->vertical_scroll_bar))
8507 {
8508 BLOCK_INPUT;
8509 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8510 left, top, width, height, 0);
8511 UNBLOCK_INPUT;
8512 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8513 disp_height);
8514 XSETVECTOR (w->vertical_scroll_bar, bar);
8515 }
8516 else
8517 {
8518 /* It may just need to be moved and resized. */
8519 ControlHandle ch;
8520
8521 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8522 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8523
8524 BLOCK_INPUT;
8525
8526 /* If already correctly positioned, do nothing. */
8527 if (XINT (bar->left) == sb_left
8528 && XINT (bar->top) == top
8529 && XINT (bar->width) == sb_width
8530 && XINT (bar->height) == height)
8531 Draw1Control (ch);
8532 else
8533 {
8534 /* Clear areas not covered by the scroll bar because it's not as
8535 wide as the area reserved for it . This makes sure a
8536 previous mode line display is cleared after C-x 2 C-x 1, for
8537 example. */
8538 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8539 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8540 left, top, area_width, height, 0);
8541
8542 #if 0
8543 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8544 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8545 sb_left - 1, top, 1, height, 0);
8546 #endif
8547
8548 HideControl (ch);
8549 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8550 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8551 disp_height);
8552 ShowControl (ch);
8553
8554 /* Remember new settings. */
8555 XSETINT (bar->left, sb_left);
8556 XSETINT (bar->top, top);
8557 XSETINT (bar->width, sb_width);
8558 XSETINT (bar->height, height);
8559 }
8560
8561 UNBLOCK_INPUT;
8562 }
8563
8564 /* Set the scroll bar's current state, unless we're currently being
8565 dragged. */
8566 if (NILP (bar->dragging))
8567 {
8568 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8569
8570 if (whole == 0)
8571 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8572 else
8573 {
8574 int start = ((double) position * top_range) / whole;
8575 int end = ((double) (position + portion) * top_range) / whole;
8576 x_scroll_bar_set_handle (bar, start, end, 0);
8577 }
8578 }
8579 }
8580
8581
8582 /* The following three hooks are used when we're doing a thorough
8583 redisplay of the frame. We don't explicitly know which scroll bars
8584 are going to be deleted, because keeping track of when windows go
8585 away is a real pain - "Can you say set-window-configuration, boys
8586 and girls?" Instead, we just assert at the beginning of redisplay
8587 that *all* scroll bars are to be removed, and then save a scroll bar
8588 from the fiery pit when we actually redisplay its window. */
8589
8590 /* Arrange for all scroll bars on FRAME to be removed at the next call
8591 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8592 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8593
8594 static void
8595 XTcondemn_scroll_bars (frame)
8596 FRAME_PTR frame;
8597 {
8598 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8599 while (! NILP (FRAME_SCROLL_BARS (frame)))
8600 {
8601 Lisp_Object bar;
8602 bar = FRAME_SCROLL_BARS (frame);
8603 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8604 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8605 XSCROLL_BAR (bar)->prev = Qnil;
8606 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8607 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8608 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8609 }
8610 }
8611
8612
8613 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8614 Note that WINDOW isn't necessarily condemned at all. */
8615
8616 static void
8617 XTredeem_scroll_bar (window)
8618 struct window *window;
8619 {
8620 struct scroll_bar *bar;
8621
8622 /* We can't redeem this window's scroll bar if it doesn't have one. */
8623 if (NILP (window->vertical_scroll_bar))
8624 abort ();
8625
8626 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8627
8628 /* Unlink it from the condemned list. */
8629 {
8630 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8631
8632 if (NILP (bar->prev))
8633 {
8634 /* If the prev pointer is nil, it must be the first in one of
8635 the lists. */
8636 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8637 /* It's not condemned. Everything's fine. */
8638 return;
8639 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8640 window->vertical_scroll_bar))
8641 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8642 else
8643 /* If its prev pointer is nil, it must be at the front of
8644 one or the other! */
8645 abort ();
8646 }
8647 else
8648 XSCROLL_BAR (bar->prev)->next = bar->next;
8649
8650 if (! NILP (bar->next))
8651 XSCROLL_BAR (bar->next)->prev = bar->prev;
8652
8653 bar->next = FRAME_SCROLL_BARS (f);
8654 bar->prev = Qnil;
8655 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8656 if (! NILP (bar->next))
8657 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8658 }
8659 }
8660
8661 /* Remove all scroll bars on FRAME that haven't been saved since the
8662 last call to `*condemn_scroll_bars_hook'. */
8663
8664 static void
8665 XTjudge_scroll_bars (f)
8666 FRAME_PTR f;
8667 {
8668 Lisp_Object bar, next;
8669
8670 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8671
8672 /* Clear out the condemned list now so we won't try to process any
8673 more events on the hapless scroll bars. */
8674 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8675
8676 for (; ! NILP (bar); bar = next)
8677 {
8678 struct scroll_bar *b = XSCROLL_BAR (bar);
8679
8680 x_scroll_bar_remove (b);
8681
8682 next = b->next;
8683 b->next = b->prev = Qnil;
8684 }
8685
8686 /* Now there should be no references to the condemned scroll bars,
8687 and they should get garbage-collected. */
8688 }
8689
8690
8691 static void
8692 activate_scroll_bars (frame)
8693 FRAME_PTR frame;
8694 {
8695 Lisp_Object bar;
8696 ControlHandle ch;
8697
8698 bar = FRAME_SCROLL_BARS (frame);
8699 while (! NILP (bar))
8700 {
8701 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8702 #ifdef TARGET_API_MAC_CARBON
8703 ActivateControl (ch);
8704 #else
8705 SetControlMaximum (ch,
8706 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8707 XINT (XSCROLL_BAR (bar)
8708 ->height)) - 1);
8709 #endif
8710 bar = XSCROLL_BAR (bar)->next;
8711 }
8712 }
8713
8714
8715 static void
8716 deactivate_scroll_bars (frame)
8717 FRAME_PTR frame;
8718 {
8719 Lisp_Object bar;
8720 ControlHandle ch;
8721
8722 bar = FRAME_SCROLL_BARS (frame);
8723 while (! NILP (bar))
8724 {
8725 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8726 #ifdef TARGET_API_MAC_CARBON
8727 DeactivateControl (ch);
8728 #else
8729 SetControlMaximum (ch, XINT (-1));
8730 #endif
8731 bar = XSCROLL_BAR (bar)->next;
8732 }
8733 }
8734
8735 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8736 is set to something other than NO_EVENT, it is enqueued.
8737
8738 This may be called from a signal handler, so we have to ignore GC
8739 mark bits. */
8740
8741 static void
8742 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8743 struct scroll_bar *bar;
8744 int part_code;
8745 EventRecord *er;
8746 struct input_event *bufp;
8747 {
8748 if (! GC_WINDOWP (bar->window))
8749 abort ();
8750
8751 bufp->kind = SCROLL_BAR_CLICK_EVENT;
8752 bufp->frame_or_window = bar->window;
8753 bufp->arg = Qnil;
8754
8755 bar->dragging = Qnil;
8756
8757 switch (part_code)
8758 {
8759 case kControlUpButtonPart:
8760 bufp->part = scroll_bar_up_arrow;
8761 break;
8762 case kControlDownButtonPart:
8763 bufp->part = scroll_bar_down_arrow;
8764 break;
8765 case kControlPageUpPart:
8766 bufp->part = scroll_bar_above_handle;
8767 break;
8768 case kControlPageDownPart:
8769 bufp->part = scroll_bar_below_handle;
8770 break;
8771 #ifdef TARGET_API_MAC_CARBON
8772 default:
8773 #else
8774 case kControlIndicatorPart:
8775 #endif
8776 if (er->what == mouseDown)
8777 bar->dragging = make_number (0);
8778 XSETVECTOR (last_mouse_scroll_bar, bar);
8779 bufp->part = scroll_bar_handle;
8780 break;
8781 }
8782 }
8783
8784
8785 /* Handle some mouse motion while someone is dragging the scroll bar.
8786
8787 This may be called from a signal handler, so we have to ignore GC
8788 mark bits. */
8789
8790 static void
8791 x_scroll_bar_note_movement (bar, y_pos, t)
8792 struct scroll_bar *bar;
8793 int y_pos;
8794 Time t;
8795 {
8796 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8797
8798 last_mouse_movement_time = t;
8799
8800 f->mouse_moved = 1;
8801 XSETVECTOR (last_mouse_scroll_bar, bar);
8802
8803 /* If we're dragging the bar, display it. */
8804 if (! GC_NILP (bar->dragging))
8805 {
8806 /* Where should the handle be now? */
8807 int new_start = y_pos - 24;
8808
8809 if (new_start != XINT (bar->start))
8810 {
8811 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8812
8813 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8814 }
8815 }
8816 }
8817
8818
8819 /* Return information to the user about the current position of the
8820 mouse on the scroll bar. */
8821
8822 static void
8823 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8824 FRAME_PTR *fp;
8825 Lisp_Object *bar_window;
8826 enum scroll_bar_part *part;
8827 Lisp_Object *x, *y;
8828 unsigned long *time;
8829 {
8830 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8831 WindowPtr wp = FrontWindow ();
8832 Point mouse_pos;
8833 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8834 int win_y, top_range;
8835
8836 #if TARGET_API_MAC_CARBON
8837 SetPort (GetWindowPort (wp));
8838 #else
8839 SetPort (wp);
8840 #endif
8841
8842 GetMouse (&mouse_pos);
8843
8844 win_y = mouse_pos.v - XINT (bar->top);
8845 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8846
8847 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8848
8849 win_y -= 24;
8850
8851 if (! NILP (bar->dragging))
8852 win_y -= XINT (bar->dragging);
8853
8854 if (win_y < 0)
8855 win_y = 0;
8856 if (win_y > top_range)
8857 win_y = top_range;
8858
8859 *fp = f;
8860 *bar_window = bar->window;
8861
8862 if (! NILP (bar->dragging))
8863 *part = scroll_bar_handle;
8864 else if (win_y < XINT (bar->start))
8865 *part = scroll_bar_above_handle;
8866 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8867 *part = scroll_bar_handle;
8868 else
8869 *part = scroll_bar_below_handle;
8870
8871 XSETINT (*x, win_y);
8872 XSETINT (*y, top_range);
8873
8874 f->mouse_moved = 0;
8875 last_mouse_scroll_bar = Qnil;
8876
8877 *time = last_mouse_movement_time;
8878 }
8879 \f
8880 /***********************************************************************
8881 Text Cursor
8882 ***********************************************************************/
8883
8884 /* Notice if the text cursor of window W has been overwritten by a
8885 drawing operation that outputs glyphs starting at START_X and
8886 ending at END_X in the line given by output_cursor.vpos.
8887 Coordinates are area-relative. END_X < 0 means all the rest
8888 of the line after START_X has been written. */
8889
8890 static void
8891 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
8892 struct window *w;
8893 enum glyph_row_area area;
8894 int x0, x1, y0, y1;
8895 {
8896 if (area == TEXT_AREA
8897 && w->phys_cursor_on_p
8898 && y0 <= w->phys_cursor.y
8899 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8900 && x0 <= w->phys_cursor.x
8901 && (x1 < 0 || x1 > w->phys_cursor.x))
8902 w->phys_cursor_on_p = 0;
8903 }
8904
8905
8906 /* Set clipping for output in glyph row ROW. W is the window in which
8907 we operate. GC is the graphics context to set clipping in.
8908 WHOLE_LINE_P non-zero means include the areas used for truncation
8909 mark display and alike in the clipping rectangle.
8910
8911 ROW may be a text row or, e.g., a mode line. Text rows must be
8912 clipped to the interior of the window dedicated to text display,
8913 mode lines must be clipped to the whole window. */
8914
8915 static void
8916 x_clip_to_row (w, row, gc, whole_line_p)
8917 struct window *w;
8918 struct glyph_row *row;
8919 GC gc;
8920 int whole_line_p;
8921 {
8922 struct frame *f = XFRAME (WINDOW_FRAME (w));
8923 Rect clip_rect;
8924 int window_x, window_y, window_width, window_height;
8925
8926 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8927
8928 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8929 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8930 clip_rect.top = max (clip_rect.top, window_y);
8931 clip_rect.right = clip_rect.left + window_width;
8932 clip_rect.bottom = clip_rect.top + row->visible_height;
8933
8934 /* If clipping to the whole line, including trunc marks, extend
8935 the rectangle to the left and increase its width. */
8936 if (whole_line_p)
8937 {
8938 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8939 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
8940 }
8941
8942 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8943 }
8944
8945
8946 /* Draw a hollow box cursor on window W in glyph row ROW. */
8947
8948 static void
8949 x_draw_hollow_cursor (w, row)
8950 struct window *w;
8951 struct glyph_row *row;
8952 {
8953 struct frame *f = XFRAME (WINDOW_FRAME (w));
8954 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8955 Display *dpy = FRAME_MAC_DISPLAY (f);
8956 int x, y, wd, h;
8957 XGCValues xgcv;
8958 struct glyph *cursor_glyph;
8959 GC gc;
8960
8961 /* Compute frame-relative coordinates from window-relative
8962 coordinates. */
8963 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8964 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8965 + row->ascent - w->phys_cursor_ascent);
8966 h = row->height - 1;
8967
8968 /* Get the glyph the cursor is on. If we can't tell because
8969 the current matrix is invalid or such, give up. */
8970 cursor_glyph = get_phys_cursor_glyph (w);
8971 if (cursor_glyph == NULL)
8972 return;
8973
8974 /* Compute the width of the rectangle to draw. If on a stretch
8975 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8976 rectangle as wide as the glyph, but use a canonical character
8977 width instead. */
8978 wd = cursor_glyph->pixel_width - 1;
8979 if (cursor_glyph->type == STRETCH_GLYPH
8980 && !x_stretch_cursor_p)
8981 wd = min (CANON_X_UNIT (f), wd);
8982
8983 /* The foreground of cursor_gc is typically the same as the normal
8984 background color, which can cause the cursor box to be invisible. */
8985 xgcv.foreground = f->output_data.mac->cursor_pixel;
8986 if (dpyinfo->scratch_cursor_gc)
8987 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8988 else
8989 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8990 GCForeground, &xgcv);
8991 gc = dpyinfo->scratch_cursor_gc;
8992
8993 /* Set clipping, draw the rectangle, and reset clipping again. */
8994 x_clip_to_row (w, row, gc, 0);
8995 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
8996 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8997 }
8998
8999
9000 /* Draw a bar cursor on window W in glyph row ROW.
9001
9002 Implementation note: One would like to draw a bar cursor with an
9003 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9004 Unfortunately, I didn't find a font yet that has this property set.
9005 --gerd. */
9006
9007 static void
9008 x_draw_bar_cursor (w, row, width)
9009 struct window *w;
9010 struct glyph_row *row;
9011 int width;
9012 {
9013 /* If cursor hpos is out of bounds, don't draw garbage. This can
9014 happen in mini-buffer windows when switching between echo area
9015 glyphs and mini-buffer. */
9016 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9017 {
9018 struct frame *f = XFRAME (w->frame);
9019 struct glyph *cursor_glyph;
9020 GC gc;
9021 int x;
9022 unsigned long mask;
9023 XGCValues xgcv;
9024 Display *dpy;
9025 Window window;
9026
9027 cursor_glyph = get_phys_cursor_glyph (w);
9028 if (cursor_glyph == NULL)
9029 return;
9030
9031 xgcv.background = f->output_data.mac->cursor_pixel;
9032 xgcv.foreground = f->output_data.mac->cursor_pixel;
9033 mask = GCForeground | GCBackground;
9034 dpy = FRAME_MAC_DISPLAY (f);
9035 window = FRAME_MAC_WINDOW (f);
9036 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9037
9038 if (gc)
9039 XChangeGC (dpy, gc, mask, &xgcv);
9040 else
9041 {
9042 gc = XCreateGC (dpy, window, mask, &xgcv);
9043 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9044 }
9045
9046 if (width < 0)
9047 width = f->output_data.mac->cursor_width;
9048
9049 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9050 x_clip_to_row (w, row, gc, 0);
9051 XFillRectangle (dpy, window, gc,
9052 x,
9053 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9054 min (cursor_glyph->pixel_width, width),
9055 row->height);
9056 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9057 }
9058 }
9059
9060
9061 /* Clear the cursor of window W to background color, and mark the
9062 cursor as not shown. This is used when the text where the cursor
9063 is is about to be rewritten. */
9064
9065 static void
9066 x_clear_cursor (w)
9067 struct window *w;
9068 {
9069 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9070 x_update_window_cursor (w, 0);
9071 }
9072
9073
9074 /* Draw the cursor glyph of window W in glyph row ROW. See the
9075 comment of x_draw_glyphs for the meaning of HL. */
9076
9077 static void
9078 x_draw_phys_cursor_glyph (w, row, hl)
9079 struct window *w;
9080 struct glyph_row *row;
9081 enum draw_glyphs_face hl;
9082 {
9083 /* If cursor hpos is out of bounds, don't draw garbage. This can
9084 happen in mini-buffer windows when switching between echo area
9085 glyphs and mini-buffer. */
9086 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9087 {
9088 int on_p = w->phys_cursor_on_p;
9089 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9090 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9091 hl, 0);
9092 w->phys_cursor_on_p = on_p;
9093
9094 /* When we erase the cursor, and ROW is overlapped by other
9095 rows, make sure that these overlapping parts of other rows
9096 are redrawn. */
9097 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9098 {
9099 if (row > w->current_matrix->rows
9100 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9101 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9102
9103 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9104 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9105 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9106 }
9107 }
9108 }
9109
9110
9111 /* Erase the image of a cursor of window W from the screen. */
9112
9113 static void
9114 x_erase_phys_cursor (w)
9115 struct window *w;
9116 {
9117 struct frame *f = XFRAME (w->frame);
9118 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9119 int hpos = w->phys_cursor.hpos;
9120 int vpos = w->phys_cursor.vpos;
9121 int mouse_face_here_p = 0;
9122 struct glyph_matrix *active_glyphs = w->current_matrix;
9123 struct glyph_row *cursor_row;
9124 struct glyph *cursor_glyph;
9125 enum draw_glyphs_face hl;
9126
9127 /* No cursor displayed or row invalidated => nothing to do on the
9128 screen. */
9129 if (w->phys_cursor_type == NO_CURSOR)
9130 goto mark_cursor_off;
9131
9132 /* VPOS >= active_glyphs->nrows means that window has been resized.
9133 Don't bother to erase the cursor. */
9134 if (vpos >= active_glyphs->nrows)
9135 goto mark_cursor_off;
9136
9137 /* If row containing cursor is marked invalid, there is nothing we
9138 can do. */
9139 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9140 if (!cursor_row->enabled_p)
9141 goto mark_cursor_off;
9142
9143 /* If row is completely invisible, don't attempt to delete a cursor which
9144 isn't there. This may happen if cursor is at top of window, and
9145 we switch to a buffer with a header line in that window. */
9146 if (cursor_row->visible_height <= 0)
9147 goto mark_cursor_off;
9148
9149 /* This can happen when the new row is shorter than the old one.
9150 In this case, either x_draw_glyphs or clear_end_of_line
9151 should have cleared the cursor. Note that we wouldn't be
9152 able to erase the cursor in this case because we don't have a
9153 cursor glyph at hand. */
9154 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9155 goto mark_cursor_off;
9156
9157 /* If the cursor is in the mouse face area, redisplay that when
9158 we clear the cursor. */
9159 if (! NILP (dpyinfo->mouse_face_window)
9160 && w == XWINDOW (dpyinfo->mouse_face_window)
9161 && (vpos > dpyinfo->mouse_face_beg_row
9162 || (vpos == dpyinfo->mouse_face_beg_row
9163 && hpos >= dpyinfo->mouse_face_beg_col))
9164 && (vpos < dpyinfo->mouse_face_end_row
9165 || (vpos == dpyinfo->mouse_face_end_row
9166 && hpos < dpyinfo->mouse_face_end_col))
9167 /* Don't redraw the cursor's spot in mouse face if it is at the
9168 end of a line (on a newline). The cursor appears there, but
9169 mouse highlighting does not. */
9170 && cursor_row->used[TEXT_AREA] > hpos)
9171 mouse_face_here_p = 1;
9172
9173 /* Maybe clear the display under the cursor. */
9174 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9175 {
9176 int x;
9177 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9178
9179 cursor_glyph = get_phys_cursor_glyph (w);
9180 if (cursor_glyph == NULL)
9181 goto mark_cursor_off;
9182
9183 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9184
9185 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9186 x,
9187 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9188 cursor_row->y)),
9189 cursor_glyph->pixel_width,
9190 cursor_row->visible_height,
9191 0);
9192 }
9193
9194 /* Erase the cursor by redrawing the character underneath it. */
9195 if (mouse_face_here_p)
9196 hl = DRAW_MOUSE_FACE;
9197 else
9198 hl = DRAW_NORMAL_TEXT;
9199 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9200
9201 mark_cursor_off:
9202 w->phys_cursor_on_p = 0;
9203 w->phys_cursor_type = NO_CURSOR;
9204 }
9205
9206
9207 /* Non-zero if physical cursor of window W is within mouse face. */
9208
9209 static int
9210 cursor_in_mouse_face_p (w)
9211 struct window *w;
9212 {
9213 struct mac_display_info *dpyinfo
9214 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9215 int in_mouse_face = 0;
9216
9217 if (WINDOWP (dpyinfo->mouse_face_window)
9218 && XWINDOW (dpyinfo->mouse_face_window) == w)
9219 {
9220 int hpos = w->phys_cursor.hpos;
9221 int vpos = w->phys_cursor.vpos;
9222
9223 if (vpos >= dpyinfo->mouse_face_beg_row
9224 && vpos <= dpyinfo->mouse_face_end_row
9225 && (vpos > dpyinfo->mouse_face_beg_row
9226 || hpos >= dpyinfo->mouse_face_beg_col)
9227 && (vpos < dpyinfo->mouse_face_end_row
9228 || hpos < dpyinfo->mouse_face_end_col
9229 || dpyinfo->mouse_face_past_end))
9230 in_mouse_face = 1;
9231 }
9232
9233 return in_mouse_face;
9234 }
9235
9236
9237 /* Display or clear cursor of window W. If ON is zero, clear the
9238 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9239 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9240
9241 void
9242 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9243 struct window *w;
9244 int on, hpos, vpos, x, y;
9245 {
9246 struct frame *f = XFRAME (w->frame);
9247 int new_cursor_type;
9248 int new_cursor_width;
9249 struct glyph_matrix *current_glyphs;
9250 struct glyph_row *glyph_row;
9251 struct glyph *glyph;
9252 int cursor_non_selected;
9253 int active_cursor = 1;
9254
9255 /* This is pointless on invisible frames, and dangerous on garbaged
9256 windows and frames; in the latter case, the frame or window may
9257 be in the midst of changing its size, and x and y may be off the
9258 window. */
9259 if (! FRAME_VISIBLE_P (f)
9260 || FRAME_GARBAGED_P (f)
9261 || vpos >= w->current_matrix->nrows
9262 || hpos >= w->current_matrix->matrix_w)
9263 return;
9264
9265 /* If cursor is off and we want it off, return quickly. */
9266 if (!on && !w->phys_cursor_on_p)
9267 return;
9268
9269 current_glyphs = w->current_matrix;
9270 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9271 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9272
9273 /* If cursor row is not enabled, we don't really know where to
9274 display the cursor. */
9275 if (!glyph_row->enabled_p)
9276 {
9277 w->phys_cursor_on_p = 0;
9278 return;
9279 }
9280
9281 xassert (interrupt_input_blocked);
9282
9283 /* Set new_cursor_type to the cursor we want to be displayed. In a
9284 mini-buffer window, we want the cursor only to appear if we are
9285 reading input from this window. For the selected window, we want
9286 the cursor type given by the frame parameter. If explicitly
9287 marked off, draw no cursor. In all other cases, we want a hollow
9288 box cursor. */
9289 cursor_non_selected
9290 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
9291 w->buffer));
9292 new_cursor_width = -1;
9293 if (cursor_in_echo_area
9294 && FRAME_HAS_MINIBUF_P (f)
9295 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
9296 {
9297 if (w == XWINDOW (echo_area_window))
9298 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9299 else
9300 {
9301 if (cursor_non_selected)
9302 new_cursor_type = HOLLOW_BOX_CURSOR;
9303 else
9304 new_cursor_type = NO_CURSOR;
9305 active_cursor = 0;
9306 }
9307 }
9308 else
9309 {
9310 if (f != FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame
9311 || w != XWINDOW (f->selected_window))
9312 {
9313 active_cursor = 0;
9314
9315 if (MINI_WINDOW_P (w)
9316 || !cursor_non_selected
9317 || NILP (XBUFFER (w->buffer)->cursor_type))
9318 new_cursor_type = NO_CURSOR;
9319 else
9320 new_cursor_type = HOLLOW_BOX_CURSOR;
9321 }
9322 else
9323 {
9324 struct buffer *b = XBUFFER (w->buffer);
9325
9326 if (EQ (b->cursor_type, Qt))
9327 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9328 else
9329 new_cursor_type = x_specified_cursor_type (b->cursor_type,
9330 &new_cursor_width);
9331 if (w->cursor_off_p)
9332 {
9333 if (new_cursor_type == FILLED_BOX_CURSOR)
9334 new_cursor_type = HOLLOW_BOX_CURSOR;
9335 else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
9336 new_cursor_width = 1;
9337 else
9338 new_cursor_type = NO_CURSOR;
9339 }
9340 }
9341 }
9342
9343 /* If cursor is currently being shown and we don't want it to be or
9344 it is in the wrong place, or the cursor type is not what we want,
9345 erase it. */
9346 if (w->phys_cursor_on_p
9347 && (!on
9348 || w->phys_cursor.x != x
9349 || w->phys_cursor.y != y
9350 || new_cursor_type != w->phys_cursor_type
9351 || (new_cursor_type == BAR_CURSOR
9352 && new_cursor_width != w->phys_cursor_width)))
9353 x_erase_phys_cursor (w);
9354
9355 /* If the cursor is now invisible and we want it to be visible,
9356 display it. */
9357 if (on && !w->phys_cursor_on_p)
9358 {
9359 w->phys_cursor_ascent = glyph_row->ascent;
9360 w->phys_cursor_height = glyph_row->height;
9361
9362 /* Set phys_cursor_.* before x_draw_.* is called because some
9363 of them may need the information. */
9364 w->phys_cursor.x = x;
9365 w->phys_cursor.y = glyph_row->y;
9366 w->phys_cursor.hpos = hpos;
9367 w->phys_cursor.vpos = vpos;
9368 w->phys_cursor_type = new_cursor_type;
9369 w->phys_cursor_width = new_cursor_width;
9370 w->phys_cursor_on_p = 1;
9371
9372 switch (new_cursor_type)
9373 {
9374 case HOLLOW_BOX_CURSOR:
9375 x_draw_hollow_cursor (w, glyph_row);
9376 break;
9377
9378 case FILLED_BOX_CURSOR:
9379 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9380 break;
9381
9382 case BAR_CURSOR:
9383 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9384 break;
9385
9386 case NO_CURSOR:
9387 break;
9388
9389 default:
9390 abort ();
9391 }
9392 }
9393 }
9394
9395
9396 /* Display the cursor on window W, or clear it. X and Y are window
9397 relative pixel coordinates. HPOS and VPOS are glyph matrix
9398 positions. If W is not the selected window, display a hollow
9399 cursor. ON non-zero means display the cursor at X, Y which
9400 correspond to HPOS, VPOS, otherwise it is cleared. */
9401
9402 void
9403 x_display_cursor (w, on, hpos, vpos, x, y)
9404 struct window *w;
9405 int on, hpos, vpos, x, y;
9406 {
9407 BLOCK_INPUT;
9408 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9409 UNBLOCK_INPUT;
9410 }
9411
9412
9413 /* Display the cursor on window W, or clear it, according to ON_P.
9414 Don't change the cursor's position. */
9415
9416 void
9417 x_update_cursor (f, on_p)
9418 struct frame *f;
9419 int on_p;
9420 {
9421 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9422 }
9423
9424
9425 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9426 in the window tree rooted at W. */
9427
9428 static void
9429 x_update_cursor_in_window_tree (w, on_p)
9430 struct window *w;
9431 int on_p;
9432 {
9433 while (w)
9434 {
9435 if (!NILP (w->hchild))
9436 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9437 else if (!NILP (w->vchild))
9438 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9439 else
9440 x_update_window_cursor (w, on_p);
9441
9442 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9443 }
9444 }
9445
9446
9447 /* Switch the display of W's cursor on or off, according to the value
9448 of ON. */
9449
9450 static void
9451 x_update_window_cursor (w, on)
9452 struct window *w;
9453 int on;
9454 {
9455 /* Don't update cursor in windows whose frame is in the process
9456 of being deleted. */
9457 if (w->current_matrix)
9458 {
9459 BLOCK_INPUT;
9460 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9461 w->phys_cursor.vpos, w->phys_cursor.x,
9462 w->phys_cursor.y);
9463 UNBLOCK_INPUT;
9464 }
9465 }
9466
9467
9468
9469 \f
9470 /* Icons. */
9471
9472 #if 0 /* MAC_TODO: no icon support yet. */
9473 int
9474 x_bitmap_icon (f, icon)
9475 struct frame *f;
9476 Lisp_Object icon;
9477 {
9478 HANDLE hicon;
9479
9480 if (FRAME_W32_WINDOW (f) == 0)
9481 return 1;
9482
9483 if (NILP (icon))
9484 hicon = LoadIcon (hinst, EMACS_CLASS);
9485 else if (STRINGP (icon))
9486 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
9487 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9488 else if (SYMBOLP (icon))
9489 {
9490 LPCTSTR name;
9491
9492 if (EQ (icon, intern ("application")))
9493 name = (LPCTSTR) IDI_APPLICATION;
9494 else if (EQ (icon, intern ("hand")))
9495 name = (LPCTSTR) IDI_HAND;
9496 else if (EQ (icon, intern ("question")))
9497 name = (LPCTSTR) IDI_QUESTION;
9498 else if (EQ (icon, intern ("exclamation")))
9499 name = (LPCTSTR) IDI_EXCLAMATION;
9500 else if (EQ (icon, intern ("asterisk")))
9501 name = (LPCTSTR) IDI_ASTERISK;
9502 else if (EQ (icon, intern ("winlogo")))
9503 name = (LPCTSTR) IDI_WINLOGO;
9504 else
9505 return 1;
9506
9507 hicon = LoadIcon (NULL, name);
9508 }
9509 else
9510 return 1;
9511
9512 if (hicon == NULL)
9513 return 1;
9514
9515 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9516 (LPARAM) hicon);
9517
9518 return 0;
9519 }
9520 #endif /* MAC_TODO */
9521 \f
9522 /************************************************************************
9523 Handling X errors
9524 ************************************************************************/
9525
9526 /* Display Error Handling functions not used on W32. Listing them here
9527 helps diff stay in step when comparing w32term.c with xterm.c.
9528
9529 x_error_catcher (display, error)
9530 x_catch_errors (dpy)
9531 x_catch_errors_unwind (old_val)
9532 x_check_errors (dpy, format)
9533 x_had_errors_p (dpy)
9534 x_clear_errors (dpy)
9535 x_uncatch_errors (dpy, count)
9536 x_trace_wire ()
9537 x_connection_signal (signalnum)
9538 x_connection_closed (dpy, error_message)
9539 x_error_quitter (display, error)
9540 x_error_handler (display, error)
9541 x_io_error_quitter (display)
9542
9543 */
9544
9545 \f
9546 /* Changing the font of the frame. */
9547
9548 /* Give frame F the font named FONTNAME as its default font, and
9549 return the full name of that font. FONTNAME may be a wildcard
9550 pattern; in that case, we choose some font that fits the pattern.
9551 The return value shows which font we chose. */
9552
9553 Lisp_Object
9554 x_new_font (f, fontname)
9555 struct frame *f;
9556 register char *fontname;
9557 {
9558 struct font_info *fontp
9559 = FS_LOAD_FONT (f, 0, fontname, -1);
9560
9561 if (!fontp)
9562 return Qnil;
9563
9564 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9565 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9566 FRAME_FONTSET (f) = -1;
9567
9568 /* Compute the scroll bar width in character columns. */
9569 if (f->scroll_bar_pixel_width > 0)
9570 {
9571 int wid = FONT_WIDTH (FRAME_FONT (f));
9572 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9573 }
9574 else
9575 {
9576 int wid = FONT_WIDTH (FRAME_FONT (f));
9577 f->scroll_bar_cols = (14 + wid - 1) / wid;
9578 }
9579
9580 /* Now make the frame display the given font. */
9581 if (FRAME_MAC_WINDOW (f) != 0)
9582 {
9583 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9584 f->output_data.mac->font);
9585 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9586 f->output_data.mac->font);
9587 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9588 f->output_data.mac->font);
9589
9590 frame_update_line_height (f);
9591 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9592 x_set_window_size (f, 0, f->width, f->height);
9593 }
9594 else
9595 /* If we are setting a new frame's font for the first time,
9596 there are no faces yet, so this font's height is the line height. */
9597 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
9598
9599 return build_string (fontp->full_name);
9600 }
9601 \f
9602 /* Give frame F the fontset named FONTSETNAME as its default font, and
9603 return the full name of that fontset. FONTSETNAME may be a wildcard
9604 pattern; in that case, we choose some fontset that fits the pattern.
9605 The return value shows which fontset we chose. */
9606
9607 Lisp_Object
9608 x_new_fontset (f, fontsetname)
9609 struct frame *f;
9610 char *fontsetname;
9611 {
9612 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9613 Lisp_Object result;
9614
9615 if (fontset < 0)
9616 return Qnil;
9617
9618 if (FRAME_FONTSET (f) == fontset)
9619 /* This fontset is already set in frame F. There's nothing more
9620 to do. */
9621 return fontset_name (fontset);
9622
9623 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
9624
9625 if (!STRINGP (result))
9626 /* Can't load ASCII font. */
9627 return Qnil;
9628
9629 /* Since x_new_font doesn't update any fontset information, do it now. */
9630 FRAME_FONTSET(f) = fontset;
9631
9632 return build_string (fontsetname);
9633 }
9634
9635 /* Compute actual fringe widths */
9636
9637 void
9638 x_compute_fringe_widths (f, redraw)
9639 struct frame *f;
9640 int redraw;
9641 {
9642 int o_left = f->output_data.mac->left_fringe_width;
9643 int o_right = f->output_data.mac->right_fringe_width;
9644 int o_cols = f->output_data.mac->fringe_cols;
9645
9646 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9647 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9648 int left_fringe_width, right_fringe_width;
9649
9650 if (!NILP (left_fringe))
9651 left_fringe = Fcdr (left_fringe);
9652 if (!NILP (right_fringe))
9653 right_fringe = Fcdr (right_fringe);
9654
9655 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9656 XINT (left_fringe));
9657 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9658 XINT (right_fringe));
9659
9660 if (left_fringe_width || right_fringe_width)
9661 {
9662 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9663 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9664 int conf_wid = left_wid + right_wid;
9665 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9666 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9667 int real_wid = cols * font_wid;
9668 if (left_wid && right_wid)
9669 {
9670 if (left_fringe_width < 0)
9671 {
9672 /* Left fringe width is fixed, adjust right fringe if necessary */
9673 f->output_data.mac->left_fringe_width = left_wid;
9674 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9675 }
9676 else if (right_fringe_width < 0)
9677 {
9678 /* Right fringe width is fixed, adjust left fringe if necessary */
9679 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9680 f->output_data.mac->right_fringe_width = right_wid;
9681 }
9682 else
9683 {
9684 /* Adjust both fringes with an equal amount.
9685 Note that we are doing integer arithmetic here, so don't
9686 lose a pixel if the total width is an odd number. */
9687 int fill = real_wid - conf_wid;
9688 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9689 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9690 }
9691 }
9692 else if (left_fringe_width)
9693 {
9694 f->output_data.mac->left_fringe_width = real_wid;
9695 f->output_data.mac->right_fringe_width = 0;
9696 }
9697 else
9698 {
9699 f->output_data.mac->left_fringe_width = 0;
9700 f->output_data.mac->right_fringe_width = real_wid;
9701 }
9702 f->output_data.mac->fringe_cols = cols;
9703 f->output_data.mac->fringes_extra = real_wid;
9704 }
9705 else
9706 {
9707 f->output_data.mac->left_fringe_width = 0;
9708 f->output_data.mac->right_fringe_width = 0;
9709 f->output_data.mac->fringe_cols = 0;
9710 f->output_data.mac->fringes_extra = 0;
9711 }
9712
9713 if (redraw && FRAME_VISIBLE_P (f))
9714 if (o_left != f->output_data.mac->left_fringe_width ||
9715 o_right != f->output_data.mac->right_fringe_width ||
9716 o_cols != f->output_data.mac->fringe_cols)
9717 redraw_frame (f);
9718 }
9719 \f
9720 /***********************************************************************
9721 TODO: W32 Input Methods
9722 ***********************************************************************/
9723 /* Listing missing functions from xterm.c helps diff stay in step.
9724
9725 xim_destroy_callback (xim, client_data, call_data)
9726 xim_open_dpy (dpyinfo, resource_name)
9727 struct xim_inst_t
9728 xim_instantiate_callback (display, client_data, call_data)
9729 xim_initialize (dpyinfo, resource_name)
9730 xim_close_dpy (dpyinfo)
9731
9732 */
9733
9734 \f
9735 /* Calculate the absolute position in frame F
9736 from its current recorded position values and gravity. */
9737
9738 void
9739 x_calc_absolute_position (f)
9740 struct frame *f;
9741 {
9742 Point pt;
9743 int flags = f->output_data.mac->size_hint_flags;
9744
9745 pt.h = pt.v = 0;
9746
9747 /* Find the position of the outside upper-left corner of
9748 the inner window, with respect to the outer window. */
9749 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9750 {
9751 GrafPtr savePort;
9752 GetPort (&savePort);
9753
9754 #if TARGET_API_MAC_CARBON
9755 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9756 #else
9757 SetPort (FRAME_MAC_WINDOW (f));
9758 #endif
9759
9760 #if TARGET_API_MAC_CARBON
9761 {
9762 Rect r;
9763
9764 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9765 SetPt(&pt, r.left, r.top);
9766 }
9767 #else /* not TARGET_API_MAC_CARBON */
9768 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
9769 #endif /* not TARGET_API_MAC_CARBON */
9770 LocalToGlobal (&pt);
9771 SetPort (savePort);
9772 }
9773
9774 /* Treat negative positions as relative to the leftmost bottommost
9775 position that fits on the screen. */
9776 if (flags & XNegative)
9777 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9778 - 2 * f->output_data.mac->border_width - pt.h
9779 - PIXEL_WIDTH (f)
9780 + f->output_data.mac->left_pos);
9781 /* NTEMACS_TODO: Subtract menubar height? */
9782 if (flags & YNegative)
9783 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9784 - 2 * f->output_data.mac->border_width - pt.v
9785 - PIXEL_HEIGHT (f)
9786 + f->output_data.mac->top_pos);
9787 /* The left_pos and top_pos
9788 are now relative to the top and left screen edges,
9789 so the flags should correspond. */
9790 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9791 }
9792
9793 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9794 to really change the position, and 0 when calling from
9795 x_make_frame_visible (in that case, XOFF and YOFF are the current
9796 position values). It is -1 when calling from x_set_frame_parameters,
9797 which means, do adjust for borders but don't change the gravity. */
9798
9799 void
9800 x_set_offset (f, xoff, yoff, change_gravity)
9801 struct frame *f;
9802 register int xoff, yoff;
9803 int change_gravity;
9804 {
9805 int modified_top, modified_left;
9806
9807 if (change_gravity > 0)
9808 {
9809 f->output_data.mac->top_pos = yoff;
9810 f->output_data.mac->left_pos = xoff;
9811 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9812 if (xoff < 0)
9813 f->output_data.mac->size_hint_flags |= XNegative;
9814 if (yoff < 0)
9815 f->output_data.mac->size_hint_flags |= YNegative;
9816 f->output_data.mac->win_gravity = NorthWestGravity;
9817 }
9818 x_calc_absolute_position (f);
9819
9820 BLOCK_INPUT;
9821 x_wm_set_size_hint (f, (long) 0, 0);
9822
9823 modified_left = f->output_data.mac->left_pos;
9824 modified_top = f->output_data.mac->top_pos;
9825
9826 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9827 modified_top + 42, false);
9828
9829 UNBLOCK_INPUT;
9830 }
9831
9832 /* Call this to change the size of frame F's x-window.
9833 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9834 for this size change and subsequent size changes.
9835 Otherwise we leave the window gravity unchanged. */
9836
9837 void
9838 x_set_window_size (f, change_gravity, cols, rows)
9839 struct frame *f;
9840 int change_gravity;
9841 int cols, rows;
9842 {
9843 int pixelwidth, pixelheight;
9844
9845 BLOCK_INPUT;
9846
9847 check_frame_size (f, &rows, &cols);
9848 f->output_data.mac->vertical_scroll_bar_extra
9849 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9850 ? 0
9851 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
9852
9853 x_compute_fringe_widths (f, 0);
9854
9855 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9856 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9857
9858 f->output_data.mac->win_gravity = NorthWestGravity;
9859 x_wm_set_size_hint (f, (long) 0, 0);
9860
9861 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9862
9863 /* Now, strictly speaking, we can't be sure that this is accurate,
9864 but the window manager will get around to dealing with the size
9865 change request eventually, and we'll hear how it went when the
9866 ConfigureNotify event gets here.
9867
9868 We could just not bother storing any of this information here,
9869 and let the ConfigureNotify event set everything up, but that
9870 might be kind of confusing to the Lisp code, since size changes
9871 wouldn't be reported in the frame parameters until some random
9872 point in the future when the ConfigureNotify event arrives.
9873
9874 We pass 1 for DELAY since we can't run Lisp code inside of
9875 a BLOCK_INPUT. */
9876 change_frame_size (f, rows, cols, 0, 1, 0);
9877 PIXEL_WIDTH (f) = pixelwidth;
9878 PIXEL_HEIGHT (f) = pixelheight;
9879
9880 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9881 receive in the ConfigureNotify event; if we get what we asked
9882 for, then the event won't cause the screen to become garbaged, so
9883 we have to make sure to do it here. */
9884 SET_FRAME_GARBAGED (f);
9885
9886 XFlush (FRAME_X_DISPLAY (f));
9887
9888 /* If cursor was outside the new size, mark it as off. */
9889 mark_window_cursors_off (XWINDOW (f->root_window));
9890
9891 /* Clear out any recollection of where the mouse highlighting was,
9892 since it might be in a place that's outside the new frame size.
9893 Actually checking whether it is outside is a pain in the neck,
9894 so don't try--just let the highlighting be done afresh with new size. */
9895 cancel_mouse_face (f);
9896
9897 UNBLOCK_INPUT;
9898 }
9899 \f
9900 /* Mouse warping. */
9901
9902 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9903
9904 void
9905 x_set_mouse_position (f, x, y)
9906 struct frame *f;
9907 int x, y;
9908 {
9909 int pix_x, pix_y;
9910
9911 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9912 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9913
9914 if (pix_x < 0) pix_x = 0;
9915 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9916
9917 if (pix_y < 0) pix_y = 0;
9918 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9919
9920 x_set_mouse_pixel_position (f, pix_x, pix_y);
9921 }
9922
9923 void
9924 x_set_mouse_pixel_position (f, pix_x, pix_y)
9925 struct frame *f;
9926 int pix_x, pix_y;
9927 {
9928 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9929 BLOCK_INPUT;
9930
9931 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9932 0, 0, 0, 0, pix_x, pix_y);
9933 UNBLOCK_INPUT;
9934 #endif
9935 }
9936
9937 \f
9938 /* focus shifting, raising and lowering. */
9939
9940 void
9941 x_focus_on_frame (f)
9942 struct frame *f;
9943 {
9944 #if 0 /* This proves to be unpleasant. */
9945 x_raise_frame (f);
9946 #endif
9947 #if 0
9948 /* I don't think that the ICCCM allows programs to do things like this
9949 without the interaction of the window manager. Whatever you end up
9950 doing with this code, do it to x_unfocus_frame too. */
9951 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9952 RevertToPointerRoot, CurrentTime);
9953 #endif /* ! 0 */
9954 }
9955
9956 void
9957 x_unfocus_frame (f)
9958 struct frame *f;
9959 {
9960 }
9961
9962 /* Raise frame F. */
9963 void
9964 x_raise_frame (f)
9965 struct frame *f;
9966 {
9967 if (f->async_visible)
9968 SelectWindow (FRAME_MAC_WINDOW (f));
9969 }
9970
9971 /* Lower frame F. */
9972 void
9973 x_lower_frame (f)
9974 struct frame *f;
9975 {
9976 if (f->async_visible)
9977 SendBehind (FRAME_MAC_WINDOW (f), nil);
9978 }
9979
9980 static void
9981 XTframe_raise_lower (f, raise_flag)
9982 FRAME_PTR f;
9983 int raise_flag;
9984 {
9985 if (raise_flag)
9986 x_raise_frame (f);
9987 else
9988 x_lower_frame (f);
9989 }
9990 \f
9991 /* Change of visibility. */
9992
9993 /* This tries to wait until the frame is really visible.
9994 However, if the window manager asks the user where to position
9995 the frame, this will return before the user finishes doing that.
9996 The frame will not actually be visible at that time,
9997 but it will become visible later when the window manager
9998 finishes with it. */
9999
10000 void
10001 x_make_frame_visible (f)
10002 struct frame *f;
10003 {
10004 Lisp_Object type;
10005 int original_top, original_left;
10006
10007 BLOCK_INPUT;
10008
10009 if (! FRAME_VISIBLE_P (f))
10010 {
10011 /* We test FRAME_GARBAGED_P here to make sure we don't
10012 call x_set_offset a second time
10013 if we get to x_make_frame_visible a second time
10014 before the window gets really visible. */
10015 if (! FRAME_ICONIFIED_P (f)
10016 && ! f->output_data.mac->asked_for_visible)
10017 x_set_offset (f, f->output_data.mac->left_pos,
10018 f->output_data.mac->top_pos, 0);
10019
10020 f->output_data.mac->asked_for_visible = 1;
10021
10022 ShowWindow (FRAME_MAC_WINDOW (f));
10023 }
10024
10025 XFlush (FRAME_MAC_DISPLAY (f));
10026
10027 #if 0 /* MAC_TODO */
10028 /* Synchronize to ensure Emacs knows the frame is visible
10029 before we do anything else. We do this loop with input not blocked
10030 so that incoming events are handled. */
10031 {
10032 Lisp_Object frame;
10033 int count;
10034
10035 /* This must come after we set COUNT. */
10036 UNBLOCK_INPUT;
10037
10038 XSETFRAME (frame, f);
10039
10040 /* Wait until the frame is visible. Process X events until a
10041 MapNotify event has been seen, or until we think we won't get a
10042 MapNotify at all.. */
10043 for (count = input_signal_count + 10;
10044 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10045 {
10046 /* Force processing of queued events. */
10047 x_sync (f);
10048
10049 /* Machines that do polling rather than SIGIO have been
10050 observed to go into a busy-wait here. So we'll fake an
10051 alarm signal to let the handler know that there's something
10052 to be read. We used to raise a real alarm, but it seems
10053 that the handler isn't always enabled here. This is
10054 probably a bug. */
10055 if (input_polling_used ())
10056 {
10057 /* It could be confusing if a real alarm arrives while
10058 processing the fake one. Turn it off and let the
10059 handler reset it. */
10060 extern void poll_for_input_1 P_ ((void));
10061 int old_poll_suppress_count = poll_suppress_count;
10062 poll_suppress_count = 1;
10063 poll_for_input_1 ();
10064 poll_suppress_count = old_poll_suppress_count;
10065 }
10066
10067 /* See if a MapNotify event has been processed. */
10068 FRAME_SAMPLE_VISIBILITY (f);
10069 }
10070 }
10071 #endif /* MAC_TODO */
10072 }
10073
10074 /* Change from mapped state to withdrawn state. */
10075
10076 /* Make the frame visible (mapped and not iconified). */
10077
10078 void
10079 x_make_frame_invisible (f)
10080 struct frame *f;
10081 {
10082 /* Don't keep the highlight on an invisible frame. */
10083 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10084 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10085
10086 BLOCK_INPUT;
10087
10088 HideWindow (FRAME_MAC_WINDOW (f));
10089
10090 /* We can't distinguish this from iconification
10091 just by the event that we get from the server.
10092 So we can't win using the usual strategy of letting
10093 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10094 and synchronize with the server to make sure we agree. */
10095 f->visible = 0;
10096 FRAME_ICONIFIED_P (f) = 0;
10097 f->async_visible = 0;
10098 f->async_iconified = 0;
10099
10100 UNBLOCK_INPUT;
10101 }
10102
10103 /* Change window state from mapped to iconified. */
10104
10105 void
10106 x_iconify_frame (f)
10107 struct frame *f;
10108 {
10109 /* Don't keep the highlight on an invisible frame. */
10110 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10111 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10112
10113 #if 0
10114 /* Review: Since window is still visible in dock, still allow updates? */
10115 if (f->async_iconified)
10116 return;
10117 #endif
10118
10119 BLOCK_INPUT;
10120
10121 CollapseWindow (FRAME_MAC_WINDOW (f), true);
10122
10123 UNBLOCK_INPUT;
10124 }
10125
10126 \f
10127 /* Destroy the X window of frame F. */
10128
10129 void
10130 x_destroy_window (f)
10131 struct frame *f;
10132 {
10133 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10134
10135 BLOCK_INPUT;
10136
10137 DisposeWindow (FRAME_MAC_WINDOW (f));
10138
10139 free_frame_menubar (f);
10140 free_frame_faces (f);
10141
10142 xfree (f->output_data.mac);
10143 f->output_data.mac = 0;
10144 if (f == dpyinfo->x_focus_frame)
10145 dpyinfo->x_focus_frame = 0;
10146 if (f == dpyinfo->x_focus_event_frame)
10147 dpyinfo->x_focus_event_frame = 0;
10148 if (f == dpyinfo->x_highlight_frame)
10149 dpyinfo->x_highlight_frame = 0;
10150
10151 dpyinfo->reference_count--;
10152
10153 if (f == dpyinfo->mouse_face_mouse_frame)
10154 {
10155 dpyinfo->mouse_face_beg_row
10156 = dpyinfo->mouse_face_beg_col = -1;
10157 dpyinfo->mouse_face_end_row
10158 = dpyinfo->mouse_face_end_col = -1;
10159 dpyinfo->mouse_face_window = Qnil;
10160 dpyinfo->mouse_face_deferred_gc = 0;
10161 dpyinfo->mouse_face_mouse_frame = 0;
10162 }
10163
10164 UNBLOCK_INPUT;
10165 }
10166 \f
10167 /* Setting window manager hints. */
10168
10169 /* Set the normal size hints for the window manager, for frame F.
10170 FLAGS is the flags word to use--or 0 meaning preserve the flags
10171 that the window now has.
10172 If USER_POSITION is nonzero, we set the USPosition
10173 flag (this is useful when FLAGS is 0). */
10174 void
10175 x_wm_set_size_hint (f, flags, user_position)
10176 struct frame *f;
10177 long flags;
10178 int user_position;
10179 {
10180 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
10181 XSizeHints size_hints;
10182
10183 #ifdef USE_X_TOOLKIT
10184 Arg al[2];
10185 int ac = 0;
10186 Dimension widget_width, widget_height;
10187 Window window = XtWindow (f->output_data.x->widget);
10188 #else /* not USE_X_TOOLKIT */
10189 Window window = FRAME_X_WINDOW (f);
10190 #endif /* not USE_X_TOOLKIT */
10191
10192 /* Setting PMaxSize caused various problems. */
10193 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10194
10195 size_hints.x = f->output_data.x->left_pos;
10196 size_hints.y = f->output_data.x->top_pos;
10197
10198 #ifdef USE_X_TOOLKIT
10199 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10200 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10201 XtGetValues (f->output_data.x->widget, al, ac);
10202 size_hints.height = widget_height;
10203 size_hints.width = widget_width;
10204 #else /* not USE_X_TOOLKIT */
10205 size_hints.height = PIXEL_HEIGHT (f);
10206 size_hints.width = PIXEL_WIDTH (f);
10207 #endif /* not USE_X_TOOLKIT */
10208
10209 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10210 size_hints.height_inc = f->output_data.x->line_height;
10211 size_hints.max_width
10212 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10213 size_hints.max_height
10214 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10215
10216 /* Calculate the base and minimum sizes.
10217
10218 (When we use the X toolkit, we don't do it here.
10219 Instead we copy the values that the widgets are using, below.) */
10220 #ifndef USE_X_TOOLKIT
10221 {
10222 int base_width, base_height;
10223 int min_rows = 0, min_cols = 0;
10224
10225 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10226 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10227
10228 check_frame_size (f, &min_rows, &min_cols);
10229
10230 /* The window manager uses the base width hints to calculate the
10231 current number of rows and columns in the frame while
10232 resizing; min_width and min_height aren't useful for this
10233 purpose, since they might not give the dimensions for a
10234 zero-row, zero-column frame.
10235
10236 We use the base_width and base_height members if we have
10237 them; otherwise, we set the min_width and min_height members
10238 to the size for a zero x zero frame. */
10239
10240 #ifdef HAVE_X11R4
10241 size_hints.flags |= PBaseSize;
10242 size_hints.base_width = base_width;
10243 size_hints.base_height = base_height;
10244 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10245 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10246 #else
10247 size_hints.min_width = base_width;
10248 size_hints.min_height = base_height;
10249 #endif
10250 }
10251
10252 /* If we don't need the old flags, we don't need the old hint at all. */
10253 if (flags)
10254 {
10255 size_hints.flags |= flags;
10256 goto no_read;
10257 }
10258 #endif /* not USE_X_TOOLKIT */
10259
10260 {
10261 XSizeHints hints; /* Sometimes I hate X Windows... */
10262 long supplied_return;
10263 int value;
10264
10265 #ifdef HAVE_X11R4
10266 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10267 &supplied_return);
10268 #else
10269 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10270 #endif
10271
10272 #ifdef USE_X_TOOLKIT
10273 size_hints.base_height = hints.base_height;
10274 size_hints.base_width = hints.base_width;
10275 size_hints.min_height = hints.min_height;
10276 size_hints.min_width = hints.min_width;
10277 #endif
10278
10279 if (flags)
10280 size_hints.flags |= flags;
10281 else
10282 {
10283 if (value == 0)
10284 hints.flags = 0;
10285 if (hints.flags & PSize)
10286 size_hints.flags |= PSize;
10287 if (hints.flags & PPosition)
10288 size_hints.flags |= PPosition;
10289 if (hints.flags & USPosition)
10290 size_hints.flags |= USPosition;
10291 if (hints.flags & USSize)
10292 size_hints.flags |= USSize;
10293 }
10294 }
10295
10296 #ifndef USE_X_TOOLKIT
10297 no_read:
10298 #endif
10299
10300 #ifdef PWinGravity
10301 size_hints.win_gravity = f->output_data.x->win_gravity;
10302 size_hints.flags |= PWinGravity;
10303
10304 if (user_position)
10305 {
10306 size_hints.flags &= ~ PPosition;
10307 size_hints.flags |= USPosition;
10308 }
10309 #endif /* PWinGravity */
10310
10311 #ifdef HAVE_X11R4
10312 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10313 #else
10314 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10315 #endif
10316 #endif /* MAC_TODO */
10317 }
10318
10319 #if 0 /* MAC_TODO: hide application instead of iconify? */
10320 /* Used for IconicState or NormalState */
10321
10322 void
10323 x_wm_set_window_state (f, state)
10324 struct frame *f;
10325 int state;
10326 {
10327 #ifdef USE_X_TOOLKIT
10328 Arg al[1];
10329
10330 XtSetArg (al[0], XtNinitialState, state);
10331 XtSetValues (f->output_data.x->widget, al, 1);
10332 #else /* not USE_X_TOOLKIT */
10333 Window window = FRAME_X_WINDOW (f);
10334
10335 f->output_data.x->wm_hints.flags |= StateHint;
10336 f->output_data.x->wm_hints.initial_state = state;
10337
10338 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10339 #endif /* not USE_X_TOOLKIT */
10340 }
10341
10342 void
10343 x_wm_set_icon_pixmap (f, pixmap_id)
10344 struct frame *f;
10345 int pixmap_id;
10346 {
10347 Pixmap icon_pixmap;
10348
10349 #ifndef USE_X_TOOLKIT
10350 Window window = FRAME_X_WINDOW (f);
10351 #endif
10352
10353 if (pixmap_id > 0)
10354 {
10355 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10356 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10357 }
10358 else
10359 {
10360 /* It seems there is no way to turn off use of an icon pixmap.
10361 The following line does it, only if no icon has yet been created,
10362 for some window managers. But with mwm it crashes.
10363 Some people say it should clear the IconPixmapHint bit in this case,
10364 but that doesn't work, and the X consortium said it isn't the
10365 right thing at all. Since there is no way to win,
10366 best to explicitly give up. */
10367 #if 0
10368 f->output_data.x->wm_hints.icon_pixmap = None;
10369 #else
10370 return;
10371 #endif
10372 }
10373
10374 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10375
10376 {
10377 Arg al[1];
10378 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10379 XtSetValues (f->output_data.x->widget, al, 1);
10380 }
10381
10382 #else /* not USE_X_TOOLKIT */
10383
10384 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10385 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10386
10387 #endif /* not USE_X_TOOLKIT */
10388 }
10389
10390 #endif /* MAC_TODO */
10391
10392 void
10393 x_wm_set_icon_position (f, icon_x, icon_y)
10394 struct frame *f;
10395 int icon_x, icon_y;
10396 {
10397 #if 0 /* MAC_TODO: no icons on Mac */
10398 #ifdef USE_X_TOOLKIT
10399 Window window = XtWindow (f->output_data.x->widget);
10400 #else
10401 Window window = FRAME_X_WINDOW (f);
10402 #endif
10403
10404 f->output_data.x->wm_hints.flags |= IconPositionHint;
10405 f->output_data.x->wm_hints.icon_x = icon_x;
10406 f->output_data.x->wm_hints.icon_y = icon_y;
10407
10408 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10409 #endif /* MAC_TODO */
10410 }
10411
10412 \f
10413 /***********************************************************************
10414 Fonts
10415 ***********************************************************************/
10416
10417 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10418
10419 struct font_info *
10420 x_get_font_info (f, font_idx)
10421 FRAME_PTR f;
10422 int font_idx;
10423 {
10424 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10425 }
10426
10427 /* the global font name table */
10428 char **font_name_table = NULL;
10429 int font_name_table_size = 0;
10430 int font_name_count = 0;
10431
10432 /* compare two strings ignoring case */
10433 static int
10434 stricmp (const char *s, const char *t)
10435 {
10436 for ( ; tolower (*s) == tolower (*t); s++, t++)
10437 if (*s == '\0')
10438 return 0;
10439 return tolower (*s) - tolower (*t);
10440 }
10441
10442 /* compare two strings ignoring case and handling wildcard */
10443 static int
10444 wildstrieq (char *s1, char *s2)
10445 {
10446 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10447 return true;
10448
10449 return stricmp (s1, s2) == 0;
10450 }
10451
10452 /* Assume parameter 1 is fully qualified, no wildcards. */
10453 static int
10454 mac_font_pattern_match (fontname, pattern)
10455 char * fontname;
10456 char * pattern;
10457 {
10458 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
10459 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10460 char *ptr;
10461
10462 /* Copy fontname so we can modify it during comparison. */
10463 strcpy (font_name_copy, fontname);
10464
10465 ptr = regex;
10466 *ptr++ = '^';
10467
10468 /* Turn pattern into a regexp and do a regexp match. */
10469 for (; *pattern; pattern++)
10470 {
10471 if (*pattern == '?')
10472 *ptr++ = '.';
10473 else if (*pattern == '*')
10474 {
10475 *ptr++ = '.';
10476 *ptr++ = '*';
10477 }
10478 else
10479 *ptr++ = *pattern;
10480 }
10481 *ptr = '$';
10482 *(ptr + 1) = '\0';
10483
10484 return (fast_c_string_match_ignore_case (build_string (regex),
10485 font_name_copy) >= 0);
10486 }
10487
10488 /* Two font specs are considered to match if their foundry, family,
10489 weight, slant, and charset match. */
10490 static int
10491 mac_font_match (char *mf, char *xf)
10492 {
10493 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10494 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10495
10496 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10497 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10498 return mac_font_pattern_match (mf, xf);
10499
10500 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10501 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10502 return mac_font_pattern_match (mf, xf);
10503
10504 return (wildstrieq (m_foundry, x_foundry)
10505 && wildstrieq (m_family, x_family)
10506 && wildstrieq (m_weight, x_weight)
10507 && wildstrieq (m_slant, x_slant)
10508 && wildstrieq (m_charset, x_charset))
10509 || mac_font_pattern_match (mf, xf);
10510 }
10511
10512
10513 static char *
10514 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10515 {
10516 char foundry[32], family[32], cs[32];
10517 char xf[255], *result, *p;
10518
10519 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10520 {
10521 strcpy(foundry, "Apple");
10522 strcpy(family, name);
10523
10524 switch (scriptcode)
10525 {
10526 case smTradChinese:
10527 strcpy(cs, "big5-0");
10528 break;
10529 case smSimpChinese:
10530 strcpy(cs, "gb2312.1980-0");
10531 break;
10532 case smJapanese:
10533 strcpy(cs, "jisx0208.1983-sjis");
10534 break;
10535 case -smJapanese:
10536 /* Each Apple Japanese font is entered into the font table
10537 twice: once as a jisx0208.1983-sjis font and once as a
10538 jisx0201.1976-0 font. The latter can be used to display
10539 the ascii charset and katakana-jisx0201 charset. A
10540 negative script code signals that the name of this latter
10541 font is being built. */
10542 strcpy(cs, "jisx0201.1976-0");
10543 break;
10544 case smKorean:
10545 strcpy(cs, "ksc5601.1989-0");
10546 break;
10547 default:
10548 strcpy(cs, "mac-roman");
10549 break;
10550 }
10551 }
10552
10553 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10554 foundry, family, style & bold ? "bold" : "medium",
10555 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10556
10557 result = (char *) xmalloc (strlen (xf) + 1);
10558 strcpy (result, xf);
10559 for (p = result; *p; p++)
10560 *p = tolower(*p);
10561 return result;
10562 }
10563
10564
10565 /* Convert an X font spec to the corresponding mac font name, which
10566 can then be passed to GetFNum after conversion to a Pascal string.
10567 For ordinary Mac fonts, this should just be their names, like
10568 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10569 collection contain their charset designation in their names, like
10570 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10571 names are handled accordingly. */
10572 static void
10573 x_font_name_to_mac_font_name (char *xf, char *mf)
10574 {
10575 char foundry[32], family[32], weight[20], slant[2], cs[32];
10576
10577 strcpy (mf, "");
10578
10579 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10580 foundry, family, weight, slant, cs) != 5 &&
10581 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10582 foundry, family, weight, slant, cs) != 5)
10583 return;
10584
10585 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
10586 || strcmp (cs, "jisx0208.1983-sjis") == 0
10587 || strcmp (cs, "jisx0201.1976-0") == 0
10588 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
10589 strcpy(mf, family);
10590 else
10591 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10592 }
10593
10594
10595 static void
10596 add_font_name_table_entry (char *font_name)
10597 {
10598 if (font_name_table_size == 0)
10599 {
10600 font_name_table_size = 16;
10601 font_name_table = (char **)
10602 xmalloc (font_name_table_size * sizeof (char *));
10603 }
10604 else if (font_name_count + 1 >= font_name_table_size)
10605 {
10606 font_name_table_size += 16;
10607 font_name_table = (char **)
10608 xrealloc (font_name_table,
10609 font_name_table_size * sizeof (char *));
10610 }
10611
10612 font_name_table[font_name_count++] = font_name;
10613 }
10614
10615 /* Sets up the table font_name_table to contain the list of all fonts
10616 in the system the first time the table is used so that the Resource
10617 Manager need not be accessed every time this information is
10618 needed. */
10619
10620 static void
10621 init_font_name_table ()
10622 {
10623 #if TARGET_API_MAC_CARBON
10624 SInt32 sv;
10625
10626 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10627 {
10628 FMFontFamilyIterator ffi;
10629 FMFontFamilyInstanceIterator ffii;
10630 FMFontFamily ff;
10631
10632 /* Create a dummy instance iterator here to avoid creating and
10633 destroying it in the loop. */
10634 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10635 return;
10636 /* Create an iterator to enumerate the font families. */
10637 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10638 != noErr)
10639 {
10640 FMDisposeFontFamilyInstanceIterator (&ffii);
10641 return;
10642 }
10643
10644 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10645 {
10646 Str255 name;
10647 FMFont font;
10648 FMFontStyle style;
10649 FMFontSize size;
10650 SInt16 sc;
10651
10652 if (FMGetFontFamilyName (ff, name) != noErr)
10653 break;
10654 p2cstr (name);
10655
10656 sc = FontToScript (ff);
10657
10658 /* Point the instance iterator at the current font family. */
10659 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10660 break;
10661
10662 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10663 == noErr)
10664 if (size == 0)
10665 {
10666 add_font_name_table_entry (mac_to_x_fontname (name, size,
10667 style, sc));
10668 add_font_name_table_entry (mac_to_x_fontname (name, size,
10669 italic, sc));
10670 add_font_name_table_entry (mac_to_x_fontname (name, size,
10671 bold, sc));
10672 add_font_name_table_entry (mac_to_x_fontname (name, size,
10673 italic | bold,
10674 sc));
10675 }
10676 else
10677 {
10678 add_font_name_table_entry (mac_to_x_fontname (name, size,
10679 style, sc));
10680 if (smJapanese == sc)
10681 add_font_name_table_entry (mac_to_x_fontname (name, size,
10682 style,
10683 -smJapanese));
10684 }
10685 }
10686
10687 /* Dispose of the iterators. */
10688 FMDisposeFontFamilyIterator (&ffi);
10689 FMDisposeFontFamilyInstanceIterator (&ffii);
10690 }
10691 else
10692 {
10693 #endif /* TARGET_API_MAC_CARBON */
10694 GrafPtr port;
10695 SInt16 fontnum, old_fontnum;
10696 int num_mac_fonts = CountResources('FOND');
10697 int i, j;
10698 Handle font_handle, font_handle_2;
10699 short id, scriptcode;
10700 ResType type;
10701 Str32 name;
10702 struct FontAssoc *fat;
10703 struct AsscEntry *assc_entry;
10704
10705 GetPort (&port); /* save the current font number used */
10706 #if TARGET_API_MAC_CARBON
10707 old_fontnum = GetPortTextFont (port);
10708 #else
10709 old_fontnum = port->txFont;
10710 #endif
10711
10712 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10713 {
10714 font_handle = GetIndResource ('FOND', i);
10715 if (!font_handle)
10716 continue;
10717
10718 GetResInfo (font_handle, &id, &type, name);
10719 GetFNum (name, &fontnum);
10720 p2cstr (name);
10721 if (fontnum == 0)
10722 continue;
10723
10724 TextFont (fontnum);
10725 scriptcode = FontToScript (fontnum);
10726 do
10727 {
10728 HLock (font_handle);
10729
10730 if (GetResourceSizeOnDisk (font_handle)
10731 >= sizeof (struct FamRec))
10732 {
10733 fat = (struct FontAssoc *) (*font_handle
10734 + sizeof (struct FamRec));
10735 assc_entry
10736 = (struct AsscEntry *) (*font_handle
10737 + sizeof (struct FamRec)
10738 + sizeof (struct FontAssoc));
10739
10740 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
10741 {
10742 if (font_name_table_size == 0)
10743 {
10744 font_name_table_size = 16;
10745 font_name_table = (char **)
10746 xmalloc (font_name_table_size * sizeof (char *));
10747 }
10748 else if (font_name_count >= font_name_table_size)
10749 {
10750 font_name_table_size += 16;
10751 font_name_table = (char **)
10752 xrealloc (font_name_table,
10753 font_name_table_size * sizeof (char *));
10754 }
10755 font_name_table[font_name_count++]
10756 = mac_to_x_fontname (name,
10757 assc_entry->fontSize,
10758 assc_entry->fontStyle,
10759 scriptcode);
10760 /* Both jisx0208.1983-sjis and
10761 jisx0201.1976-sjis parts are contained in
10762 Apple Japanese (SJIS) font. */
10763 if (smJapanese == scriptcode)
10764 {
10765 font_name_table[font_name_count++]
10766 = mac_to_x_fontname (name,
10767 assc_entry->fontSize,
10768 assc_entry->fontStyle,
10769 -smJapanese);
10770 }
10771 }
10772 }
10773
10774 HUnlock (font_handle);
10775 font_handle_2 = GetNextFOND (font_handle);
10776 ReleaseResource (font_handle);
10777 font_handle = font_handle_2;
10778 }
10779 while (ResError () == noErr && font_handle);
10780 }
10781
10782 TextFont (old_fontnum);
10783 #if TARGET_API_MAC_CARBON
10784 }
10785 #endif /* TARGET_API_MAC_CARBON */
10786 }
10787
10788
10789 /* Return a list of at most MAXNAMES font specs matching the one in
10790 PATTERN. Cache matching fonts for patterns in
10791 dpyinfo->name_list_element to avoid looking them up again by
10792 calling mac_font_pattern_match (slow). */
10793
10794 Lisp_Object
10795 x_list_fonts (struct frame *f,
10796 Lisp_Object pattern,
10797 int size,
10798 int maxnames)
10799 {
10800 char *ptnstr;
10801 Lisp_Object newlist = Qnil, tem, key;
10802 int n_fonts = 0;
10803 int i;
10804 struct gcpro gcpro1, gcpro2;
10805 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
10806
10807 if (font_name_table == NULL) /* Initialize when first used. */
10808 init_font_name_table ();
10809
10810 if (dpyinfo)
10811 {
10812 tem = XCDR (dpyinfo->name_list_element);
10813 key = Fcons (pattern, make_number (maxnames));
10814
10815 newlist = Fassoc (key, tem);
10816 if (!NILP (newlist))
10817 {
10818 newlist = Fcdr_safe (newlist);
10819 goto label_cached;
10820 }
10821 }
10822
10823 ptnstr = SDATA (pattern);
10824
10825 GCPRO2 (pattern, newlist);
10826
10827 /* Scan and matching bitmap fonts. */
10828 for (i = 0; i < font_name_count; i++)
10829 {
10830 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10831 {
10832 newlist = Fcons (build_string (font_name_table[i]), newlist);
10833
10834 n_fonts++;
10835 if (n_fonts >= maxnames)
10836 break;
10837 }
10838 }
10839
10840 /* MAC_TODO: add code for matching outline fonts here */
10841
10842 UNGCPRO;
10843
10844 if (dpyinfo)
10845 {
10846 XSETCDR (dpyinfo->name_list_element,
10847 Fcons (Fcons (key, newlist),
10848 XCDR (dpyinfo->name_list_element)));
10849 }
10850 label_cached:
10851
10852 return newlist;
10853 }
10854
10855
10856 #if GLYPH_DEBUG
10857
10858 /* Check that FONT is valid on frame F. It is if it can be found in F's
10859 font table. */
10860
10861 static void
10862 x_check_font (f, font)
10863 struct frame *f;
10864 XFontStruct *font;
10865 {
10866 int i;
10867 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10868
10869 xassert (font != NULL);
10870
10871 for (i = 0; i < dpyinfo->n_fonts; i++)
10872 if (dpyinfo->font_table[i].name
10873 && font == dpyinfo->font_table[i].font)
10874 break;
10875
10876 xassert (i < dpyinfo->n_fonts);
10877 }
10878
10879 #endif /* GLYPH_DEBUG != 0 */
10880
10881 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10882 Note: There are (broken) X fonts out there with invalid XFontStruct
10883 min_bounds contents. For example, handa@etl.go.jp reports that
10884 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10885 have font->min_bounds.width == 0. */
10886
10887 static INLINE void
10888 x_font_min_bounds (font, w, h)
10889 MacFontStruct *font;
10890 int *w, *h;
10891 {
10892 /*
10893 * TODO: Windows does not appear to offer min bound, only
10894 * average and maximum width, and maximum height.
10895 */
10896 *h = FONT_HEIGHT (font);
10897 *w = FONT_WIDTH (font);
10898 }
10899
10900
10901 /* Compute the smallest character width and smallest font height over
10902 all fonts available on frame F. Set the members smallest_char_width
10903 and smallest_font_height in F's x_display_info structure to
10904 the values computed. Value is non-zero if smallest_font_height or
10905 smallest_char_width become smaller than they were before. */
10906
10907 int
10908 x_compute_min_glyph_bounds (f)
10909 struct frame *f;
10910 {
10911 int i;
10912 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10913 MacFontStruct *font;
10914 int old_width = dpyinfo->smallest_char_width;
10915 int old_height = dpyinfo->smallest_font_height;
10916
10917 dpyinfo->smallest_font_height = 100000;
10918 dpyinfo->smallest_char_width = 100000;
10919
10920 for (i = 0; i < dpyinfo->n_fonts; ++i)
10921 if (dpyinfo->font_table[i].name)
10922 {
10923 struct font_info *fontp = dpyinfo->font_table + i;
10924 int w, h;
10925
10926 font = (MacFontStruct *) fontp->font;
10927 xassert (font != (MacFontStruct *) ~0);
10928 x_font_min_bounds (font, &w, &h);
10929
10930 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10931 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10932 }
10933
10934 xassert (dpyinfo->smallest_char_width > 0
10935 && dpyinfo->smallest_font_height > 0);
10936
10937 return (dpyinfo->n_fonts == 1
10938 || dpyinfo->smallest_char_width < old_width
10939 || dpyinfo->smallest_font_height < old_height);
10940 }
10941
10942
10943 /* Determine whether given string is a fully-specified XLFD: all 14
10944 fields are present, none is '*'. */
10945
10946 static int
10947 is_fully_specified_xlfd (char *p)
10948 {
10949 int i;
10950 char *q;
10951
10952 if (*p != '-')
10953 return 0;
10954
10955 for (i = 0; i < 13; i++)
10956 {
10957 q = strchr (p + 1, '-');
10958 if (q == NULL)
10959 return 0;
10960 if (q - p == 2 && *(p + 1) == '*')
10961 return 0;
10962 p = q;
10963 }
10964
10965 if (strchr (p + 1, '-') != NULL)
10966 return 0;
10967
10968 if (*(p + 1) == '*' && *(p + 2) == '\0')
10969 return 0;
10970
10971 return 1;
10972 }
10973
10974
10975 const int kDefaultFontSize = 9;
10976
10977
10978 /* XLoadQueryFont creates and returns an internal representation for a
10979 font in a MacFontStruct struct. There is really no concept
10980 corresponding to "loading" a font on the Mac. But we check its
10981 existence and find the font number and all other information for it
10982 and store them in the returned MacFontStruct. */
10983
10984 static MacFontStruct *
10985 XLoadQueryFont (Display *dpy, char *fontname)
10986 {
10987 int i, size, is_two_byte_font, char_width;
10988 char *name;
10989 GrafPtr port;
10990 SInt16 old_fontnum, old_fontsize;
10991 Style old_fontface;
10992 Str32 mfontname;
10993 SInt16 fontnum;
10994 Style fontface = normal;
10995 MacFontStruct *font;
10996 FontInfo the_fontinfo;
10997 char s_weight[7], c_slant;
10998
10999 if (is_fully_specified_xlfd (fontname))
11000 name = fontname;
11001 else
11002 {
11003 for (i = 0; i < font_name_count; i++)
11004 if (mac_font_pattern_match (font_name_table[i], fontname))
11005 break;
11006
11007 if (i >= font_name_count)
11008 return NULL;
11009
11010 name = font_name_table[i];
11011 }
11012
11013 GetPort (&port); /* save the current font number used */
11014 #if TARGET_API_MAC_CARBON
11015 old_fontnum = GetPortTextFont (port);
11016 old_fontsize = GetPortTextSize (port);
11017 old_fontface = GetPortTextFace (port);
11018 #else
11019 old_fontnum = port->txFont;
11020 old_fontsize = port->txSize;
11021 old_fontface = port->txFace;
11022 #endif
11023
11024 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11025 size = kDefaultFontSize;
11026
11027 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11028 if (strcmp (s_weight, "bold") == 0)
11029 fontface |= bold;
11030
11031 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11032 if (c_slant == 'i')
11033 fontface |= italic;
11034
11035 x_font_name_to_mac_font_name (name, mfontname);
11036 c2pstr (mfontname);
11037 GetFNum (mfontname, &fontnum);
11038 if (fontnum == 0)
11039 return NULL;
11040
11041 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
11042
11043 font->fontname = (char *) xmalloc (strlen (name) + 1);
11044 bcopy (name, font->fontname, strlen (name) + 1);
11045
11046 font->mac_fontnum = fontnum;
11047 font->mac_fontsize = size;
11048 font->mac_fontface = fontface;
11049 font->mac_scriptcode = FontToScript (fontnum);
11050
11051 /* Apple Japanese (SJIS) font is listed as both
11052 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
11053 (Roman script) in init_font_name_table (). The latter should be
11054 treated as a one-byte font. */
11055 {
11056 char cs[32];
11057
11058 if (sscanf (name,
11059 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11060 cs) == 1
11061 && 0 == strcmp (cs, "jisx0201.1976-0"))
11062 font->mac_scriptcode = smRoman;
11063 }
11064
11065 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11066 font->mac_scriptcode == smTradChinese ||
11067 font->mac_scriptcode == smSimpChinese ||
11068 font->mac_scriptcode == smKorean;
11069
11070 TextFont (fontnum);
11071 TextSize (size);
11072 TextFace (fontface);
11073
11074 GetFontInfo (&the_fontinfo);
11075
11076 font->ascent = the_fontinfo.ascent;
11077 font->descent = the_fontinfo.descent;
11078
11079 font->min_byte1 = 0;
11080 if (is_two_byte_font)
11081 font->max_byte1 = 1;
11082 else
11083 font->max_byte1 = 0;
11084 font->min_char_or_byte2 = 0x20;
11085 font->max_char_or_byte2 = 0xff;
11086
11087 if (is_two_byte_font)
11088 {
11089 /* Use the width of an "ideographic space" of that font because
11090 the_fontinfo.widMax returns the wrong width for some fonts. */
11091 switch (font->mac_scriptcode)
11092 {
11093 case smJapanese:
11094 char_width = StringWidth("\p\x81\x40");
11095 break;
11096 case smTradChinese:
11097 char_width = StringWidth("\p\xa1\x40");
11098 break;
11099 case smSimpChinese:
11100 char_width = StringWidth("\p\xa1\xa1");
11101 break;
11102 case smKorean:
11103 char_width = StringWidth("\p\xa1\xa1");
11104 break;
11105 }
11106 }
11107 else
11108 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11109 returns 15 for 12-point Monaco! */
11110 char_width = CharWidth ('m');
11111
11112 font->max_bounds.rbearing = char_width;
11113 font->max_bounds.lbearing = 0;
11114 font->max_bounds.width = char_width;
11115 font->max_bounds.ascent = the_fontinfo.ascent;
11116 font->max_bounds.descent = the_fontinfo.descent;
11117
11118 font->min_bounds = font->max_bounds;
11119
11120 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11121 font->per_char = NULL;
11122 else
11123 {
11124 font->per_char = (XCharStruct *)
11125 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11126 {
11127 int c;
11128
11129 for (c = 0x20; c <= 0xff; c++)
11130 {
11131 font->per_char[c - 0x20] = font->max_bounds;
11132 font->per_char[c - 0x20].width = CharWidth (c);
11133 }
11134 }
11135 }
11136
11137 TextFont (old_fontnum); /* restore previous font number, size and face */
11138 TextSize (old_fontsize);
11139 TextFace (old_fontface);
11140
11141 return font;
11142 }
11143
11144
11145 /* Load font named FONTNAME of the size SIZE for frame F, and return a
11146 pointer to the structure font_info while allocating it dynamically.
11147 If SIZE is 0, load any size of font.
11148 If loading is failed, return NULL. */
11149
11150 struct font_info *
11151 x_load_font (f, fontname, size)
11152 struct frame *f;
11153 register char *fontname;
11154 int size;
11155 {
11156 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11157 Lisp_Object font_names;
11158
11159 /* Get a list of all the fonts that match this name. Once we
11160 have a list of matching fonts, we compare them against the fonts
11161 we already have by comparing names. */
11162 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11163
11164 if (!NILP (font_names))
11165 {
11166 Lisp_Object tail;
11167 int i;
11168
11169 for (i = 0; i < dpyinfo->n_fonts; i++)
11170 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11171 if (dpyinfo->font_table[i].name
11172 && (!strcmp (dpyinfo->font_table[i].name,
11173 SDATA (XCAR (tail)))
11174 || !strcmp (dpyinfo->font_table[i].full_name,
11175 SDATA (XCAR (tail)))))
11176 return (dpyinfo->font_table + i);
11177 }
11178
11179 /* Load the font and add it to the table. */
11180 {
11181 char *full_name;
11182 struct MacFontStruct *font;
11183 struct font_info *fontp;
11184 unsigned long value;
11185 int i;
11186
11187 /* If we have found fonts by x_list_font, load one of them. If
11188 not, we still try to load a font by the name given as FONTNAME
11189 because XListFonts (called in x_list_font) of some X server has
11190 a bug of not finding a font even if the font surely exists and
11191 is loadable by XLoadQueryFont. */
11192 if (size > 0 && !NILP (font_names))
11193 fontname = (char *) SDATA (XCAR (font_names));
11194
11195 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11196 if (!font)
11197 return NULL;
11198
11199 /* Find a free slot in the font table. */
11200 for (i = 0; i < dpyinfo->n_fonts; ++i)
11201 if (dpyinfo->font_table[i].name == NULL)
11202 break;
11203
11204 /* If no free slot found, maybe enlarge the font table. */
11205 if (i == dpyinfo->n_fonts
11206 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11207 {
11208 int sz;
11209 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11210 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11211 dpyinfo->font_table
11212 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11213 }
11214
11215 fontp = dpyinfo->font_table + i;
11216 if (i == dpyinfo->n_fonts)
11217 ++dpyinfo->n_fonts;
11218
11219 /* Now fill in the slots of *FONTP. */
11220 BLOCK_INPUT;
11221 fontp->font = font;
11222 fontp->font_idx = i;
11223 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11224 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11225
11226 fontp->full_name = fontp->name;
11227
11228 fontp->size = font->max_bounds.width;
11229 fontp->height = FONT_HEIGHT (font);
11230 {
11231 /* For some font, ascent and descent in max_bounds field is
11232 larger than the above value. */
11233 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11234 if (max_height > fontp->height)
11235 fontp->height = max_height;
11236 }
11237
11238 /* The slot `encoding' specifies how to map a character
11239 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11240 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11241 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11242 2:0xA020..0xFF7F). For the moment, we don't know which charset
11243 uses this font. So, we set information in fontp->encoding[1]
11244 which is never used by any charset. If mapping can't be
11245 decided, set FONT_ENCODING_NOT_DECIDED. */
11246 if (font->mac_scriptcode == smJapanese)
11247 fontp->encoding[1] = 4;
11248 else
11249 {
11250 fontp->encoding[1]
11251 = (font->max_byte1 == 0
11252 /* 1-byte font */
11253 ? (font->min_char_or_byte2 < 0x80
11254 ? (font->max_char_or_byte2 < 0x80
11255 ? 0 /* 0x20..0x7F */
11256 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11257 : 1) /* 0xA0..0xFF */
11258 /* 2-byte font */
11259 : (font->min_byte1 < 0x80
11260 ? (font->max_byte1 < 0x80
11261 ? (font->min_char_or_byte2 < 0x80
11262 ? (font->max_char_or_byte2 < 0x80
11263 ? 0 /* 0x2020..0x7F7F */
11264 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11265 : 3) /* 0x20A0..0x7FFF */
11266 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11267 : (font->min_char_or_byte2 < 0x80
11268 ? (font->max_char_or_byte2 < 0x80
11269 ? 2 /* 0xA020..0xFF7F */
11270 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11271 : 1))); /* 0xA0A0..0xFFFF */
11272 }
11273
11274 #if 0 /* MAC_TODO: fill these out with more reasonably values */
11275 fontp->baseline_offset
11276 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11277 ? (long) value : 0);
11278 fontp->relative_compose
11279 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11280 ? (long) value : 0);
11281 fontp->default_ascent
11282 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11283 ? (long) value : 0);
11284 #else
11285 fontp->baseline_offset = 0;
11286 fontp->relative_compose = 0;
11287 fontp->default_ascent = 0;
11288 #endif
11289
11290 /* Set global flag fonts_changed_p to non-zero if the font loaded
11291 has a character with a smaller width than any other character
11292 before, or if the font loaded has a smalle>r height than any
11293 other font loaded before. If this happens, it will make a
11294 glyph matrix reallocation necessary. */
11295 fonts_changed_p = x_compute_min_glyph_bounds (f);
11296 UNBLOCK_INPUT;
11297 return fontp;
11298 }
11299 }
11300
11301
11302 /* Return a pointer to struct font_info of a font named FONTNAME for
11303 frame F. If no such font is loaded, return NULL. */
11304
11305 struct font_info *
11306 x_query_font (f, fontname)
11307 struct frame *f;
11308 register char *fontname;
11309 {
11310 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11311 int i;
11312
11313 for (i = 0; i < dpyinfo->n_fonts; i++)
11314 if (dpyinfo->font_table[i].name
11315 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11316 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11317 return (dpyinfo->font_table + i);
11318 return NULL;
11319 }
11320
11321
11322 /* Find a CCL program for a font specified by FONTP, and set the member
11323 `encoder' of the structure. */
11324
11325 void
11326 x_find_ccl_program (fontp)
11327 struct font_info *fontp;
11328 {
11329 Lisp_Object list, elt;
11330
11331 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11332 {
11333 elt = XCAR (list);
11334 if (CONSP (elt)
11335 && STRINGP (XCAR (elt))
11336 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11337 >= 0))
11338 break;
11339 }
11340 if (! NILP (list))
11341 {
11342 struct ccl_program *ccl
11343 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11344
11345 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11346 xfree (ccl);
11347 else
11348 fontp->font_encoder = ccl;
11349 }
11350 }
11351
11352
11353 \f
11354 /***********************************************************************
11355 Initialization
11356 ***********************************************************************/
11357
11358 #ifdef USE_X_TOOLKIT
11359 static XrmOptionDescRec emacs_options[] = {
11360 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11361 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11362
11363 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11364 XrmoptionSepArg, NULL},
11365 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11366
11367 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11368 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11369 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11370 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11371 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11372 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11373 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11374 };
11375 #endif /* USE_X_TOOLKIT */
11376
11377 static int x_initialized;
11378
11379 #ifdef MULTI_KBOARD
11380 /* Test whether two display-name strings agree up to the dot that separates
11381 the screen number from the server number. */
11382 static int
11383 same_x_server (name1, name2)
11384 char *name1, *name2;
11385 {
11386 int seen_colon = 0;
11387 unsigned char *system_name = SDATA (Vsystem_name);
11388 int system_name_length = strlen (system_name);
11389 int length_until_period = 0;
11390
11391 while (system_name[length_until_period] != 0
11392 && system_name[length_until_period] != '.')
11393 length_until_period++;
11394
11395 /* Treat `unix' like an empty host name. */
11396 if (! strncmp (name1, "unix:", 5))
11397 name1 += 4;
11398 if (! strncmp (name2, "unix:", 5))
11399 name2 += 4;
11400 /* Treat this host's name like an empty host name. */
11401 if (! strncmp (name1, system_name, system_name_length)
11402 && name1[system_name_length] == ':')
11403 name1 += system_name_length;
11404 if (! strncmp (name2, system_name, system_name_length)
11405 && name2[system_name_length] == ':')
11406 name2 += system_name_length;
11407 /* Treat this host's domainless name like an empty host name. */
11408 if (! strncmp (name1, system_name, length_until_period)
11409 && name1[length_until_period] == ':')
11410 name1 += length_until_period;
11411 if (! strncmp (name2, system_name, length_until_period)
11412 && name2[length_until_period] == ':')
11413 name2 += length_until_period;
11414
11415 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11416 {
11417 if (*name1 == ':')
11418 seen_colon++;
11419 if (seen_colon && *name1 == '.')
11420 return 1;
11421 }
11422 return (seen_colon
11423 && (*name1 == '.' || *name1 == '\0')
11424 && (*name2 == '.' || *name2 == '\0'));
11425 }
11426 #endif
11427
11428
11429 /* The Mac Event loop code */
11430
11431 #ifndef MAC_OSX
11432 #include <Events.h>
11433 #include <Quickdraw.h>
11434 #include <Balloons.h>
11435 #include <Devices.h>
11436 #include <Fonts.h>
11437 #include <Gestalt.h>
11438 #include <Menus.h>
11439 #include <Processes.h>
11440 #include <Sound.h>
11441 #include <ToolUtils.h>
11442 #include <TextUtils.h>
11443 #include <Dialogs.h>
11444 #include <Script.h>
11445 #include <Types.h>
11446 #include <TextEncodingConverter.h>
11447 #include <Resources.h>
11448
11449 #if __MWERKS__
11450 #include <unix.h>
11451 #endif
11452 #endif /* ! MAC_OSX */
11453
11454 #define M_APPLE 128
11455 #define I_ABOUT 1
11456
11457 #define WINDOW_RESOURCE 128
11458 #define TERM_WINDOW_RESOURCE 129
11459
11460 #define DEFAULT_NUM_COLS 80
11461
11462 #define MIN_DOC_SIZE 64
11463 #define MAX_DOC_SIZE 32767
11464
11465 /* sleep time for WaitNextEvent */
11466 #define WNE_SLEEP_AT_SUSPEND 10
11467 #define WNE_SLEEP_AT_RESUME 1
11468
11469 /* true when cannot handle any Mac OS events */
11470 static int handling_window_update = 0;
11471
11472 /* the flag appl_is_suspended is used both for determining the sleep
11473 time to be passed to WaitNextEvent and whether the cursor should be
11474 drawn when updating the display. The cursor is turned off when
11475 Emacs is suspended. Redrawing it is unnecessary and what needs to
11476 be done depends on whether the cursor lies inside or outside the
11477 redraw region. So we might as well skip drawing it when Emacs is
11478 suspended. */
11479 static Boolean app_is_suspended = false;
11480 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11481
11482 #define EXTRA_STACK_ALLOC (256 * 1024)
11483
11484 #define ARGV_STRING_LIST_ID 129
11485 #define ABOUT_ALERT_ID 128
11486 #define RAM_TOO_LARGE_ALERT_ID 129
11487
11488 Boolean terminate_flag = false;
11489
11490 /* True if using command key as meta key. */
11491 Lisp_Object Vmac_command_key_is_meta;
11492
11493 /* True if the ctrl and meta keys should be reversed. */
11494 Lisp_Object Vmac_reverse_ctrl_meta;
11495
11496 #if USE_CARBON_EVENTS
11497 /* True if the mouse wheel button (i.e. button 4) should map to
11498 mouse-2, instead of mouse-3. */
11499 Lisp_Object Vmac_wheel_button_is_mouse_2;
11500 #endif
11501
11502 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11503 to this text encoding */
11504 int mac_keyboard_text_encoding;
11505 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11506
11507 /* Set in term/mac-win.el to indicate that event loop can now generate
11508 drag and drop events. */
11509 Lisp_Object Qmac_ready_for_drag_n_drop;
11510
11511 Lisp_Object drag_and_drop_file_list;
11512
11513 Point saved_menu_event_location;
11514
11515 /* Apple Events */
11516 static void init_required_apple_events (void);
11517 static pascal OSErr
11518 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
11519 static pascal OSErr
11520 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
11521 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
11522 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
11523
11524 /* Drag and Drop */
11525 static OSErr init_mac_drag_n_drop ();
11526 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
11527
11528 #if USE_CARBON_EVENTS
11529 /* Preliminary Support for the OSX Services Menu */
11530 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
11531 static void init_service_handler ();
11532 #endif
11533
11534 extern void init_emacs_passwd_dir ();
11535 extern int emacs_main (int, char **, char **);
11536 extern void check_alarm ();
11537
11538 extern void initialize_applescript();
11539 extern void terminate_applescript();
11540
11541 static unsigned int
11542 #if USE_CARBON_EVENTS
11543 mac_to_emacs_modifiers (UInt32 mods)
11544 #else
11545 mac_to_emacs_modifiers (EventModifiers mods)
11546 #endif
11547 {
11548 unsigned int result = 0;
11549 if (mods & macShiftKey)
11550 result |= shift_modifier;
11551 if (mods & macCtrlKey)
11552 result |= ctrl_modifier;
11553 if (mods & macMetaKey)
11554 result |= meta_modifier;
11555 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
11556 result |= alt_modifier;
11557 return result;
11558 }
11559
11560 #if USE_CARBON_EVENTS
11561 /* Obtains the event modifiers from the event ref and then calls
11562 mac_to_emacs_modifiers. */
11563 static int
11564 mac_event_to_emacs_modifiers (EventRef eventRef)
11565 {
11566 UInt32 mods = 0;
11567 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
11568 sizeof (UInt32), NULL, &mods);
11569 return mac_to_emacs_modifiers (mods);
11570 }
11571
11572 /* Given an event ref, return the code to use for the mouse button
11573 code in the emacs input_event. */
11574 static int
11575 mac_get_mouse_btn (EventRef ref)
11576 {
11577 EventMouseButton result = kEventMouseButtonPrimary;
11578 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
11579 sizeof (EventMouseButton), NULL, &result);
11580 switch (result)
11581 {
11582 case kEventMouseButtonPrimary:
11583 return 0;
11584 case kEventMouseButtonSecondary:
11585 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
11586 case kEventMouseButtonTertiary:
11587 case 4: /* 4 is the number for the mouse wheel button */
11588 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
11589 default:
11590 return 0;
11591 }
11592 }
11593
11594 /* Normally, ConvertEventRefToEventRecord will correctly handle all
11595 events. However the click of the mouse wheel is not converted to a
11596 mouseDown or mouseUp event. This calls ConvertEventRef, but then
11597 checks to see if it is a mouse up or down carbon event that has not
11598 been converted, and if so, converts it by hand (to be picked up in
11599 the XTread_socket loop). */
11600 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
11601 {
11602 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
11603 /* Do special case for mouse wheel button. */
11604 if (!result && GetEventClass (eventRef) == kEventClassMouse)
11605 {
11606 UInt32 kind = GetEventKind (eventRef);
11607 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
11608 {
11609 eventRec->what = mouseDown;
11610 result=1;
11611 }
11612 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
11613 {
11614 eventRec->what = mouseUp;
11615 result=1;
11616 }
11617 if (result)
11618 {
11619 /* Need where and when. */
11620 UInt32 mods;
11621 GetEventParameter (eventRef, kEventParamMouseLocation,
11622 typeQDPoint, NULL, sizeof (Point),
11623 NULL, &eventRec->where);
11624 /* Use two step process because new event modifiers are
11625 32-bit and old are 16-bit. Currently, only loss is
11626 NumLock & Fn. */
11627 GetEventParameter (eventRef, kEventParamKeyModifiers,
11628 typeUInt32, NULL, sizeof (UInt32),
11629 NULL, &mods);
11630 eventRec->modifiers = mods;
11631
11632 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
11633 }
11634 }
11635 return result;
11636 }
11637
11638 #endif
11639
11640 static void
11641 do_get_menus (void)
11642 {
11643 Handle menubar_handle;
11644 MenuHandle menu_handle;
11645
11646 menubar_handle = GetNewMBar (128);
11647 if(menubar_handle == NULL)
11648 abort ();
11649 SetMenuBar (menubar_handle);
11650 DrawMenuBar ();
11651
11652 menu_handle = GetMenuHandle (M_APPLE);
11653 if(menu_handle != NULL)
11654 AppendResMenu (menu_handle,'DRVR');
11655 else
11656 abort ();
11657 }
11658
11659
11660 static void
11661 do_init_managers (void)
11662 {
11663 #if !TARGET_API_MAC_CARBON
11664 InitGraf (&qd.thePort);
11665 InitFonts ();
11666 FlushEvents (everyEvent, 0);
11667 InitWindows ();
11668 InitMenus ();
11669 TEInit ();
11670 InitDialogs (NULL);
11671 #endif /* !TARGET_API_MAC_CARBON */
11672 InitCursor ();
11673
11674 #if !TARGET_API_MAC_CARBON
11675 /* set up some extra stack space for use by emacs */
11676 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11677
11678 /* MaxApplZone must be called for AppleScript to execute more
11679 complicated scripts */
11680 MaxApplZone ();
11681 MoreMasters ();
11682 #endif /* !TARGET_API_MAC_CARBON */
11683 }
11684
11685 static void
11686 do_check_ram_size (void)
11687 {
11688 SInt32 physical_ram_size, logical_ram_size;
11689
11690 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11691 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11692 || physical_ram_size > 256 * 1024 * 1024
11693 || logical_ram_size > 256 * 1024 * 1024)
11694 {
11695 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11696 exit (1);
11697 }
11698 }
11699
11700 static void
11701 do_window_update (WindowPtr win)
11702 {
11703 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11704 struct frame *f = mwp->mFP;
11705
11706 if (f)
11707 {
11708 if (f->async_visible == 0)
11709 {
11710 f->async_visible = 1;
11711 f->async_iconified = 0;
11712 SET_FRAME_GARBAGED (f);
11713
11714 /* An update event is equivalent to MapNotify on X, so report
11715 visibility changes properly. */
11716 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11717 /* Force a redisplay sooner or later to update the
11718 frame titles in case this is the second frame. */
11719 record_asynch_buffer_change ();
11720 }
11721 else
11722 {
11723 BeginUpdate (win);
11724 handling_window_update = 1;
11725
11726 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
11727
11728 expose_frame (f, 0, 0, 0, 0);
11729
11730 handling_window_update = 0;
11731 EndUpdate (win);
11732 }
11733 }
11734 }
11735
11736 static int
11737 is_emacs_window (WindowPtr win)
11738 {
11739 Lisp_Object tail, frame;
11740
11741 if (!win)
11742 return 0;
11743
11744 FOR_EACH_FRAME (tail, frame)
11745 if (FRAME_MAC_P (XFRAME (frame)))
11746 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11747 return 1;
11748
11749 return 0;
11750 }
11751
11752 static void
11753 do_window_activate (WindowPtr win)
11754 {
11755 mac_output *mwp;
11756 struct frame *f;
11757
11758 if (is_emacs_window (win))
11759 {
11760 mwp = (mac_output *) GetWRefCon (win);
11761 f = mwp->mFP;
11762
11763 if (f)
11764 {
11765 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11766 activate_scroll_bars (f);
11767 }
11768 }
11769 }
11770
11771 static void
11772 do_window_deactivate (WindowPtr win)
11773 {
11774 mac_output *mwp;
11775 struct frame *f;
11776
11777 if (is_emacs_window (win))
11778 {
11779 mwp = (mac_output *) GetWRefCon (win);
11780 f = mwp->mFP;
11781
11782 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11783 {
11784 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11785 deactivate_scroll_bars (f);
11786 }
11787 }
11788 }
11789
11790 static void
11791 do_app_resume ()
11792 {
11793 WindowPtr wp;
11794 mac_output *mwp;
11795 struct frame *f;
11796
11797 wp = FrontWindow();
11798 if (is_emacs_window (wp))
11799 {
11800 mwp = (mac_output *) GetWRefCon (wp);
11801 f = mwp->mFP;
11802
11803 if (f)
11804 {
11805 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11806 activate_scroll_bars (f);
11807 }
11808 }
11809
11810 app_is_suspended = false;
11811 app_sleep_time = WNE_SLEEP_AT_RESUME;
11812 }
11813
11814 static void
11815 do_app_suspend ()
11816 {
11817 WindowPtr wp;
11818 mac_output *mwp;
11819 struct frame *f;
11820
11821 wp = FrontWindow();
11822 if (is_emacs_window (wp))
11823 {
11824 mwp = (mac_output *) GetWRefCon (wp);
11825 f = mwp->mFP;
11826
11827 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11828 {
11829 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11830 deactivate_scroll_bars (f);
11831 }
11832 }
11833
11834 app_is_suspended = true;
11835 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11836 }
11837
11838
11839 static void
11840 do_mouse_moved (Point mouse_pos)
11841 {
11842 WindowPtr wp = FrontWindow ();
11843 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11844
11845 #if TARGET_API_MAC_CARBON
11846 SetPort (GetWindowPort (wp));
11847 #else
11848 SetPort (wp);
11849 #endif
11850
11851 GlobalToLocal (&mouse_pos);
11852
11853 note_mouse_movement (f, &mouse_pos);
11854 }
11855
11856
11857 static void
11858 do_os_event (EventRecord *erp)
11859 {
11860 switch((erp->message >> 24) & 0x000000FF)
11861 {
11862 case suspendResumeMessage:
11863 if((erp->message & resumeFlag) == 1)
11864 do_app_resume ();
11865 else
11866 do_app_suspend ();
11867 break;
11868
11869 case mouseMovedMessage:
11870 do_mouse_moved (erp->where);
11871 break;
11872 }
11873 }
11874
11875 static void
11876 do_events (EventRecord *erp)
11877 {
11878 switch (erp->what)
11879 {
11880 case updateEvt:
11881 do_window_update ((WindowPtr) erp->message);
11882 break;
11883
11884 case osEvt:
11885 do_os_event (erp);
11886 break;
11887
11888 case activateEvt:
11889 if ((erp->modifiers & activeFlag) != 0)
11890 do_window_activate ((WindowPtr) erp->message);
11891 else
11892 do_window_deactivate ((WindowPtr) erp->message);
11893 break;
11894 }
11895 }
11896
11897 static void
11898 do_apple_menu (SInt16 menu_item)
11899 {
11900 #if !TARGET_API_MAC_CARBON
11901 Str255 item_name;
11902 SInt16 da_driver_refnum;
11903
11904 if (menu_item == I_ABOUT)
11905 NoteAlert (ABOUT_ALERT_ID, NULL);
11906 else
11907 {
11908 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11909 da_driver_refnum = OpenDeskAcc (item_name);
11910 }
11911 #endif /* !TARGET_API_MAC_CARBON */
11912 }
11913
11914 void
11915 do_menu_choice (SInt32 menu_choice)
11916 {
11917 SInt16 menu_id, menu_item;
11918
11919 menu_id = HiWord (menu_choice);
11920 menu_item = LoWord (menu_choice);
11921
11922 if (menu_id == 0)
11923 return;
11924
11925 switch (menu_id)
11926 {
11927 case M_APPLE:
11928 do_apple_menu (menu_item);
11929 break;
11930
11931 default:
11932 {
11933 WindowPtr wp = FrontWindow ();
11934 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11935 MenuHandle menu = GetMenuHandle (menu_id);
11936 if (menu)
11937 {
11938 UInt32 refcon;
11939
11940 GetMenuItemRefCon (menu, menu_item, &refcon);
11941 menubar_selection_callback (f, refcon);
11942 }
11943 }
11944 }
11945
11946 HiliteMenu (0);
11947 }
11948
11949
11950 /* Handle drags in size box. Based on code contributed by Ben
11951 Mesander and IM - Window Manager A. */
11952
11953 static void
11954 do_grow_window (WindowPtr w, EventRecord *e)
11955 {
11956 long grow_size;
11957 Rect limit_rect;
11958 int rows, columns;
11959 mac_output *mwp = (mac_output *) GetWRefCon (w);
11960 struct frame *f = mwp->mFP;
11961
11962 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11963
11964 grow_size = GrowWindow (w, e->where, &limit_rect);
11965
11966 /* see if it really changed size */
11967 if (grow_size != 0)
11968 {
11969 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11970 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11971
11972 x_set_window_size (f, 0, columns, rows);
11973 }
11974 }
11975
11976
11977 /* Handle clicks in zoom box. Calculation of "standard state" based
11978 on code in IM - Window Manager A and code contributed by Ben
11979 Mesander. The standard state of an Emacs window is 80-characters
11980 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11981
11982 static void
11983 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11984 {
11985 GrafPtr save_port;
11986 Rect zoom_rect, port_rect;
11987 Point top_left;
11988 int w_title_height, columns, rows, width, height, dummy, x, y;
11989 mac_output *mwp = (mac_output *) GetWRefCon (w);
11990 struct frame *f = mwp->mFP;
11991
11992 GetPort (&save_port);
11993
11994 #if TARGET_API_MAC_CARBON
11995 SetPort (GetWindowPort (w));
11996 #else
11997 SetPort (w);
11998 #endif
11999
12000 /* Clear window to avoid flicker. */
12001 #if TARGET_API_MAC_CARBON
12002 {
12003 Rect r;
12004 BitMap bm;
12005
12006 GetWindowPortBounds (w, &r);
12007 EraseRect (&r);
12008
12009 if (zoom_in_or_out == inZoomOut)
12010 {
12011 /* calculate height of window's title bar (hard card it for now). */
12012 w_title_height = 20 + GetMBarHeight ();
12013
12014 /* get maximum height of window into zoom_rect.bottom -
12015 zoom_rect.top */
12016 GetQDGlobalsScreenBits (&bm);
12017 zoom_rect = bm.bounds;
12018 zoom_rect.top += w_title_height;
12019 InsetRect (&zoom_rect, 8, 4); /* not too tight */
12020
12021 zoom_rect.right = zoom_rect.left
12022 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12023
12024 SetWindowStandardState (w, &zoom_rect);
12025 }
12026 }
12027 #else /* not TARGET_API_MAC_CARBON */
12028 EraseRect (&(w->portRect));
12029 if (zoom_in_or_out == inZoomOut)
12030 {
12031 SetPt (&top_left, w->portRect.left, w->portRect.top);
12032 LocalToGlobal (&top_left);
12033
12034 /* calculate height of window's title bar */
12035 w_title_height = top_left.v - 1
12036 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
12037
12038 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
12039 zoom_rect = qd.screenBits.bounds;
12040 zoom_rect.top += w_title_height;
12041 InsetRect (&zoom_rect, 8, 4); /* not too tight */
12042
12043 zoom_rect.right = zoom_rect.left
12044 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12045
12046 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
12047 = zoom_rect;
12048 }
12049 #endif /* not TARGET_API_MAC_CARBON */
12050
12051 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
12052
12053 /* retrieve window size and update application values */
12054 #if TARGET_API_MAC_CARBON
12055 GetWindowPortBounds (w, &port_rect);
12056 #else
12057 port_rect = w->portRect;
12058 #endif
12059 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
12060 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
12061 x_set_window_size (mwp->mFP, 0, columns, rows);
12062
12063 SetPort (save_port);
12064 }
12065
12066 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
12067 static OSErr
12068 init_mac_drag_n_drop ()
12069 {
12070 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
12071 return result;
12072 }
12073
12074 /* Intialize AppleEvent dispatcher table for the required events. */
12075 void
12076 init_required_apple_events ()
12077 {
12078 OSErr err;
12079 long result;
12080
12081 /* Make sure we have apple events before starting. */
12082 err = Gestalt (gestaltAppleEventsAttr, &result);
12083 if (err != noErr)
12084 abort ();
12085
12086 if (!(result & (1 << gestaltAppleEventsPresent)))
12087 abort ();
12088
12089 #if TARGET_API_MAC_CARBON
12090 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12091 NewAEEventHandlerUPP
12092 ((AEEventHandlerProcPtr) do_ae_open_application),
12093 0L, false);
12094 #else
12095 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12096 NewAEEventHandlerProc
12097 ((AEEventHandlerProcPtr) do_ae_open_application),
12098 0L, false);
12099 #endif
12100 if (err != noErr)
12101 abort ();
12102
12103 #if TARGET_API_MAC_CARBON
12104 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12105 NewAEEventHandlerUPP
12106 ((AEEventHandlerProcPtr) do_ae_open_documents),
12107 0L, false);
12108 #else
12109 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12110 NewAEEventHandlerProc
12111 ((AEEventHandlerProcPtr) do_ae_open_documents),
12112 0L, false);
12113 #endif
12114 if (err != noErr)
12115 abort ();
12116
12117 #if TARGET_API_MAC_CARBON
12118 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12119 NewAEEventHandlerUPP
12120 ((AEEventHandlerProcPtr) do_ae_print_documents),
12121 0L, false);
12122 #else
12123 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12124 NewAEEventHandlerProc
12125 ((AEEventHandlerProcPtr) do_ae_print_documents),
12126 0L, false);
12127 #endif
12128 if (err != noErr)
12129 abort ();
12130
12131 #if TARGET_API_MAC_CARBON
12132 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12133 NewAEEventHandlerUPP
12134 ((AEEventHandlerProcPtr) do_ae_quit_application),
12135 0L, false);
12136 #else
12137 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12138 NewAEEventHandlerProc
12139 ((AEEventHandlerProcPtr) do_ae_quit_application),
12140 0L, false);
12141 #endif
12142 if (err != noErr)
12143 abort ();
12144 }
12145
12146 #if USE_CARBON_EVENTS
12147
12148 void init_service_handler()
12149 {
12150 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
12151 {kEventClassService, kEventServiceCopy},
12152 {kEventClassService, kEventServicePaste}};
12153 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
12154 3, specs, NULL, NULL);
12155 }
12156
12157 /*
12158 MAC_TODO: Check to see if this is called by AEProcessDesc...
12159 */
12160 OSStatus mac_handle_service_event (EventHandlerCallRef callRef,
12161 EventRef event, void *data)
12162 {
12163 OSStatus err = noErr;
12164 switch (GetEventKind (event))
12165 {
12166 case kEventServiceGetTypes:
12167 {
12168 CFMutableArrayRef copyTypes, pasteTypes;
12169 CFStringRef type;
12170 Boolean selection = true;
12171 /*
12172 GetEventParameter(event, kEventParamServicePasteTypes,
12173 typeCFMutableArrayRef, NULL,
12174 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
12175 */
12176 GetEventParameter(event, kEventParamServiceCopyTypes,
12177 typeCFMutableArrayRef, NULL,
12178 sizeof (CFMutableArrayRef), NULL, &copyTypes);
12179 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
12180 if (type) {
12181 CFArrayAppendValue (copyTypes, type);
12182 //CFArrayAppendValue (pasteTypes, type);
12183 CFRelease (type);
12184 }
12185 }
12186 case kEventServiceCopy:
12187 {
12188 ScrapRef currentScrap, specificScrap;
12189 char * buf = "";
12190 Size byteCount = 0;
12191
12192 GetCurrentScrap (&currentScrap);
12193
12194 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
12195 if (err == noErr)
12196 {
12197 void *buffer = xmalloc (byteCount);
12198 if (buffer != NULL)
12199 {
12200 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
12201 sizeof (ScrapRef), NULL, &specificScrap);
12202
12203 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
12204 &byteCount, buffer);
12205 if (err == noErr)
12206 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
12207 kScrapFlavorMaskNone, byteCount, buffer);
12208 xfree (buffer);
12209 }
12210 }
12211 err = noErr;
12212 }
12213 case kEventServicePaste:
12214 {
12215 /*
12216 // Get the current location
12217 Size byteCount;
12218 ScrapRef specificScrap;
12219 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
12220 sizeof(ScrapRef), NULL, &specificScrap);
12221 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
12222 if (err == noErr) {
12223 void * buffer = xmalloc(byteCount);
12224 if (buffer != NULL ) {
12225 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
12226 &byteCount, buffer);
12227 if (err == noErr) {
12228 // Actually place in the buffer
12229 BLOCK_INPUT;
12230 // Get the current "selection" string here
12231 UNBLOCK_INPUT;
12232 }
12233 }
12234 xfree(buffer);
12235 }
12236 */
12237 }
12238 }
12239 return err;
12240 }
12241 #endif
12242
12243 /* Open Application Apple Event */
12244 static pascal OSErr
12245 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12246 {
12247 return noErr;
12248 }
12249
12250
12251 /* Defined in mac.c. */
12252 extern int
12253 path_from_vol_dir_name (char *, int, short, long, char *);
12254
12255
12256 /* Called when we receive an AppleEvent with an ID of
12257 "kAEOpenDocuments". This routine gets the direct parameter,
12258 extracts the FSSpecs in it, and puts their names on a list. */
12259 static pascal OSErr
12260 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12261 {
12262 OSErr err, err2;
12263 AEDesc the_desc;
12264 AEKeyword keyword;
12265 DescType actual_type;
12266 Size actual_size;
12267
12268 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12269 if (err != noErr)
12270 goto descriptor_error_exit;
12271
12272 /* Check to see that we got all of the required parameters from the
12273 event descriptor. For an 'odoc' event this should just be the
12274 file list. */
12275 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12276 &actual_type, (Ptr) &keyword,
12277 sizeof (keyword), &actual_size);
12278 /* No error means that we found some unused parameters.
12279 errAEDescNotFound means that there are no more parameters. If we
12280 get an error code other than that, flag it. */
12281 if ((err == noErr) || (err != errAEDescNotFound))
12282 {
12283 err = errAEEventNotHandled;
12284 goto error_exit;
12285 }
12286 err = noErr;
12287
12288 /* Got all the parameters we need. Now, go through the direct
12289 object list and parse it up. */
12290 {
12291 long num_files_to_open;
12292
12293 err = AECountItems (&the_desc, &num_files_to_open);
12294 if (err == noErr)
12295 {
12296 int i;
12297
12298 /* AE file list is one based so just use that for indexing here. */
12299 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
12300 {
12301 FSSpec fs;
12302 Str255 path_name, unix_path_name;
12303 #ifdef MAC_OSX
12304 FSRef fref;
12305 #endif
12306
12307 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12308 (Ptr) &fs, sizeof (fs), &actual_size);
12309 if (err != noErr) break;
12310
12311 #ifdef MAC_OSX
12312 err = FSpMakeFSRef (&fs, &fref);
12313 if (err != noErr) break;
12314
12315 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12316 #else
12317 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12318 fs.name) &&
12319 mac_to_posix_pathname (path_name, unix_path_name, 255))
12320 #endif
12321 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12322 drag_and_drop_file_list);
12323 }
12324 }
12325 }
12326
12327 error_exit:
12328 /* Nuke the coerced file list in any case */
12329 err2 = AEDisposeDesc(&the_desc);
12330
12331 descriptor_error_exit:
12332 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12333 return err;
12334 }
12335
12336
12337 static pascal OSErr mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
12338 DragReference theDrag)
12339 {
12340 short items;
12341 short index;
12342 FlavorFlags theFlags;
12343 Point mouse;
12344 OSErr result;
12345 ItemReference theItem;
12346 HFSFlavor data;
12347 FSRef fref;
12348 Size size = sizeof (HFSFlavor);
12349
12350 drag_and_drop_file_list = Qnil;
12351 GetDragMouse (theDrag, &mouse, 0L);
12352 CountDragItems (theDrag, &items);
12353 for (index = 1; index <= items; index++)
12354 {
12355 /* Only handle file references. */
12356 GetDragItemReferenceNumber (theDrag, index, &theItem);
12357 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
12358 if (result == noErr)
12359 {
12360 #ifdef MAC_OSX
12361 FSRef frref;
12362 #else
12363 Str255 path_name;
12364 #endif
12365 Str255 unix_path_name;
12366 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
12367 #ifdef MAC_OSX
12368 /* Use Carbon routines, otherwise it converts the file name
12369 to /Macintosh HD/..., which is not correct. */
12370 FSpMakeFSRef (&data.fileSpec, &fref);
12371 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
12372 #else
12373 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
12374 data.fileSpec.parID, data.fileSpec.name) &&
12375 mac_to_posix_pathname (path_name, unix_path_name, 255))
12376 #endif
12377 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12378 drag_and_drop_file_list);
12379 }
12380 else
12381 return;
12382 }
12383 /* If there are items in the list, construct an event and post it to
12384 the queue like an interrupt using kbd_buffer_store_event. */
12385 if (!NILP (drag_and_drop_file_list))
12386 {
12387 struct input_event event;
12388 Lisp_Object frame;
12389 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
12390 SetPort (GetWindowPort (window));
12391 GlobalToLocal (&mouse);
12392
12393 event.kind = DRAG_N_DROP_EVENT;
12394 event.code = 0;
12395 event.modifiers = 0;
12396 event.timestamp = TickCount () * (1000 / 60);
12397 XSETINT (event.x, mouse.h);
12398 XSETINT (event.y, mouse.v);
12399 XSETFRAME (frame, f);
12400 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
12401 event.arg = Qnil;
12402 /* Post to the interrupt queue */
12403 kbd_buffer_store_event (&event);
12404 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
12405 {
12406 ProcessSerialNumber psn;
12407 GetCurrentProcess (&psn);
12408 SetFrontProcess (&psn);
12409 }
12410 }
12411 }
12412
12413
12414 /* Print Document Apple Event */
12415 static pascal OSErr
12416 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12417 {
12418 return errAEEventNotHandled;
12419 }
12420
12421
12422 static pascal OSErr
12423 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12424 {
12425 /* FixMe: Do we need an unwind-protect or something here? And what
12426 do we do about unsaved files. Currently just forces quit rather
12427 than doing recursive callback to get user input. */
12428
12429 terminate_flag = true;
12430
12431 /* Fkill_emacs doesn't return. We have to return. (TI) */
12432 return noErr;
12433 }
12434
12435
12436 #if __profile__
12437 void
12438 profiler_exit_proc ()
12439 {
12440 ProfilerDump ("\pEmacs.prof");
12441 ProfilerTerm ();
12442 }
12443 #endif
12444
12445 /* These few functions implement Emacs as a normal Mac application
12446 (almost): set up the heap and the Toolbox, handle necessary
12447 system events plus a few simple menu events. They also set up
12448 Emacs's access to functions defined in the rest of this file.
12449 Emacs uses function hooks to perform all its terminal I/O. A
12450 complete list of these functions appear in termhooks.h. For what
12451 they do, read the comments there and see also w32term.c and
12452 xterm.c. What's noticeably missing here is the event loop, which
12453 is normally present in most Mac application. After performing the
12454 necessary Mac initializations, main passes off control to
12455 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12456 mac_read_socket (defined further below) to read input. This is
12457 where WaitNextEvent is called to process Mac events. This is also
12458 where check_alarm in sysdep.c is called to simulate alarm signals.
12459 This makes the cursor jump back to its correct position after
12460 briefly jumping to that of the matching parenthesis, print useful
12461 hints and prompts in the minibuffer after the user stops typing for
12462 a wait, etc. */
12463
12464 #if !TARGET_API_MAC_CARBON
12465 #undef main
12466 int
12467 main (void)
12468 {
12469 #if __profile__ /* is the profiler on? */
12470 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12471 exit(1);
12472 #endif
12473
12474 #if __MWERKS__
12475 /* set creator and type for files created by MSL */
12476 _fcreator = 'EMAx';
12477 _ftype = 'TEXT';
12478 #endif
12479
12480 do_init_managers ();
12481
12482 do_get_menus ();
12483
12484 do_check_ram_size ();
12485
12486 init_emacs_passwd_dir ();
12487
12488 init_environ ();
12489
12490 initialize_applescript ();
12491
12492 init_required_apple_events ();
12493
12494 {
12495 char **argv;
12496 int argc = 0;
12497
12498 /* set up argv array from STR# resource */
12499 get_string_list (&argv, ARGV_STRING_LIST_ID);
12500 while (argv[argc])
12501 argc++;
12502
12503 /* free up AppleScript resources on exit */
12504 atexit (terminate_applescript);
12505
12506 #if __profile__ /* is the profiler on? */
12507 atexit (profiler_exit_proc);
12508 #endif
12509
12510 /* 3rd param "envp" never used in emacs_main */
12511 (void) emacs_main (argc, argv, 0);
12512 }
12513
12514 /* Never reached - real exit in Fkill_emacs */
12515 return 0;
12516 }
12517 #endif
12518
12519 /* Table for translating Mac keycode to X keysym values. Contributed
12520 by Sudhir Shenoy. */
12521 static unsigned char keycode_to_xkeysym_table[] = {
12522 /* 0x00 - 0x3f */
12523 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12524 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12525 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12526 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12527 /* 0x40 */
12528 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12529 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12530 0, 0, 0, '\xaf' /* kp/ */,
12531 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
12532 /* 0x50 */
12533 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12534 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12535 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12536 '\xb9' /* kp9 */, 0, 0, 0,
12537 /* 0x60 */
12538 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12539 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12540 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12541 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
12542 /* 0x70 */
12543 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12544 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12545 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12546 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
12547 };
12548
12549 static int
12550 keycode_to_xkeysym (int keyCode, int *xKeySym)
12551 {
12552 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12553 return *xKeySym != 0;
12554 }
12555
12556 /* Emacs calls this whenever it wants to read an input event from the
12557 user. */
12558 int
12559 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12560 {
12561 int count = 0;
12562 #if USE_CARBON_EVENTS
12563 OSStatus rneResult;
12564 EventRef eventRef;
12565 EventMouseButton mouseBtn;
12566 #endif
12567 EventRecord er;
12568 int the_modifiers;
12569 EventMask event_mask;
12570
12571 #if 0
12572 if (interrupt_input_blocked)
12573 {
12574 interrupt_input_pending = 1;
12575 return -1;
12576 }
12577 #endif
12578
12579 interrupt_input_pending = 0;
12580 BLOCK_INPUT;
12581
12582 /* So people can tell when we have read the available input. */
12583 input_signal_count++;
12584
12585 if (numchars <= 0)
12586 abort ();
12587
12588 /* Don't poll for events to process (specifically updateEvt) if
12589 window update currently already in progress. A call to redisplay
12590 (in do_window_update) can be preempted by another call to
12591 redisplay, causing blank regions to be left on the screen and the
12592 cursor to be left at strange places. */
12593 if (handling_window_update)
12594 {
12595 UNBLOCK_INPUT;
12596 return 0;
12597 }
12598
12599 if (terminate_flag)
12600 Fkill_emacs (make_number (1));
12601
12602 /* It is necessary to set this (additional) argument slot of an
12603 event to nil because keyboard.c protects incompletely processed
12604 event from being garbage collected by placing them in the
12605 kbd_buffer_gcpro vector. */
12606 bufp->arg = Qnil;
12607
12608 event_mask = everyEvent;
12609 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
12610 event_mask -= highLevelEventMask;
12611
12612 #if USE_CARBON_EVENTS
12613 rneResult = ReceiveNextEvent (0, NULL,
12614 expected
12615 ? TicksToEventTime (app_sleep_time)
12616 : 0,
12617 true, &eventRef);
12618 if (!rneResult)
12619 {
12620 /* Handle new events */
12621 if (!mac_convert_event_ref (eventRef, &er))
12622 switch (GetEventClass (eventRef))
12623 {
12624 case kEventClassMouse:
12625 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
12626 {
12627 SInt32 delta;
12628 Point point;
12629 WindowPtr window_ptr = FrontWindow ();
12630 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12631 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
12632 typeSInt32, NULL, sizeof (SInt32),
12633 NULL, &delta);
12634 GetEventParameter(eventRef, kEventParamMouseLocation,
12635 typeQDPoint, NULL, sizeof (Point),
12636 NULL, &point);
12637 bufp->kind = MOUSE_WHEEL_EVENT;
12638 bufp->code = delta;
12639 bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
12640 SetPort (GetWindowPort (window_ptr));
12641 GlobalToLocal (&point);
12642 XSETINT (bufp->x, point.h);
12643 XSETINT (bufp->y, point.v);
12644 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12645 bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
12646 count++;
12647 }
12648 else
12649 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12650
12651 break;
12652 default:
12653 /* Send the event to the appropriate receiver. */
12654 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12655 }
12656 else
12657 #else
12658 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
12659 #endif /* USE_CARBON_EVENTS */
12660 switch (er.what)
12661 {
12662 case mouseDown:
12663 case mouseUp:
12664 {
12665 WindowPtr window_ptr = FrontWindow ();
12666 SInt16 part_code;
12667
12668 #if USE_CARBON_EVENTS
12669 /* This is needed to correctly */
12670 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12671 #endif
12672
12673 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12674 && er.what == mouseUp)
12675 {
12676 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12677 Point mouse_loc = er.where;
12678
12679 /* Convert to local coordinates of new window. */
12680 #if TARGET_API_MAC_CARBON
12681 SetPort (GetWindowPort (window_ptr));
12682 #else
12683 SetPort (window_ptr);
12684 #endif
12685
12686 GlobalToLocal (&mouse_loc);
12687
12688 #if USE_CARBON_EVENTS
12689 bufp->code = mac_get_mouse_btn (eventRef);
12690 #else
12691 bufp->code = 0; /* only one mouse button */
12692 #endif
12693 bufp->kind = SCROLL_BAR_CLICK_EVENT;
12694 bufp->frame_or_window = tracked_scroll_bar->window;
12695 bufp->part = scroll_bar_handle;
12696 #if USE_CARBON_EVENTS
12697 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12698 #else
12699 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12700 #endif
12701 bufp->modifiers |= up_modifier;
12702 bufp->timestamp = er.when * (1000 / 60);
12703 /* ticks to milliseconds */
12704
12705 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12706 XSETINT (bufp->y, mouse_loc.v - 24);
12707 tracked_scroll_bar->dragging = Qnil;
12708 mouse_tracking_in_progress = mouse_tracking_none;
12709 tracked_scroll_bar = NULL;
12710 count++;
12711 break;
12712 }
12713
12714 part_code = FindWindow (er.where, &window_ptr);
12715
12716 switch (part_code)
12717 {
12718 case inMenuBar:
12719 {
12720 struct frame *f = ((mac_output *)
12721 GetWRefCon (FrontWindow ()))->mFP;
12722 saved_menu_event_location = er.where;
12723 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
12724 XSETFRAME (bufp->frame_or_window, f);
12725 count++;
12726 }
12727 break;
12728
12729 case inContent:
12730 if (window_ptr != FrontWindow ())
12731 SelectWindow (window_ptr);
12732 else
12733 {
12734 SInt16 control_part_code;
12735 ControlHandle ch;
12736 struct mac_output *mwp = (mac_output *)
12737 GetWRefCon (window_ptr);
12738 Point mouse_loc = er.where;
12739
12740 /* convert to local coordinates of new window */
12741 #if TARGET_API_MAC_CARBON
12742 SetPort (GetWindowPort (window_ptr));
12743 #else
12744 SetPort (window_ptr);
12745 #endif
12746
12747 GlobalToLocal (&mouse_loc);
12748 #if TARGET_API_MAC_CARBON
12749 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12750 &control_part_code);
12751 #else
12752 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
12753 #endif
12754
12755 #if USE_CARBON_EVENTS
12756 bufp->code = mac_get_mouse_btn (eventRef);
12757 #else
12758 bufp->code = 0; /* only one mouse button */
12759 #endif
12760 XSETINT (bufp->x, mouse_loc.h);
12761 XSETINT (bufp->y, mouse_loc.v);
12762 bufp->timestamp = er.when * (1000 / 60);
12763 /* ticks to milliseconds */
12764
12765 #if TARGET_API_MAC_CARBON
12766 if (ch != 0)
12767 #else
12768 if (control_part_code != 0)
12769 #endif
12770 {
12771 struct scroll_bar *bar = (struct scroll_bar *)
12772 GetControlReference (ch);
12773 x_scroll_bar_handle_click (bar, control_part_code, &er,
12774 bufp);
12775 if (er.what == mouseDown
12776 && control_part_code == kControlIndicatorPart)
12777 {
12778 mouse_tracking_in_progress
12779 = mouse_tracking_scroll_bar;
12780 tracked_scroll_bar = bar;
12781 }
12782 else
12783 {
12784 mouse_tracking_in_progress = mouse_tracking_none;
12785 tracked_scroll_bar = NULL;
12786 }
12787 }
12788 else
12789 {
12790 bufp->kind = MOUSE_CLICK_EVENT;
12791 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12792 if (er.what == mouseDown)
12793 mouse_tracking_in_progress
12794 = mouse_tracking_mouse_movement;
12795 else
12796 mouse_tracking_in_progress = mouse_tracking_none;
12797 }
12798
12799 #if USE_CARBON_EVENTS
12800 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12801 #else
12802 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12803 #endif
12804
12805 switch (er.what)
12806 {
12807 case mouseDown:
12808 bufp->modifiers |= down_modifier;
12809 break;
12810 case mouseUp:
12811 bufp->modifiers |= up_modifier;
12812 break;
12813 }
12814
12815 count++;
12816 }
12817 break;
12818
12819 case inDrag:
12820 #if TARGET_API_MAC_CARBON
12821 {
12822 BitMap bm;
12823
12824 GetQDGlobalsScreenBits (&bm);
12825 DragWindow (window_ptr, er.where, &bm.bounds);
12826 }
12827 #else /* not TARGET_API_MAC_CARBON */
12828 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12829 #endif /* not TARGET_API_MAC_CARBON */
12830 break;
12831
12832 case inGoAway:
12833 if (TrackGoAway (window_ptr, er.where))
12834 {
12835 bufp->kind = DELETE_WINDOW_EVENT;
12836 XSETFRAME (bufp->frame_or_window,
12837 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12838 count++;
12839 }
12840 break;
12841
12842 /* window resize handling added --ben */
12843 case inGrow:
12844 do_grow_window(window_ptr, &er);
12845 break;
12846
12847 /* window zoom handling added --ben */
12848 case inZoomIn:
12849 case inZoomOut:
12850 if (TrackBox (window_ptr, er.where, part_code))
12851 do_zoom_window (window_ptr, part_code);
12852 break;
12853
12854 default:
12855 break;
12856 }
12857 }
12858 break;
12859
12860 case updateEvt:
12861 case osEvt:
12862 case activateEvt:
12863 #if USE_CARBON_EVENTS
12864 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12865 #endif
12866 do_events (&er);
12867 break;
12868
12869 case keyDown:
12870 case autoKey:
12871 {
12872 int keycode = (er.message & keyCodeMask) >> 8;
12873 int xkeysym;
12874
12875 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
12876 {
12877 SysBeep (1);
12878 UNBLOCK_INPUT;
12879 return 0;
12880 }
12881
12882 ObscureCursor ();
12883
12884 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12885 {
12886 bufp->code = 0x7f;
12887 bufp->kind = ASCII_KEYSTROKE_EVENT;
12888 }
12889 else if (keycode_to_xkeysym (keycode, &xkeysym))
12890 {
12891 bufp->code = 0xff00 | xkeysym;
12892 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
12893 }
12894 else if (!NILP (Vmac_reverse_ctrl_meta) && (er.modifiers & controlKey))
12895 {
12896 /* This is a special case to deal with converting from
12897 a control character to non-control character */
12898 int new_modifiers = er.modifiers & ~controlKey;
12899 int new_keycode = keycode | new_modifiers;
12900 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12901 unsigned long some_state = 0;
12902 bufp->code = KeyTranslate (kchr_ptr, new_keycode, &some_state) & 0xff;
12903 bufp->kind = ASCII_KEYSTROKE_EVENT;
12904 }
12905 else
12906 {
12907 if (er.modifiers & macMetaKey)
12908 {
12909 /* This code comes from Keyboard Resource, Appendix
12910 C of IM - Text. This is necessary since shift is
12911 ignored in KCHR table translation when option or
12912 command is pressed. */
12913 int new_modifiers = er.modifiers & 0xf600;
12914 /* mask off option and command */
12915 int new_keycode = keycode | new_modifiers;
12916 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12917 unsigned long some_state = 0;
12918 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12919 &some_state) & 0xff;
12920 }
12921 #if USE_CARBON_EVENTS
12922 else if (er.modifiers & cmdKey &&
12923 (NILP (Vmac_command_key_is_meta)))
12924 {
12925 /* If this is a command key (and we are not overriding it),
12926 send back to the operating system */
12927 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12928 break;
12929 }
12930 #endif
12931 else
12932 bufp->code = er.message & charCodeMask;
12933 bufp->kind = ASCII_KEYSTROKE_EVENT;
12934 }
12935 }
12936
12937 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12938 convert non-ASCII characters typed at the Mac keyboard
12939 (presumed to be in the Mac Roman encoding) to iso-latin-1
12940 encoding before they are passed to Emacs. This enables the
12941 Mac keyboard to be used to enter non-ASCII iso-latin-1
12942 characters directly. */
12943 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12944 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
12945 {
12946 static TECObjectRef converter = NULL;
12947 OSStatus the_err = noErr;
12948 OSStatus convert_status = noErr;
12949
12950 if (converter == NULL)
12951 {
12952 the_err = TECCreateConverter (&converter,
12953 kTextEncodingMacRoman,
12954 mac_keyboard_text_encoding);
12955 current_mac_keyboard_text_encoding
12956 = mac_keyboard_text_encoding;
12957 }
12958 else if (mac_keyboard_text_encoding
12959 != current_mac_keyboard_text_encoding)
12960 {
12961 /* Free the converter for the current encoding before
12962 creating a new one. */
12963 TECDisposeConverter (converter);
12964 the_err = TECCreateConverter (&converter,
12965 kTextEncodingMacRoman,
12966 mac_keyboard_text_encoding);
12967 current_mac_keyboard_text_encoding
12968 = mac_keyboard_text_encoding;
12969 }
12970
12971 if (the_err == noErr)
12972 {
12973 unsigned char ch = bufp->code;
12974 ByteCount actual_input_length, actual_output_length;
12975 unsigned char outch;
12976
12977 convert_status = TECConvertText (converter, &ch, 1,
12978 &actual_input_length,
12979 &outch, 1,
12980 &actual_output_length);
12981 if (convert_status == noErr
12982 && actual_input_length == 1
12983 && actual_output_length == 1)
12984 bufp->code = outch;
12985 }
12986 }
12987
12988 #if USE_CARBON_EVENTS
12989 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12990 #else
12991 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12992 #endif
12993
12994 {
12995 mac_output *mwp
12996 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
12997 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12998 }
12999
13000 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
13001
13002 count++;
13003 break;
13004
13005 case kHighLevelEvent:
13006 drag_and_drop_file_list = Qnil;
13007
13008 AEProcessAppleEvent(&er);
13009
13010 /* Build a DRAG_N_DROP_EVENT type event as is done in
13011 constuct_drag_n_drop in w32term.c. */
13012 if (!NILP (drag_and_drop_file_list))
13013 {
13014 struct frame *f;
13015 WindowPtr wp;
13016 Lisp_Object frame;
13017
13018 wp = FrontWindow ();
13019 if (!wp)
13020 f = NULL;
13021 else
13022 f = ((mac_output *) GetWRefCon (wp))->mFP;
13023
13024 bufp->kind = DRAG_N_DROP_EVENT;
13025 bufp->code = 0;
13026 bufp->timestamp = er.when * (1000 / 60);
13027 /* ticks to milliseconds */
13028 #if USE_CARBON_EVENTS
13029 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13030 #else
13031 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13032 #endif
13033
13034 XSETINT (bufp->x, 0);
13035 XSETINT (bufp->y, 0);
13036
13037 XSETFRAME (frame, f);
13038 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
13039
13040 /* Regardless of whether Emacs was suspended or in the
13041 foreground, ask it to redraw its entire screen.
13042 Otherwise parts of the screen can be left in an
13043 inconsistent state. */
13044 if (wp)
13045 #if TARGET_API_MAC_CARBON
13046 {
13047 Rect r;
13048
13049 GetWindowPortBounds (wp, &r);
13050 InvalWindowRect (wp, &r);
13051 }
13052 #else /* not TARGET_API_MAC_CARBON */
13053 InvalRect (&(wp->portRect));
13054 #endif /* not TARGET_API_MAC_CARBON */
13055
13056 count++;
13057 }
13058 default:
13059 break;
13060 }
13061 #if USE_CARBON_EVENTS
13062 ReleaseEvent (eventRef);
13063 }
13064 #endif
13065
13066 /* If the focus was just given to an autoraising frame,
13067 raise it now. */
13068 /* ??? This ought to be able to handle more than one such frame. */
13069 if (pending_autoraise_frame)
13070 {
13071 x_raise_frame (pending_autoraise_frame);
13072 pending_autoraise_frame = 0;
13073 }
13074
13075 #if !TARGET_API_MAC_CARBON
13076 check_alarm (); /* simulate the handling of a SIGALRM */
13077 #endif
13078
13079 {
13080 static Point old_mouse_pos = { -1, -1 };
13081
13082 if (app_is_suspended)
13083 {
13084 old_mouse_pos.h = -1;
13085 old_mouse_pos.v = -1;
13086 }
13087 else
13088 {
13089 Point mouse_pos;
13090 WindowPtr wp;
13091 struct frame *f;
13092 Lisp_Object bar;
13093 struct scroll_bar *sb;
13094
13095 wp = FrontWindow ();
13096 if (is_emacs_window (wp))
13097 {
13098 f = ((mac_output *) GetWRefCon (wp))->mFP;
13099
13100 #if TARGET_API_MAC_CARBON
13101 SetPort (GetWindowPort (wp));
13102 #else
13103 SetPort (wp);
13104 #endif
13105
13106 GetMouse (&mouse_pos);
13107
13108 if (!EqualPt (mouse_pos, old_mouse_pos))
13109 {
13110 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
13111 && tracked_scroll_bar)
13112 x_scroll_bar_note_movement (tracked_scroll_bar,
13113 mouse_pos.v
13114 - XINT (tracked_scroll_bar->top),
13115 TickCount() * (1000 / 60));
13116 else
13117 note_mouse_movement (f, &mouse_pos);
13118
13119 old_mouse_pos = mouse_pos;
13120 }
13121 }
13122 }
13123 }
13124
13125 UNBLOCK_INPUT;
13126
13127 return count;
13128 }
13129
13130
13131 /* Need to override CodeWarrior's input function so no conversion is
13132 done on newlines Otherwise compiled functions in .elc files will be
13133 read incorrectly. Defined in ...:MSL C:MSL
13134 Common:Source:buffer_io.c. */
13135 #ifdef __MWERKS__
13136 void
13137 __convert_to_newlines (unsigned char * p, size_t * n)
13138 {
13139 #pragma unused(p,n)
13140 }
13141
13142 void
13143 __convert_from_newlines (unsigned char * p, size_t * n)
13144 {
13145 #pragma unused(p,n)
13146 }
13147 #endif
13148
13149
13150 /* Initialize the struct pointed to by MW to represent a new COLS x
13151 ROWS Macintosh window, using font with name FONTNAME and size
13152 FONTSIZE. */
13153 void
13154 NewMacWindow (FRAME_PTR fp)
13155 {
13156 mac_output *mwp;
13157 #if TARGET_API_MAC_CARBON
13158 static int making_terminal_window = 0;
13159 #else
13160 static int making_terminal_window = 1;
13161 #endif
13162
13163 mwp = fp->output_data.mac;
13164
13165 if (making_terminal_window)
13166 {
13167 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
13168 (WindowPtr) -1)))
13169 abort ();
13170 making_terminal_window = 0;
13171 }
13172 else
13173 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
13174 abort ();
13175
13176 SetWRefCon (mwp->mWP, (long) mwp);
13177 /* so that update events can find this mac_output struct */
13178 mwp->mFP = fp; /* point back to emacs frame */
13179
13180 #if TARGET_API_MAC_CARBON
13181 SetPort (GetWindowPort (mwp->mWP));
13182 #else
13183 SetPort (mwp->mWP);
13184 #endif
13185
13186 mwp->fontset = -1;
13187
13188 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
13189 ShowWindow (mwp->mWP);
13190
13191 }
13192
13193
13194 void make_mac_frame (struct frame *f)
13195 {
13196 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
13197 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
13198
13199 NewMacWindow(f);
13200
13201 f->output_data.mac->cursor_pixel = 0;
13202 f->output_data.mac->border_pixel = 0x00ff00;
13203 f->output_data.mac->mouse_pixel = 0xff00ff;
13204 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
13205
13206 f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
13207
13208 f->output_data.mac->fontset = -1;
13209 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13210 f->output_data.mac->scroll_bar_background_pixel = -1;
13211 f->output_data.mac->left_pos = 4;
13212 f->output_data.mac->top_pos = 4;
13213 f->output_data.mac->border_width = 0;
13214 f->output_data.mac->explicit_parent = 0;
13215
13216 f->output_data.mac->internal_border_width = 0;
13217
13218 f->output_method = output_mac;
13219
13220 f->auto_raise = 1;
13221 f->auto_lower = 1;
13222
13223 f->new_width = 0;
13224 f->new_height = 0;
13225 }
13226
13227 void make_mac_terminal_frame (struct frame *f)
13228 {
13229 Lisp_Object frame;
13230
13231 XSETFRAME (frame, f);
13232
13233 f->output_method = output_mac;
13234 f->output_data.mac = (struct mac_output *)
13235 xmalloc (sizeof (struct mac_output));
13236 bzero (f->output_data.mac, sizeof (struct mac_output));
13237 f->output_data.mac->fontset = -1;
13238 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13239 f->output_data.mac->scroll_bar_background_pixel = -1;
13240
13241 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
13242
13243 f->width = 96;
13244 f->height = 4;
13245
13246 make_mac_frame (f);
13247
13248 x_make_gc (f);
13249
13250 /* Need to be initialized for unshow_buffer in window.c. */
13251 selected_window = f->selected_window;
13252
13253 Fmodify_frame_parameters (frame,
13254 Fcons (Fcons (Qfont,
13255 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
13256 Fmodify_frame_parameters (frame,
13257 Fcons (Fcons (Qforeground_color,
13258 build_string ("black")), Qnil));
13259 Fmodify_frame_parameters (frame,
13260 Fcons (Fcons (Qbackground_color,
13261 build_string ("white")), Qnil));
13262 }
13263
13264 \f
13265 /***********************************************************************
13266 Initialization
13267 ***********************************************************************/
13268
13269 #ifdef USE_X_TOOLKIT
13270 static XrmOptionDescRec emacs_options[] = {
13271 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13272 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13273
13274 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13275 XrmoptionSepArg, NULL},
13276 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13277
13278 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13279 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13280 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13281 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13282 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13283 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13284 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13285 };
13286 #endif /* USE_X_TOOLKIT */
13287
13288 #ifdef MULTI_KBOARD
13289 /* Test whether two display-name strings agree up to the dot that separates
13290 the screen number from the server number. */
13291 static int
13292 same_x_server (name1, name2)
13293 char *name1, *name2;
13294 {
13295 int seen_colon = 0;
13296 unsigned char *system_name = SDATA (Vsystem_name);
13297 int system_name_length = strlen (system_name);
13298 int length_until_period = 0;
13299
13300 while (system_name[length_until_period] != 0
13301 && system_name[length_until_period] != '.')
13302 length_until_period++;
13303
13304 /* Treat `unix' like an empty host name. */
13305 if (! strncmp (name1, "unix:", 5))
13306 name1 += 4;
13307 if (! strncmp (name2, "unix:", 5))
13308 name2 += 4;
13309 /* Treat this host's name like an empty host name. */
13310 if (! strncmp (name1, system_name, system_name_length)
13311 && name1[system_name_length] == ':')
13312 name1 += system_name_length;
13313 if (! strncmp (name2, system_name, system_name_length)
13314 && name2[system_name_length] == ':')
13315 name2 += system_name_length;
13316 /* Treat this host's domainless name like an empty host name. */
13317 if (! strncmp (name1, system_name, length_until_period)
13318 && name1[length_until_period] == ':')
13319 name1 += length_until_period;
13320 if (! strncmp (name2, system_name, length_until_period)
13321 && name2[length_until_period] == ':')
13322 name2 += length_until_period;
13323
13324 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13325 {
13326 if (*name1 == ':')
13327 seen_colon++;
13328 if (seen_colon && *name1 == '.')
13329 return 1;
13330 }
13331 return (seen_colon
13332 && (*name1 == '.' || *name1 == '\0')
13333 && (*name2 == '.' || *name2 == '\0'));
13334 }
13335 #endif
13336
13337 int mac_initialized = 0;
13338
13339 void
13340 mac_initialize_display_info ()
13341 {
13342 struct mac_display_info *dpyinfo = &one_mac_display_info;
13343 GDHandle main_device_handle;
13344
13345 bzero (dpyinfo, sizeof (*dpyinfo));
13346
13347 /* Put it on x_display_name_list. */
13348 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13349 x_display_name_list);
13350 dpyinfo->name_list_element = XCAR (x_display_name_list);
13351
13352 #if 0
13353 dpyinfo->mac_id_name
13354 = (char *) xmalloc (SCHARS (Vinvocation_name)
13355 + SCHARS (Vsystem_name)
13356 + 2);
13357 sprintf (dpyinfo->mac_id_name, "%s@%s",
13358 SDATA (Vinvocation_name), SDATA (Vsystem_name));
13359 #else
13360 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13361 strcpy (dpyinfo->mac_id_name, "Mac Display");
13362 #endif
13363
13364 main_device_handle = LMGetMainDevice();
13365
13366 dpyinfo->reference_count = 0;
13367 dpyinfo->resx = 75.0;
13368 dpyinfo->resy = 75.0;
13369 dpyinfo->n_planes = 1;
13370 dpyinfo->n_cbits = 16;
13371 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13372 dpyinfo->width = (**main_device_handle).gdRect.right;
13373 dpyinfo->grabbed = 0;
13374 dpyinfo->root_window = NULL;
13375
13376 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13377 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13378 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13379 dpyinfo->mouse_face_window = Qnil;
13380 }
13381
13382 struct mac_display_info *
13383 mac_term_init (display_name, xrm_option, resource_name)
13384 Lisp_Object display_name;
13385 char *xrm_option;
13386 char *resource_name;
13387 {
13388 struct mac_display_info *dpyinfo;
13389 GDHandle main_device_handle;
13390
13391 if (!mac_initialized)
13392 {
13393 mac_initialize ();
13394 mac_initialized = 1;
13395 }
13396
13397 mac_initialize_display_info (display_name);
13398
13399 dpyinfo = &one_mac_display_info;
13400
13401 main_device_handle = LMGetMainDevice();
13402
13403 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13404 dpyinfo->width = (**main_device_handle).gdRect.right;
13405
13406 return dpyinfo;
13407 }
13408 \f
13409 #ifdef MAC_OSX
13410 void MakeMeTheFrontProcess ()
13411 {
13412 ProcessSerialNumber psn;
13413 OSErr err;
13414
13415 err = GetCurrentProcess (&psn);
13416 if (err == noErr)
13417 (void) SetFrontProcess (&psn);
13418 }
13419 #endif /* MAC_OSX */
13420
13421 /* Set up use of X before we make the first connection. */
13422
13423 static struct redisplay_interface x_redisplay_interface =
13424 {
13425 x_produce_glyphs,
13426 x_write_glyphs,
13427 x_insert_glyphs,
13428 x_clear_end_of_line,
13429 x_scroll_run,
13430 x_after_update_window_line,
13431 x_update_window_begin,
13432 x_update_window_end,
13433 XTcursor_to,
13434 x_flush,
13435 x_clear_mouse_face,
13436 x_get_glyph_overhangs,
13437 x_fix_overlapping_area
13438 };
13439
13440 void
13441 mac_initialize ()
13442 {
13443 rif = &x_redisplay_interface;
13444
13445 clear_frame_hook = x_clear_frame;
13446 ins_del_lines_hook = x_ins_del_lines;
13447 delete_glyphs_hook = x_delete_glyphs;
13448 ring_bell_hook = XTring_bell;
13449 reset_terminal_modes_hook = XTreset_terminal_modes;
13450 set_terminal_modes_hook = XTset_terminal_modes;
13451 update_begin_hook = x_update_begin;
13452 update_end_hook = x_update_end;
13453 set_terminal_window_hook = XTset_terminal_window;
13454 read_socket_hook = XTread_socket;
13455 frame_up_to_date_hook = XTframe_up_to_date;
13456 mouse_position_hook = XTmouse_position;
13457 frame_rehighlight_hook = XTframe_rehighlight;
13458 frame_raise_lower_hook = XTframe_raise_lower;
13459
13460 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13461 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13462 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13463 judge_scroll_bars_hook = XTjudge_scroll_bars;
13464
13465 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13466
13467 scroll_region_ok = 1; /* we'll scroll partial frames */
13468 char_ins_del_ok = 1;
13469 line_ins_del_ok = 1; /* we'll just blt 'em */
13470 fast_clear_end_of_line = 1; /* X does this well */
13471 memory_below_frame = 0; /* we don't remember what scrolls
13472 off the bottom */
13473 baud_rate = 19200;
13474
13475 x_noop_count = 0;
13476 last_tool_bar_item = -1;
13477 any_help_event_p = 0;
13478
13479 /* Try to use interrupt input; if we can't, then start polling. */
13480 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13481
13482 #ifdef USE_X_TOOLKIT
13483 XtToolkitInitialize ();
13484 Xt_app_con = XtCreateApplicationContext ();
13485 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13486
13487 /* Install an asynchronous timer that processes Xt timeout events
13488 every 0.1s. This is necessary because some widget sets use
13489 timeouts internally, for example the LessTif menu bar, or the
13490 Xaw3d scroll bar. When Xt timouts aren't processed, these
13491 widgets don't behave normally. */
13492 {
13493 EMACS_TIME interval;
13494 EMACS_SET_SECS_USECS (interval, 0, 100000);
13495 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13496 }
13497 #endif
13498
13499 #if USE_TOOLKIT_SCROLL_BARS
13500 xaw3d_arrow_scroll = False;
13501 xaw3d_pick_top = True;
13502 #endif
13503
13504 #if 0
13505 /* Note that there is no real way portable across R3/R4 to get the
13506 original error handler. */
13507 XSetErrorHandler (x_error_handler);
13508 XSetIOErrorHandler (x_io_error_quitter);
13509
13510 /* Disable Window Change signals; they are handled by X events. */
13511 #ifdef SIGWINCH
13512 signal (SIGWINCH, SIG_DFL);
13513 #endif /* ! defined (SIGWINCH) */
13514
13515 signal (SIGPIPE, x_connection_signal);
13516 #endif
13517
13518 mac_initialize_display_info ();
13519
13520 #if TARGET_API_MAC_CARBON
13521 init_required_apple_events ();
13522
13523 init_mac_drag_n_drop ();
13524
13525 #if USE_CARBON_EVENTS
13526 init_service_handler ();
13527 #endif
13528
13529 DisableMenuCommand (NULL, kHICommandQuit);
13530
13531 if (!inhibit_window_system)
13532 MakeMeTheFrontProcess ();
13533 #endif
13534 }
13535
13536
13537 void
13538 syms_of_macterm ()
13539 {
13540 #if 0
13541 staticpro (&x_error_message_string);
13542 x_error_message_string = Qnil;
13543 #endif
13544
13545 staticpro (&x_display_name_list);
13546 x_display_name_list = Qnil;
13547
13548 staticpro (&last_mouse_scroll_bar);
13549 last_mouse_scroll_bar = Qnil;
13550
13551 staticpro (&Qvendor_specific_keysyms);
13552 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13553
13554 staticpro (&last_mouse_press_frame);
13555 last_mouse_press_frame = Qnil;
13556
13557 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13558 staticpro (&Qmac_ready_for_drag_n_drop);
13559
13560 help_echo = Qnil;
13561 staticpro (&help_echo);
13562 help_echo_object = Qnil;
13563 staticpro (&help_echo_object);
13564 help_echo_window = Qnil;
13565 staticpro (&help_echo_window);
13566 previous_help_echo = Qnil;
13567 staticpro (&previous_help_echo);
13568 help_echo_pos = -1;
13569
13570 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13571 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13572 x_autoselect_window_p = 0;
13573
13574 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13575 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13576 For example, if a block cursor is over a tab, it will be drawn as
13577 wide as that tab on the display. */);
13578 x_stretch_cursor_p = 0;
13579
13580 #if 0 /* TODO: Setting underline position from font properties. */
13581 DEFVAR_BOOL ("x-use-underline-position-properties",
13582 &x_use_underline_position_properties,
13583 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13584 nil means ignore them. If you encounter fonts with bogus
13585 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13586 to 4.1, set this to nil. */);
13587 x_use_underline_position_properties = 1;
13588 #endif
13589
13590 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13591 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13592 Vx_toolkit_scroll_bars = Qt;
13593
13594 staticpro (&last_mouse_motion_frame);
13595 last_mouse_motion_frame = Qnil;
13596
13597 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
13598 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13599 Otherwise the option key is used. */);
13600 Vmac_command_key_is_meta = Qt;
13601
13602 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
13603 doc: /* Non-nil means that the control and meta keys are reversed. This is
13604 useful for non-standard keyboard layouts. */);
13605 Vmac_reverse_ctrl_meta = Qnil;
13606
13607 #if USE_CARBON_EVENTS
13608 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
13609 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
13610 the right click will be mouse-3.
13611 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
13612 Vmac_wheel_button_is_mouse_2 = Qt;
13613 #endif
13614
13615 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
13616 doc: /* One of the Text Encoding Base constant values defined in the
13617 Basic Text Constants section of Inside Macintosh - Text Encoding
13618 Conversion Manager. Its value determines the encoding characters
13619 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13620 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13621 its default value, no conversion takes place. If it is set to
13622 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13623 characters typed on Mac keyboard are first converted into the
13624 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13625 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13626 command, this enables the Mac keyboard to be used to enter non-ASCII
13627 characters directly. */);
13628 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13629 }