]> code.delx.au - gnu-emacs/blob - src/macterm.c
In src:
[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
370 #if __MRC__
371 QDGlobals qd; /* QuickDraw global information structure. */
372 #endif
373
374
375 /* Enumeration for overriding/changing the face to use for drawing
376 glyphs in x_draw_glyphs. */
377
378 enum draw_glyphs_face
379 {
380 DRAW_NORMAL_TEXT,
381 DRAW_INVERSE_VIDEO,
382 DRAW_CURSOR,
383 DRAW_MOUSE_FACE,
384 DRAW_IMAGE_RAISED,
385 DRAW_IMAGE_SUNKEN
386 };
387
388 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
389 struct mac_display_info *mac_display_info_for_display (Display *);
390 static void x_update_window_end P_ ((struct window *, int, int));
391 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
392 static int fast_find_position P_ ((struct window *, int, int *, int *,
393 int *, int *, Lisp_Object));
394 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
395 int *, int *, int *, int *, int));
396 static void set_output_cursor P_ ((struct cursor_pos *));
397 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
398 int *, int *, int *, int));
399 static void note_mode_line_highlight P_ ((struct window *, int, int));
400 static void note_mouse_highlight P_ ((struct frame *, int, int));
401 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
402 static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
403 static void show_mouse_face P_ ((struct x_display_info *,
404 enum draw_glyphs_face));
405 static int cursor_in_mouse_face_p P_ ((struct window *));
406 static int clear_mouse_face P_ ((struct mac_display_info *));
407 static int x_io_error_quitter P_ ((Display *));
408 int x_catch_errors P_ ((Display *));
409 void x_uncatch_errors P_ ((Display *, int));
410 void x_lower_frame P_ ((struct frame *));
411 void x_scroll_bar_clear P_ ((struct frame *));
412 int x_had_errors_p P_ ((Display *));
413 void x_wm_set_size_hint P_ ((struct frame *, long, int));
414 void x_raise_frame P_ ((struct frame *));
415 void x_set_window_size P_ ((struct frame *, int, int, int));
416 void x_wm_set_window_state P_ ((struct frame *, int));
417 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
418 void mac_initialize P_ ((void));
419 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
420 static int x_compute_min_glyph_bounds P_ ((struct frame *));
421 enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
422 static void x_draw_phys_cursor_glyph P_ ((struct window *,
423 struct glyph_row *,
424 enum draw_glyphs_face));
425 static void x_update_end P_ ((struct frame *));
426 static void XTframe_up_to_date P_ ((struct frame *));
427 static void XTreassert_line_highlight P_ ((int, int));
428 static void x_change_line_highlight P_ ((int, int, int, int));
429 static void XTset_terminal_modes P_ ((void));
430 static void XTreset_terminal_modes P_ ((void));
431 static void XTcursor_to P_ ((int, int, int, int));
432 static void x_write_glyphs P_ ((struct glyph *, int));
433 static void x_clear_end_of_line P_ ((int));
434 static void x_clear_frame P_ ((void));
435 static void x_clear_cursor P_ ((struct window *));
436 static void frame_highlight P_ ((struct frame *));
437 static void frame_unhighlight P_ ((struct frame *));
438 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
439 static void XTframe_rehighlight P_ ((struct frame *));
440 static void x_frame_rehighlight P_ ((struct x_display_info *));
441 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
442 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
443 static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
444 static void expose_frame P_ ((struct frame *, int, int, int, int));
445 static int expose_window_tree P_ ((struct window *, Rect *));
446 static int expose_window P_ ((struct window *, Rect *));
447 static void expose_area P_ ((struct window *, struct glyph_row *,
448 Rect *, enum glyph_row_area));
449 static int expose_line P_ ((struct window *, struct glyph_row *,
450 Rect *));
451 void x_display_cursor (struct window *, int, int, int, int, int);
452 void x_update_cursor P_ ((struct frame *, int));
453 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
454 static void x_update_window_cursor P_ ((struct window *, int));
455 static void x_erase_phys_cursor P_ ((struct window *));
456 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
457 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
458 enum fringe_bitmap_type, int left_p));
459 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
460 GC, int));
461 static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
462 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
463 static void notice_overwritten_cursor P_ ((struct window *,
464 enum glyph_row_area,
465 int, int, int, int));
466 static void x_flush P_ ((struct frame *f));
467 static void x_update_begin P_ ((struct frame *));
468 static void x_update_window_begin P_ ((struct window *));
469 static void x_draw_vertical_border P_ ((struct window *));
470 static void x_after_update_window_line P_ ((struct glyph_row *));
471 static INLINE void take_vertical_position_into_account P_ ((struct it *));
472 static void x_produce_stretch_glyph P_ ((struct it *));
473
474 static void activate_scroll_bars (FRAME_PTR);
475 static void deactivate_scroll_bars (FRAME_PTR);
476
477 extern int image_ascent (struct image *, struct face *);
478 void x_set_offset (struct frame *, int, int, int);
479 int x_bitmap_icon (struct frame *, Lisp_Object);
480 void x_make_frame_visible (struct frame *);
481
482 extern void window_scroll (Lisp_Object, int, int, int);
483
484 /* Defined in macmenu.h. */
485 extern void menubar_selection_callback (FRAME_PTR, int);
486 extern void set_frame_menubar (FRAME_PTR, int, int);
487
488 /* X display function emulation */
489
490 /* Structure borrowed from Xlib.h to represent two-byte characters in
491 dumpglyphs. */
492
493 typedef struct {
494 unsigned char byte1;
495 unsigned char byte2;
496 } XChar2b;
497
498 static void
499 XFreePixmap (display, pixmap)
500 Display *display;
501 Pixmap pixmap;
502 {
503 PixMap *p = (PixMap *) pixmap;
504
505 xfree (p->baseAddr);
506 xfree (p);
507 }
508
509
510 /* Set foreground color for subsequent QuickDraw commands. Assume
511 graphic port has already been set. */
512
513 static void
514 mac_set_forecolor (unsigned long color)
515 {
516 RGBColor fg_color;
517
518 fg_color.red = RED_FROM_ULONG (color) * 256;
519 fg_color.green = GREEN_FROM_ULONG (color) * 256;
520 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
521
522 RGBForeColor (&fg_color);
523 }
524
525
526 /* Set background color for subsequent QuickDraw commands. Assume
527 graphic port has already been set. */
528
529 static void
530 mac_set_backcolor (unsigned long color)
531 {
532 RGBColor bg_color;
533
534 bg_color.red = RED_FROM_ULONG (color) * 256;
535 bg_color.green = GREEN_FROM_ULONG (color) * 256;
536 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
537
538 RGBBackColor (&bg_color);
539 }
540
541 /* Set foreground and background color for subsequent QuickDraw
542 commands. Assume that the graphic port has already been set. */
543
544 static void
545 mac_set_colors (GC gc)
546 {
547 mac_set_forecolor (gc->foreground);
548 mac_set_backcolor (gc->background);
549 }
550
551 /* Mac version of XDrawLine. */
552
553 static void
554 XDrawLine (display, w, gc, x1, y1, x2, y2)
555 Display *display;
556 WindowPtr w;
557 GC gc;
558 int x1, y1, x2, y2;
559 {
560 #if TARGET_API_MAC_CARBON
561 SetPort (GetWindowPort (w));
562 #else
563 SetPort (w);
564 #endif
565
566 mac_set_colors (gc);
567
568 MoveTo (x1, y1);
569 LineTo (x2, y2);
570 }
571
572 /* Mac version of XClearArea. */
573
574 void
575 XClearArea (display, w, x, y, width, height, exposures)
576 Display *display;
577 WindowPtr w;
578 int x, y;
579 unsigned int width, height;
580 int exposures;
581 {
582 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
583 Rect r;
584 XGCValues xgc;
585
586 xgc.foreground = mwp->x_compatible.foreground_pixel;
587 xgc.background = mwp->x_compatible.background_pixel;
588
589 #if TARGET_API_MAC_CARBON
590 SetPort (GetWindowPort (w));
591 #else
592 SetPort (w);
593 #endif
594
595 mac_set_colors (&xgc);
596 SetRect (&r, x, y, x + width, y + height);
597
598 EraseRect (&r);
599 }
600
601 /* Mac version of XClearWindow. */
602
603 static void
604 XClearWindow (display, w)
605 Display *display;
606 WindowPtr w;
607 {
608 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
609 XGCValues xgc;
610
611 xgc.foreground = mwp->x_compatible.foreground_pixel;
612 xgc.background = mwp->x_compatible.background_pixel;
613
614 #if TARGET_API_MAC_CARBON
615 SetPort (GetWindowPort (w));
616 #else
617 SetPort (w);
618 #endif
619
620 mac_set_colors (&xgc);
621
622 #if TARGET_API_MAC_CARBON
623 {
624 Rect r;
625
626 GetWindowPortBounds (w, &r);
627 EraseRect (&r);
628 }
629 #else /* not TARGET_API_MAC_CARBON */
630 EraseRect (&(w->portRect));
631 #endif /* not TARGET_API_MAC_CARBON */
632 }
633
634
635 /* Mac replacement for XCopyArea. */
636
637 static void
638 mac_draw_bitmap (display, w, gc, x, y, bitmap)
639 Display *display;
640 WindowPtr w;
641 GC gc;
642 int x, y;
643 BitMap *bitmap;
644 {
645 Rect r;
646
647 #if TARGET_API_MAC_CARBON
648 SetPort (GetWindowPort (w));
649 #else
650 SetPort (w);
651 #endif
652
653 mac_set_colors (gc);
654 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
655
656 #if TARGET_API_MAC_CARBON
657 {
658 PixMapHandle pmh;
659
660 LockPortBits (GetWindowPort (w));
661 pmh = GetPortPixMap (GetWindowPort (w));
662 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
663 UnlockPortBits (GetWindowPort (w));
664 }
665 #else /* not TARGET_API_MAC_CARBON */
666 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
667 #endif /* not TARGET_API_MAC_CARBON */
668 }
669
670
671 /* Mac replacement for XSetClipRectangles. */
672
673 static void
674 mac_set_clip_rectangle (display, w, r)
675 Display *display;
676 WindowPtr w;
677 Rect *r;
678 {
679 #if TARGET_API_MAC_CARBON
680 SetPort (GetWindowPort (w));
681 #else
682 SetPort (w);
683 #endif
684
685 ClipRect (r);
686 }
687
688
689 /* Mac replacement for XSetClipMask. */
690
691 static void
692 mac_reset_clipping (display, w)
693 Display *display;
694 WindowPtr w;
695 {
696 Rect r;
697
698 #if TARGET_API_MAC_CARBON
699 SetPort (GetWindowPort (w));
700 #else
701 SetPort (w);
702 #endif
703
704 SetRect (&r, -32767, -32767, 32767, 32767);
705 ClipRect (&r);
706 }
707
708
709 /* Mac replacement for XCreateBitmapFromBitmapData. */
710
711 static void
712 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
713 BitMap *bitmap;
714 char *bits;
715 int w, h;
716 {
717 int bytes_per_row, i, j;
718
719 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
720 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
721 if (!bitmap->baseAddr)
722 abort ();
723
724 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
725 for (i = 0; i < h; i++)
726 for (j = 0; j < w; j++)
727 if (BitTst (bits, i * w + j))
728 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
729
730 SetRect (&(bitmap->bounds), 0, 0, w, h);
731 }
732
733
734 static void
735 mac_free_bitmap (bitmap)
736 BitMap *bitmap;
737 {
738 xfree (bitmap->baseAddr);
739 }
740
741 /* Mac replacement for XFillRectangle. */
742
743 static void
744 XFillRectangle (display, w, gc, x, y, width, height)
745 Display *display;
746 WindowPtr w;
747 GC gc;
748 int x, y;
749 unsigned int width, height;
750 {
751 Rect r;
752
753 #if TARGET_API_MAC_CARBON
754 SetPort (GetWindowPort (w));
755 #else
756 SetPort (w);
757 #endif
758
759 mac_set_colors (gc);
760 SetRect (&r, x, y, x + width, y + height);
761
762 PaintRect (&r); /* using foreground color of gc */
763 }
764
765
766 /* Mac replacement for XDrawRectangle: dest is a window. */
767
768 static void
769 mac_draw_rectangle (display, w, gc, x, y, width, height)
770 Display *display;
771 WindowPtr w;
772 GC gc;
773 int x, y;
774 unsigned int width, height;
775 {
776 Rect r;
777
778 #if TARGET_API_MAC_CARBON
779 SetPort (GetWindowPort (w));
780 #else
781 SetPort (w);
782 #endif
783
784 mac_set_colors (gc);
785 SetRect (&r, x, y, x + width + 1, y + height + 1);
786
787 FrameRect (&r); /* using foreground color of gc */
788 }
789
790
791 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
792
793 static void
794 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
795 Display *display;
796 Pixmap p;
797 GC gc;
798 int x, y;
799 unsigned int width, height;
800 {
801 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
802 Rect r;
803
804 #if TARGET_API_MAC_CARBON
805 SetPort (GetWindowPort (w));
806 #else
807 SetPort (w);
808 #endif
809
810 mac_set_colors (gc);
811 SetRect (&r, x, y, x + width, y + height);
812
813 FrameRect (&r); /* using foreground color of gc */
814 #endif /* 0 */
815 }
816
817
818 static void
819 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
820 bytes_per_char)
821 Display *display;
822 WindowPtr w;
823 GC gc;
824 int x, y;
825 char *buf;
826 int nchars, mode, bytes_per_char;
827 {
828 #if TARGET_API_MAC_CARBON
829 SetPort (GetWindowPort (w));
830 #else
831 SetPort (w);
832 #endif
833
834 mac_set_colors (gc);
835
836 TextFont (gc->font->mac_fontnum);
837 TextSize (gc->font->mac_fontsize);
838 TextFace (gc->font->mac_fontface);
839 TextMode (mode);
840
841 MoveTo (x, y);
842 DrawText (buf, 0, nchars * bytes_per_char);
843 }
844
845
846 /* Mac replacement for XDrawString. */
847
848 static void
849 XDrawString (display, w, gc, x, y, buf, nchars)
850 Display *display;
851 WindowPtr w;
852 GC gc;
853 int x, y;
854 char *buf;
855 int nchars;
856 {
857 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
858 }
859
860
861 /* Mac replacement for XDrawString16. */
862
863 static void
864 XDrawString16 (display, w, gc, x, y, buf, nchars)
865 Display *display;
866 WindowPtr w;
867 GC gc;
868 int x, y;
869 XChar2b *buf;
870 int nchars;
871 {
872 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
873 2);
874 }
875
876
877 /* Mac replacement for XDrawImageString. */
878
879 static void
880 XDrawImageString (display, w, gc, x, y, buf, nchars)
881 Display *display;
882 WindowPtr w;
883 GC gc;
884 int x, y;
885 char *buf;
886 int nchars;
887 {
888 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
889 }
890
891
892 /* Mac replacement for XDrawString16. */
893
894 static void
895 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
896 Display *display;
897 WindowPtr w;
898 GC gc;
899 int x, y;
900 XChar2b *buf;
901 int nchars;
902 {
903 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
904 2);
905 }
906
907
908 /* Mac replacement for XCopyArea: dest must be window. */
909
910 static void
911 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
912 dest_y)
913 Display *display;
914 Pixmap src;
915 WindowPtr dest;
916 GC gc;
917 int src_x, src_y;
918 unsigned int width, height;
919 int dest_x, dest_y;
920 {
921 Rect src_r, dest_r;
922
923 #if TARGET_API_MAC_CARBON
924 SetPort (GetWindowPort (dest));
925 #else
926 SetPort (dest);
927 #endif
928
929 mac_set_colors (gc);
930
931 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
932 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
933
934 #if TARGET_API_MAC_CARBON
935 {
936 PixMapHandle pmh;
937
938 LockPortBits (GetWindowPort (dest));
939 pmh = GetPortPixMap (GetWindowPort (dest));
940 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
941 UnlockPortBits (GetWindowPort (dest));
942 }
943 #else /* not TARGET_API_MAC_CARBON */
944 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
945 #endif /* not TARGET_API_MAC_CARBON */
946 }
947
948
949 #if 0
950 /* Convert a pair of local coordinates to global (screen) coordinates.
951 Assume graphic port has been properly set. */
952 static void
953 local_to_global_coord (short *h, short *v)
954 {
955 Point p;
956
957 p.h = *h;
958 p.v = *v;
959
960 LocalToGlobal (&p);
961
962 *h = p.h;
963 *v = p.v;
964 }
965 #endif
966
967 /* Mac replacement for XCopyArea: used only for scrolling. */
968
969 static void
970 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
971 Display *display;
972 WindowPtr w;
973 GC gc;
974 int src_x, src_y;
975 unsigned int width, height;
976 int dest_x, dest_y;
977 {
978 #if TARGET_API_MAC_CARBON
979 Rect gw_r, src_r, dest_r;
980 PixMapHandle pmh;
981
982 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
983 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
984
985 SetPort (GetWindowPort (w));
986
987 ForeColor (blackColor);
988 BackColor (whiteColor);
989
990 LockPortBits (GetWindowPort (w));
991 pmh = GetPortPixMap (GetWindowPort (w));
992 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
993 UnlockPortBits (GetWindowPort (w));
994
995 mac_set_colors (gc);
996 #else /* not TARGET_API_MAC_CARBON */
997 Rect src_r, dest_r;
998
999 SetPort (w);
1000 #if 0
1001 mac_set_colors (gc);
1002 #endif
1003
1004 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1005 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1006
1007 #if 0
1008 /* Need to use global coordinates and screenBits since src and dest
1009 areas overlap in general. */
1010 local_to_global_coord (&src_r.left, &src_r.top);
1011 local_to_global_coord (&src_r.right, &src_r.bottom);
1012 local_to_global_coord (&dest_r.left, &dest_r.top);
1013 local_to_global_coord (&dest_r.right, &dest_r.bottom);
1014
1015 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
1016 #else
1017 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1018 color mapping in CopyBits. Otherwise, it will be slow. */
1019 ForeColor (blackColor);
1020 BackColor (whiteColor);
1021 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1022
1023 mac_set_colors (gc);
1024 #endif
1025 #endif /* not TARGET_API_MAC_CARBON */
1026 }
1027
1028
1029 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1030
1031 static void
1032 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1033 dest_x, dest_y)
1034 Display *display;
1035 Pixmap src;
1036 Pixmap dest;
1037 GC gc;
1038 int src_x, src_y;
1039 unsigned int width, height;
1040 int dest_x, dest_y;
1041 {
1042 Rect src_r, dest_r;
1043 int src_right = ((PixMap *) src)->bounds.right;
1044 int src_bottom = ((PixMap *) src)->bounds.bottom;
1045 int w = src_right - src_x;
1046 int h = src_bottom - src_y;
1047
1048 mac_set_colors (gc);
1049
1050 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1051 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1052
1053 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1054 }
1055
1056
1057 /* Mac replacement for XChangeGC. */
1058
1059 static void
1060 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1061 XGCValues *xgcv)
1062 {
1063 if (mask & GCForeground)
1064 gc->foreground = xgcv->foreground;
1065 if (mask & GCBackground)
1066 gc->background = xgcv->background;
1067 if (mask & GCFont)
1068 gc->font = xgcv->font;
1069 }
1070
1071
1072 /* Mac replacement for XCreateGC. */
1073
1074 XGCValues *
1075 XCreateGC (void * ignore, Window window, unsigned long mask,
1076 XGCValues *xgcv)
1077 {
1078 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1079 bzero (gc, sizeof (XGCValues));
1080
1081 XChangeGC (ignore, gc, mask, xgcv);
1082
1083 return gc;
1084 }
1085
1086
1087 /* Used in xfaces.c. */
1088
1089 void
1090 XFreeGC (display, gc)
1091 Display *display;
1092 GC gc;
1093 {
1094 xfree (gc);
1095 }
1096
1097
1098 /* Mac replacement for XGetGCValues. */
1099
1100 static void
1101 XGetGCValues (void* ignore, XGCValues *gc,
1102 unsigned long mask, XGCValues *xgcv)
1103 {
1104 XChangeGC (ignore, xgcv, mask, gc);
1105 }
1106
1107
1108 /* Mac replacement for XSetForeground. */
1109
1110 static void
1111 XSetForeground (display, gc, color)
1112 Display *display;
1113 GC gc;
1114 unsigned long color;
1115 {
1116 gc->foreground = color;
1117 }
1118
1119
1120 /* Mac replacement for XSetFont. */
1121
1122 static void
1123 XSetFont (display, gc, font)
1124 Display *display;
1125 GC gc;
1126 XFontStruct *font;
1127 {
1128 gc->font = font;
1129 }
1130
1131
1132 static void
1133 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1134 int *direction,int *font_ascent,
1135 int *font_descent, XCharStruct *cs)
1136 {
1137 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1138 }
1139
1140
1141 /* x_sync is a no-op on Mac. */
1142 void
1143 x_sync (f)
1144 void *f;
1145 {
1146 }
1147
1148
1149 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1150 Calls to XFlush should be unnecessary because the X output buffer
1151 is flushed automatically as needed by calls to XPending,
1152 XNextEvent, or XWindowEvent according to the XFlush man page.
1153 XTread_socket calls XPending. Removing XFlush improves
1154 performance. */
1155
1156 #if TARGET_API_MAC_CARBON
1157 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1158 #else
1159 #define XFlush(DISPLAY) (void) 0
1160 #endif
1161
1162 /* Flush display of frame F, or of all frames if F is null. */
1163
1164 void
1165 x_flush (f)
1166 struct frame *f;
1167 {
1168 #if TARGET_API_MAC_CARBON
1169 BLOCK_INPUT;
1170 if (f == NULL)
1171 {
1172 Lisp_Object rest, frame;
1173 FOR_EACH_FRAME (rest, frame)
1174 x_flush (XFRAME (frame));
1175 }
1176 else if (FRAME_X_P (f))
1177 XFlush (FRAME_MAC_DISPLAY (f));
1178 UNBLOCK_INPUT;
1179 #endif /* TARGET_API_MAC_CARBON */
1180 }
1181
1182
1183 \f
1184 /* Return the struct mac_display_info corresponding to DPY. There's
1185 only one. */
1186
1187 struct mac_display_info *
1188 mac_display_info_for_display (dpy)
1189 Display *dpy;
1190 {
1191 return &one_mac_display_info;
1192 }
1193
1194
1195 \f
1196 /***********************************************************************
1197 Starting and ending an update
1198 ***********************************************************************/
1199
1200 /* Start an update of frame F. This function is installed as a hook
1201 for update_begin, i.e. it is called when update_begin is called.
1202 This function is called prior to calls to x_update_window_begin for
1203 each window being updated. */
1204
1205 static void
1206 x_update_begin (f)
1207 struct frame *f;
1208 {
1209 /* Nothing to do. */
1210 }
1211
1212
1213 /* Start update of window W. Set the global variable updated_window
1214 to the window being updated and set output_cursor to the cursor
1215 position of W. */
1216
1217 static void
1218 x_update_window_begin (w)
1219 struct window *w;
1220 {
1221 struct frame *f = XFRAME (WINDOW_FRAME (w));
1222 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1223
1224 updated_window = w;
1225 set_output_cursor (&w->cursor);
1226
1227 BLOCK_INPUT;
1228
1229 if (f == display_info->mouse_face_mouse_frame)
1230 {
1231 /* Don't do highlighting for mouse motion during the update. */
1232 display_info->mouse_face_defer = 1;
1233
1234 /* If F needs to be redrawn, simply forget about any prior mouse
1235 highlighting. */
1236 if (FRAME_GARBAGED_P (f))
1237 display_info->mouse_face_window = Qnil;
1238
1239 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1240 their mouse_face_p flag set, which means that they are always
1241 unequal to rows in a desired matrix which never have that
1242 flag set. So, rows containing mouse-face glyphs are never
1243 scrolled, and we don't have to switch the mouse highlight off
1244 here to prevent it from being scrolled. */
1245
1246 /* Can we tell that this update does not affect the window
1247 where the mouse highlight is? If so, no need to turn off.
1248 Likewise, don't do anything if the frame is garbaged;
1249 in that case, the frame's current matrix that we would use
1250 is all wrong, and we will redisplay that line anyway. */
1251 if (!NILP (display_info->mouse_face_window)
1252 && w == XWINDOW (display_info->mouse_face_window))
1253 {
1254 int i;
1255
1256 for (i = 0; i < w->desired_matrix->nrows; ++i)
1257 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1258 break;
1259
1260 if (i < w->desired_matrix->nrows)
1261 clear_mouse_face (display_info);
1262 }
1263 #endif /* 0 */
1264 }
1265
1266 UNBLOCK_INPUT;
1267 }
1268
1269
1270 /* Draw a vertical window border to the right of window W if W doesn't
1271 have vertical scroll bars. */
1272
1273 static void
1274 x_draw_vertical_border (w)
1275 struct window *w;
1276 {
1277 struct frame *f = XFRAME (WINDOW_FRAME (w));
1278
1279 /* Redraw borders between horizontally adjacent windows. Don't
1280 do it for frames with vertical scroll bars because either the
1281 right scroll bar of a window, or the left scroll bar of its
1282 neighbor will suffice as a border. */
1283 if (!WINDOW_RIGHTMOST_P (w)
1284 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1285 {
1286 int x0, x1, y0, y1;
1287
1288 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1289 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1290 y1 -= 1;
1291
1292 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1293 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1294 }
1295 }
1296
1297
1298 /* End update of window W (which is equal to updated_window).
1299
1300 Draw vertical borders between horizontally adjacent windows, and
1301 display W's cursor if CURSOR_ON_P is non-zero.
1302
1303 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1304 glyphs in mouse-face were overwritten. In that case we have to
1305 make sure that the mouse-highlight is properly redrawn.
1306
1307 W may be a menu bar pseudo-window in case we don't have X toolkit
1308 support. Such windows don't have a cursor, so don't display it
1309 here. */
1310
1311 static void
1312 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1313 struct window *w;
1314 int cursor_on_p, mouse_face_overwritten_p;
1315 {
1316 struct mac_display_info *dpyinfo
1317 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1318
1319 if (!w->pseudo_window_p)
1320 {
1321 BLOCK_INPUT;
1322
1323 if (cursor_on_p)
1324 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1325 output_cursor.vpos,
1326 output_cursor.x, output_cursor.y);
1327
1328 x_draw_vertical_border (w);
1329 UNBLOCK_INPUT;
1330 }
1331
1332 /* If a row with mouse-face was overwritten, arrange for
1333 XTframe_up_to_date to redisplay the mouse highlight. */
1334 if (mouse_face_overwritten_p)
1335 {
1336 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1337 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1338 dpyinfo->mouse_face_window = Qnil;
1339 }
1340
1341 #if 0
1342 /* Unhide the caret. This won't actually show the cursor, unless it
1343 was visible before the corresponding call to HideCaret in
1344 x_update_window_begin. */
1345 if (w32_use_visible_system_caret)
1346 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1347 #endif
1348
1349 updated_window = NULL;
1350 }
1351
1352
1353 /* End update of frame F. This function is installed as a hook in
1354 update_end. */
1355
1356 static void
1357 x_update_end (f)
1358 struct frame *f;
1359 {
1360 /* Reset the background color of Mac OS Window to that of the frame after
1361 update so that it is used by Mac Toolbox to clear the update region before
1362 an update event is generated. */
1363 #if TARGET_API_MAC_CARBON
1364 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1365 #else
1366 SetPort (FRAME_MAC_WINDOW (f));
1367 #endif
1368
1369 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1370
1371 /* Mouse highlight may be displayed again. */
1372 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1373
1374 BLOCK_INPUT;
1375 XFlush (FRAME_MAC_DISPLAY (f));
1376 UNBLOCK_INPUT;
1377 }
1378
1379
1380 /* This function is called from various places in xdisp.c whenever a
1381 complete update has been performed. The global variable
1382 updated_window is not available here. */
1383
1384 static void
1385 XTframe_up_to_date (f)
1386 struct frame *f;
1387 {
1388 if (FRAME_X_P (f))
1389 {
1390 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1391
1392 if (dpyinfo->mouse_face_deferred_gc
1393 || f == dpyinfo->mouse_face_mouse_frame)
1394 {
1395 BLOCK_INPUT;
1396 if (dpyinfo->mouse_face_mouse_frame)
1397 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1398 dpyinfo->mouse_face_mouse_x,
1399 dpyinfo->mouse_face_mouse_y);
1400 dpyinfo->mouse_face_deferred_gc = 0;
1401 UNBLOCK_INPUT;
1402 }
1403 }
1404 }
1405
1406
1407 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1408 arrow bitmaps, or clear the fringes if no bitmaps are required
1409 before DESIRED_ROW is made current. The window being updated is
1410 found in updated_window. This function is called from
1411 update_window_line only if it is known that there are differences
1412 between bitmaps to be drawn between current row and DESIRED_ROW. */
1413
1414 static void
1415 x_after_update_window_line (desired_row)
1416 struct glyph_row *desired_row;
1417 {
1418 struct window *w = updated_window;
1419 struct frame *f;
1420 int width, height;
1421
1422 xassert (w);
1423
1424 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1425 {
1426 BLOCK_INPUT;
1427 x_draw_row_fringe_bitmaps (w, desired_row);
1428 UNBLOCK_INPUT;
1429 }
1430
1431 /* When a window has disappeared, make sure that no rest of
1432 full-width rows stays visible in the internal border. Could
1433 check here if updated_window is the leftmost/rightmost window,
1434 but I guess it's not worth doing since vertically split windows
1435 are almost never used, internal border is rarely set, and the
1436 overhead is very small. */
1437 if (windows_or_buffers_changed
1438 && desired_row->full_width_p
1439 && (f = XFRAME (w->frame),
1440 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1441 width != 0)
1442 && (height = desired_row->visible_height,
1443 height > 0))
1444 {
1445 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1446 /* Internal border is drawn below the tool bar. */
1447 if (WINDOWP (f->tool_bar_window)
1448 && w == XWINDOW (f->tool_bar_window))
1449 y -= width;
1450
1451 BLOCK_INPUT;
1452
1453 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1454 0, y, width, height, 0);
1455 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1456 f->output_data.mac->pixel_width - width, y,
1457 width, height, 0);
1458
1459 UNBLOCK_INPUT;
1460 }
1461 }
1462
1463
1464 /* Draw the bitmap WHICH in one of the left or right fringes of
1465 window W. ROW is the glyph row for which to display the bitmap; it
1466 determines the vertical position at which the bitmap has to be
1467 drawn. */
1468
1469 static void
1470 x_draw_fringe_bitmap (w, row, which, left_p)
1471 struct window *w;
1472 struct glyph_row *row;
1473 enum fringe_bitmap_type which;
1474 int left_p;
1475 {
1476 struct frame *f = XFRAME (WINDOW_FRAME (w));
1477 Display *display = FRAME_MAC_DISPLAY (f);
1478 WindowPtr window = FRAME_MAC_WINDOW (f);
1479 int x, y, wd, h, dy;
1480 int b1, b2;
1481 unsigned char *bits;
1482 BitMap bitmap;
1483 XGCValues gcv;
1484 GC gc = f->output_data.mac->normal_gc;
1485 struct face *face;
1486
1487 /* Must clip because of partially visible lines. */
1488 x_clip_to_row (w, row, gc, 1);
1489
1490 /* Convert row to frame coordinates. */
1491 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1492
1493 switch (which)
1494 {
1495 case NO_FRINGE_BITMAP:
1496 wd = 0;
1497 h = 0;
1498 break;
1499
1500 case LEFT_TRUNCATION_BITMAP:
1501 wd = left_width;
1502 h = left_height;
1503 bits = left_bits;
1504 break;
1505
1506 case OVERLAY_ARROW_BITMAP:
1507 wd = ov_width;
1508 h = ov_height;
1509 bits = ov_bits;
1510 break;
1511
1512 case RIGHT_TRUNCATION_BITMAP:
1513 wd = right_width;
1514 h = right_height;
1515 bits = right_bits;
1516 break;
1517
1518 case CONTINUED_LINE_BITMAP:
1519 wd = continued_width;
1520 h = continued_height;
1521 bits = continued_bits;
1522 break;
1523
1524 case CONTINUATION_LINE_BITMAP:
1525 wd = continuation_width;
1526 h = continuation_height;
1527 bits = continuation_bits;
1528 break;
1529
1530 case ZV_LINE_BITMAP:
1531 wd = zv_width;
1532 h = zv_height - (y % zv_period);
1533 bits = zv_bits + (y % zv_period);
1534 break;
1535
1536 default:
1537 abort ();
1538 }
1539
1540 /* Clip bitmap if too high. */
1541 if (h > row->height)
1542 h = row->height;
1543
1544 /* Set dy to the offset in the row to start drawing the bitmap. */
1545 dy = (row->height - h) / 2;
1546
1547 /* Draw the bitmap. */
1548 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
1549 PREPARE_FACE_FOR_DISPLAY (f, face);
1550
1551 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1552 the fringe. */
1553 b1 = -1;
1554 if (left_p)
1555 {
1556 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1557 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1558 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1559 - wd
1560 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1561 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1562 {
1563 /* If W has a vertical border to its left, don't draw over it. */
1564 int border = ((XFASTINT (w->left) > 0
1565 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1566 ? 1 : 0);
1567 b1 = (window_box_left (w, -1)
1568 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1569 + border);
1570 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1571 }
1572 }
1573 else
1574 {
1575 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1576 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1577 x = (window_box_right (w, -1)
1578 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1579 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1580 the fringe. */
1581 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1582 {
1583 b1 = window_box_right (w, -1);
1584 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1585 }
1586 }
1587
1588 if (b1 >= 0)
1589 {
1590 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1591 XGCValues gcv;
1592 gcv.foreground = face->background;
1593
1594 #if 0 /* MAC_TODO: stipple */
1595 /* In case the same realized face is used for fringes and
1596 for something displayed in the text (e.g. face `region' on
1597 mono-displays, the fill style may have been changed to
1598 FillSolid in x_draw_glyph_string_background. */
1599 if (face->stipple)
1600 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1601 else
1602 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1603 #endif
1604
1605 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1606 &gcv,
1607 b1,
1608 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1609 row->y)),
1610 b2,
1611 row->visible_height);
1612
1613 #if 0 /* MAC_TODO: stipple */
1614 if (!face->stipple)
1615 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1616 #endif
1617 }
1618
1619 if (which == NO_FRINGE_BITMAP)
1620 {
1621 mac_reset_clipping (display, window);
1622 return;
1623 }
1624
1625 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1626 gcv.foreground = face->foreground;
1627 gcv.background = face->background;
1628
1629 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1630
1631 mac_free_bitmap (&bitmap);
1632 mac_reset_clipping (display, window);
1633 }
1634
1635
1636 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1637 function with input blocked. */
1638
1639 static void
1640 x_draw_row_fringe_bitmaps (w, row)
1641 struct window *w;
1642 struct glyph_row *row;
1643 {
1644 struct frame *f = XFRAME (w->frame);
1645 enum fringe_bitmap_type bitmap;
1646
1647 xassert (interrupt_input_blocked);
1648
1649 /* If row is completely invisible, because of vscrolling, we
1650 don't have to draw anything. */
1651 if (row->visible_height <= 0)
1652 return;
1653
1654 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1655 {
1656 /* Decide which bitmap to draw in the left fringe. */
1657 if (row->overlay_arrow_p)
1658 bitmap = OVERLAY_ARROW_BITMAP;
1659 else if (row->truncated_on_left_p)
1660 bitmap = LEFT_TRUNCATION_BITMAP;
1661 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1662 bitmap = CONTINUATION_LINE_BITMAP;
1663 else if (row->indicate_empty_line_p)
1664 bitmap = ZV_LINE_BITMAP;
1665 else
1666 bitmap = NO_FRINGE_BITMAP;
1667
1668 x_draw_fringe_bitmap (w, row, bitmap, 1);
1669 }
1670
1671 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1672 {
1673 /* Decide which bitmap to draw in the right fringe. */
1674 if (row->truncated_on_right_p)
1675 bitmap = RIGHT_TRUNCATION_BITMAP;
1676 else if (row->continued_p)
1677 bitmap = CONTINUED_LINE_BITMAP;
1678 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1679 bitmap = ZV_LINE_BITMAP;
1680 else
1681 bitmap = NO_FRINGE_BITMAP;
1682
1683 x_draw_fringe_bitmap (w, row, bitmap, 0);
1684 }
1685 }
1686
1687 \f
1688 /* This is called when starting Emacs and when restarting after
1689 suspend. When starting Emacs, no window is mapped. And nothing
1690 must be done to Emacs's own window if it is suspended (though that
1691 rarely happens). */
1692
1693 static void
1694 XTset_terminal_modes ()
1695 {
1696 }
1697
1698 /* This is called when exiting or suspending Emacs. Exiting will make
1699 the windows go away, and suspending requires no action. */
1700
1701 static void
1702 XTreset_terminal_modes ()
1703 {
1704 }
1705
1706
1707 \f
1708 /***********************************************************************
1709 Output Cursor
1710 ***********************************************************************/
1711
1712 /* Set the global variable output_cursor to CURSOR. All cursor
1713 positions are relative to updated_window. */
1714
1715 static void
1716 set_output_cursor (cursor)
1717 struct cursor_pos *cursor;
1718 {
1719 output_cursor.hpos = cursor->hpos;
1720 output_cursor.vpos = cursor->vpos;
1721 output_cursor.x = cursor->x;
1722 output_cursor.y = cursor->y;
1723 }
1724
1725
1726 /* Set a nominal cursor position.
1727
1728 HPOS and VPOS are column/row positions in a window glyph matrix. X
1729 and Y are window text area relative pixel positions.
1730
1731 If this is done during an update, updated_window will contain the
1732 window that is being updated and the position is the future output
1733 cursor position for that window. If updated_window is null, use
1734 selected_window and display the cursor at the given position. */
1735
1736 static void
1737 XTcursor_to (vpos, hpos, y, x)
1738 int vpos, hpos, y, x;
1739 {
1740 struct window *w;
1741
1742 /* If updated_window is not set, work on selected_window. */
1743 if (updated_window)
1744 w = updated_window;
1745 else
1746 w = XWINDOW (selected_window);
1747
1748 /* Set the output cursor. */
1749 output_cursor.hpos = hpos;
1750 output_cursor.vpos = vpos;
1751 output_cursor.x = x;
1752 output_cursor.y = y;
1753
1754 /* If not called as part of an update, really display the cursor.
1755 This will also set the cursor position of W. */
1756 if (updated_window == NULL)
1757 {
1758 BLOCK_INPUT;
1759 x_display_cursor (w, 1, hpos, vpos, x, y);
1760 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1761 UNBLOCK_INPUT;
1762 }
1763 }
1764
1765
1766 \f
1767 /***********************************************************************
1768 Display Iterator
1769 ***********************************************************************/
1770
1771 /* Function prototypes of this page. */
1772
1773 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1774 struct glyph *,
1775 XChar2b *,
1776 int *));
1777 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1778 int, XChar2b *, int));
1779 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1780 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1781 static void x_append_glyph P_ ((struct it *));
1782 static void x_append_composite_glyph P_ ((struct it *));
1783 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1784 int, int, double));
1785 static void x_produce_glyphs P_ ((struct it *));
1786 static void x_produce_image_glyph P_ ((struct it *it));
1787
1788
1789 /* Return a pointer to per-char metric information in FONT of a
1790 character pointed by B which is a pointer to an XChar2b. */
1791
1792 #define PER_CHAR_METRIC(font, b) \
1793 ((font)->per_char \
1794 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1795 + (((font)->min_byte1 || (font)->max_byte1) \
1796 ? (((b)->byte1 - (font)->min_byte1) \
1797 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1798 : 0)) \
1799 : &((font)->max_bounds))
1800
1801
1802 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1803 is not contained in the font. */
1804
1805 static INLINE XCharStruct *
1806 x_per_char_metric (font, char2b)
1807 XFontStruct *font;
1808 XChar2b *char2b;
1809 {
1810 /* The result metric information. */
1811 XCharStruct *pcm = NULL;
1812
1813 xassert (font && char2b);
1814
1815 if (font->per_char != NULL)
1816 {
1817 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1818 {
1819 /* min_char_or_byte2 specifies the linear character index
1820 corresponding to the first element of the per_char array,
1821 max_char_or_byte2 is the index of the last character. A
1822 character with non-zero CHAR2B->byte1 is not in the font.
1823 A character with byte2 less than min_char_or_byte2 or
1824 greater max_char_or_byte2 is not in the font. */
1825 if (char2b->byte1 == 0
1826 && char2b->byte2 >= font->min_char_or_byte2
1827 && char2b->byte2 <= font->max_char_or_byte2)
1828 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1829 }
1830 else
1831 {
1832 /* If either min_byte1 or max_byte1 are nonzero, both
1833 min_char_or_byte2 and max_char_or_byte2 are less than
1834 256, and the 2-byte character index values corresponding
1835 to the per_char array element N (counting from 0) are:
1836
1837 byte1 = N/D + min_byte1
1838 byte2 = N\D + min_char_or_byte2
1839
1840 where:
1841
1842 D = max_char_or_byte2 - min_char_or_byte2 + 1
1843 / = integer division
1844 \ = integer modulus */
1845 if (char2b->byte1 >= font->min_byte1
1846 && char2b->byte1 <= font->max_byte1
1847 && char2b->byte2 >= font->min_char_or_byte2
1848 && char2b->byte2 <= font->max_char_or_byte2)
1849 {
1850 pcm = (font->per_char
1851 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1852 * (char2b->byte1 - font->min_byte1))
1853 + (char2b->byte2 - font->min_char_or_byte2));
1854 }
1855 }
1856 }
1857 else
1858 {
1859 /* If the per_char pointer is null, all glyphs between the first
1860 and last character indexes inclusive have the same
1861 information, as given by both min_bounds and max_bounds. */
1862 if (char2b->byte2 >= font->min_char_or_byte2
1863 && char2b->byte2 <= font->max_char_or_byte2)
1864 pcm = &font->max_bounds;
1865 }
1866
1867 return ((pcm == NULL
1868 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1869 ? NULL : pcm);
1870 }
1871
1872
1873 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1874 the two-byte form of C. Encoding is returned in *CHAR2B. */
1875
1876 static INLINE void
1877 x_encode_char (c, char2b, font_info)
1878 int c;
1879 XChar2b *char2b;
1880 struct font_info *font_info;
1881 {
1882 int charset = CHAR_CHARSET (c);
1883 XFontStruct *font = font_info->font;
1884
1885 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1886 This may be either a program in a special encoder language or a
1887 fixed encoding. */
1888 if (font_info->font_encoder)
1889 {
1890 /* It's a program. */
1891 struct ccl_program *ccl = font_info->font_encoder;
1892
1893 if (CHARSET_DIMENSION (charset) == 1)
1894 {
1895 ccl->reg[0] = charset;
1896 ccl->reg[1] = char2b->byte2;
1897 }
1898 else
1899 {
1900 ccl->reg[0] = charset;
1901 ccl->reg[1] = char2b->byte1;
1902 ccl->reg[2] = char2b->byte2;
1903 }
1904
1905 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1906
1907 /* We assume that MSBs are appropriately set/reset by CCL
1908 program. */
1909 if (font->max_byte1 == 0) /* 1-byte font */
1910 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1911 else
1912 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1913 }
1914 else if (font_info->encoding[charset])
1915 {
1916 /* Fixed encoding scheme. See fontset.h for the meaning of the
1917 encoding numbers. */
1918 int enc = font_info->encoding[charset];
1919
1920 if ((enc == 1 || enc == 2)
1921 && CHARSET_DIMENSION (charset) == 2)
1922 char2b->byte1 |= 0x80;
1923
1924 if (enc == 1 || enc == 3)
1925 char2b->byte2 |= 0x80;
1926
1927 if (enc == 4)
1928 {
1929 int sjis1, sjis2;
1930
1931 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1932 char2b->byte1 = sjis1;
1933 char2b->byte2 = sjis2;
1934 }
1935 }
1936 }
1937
1938
1939 /* Get face and two-byte form of character C in face FACE_ID on frame
1940 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1941 means we want to display multibyte text. Value is a pointer to a
1942 realized face that is ready for display. */
1943
1944 static INLINE struct face *
1945 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1946 struct frame *f;
1947 int c, face_id;
1948 XChar2b *char2b;
1949 int multibyte_p;
1950 {
1951 struct face *face = FACE_FROM_ID (f, face_id);
1952
1953 if (!multibyte_p)
1954 {
1955 /* Unibyte case. We don't have to encode, but we have to make
1956 sure to use a face suitable for unibyte. */
1957 char2b->byte1 = 0;
1958 char2b->byte2 = c;
1959 face_id = FACE_FOR_CHAR (f, face, c);
1960 face = FACE_FROM_ID (f, face_id);
1961 }
1962 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1963 {
1964 /* Case of ASCII in a face known to fit ASCII. */
1965 char2b->byte1 = 0;
1966 char2b->byte2 = c;
1967 }
1968 else
1969 {
1970 int c1, c2, charset;
1971
1972 /* Split characters into bytes. If c2 is -1 afterwards, C is
1973 really a one-byte character so that byte1 is zero. */
1974 SPLIT_CHAR (c, charset, c1, c2);
1975 if (c2 > 0)
1976 char2b->byte1 = c1, char2b->byte2 = c2;
1977 else
1978 char2b->byte1 = 0, char2b->byte2 = c1;
1979
1980 /* Maybe encode the character in *CHAR2B. */
1981 if (face->font != NULL)
1982 {
1983 struct font_info *font_info
1984 = FONT_INFO_FROM_ID (f, face->font_info_id);
1985 if (font_info)
1986 x_encode_char (c, char2b, font_info);
1987 }
1988 }
1989
1990 /* Make sure X resources of the face are allocated. */
1991 xassert (face != NULL);
1992 PREPARE_FACE_FOR_DISPLAY (f, face);
1993
1994 return face;
1995 }
1996
1997
1998 /* Get face and two-byte form of character glyph GLYPH on frame F.
1999 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
2000 a pointer to a realized face that is ready for display. */
2001
2002 static INLINE struct face *
2003 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
2004 struct frame *f;
2005 struct glyph *glyph;
2006 XChar2b *char2b;
2007 int *two_byte_p;
2008 {
2009 struct face *face;
2010
2011 xassert (glyph->type == CHAR_GLYPH);
2012 face = FACE_FROM_ID (f, glyph->face_id);
2013
2014 if (two_byte_p)
2015 *two_byte_p = 0;
2016
2017 if (!glyph->multibyte_p)
2018 {
2019 /* Unibyte case. We don't have to encode, but we have to make
2020 sure to use a face suitable for unibyte. */
2021 char2b->byte1 = 0;
2022 char2b->byte2 = glyph->u.ch;
2023 }
2024 else if (glyph->u.ch < 128
2025 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2026 {
2027 /* Case of ASCII in a face known to fit ASCII. */
2028 char2b->byte1 = 0;
2029 char2b->byte2 = glyph->u.ch;
2030 }
2031 else
2032 {
2033 int c1, c2, charset;
2034
2035 /* Split characters into bytes. If c2 is -1 afterwards, C is
2036 really a one-byte character so that byte1 is zero. */
2037 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2038 if (c2 > 0)
2039 char2b->byte1 = c1, char2b->byte2 = c2;
2040 else
2041 char2b->byte1 = 0, char2b->byte2 = c1;
2042
2043 /* Maybe encode the character in *CHAR2B. */
2044 if (charset != CHARSET_ASCII)
2045 {
2046 struct font_info *font_info
2047 = FONT_INFO_FROM_ID (f, face->font_info_id);
2048 if (font_info)
2049 {
2050 x_encode_char (glyph->u.ch, char2b, font_info);
2051 if (two_byte_p)
2052 *two_byte_p
2053 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2054 }
2055 }
2056 }
2057
2058 /* Make sure X resources of the face are allocated. */
2059 xassert (face != NULL);
2060 PREPARE_FACE_FOR_DISPLAY (f, face);
2061 return face;
2062 }
2063
2064
2065 /* Store one glyph for IT->char_to_display in IT->glyph_row.
2066 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2067
2068 static INLINE void
2069 x_append_glyph (it)
2070 struct it *it;
2071 {
2072 struct glyph *glyph;
2073 enum glyph_row_area area = it->area;
2074
2075 xassert (it->glyph_row);
2076 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2077
2078 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2079 if (glyph < it->glyph_row->glyphs[area + 1])
2080 {
2081 glyph->charpos = CHARPOS (it->position);
2082 glyph->object = it->object;
2083 glyph->pixel_width = it->pixel_width;
2084 glyph->voffset = it->voffset;
2085 glyph->type = CHAR_GLYPH;
2086 glyph->multibyte_p = it->multibyte_p;
2087 glyph->left_box_line_p = it->start_of_box_run_p;
2088 glyph->right_box_line_p = it->end_of_box_run_p;
2089 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2090 || it->phys_descent > it->descent);
2091 glyph->padding_p = 0;
2092 glyph->glyph_not_available_p = it->glyph_not_available_p;
2093 glyph->face_id = it->face_id;
2094 glyph->u.ch = it->char_to_display;
2095 ++it->glyph_row->used[area];
2096 }
2097 }
2098
2099 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2100 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2101
2102 static INLINE void
2103 x_append_composite_glyph (it)
2104 struct it *it;
2105 {
2106 struct glyph *glyph;
2107 enum glyph_row_area area = it->area;
2108
2109 xassert (it->glyph_row);
2110
2111 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2112 if (glyph < it->glyph_row->glyphs[area + 1])
2113 {
2114 glyph->charpos = CHARPOS (it->position);
2115 glyph->object = it->object;
2116 glyph->pixel_width = it->pixel_width;
2117 glyph->voffset = it->voffset;
2118 glyph->type = COMPOSITE_GLYPH;
2119 glyph->multibyte_p = it->multibyte_p;
2120 glyph->left_box_line_p = it->start_of_box_run_p;
2121 glyph->right_box_line_p = it->end_of_box_run_p;
2122 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2123 || it->phys_descent > it->descent);
2124 glyph->padding_p = 0;
2125 glyph->glyph_not_available_p = 0;
2126 glyph->face_id = it->face_id;
2127 glyph->u.cmp_id = it->cmp_id;
2128 ++it->glyph_row->used[area];
2129 }
2130 }
2131
2132
2133 /* Change IT->ascent and IT->height according to the setting of
2134 IT->voffset. */
2135
2136 static INLINE void
2137 take_vertical_position_into_account (it)
2138 struct it *it;
2139 {
2140 if (it->voffset)
2141 {
2142 if (it->voffset < 0)
2143 /* Increase the ascent so that we can display the text higher
2144 in the line. */
2145 it->ascent += abs (it->voffset);
2146 else
2147 /* Increase the descent so that we can display the text lower
2148 in the line. */
2149 it->descent += it->voffset;
2150 }
2151 }
2152
2153
2154 /* Produce glyphs/get display metrics for the image IT is loaded with.
2155 See the description of struct display_iterator in dispextern.h for
2156 an overview of struct display_iterator. */
2157
2158 static void
2159 x_produce_image_glyph (it)
2160 struct it *it;
2161 {
2162 struct image *img;
2163 struct face *face;
2164
2165 xassert (it->what == IT_IMAGE);
2166
2167 face = FACE_FROM_ID (it->f, it->face_id);
2168 img = IMAGE_FROM_ID (it->f, it->image_id);
2169 xassert (img);
2170
2171 /* Make sure X resources of the face and image are loaded. */
2172 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2173 prepare_image_for_display (it->f, img);
2174
2175 it->ascent = it->phys_ascent = image_ascent (img, face);
2176 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2177 it->pixel_width = img->width + 2 * img->hmargin;
2178
2179 it->nglyphs = 1;
2180
2181 if (face->box != FACE_NO_BOX)
2182 {
2183 if (face->box_line_width > 0)
2184 {
2185 it->ascent += face->box_line_width;
2186 it->descent += face->box_line_width;
2187 }
2188
2189 if (it->start_of_box_run_p)
2190 it->pixel_width += abs (face->box_line_width);
2191 if (it->end_of_box_run_p)
2192 it->pixel_width += abs (face->box_line_width);
2193 }
2194
2195 take_vertical_position_into_account (it);
2196
2197 if (it->glyph_row)
2198 {
2199 struct glyph *glyph;
2200 enum glyph_row_area area = it->area;
2201
2202 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2203 if (glyph < it->glyph_row->glyphs[area + 1])
2204 {
2205 glyph->charpos = CHARPOS (it->position);
2206 glyph->object = it->object;
2207 glyph->pixel_width = it->pixel_width;
2208 glyph->voffset = it->voffset;
2209 glyph->type = IMAGE_GLYPH;
2210 glyph->multibyte_p = it->multibyte_p;
2211 glyph->left_box_line_p = it->start_of_box_run_p;
2212 glyph->right_box_line_p = it->end_of_box_run_p;
2213 glyph->overlaps_vertically_p = 0;
2214 glyph->padding_p = 0;
2215 glyph->glyph_not_available_p = 0;
2216 glyph->face_id = it->face_id;
2217 glyph->u.img_id = img->id;
2218 ++it->glyph_row->used[area];
2219 }
2220 }
2221 }
2222
2223
2224 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2225 of the glyph, WIDTH and HEIGHT are the width and height of the
2226 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2227 ascent of the glyph (0 <= ASCENT <= 1). */
2228
2229 static void
2230 x_append_stretch_glyph (it, object, width, height, ascent)
2231 struct it *it;
2232 Lisp_Object object;
2233 int width, height;
2234 double ascent;
2235 {
2236 struct glyph *glyph;
2237 enum glyph_row_area area = it->area;
2238
2239 xassert (ascent >= 0 && ascent <= 1);
2240
2241 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2242 if (glyph < it->glyph_row->glyphs[area + 1])
2243 {
2244 glyph->charpos = CHARPOS (it->position);
2245 glyph->object = object;
2246 glyph->pixel_width = width;
2247 glyph->voffset = it->voffset;
2248 glyph->type = STRETCH_GLYPH;
2249 glyph->multibyte_p = it->multibyte_p;
2250 glyph->left_box_line_p = it->start_of_box_run_p;
2251 glyph->right_box_line_p = it->end_of_box_run_p;
2252 glyph->overlaps_vertically_p = 0;
2253 glyph->padding_p = 0;
2254 glyph->glyph_not_available_p = 0;
2255 glyph->face_id = it->face_id;
2256 glyph->u.stretch.ascent = height * ascent;
2257 glyph->u.stretch.height = height;
2258 ++it->glyph_row->used[area];
2259 }
2260 }
2261
2262
2263 /* Produce a stretch glyph for iterator IT. IT->object is the value
2264 of the glyph property displayed. The value must be a list
2265 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2266 being recognized:
2267
2268 1. `:width WIDTH' specifies that the space should be WIDTH *
2269 canonical char width wide. WIDTH may be an integer or floating
2270 point number.
2271
2272 2. `:relative-width FACTOR' specifies that the width of the stretch
2273 should be computed from the width of the first character having the
2274 `glyph' property, and should be FACTOR times that width.
2275
2276 3. `:align-to HPOS' specifies that the space should be wide enough
2277 to reach HPOS, a value in canonical character units.
2278
2279 Exactly one of the above pairs must be present.
2280
2281 4. `:height HEIGHT' specifies that the height of the stretch produced
2282 should be HEIGHT, measured in canonical character units.
2283
2284 5. `:relative-height FACTOR' specifies that the height of the
2285 stretch should be FACTOR times the height of the characters having
2286 the glyph property.
2287
2288 Either none or exactly one of 4 or 5 must be present.
2289
2290 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2291 of the stretch should be used for the ascent of the stretch.
2292 ASCENT must be in the range 0 <= ASCENT <= 100. */
2293
2294 #define NUMVAL(X) \
2295 ((INTEGERP (X) || FLOATP (X)) \
2296 ? XFLOATINT (X) \
2297 : - 1)
2298
2299
2300 static void
2301 x_produce_stretch_glyph (it)
2302 struct it *it;
2303 {
2304 /* (space :width WIDTH :height HEIGHT. */
2305 #if GLYPH_DEBUG
2306 extern Lisp_Object Qspace;
2307 #endif
2308 extern Lisp_Object QCwidth, QCheight, QCascent;
2309 extern Lisp_Object QCrelative_width, QCrelative_height;
2310 extern Lisp_Object QCalign_to;
2311 Lisp_Object prop, plist;
2312 double width = 0, height = 0, ascent = 0;
2313 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2314 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2315
2316 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2317
2318 /* List should start with `space'. */
2319 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2320 plist = XCDR (it->object);
2321
2322 /* Compute the width of the stretch. */
2323 if (prop = Fplist_get (plist, QCwidth),
2324 NUMVAL (prop) > 0)
2325 /* Absolute width `:width WIDTH' specified and valid. */
2326 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2327 else if (prop = Fplist_get (plist, QCrelative_width),
2328 NUMVAL (prop) > 0)
2329 {
2330 /* Relative width `:relative-width FACTOR' specified and valid.
2331 Compute the width of the characters having the `glyph'
2332 property. */
2333 struct it it2;
2334 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2335
2336 it2 = *it;
2337 if (it->multibyte_p)
2338 {
2339 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2340 - IT_BYTEPOS (*it));
2341 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2342 }
2343 else
2344 it2.c = *p, it2.len = 1;
2345
2346 it2.glyph_row = NULL;
2347 it2.what = IT_CHARACTER;
2348 x_produce_glyphs (&it2);
2349 width = NUMVAL (prop) * it2.pixel_width;
2350 }
2351 else if (prop = Fplist_get (plist, QCalign_to),
2352 NUMVAL (prop) > 0)
2353 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2354 else
2355 /* Nothing specified -> width defaults to canonical char width. */
2356 width = CANON_X_UNIT (it->f);
2357
2358 /* Compute height. */
2359 if (prop = Fplist_get (plist, QCheight),
2360 NUMVAL (prop) > 0)
2361 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2362 else if (prop = Fplist_get (plist, QCrelative_height),
2363 NUMVAL (prop) > 0)
2364 height = FONT_HEIGHT (font) * NUMVAL (prop);
2365 else
2366 height = FONT_HEIGHT (font);
2367
2368 /* Compute percentage of height used for ascent. If
2369 `:ascent ASCENT' is present and valid, use that. Otherwise,
2370 derive the ascent from the font in use. */
2371 if (prop = Fplist_get (plist, QCascent),
2372 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2373 ascent = NUMVAL (prop) / 100.0;
2374 else
2375 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
2376
2377 if (width <= 0)
2378 width = 1;
2379 if (height <= 0)
2380 height = 1;
2381
2382 if (it->glyph_row)
2383 {
2384 Lisp_Object object = it->stack[it->sp - 1].string;
2385 if (!STRINGP (object))
2386 object = it->w->buffer;
2387 x_append_stretch_glyph (it, object, width, height, ascent);
2388 }
2389
2390 it->pixel_width = width;
2391 it->ascent = it->phys_ascent = height * ascent;
2392 it->descent = it->phys_descent = height - it->ascent;
2393 it->nglyphs = 1;
2394
2395 if (face->box != FACE_NO_BOX)
2396 {
2397 if (face->box_line_width > 0)
2398 {
2399 it->ascent += face->box_line_width;
2400 it->descent += face->box_line_width;
2401 }
2402
2403 if (it->start_of_box_run_p)
2404 it->pixel_width += abs (face->box_line_width);
2405 if (it->end_of_box_run_p)
2406 it->pixel_width += abs (face->box_line_width);
2407 }
2408
2409 take_vertical_position_into_account (it);
2410 }
2411
2412 /* Return proper value to be used as baseline offset of font that has
2413 ASCENT and DESCENT to draw characters by the font at the vertical
2414 center of the line of frame F.
2415
2416 Here, out task is to find the value of BOFF in the following figure;
2417
2418 -------------------------+-----------+-
2419 -+-+---------+-+ | |
2420 | | | | | |
2421 | | | | F_ASCENT F_HEIGHT
2422 | | | ASCENT | |
2423 HEIGHT | | | | |
2424 | | |-|-+------+-----------|------- baseline
2425 | | | | BOFF | |
2426 | |---------|-+-+ | |
2427 | | | DESCENT | |
2428 -+-+---------+-+ F_DESCENT |
2429 -------------------------+-----------+-
2430
2431 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2432 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2433 DESCENT = FONT->descent
2434 HEIGHT = FONT_HEIGHT (FONT)
2435 F_DESCENT = (F->output_data.x->font->descent
2436 - F->output_data.x->baseline_offset)
2437 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2438 */
2439
2440 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2441 (FONT_DESCENT (FONT) \
2442 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2443 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2444 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2445
2446 /* Produce glyphs/get display metrics for the display element IT is
2447 loaded with. See the description of struct display_iterator in
2448 dispextern.h for an overview of struct display_iterator. */
2449
2450 static void
2451 x_produce_glyphs (it)
2452 struct it *it;
2453 {
2454 it->glyph_not_available_p = 0;
2455
2456 if (it->what == IT_CHARACTER)
2457 {
2458 XChar2b char2b;
2459 XFontStruct *font;
2460 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2461 XCharStruct *pcm;
2462 int font_not_found_p;
2463 struct font_info *font_info;
2464 int boff; /* baseline offset */
2465 /* We may change it->multibyte_p upon unibyte<->multibyte
2466 conversion. So, save the current value now and restore it
2467 later.
2468
2469 Note: It seems that we don't have to record multibyte_p in
2470 struct glyph because the character code itself tells if or
2471 not the character is multibyte. Thus, in the future, we must
2472 consider eliminating the field `multibyte_p' in the struct
2473 glyph.
2474 */
2475 int saved_multibyte_p = it->multibyte_p;
2476
2477 /* Maybe translate single-byte characters to multibyte, or the
2478 other way. */
2479 it->char_to_display = it->c;
2480 if (!ASCII_BYTE_P (it->c))
2481 {
2482 if (unibyte_display_via_language_environment
2483 && SINGLE_BYTE_CHAR_P (it->c)
2484 && (it->c >= 0240
2485 || !NILP (Vnonascii_translation_table)))
2486 {
2487 it->char_to_display = unibyte_char_to_multibyte (it->c);
2488 it->multibyte_p = 1;
2489 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2490 face = FACE_FROM_ID (it->f, it->face_id);
2491 }
2492 else if (!SINGLE_BYTE_CHAR_P (it->c)
2493 && !it->multibyte_p)
2494 {
2495 it->multibyte_p = 1;
2496 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2497 face = FACE_FROM_ID (it->f, it->face_id);
2498 }
2499 }
2500
2501 /* Get font to use. Encode IT->char_to_display. */
2502 x_get_char_face_and_encoding (it->f, it->char_to_display,
2503 it->face_id, &char2b,
2504 it->multibyte_p);
2505 font = face->font;
2506
2507 /* When no suitable font found, use the default font. */
2508 font_not_found_p = font == NULL;
2509 if (font_not_found_p)
2510 {
2511 font = FRAME_FONT (it->f);
2512 boff = it->f->output_data.mac->baseline_offset;
2513 font_info = NULL;
2514 }
2515 else
2516 {
2517 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2518 boff = font_info->baseline_offset;
2519 if (font_info->vertical_centering)
2520 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2521 }
2522
2523 if (it->char_to_display >= ' '
2524 && (!it->multibyte_p || it->char_to_display < 128))
2525 {
2526 /* Either unibyte or ASCII. */
2527 int stretched_p;
2528
2529 it->nglyphs = 1;
2530
2531 pcm = x_per_char_metric (font, &char2b);
2532 it->ascent = FONT_BASE (font) + boff;
2533 it->descent = FONT_DESCENT (font) - boff;
2534
2535 if (pcm)
2536 {
2537 it->phys_ascent = pcm->ascent + boff;
2538 it->phys_descent = pcm->descent - boff;
2539 it->pixel_width = pcm->width;
2540 }
2541 else
2542 {
2543 it->glyph_not_available_p = 1;
2544 it->phys_ascent = FONT_BASE (font) + boff;
2545 it->phys_descent = FONT_DESCENT (font) - boff;
2546 it->pixel_width = FONT_WIDTH (font);
2547 }
2548
2549 /* If this is a space inside a region of text with
2550 `space-width' property, change its width. */
2551 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2552 if (stretched_p)
2553 it->pixel_width *= XFLOATINT (it->space_width);
2554
2555 /* If face has a box, add the box thickness to the character
2556 height. If character has a box line to the left and/or
2557 right, add the box line width to the character's width. */
2558 if (face->box != FACE_NO_BOX)
2559 {
2560 int thick = face->box_line_width;
2561
2562 if (thick > 0)
2563 {
2564 it->ascent += thick;
2565 it->descent += thick;
2566 }
2567 else
2568 thick = -thick;
2569
2570 if (it->start_of_box_run_p)
2571 it->pixel_width += thick;
2572 if (it->end_of_box_run_p)
2573 it->pixel_width += thick;
2574 }
2575
2576 /* If face has an overline, add the height of the overline
2577 (1 pixel) and a 1 pixel margin to the character height. */
2578 if (face->overline_p)
2579 it->ascent += 2;
2580
2581 take_vertical_position_into_account (it);
2582
2583 /* If we have to actually produce glyphs, do it. */
2584 if (it->glyph_row)
2585 {
2586 if (stretched_p)
2587 {
2588 /* Translate a space with a `space-width' property
2589 into a stretch glyph. */
2590 double ascent = (double) FONT_BASE (font)
2591 / FONT_HEIGHT (font);
2592 x_append_stretch_glyph (it, it->object, it->pixel_width,
2593 it->ascent + it->descent, ascent);
2594 }
2595 else
2596 x_append_glyph (it);
2597
2598 /* If characters with lbearing or rbearing are displayed
2599 in this line, record that fact in a flag of the
2600 glyph row. This is used to optimize X output code. */
2601 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2602 it->glyph_row->contains_overlapping_glyphs_p = 1;
2603 }
2604 }
2605 else if (it->char_to_display == '\n')
2606 {
2607 /* A newline has no width but we need the height of the line. */
2608 it->pixel_width = 0;
2609 it->nglyphs = 0;
2610 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2611 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2612
2613 if (face->box != FACE_NO_BOX
2614 && face->box_line_width > 0)
2615 {
2616 it->ascent += face->box_line_width;
2617 it->descent += face->box_line_width;
2618 }
2619 }
2620 else if (it->char_to_display == '\t')
2621 {
2622 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2623 int x = it->current_x + it->continuation_lines_width;
2624 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2625
2626 /* If the distance from the current position to the next tab
2627 stop is less than a canonical character width, use the
2628 tab stop after that. */
2629 if (next_tab_x - x < CANON_X_UNIT (it->f))
2630 next_tab_x += tab_width;
2631
2632 it->pixel_width = next_tab_x - x;
2633 it->nglyphs = 1;
2634 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2635 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2636
2637 if (it->glyph_row)
2638 {
2639 double ascent = (double) it->ascent / (it->ascent + it->descent);
2640 x_append_stretch_glyph (it, it->object, it->pixel_width,
2641 it->ascent + it->descent, ascent);
2642 }
2643 }
2644 else
2645 {
2646 /* A multi-byte character. Assume that the display width of the
2647 character is the width of the character multiplied by the
2648 width of the font. */
2649
2650 /* If we found a font, this font should give us the right
2651 metrics. If we didn't find a font, use the frame's
2652 default font and calculate the width of the character
2653 from the charset width; this is what old redisplay code
2654 did. */
2655 pcm = x_per_char_metric (font, &char2b);
2656 if (font_not_found_p || !pcm)
2657 {
2658 int charset = CHAR_CHARSET (it->char_to_display);
2659
2660 it->glyph_not_available_p = 1;
2661 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2662 * CHARSET_WIDTH (charset));
2663 it->phys_ascent = FONT_BASE (font) + boff;
2664 it->phys_descent = FONT_DESCENT (font) - boff;
2665 }
2666 else
2667 {
2668 it->pixel_width = pcm->width;
2669 it->phys_ascent = pcm->ascent + boff;
2670 it->phys_descent = pcm->descent - boff;
2671 if (it->glyph_row
2672 && (pcm->lbearing < 0
2673 || pcm->rbearing > pcm->width))
2674 it->glyph_row->contains_overlapping_glyphs_p = 1;
2675 }
2676 it->nglyphs = 1;
2677 it->ascent = FONT_BASE (font) + boff;
2678 it->descent = FONT_DESCENT (font) - boff;
2679 if (face->box != FACE_NO_BOX)
2680 {
2681 int thick = face->box_line_width;
2682
2683 if (thick > 0)
2684 {
2685 it->ascent += thick;
2686 it->descent += thick;
2687 }
2688 else
2689 thick = - thick;
2690
2691 if (it->start_of_box_run_p)
2692 it->pixel_width += thick;
2693 if (it->end_of_box_run_p)
2694 it->pixel_width += thick;
2695 }
2696
2697 /* If face has an overline, add the height of the overline
2698 (1 pixel) and a 1 pixel margin to the character height. */
2699 if (face->overline_p)
2700 it->ascent += 2;
2701
2702 take_vertical_position_into_account (it);
2703
2704 if (it->glyph_row)
2705 x_append_glyph (it);
2706 }
2707 it->multibyte_p = saved_multibyte_p;
2708 }
2709 else if (it->what == IT_COMPOSITION)
2710 {
2711 /* Note: A composition is represented as one glyph in the
2712 glyph matrix. There are no padding glyphs. */
2713 XChar2b char2b;
2714 XFontStruct *font;
2715 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2716 XCharStruct *pcm;
2717 int font_not_found_p;
2718 struct font_info *font_info;
2719 int boff; /* baseline offset */
2720 struct composition *cmp = composition_table[it->cmp_id];
2721
2722 /* Maybe translate single-byte characters to multibyte. */
2723 it->char_to_display = it->c;
2724 if (unibyte_display_via_language_environment
2725 && SINGLE_BYTE_CHAR_P (it->c)
2726 && (it->c >= 0240
2727 || (it->c >= 0200
2728 && !NILP (Vnonascii_translation_table))))
2729 {
2730 it->char_to_display = unibyte_char_to_multibyte (it->c);
2731 }
2732
2733 /* Get face and font to use. Encode IT->char_to_display. */
2734 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2735 face = FACE_FROM_ID (it->f, it->face_id);
2736 x_get_char_face_and_encoding (it->f, it->char_to_display,
2737 it->face_id, &char2b, it->multibyte_p);
2738 font = face->font;
2739
2740 /* When no suitable font found, use the default font. */
2741 font_not_found_p = font == NULL;
2742 if (font_not_found_p)
2743 {
2744 font = FRAME_FONT (it->f);
2745 boff = it->f->output_data.mac->baseline_offset;
2746 font_info = NULL;
2747 }
2748 else
2749 {
2750 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2751 boff = font_info->baseline_offset;
2752 if (font_info->vertical_centering)
2753 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2754 }
2755
2756 /* There are no padding glyphs, so there is only one glyph to
2757 produce for the composition. Important is that pixel_width,
2758 ascent and descent are the values of what is drawn by
2759 draw_glyphs (i.e. the values of the overall glyphs composed). */
2760 it->nglyphs = 1;
2761
2762 /* If we have not yet calculated pixel size data of glyphs of
2763 the composition for the current face font, calculate them
2764 now. Theoretically, we have to check all fonts for the
2765 glyphs, but that requires much time and memory space. So,
2766 here we check only the font of the first glyph. This leads
2767 to incorrect display very rarely, and C-l (recenter) can
2768 correct the display anyway. */
2769 if (cmp->font != (void *) font)
2770 {
2771 /* Ascent and descent of the font of the first character of
2772 this composition (adjusted by baseline offset). Ascent
2773 and descent of overall glyphs should not be less than
2774 them respectively. */
2775 int font_ascent = FONT_BASE (font) + boff;
2776 int font_descent = FONT_DESCENT (font) - boff;
2777 /* Bounding box of the overall glyphs. */
2778 int leftmost, rightmost, lowest, highest;
2779 int i, width, ascent, descent;
2780
2781 cmp->font = (void *) font;
2782
2783 /* Initialize the bounding box. */
2784 pcm = x_per_char_metric (font, &char2b);
2785 if (pcm)
2786 {
2787 width = pcm->width;
2788 ascent = pcm->ascent;
2789 descent = pcm->descent;
2790 }
2791 else
2792 {
2793 width = FONT_WIDTH (font);
2794 ascent = FONT_BASE (font);
2795 descent = FONT_DESCENT (font);
2796 }
2797
2798 rightmost = width;
2799 lowest = - descent + boff;
2800 highest = ascent + boff;
2801 leftmost = 0;
2802
2803 if (font_info
2804 && font_info->default_ascent
2805 && CHAR_TABLE_P (Vuse_default_ascent)
2806 && !NILP (Faref (Vuse_default_ascent,
2807 make_number (it->char_to_display))))
2808 highest = font_info->default_ascent + boff;
2809
2810 /* Draw the first glyph at the normal position. It may be
2811 shifted to right later if some other glyphs are drawn at
2812 the left. */
2813 cmp->offsets[0] = 0;
2814 cmp->offsets[1] = boff;
2815
2816 /* Set cmp->offsets for the remaining glyphs. */
2817 for (i = 1; i < cmp->glyph_len; i++)
2818 {
2819 int left, right, btm, top;
2820 int ch = COMPOSITION_GLYPH (cmp, i);
2821 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2822
2823 face = FACE_FROM_ID (it->f, face_id);
2824 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2825 it->multibyte_p);
2826 font = face->font;
2827 if (font == NULL)
2828 {
2829 font = FRAME_FONT (it->f);
2830 boff = it->f->output_data.mac->baseline_offset;
2831 font_info = NULL;
2832 }
2833 else
2834 {
2835 font_info
2836 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2837 boff = font_info->baseline_offset;
2838 if (font_info->vertical_centering)
2839 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2840 }
2841
2842 pcm = x_per_char_metric (font, &char2b);
2843 if (pcm)
2844 {
2845 width = pcm->width;
2846 ascent = pcm->ascent;
2847 descent = pcm->descent;
2848 }
2849 else
2850 {
2851 width = FONT_WIDTH (font);
2852 ascent = 1;
2853 descent = 0;
2854 }
2855
2856 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2857 {
2858 /* Relative composition with or without
2859 alternate chars. */
2860 left = (leftmost + rightmost - width) / 2;
2861 btm = - descent + boff;
2862 if (font_info && font_info->relative_compose
2863 && (! CHAR_TABLE_P (Vignore_relative_composition)
2864 || NILP (Faref (Vignore_relative_composition,
2865 make_number (ch)))))
2866 {
2867
2868 if (- descent >= font_info->relative_compose)
2869 /* One extra pixel between two glyphs. */
2870 btm = highest + 1;
2871 else if (ascent <= 0)
2872 /* One extra pixel between two glyphs. */
2873 btm = lowest - 1 - ascent - descent;
2874 }
2875 }
2876 else
2877 {
2878 /* A composition rule is specified by an integer
2879 value that encodes global and new reference
2880 points (GREF and NREF). GREF and NREF are
2881 specified by numbers as below:
2882
2883 0---1---2 -- ascent
2884 | |
2885 | |
2886 | |
2887 9--10--11 -- center
2888 | |
2889 ---3---4---5--- baseline
2890 | |
2891 6---7---8 -- descent
2892 */
2893 int rule = COMPOSITION_RULE (cmp, i);
2894 int gref, nref, grefx, grefy, nrefx, nrefy;
2895
2896 COMPOSITION_DECODE_RULE (rule, gref, nref);
2897 grefx = gref % 3, nrefx = nref % 3;
2898 grefy = gref / 3, nrefy = nref / 3;
2899
2900 left = (leftmost
2901 + grefx * (rightmost - leftmost) / 2
2902 - nrefx * width / 2);
2903 btm = ((grefy == 0 ? highest
2904 : grefy == 1 ? 0
2905 : grefy == 2 ? lowest
2906 : (highest + lowest) / 2)
2907 - (nrefy == 0 ? ascent + descent
2908 : nrefy == 1 ? descent - boff
2909 : nrefy == 2 ? 0
2910 : (ascent + descent) / 2));
2911 }
2912
2913 cmp->offsets[i * 2] = left;
2914 cmp->offsets[i * 2 + 1] = btm + descent;
2915
2916 /* Update the bounding box of the overall glyphs. */
2917 right = left + width;
2918 top = btm + descent + ascent;
2919 if (left < leftmost)
2920 leftmost = left;
2921 if (right > rightmost)
2922 rightmost = right;
2923 if (top > highest)
2924 highest = top;
2925 if (btm < lowest)
2926 lowest = btm;
2927 }
2928
2929 /* If there are glyphs whose x-offsets are negative,
2930 shift all glyphs to the right and make all x-offsets
2931 non-negative. */
2932 if (leftmost < 0)
2933 {
2934 for (i = 0; i < cmp->glyph_len; i++)
2935 cmp->offsets[i * 2] -= leftmost;
2936 rightmost -= leftmost;
2937 }
2938
2939 cmp->pixel_width = rightmost;
2940 cmp->ascent = highest;
2941 cmp->descent = - lowest;
2942 if (cmp->ascent < font_ascent)
2943 cmp->ascent = font_ascent;
2944 if (cmp->descent < font_descent)
2945 cmp->descent = font_descent;
2946 }
2947
2948 it->pixel_width = cmp->pixel_width;
2949 it->ascent = it->phys_ascent = cmp->ascent;
2950 it->descent = it->phys_descent = cmp->descent;
2951
2952 if (face->box != FACE_NO_BOX)
2953 {
2954 int thick = face->box_line_width;
2955
2956 if (thick > 0)
2957 {
2958 it->ascent += thick;
2959 it->descent += thick;
2960 }
2961 else
2962 thick = - thick;
2963
2964 if (it->start_of_box_run_p)
2965 it->pixel_width += thick;
2966 if (it->end_of_box_run_p)
2967 it->pixel_width += thick;
2968 }
2969
2970 /* If face has an overline, add the height of the overline
2971 (1 pixel) and a 1 pixel margin to the character height. */
2972 if (face->overline_p)
2973 it->ascent += 2;
2974
2975 take_vertical_position_into_account (it);
2976
2977 if (it->glyph_row)
2978 x_append_composite_glyph (it);
2979 }
2980 else if (it->what == IT_IMAGE)
2981 x_produce_image_glyph (it);
2982 else if (it->what == IT_STRETCH)
2983 x_produce_stretch_glyph (it);
2984
2985 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2986 because this isn't true for images with `:ascent 100'. */
2987 xassert (it->ascent >= 0 && it->descent >= 0);
2988 if (it->area == TEXT_AREA)
2989 it->current_x += it->pixel_width;
2990
2991 it->descent += it->extra_line_spacing;
2992
2993 it->max_ascent = max (it->max_ascent, it->ascent);
2994 it->max_descent = max (it->max_descent, it->descent);
2995 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2996 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2997 }
2998
2999
3000 /* Estimate the pixel height of the mode or top line on frame F.
3001 FACE_ID specifies what line's height to estimate. */
3002
3003 int
3004 x_estimate_mode_line_height (f, face_id)
3005 struct frame *f;
3006 enum face_id face_id;
3007 {
3008 int height = FONT_HEIGHT (FRAME_FONT (f));
3009
3010 /* This function is called so early when Emacs starts that the face
3011 cache and mode line face are not yet initialized. */
3012 if (FRAME_FACE_CACHE (f))
3013 {
3014 struct face *face = FACE_FROM_ID (f, face_id);
3015 if (face)
3016 {
3017 if (face->font)
3018 height = FONT_HEIGHT (face->font);
3019 if (face->box_line_width > 0)
3020 height += 2 * face->box_line_width;
3021 }
3022 }
3023
3024 return height;
3025 }
3026
3027 \f
3028 /***********************************************************************
3029 Glyph display
3030 ***********************************************************************/
3031
3032 /* A sequence of glyphs to be drawn in the same face.
3033
3034 This data structure is not really completely X specific, so it
3035 could possibly, at least partially, be useful for other systems. It
3036 is currently not part of the external redisplay interface because
3037 it's not clear what other systems will need. */
3038
3039 struct glyph_string
3040 {
3041 /* X-origin of the string. */
3042 int x;
3043
3044 /* Y-origin and y-position of the base line of this string. */
3045 int y, ybase;
3046
3047 /* The width of the string, not including a face extension. */
3048 int width;
3049
3050 /* The width of the string, including a face extension. */
3051 int background_width;
3052
3053 /* The height of this string. This is the height of the line this
3054 string is drawn in, and can be different from the height of the
3055 font the string is drawn in. */
3056 int height;
3057
3058 /* Number of pixels this string overwrites in front of its x-origin.
3059 This number is zero if the string has an lbearing >= 0; it is
3060 -lbearing, if the string has an lbearing < 0. */
3061 int left_overhang;
3062
3063 /* Number of pixels this string overwrites past its right-most
3064 nominal x-position, i.e. x + width. Zero if the string's
3065 rbearing is <= its nominal width, rbearing - width otherwise. */
3066 int right_overhang;
3067
3068 /* The frame on which the glyph string is drawn. */
3069 struct frame *f;
3070
3071 /* The window on which the glyph string is drawn. */
3072 struct window *w;
3073
3074 /* X display and window for convenience. */
3075 Display *display;
3076 Window window;
3077
3078 /* The glyph row for which this string was built. It determines the
3079 y-origin and height of the string. */
3080 struct glyph_row *row;
3081
3082 /* The area within row. */
3083 enum glyph_row_area area;
3084
3085 /* Characters to be drawn, and number of characters. */
3086 XChar2b *char2b;
3087 int nchars;
3088
3089 /* A face-override for drawing cursors, mouse face and similar. */
3090 enum draw_glyphs_face hl;
3091
3092 /* Face in which this string is to be drawn. */
3093 struct face *face;
3094
3095 /* Font in which this string is to be drawn. */
3096 XFontStruct *font;
3097
3098 /* Font info for this string. */
3099 struct font_info *font_info;
3100
3101 /* Non-null means this string describes (part of) a composition.
3102 All characters from char2b are drawn composed. */
3103 struct composition *cmp;
3104
3105 /* Index of this glyph string's first character in the glyph
3106 definition of CMP. If this is zero, this glyph string describes
3107 the first character of a composition. */
3108 int gidx;
3109
3110 /* 1 means this glyph strings face has to be drawn to the right end
3111 of the window's drawing area. */
3112 unsigned extends_to_end_of_line_p : 1;
3113
3114 /* 1 means the background of this string has been drawn. */
3115 unsigned background_filled_p : 1;
3116
3117 /* 1 means glyph string must be drawn with 16-bit functions. */
3118 unsigned two_byte_p : 1;
3119
3120 /* 1 means that the original font determined for drawing this glyph
3121 string could not be loaded. The member `font' has been set to
3122 the frame's default font in this case. */
3123 unsigned font_not_found_p : 1;
3124
3125 /* 1 means that the face in which this glyph string is drawn has a
3126 stipple pattern. */
3127 unsigned stippled_p : 1;
3128
3129 /* 1 means only the foreground of this glyph string must be drawn,
3130 and we should use the physical height of the line this glyph
3131 string appears in as clip rect. */
3132 unsigned for_overlaps_p : 1;
3133
3134 /* The GC to use for drawing this glyph string. */
3135 GC gc;
3136
3137 /* A pointer to the first glyph in the string. This glyph
3138 corresponds to char2b[0]. Needed to draw rectangles if
3139 font_not_found_p is 1. */
3140 struct glyph *first_glyph;
3141
3142 /* Image, if any. */
3143 struct image *img;
3144
3145 struct glyph_string *next, *prev;
3146 };
3147
3148
3149 #if 0
3150
3151 static void
3152 x_dump_glyph_string (s)
3153 struct glyph_string *s;
3154 {
3155 fprintf (stderr, "glyph string\n");
3156 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3157 s->x, s->y, s->width, s->height);
3158 fprintf (stderr, " ybase = %d\n", s->ybase);
3159 fprintf (stderr, " hl = %d\n", s->hl);
3160 fprintf (stderr, " left overhang = %d, right = %d\n",
3161 s->left_overhang, s->right_overhang);
3162 fprintf (stderr, " nchars = %d\n", s->nchars);
3163 fprintf (stderr, " extends to end of line = %d\n",
3164 s->extends_to_end_of_line_p);
3165 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3166 fprintf (stderr, " bg width = %d\n", s->background_width);
3167 }
3168
3169 #endif /* GLYPH_DEBUG */
3170
3171
3172
3173 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3174 struct glyph_string **,
3175 struct glyph_string *,
3176 struct glyph_string *));
3177 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3178 struct glyph_string **,
3179 struct glyph_string *,
3180 struct glyph_string *));
3181 static void x_append_glyph_string P_ ((struct glyph_string **,
3182 struct glyph_string **,
3183 struct glyph_string *));
3184 static int x_left_overwritten P_ ((struct glyph_string *));
3185 static int x_left_overwriting P_ ((struct glyph_string *));
3186 static int x_right_overwritten P_ ((struct glyph_string *));
3187 static int x_right_overwriting P_ ((struct glyph_string *));
3188 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3189 int));
3190 static void x_init_glyph_string P_ ((struct glyph_string *,
3191 XChar2b *, struct window *,
3192 struct glyph_row *,
3193 enum glyph_row_area, int,
3194 enum draw_glyphs_face));
3195 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3196 enum glyph_row_area, int, int,
3197 enum draw_glyphs_face, int));
3198 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3199 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3200 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3201 int));
3202 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3203 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3204 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3205 static void x_draw_glyph_string P_ ((struct glyph_string *));
3206 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3207 static void x_set_cursor_gc P_ ((struct glyph_string *));
3208 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3209 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3210 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3211 int *, int *));
3212 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
3213 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3214 unsigned long *, double, int));*/
3215 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3216 double, int, unsigned long));
3217 static void x_setup_relief_colors P_ ((struct glyph_string *));
3218 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3219 static void x_draw_image_relief P_ ((struct glyph_string *));
3220 static void x_draw_image_foreground P_ ((struct glyph_string *));
3221 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3222 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3223 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3224 int, int, int));
3225 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
3226 int, int, int, int, Rect *));
3227 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
3228 int, int, int, Rect *));
3229 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3230 enum glyph_row_area));
3231 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3232 struct glyph_row *,
3233 enum glyph_row_area, int, int));
3234
3235 #if GLYPH_DEBUG
3236 static void x_check_font P_ ((struct frame *, XFontStruct *));
3237 #endif
3238
3239
3240 /* Append the list of glyph strings with head H and tail T to the list
3241 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3242
3243 static INLINE void
3244 x_append_glyph_string_lists (head, tail, h, t)
3245 struct glyph_string **head, **tail;
3246 struct glyph_string *h, *t;
3247 {
3248 if (h)
3249 {
3250 if (*head)
3251 (*tail)->next = h;
3252 else
3253 *head = h;
3254 h->prev = *tail;
3255 *tail = t;
3256 }
3257 }
3258
3259
3260 /* Prepend the list of glyph strings with head H and tail T to the
3261 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3262 result. */
3263
3264 static INLINE void
3265 x_prepend_glyph_string_lists (head, tail, h, t)
3266 struct glyph_string **head, **tail;
3267 struct glyph_string *h, *t;
3268 {
3269 if (h)
3270 {
3271 if (*head)
3272 (*head)->prev = t;
3273 else
3274 *tail = t;
3275 t->next = *head;
3276 *head = h;
3277 }
3278 }
3279
3280
3281 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3282 Set *HEAD and *TAIL to the resulting list. */
3283
3284 static INLINE void
3285 x_append_glyph_string (head, tail, s)
3286 struct glyph_string **head, **tail;
3287 struct glyph_string *s;
3288 {
3289 s->next = s->prev = NULL;
3290 x_append_glyph_string_lists (head, tail, s, s);
3291 }
3292
3293
3294 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3295 face. */
3296
3297 static void
3298 x_set_cursor_gc (s)
3299 struct glyph_string *s;
3300 {
3301 if (s->font == FRAME_FONT (s->f)
3302 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3303 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3304 && !s->cmp)
3305 s->gc = s->f->output_data.mac->cursor_gc;
3306 else
3307 {
3308 /* Cursor on non-default face: must merge. */
3309 XGCValues xgcv;
3310 unsigned long mask;
3311
3312 xgcv.background = s->f->output_data.mac->cursor_pixel;
3313 xgcv.foreground = s->face->background;
3314
3315 /* If the glyph would be invisible, try a different foreground. */
3316 if (xgcv.foreground == xgcv.background)
3317 xgcv.foreground = s->face->foreground;
3318 if (xgcv.foreground == xgcv.background)
3319 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3320 if (xgcv.foreground == xgcv.background)
3321 xgcv.foreground = s->face->foreground;
3322
3323 /* Make sure the cursor is distinct from text in this face. */
3324 if (xgcv.background == s->face->background
3325 && xgcv.foreground == s->face->foreground)
3326 {
3327 xgcv.background = s->face->foreground;
3328 xgcv.foreground = s->face->background;
3329 }
3330
3331 IF_DEBUG (x_check_font (s->f, s->font));
3332 xgcv.font = s->font;
3333 mask = GCForeground | GCBackground | GCFont;
3334
3335 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3336 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3337 mask, &xgcv);
3338 else
3339 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3340 = XCreateGC (s->display, s->window, mask, &xgcv);
3341
3342 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3343 }
3344 }
3345
3346
3347 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3348
3349 static void
3350 x_set_mouse_face_gc (s)
3351 struct glyph_string *s;
3352 {
3353 int face_id;
3354 struct face *face;
3355
3356 /* What face has to be used last for the mouse face? */
3357 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3358 face = FACE_FROM_ID (s->f, face_id);
3359 if (face == NULL)
3360 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3361
3362 if (s->first_glyph->type == CHAR_GLYPH)
3363 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3364 else
3365 face_id = FACE_FOR_CHAR (s->f, face, 0);
3366 s->face = FACE_FROM_ID (s->f, face_id);
3367 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3368
3369 /* If font in this face is same as S->font, use it. */
3370 if (s->font == s->face->font)
3371 s->gc = s->face->gc;
3372 else
3373 {
3374 /* Otherwise construct scratch_cursor_gc with values from FACE
3375 but font FONT. */
3376 XGCValues xgcv;
3377 unsigned long mask;
3378
3379 xgcv.background = s->face->background;
3380 xgcv.foreground = s->face->foreground;
3381 IF_DEBUG (x_check_font (s->f, s->font));
3382 xgcv.font = s->font;
3383 mask = GCForeground | GCBackground | GCFont;
3384
3385 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3386 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3387 mask, &xgcv);
3388 else
3389 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3390 = XCreateGC (s->display, s->window, mask, &xgcv);
3391
3392 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3393 }
3394
3395 xassert (s->gc != 0);
3396 }
3397
3398
3399 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3400 Faces to use in the mode line have already been computed when the
3401 matrix was built, so there isn't much to do, here. */
3402
3403 static INLINE void
3404 x_set_mode_line_face_gc (s)
3405 struct glyph_string *s;
3406 {
3407 s->gc = s->face->gc;
3408 }
3409
3410
3411 /* Set S->gc of glyph string S for drawing that glyph string. Set
3412 S->stippled_p to a non-zero value if the face of S has a stipple
3413 pattern. */
3414
3415 static INLINE void
3416 x_set_glyph_string_gc (s)
3417 struct glyph_string *s;
3418 {
3419 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3420
3421 if (s->hl == DRAW_NORMAL_TEXT)
3422 {
3423 s->gc = s->face->gc;
3424 s->stippled_p = s->face->stipple != 0;
3425 }
3426 else if (s->hl == DRAW_INVERSE_VIDEO)
3427 {
3428 x_set_mode_line_face_gc (s);
3429 s->stippled_p = s->face->stipple != 0;
3430 }
3431 else if (s->hl == DRAW_CURSOR)
3432 {
3433 x_set_cursor_gc (s);
3434 s->stippled_p = 0;
3435 }
3436 else if (s->hl == DRAW_MOUSE_FACE)
3437 {
3438 x_set_mouse_face_gc (s);
3439 s->stippled_p = s->face->stipple != 0;
3440 }
3441 else if (s->hl == DRAW_IMAGE_RAISED
3442 || s->hl == DRAW_IMAGE_SUNKEN)
3443 {
3444 s->gc = s->face->gc;
3445 s->stippled_p = s->face->stipple != 0;
3446 }
3447 else
3448 {
3449 s->gc = s->face->gc;
3450 s->stippled_p = s->face->stipple != 0;
3451 }
3452
3453 /* GC must have been set. */
3454 xassert (s->gc != 0);
3455 }
3456
3457
3458 /* Return in *R the clipping rectangle for glyph string S. */
3459
3460 static void
3461 x_get_glyph_string_clip_rect (s, r)
3462 struct glyph_string *s;
3463 Rect *r;
3464 {
3465 int r_height, r_width;
3466
3467 if (s->row->full_width_p)
3468 {
3469 /* Draw full-width. X coordinates are relative to S->w->left. */
3470 int canon_x = CANON_X_UNIT (s->f);
3471
3472 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3473 r_width = XFASTINT (s->w->width) * canon_x;
3474
3475 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3476 {
3477 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3478 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3479 r->left -= width;
3480 }
3481
3482 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3483
3484 /* Unless displaying a mode or menu bar line, which are always
3485 fully visible, clip to the visible part of the row. */
3486 if (s->w->pseudo_window_p)
3487 r_height = s->row->visible_height;
3488 else
3489 r_height = s->height;
3490 }
3491 else
3492 {
3493 /* This is a text line that may be partially visible. */
3494 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3495 r_width = window_box_width (s->w, s->area);
3496 r_height = s->row->visible_height;
3497 }
3498
3499 /* If S draws overlapping rows, it's sufficient to use the top and
3500 bottom of the window for clipping because this glyph string
3501 intentionally draws over other lines. */
3502 if (s->for_overlaps_p)
3503 {
3504 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3505 r_height = window_text_bottom_y (s->w) - r->top;
3506 }
3507 else
3508 {
3509 /* Don't use S->y for clipping because it doesn't take partially
3510 visible lines into account. For example, it can be negative for
3511 partially visible lines at the top of a window. */
3512 if (!s->row->full_width_p
3513 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3514 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3515 else
3516 r->top = max (0, s->row->y);
3517
3518 /* If drawing a tool-bar window, draw it over the internal border
3519 at the top of the window. */
3520 if (s->w == XWINDOW (s->f->tool_bar_window))
3521 r->top -= s->f->output_data.mac->internal_border_width;
3522 }
3523
3524 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3525
3526 r->bottom = r->top + r_height;
3527 r->right = r->left + r_width;
3528 }
3529
3530
3531 /* Set clipping for output of glyph string S. S may be part of a mode
3532 line or menu if we don't have X toolkit support. */
3533
3534 static INLINE void
3535 x_set_glyph_string_clipping (s)
3536 struct glyph_string *s;
3537 {
3538 Rect r;
3539 x_get_glyph_string_clip_rect (s, &r);
3540 mac_set_clip_rectangle (s->display, s->window, &r);
3541 }
3542
3543
3544 /* Compute left and right overhang of glyph string S. If S is a glyph
3545 string for a composition, assume overhangs don't exist. */
3546
3547 static INLINE void
3548 x_compute_glyph_string_overhangs (s)
3549 struct glyph_string *s;
3550 {
3551 if (s->cmp == NULL
3552 && s->first_glyph->type == CHAR_GLYPH)
3553 {
3554 XCharStruct cs;
3555 int direction, font_ascent, font_descent;
3556 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3557 &font_ascent, &font_descent, &cs);
3558 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3559 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3560 }
3561 }
3562
3563
3564 /* Compute overhangs and x-positions for glyph string S and its
3565 predecessors, or successors. X is the starting x-position for S.
3566 BACKWARD_P non-zero means process predecessors. */
3567
3568 static void
3569 x_compute_overhangs_and_x (s, x, backward_p)
3570 struct glyph_string *s;
3571 int x;
3572 int backward_p;
3573 {
3574 if (backward_p)
3575 {
3576 while (s)
3577 {
3578 x_compute_glyph_string_overhangs (s);
3579 x -= s->width;
3580 s->x = x;
3581 s = s->prev;
3582 }
3583 }
3584 else
3585 {
3586 while (s)
3587 {
3588 x_compute_glyph_string_overhangs (s);
3589 s->x = x;
3590 x += s->width;
3591 s = s->next;
3592 }
3593 }
3594 }
3595
3596
3597 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3598 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3599 assumed to be zero. */
3600
3601 void
3602 x_get_glyph_overhangs (glyph, f, left, right)
3603 struct glyph *glyph;
3604 struct frame *f;
3605 int *left, *right;
3606 {
3607 *left = *right = 0;
3608
3609 if (glyph->type == CHAR_GLYPH)
3610 {
3611 XFontStruct *font;
3612 struct face *face;
3613 struct font_info *font_info;
3614 XChar2b char2b;
3615 XCharStruct *pcm;
3616
3617 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3618 font = face->font;
3619 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3620 if (font
3621 && (pcm = x_per_char_metric (font, &char2b)))
3622 {
3623 if (pcm->rbearing > pcm->width)
3624 *right = pcm->rbearing - pcm->width;
3625 if (pcm->lbearing < 0)
3626 *left = -pcm->lbearing;
3627 }
3628 }
3629 }
3630
3631
3632 /* Return the index of the first glyph preceding glyph string S that
3633 is overwritten by S because of S's left overhang. Value is -1
3634 if no glyphs are overwritten. */
3635
3636 static int
3637 x_left_overwritten (s)
3638 struct glyph_string *s;
3639 {
3640 int k;
3641
3642 if (s->left_overhang)
3643 {
3644 int x = 0, i;
3645 struct glyph *glyphs = s->row->glyphs[s->area];
3646 int first = s->first_glyph - glyphs;
3647
3648 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3649 x -= glyphs[i].pixel_width;
3650
3651 k = i + 1;
3652 }
3653 else
3654 k = -1;
3655
3656 return k;
3657 }
3658
3659
3660 /* Return the index of the first glyph preceding glyph string S that
3661 is overwriting S because of its right overhang. Value is -1 if no
3662 glyph in front of S overwrites S. */
3663
3664 static int
3665 x_left_overwriting (s)
3666 struct glyph_string *s;
3667 {
3668 int i, k, x;
3669 struct glyph *glyphs = s->row->glyphs[s->area];
3670 int first = s->first_glyph - glyphs;
3671
3672 k = -1;
3673 x = 0;
3674 for (i = first - 1; i >= 0; --i)
3675 {
3676 int left, right;
3677 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3678 if (x + right > 0)
3679 k = i;
3680 x -= glyphs[i].pixel_width;
3681 }
3682
3683 return k;
3684 }
3685
3686
3687 /* Return the index of the last glyph following glyph string S that is
3688 not overwritten by S because of S's right overhang. Value is -1 if
3689 no such glyph is found. */
3690
3691 static int
3692 x_right_overwritten (s)
3693 struct glyph_string *s;
3694 {
3695 int k = -1;
3696
3697 if (s->right_overhang)
3698 {
3699 int x = 0, i;
3700 struct glyph *glyphs = s->row->glyphs[s->area];
3701 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3702 int end = s->row->used[s->area];
3703
3704 for (i = first; i < end && s->right_overhang > x; ++i)
3705 x += glyphs[i].pixel_width;
3706
3707 k = i;
3708 }
3709
3710 return k;
3711 }
3712
3713
3714 /* Return the index of the last glyph following glyph string S that
3715 overwrites S because of its left overhang. Value is negative
3716 if no such glyph is found. */
3717
3718 static int
3719 x_right_overwriting (s)
3720 struct glyph_string *s;
3721 {
3722 int i, k, x;
3723 int end = s->row->used[s->area];
3724 struct glyph *glyphs = s->row->glyphs[s->area];
3725 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3726
3727 k = -1;
3728 x = 0;
3729 for (i = first; i < end; ++i)
3730 {
3731 int left, right;
3732 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3733 if (x - left < 0)
3734 k = i;
3735 x += glyphs[i].pixel_width;
3736 }
3737
3738 return k;
3739 }
3740
3741
3742 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3743
3744 static INLINE void
3745 x_clear_glyph_string_rect (s, x, y, w, h)
3746 struct glyph_string *s;
3747 int x, y, w, h;
3748 {
3749 XGCValues xgcv;
3750
3751 xgcv.foreground = s->gc->background;
3752 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3753 }
3754
3755
3756 /* Draw the background of glyph_string S. If S->background_filled_p
3757 is non-zero don't draw it. FORCE_P non-zero means draw the
3758 background even if it wouldn't be drawn normally. This is used
3759 when a string preceding S draws into the background of S, or S
3760 contains the first component of a composition. */
3761
3762 static void
3763 x_draw_glyph_string_background (s, force_p)
3764 struct glyph_string *s;
3765 int force_p;
3766 {
3767 /* Nothing to do if background has already been drawn or if it
3768 shouldn't be drawn in the first place. */
3769 if (!s->background_filled_p)
3770 {
3771 int box_line_width = max (s->face->box_line_width, 0);
3772
3773 #if 0 /* MAC_TODO: stipple */
3774 if (s->stippled_p)
3775 {
3776 /* Fill background with a stipple pattern. */
3777 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3778 XFillRectangle (s->display, s->window, s->gc, s->x,
3779 s->y + box_line_width,
3780 s->background_width,
3781 s->height - 2 * box_line_width);
3782 XSetFillStyle (s->display, s->gc, FillSolid);
3783 s->background_filled_p = 1;
3784 }
3785 else
3786 #endif
3787 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3788 || s->font_not_found_p
3789 || s->extends_to_end_of_line_p
3790 || force_p)
3791 {
3792 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3793 s->background_width,
3794 s->height - 2 * box_line_width);
3795 s->background_filled_p = 1;
3796 }
3797 }
3798 }
3799
3800
3801 /* Draw the foreground of glyph string S. */
3802
3803 static void
3804 x_draw_glyph_string_foreground (s)
3805 struct glyph_string *s;
3806 {
3807 int i, x;
3808
3809 /* If first glyph of S has a left box line, start drawing the text
3810 of S to the right of that box line. */
3811 if (s->face->box != FACE_NO_BOX
3812 && s->first_glyph->left_box_line_p)
3813 x = s->x + abs (s->face->box_line_width);
3814 else
3815 x = s->x;
3816
3817 /* Draw characters of S as rectangles if S's font could not be
3818 loaded. */
3819 if (s->font_not_found_p)
3820 {
3821 for (i = 0; i < s->nchars; ++i)
3822 {
3823 struct glyph *g = s->first_glyph + i;
3824 mac_draw_rectangle (s->display, s->window,
3825 s->gc, x, s->y, g->pixel_width - 1,
3826 s->height - 1);
3827 x += g->pixel_width;
3828 }
3829 }
3830 else
3831 {
3832 char *char1b = (char *) s->char2b;
3833 int boff = s->font_info->baseline_offset;
3834
3835 if (s->font_info->vertical_centering)
3836 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3837
3838 /* If we can use 8-bit functions, condense S->char2b. */
3839 if (!s->two_byte_p)
3840 for (i = 0; i < s->nchars; ++i)
3841 char1b[i] = s->char2b[i].byte2;
3842
3843 /* Draw text with XDrawString if background has already been
3844 filled. Otherwise, use XDrawImageString. (Note that
3845 XDrawImageString is usually faster than XDrawString.) Always
3846 use XDrawImageString when drawing the cursor so that there is
3847 no chance that characters under a box cursor are invisible. */
3848 if (s->for_overlaps_p
3849 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3850 {
3851 /* Draw characters with 16-bit or 8-bit functions. */
3852 if (s->two_byte_p)
3853 XDrawString16 (s->display, s->window, s->gc, x,
3854 s->ybase - boff, s->char2b, s->nchars);
3855 else
3856 XDrawString (s->display, s->window, s->gc, x,
3857 s->ybase - boff, char1b, s->nchars);
3858 }
3859 else
3860 {
3861 if (s->two_byte_p)
3862 XDrawImageString16 (s->display, s->window, s->gc, x,
3863 s->ybase - boff, s->char2b, s->nchars);
3864 else
3865 XDrawImageString (s->display, s->window, s->gc, x,
3866 s->ybase - boff, char1b, s->nchars);
3867 }
3868 }
3869 }
3870
3871 /* Draw the foreground of composite glyph string S. */
3872
3873 static void
3874 x_draw_composite_glyph_string_foreground (s)
3875 struct glyph_string *s;
3876 {
3877 int i, x;
3878
3879 /* If first glyph of S has a left box line, start drawing the text
3880 of S to the right of that box line. */
3881 if (s->face->box != FACE_NO_BOX
3882 && s->first_glyph->left_box_line_p)
3883 x = s->x + abs (s->face->box_line_width);
3884 else
3885 x = s->x;
3886
3887 /* S is a glyph string for a composition. S->gidx is the index of
3888 the first character drawn for glyphs of this composition.
3889 S->gidx == 0 means we are drawing the very first character of
3890 this composition. */
3891
3892 /* Draw a rectangle for the composition if the font for the very
3893 first character of the composition could not be loaded. */
3894 if (s->font_not_found_p)
3895 {
3896 if (s->gidx == 0)
3897 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3898 s->width - 1, s->height - 1);
3899 }
3900 else
3901 {
3902 for (i = 0; i < s->nchars; i++, ++s->gidx)
3903 XDrawString16 (s->display, s->window, s->gc,
3904 x + s->cmp->offsets[s->gidx * 2],
3905 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3906 s->char2b + i, 1);
3907 }
3908 }
3909
3910
3911 #ifdef USE_X_TOOLKIT
3912
3913 static struct frame *x_frame_of_widget P_ ((Widget));
3914
3915
3916 /* Return the frame on which widget WIDGET is used.. Abort if frame
3917 cannot be determined. */
3918
3919 static struct frame *
3920 x_frame_of_widget (widget)
3921 Widget widget;
3922 {
3923 struct x_display_info *dpyinfo;
3924 Lisp_Object tail;
3925 struct frame *f;
3926
3927 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3928
3929 /* Find the top-level shell of the widget. Note that this function
3930 can be called when the widget is not yet realized, so XtWindow
3931 (widget) == 0. That's the reason we can't simply use
3932 x_any_window_to_frame. */
3933 while (!XtIsTopLevelShell (widget))
3934 widget = XtParent (widget);
3935
3936 /* Look for a frame with that top-level widget. Allocate the color
3937 on that frame to get the right gamma correction value. */
3938 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3939 if (GC_FRAMEP (XCAR (tail))
3940 && (f = XFRAME (XCAR (tail)),
3941 (f->output_data.nothing != 1
3942 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3943 && f->output_data.x->widget == widget)
3944 return f;
3945
3946 abort ();
3947 }
3948
3949
3950 /* Allocate the color COLOR->pixel on the screen and display of
3951 widget WIDGET in colormap CMAP. If an exact match cannot be
3952 allocated, try the nearest color available. Value is non-zero
3953 if successful. This is called from lwlib. */
3954
3955 int
3956 x_alloc_nearest_color_for_widget (widget, cmap, color)
3957 Widget widget;
3958 Colormap cmap;
3959 XColor *color;
3960 {
3961 struct frame *f = x_frame_of_widget (widget);
3962 return x_alloc_nearest_color (f, cmap, color);
3963 }
3964
3965
3966 #endif /* USE_X_TOOLKIT */
3967
3968 #if 0 /* MAC_TODO */
3969
3970 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3971 CMAP. If an exact match can't be allocated, try the nearest color
3972 available. Value is non-zero if successful. Set *COLOR to the
3973 color allocated. */
3974
3975 int
3976 x_alloc_nearest_color (f, cmap, color)
3977 struct frame *f;
3978 Colormap cmap;
3979 XColor *color;
3980 {
3981 Display *display = FRAME_X_DISPLAY (f);
3982 Screen *screen = FRAME_X_SCREEN (f);
3983 int rc;
3984
3985 gamma_correct (f, color);
3986 rc = XAllocColor (display, cmap, color);
3987 if (rc == 0)
3988 {
3989 /* If we got to this point, the colormap is full, so we're going
3990 to try to get the next closest color. The algorithm used is
3991 a least-squares matching, which is what X uses for closest
3992 color matching with StaticColor visuals. */
3993 int nearest, i;
3994 unsigned long nearest_delta = ~0;
3995 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3996 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3997
3998 for (i = 0; i < ncells; ++i)
3999 cells[i].pixel = i;
4000 XQueryColors (display, cmap, cells, ncells);
4001
4002 for (nearest = i = 0; i < ncells; ++i)
4003 {
4004 long dred = (color->red >> 8) - (cells[i].red >> 8);
4005 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
4006 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
4007 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
4008
4009 if (delta < nearest_delta)
4010 {
4011 nearest = i;
4012 nearest_delta = delta;
4013 }
4014 }
4015
4016 color->red = cells[nearest].red;
4017 color->green = cells[nearest].green;
4018 color->blue = cells[nearest].blue;
4019 rc = XAllocColor (display, cmap, color);
4020 }
4021
4022 #ifdef DEBUG_X_COLORS
4023 if (rc)
4024 register_color (color->pixel);
4025 #endif /* DEBUG_X_COLORS */
4026
4027 return rc;
4028 }
4029
4030
4031 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4032 It's necessary to do this instead of just using PIXEL directly to
4033 get color reference counts right. */
4034
4035 unsigned long
4036 x_copy_color (f, pixel)
4037 struct frame *f;
4038 unsigned long pixel;
4039 {
4040 XColor color;
4041
4042 color.pixel = pixel;
4043 BLOCK_INPUT;
4044 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4045 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4046 UNBLOCK_INPUT;
4047 #ifdef DEBUG_X_COLORS
4048 register_color (pixel);
4049 #endif
4050 return color.pixel;
4051 }
4052
4053
4054 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4055 It's necessary to do this instead of just using PIXEL directly to
4056 get color reference counts right. */
4057
4058 unsigned long
4059 x_copy_dpy_color (dpy, cmap, pixel)
4060 Display *dpy;
4061 Colormap cmap;
4062 unsigned long pixel;
4063 {
4064 XColor color;
4065
4066 color.pixel = pixel;
4067 BLOCK_INPUT;
4068 XQueryColor (dpy, cmap, &color);
4069 XAllocColor (dpy, cmap, &color);
4070 UNBLOCK_INPUT;
4071 #ifdef DEBUG_X_COLORS
4072 register_color (pixel);
4073 #endif
4074 return color.pixel;
4075 }
4076
4077 #endif /* MAC_TODO */
4078
4079 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
4080 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4081 If this produces the same color as COLOR, try a color where all RGB
4082 values have DELTA added. Return the allocated color in *COLOR.
4083 DISPLAY is the X display, CMAP is the colormap to operate on.
4084 Value is non-zero if successful. */
4085
4086 static int
4087 mac_alloc_lighter_color (f, color, factor, delta)
4088 struct frame *f;
4089 unsigned long *color;
4090 double factor;
4091 int delta;
4092 {
4093 unsigned long new;
4094
4095 /* Change RGB values by specified FACTOR. Avoid overflow! */
4096 xassert (factor >= 0);
4097 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4098 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4099 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4100 if (new == *color)
4101 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4102 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4103 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4104
4105 /* MAC_TODO: Map to palette and retry with delta if same? */
4106 /* MAC_TODO: Free colors (if using palette)? */
4107
4108 if (new == *color)
4109 return 0;
4110
4111 *color = new;
4112
4113 return 1;
4114 }
4115
4116
4117 /* Set up the foreground color for drawing relief lines of glyph
4118 string S. RELIEF is a pointer to a struct relief containing the GC
4119 with which lines will be drawn. Use a color that is FACTOR or
4120 DELTA lighter or darker than the relief's background which is found
4121 in S->f->output_data.x->relief_background. If such a color cannot
4122 be allocated, use DEFAULT_PIXEL, instead. */
4123
4124 static void
4125 x_setup_relief_color (f, relief, factor, delta, default_pixel)
4126 struct frame *f;
4127 struct relief *relief;
4128 double factor;
4129 int delta;
4130 unsigned long default_pixel;
4131 {
4132 XGCValues xgcv;
4133 struct mac_output *di = f->output_data.mac;
4134 unsigned long mask = GCForeground;
4135 unsigned long pixel;
4136 unsigned long background = di->relief_background;
4137 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4138
4139 /* MAC_TODO: Free colors (if using palette)? */
4140
4141 /* Allocate new color. */
4142 xgcv.foreground = default_pixel;
4143 pixel = background;
4144 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4145 {
4146 relief->allocated_p = 1;
4147 xgcv.foreground = relief->pixel = pixel;
4148 }
4149
4150 if (relief->gc == 0)
4151 {
4152 #if 0 /* MAC_TODO: stipple */
4153 xgcv.stipple = dpyinfo->gray;
4154 mask |= GCStipple;
4155 #endif
4156 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4157 }
4158 else
4159 XChangeGC (NULL, relief->gc, mask, &xgcv);
4160 }
4161
4162
4163 /* Set up colors for the relief lines around glyph string S. */
4164
4165 static void
4166 x_setup_relief_colors (s)
4167 struct glyph_string *s;
4168 {
4169 struct mac_output *di = s->f->output_data.mac;
4170 unsigned long color;
4171
4172 if (s->face->use_box_color_for_shadows_p)
4173 color = s->face->box_color;
4174 else
4175 {
4176 XGCValues xgcv;
4177
4178 /* Get the background color of the face. */
4179 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4180 color = xgcv.background;
4181 }
4182
4183 if (di->white_relief.gc == 0
4184 || color != di->relief_background)
4185 {
4186 di->relief_background = color;
4187 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4188 WHITE_PIX_DEFAULT (s->f));
4189 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4190 BLACK_PIX_DEFAULT (s->f));
4191 }
4192 }
4193
4194
4195 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4196 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4197 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4198 relief. LEFT_P non-zero means draw a relief on the left side of
4199 the rectangle. RIGHT_P non-zero means draw a relief on the right
4200 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4201 when drawing. */
4202
4203 static void
4204 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4205 raised_p, left_p, right_p, clip_rect)
4206 struct frame *f;
4207 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4208 Rect *clip_rect;
4209 {
4210 int i;
4211 GC gc;
4212
4213 if (raised_p)
4214 gc = f->output_data.mac->white_relief.gc;
4215 else
4216 gc = f->output_data.mac->black_relief.gc;
4217 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4218
4219 /* Top. */
4220 for (i = 0; i < width; ++i)
4221 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4222 left_x + i * left_p, top_y + i,
4223 right_x + 1 - i * right_p, top_y + i);
4224
4225 /* Left. */
4226 if (left_p)
4227 for (i = 0; i < width; ++i)
4228 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4229 left_x + i, top_y + i, left_x + i, bottom_y - i);
4230
4231 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4232 if (raised_p)
4233 gc = f->output_data.mac->black_relief.gc;
4234 else
4235 gc = f->output_data.mac->white_relief.gc;
4236 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4237 clip_rect);
4238
4239 /* Bottom. */
4240 for (i = 0; i < width; ++i)
4241 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4242 left_x + i * left_p, bottom_y - i,
4243 right_x + 1 - i * right_p, bottom_y - i);
4244
4245 /* Right. */
4246 if (right_p)
4247 for (i = 0; i < width; ++i)
4248 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4249 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4250
4251 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4252 }
4253
4254
4255 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4256 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4257 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4258 left side of the rectangle. RIGHT_P non-zero means draw a line
4259 on the right side of the rectangle. CLIP_RECT is the clipping
4260 rectangle to use when drawing. */
4261
4262 static void
4263 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4264 left_p, right_p, clip_rect)
4265 struct glyph_string *s;
4266 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4267 Rect *clip_rect;
4268 {
4269 XGCValues xgcv;
4270
4271 xgcv.foreground = s->face->box_color;
4272 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4273
4274 /* Top. */
4275 XFillRectangle (s->display, s->window, &xgcv,
4276 left_x, top_y, right_x - left_x, width);
4277
4278 /* Left. */
4279 if (left_p)
4280 XFillRectangle (s->display, s->window, &xgcv,
4281 left_x, top_y, width, bottom_y - top_y);
4282
4283 /* Bottom. */
4284 XFillRectangle (s->display, s->window, &xgcv,
4285 left_x, bottom_y - width, right_x - left_x, width);
4286
4287 /* Right. */
4288 if (right_p)
4289 XFillRectangle (s->display, s->window, &xgcv,
4290 right_x - width, top_y, width, bottom_y - top_y);
4291
4292 mac_reset_clipping (s->display, s->window);
4293 }
4294
4295
4296 /* Draw a box around glyph string S. */
4297
4298 static void
4299 x_draw_glyph_string_box (s)
4300 struct glyph_string *s;
4301 {
4302 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4303 int left_p, right_p;
4304 struct glyph *last_glyph;
4305 Rect clip_rect;
4306
4307 last_x = window_box_right (s->w, s->area);
4308 if (s->row->full_width_p
4309 && !s->w->pseudo_window_p)
4310 {
4311 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4312 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4313 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4314 }
4315
4316 /* The glyph that may have a right box line. */
4317 last_glyph = (s->cmp || s->img
4318 ? s->first_glyph
4319 : s->first_glyph + s->nchars - 1);
4320
4321 width = abs (s->face->box_line_width);
4322 raised_p = s->face->box == FACE_RAISED_BOX;
4323 left_x = s->x;
4324 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
4325 ? last_x - 1
4326 : min (last_x, s->x + s->background_width) - 1));
4327 top_y = s->y;
4328 bottom_y = top_y + s->height - 1;
4329
4330 left_p = (s->first_glyph->left_box_line_p
4331 || (s->hl == DRAW_MOUSE_FACE
4332 && (s->prev == NULL
4333 || s->prev->hl != s->hl)));
4334 right_p = (last_glyph->right_box_line_p
4335 || (s->hl == DRAW_MOUSE_FACE
4336 && (s->next == NULL
4337 || s->next->hl != s->hl)));
4338
4339 x_get_glyph_string_clip_rect (s, &clip_rect);
4340
4341 if (s->face->box == FACE_SIMPLE_BOX)
4342 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4343 left_p, right_p, &clip_rect);
4344 else
4345 {
4346 x_setup_relief_colors (s);
4347 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4348 width, raised_p, left_p, right_p, &clip_rect);
4349 }
4350 }
4351
4352
4353 /* Draw foreground of image glyph string S. */
4354
4355 static void
4356 x_draw_image_foreground (s)
4357 struct glyph_string *s;
4358 {
4359 int x;
4360 int y = s->ybase - image_ascent (s->img, s->face);
4361
4362 /* If first glyph of S has a left box line, start drawing it to the
4363 right of that line. */
4364 if (s->face->box != FACE_NO_BOX
4365 && s->first_glyph->left_box_line_p)
4366 x = s->x + abs (s->face->box_line_width);
4367 else
4368 x = s->x;
4369
4370 /* If there is a margin around the image, adjust x- and y-position
4371 by that margin. */
4372 x += s->img->hmargin;
4373 y += s->img->vmargin;
4374
4375 if (s->img->pixmap)
4376 {
4377 #if 0 /* MAC_TODO: image mask */
4378 if (s->img->mask)
4379 {
4380 /* We can't set both a clip mask and use XSetClipRectangles
4381 because the latter also sets a clip mask. We also can't
4382 trust on the shape extension to be available
4383 (XShapeCombineRegion). So, compute the rectangle to draw
4384 manually. */
4385 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4386 | GCFunction);
4387 XGCValues xgcv;
4388 XRectangle clip_rect, image_rect, r;
4389
4390 xgcv.clip_mask = s->img->mask;
4391 xgcv.clip_x_origin = x;
4392 xgcv.clip_y_origin = y;
4393 xgcv.function = GXcopy;
4394 XChangeGC (s->display, s->gc, mask, &xgcv);
4395
4396 x_get_glyph_string_clip_rect (s, &clip_rect);
4397 image_rect.x = x;
4398 image_rect.y = y;
4399 image_rect.width = s->img->width;
4400 image_rect.height = s->img->height;
4401 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4402 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4403 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4404 }
4405 else
4406 #endif /* MAC_TODO */
4407 {
4408 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4409 0, 0, s->img->width, s->img->height, x, y);
4410
4411 /* When the image has a mask, we can expect that at
4412 least part of a mouse highlight or a block cursor will
4413 be visible. If the image doesn't have a mask, make
4414 a block cursor visible by drawing a rectangle around
4415 the image. I believe it's looking better if we do
4416 nothing here for mouse-face. */
4417 if (s->hl == DRAW_CURSOR)
4418 {
4419 int r = s->img->relief;
4420 if (r < 0) r = -r;
4421 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4422 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4423 }
4424 }
4425 }
4426 else
4427 /* Draw a rectangle if image could not be loaded. */
4428 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4429 s->img->width - 1, s->img->height - 1);
4430 }
4431
4432
4433
4434 /* Draw a relief around the image glyph string S. */
4435
4436 static void
4437 x_draw_image_relief (s)
4438 struct glyph_string *s;
4439 {
4440 int x0, y0, x1, y1, thick, raised_p;
4441 Rect r;
4442 int x;
4443 int y = s->ybase - image_ascent (s->img, s->face);
4444
4445 /* If first glyph of S has a left box line, start drawing it to the
4446 right of that line. */
4447 if (s->face->box != FACE_NO_BOX
4448 && s->first_glyph->left_box_line_p)
4449 x = s->x + abs (s->face->box_line_width);
4450 else
4451 x = s->x;
4452
4453 /* If there is a margin around the image, adjust x- and y-position
4454 by that margin. */
4455 x += s->img->hmargin;
4456 y += s->img->vmargin;
4457
4458 if (s->hl == DRAW_IMAGE_SUNKEN
4459 || s->hl == DRAW_IMAGE_RAISED)
4460 {
4461 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4462 raised_p = s->hl == DRAW_IMAGE_RAISED;
4463 }
4464 else
4465 {
4466 thick = abs (s->img->relief);
4467 raised_p = s->img->relief > 0;
4468 }
4469
4470 x0 = x - thick;
4471 y0 = y - thick;
4472 x1 = x + s->img->width + thick - 1;
4473 y1 = y + s->img->height + thick - 1;
4474
4475 x_setup_relief_colors (s);
4476 x_get_glyph_string_clip_rect (s, &r);
4477 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4478 }
4479
4480
4481 /* Draw the foreground of image glyph string S to PIXMAP. */
4482
4483 static void
4484 x_draw_image_foreground_1 (s, pixmap)
4485 struct glyph_string *s;
4486 Pixmap pixmap;
4487 {
4488 int x;
4489 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4490
4491 /* If first glyph of S has a left box line, start drawing it to the
4492 right of that line. */
4493 if (s->face->box != FACE_NO_BOX
4494 && s->first_glyph->left_box_line_p)
4495 x = abs (s->face->box_line_width);
4496 else
4497 x = 0;
4498
4499 /* If there is a margin around the image, adjust x- and y-position
4500 by that margin. */
4501 x += s->img->hmargin;
4502 y += s->img->vmargin;
4503
4504 if (s->img->pixmap)
4505 {
4506 #if 0 /* MAC_TODO: image mask */
4507 if (s->img->mask)
4508 {
4509 /* We can't set both a clip mask and use XSetClipRectangles
4510 because the latter also sets a clip mask. We also can't
4511 trust on the shape extension to be available
4512 (XShapeCombineRegion). So, compute the rectangle to draw
4513 manually. */
4514 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4515 | GCFunction);
4516 XGCValues xgcv;
4517
4518 xgcv.clip_mask = s->img->mask;
4519 xgcv.clip_x_origin = x;
4520 xgcv.clip_y_origin = y;
4521 xgcv.function = GXcopy;
4522 XChangeGC (s->display, s->gc, mask, &xgcv);
4523
4524 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4525 0, 0, s->img->width, s->img->height, x, y);
4526 XSetClipMask (s->display, s->gc, None);
4527 }
4528 else
4529 #endif /* MAC_TODO */
4530 {
4531 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4532 0, 0, s->img->width, s->img->height, x, y);
4533
4534 /* When the image has a mask, we can expect that at
4535 least part of a mouse highlight or a block cursor will
4536 be visible. If the image doesn't have a mask, make
4537 a block cursor visible by drawing a rectangle around
4538 the image. I believe it's looking better if we do
4539 nothing here for mouse-face. */
4540 if (s->hl == DRAW_CURSOR)
4541 {
4542 int r = s->img->relief;
4543 if (r < 0) r = -r;
4544 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4545 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4546 }
4547 }
4548 }
4549 else
4550 /* Draw a rectangle if image could not be loaded. */
4551 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4552 s->img->width - 1, s->img->height - 1);
4553 }
4554
4555
4556 /* Draw part of the background of glyph string S. X, Y, W, and H
4557 give the rectangle to draw. */
4558
4559 static void
4560 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4561 struct glyph_string *s;
4562 int x, y, w, h;
4563 {
4564 #if 0 /* MAC_TODO: stipple */
4565 if (s->stippled_p)
4566 {
4567 /* Fill background with a stipple pattern. */
4568 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4569 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4570 XSetFillStyle (s->display, s->gc, FillSolid);
4571 }
4572 else
4573 #endif /* MAC_TODO */
4574 x_clear_glyph_string_rect (s, x, y, w, h);
4575 }
4576
4577
4578 /* Draw image glyph string S.
4579
4580 s->y
4581 s->x +-------------------------
4582 | s->face->box
4583 |
4584 | +-------------------------
4585 | | s->img->vmargin
4586 | |
4587 | | +-------------------
4588 | | | the image
4589
4590 */
4591
4592 static void
4593 x_draw_image_glyph_string (s)
4594 struct glyph_string *s;
4595 {
4596 int x, y;
4597 int box_line_hwidth = abs (s->face->box_line_width);
4598 int box_line_vwidth = max (s->face->box_line_width, 0);
4599 int height;
4600 Pixmap pixmap = 0;
4601
4602 height = s->height - 2 * box_line_vwidth;
4603
4604 /* Fill background with face under the image. Do it only if row is
4605 taller than image or if image has a clip mask to reduce
4606 flickering. */
4607 s->stippled_p = s->face->stipple != 0;
4608 if (height > s->img->height
4609 || s->img->hmargin
4610 || s->img->vmargin
4611 #if 0 /* TODO: image mask */
4612 || s->img->mask
4613 #endif
4614 || s->img->pixmap == 0
4615 || s->width != s->background_width)
4616 {
4617 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4618 x = s->x + box_line_hwidth;
4619 else
4620 x = s->x;
4621
4622 y = s->y + box_line_vwidth;
4623 #if 0 /* TODO: image mask */
4624 if (s->img->mask)
4625 {
4626 /* Create a pixmap as large as the glyph string. Fill it
4627 with the background color. Copy the image to it, using
4628 its mask. Copy the temporary pixmap to the display. */
4629 Screen *screen = FRAME_X_SCREEN (s->f);
4630 int depth = DefaultDepthOfScreen (screen);
4631
4632 /* Create a pixmap as large as the glyph string. */
4633 pixmap = XCreatePixmap (s->display, s->window,
4634 s->background_width,
4635 s->height, depth);
4636
4637 /* Don't clip in the following because we're working on the
4638 pixmap. */
4639 XSetClipMask (s->display, s->gc, None);
4640
4641 /* Fill the pixmap with the background color/stipple. */
4642 if (s->stippled_p)
4643 {
4644 /* Fill background with a stipple pattern. */
4645 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4646 XFillRectangle (s->display, pixmap, s->gc,
4647 0, 0, s->background_width, s->height);
4648 XSetFillStyle (s->display, s->gc, FillSolid);
4649 }
4650 else
4651 {
4652 XGCValues xgcv;
4653 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4654 &xgcv);
4655 XSetForeground (s->display, s->gc, xgcv.background);
4656 XFillRectangle (s->display, pixmap, s->gc,
4657 0, 0, s->background_width, s->height);
4658 XSetForeground (s->display, s->gc, xgcv.foreground);
4659 }
4660 }
4661 else
4662 #endif
4663 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4664
4665 s->background_filled_p = 1;
4666 }
4667
4668 /* Draw the foreground. */
4669 if (pixmap != 0)
4670 {
4671 x_draw_image_foreground_1 (s, pixmap);
4672 x_set_glyph_string_clipping (s);
4673 mac_copy_area (s->display, pixmap, s->window, s->gc,
4674 0, 0, s->background_width, s->height, s->x, s->y);
4675 mac_reset_clipping (s->display, s->window);
4676 XFreePixmap (s->display, pixmap);
4677 }
4678 else
4679 x_draw_image_foreground (s);
4680
4681 /* If we must draw a relief around the image, do it. */
4682 if (s->img->relief
4683 || s->hl == DRAW_IMAGE_RAISED
4684 || s->hl == DRAW_IMAGE_SUNKEN)
4685 x_draw_image_relief (s);
4686 }
4687
4688
4689 /* Draw stretch glyph string S. */
4690
4691 static void
4692 x_draw_stretch_glyph_string (s)
4693 struct glyph_string *s;
4694 {
4695 xassert (s->first_glyph->type == STRETCH_GLYPH);
4696 s->stippled_p = s->face->stipple != 0;
4697
4698 if (s->hl == DRAW_CURSOR
4699 && !x_stretch_cursor_p)
4700 {
4701 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4702 as wide as the stretch glyph. */
4703 int width = min (CANON_X_UNIT (s->f), s->background_width);
4704
4705 /* Draw cursor. */
4706 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4707
4708 /* Clear rest using the GC of the original non-cursor face. */
4709 if (width < s->background_width)
4710 {
4711 GC gc = s->face->gc;
4712 int x = s->x + width, y = s->y;
4713 int w = s->background_width - width, h = s->height;
4714 Rect r;
4715
4716 if (s->row->mouse_face_p
4717 && cursor_in_mouse_face_p (s->w))
4718 {
4719 x_set_mouse_face_gc (s);
4720 gc = s->gc;
4721 }
4722 else
4723 gc = s->face->gc;
4724
4725 x_get_glyph_string_clip_rect (s, &r);
4726 mac_set_clip_rectangle (s->display, s->window, &r);
4727
4728 #if 0 /* MAC_TODO: stipple */
4729 if (s->face->stipple)
4730 {
4731 /* Fill background with a stipple pattern. */
4732 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4733 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4734 XSetFillStyle (s->display, gc, FillSolid);
4735 }
4736 else
4737 #endif /* MAC_TODO */
4738 {
4739 XGCValues xgcv;
4740 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4741 XSetForeground (s->display, gc, xgcv.background);
4742 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4743 XSetForeground (s->display, gc, xgcv.foreground);
4744 }
4745
4746 mac_reset_clipping (s->display, s->window);
4747 }
4748 }
4749 else if (!s->background_filled_p)
4750 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4751 s->height);
4752
4753 s->background_filled_p = 1;
4754 }
4755
4756
4757 /* Draw glyph string S. */
4758
4759 static void
4760 x_draw_glyph_string (s)
4761 struct glyph_string *s;
4762 {
4763 int relief_drawn_p = 0;
4764
4765 /* If S draws into the background of its successor, draw the
4766 background of the successor first so that S can draw into it.
4767 This makes S->next use XDrawString instead of XDrawImageString. */
4768 if (s->next && s->right_overhang && !s->for_overlaps_p)
4769 {
4770 xassert (s->next->img == NULL);
4771 x_set_glyph_string_gc (s->next);
4772 x_set_glyph_string_clipping (s->next);
4773 x_draw_glyph_string_background (s->next, 1);
4774
4775 }
4776
4777 /* Set up S->gc, set clipping and draw S. */
4778 x_set_glyph_string_gc (s);
4779
4780 /* Draw relief (if any) in advance for char/composition so that the
4781 glyph string can be drawn over it. */
4782 if (!s->for_overlaps_p
4783 && s->face->box != FACE_NO_BOX
4784 && (s->first_glyph->type == CHAR_GLYPH
4785 || s->first_glyph->type == COMPOSITE_GLYPH))
4786
4787 {
4788 x_set_glyph_string_clipping (s);
4789 x_draw_glyph_string_background (s, 1);
4790 x_draw_glyph_string_box (s);
4791 x_set_glyph_string_clipping (s);
4792 relief_drawn_p = 1;
4793 }
4794 else
4795 x_set_glyph_string_clipping (s);
4796
4797 switch (s->first_glyph->type)
4798 {
4799 case IMAGE_GLYPH:
4800 x_draw_image_glyph_string (s);
4801 break;
4802
4803 case STRETCH_GLYPH:
4804 x_draw_stretch_glyph_string (s);
4805 break;
4806
4807 case CHAR_GLYPH:
4808 if (s->for_overlaps_p)
4809 s->background_filled_p = 1;
4810 else
4811 x_draw_glyph_string_background (s, 0);
4812 x_draw_glyph_string_foreground (s);
4813 break;
4814
4815 case COMPOSITE_GLYPH:
4816 if (s->for_overlaps_p || s->gidx > 0)
4817 s->background_filled_p = 1;
4818 else
4819 x_draw_glyph_string_background (s, 1);
4820 x_draw_composite_glyph_string_foreground (s);
4821 break;
4822
4823 default:
4824 abort ();
4825 }
4826
4827 if (!s->for_overlaps_p)
4828 {
4829 /* Draw underline. */
4830 if (s->face->underline_p)
4831 {
4832 unsigned long h = 1;
4833 unsigned long dy = s->height - h;
4834
4835 if (s->face->underline_defaulted_p)
4836 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4837 s->width, h);
4838 else
4839 {
4840 XGCValues xgcv;
4841 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4842 XSetForeground (s->display, s->gc, s->face->underline_color);
4843 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4844 s->width, h);
4845 XSetForeground (s->display, s->gc, xgcv.foreground);
4846 }
4847 }
4848
4849 /* Draw overline. */
4850 if (s->face->overline_p)
4851 {
4852 unsigned long dy = 0, h = 1;
4853
4854 if (s->face->overline_color_defaulted_p)
4855 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4856 s->width, h);
4857 else
4858 {
4859 XGCValues xgcv;
4860 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4861 XSetForeground (s->display, s->gc, s->face->overline_color);
4862 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4863 s->width, h);
4864 XSetForeground (s->display, s->gc, xgcv.foreground);
4865 }
4866 }
4867
4868 /* Draw strike-through. */
4869 if (s->face->strike_through_p)
4870 {
4871 unsigned long h = 1;
4872 unsigned long dy = (s->height - h) / 2;
4873
4874 if (s->face->strike_through_color_defaulted_p)
4875 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4876 s->width, h);
4877 else
4878 {
4879 XGCValues xgcv;
4880 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4881 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4882 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4883 s->width, h);
4884 XSetForeground (s->display, s->gc, xgcv.foreground);
4885 }
4886 }
4887
4888 /* Draw relief. */
4889 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4890 x_draw_glyph_string_box (s);
4891 }
4892
4893 /* Reset clipping. */
4894 mac_reset_clipping (s->display, s->window);
4895 }
4896
4897
4898 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4899 struct face **, int));
4900
4901
4902 /* Fill glyph string S with composition components specified by S->cmp.
4903
4904 FACES is an array of faces for all components of this composition.
4905 S->gidx is the index of the first component for S.
4906 OVERLAPS_P non-zero means S should draw the foreground only, and
4907 use its physical height for clipping.
4908
4909 Value is the index of a component not in S. */
4910
4911 static int
4912 x_fill_composite_glyph_string (s, faces, overlaps_p)
4913 struct glyph_string *s;
4914 struct face **faces;
4915 int overlaps_p;
4916 {
4917 int i;
4918
4919 xassert (s);
4920
4921 s->for_overlaps_p = overlaps_p;
4922
4923 s->face = faces[s->gidx];
4924 s->font = s->face->font;
4925 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4926
4927 /* For all glyphs of this composition, starting at the offset
4928 S->gidx, until we reach the end of the definition or encounter a
4929 glyph that requires the different face, add it to S. */
4930 ++s->nchars;
4931 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4932 ++s->nchars;
4933
4934 /* All glyph strings for the same composition has the same width,
4935 i.e. the width set for the first component of the composition. */
4936
4937 s->width = s->first_glyph->pixel_width;
4938
4939 /* If the specified font could not be loaded, use the frame's
4940 default font, but record the fact that we couldn't load it in
4941 the glyph string so that we can draw rectangles for the
4942 characters of the glyph string. */
4943 if (s->font == NULL)
4944 {
4945 s->font_not_found_p = 1;
4946 s->font = FRAME_FONT (s->f);
4947 }
4948
4949 /* Adjust base line for subscript/superscript text. */
4950 s->ybase += s->first_glyph->voffset;
4951
4952 xassert (s->face && s->face->gc);
4953
4954 /* This glyph string must always be drawn with 16-bit functions. */
4955 s->two_byte_p = 1;
4956
4957 return s->gidx + s->nchars;
4958 }
4959
4960
4961 /* Fill glyph string S from a sequence of character glyphs.
4962
4963 FACE_ID is the face id of the string. START is the index of the
4964 first glyph to consider, END is the index of the last + 1.
4965 OVERLAPS_P non-zero means S should draw the foreground only, and
4966 use its physical height for clipping.
4967
4968 Value is the index of the first glyph not in S. */
4969
4970 static int
4971 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4972 struct glyph_string *s;
4973 int face_id;
4974 int start, end, overlaps_p;
4975 {
4976 struct glyph *glyph, *last;
4977 int voffset;
4978 int glyph_not_available_p;
4979
4980 xassert (s->f == XFRAME (s->w->frame));
4981 xassert (s->nchars == 0);
4982 xassert (start >= 0 && end > start);
4983
4984 s->for_overlaps_p = overlaps_p;
4985 glyph = s->row->glyphs[s->area] + start;
4986 last = s->row->glyphs[s->area] + end;
4987 voffset = glyph->voffset;
4988
4989 glyph_not_available_p = glyph->glyph_not_available_p;
4990
4991 while (glyph < last
4992 && glyph->type == CHAR_GLYPH
4993 && glyph->voffset == voffset
4994 /* Same face id implies same font, nowadays. */
4995 && glyph->face_id == face_id
4996 && glyph->glyph_not_available_p == glyph_not_available_p)
4997 {
4998 int two_byte_p;
4999
5000 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
5001 s->char2b + s->nchars,
5002 &two_byte_p);
5003 s->two_byte_p = two_byte_p;
5004 ++s->nchars;
5005 xassert (s->nchars <= end - start);
5006 s->width += glyph->pixel_width;
5007 ++glyph;
5008 }
5009
5010 s->font = s->face->font;
5011 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5012
5013 /* If the specified font could not be loaded, use the frame's font,
5014 but record the fact that we couldn't load it in
5015 S->font_not_found_p so that we can draw rectangles for the
5016 characters of the glyph string. */
5017 if (s->font == NULL || glyph_not_available_p)
5018 {
5019 s->font_not_found_p = 1;
5020 s->font = FRAME_FONT (s->f);
5021 }
5022
5023 /* Adjust base line for subscript/superscript text. */
5024 s->ybase += voffset;
5025
5026 xassert (s->face && s->face->gc);
5027 return glyph - s->row->glyphs[s->area];
5028 }
5029
5030
5031 /* Fill glyph string S from image glyph S->first_glyph. */
5032
5033 static void
5034 x_fill_image_glyph_string (s)
5035 struct glyph_string *s;
5036 {
5037 xassert (s->first_glyph->type == IMAGE_GLYPH);
5038 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5039 xassert (s->img);
5040 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5041 s->font = s->face->font;
5042 s->width = s->first_glyph->pixel_width;
5043
5044 /* Adjust base line for subscript/superscript text. */
5045 s->ybase += s->first_glyph->voffset;
5046 }
5047
5048
5049 /* Fill glyph string S from a sequence of stretch glyphs.
5050
5051 ROW is the glyph row in which the glyphs are found, AREA is the
5052 area within the row. START is the index of the first glyph to
5053 consider, END is the index of the last + 1.
5054
5055 Value is the index of the first glyph not in S. */
5056
5057 static int
5058 x_fill_stretch_glyph_string (s, row, area, start, end)
5059 struct glyph_string *s;
5060 struct glyph_row *row;
5061 enum glyph_row_area area;
5062 int start, end;
5063 {
5064 struct glyph *glyph, *last;
5065 int voffset, face_id;
5066
5067 xassert (s->first_glyph->type == STRETCH_GLYPH);
5068
5069 glyph = s->row->glyphs[s->area] + start;
5070 last = s->row->glyphs[s->area] + end;
5071 face_id = glyph->face_id;
5072 s->face = FACE_FROM_ID (s->f, face_id);
5073 s->font = s->face->font;
5074 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5075 s->width = glyph->pixel_width;
5076 voffset = glyph->voffset;
5077
5078 for (++glyph;
5079 (glyph < last
5080 && glyph->type == STRETCH_GLYPH
5081 && glyph->voffset == voffset
5082 && glyph->face_id == face_id);
5083 ++glyph)
5084 s->width += glyph->pixel_width;
5085
5086 /* Adjust base line for subscript/superscript text. */
5087 s->ybase += voffset;
5088
5089 xassert (s->face);
5090 return glyph - s->row->glyphs[s->area];
5091 }
5092
5093
5094 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
5095 of XChar2b structures for S; it can't be allocated in
5096 x_init_glyph_string because it must be allocated via `alloca'. W
5097 is the window on which S is drawn. ROW and AREA are the glyph row
5098 and area within the row from which S is constructed. START is the
5099 index of the first glyph structure covered by S. HL is a
5100 face-override for drawing S. */
5101
5102 static void
5103 x_init_glyph_string (s, char2b, w, row, area, start, hl)
5104 struct glyph_string *s;
5105 XChar2b *char2b;
5106 struct window *w;
5107 struct glyph_row *row;
5108 enum glyph_row_area area;
5109 int start;
5110 enum draw_glyphs_face hl;
5111 {
5112 bzero (s, sizeof *s);
5113 s->w = w;
5114 s->f = XFRAME (w->frame);
5115 s->display = FRAME_MAC_DISPLAY (s->f);
5116 s->window = FRAME_MAC_WINDOW (s->f);
5117 s->char2b = char2b;
5118 s->hl = hl;
5119 s->row = row;
5120 s->area = area;
5121 s->first_glyph = row->glyphs[area] + start;
5122 s->height = row->height;
5123 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5124
5125 /* Display the internal border below the tool-bar window. */
5126 if (s->w == XWINDOW (s->f->tool_bar_window))
5127 s->y -= s->f->output_data.mac->internal_border_width;
5128
5129 s->ybase = s->y + row->ascent;
5130 }
5131
5132
5133 /* Set background width of glyph string S. START is the index of the
5134 first glyph following S. LAST_X is the right-most x-position + 1
5135 in the drawing area. */
5136
5137 static INLINE void
5138 x_set_glyph_string_background_width (s, start, last_x)
5139 struct glyph_string *s;
5140 int start;
5141 int last_x;
5142 {
5143 /* If the face of this glyph string has to be drawn to the end of
5144 the drawing area, set S->extends_to_end_of_line_p. */
5145 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
5146
5147 if (start == s->row->used[s->area]
5148 && s->area == TEXT_AREA
5149 && ((s->hl == DRAW_NORMAL_TEXT
5150 && (s->row->fill_line_p
5151 || s->face->background != default_face->background
5152 || s->face->stipple != default_face->stipple
5153 || s->row->mouse_face_p))
5154 || s->hl == DRAW_MOUSE_FACE
5155 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5156 && s->row->fill_line_p)))
5157 s->extends_to_end_of_line_p = 1;
5158
5159 /* If S extends its face to the end of the line, set its
5160 background_width to the distance to the right edge of the drawing
5161 area. */
5162 if (s->extends_to_end_of_line_p)
5163 s->background_width = last_x - s->x + 1;
5164 else
5165 s->background_width = s->width;
5166 }
5167
5168
5169 /* Add a glyph string for a stretch glyph to the list of strings
5170 between HEAD and TAIL. START is the index of the stretch glyph in
5171 row area AREA of glyph row ROW. END is the index of the last glyph
5172 in that glyph row area. X is the current output position assigned
5173 to the new glyph string constructed. HL overrides that face of the
5174 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5175 is the right-most x-position of the drawing area. */
5176
5177 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5178 and below -- keep them on one line. */
5179 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5180 do \
5181 { \
5182 s = (struct glyph_string *) alloca (sizeof *s); \
5183 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5184 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5185 x_append_glyph_string (&HEAD, &TAIL, s); \
5186 s->x = (X); \
5187 } \
5188 while (0)
5189
5190
5191 /* Add a glyph string for an image glyph to the list of strings
5192 between HEAD and TAIL. START is the index of the image glyph in
5193 row area AREA of glyph row ROW. END is the index of the last glyph
5194 in that glyph row area. X is the current output position assigned
5195 to the new glyph string constructed. HL overrides that face of the
5196 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5197 is the right-most x-position of the drawing area. */
5198
5199 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5200 do \
5201 { \
5202 s = (struct glyph_string *) alloca (sizeof *s); \
5203 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5204 x_fill_image_glyph_string (s); \
5205 x_append_glyph_string (&HEAD, &TAIL, s); \
5206 ++START; \
5207 s->x = (X); \
5208 } \
5209 while (0)
5210
5211
5212 /* Add a glyph string for a sequence of character glyphs to the list
5213 of strings between HEAD and TAIL. START is the index of the first
5214 glyph in row area AREA of glyph row ROW that is part of the new
5215 glyph string. END is the index of the last glyph in that glyph row
5216 area. X is the current output position assigned to the new glyph
5217 string constructed. HL overrides that face of the glyph; e.g. it
5218 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5219 right-most x-position of the drawing area. */
5220
5221 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5222 do \
5223 { \
5224 int c, face_id; \
5225 XChar2b *char2b; \
5226 \
5227 c = (ROW)->glyphs[AREA][START].u.ch; \
5228 face_id = (ROW)->glyphs[AREA][START].face_id; \
5229 \
5230 s = (struct glyph_string *) alloca (sizeof *s); \
5231 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5232 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5233 x_append_glyph_string (&HEAD, &TAIL, s); \
5234 s->x = (X); \
5235 START = x_fill_glyph_string (s, face_id, START, END, \
5236 OVERLAPS_P); \
5237 } \
5238 while (0)
5239
5240
5241 /* Add a glyph string for a composite sequence to the list of strings
5242 between HEAD and TAIL. START is the index of the first glyph in
5243 row area AREA of glyph row ROW that is part of the new glyph
5244 string. END is the index of the last glyph in that glyph row area.
5245 X is the current output position assigned to the new glyph string
5246 constructed. HL overrides that face of the glyph; e.g. it is
5247 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5248 x-position of the drawing area. */
5249
5250 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5251 do { \
5252 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5253 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5254 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5255 struct composition *cmp = composition_table[cmp_id]; \
5256 int glyph_len = cmp->glyph_len; \
5257 XChar2b *char2b; \
5258 struct face **faces; \
5259 struct glyph_string *first_s = NULL; \
5260 int n; \
5261 \
5262 base_face = base_face->ascii_face; \
5263 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5264 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5265 /* At first, fill in `char2b' and `faces'. */ \
5266 for (n = 0; n < glyph_len; n++) \
5267 { \
5268 int c = COMPOSITION_GLYPH (cmp, n); \
5269 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5270 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5271 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5272 this_face_id, char2b + n, 1); \
5273 } \
5274 \
5275 /* Make glyph_strings for each glyph sequence that is drawable by \
5276 the same face, and append them to HEAD/TAIL. */ \
5277 for (n = 0; n < cmp->glyph_len;) \
5278 { \
5279 s = (struct glyph_string *) alloca (sizeof *s); \
5280 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5281 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5282 s->cmp = cmp; \
5283 s->gidx = n; \
5284 s->x = (X); \
5285 \
5286 if (n == 0) \
5287 first_s = s; \
5288 \
5289 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5290 } \
5291 \
5292 ++START; \
5293 s = first_s; \
5294 } while (0)
5295
5296
5297 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5298 of AREA of glyph row ROW on window W between indices START and END.
5299 HL overrides the face for drawing glyph strings, e.g. it is
5300 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5301 x-positions of the drawing area.
5302
5303 This is an ugly monster macro construct because we must use alloca
5304 to allocate glyph strings (because x_draw_glyphs can be called
5305 asynchronously). */
5306
5307 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5308 do \
5309 { \
5310 HEAD = TAIL = NULL; \
5311 while (START < END) \
5312 { \
5313 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5314 switch (first_glyph->type) \
5315 { \
5316 case CHAR_GLYPH: \
5317 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5318 TAIL, HL, X, LAST_X, \
5319 OVERLAPS_P); \
5320 break; \
5321 \
5322 case COMPOSITE_GLYPH: \
5323 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5324 HEAD, TAIL, HL, X, LAST_X,\
5325 OVERLAPS_P); \
5326 break; \
5327 \
5328 case STRETCH_GLYPH: \
5329 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5330 HEAD, TAIL, HL, X, LAST_X); \
5331 break; \
5332 \
5333 case IMAGE_GLYPH: \
5334 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5335 TAIL, HL, X, LAST_X); \
5336 break; \
5337 \
5338 default: \
5339 abort (); \
5340 } \
5341 \
5342 x_set_glyph_string_background_width (s, START, LAST_X); \
5343 (X) += s->width; \
5344 } \
5345 } \
5346 while (0)
5347
5348
5349 /* Draw glyphs between START and END in AREA of ROW on window W,
5350 starting at x-position X. X is relative to AREA in W. HL is a
5351 face-override with the following meaning:
5352
5353 DRAW_NORMAL_TEXT draw normally
5354 DRAW_CURSOR draw in cursor face
5355 DRAW_MOUSE_FACE draw in mouse face.
5356 DRAW_INVERSE_VIDEO draw in mode line face
5357 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5358 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5359
5360 If OVERLAPS_P is non-zero, draw only the foreground of characters
5361 and clip to the physical height of ROW.
5362
5363 Value is the x-position reached, relative to AREA of W. */
5364
5365 static int
5366 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5367 struct window *w;
5368 int x;
5369 struct glyph_row *row;
5370 enum glyph_row_area area;
5371 int start, end;
5372 enum draw_glyphs_face hl;
5373 int overlaps_p;
5374 {
5375 struct glyph_string *head, *tail;
5376 struct glyph_string *s;
5377 int last_x, area_width;
5378 int x_reached;
5379 int i, j;
5380
5381 /* Let's rather be paranoid than getting a SEGV. */
5382 end = min (end, row->used[area]);
5383 start = max (0, start);
5384 start = min (end, start);
5385
5386 /* Translate X to frame coordinates. Set last_x to the right
5387 end of the drawing area. */
5388 if (row->full_width_p)
5389 {
5390 /* X is relative to the left edge of W, without scroll bars
5391 or fringes. */
5392 struct frame *f = XFRAME (WINDOW_FRAME (w));
5393 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5394
5395 x += window_left_x;
5396 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5397 last_x = window_left_x + area_width;
5398
5399 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5400 {
5401 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5402 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5403 last_x += width;
5404 else
5405 x -= width;
5406 }
5407
5408 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5409 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5410 }
5411 else
5412 {
5413 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5414 area_width = window_box_width (w, area);
5415 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5416 }
5417
5418 /* Build a doubly-linked list of glyph_string structures between
5419 head and tail from what we have to draw. Note that the macro
5420 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5421 the reason we use a separate variable `i'. */
5422 i = start;
5423 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5424 overlaps_p);
5425 if (tail)
5426 x_reached = tail->x + tail->background_width;
5427 else
5428 x_reached = x;
5429
5430 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5431 the row, redraw some glyphs in front or following the glyph
5432 strings built above. */
5433 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5434 {
5435 int dummy_x = 0;
5436 struct glyph_string *h, *t;
5437
5438 /* Compute overhangs for all glyph strings. */
5439 for (s = head; s; s = s->next)
5440 x_compute_glyph_string_overhangs (s);
5441
5442 /* Prepend glyph strings for glyphs in front of the first glyph
5443 string that are overwritten because of the first glyph
5444 string's left overhang. The background of all strings
5445 prepended must be drawn because the first glyph string
5446 draws over it. */
5447 i = x_left_overwritten (head);
5448 if (i >= 0)
5449 {
5450 j = i;
5451 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5452 DRAW_NORMAL_TEXT, dummy_x, last_x,
5453 overlaps_p);
5454 start = i;
5455 x_compute_overhangs_and_x (t, head->x, 1);
5456 x_prepend_glyph_string_lists (&head, &tail, h, t);
5457 }
5458
5459 /* Prepend glyph strings for glyphs in front of the first glyph
5460 string that overwrite that glyph string because of their
5461 right overhang. For these strings, only the foreground must
5462 be drawn, because it draws over the glyph string at `head'.
5463 The background must not be drawn because this would overwrite
5464 right overhangs of preceding glyphs for which no glyph
5465 strings exist. */
5466 i = x_left_overwriting (head);
5467 if (i >= 0)
5468 {
5469 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5470 DRAW_NORMAL_TEXT, dummy_x, last_x,
5471 overlaps_p);
5472 for (s = h; s; s = s->next)
5473 s->background_filled_p = 1;
5474 x_compute_overhangs_and_x (t, head->x, 1);
5475 x_prepend_glyph_string_lists (&head, &tail, h, t);
5476 }
5477
5478 /* Append glyphs strings for glyphs following the last glyph
5479 string tail that are overwritten by tail. The background of
5480 these strings has to be drawn because tail's foreground draws
5481 over it. */
5482 i = x_right_overwritten (tail);
5483 if (i >= 0)
5484 {
5485 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5486 DRAW_NORMAL_TEXT, x, last_x,
5487 overlaps_p);
5488 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5489 x_append_glyph_string_lists (&head, &tail, h, t);
5490 }
5491
5492 /* Append glyph strings for glyphs following the last glyph
5493 string tail that overwrite tail. The foreground of such
5494 glyphs has to be drawn because it writes into the background
5495 of tail. The background must not be drawn because it could
5496 paint over the foreground of following glyphs. */
5497 i = x_right_overwriting (tail);
5498 if (i >= 0)
5499 {
5500 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5501 DRAW_NORMAL_TEXT, x, last_x,
5502 overlaps_p);
5503 for (s = h; s; s = s->next)
5504 s->background_filled_p = 1;
5505 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5506 x_append_glyph_string_lists (&head, &tail, h, t);
5507 }
5508 }
5509
5510 /* Draw all strings. */
5511 for (s = head; s; s = s->next)
5512 x_draw_glyph_string (s);
5513
5514 if (area == TEXT_AREA
5515 && !row->full_width_p
5516 /* When drawing overlapping rows, only the glyph strings'
5517 foreground is drawn, which doesn't erase a cursor
5518 completely. */
5519 && !overlaps_p)
5520 {
5521 int x0 = head ? head->x : x;
5522 int x1 = tail ? tail->x + tail->background_width : x;
5523
5524 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5525 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5526
5527 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5528 {
5529 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5530 x0 -= left_area_width;
5531 x1 -= left_area_width;
5532 }
5533
5534 notice_overwritten_cursor (w, area, x0, x1,
5535 row->y, MATRIX_ROW_BOTTOM_Y (row));
5536 }
5537
5538 /* Value is the x-position up to which drawn, relative to AREA of W.
5539 This doesn't include parts drawn because of overhangs. */
5540 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5541 if (!row->full_width_p)
5542 {
5543 if (area > LEFT_MARGIN_AREA)
5544 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5545 if (area > TEXT_AREA)
5546 x_reached -= window_box_width (w, TEXT_AREA);
5547 }
5548
5549 return x_reached;
5550 }
5551
5552
5553 /* Fix the display of area AREA of overlapping row ROW in window W. */
5554
5555 static void
5556 x_fix_overlapping_area (w, row, area)
5557 struct window *w;
5558 struct glyph_row *row;
5559 enum glyph_row_area area;
5560 {
5561 int i, x;
5562
5563 BLOCK_INPUT;
5564
5565 if (area == LEFT_MARGIN_AREA)
5566 x = 0;
5567 else if (area == TEXT_AREA)
5568 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5569 else
5570 x = (window_box_width (w, LEFT_MARGIN_AREA)
5571 + window_box_width (w, TEXT_AREA));
5572
5573 for (i = 0; i < row->used[area];)
5574 {
5575 if (row->glyphs[area][i].overlaps_vertically_p)
5576 {
5577 int start = i, start_x = x;
5578
5579 do
5580 {
5581 x += row->glyphs[area][i].pixel_width;
5582 ++i;
5583 }
5584 while (i < row->used[area]
5585 && row->glyphs[area][i].overlaps_vertically_p);
5586
5587 x_draw_glyphs (w, start_x, row, area, start, i,
5588 DRAW_NORMAL_TEXT, 1);
5589 }
5590 else
5591 {
5592 x += row->glyphs[area][i].pixel_width;
5593 ++i;
5594 }
5595 }
5596
5597 UNBLOCK_INPUT;
5598 }
5599
5600
5601 /* Output LEN glyphs starting at START at the nominal cursor position.
5602 Advance the nominal cursor over the text. The global variable
5603 updated_window contains the window being updated, updated_row is
5604 the glyph row being updated, and updated_area is the area of that
5605 row being updated. */
5606
5607 static void
5608 x_write_glyphs (start, len)
5609 struct glyph *start;
5610 int len;
5611 {
5612 int x, hpos;
5613
5614 xassert (updated_window && updated_row);
5615 BLOCK_INPUT;
5616
5617 /* Write glyphs. */
5618
5619 hpos = start - updated_row->glyphs[updated_area];
5620 x = x_draw_glyphs (updated_window, output_cursor.x,
5621 updated_row, updated_area,
5622 hpos, hpos + len,
5623 DRAW_NORMAL_TEXT, 0);
5624
5625 UNBLOCK_INPUT;
5626
5627 /* Advance the output cursor. */
5628 output_cursor.hpos += len;
5629 output_cursor.x = x;
5630 }
5631
5632
5633 /* Insert LEN glyphs from START at the nominal cursor position. */
5634
5635 static void
5636 x_insert_glyphs (start, len)
5637 struct glyph *start;
5638 register int len;
5639 {
5640 struct frame *f;
5641 struct window *w;
5642 int line_height, shift_by_width, shifted_region_width;
5643 struct glyph_row *row;
5644 struct glyph *glyph;
5645 int frame_x, frame_y, hpos;
5646
5647 xassert (updated_window && updated_row);
5648 BLOCK_INPUT;
5649 w = updated_window;
5650 f = XFRAME (WINDOW_FRAME (w));
5651
5652 /* Get the height of the line we are in. */
5653 row = updated_row;
5654 line_height = row->height;
5655
5656 /* Get the width of the glyphs to insert. */
5657 shift_by_width = 0;
5658 for (glyph = start; glyph < start + len; ++glyph)
5659 shift_by_width += glyph->pixel_width;
5660
5661 /* Get the width of the region to shift right. */
5662 shifted_region_width = (window_box_width (w, updated_area)
5663 - output_cursor.x
5664 - shift_by_width);
5665
5666 /* Shift right. */
5667 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5668 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5669
5670 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5671 f->output_data.mac->normal_gc,
5672 frame_x, frame_y,
5673 shifted_region_width, line_height,
5674 frame_x + shift_by_width, frame_y);
5675
5676 /* Write the glyphs. */
5677 hpos = start - row->glyphs[updated_area];
5678 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5679 DRAW_NORMAL_TEXT, 0);
5680
5681 /* Advance the output cursor. */
5682 output_cursor.hpos += len;
5683 output_cursor.x += shift_by_width;
5684 UNBLOCK_INPUT;
5685 }
5686
5687
5688 /* Delete N glyphs at the nominal cursor position. Not implemented
5689 for X frames. */
5690
5691 static void
5692 x_delete_glyphs (n)
5693 register int n;
5694 {
5695 abort ();
5696 }
5697
5698
5699 /* Erase the current text line from the nominal cursor position
5700 (inclusive) to pixel column TO_X (exclusive). The idea is that
5701 everything from TO_X onward is already erased.
5702
5703 TO_X is a pixel position relative to updated_area of
5704 updated_window. TO_X == -1 means clear to the end of this area. */
5705
5706 static void
5707 x_clear_end_of_line (to_x)
5708 int to_x;
5709 {
5710 struct frame *f;
5711 struct window *w = updated_window;
5712 int max_x, min_y, max_y;
5713 int from_x, from_y, to_y;
5714
5715 xassert (updated_window && updated_row);
5716 f = XFRAME (w->frame);
5717
5718 if (updated_row->full_width_p)
5719 {
5720 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5721 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5722 && !w->pseudo_window_p)
5723 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5724 }
5725 else
5726 max_x = window_box_width (w, updated_area);
5727 max_y = window_text_bottom_y (w);
5728
5729 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5730 of window. For TO_X > 0, truncate to end of drawing area. */
5731 if (to_x == 0)
5732 return;
5733 else if (to_x < 0)
5734 to_x = max_x;
5735 else
5736 to_x = min (to_x, max_x);
5737
5738 to_y = min (max_y, output_cursor.y + updated_row->height);
5739
5740 /* Notice if the cursor will be cleared by this operation. */
5741 if (!updated_row->full_width_p)
5742 notice_overwritten_cursor (w, updated_area,
5743 output_cursor.x, -1,
5744 updated_row->y,
5745 MATRIX_ROW_BOTTOM_Y (updated_row));
5746
5747 from_x = output_cursor.x;
5748
5749 /* Translate to frame coordinates. */
5750 if (updated_row->full_width_p)
5751 {
5752 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5753 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5754 }
5755 else
5756 {
5757 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5758 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5759 }
5760
5761 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5762 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5763 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5764
5765 /* Prevent inadvertently clearing to end of the X window. */
5766 if (to_x > from_x && to_y > from_y)
5767 {
5768 BLOCK_INPUT;
5769 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5770 from_x, from_y, to_x - from_x, to_y - from_y,
5771 0);
5772 UNBLOCK_INPUT;
5773 }
5774 }
5775
5776
5777 /* Clear entire frame. If updating_frame is non-null, clear that
5778 frame. Otherwise clear the selected frame. */
5779
5780 static void
5781 x_clear_frame ()
5782 {
5783 struct frame *f;
5784
5785 if (updating_frame)
5786 f = updating_frame;
5787 else
5788 f = SELECTED_FRAME ();
5789
5790 /* Clearing the frame will erase any cursor, so mark them all as no
5791 longer visible. */
5792 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5793 output_cursor.hpos = output_cursor.vpos = 0;
5794 output_cursor.x = -1;
5795
5796 /* We don't set the output cursor here because there will always
5797 follow an explicit cursor_to. */
5798 BLOCK_INPUT;
5799 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5800
5801 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5802 /* We have to clear the scroll bars, too. If we have changed
5803 colors or something like that, then they should be notified. */
5804 x_scroll_bar_clear (f);
5805 #endif
5806
5807 XFlush (FRAME_MAC_DISPLAY (f));
5808 UNBLOCK_INPUT;
5809 }
5810
5811
5812 \f
5813 /* Invert the middle quarter of the frame for .15 sec. */
5814
5815 /* We use the select system call to do the waiting, so we have to make
5816 sure it's available. If it isn't, we just won't do visual bells. */
5817
5818 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5819
5820 /* Subtract the `struct timeval' values X and Y, storing the result in
5821 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5822
5823 static int
5824 timeval_subtract (result, x, y)
5825 struct timeval *result, x, y;
5826 {
5827 /* Perform the carry for the later subtraction by updating y. This
5828 is safer because on some systems the tv_sec member is unsigned. */
5829 if (x.tv_usec < y.tv_usec)
5830 {
5831 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5832 y.tv_usec -= 1000000 * nsec;
5833 y.tv_sec += nsec;
5834 }
5835
5836 if (x.tv_usec - y.tv_usec > 1000000)
5837 {
5838 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5839 y.tv_usec += 1000000 * nsec;
5840 y.tv_sec -= nsec;
5841 }
5842
5843 /* Compute the time remaining to wait. tv_usec is certainly
5844 positive. */
5845 result->tv_sec = x.tv_sec - y.tv_sec;
5846 result->tv_usec = x.tv_usec - y.tv_usec;
5847
5848 /* Return indication of whether the result should be considered
5849 negative. */
5850 return x.tv_sec < y.tv_sec;
5851 }
5852
5853 void
5854 XTflash (f)
5855 struct frame *f;
5856 {
5857 BLOCK_INPUT;
5858
5859 FlashMenuBar (0);
5860
5861 {
5862 struct timeval wakeup;
5863
5864 EMACS_GET_TIME (wakeup);
5865
5866 /* Compute time to wait until, propagating carry from usecs. */
5867 wakeup.tv_usec += 150000;
5868 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5869 wakeup.tv_usec %= 1000000;
5870
5871 /* Keep waiting until past the time wakeup. */
5872 while (1)
5873 {
5874 struct timeval timeout;
5875
5876 EMACS_GET_TIME (timeout);
5877
5878 /* In effect, timeout = wakeup - timeout.
5879 Break if result would be negative. */
5880 if (timeval_subtract (&timeout, wakeup, timeout))
5881 break;
5882
5883 /* Try to wait that long--but we might wake up sooner. */
5884 select (0, NULL, NULL, NULL, &timeout);
5885 }
5886 }
5887
5888 FlashMenuBar (0);
5889
5890 UNBLOCK_INPUT;
5891 }
5892
5893 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5894
5895
5896 /* Make audible bell. */
5897
5898 void
5899 XTring_bell ()
5900 {
5901 struct frame *f = SELECTED_FRAME ();
5902
5903 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5904 if (visible_bell)
5905 XTflash (f);
5906 else
5907 #endif
5908 {
5909 BLOCK_INPUT;
5910 SysBeep (1);
5911 XFlush (FRAME_MAC_DISPLAY (f));
5912 UNBLOCK_INPUT;
5913 }
5914 }
5915
5916
5917 \f
5918 /* Specify how many text lines, from the top of the window,
5919 should be affected by insert-lines and delete-lines operations.
5920 This, and those operations, are used only within an update
5921 that is bounded by calls to x_update_begin and x_update_end. */
5922
5923 void
5924 XTset_terminal_window (n)
5925 register int n;
5926 {
5927 /* This function intentionally left blank. */
5928 }
5929
5930
5931 \f
5932 /***********************************************************************
5933 Line Dance
5934 ***********************************************************************/
5935
5936 /* Perform an insert-lines or delete-lines operation, inserting N
5937 lines or deleting -N lines at vertical position VPOS. */
5938
5939 static void
5940 x_ins_del_lines (vpos, n)
5941 int vpos, n;
5942 {
5943 abort ();
5944 }
5945
5946
5947 /* Scroll part of the display as described by RUN. */
5948
5949 static void
5950 x_scroll_run (w, run)
5951 struct window *w;
5952 struct run *run;
5953 {
5954 struct frame *f = XFRAME (w->frame);
5955 int x, y, width, height, from_y, to_y, bottom_y;
5956
5957 /* Get frame-relative bounding box of the text display area of W,
5958 without mode lines. Include in this box the left and right
5959 fringes of W. */
5960 window_box (w, -1, &x, &y, &width, &height);
5961 width += FRAME_X_FRINGE_WIDTH (f);
5962 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5963
5964 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5965 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5966 bottom_y = y + height;
5967
5968 if (to_y < from_y)
5969 {
5970 /* Scrolling up. Make sure we don't copy part of the mode
5971 line at the bottom. */
5972 if (from_y + run->height > bottom_y)
5973 height = bottom_y - from_y;
5974 else
5975 height = run->height;
5976 }
5977 else
5978 {
5979 /* Scolling down. Make sure we don't copy over the mode line.
5980 at the bottom. */
5981 if (to_y + run->height > bottom_y)
5982 height = bottom_y - to_y;
5983 else
5984 height = run->height;
5985 }
5986
5987 BLOCK_INPUT;
5988
5989 /* Cursor off. Will be switched on again in x_update_window_end. */
5990 updated_window = w;
5991 x_clear_cursor (w);
5992
5993 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5994 f->output_data.mac->normal_gc,
5995 x, from_y,
5996 width, height,
5997 x, to_y);
5998
5999 UNBLOCK_INPUT;
6000 }
6001
6002
6003 \f
6004 /***********************************************************************
6005 Exposure Events
6006 ***********************************************************************/
6007
6008 /* Redisplay an exposed area of frame F. X and Y are the upper-left
6009 corner of the exposed rectangle. W and H are width and height of
6010 the exposed area. All are pixel values. W or H zero means redraw
6011 the entire frame. */
6012
6013 static void
6014 expose_frame (f, x, y, w, h)
6015 struct frame *f;
6016 int x, y, w, h;
6017 {
6018 Rect r;
6019 int mouse_face_overwritten_p = 0;
6020
6021 TRACE ((stderr, "expose_frame "));
6022
6023 /* No need to redraw if frame will be redrawn soon. */
6024 if (FRAME_GARBAGED_P (f))
6025 {
6026 TRACE ((stderr, " garbaged\n"));
6027 return;
6028 }
6029
6030 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6031 or deactivated here, for unknown reasons, activated scroll bars
6032 are shown in deactivated frames in some instances. */
6033 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6034 activate_scroll_bars (f);
6035 else
6036 deactivate_scroll_bars (f);
6037
6038 /* If basic faces haven't been realized yet, there is no point in
6039 trying to redraw anything. This can happen when we get an expose
6040 event while Emacs is starting, e.g. by moving another window. */
6041 if (FRAME_FACE_CACHE (f) == NULL
6042 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6043 {
6044 TRACE ((stderr, " no faces\n"));
6045 return;
6046 }
6047
6048 if (w == 0 || h == 0)
6049 {
6050 r.left = r.top = 0;
6051 r.right = CANON_X_UNIT (f) * f->width;
6052 r.bottom = CANON_Y_UNIT (f) * f->height;
6053 }
6054 else
6055 {
6056 r.left = x;
6057 r.top = y;
6058 r.right = x + w;
6059 r.bottom = y + h;
6060 }
6061
6062 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
6063 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
6064
6065 if (WINDOWP (f->tool_bar_window))
6066 mouse_face_overwritten_p
6067 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6068
6069 /* Some window managers support a focus-follows-mouse style with
6070 delayed raising of frames. Imagine a partially obscured frame,
6071 and moving the mouse into partially obscured mouse-face on that
6072 frame. The visible part of the mouse-face will be highlighted,
6073 then the WM raises the obscured frame. With at least one WM, KDE
6074 2.1, Emacs is not getting any event for the raising of the frame
6075 (even tried with SubstructureRedirectMask), only Expose events.
6076 These expose events will draw text normally, i.e. not
6077 highlighted. Which means we must redo the highlight here.
6078 Subsume it under ``we love X''. --gerd 2001-08-15 */
6079 /* Included in Windows version because Windows most likely does not
6080 do the right thing if any third party tool offers
6081 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6082 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
6083 {
6084 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6085 if (f == dpyinfo->mouse_face_mouse_frame)
6086 {
6087 int x = dpyinfo->mouse_face_mouse_x;
6088 int y = dpyinfo->mouse_face_mouse_y;
6089 clear_mouse_face (dpyinfo);
6090 note_mouse_highlight (f, x, y);
6091 }
6092 }
6093 }
6094
6095
6096 /* Redraw (parts) of all windows in the window tree rooted at W that
6097 intersect R. R contains frame pixel coordinates. */
6098
6099 static int
6100 expose_window_tree (w, r)
6101 struct window *w;
6102 Rect *r;
6103 {
6104 struct frame *f = XFRAME (w->frame);
6105 int mouse_face_overwritten_p = 0;
6106
6107 while (w && !FRAME_GARBAGED_P (f))
6108 {
6109 if (!NILP (w->hchild))
6110 mouse_face_overwritten_p
6111 |= expose_window_tree (XWINDOW (w->hchild), r);
6112 else if (!NILP (w->vchild))
6113 mouse_face_overwritten_p
6114 |= expose_window_tree (XWINDOW (w->vchild), r);
6115 else
6116 mouse_face_overwritten_p |= expose_window (w, r);
6117
6118 w = NILP (w->next) ? NULL : XWINDOW (w->next);
6119 }
6120
6121 return mouse_face_overwritten_p;
6122 }
6123
6124
6125 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
6126 which intersects rectangle R. R is in window-relative coordinates. */
6127
6128 static void
6129 expose_area (w, row, r, area)
6130 struct window *w;
6131 struct glyph_row *row;
6132 Rect *r;
6133 enum glyph_row_area area;
6134 {
6135 struct glyph *first = row->glyphs[area];
6136 struct glyph *end = row->glyphs[area] + row->used[area];
6137 struct glyph *last;
6138 int first_x, start_x, x;
6139
6140 if (area == TEXT_AREA && row->fill_line_p)
6141 /* If row extends face to end of line write the whole line. */
6142 x_draw_glyphs (w, 0, row, area,
6143 0, row->used[area],
6144 DRAW_NORMAL_TEXT, 0);
6145 else
6146 {
6147 /* Set START_X to the window-relative start position for drawing glyphs of
6148 AREA. The first glyph of the text area can be partially visible.
6149 The first glyphs of other areas cannot. */
6150 if (area == LEFT_MARGIN_AREA)
6151 start_x = 0;
6152 else if (area == TEXT_AREA)
6153 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6154 else
6155 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6156 + window_box_width (w, TEXT_AREA));
6157 x = start_x;
6158
6159 /* Find the first glyph that must be redrawn. */
6160 while (first < end
6161 && x + first->pixel_width < r->left)
6162 {
6163 x += first->pixel_width;
6164 ++first;
6165 }
6166
6167 /* Find the last one. */
6168 last = first;
6169 first_x = x;
6170 while (last < end
6171 && x < r->right)
6172 {
6173 x += last->pixel_width;
6174 ++last;
6175 }
6176
6177 /* Repaint. */
6178 if (last > first)
6179 x_draw_glyphs (w, first_x - start_x, row, area,
6180 first - row->glyphs[area],
6181 last - row->glyphs[area],
6182 DRAW_NORMAL_TEXT, 0);
6183 }
6184 }
6185
6186
6187 /* Redraw the parts of the glyph row ROW on window W intersecting
6188 rectangle R. R is in window-relative coordinates. Value is
6189 non-zero if mouse face was overwritten. */
6190
6191 static int
6192 expose_line (w, row, r)
6193 struct window *w;
6194 struct glyph_row *row;
6195 Rect *r;
6196 {
6197 xassert (row->enabled_p);
6198
6199 if (row->mode_line_p || w->pseudo_window_p)
6200 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6201 DRAW_NORMAL_TEXT, 0);
6202 else
6203 {
6204 if (row->used[LEFT_MARGIN_AREA])
6205 expose_area (w, row, r, LEFT_MARGIN_AREA);
6206 if (row->used[TEXT_AREA])
6207 expose_area (w, row, r, TEXT_AREA);
6208 if (row->used[RIGHT_MARGIN_AREA])
6209 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6210 x_draw_row_fringe_bitmaps (w, row);
6211 }
6212
6213 return row->mouse_face_p;
6214 }
6215
6216
6217 /* Return non-zero if W's cursor intersects rectangle R. */
6218
6219 static int
6220 x_phys_cursor_in_rect_p (w, r)
6221 struct window *w;
6222 Rect *r;
6223 {
6224 Rect cr, result;
6225 struct glyph *cursor_glyph;
6226
6227 cursor_glyph = get_phys_cursor_glyph (w);
6228 if (cursor_glyph)
6229 {
6230 cr.left = w->phys_cursor.x;
6231 cr.top = w->phys_cursor.y;
6232 cr.right = cr.left + cursor_glyph->pixel_width;
6233 cr.bottom = cr.top + w->phys_cursor_height;
6234 return x_intersect_rectangles (&cr, r, &result);
6235 }
6236 else
6237 return 0;
6238 }
6239
6240
6241 /* Redraw the part of window W intersection rectagle FR. Pixel
6242 coordinates in FR are frame relative. Call this function with
6243 input blocked. Value is non-zero if the exposure overwrites
6244 mouse-face. */
6245
6246 static int
6247 expose_window (w, fr)
6248 struct window *w;
6249 Rect *fr;
6250 {
6251 struct frame *f = XFRAME (w->frame);
6252 Rect wr, r;
6253 int mouse_face_overwritten_p = 0;
6254
6255 /* If window is not yet fully initialized, do nothing. This can
6256 happen when toolkit scroll bars are used and a window is split.
6257 Reconfiguring the scroll bar will generate an expose for a newly
6258 created window. */
6259 if (w->current_matrix == NULL)
6260 return 0;
6261
6262 /* When we're currently updating the window, display and current
6263 matrix usually don't agree. Arrange for a thorough display
6264 later. */
6265 if (w == updated_window)
6266 {
6267 SET_FRAME_GARBAGED (f);
6268 return 0;
6269 }
6270
6271 /* Frame-relative pixel rectangle of W. */
6272 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6273 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6274 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6275 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6276
6277 if (x_intersect_rectangles (fr, &wr, &r))
6278 {
6279 int yb = window_text_bottom_y (w);
6280 struct glyph_row *row;
6281 int cursor_cleared_p;
6282
6283 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6284 r.left, r.top, r.right, r.bottom));
6285
6286 /* Convert to window coordinates. */
6287 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6288 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6289 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6290 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6291
6292 /* Turn off the cursor. */
6293 if (!w->pseudo_window_p
6294 && x_phys_cursor_in_rect_p (w, &r))
6295 {
6296 x_clear_cursor (w);
6297 cursor_cleared_p = 1;
6298 }
6299 else
6300 cursor_cleared_p = 0;
6301
6302 /* Find the first row intersecting the rectangle R. */
6303 for (row = w->current_matrix->rows;
6304 row->enabled_p;
6305 ++row)
6306 {
6307 int y0 = row->y;
6308 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6309
6310 if ((y0 >= r.top && y0 < r.bottom)
6311 || (y1 > r.top && y1 < r.bottom)
6312 || (r.top >= y0 && r.top < y1)
6313 || (r.bottom > y0 && r.bottom < y1))
6314 {
6315 if (expose_line (w, row, &r))
6316 mouse_face_overwritten_p = 1;
6317 }
6318
6319 if (y1 >= yb)
6320 break;
6321 }
6322
6323 /* Display the mode line if there is one. */
6324 if (WINDOW_WANTS_MODELINE_P (w)
6325 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6326 row->enabled_p)
6327 && row->y < r.bottom)
6328 {
6329 if (expose_line (w, row, &r))
6330 mouse_face_overwritten_p = 1;
6331 }
6332
6333 if (!w->pseudo_window_p)
6334 {
6335 /* Draw border between windows. */
6336 x_draw_vertical_border (w);
6337
6338 /* Turn the cursor on again. */
6339 if (cursor_cleared_p)
6340 x_update_window_cursor (w, 1);
6341 }
6342 }
6343
6344 /* Display scroll bar for this window. */
6345 if (!NILP (w->vertical_scroll_bar))
6346 {
6347 ControlHandle ch
6348 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6349
6350 Draw1Control (ch);
6351 }
6352
6353 return mouse_face_overwritten_p;
6354 }
6355
6356 static int
6357 x_intersect_rectangles (r1, r2, result)
6358 Rect *r1, *r2, *result;
6359 {
6360 Rect *left, *right;
6361 Rect *upper, *lower;
6362 int intersection_p = 0;
6363
6364 /* Rerrange so that R1 is the left-most rectangle. */
6365 if (r1->left < r2->left)
6366 left = r1, right = r2;
6367 else
6368 left = r2, right = r1;
6369
6370 /* X0 of the intersection is right.x0, if this is inside R1,
6371 otherwise there is no intersection. */
6372 if (right->left <= left->right)
6373 {
6374 result->left = right->left;
6375
6376 /* The right end of the intersection is the minimum of the
6377 the right ends of left and right. */
6378 result->right = min (left->right, right->right);
6379
6380 /* Same game for Y. */
6381 if (r1->top < r2->top)
6382 upper = r1, lower = r2;
6383 else
6384 upper = r2, lower = r1;
6385
6386 /* The upper end of the intersection is lower.y0, if this is inside
6387 of upper. Otherwise, there is no intersection. */
6388 if (lower->top <= upper->bottom)
6389 {
6390 result->top = lower->top;
6391
6392 /* The lower end of the intersection is the minimum of the lower
6393 ends of upper and lower. */
6394 result->bottom = min (lower->bottom, upper->bottom);
6395 intersection_p = 1;
6396 }
6397 }
6398
6399 return intersection_p;
6400 }
6401
6402
6403
6404
6405 \f
6406 static void
6407 frame_highlight (f)
6408 struct frame *f;
6409 {
6410 x_update_cursor (f, 1);
6411 }
6412
6413 static void
6414 frame_unhighlight (f)
6415 struct frame *f;
6416 {
6417 x_update_cursor (f, 1);
6418 }
6419
6420 /* The focus has changed. Update the frames as necessary to reflect
6421 the new situation. Note that we can't change the selected frame
6422 here, because the Lisp code we are interrupting might become confused.
6423 Each event gets marked with the frame in which it occurred, so the
6424 Lisp code can tell when the switch took place by examining the events. */
6425
6426 static void
6427 x_new_focus_frame (dpyinfo, frame)
6428 struct x_display_info *dpyinfo;
6429 struct frame *frame;
6430 {
6431 struct frame *old_focus = dpyinfo->x_focus_frame;
6432
6433 if (frame != dpyinfo->x_focus_frame)
6434 {
6435 /* Set this before calling other routines, so that they see
6436 the correct value of x_focus_frame. */
6437 dpyinfo->x_focus_frame = frame;
6438
6439 if (old_focus && old_focus->auto_lower)
6440 x_lower_frame (old_focus);
6441
6442 #if 0
6443 selected_frame = frame;
6444 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6445 selected_frame);
6446 Fselect_window (selected_frame->selected_window);
6447 choose_minibuf_frame ();
6448 #endif /* ! 0 */
6449
6450 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6451 pending_autoraise_frame = dpyinfo->x_focus_frame;
6452 else
6453 pending_autoraise_frame = 0;
6454 }
6455
6456 x_frame_rehighlight (dpyinfo);
6457 }
6458
6459 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6460
6461 void
6462 x_mouse_leave (dpyinfo)
6463 struct x_display_info *dpyinfo;
6464 {
6465 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6466 }
6467
6468 /* The focus has changed, or we have redirected a frame's focus to
6469 another frame (this happens when a frame uses a surrogate
6470 mini-buffer frame). Shift the highlight as appropriate.
6471
6472 The FRAME argument doesn't necessarily have anything to do with which
6473 frame is being highlighted or un-highlighted; we only use it to find
6474 the appropriate X display info. */
6475
6476 static void
6477 XTframe_rehighlight (frame)
6478 struct frame *frame;
6479 {
6480 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6481 }
6482
6483 static void
6484 x_frame_rehighlight (dpyinfo)
6485 struct x_display_info *dpyinfo;
6486 {
6487 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6488
6489 if (dpyinfo->x_focus_frame)
6490 {
6491 dpyinfo->x_highlight_frame
6492 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6493 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6494 : dpyinfo->x_focus_frame);
6495 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6496 {
6497 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6498 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6499 }
6500 }
6501 else
6502 dpyinfo->x_highlight_frame = 0;
6503
6504 if (dpyinfo->x_highlight_frame != old_highlight)
6505 {
6506 if (old_highlight)
6507 frame_unhighlight (old_highlight);
6508 if (dpyinfo->x_highlight_frame)
6509 frame_highlight (dpyinfo->x_highlight_frame);
6510 }
6511 }
6512
6513
6514 \f
6515 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6516
6517 #if 0 /* MAC_TODO */
6518 /* Initialize mode_switch_bit and modifier_meaning. */
6519 static void
6520 x_find_modifier_meanings (dpyinfo)
6521 struct x_display_info *dpyinfo;
6522 {
6523 int min_code, max_code;
6524 KeySym *syms;
6525 int syms_per_code;
6526 XModifierKeymap *mods;
6527
6528 dpyinfo->meta_mod_mask = 0;
6529 dpyinfo->shift_lock_mask = 0;
6530 dpyinfo->alt_mod_mask = 0;
6531 dpyinfo->super_mod_mask = 0;
6532 dpyinfo->hyper_mod_mask = 0;
6533
6534 #ifdef HAVE_X11R4
6535 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6536 #else
6537 min_code = dpyinfo->display->min_keycode;
6538 max_code = dpyinfo->display->max_keycode;
6539 #endif
6540
6541 syms = XGetKeyboardMapping (dpyinfo->display,
6542 min_code, max_code - min_code + 1,
6543 &syms_per_code);
6544 mods = XGetModifierMapping (dpyinfo->display);
6545
6546 /* Scan the modifier table to see which modifier bits the Meta and
6547 Alt keysyms are on. */
6548 {
6549 int row, col; /* The row and column in the modifier table. */
6550
6551 for (row = 3; row < 8; row++)
6552 for (col = 0; col < mods->max_keypermod; col++)
6553 {
6554 KeyCode code
6555 = mods->modifiermap[(row * mods->max_keypermod) + col];
6556
6557 /* Zeroes are used for filler. Skip them. */
6558 if (code == 0)
6559 continue;
6560
6561 /* Are any of this keycode's keysyms a meta key? */
6562 {
6563 int code_col;
6564
6565 for (code_col = 0; code_col < syms_per_code; code_col++)
6566 {
6567 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6568
6569 switch (sym)
6570 {
6571 case XK_Meta_L:
6572 case XK_Meta_R:
6573 dpyinfo->meta_mod_mask |= (1 << row);
6574 break;
6575
6576 case XK_Alt_L:
6577 case XK_Alt_R:
6578 dpyinfo->alt_mod_mask |= (1 << row);
6579 break;
6580
6581 case XK_Hyper_L:
6582 case XK_Hyper_R:
6583 dpyinfo->hyper_mod_mask |= (1 << row);
6584 break;
6585
6586 case XK_Super_L:
6587 case XK_Super_R:
6588 dpyinfo->super_mod_mask |= (1 << row);
6589 break;
6590
6591 case XK_Shift_Lock:
6592 /* Ignore this if it's not on the lock modifier. */
6593 if ((1 << row) == LockMask)
6594 dpyinfo->shift_lock_mask = LockMask;
6595 break;
6596 }
6597 }
6598 }
6599 }
6600 }
6601
6602 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6603 if (! dpyinfo->meta_mod_mask)
6604 {
6605 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6606 dpyinfo->alt_mod_mask = 0;
6607 }
6608
6609 /* If some keys are both alt and meta,
6610 make them just meta, not alt. */
6611 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6612 {
6613 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6614 }
6615
6616 XFree ((char *) syms);
6617 XFreeModifiermap (mods);
6618 }
6619
6620 #endif /* MAC_TODO */
6621
6622 /* Convert between the modifier bits X uses and the modifier bits
6623 Emacs uses. */
6624
6625 static unsigned int
6626 x_mac_to_emacs_modifiers (dpyinfo, state)
6627 struct x_display_info *dpyinfo;
6628 unsigned short state;
6629 {
6630 return (((state & shiftKey) ? shift_modifier : 0)
6631 | ((state & controlKey) ? ctrl_modifier : 0)
6632 | ((state & cmdKey) ? meta_modifier : 0)
6633 | ((state & optionKey) ? alt_modifier : 0));
6634 }
6635
6636 #if 0 /* MAC_TODO */
6637 static unsigned short
6638 x_emacs_to_x_modifiers (dpyinfo, state)
6639 struct x_display_info *dpyinfo;
6640 unsigned int state;
6641 {
6642 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6643 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6644 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6645 | ((state & shift_modifier) ? ShiftMask : 0)
6646 | ((state & ctrl_modifier) ? ControlMask : 0)
6647 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6648 }
6649 #endif /* MAC_TODO */
6650
6651 /* Convert a keysym to its name. */
6652
6653 char *
6654 x_get_keysym_name (keysym)
6655 int keysym;
6656 {
6657 char *value;
6658
6659 BLOCK_INPUT;
6660 #if 0
6661 value = XKeysymToString (keysym);
6662 #else
6663 value = 0;
6664 #endif
6665 UNBLOCK_INPUT;
6666
6667 return value;
6668 }
6669
6670
6671 \f
6672 /* Mouse clicks and mouse movement. Rah. */
6673
6674 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6675 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6676 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6677 not force the value into range. */
6678
6679 void
6680 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6681 FRAME_PTR f;
6682 register int pix_x, pix_y;
6683 register int *x, *y;
6684 Rect *bounds;
6685 int noclip;
6686 {
6687 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6688 if (NILP (Vwindow_system))
6689 {
6690 *x = pix_x;
6691 *y = pix_y;
6692 return;
6693 }
6694
6695 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6696 even for negative values. */
6697 if (pix_x < 0)
6698 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6699 if (pix_y < 0)
6700 pix_y -= (f)->output_data.mac->line_height - 1;
6701
6702 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6703 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6704
6705 if (bounds)
6706 {
6707 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6708 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6709 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6710 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
6711 }
6712
6713 if (!noclip)
6714 {
6715 if (pix_x < 0)
6716 pix_x = 0;
6717 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6718 pix_x = FRAME_WINDOW_WIDTH (f);
6719
6720 if (pix_y < 0)
6721 pix_y = 0;
6722 else if (pix_y > f->height)
6723 pix_y = f->height;
6724 }
6725
6726 *x = pix_x;
6727 *y = pix_y;
6728 }
6729
6730
6731 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6732 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6733 can't tell the positions because W's display is not up to date,
6734 return 0. */
6735
6736 int
6737 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6738 struct window *w;
6739 int hpos, vpos;
6740 int *frame_x, *frame_y;
6741 {
6742 int success_p;
6743
6744 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6745 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6746
6747 if (display_completed)
6748 {
6749 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6750 struct glyph *glyph = row->glyphs[TEXT_AREA];
6751 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6752
6753 *frame_y = row->y;
6754 *frame_x = row->x;
6755 while (glyph < end)
6756 {
6757 *frame_x += glyph->pixel_width;
6758 ++glyph;
6759 }
6760
6761 success_p = 1;
6762 }
6763 else
6764 {
6765 *frame_y = *frame_x = 0;
6766 success_p = 0;
6767 }
6768
6769 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6770 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6771 return success_p;
6772 }
6773
6774
6775 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6776
6777 If the event is a button press, then note that we have grabbed
6778 the mouse. */
6779
6780 static Lisp_Object
6781 construct_mouse_click (result, event, f)
6782 struct input_event *result;
6783 EventRecord *event;
6784 struct frame *f;
6785 {
6786 Point mouseLoc;
6787
6788 result->kind = MOUSE_CLICK_EVENT;
6789 result->code = 0; /* only one mouse button */
6790 result->timestamp = event->when;
6791 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6792
6793 mouseLoc = event->where;
6794
6795 #if TARGET_API_MAC_CARBON
6796 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6797 #else
6798 SetPort (FRAME_MAC_WINDOW (f));
6799 #endif
6800
6801 GlobalToLocal (&mouseLoc);
6802 XSETINT (result->x, mouseLoc.h);
6803 XSETINT (result->y, mouseLoc.v);
6804
6805 XSETFRAME (result->frame_or_window, f);
6806
6807 result->arg = Qnil;
6808 return Qnil;
6809 }
6810
6811 \f
6812 /* Function to report a mouse movement to the mainstream Emacs code.
6813 The input handler calls this.
6814
6815 We have received a mouse movement event, which is given in *event.
6816 If the mouse is over a different glyph than it was last time, tell
6817 the mainstream emacs code by setting mouse_moved. If not, ask for
6818 another motion event, so we can check again the next time it moves. */
6819
6820 static Point last_mouse_motion_position;
6821 static Lisp_Object last_mouse_motion_frame;
6822
6823 static void
6824 note_mouse_movement (frame, pos)
6825 FRAME_PTR frame;
6826 Point *pos;
6827 {
6828 #if TARGET_API_MAC_CARBON
6829 Rect r;
6830 #endif
6831
6832 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6833 last_mouse_motion_position = *pos;
6834 XSETFRAME (last_mouse_motion_frame, frame);
6835
6836 #if TARGET_API_MAC_CARBON
6837 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6838 #else
6839 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6840 #endif
6841 {
6842 frame->mouse_moved = 1;
6843 last_mouse_scroll_bar = Qnil;
6844 note_mouse_highlight (frame, -1, -1);
6845 }
6846 /* Has the mouse moved off the glyph it was on at the last sighting? */
6847 else if (pos->h < last_mouse_glyph.left
6848 || pos->h >= last_mouse_glyph.right
6849 || pos->v < last_mouse_glyph.top
6850 || pos->v >= last_mouse_glyph.bottom)
6851 {
6852 frame->mouse_moved = 1;
6853 last_mouse_scroll_bar = Qnil;
6854 note_mouse_highlight (frame, pos->h, pos->v);
6855 }
6856 }
6857
6858 /* This is used for debugging, to turn off note_mouse_highlight. */
6859
6860 int disable_mouse_highlight;
6861
6862
6863 \f
6864 /************************************************************************
6865 Mouse Face
6866 ************************************************************************/
6867
6868 /* Find the glyph under window-relative coordinates X/Y in window W.
6869 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6870 strings. Return in *HPOS and *VPOS the row and column number of
6871 the glyph found. Return in *AREA the glyph area containing X.
6872 Value is a pointer to the glyph found or null if X/Y is not on
6873 text, or we can't tell because W's current matrix is not up to
6874 date. */
6875
6876 static struct glyph *
6877 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6878 struct window *w;
6879 int x, y;
6880 int *hpos, *vpos, *area;
6881 int buffer_only_p;
6882 {
6883 struct glyph *glyph, *end;
6884 struct glyph_row *row = NULL;
6885 int x0, i, left_area_width;
6886
6887 /* Find row containing Y. Give up if some row is not enabled. */
6888 for (i = 0; i < w->current_matrix->nrows; ++i)
6889 {
6890 row = MATRIX_ROW (w->current_matrix, i);
6891 if (!row->enabled_p)
6892 return NULL;
6893 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6894 break;
6895 }
6896
6897 *vpos = i;
6898 *hpos = 0;
6899
6900 /* Give up if Y is not in the window. */
6901 if (i == w->current_matrix->nrows)
6902 return NULL;
6903
6904 /* Get the glyph area containing X. */
6905 if (w->pseudo_window_p)
6906 {
6907 *area = TEXT_AREA;
6908 x0 = 0;
6909 }
6910 else
6911 {
6912 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6913 if (x < left_area_width)
6914 {
6915 *area = LEFT_MARGIN_AREA;
6916 x0 = 0;
6917 }
6918 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6919 {
6920 *area = TEXT_AREA;
6921 x0 = row->x + left_area_width;
6922 }
6923 else
6924 {
6925 *area = RIGHT_MARGIN_AREA;
6926 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6927 }
6928 }
6929
6930 /* Find glyph containing X. */
6931 glyph = row->glyphs[*area];
6932 end = glyph + row->used[*area];
6933 while (glyph < end)
6934 {
6935 if (x < x0 + glyph->pixel_width)
6936 {
6937 if (w->pseudo_window_p)
6938 break;
6939 else if (!buffer_only_p || BUFFERP (glyph->object))
6940 break;
6941 }
6942
6943 x0 += glyph->pixel_width;
6944 ++glyph;
6945 }
6946
6947 if (glyph == end)
6948 return NULL;
6949
6950 *hpos = glyph - row->glyphs[*area];
6951 return glyph;
6952 }
6953
6954
6955 /* Convert frame-relative x/y to coordinates relative to window W.
6956 Takes pseudo-windows into account. */
6957
6958 static void
6959 frame_to_window_pixel_xy (w, x, y)
6960 struct window *w;
6961 int *x, *y;
6962 {
6963 if (w->pseudo_window_p)
6964 {
6965 /* A pseudo-window is always full-width, and starts at the
6966 left edge of the frame, plus a frame border. */
6967 struct frame *f = XFRAME (w->frame);
6968 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6969 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6970 }
6971 else
6972 {
6973 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6974 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6975 }
6976 }
6977
6978
6979 /* Take proper action when mouse has moved to the mode or header line of
6980 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6981 mode line. X is relative to the start of the text display area of
6982 W, so the width of fringes and scroll bars must be subtracted
6983 to get a position relative to the start of the mode line. */
6984
6985 static void
6986 note_mode_line_highlight (w, x, mode_line_p)
6987 struct window *w;
6988 int x, mode_line_p;
6989 {
6990 struct frame *f = XFRAME (w->frame);
6991 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6992 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
6993 struct glyph_row *row;
6994
6995 if (mode_line_p)
6996 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6997 else
6998 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6999
7000 if (row->enabled_p)
7001 {
7002 struct glyph *glyph, *end;
7003 Lisp_Object help, map;
7004 int x0;
7005
7006 /* Find the glyph under X. */
7007 glyph = row->glyphs[TEXT_AREA];
7008 end = glyph + row->used[TEXT_AREA];
7009 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
7010 + FRAME_X_LEFT_FRINGE_WIDTH (f));
7011
7012 while (glyph < end
7013 && x >= x0 + glyph->pixel_width)
7014 {
7015 x0 += glyph->pixel_width;
7016 ++glyph;
7017 }
7018
7019 if (glyph < end
7020 && STRINGP (glyph->object)
7021 && STRING_INTERVALS (glyph->object)
7022 && glyph->charpos >= 0
7023 && glyph->charpos < SCHARS (glyph->object))
7024 {
7025 /* If we're on a string with `help-echo' text property,
7026 arrange for the help to be displayed. This is done by
7027 setting the global variable help_echo to the help string. */
7028 help = Fget_text_property (make_number (glyph->charpos),
7029 Qhelp_echo, glyph->object);
7030 if (!NILP (help))
7031 {
7032 help_echo = help;
7033 XSETWINDOW (help_echo_window, w);
7034 help_echo_object = glyph->object;
7035 help_echo_pos = glyph->charpos;
7036 }
7037
7038 /* Change the mouse pointer according to what is under X/Y. */
7039 map = Fget_text_property (make_number (glyph->charpos),
7040 Qlocal_map, glyph->object);
7041 if (KEYMAPP (map))
7042 cursor = f->output_data.mac->nontext_cursor;
7043 else
7044 {
7045 map = Fget_text_property (make_number (glyph->charpos),
7046 Qkeymap, glyph->object);
7047 if (KEYMAPP (map))
7048 cursor = f->output_data.mac->nontext_cursor;
7049 }
7050 }
7051 }
7052
7053 #if 0 /* MAC_TODO: mouse cursor */
7054 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7055 #endif
7056 }
7057
7058
7059 /* Take proper action when the mouse has moved to position X, Y on
7060 frame F as regards highlighting characters that have mouse-face
7061 properties. Also de-highlighting chars where the mouse was before.
7062 X and Y can be negative or out of range. */
7063
7064 static void
7065 note_mouse_highlight (f, x, y)
7066 struct frame *f;
7067 int x, y;
7068 {
7069 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7070 int portion;
7071 Lisp_Object window;
7072 struct window *w;
7073 struct buffer *b;
7074
7075 #if 0
7076 /* When a menu is active, don't highlight because this looks odd. */
7077 if (popup_activated ())
7078 return;
7079 #endif
7080
7081 if (NILP (Vmouse_highlight)
7082 || !f->glyphs_initialized_p)
7083 return;
7084
7085 dpyinfo->mouse_face_mouse_x = x;
7086 dpyinfo->mouse_face_mouse_y = y;
7087 dpyinfo->mouse_face_mouse_frame = f;
7088
7089 if (dpyinfo->mouse_face_defer)
7090 return;
7091
7092 if (gc_in_progress)
7093 {
7094 dpyinfo->mouse_face_deferred_gc = 1;
7095 return;
7096 }
7097
7098 /* Which window is that in? */
7099 window = window_from_coordinates (f, x, y, &portion, 1);
7100
7101 /* If we were displaying active text in another window, clear that. */
7102 if (! EQ (window, dpyinfo->mouse_face_window))
7103 clear_mouse_face (dpyinfo);
7104
7105 /* Not on a window -> return. */
7106 if (!WINDOWP (window))
7107 return;
7108
7109 /* Reset help_echo. It will get recomputed below. */
7110 help_echo = Qnil;
7111
7112 /* Convert to window-relative pixel coordinates. */
7113 w = XWINDOW (window);
7114 frame_to_window_pixel_xy (w, &x, &y);
7115
7116 /* Handle tool-bar window differently since it doesn't display a
7117 buffer. */
7118 if (EQ (window, f->tool_bar_window))
7119 {
7120 note_tool_bar_highlight (f, x, y);
7121 return;
7122 }
7123
7124 /* Mouse is on the mode or header line? */
7125 if (portion == 1 || portion == 3)
7126 {
7127 note_mode_line_highlight (w, x, portion == 1);
7128 return;
7129 }
7130 #if 0 /* TODO: mouse cursor */
7131 if (portion == 2)
7132 cursor = f->output_data.x->horizontal_drag_cursor;
7133 else
7134 cursor = f->output_data.x->text_cursor;
7135 #endif
7136 /* Are we in a window whose display is up to date?
7137 And verify the buffer's text has not changed. */
7138 b = XBUFFER (w->buffer);
7139 if (/* Within text portion of the window. */
7140 portion == 0
7141 && EQ (w->window_end_valid, w->buffer)
7142 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7143 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7144 {
7145 int hpos, vpos, pos, i, area;
7146 struct glyph *glyph;
7147 Lisp_Object object;
7148 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7149 Lisp_Object *overlay_vec = NULL;
7150 int len, noverlays;
7151 struct buffer *obuf;
7152 int obegv, ozv, same_region;
7153
7154 /* Find the glyph under X/Y. */
7155 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7156
7157 /* Clear mouse face if X/Y not over text. */
7158 if (glyph == NULL
7159 || area != TEXT_AREA
7160 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7161 {
7162 clear_mouse_face (dpyinfo);
7163 /* TODO: mouse cursor */
7164 goto set_cursor;
7165 }
7166
7167 pos = glyph->charpos;
7168 object = glyph->object;
7169 if (!STRINGP (object) && !BUFFERP (object))
7170 goto set_cursor;
7171
7172 /* If we get an out-of-range value, return now; avoid an error. */
7173 if (BUFFERP (object) && pos > BUF_Z (b))
7174 goto set_cursor;
7175
7176 /* Make the window's buffer temporarily current for
7177 overlays_at and compute_char_face. */
7178 obuf = current_buffer;
7179 current_buffer = b;
7180 obegv = BEGV;
7181 ozv = ZV;
7182 BEGV = BEG;
7183 ZV = Z;
7184
7185 /* Is this char mouse-active or does it have help-echo? */
7186 position = make_number (pos);
7187
7188 if (BUFFERP (object))
7189 {
7190 /* Put all the overlays we want in a vector in overlay_vec.
7191 Store the length in len. If there are more than 10, make
7192 enough space for all, and try again. */
7193 len = 10;
7194 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7195 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7196 if (noverlays > len)
7197 {
7198 len = noverlays;
7199 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7200 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7201 }
7202
7203 /* Sort overlays into increasing priority order. */
7204 noverlays = sort_overlays (overlay_vec, noverlays, w);
7205 }
7206 else
7207 noverlays = 0;
7208
7209 same_region = (EQ (window, dpyinfo->mouse_face_window)
7210 && vpos >= dpyinfo->mouse_face_beg_row
7211 && vpos <= dpyinfo->mouse_face_end_row
7212 && (vpos > dpyinfo->mouse_face_beg_row
7213 || hpos >= dpyinfo->mouse_face_beg_col)
7214 && (vpos < dpyinfo->mouse_face_end_row
7215 || hpos < dpyinfo->mouse_face_end_col
7216 || dpyinfo->mouse_face_past_end));
7217
7218 /* TODO: if (same_region)
7219 mouse cursor */
7220
7221 /* Check mouse-face highlighting. */
7222 if (! same_region
7223 /* If there exists an overlay with mouse-face overlapping
7224 the one we are currently highlighting, we have to
7225 check if we enter the overlapping overlay, and then
7226 highlight that. */
7227 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7228 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7229 {
7230 /* Find the highest priority overlay that has a mouse-face
7231 property. */
7232 overlay = Qnil;
7233 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7234 {
7235 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7236 if (!NILP (mouse_face))
7237 overlay = overlay_vec[i];
7238 }
7239
7240 /* If we're actually highlighting the same overlay as
7241 before, there's no need to do that again. */
7242 if (!NILP (overlay)
7243 && EQ (overlay, dpyinfo->mouse_face_overlay))
7244 goto check_help_echo;
7245
7246 dpyinfo->mouse_face_overlay = overlay;
7247
7248 /* Clear the display of the old active region, if any. */
7249 clear_mouse_face (dpyinfo);
7250 /* TODO: mouse cursor changes. */
7251
7252 /* If no overlay applies, get a text property. */
7253 if (NILP (overlay))
7254 mouse_face = Fget_text_property (position, Qmouse_face, object);
7255
7256 /* Handle the overlay case. */
7257 if (!NILP (overlay))
7258 {
7259 /* Find the range of text around this char that
7260 should be active. */
7261 Lisp_Object before, after;
7262 int ignore;
7263
7264 before = Foverlay_start (overlay);
7265 after = Foverlay_end (overlay);
7266 /* Record this as the current active region. */
7267 fast_find_position (w, XFASTINT (before),
7268 &dpyinfo->mouse_face_beg_col,
7269 &dpyinfo->mouse_face_beg_row,
7270 &dpyinfo->mouse_face_beg_x,
7271 &dpyinfo->mouse_face_beg_y, Qnil);
7272
7273 dpyinfo->mouse_face_past_end
7274 = !fast_find_position (w, XFASTINT (after),
7275 &dpyinfo->mouse_face_end_col,
7276 &dpyinfo->mouse_face_end_row,
7277 &dpyinfo->mouse_face_end_x,
7278 &dpyinfo->mouse_face_end_y, Qnil);
7279 dpyinfo->mouse_face_window = window;
7280
7281 dpyinfo->mouse_face_face_id
7282 = face_at_buffer_position (w, pos, 0, 0,
7283 &ignore, pos + 1, 1);
7284
7285 /* Display it as active. */
7286 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7287 /* TODO: mouse cursor changes. */
7288 }
7289 /* Handle the text property case. */
7290 else if (! NILP (mouse_face) && BUFFERP (object))
7291 {
7292 /* Find the range of text around this char that
7293 should be active. */
7294 Lisp_Object before, after, beginning, end;
7295 int ignore;
7296
7297 beginning = Fmarker_position (w->start);
7298 end = make_number (BUF_Z (XBUFFER (object))
7299 - XFASTINT (w->window_end_pos));
7300 before
7301 = Fprevious_single_property_change (make_number (pos + 1),
7302 Qmouse_face,
7303 object, beginning);
7304 after
7305 = Fnext_single_property_change (position, Qmouse_face,
7306 object, end);
7307
7308 /* Record this as the current active region. */
7309 fast_find_position (w, XFASTINT (before),
7310 &dpyinfo->mouse_face_beg_col,
7311 &dpyinfo->mouse_face_beg_row,
7312 &dpyinfo->mouse_face_beg_x,
7313 &dpyinfo->mouse_face_beg_y, Qnil);
7314 dpyinfo->mouse_face_past_end
7315 = !fast_find_position (w, XFASTINT (after),
7316 &dpyinfo->mouse_face_end_col,
7317 &dpyinfo->mouse_face_end_row,
7318 &dpyinfo->mouse_face_end_x,
7319 &dpyinfo->mouse_face_end_y, Qnil);
7320 dpyinfo->mouse_face_window = window;
7321
7322 if (BUFFERP (object))
7323 dpyinfo->mouse_face_face_id
7324 = face_at_buffer_position (w, pos, 0, 0,
7325 &ignore, pos + 1, 1);
7326
7327 /* Display it as active. */
7328 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7329 /* TODO: mouse cursor changes. */
7330 }
7331 else if (!NILP (mouse_face) && STRINGP (object))
7332 {
7333 Lisp_Object b, e;
7334 int ignore;
7335
7336 b = Fprevious_single_property_change (make_number (pos + 1),
7337 Qmouse_face,
7338 object, Qnil);
7339 e = Fnext_single_property_change (position, Qmouse_face,
7340 object, Qnil);
7341 if (NILP (b))
7342 b = make_number (0);
7343 if (NILP (e))
7344 e = make_number (SCHARS (object) - 1);
7345 fast_find_string_pos (w, XINT (b), object,
7346 &dpyinfo->mouse_face_beg_col,
7347 &dpyinfo->mouse_face_beg_row,
7348 &dpyinfo->mouse_face_beg_x,
7349 &dpyinfo->mouse_face_beg_y, 0);
7350 fast_find_string_pos (w, XINT (e), object,
7351 &dpyinfo->mouse_face_end_col,
7352 &dpyinfo->mouse_face_end_row,
7353 &dpyinfo->mouse_face_end_x,
7354 &dpyinfo->mouse_face_end_y, 1);
7355 dpyinfo->mouse_face_past_end = 0;
7356 dpyinfo->mouse_face_window = window;
7357 dpyinfo->mouse_face_face_id
7358 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7359 glyph->face_id, 1);
7360 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7361 /* TODO: mouse cursor changes. */
7362 }
7363 else if (STRINGP (object) && NILP (mouse_face))
7364 {
7365 /* A string which doesn't have mouse-face, but
7366 the text ``under'' it might have. */
7367 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7368 int start = MATRIX_ROW_START_CHARPOS (r);
7369
7370 pos = string_buffer_position (w, object, start);
7371 if (pos > 0)
7372 mouse_face = get_char_property_and_overlay (make_number (pos),
7373 Qmouse_face,
7374 w->buffer,
7375 &overlay);
7376 if (!NILP (mouse_face) && !NILP (overlay))
7377 {
7378 Lisp_Object before = Foverlay_start (overlay);
7379 Lisp_Object after = Foverlay_end (overlay);
7380 int ignore;
7381
7382 /* Note that we might not be able to find position
7383 BEFORE in the glyph matrix if the overlay is
7384 entirely covered by a `display' property. In
7385 this case, we overshoot. So let's stop in
7386 the glyph matrix before glyphs for OBJECT. */
7387 fast_find_position (w, XFASTINT (before),
7388 &dpyinfo->mouse_face_beg_col,
7389 &dpyinfo->mouse_face_beg_row,
7390 &dpyinfo->mouse_face_beg_x,
7391 &dpyinfo->mouse_face_beg_y,
7392 object);
7393
7394 dpyinfo->mouse_face_past_end
7395 = !fast_find_position (w, XFASTINT (after),
7396 &dpyinfo->mouse_face_end_col,
7397 &dpyinfo->mouse_face_end_row,
7398 &dpyinfo->mouse_face_end_x,
7399 &dpyinfo->mouse_face_end_y,
7400 Qnil);
7401 dpyinfo->mouse_face_window = window;
7402 dpyinfo->mouse_face_face_id
7403 = face_at_buffer_position (w, pos, 0, 0,
7404 &ignore, pos + 1, 1);
7405
7406 /* Display it as active. */
7407 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7408 /* TODO: mouse cursor changes. */
7409 }
7410 }
7411 }
7412
7413 check_help_echo:
7414
7415 /* Look for a `help-echo' property. */
7416 {
7417 Lisp_Object help, overlay;
7418
7419 /* Check overlays first. */
7420 help = overlay = Qnil;
7421 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7422 {
7423 overlay = overlay_vec[i];
7424 help = Foverlay_get (overlay, Qhelp_echo);
7425 }
7426
7427 if (!NILP (help))
7428 {
7429 help_echo = help;
7430 help_echo_window = window;
7431 help_echo_object = overlay;
7432 help_echo_pos = pos;
7433 }
7434 else
7435 {
7436 Lisp_Object object = glyph->object;
7437 int charpos = glyph->charpos;
7438
7439 /* Try text properties. */
7440 if (STRINGP (object)
7441 && charpos >= 0
7442 && charpos < SCHARS (object))
7443 {
7444 help = Fget_text_property (make_number (charpos),
7445 Qhelp_echo, object);
7446 if (NILP (help))
7447 {
7448 /* If the string itself doesn't specify a help-echo,
7449 see if the buffer text ``under'' it does. */
7450 struct glyph_row *r
7451 = MATRIX_ROW (w->current_matrix, vpos);
7452 int start = MATRIX_ROW_START_CHARPOS (r);
7453 int pos = string_buffer_position (w, object, start);
7454 if (pos > 0)
7455 {
7456 help = Fget_char_property (make_number (pos),
7457 Qhelp_echo, w->buffer);
7458 if (!NILP (help))
7459 {
7460 charpos = pos;
7461 object = w->buffer;
7462 }
7463 }
7464 }
7465 }
7466 else if (BUFFERP (object)
7467 && charpos >= BEGV
7468 && charpos < ZV)
7469 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7470 object);
7471
7472 if (!NILP (help))
7473 {
7474 help_echo = help;
7475 help_echo_window = window;
7476 help_echo_object = object;
7477 help_echo_pos = charpos;
7478 }
7479 }
7480 }
7481
7482 BEGV = obegv;
7483 ZV = ozv;
7484 current_buffer = obuf;
7485 }
7486
7487 set_cursor:
7488 /* TODO: mouse cursor changes. */
7489 ;
7490 }
7491
7492 static void
7493 redo_mouse_highlight ()
7494 {
7495 if (!NILP (last_mouse_motion_frame)
7496 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7497 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7498 last_mouse_motion_position.h,
7499 last_mouse_motion_position.v);
7500 }
7501
7502
7503 \f
7504 /***********************************************************************
7505 Tool-bars
7506 ***********************************************************************/
7507
7508 static int x_tool_bar_item P_ ((struct frame *, int, int,
7509 struct glyph **, int *, int *, int *));
7510
7511 /* Tool-bar item index of the item on which a mouse button was pressed
7512 or -1. */
7513
7514 static int last_tool_bar_item;
7515
7516
7517 /* Get information about the tool-bar item at position X/Y on frame F.
7518 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7519 the current matrix of the tool-bar window of F, or NULL if not
7520 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7521 item in F->current_tool_bar_items. Value is
7522
7523 -1 if X/Y is not on a tool-bar item
7524 0 if X/Y is on the same item that was highlighted before.
7525 1 otherwise. */
7526
7527 static int
7528 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7529 struct frame *f;
7530 int x, y;
7531 struct glyph **glyph;
7532 int *hpos, *vpos, *prop_idx;
7533 {
7534 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7535 struct window *w = XWINDOW (f->tool_bar_window);
7536 int area;
7537
7538 /* Find the glyph under X/Y. */
7539 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7540 if (*glyph == NULL)
7541 return -1;
7542
7543 /* Get the start of this tool-bar item's properties in
7544 f->current_tool_bar_items. */
7545 if (!tool_bar_item_info (f, *glyph, prop_idx))
7546 return -1;
7547
7548 /* Is mouse on the highlighted item? */
7549 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7550 && *vpos >= dpyinfo->mouse_face_beg_row
7551 && *vpos <= dpyinfo->mouse_face_end_row
7552 && (*vpos > dpyinfo->mouse_face_beg_row
7553 || *hpos >= dpyinfo->mouse_face_beg_col)
7554 && (*vpos < dpyinfo->mouse_face_end_row
7555 || *hpos < dpyinfo->mouse_face_end_col
7556 || dpyinfo->mouse_face_past_end))
7557 return 0;
7558
7559 return 1;
7560 }
7561
7562
7563 /* Handle mouse button event on the tool-bar of frame F, at
7564 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7565 or ButtonRelase. */
7566
7567 static void
7568 x_handle_tool_bar_click (f, button_event)
7569 struct frame *f;
7570 EventRecord *button_event;
7571 {
7572 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7573 struct window *w = XWINDOW (f->tool_bar_window);
7574 int hpos, vpos, prop_idx;
7575 struct glyph *glyph;
7576 Lisp_Object enabled_p;
7577 int x = button_event->where.h;
7578 int y = button_event->where.v;
7579
7580 /* If not on the highlighted tool-bar item, return. */
7581 frame_to_window_pixel_xy (w, &x, &y);
7582 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7583 return;
7584
7585 /* If item is disabled, do nothing. */
7586 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7587 if (NILP (enabled_p))
7588 return;
7589
7590 if (button_event->what == mouseDown)
7591 {
7592 /* Show item in pressed state. */
7593 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7594 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7595 last_tool_bar_item = prop_idx;
7596 }
7597 else
7598 {
7599 Lisp_Object key, frame;
7600 struct input_event event;
7601
7602 /* Show item in released state. */
7603 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7604 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7605
7606 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7607
7608 XSETFRAME (frame, f);
7609 event.kind = TOOL_BAR_EVENT;
7610 event.frame_or_window = frame;
7611 event.arg = frame;
7612 kbd_buffer_store_event (&event);
7613
7614 event.kind = TOOL_BAR_EVENT;
7615 event.frame_or_window = frame;
7616 event.arg = key;
7617 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7618 button_event->modifiers);
7619 kbd_buffer_store_event (&event);
7620 last_tool_bar_item = -1;
7621 }
7622 }
7623
7624
7625 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7626 tool-bar window-relative coordinates X/Y. Called from
7627 note_mouse_highlight. */
7628
7629 static void
7630 note_tool_bar_highlight (f, x, y)
7631 struct frame *f;
7632 int x, y;
7633 {
7634 Lisp_Object window = f->tool_bar_window;
7635 struct window *w = XWINDOW (window);
7636 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7637 int hpos, vpos;
7638 struct glyph *glyph;
7639 struct glyph_row *row;
7640 int i;
7641 Lisp_Object enabled_p;
7642 int prop_idx;
7643 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7644 int mouse_down_p, rc;
7645
7646 /* Function note_mouse_highlight is called with negative x(y
7647 values when mouse moves outside of the frame. */
7648 if (x <= 0 || y <= 0)
7649 {
7650 clear_mouse_face (dpyinfo);
7651 return;
7652 }
7653
7654 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7655 if (rc < 0)
7656 {
7657 /* Not on tool-bar item. */
7658 clear_mouse_face (dpyinfo);
7659 return;
7660 }
7661 else if (rc == 0)
7662 /* On same tool-bar item as before. */
7663 goto set_help_echo;
7664
7665 clear_mouse_face (dpyinfo);
7666
7667 /* Mouse is down, but on different tool-bar item? */
7668 mouse_down_p = (dpyinfo->grabbed
7669 && f == last_mouse_frame
7670 && FRAME_LIVE_P (f));
7671 if (mouse_down_p
7672 && last_tool_bar_item != prop_idx)
7673 return;
7674
7675 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7676 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7677
7678 /* If tool-bar item is not enabled, don't highlight it. */
7679 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7680 if (!NILP (enabled_p))
7681 {
7682 /* Compute the x-position of the glyph. In front and past the
7683 image is a space. We include this is the highlighted area. */
7684 row = MATRIX_ROW (w->current_matrix, vpos);
7685 for (i = x = 0; i < hpos; ++i)
7686 x += row->glyphs[TEXT_AREA][i].pixel_width;
7687
7688 /* Record this as the current active region. */
7689 dpyinfo->mouse_face_beg_col = hpos;
7690 dpyinfo->mouse_face_beg_row = vpos;
7691 dpyinfo->mouse_face_beg_x = x;
7692 dpyinfo->mouse_face_beg_y = row->y;
7693 dpyinfo->mouse_face_past_end = 0;
7694
7695 dpyinfo->mouse_face_end_col = hpos + 1;
7696 dpyinfo->mouse_face_end_row = vpos;
7697 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7698 dpyinfo->mouse_face_end_y = row->y;
7699 dpyinfo->mouse_face_window = window;
7700 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7701
7702 /* Display it as active. */
7703 show_mouse_face (dpyinfo, draw);
7704 dpyinfo->mouse_face_image_state = draw;
7705 }
7706
7707 set_help_echo:
7708
7709 /* Set help_echo to a help string.to display for this tool-bar item.
7710 XTread_socket does the rest. */
7711 help_echo_object = help_echo_window = Qnil;
7712 help_echo_pos = -1;
7713 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7714 if (NILP (help_echo))
7715 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7716 }
7717
7718
7719 \f
7720 /* Find the glyph matrix position of buffer position CHARPOS in window
7721 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7722 current glyphs must be up to date. If CHARPOS is above window
7723 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7724 of last line in W. In the row containing CHARPOS, stop before glyphs
7725 having STOP as object. */
7726
7727 #if 0 /* This is a version of fast_find_position that's more correct
7728 in the presence of hscrolling, for example. I didn't install
7729 it right away because the problem fixed is minor, it failed
7730 in 20.x as well, and I think it's too risky to install
7731 so near the release of 21.1. 2001-09-25 gerd. */
7732
7733 static int
7734 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7735 struct window *w;
7736 int charpos;
7737 int *hpos, *vpos, *x, *y;
7738 Lisp_Object stop;
7739 {
7740 struct glyph_row *row, *first;
7741 struct glyph *glyph, *end;
7742 int i, past_end = 0;
7743
7744 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7745 row = row_containing_pos (w, charpos, first, NULL, 0);
7746 if (row == NULL)
7747 {
7748 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7749 {
7750 *x = *y = *hpos = *vpos = 0;
7751 return 0;
7752 }
7753 else
7754 {
7755 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7756 past_end = 1;
7757 }
7758 }
7759
7760 *x = row->x;
7761 *y = row->y;
7762 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7763
7764 glyph = row->glyphs[TEXT_AREA];
7765 end = glyph + row->used[TEXT_AREA];
7766
7767 /* Skip over glyphs not having an object at the start of the row.
7768 These are special glyphs like truncation marks on terminal
7769 frames. */
7770 if (row->displays_text_p)
7771 while (glyph < end
7772 && INTEGERP (glyph->object)
7773 && !EQ (stop, glyph->object)
7774 && glyph->charpos < 0)
7775 {
7776 *x += glyph->pixel_width;
7777 ++glyph;
7778 }
7779
7780 while (glyph < end
7781 && !INTEGERP (glyph->object)
7782 && !EQ (stop, glyph->object)
7783 && (!BUFFERP (glyph->object)
7784 || glyph->charpos < charpos))
7785 {
7786 *x += glyph->pixel_width;
7787 ++glyph;
7788 }
7789
7790 *hpos = glyph - row->glyphs[TEXT_AREA];
7791 return past_end;
7792 }
7793
7794 #else /* not 0 */
7795
7796 static int
7797 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7798 struct window *w;
7799 int pos;
7800 int *hpos, *vpos, *x, *y;
7801 Lisp_Object stop;
7802 {
7803 int i;
7804 int lastcol;
7805 int maybe_next_line_p = 0;
7806 int line_start_position;
7807 int yb = window_text_bottom_y (w);
7808 struct glyph_row *row, *best_row;
7809 int row_vpos, best_row_vpos;
7810 int current_x;
7811
7812 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7813 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7814
7815 while (row->y < yb)
7816 {
7817 if (row->used[TEXT_AREA])
7818 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7819 else
7820 line_start_position = 0;
7821
7822 if (line_start_position > pos)
7823 break;
7824 /* If the position sought is the end of the buffer,
7825 don't include the blank lines at the bottom of the window. */
7826 else if (line_start_position == pos
7827 && pos == BUF_ZV (XBUFFER (w->buffer)))
7828 {
7829 maybe_next_line_p = 1;
7830 break;
7831 }
7832 else if (line_start_position > 0)
7833 {
7834 best_row = row;
7835 best_row_vpos = row_vpos;
7836 }
7837
7838 if (row->y + row->height >= yb)
7839 break;
7840
7841 ++row;
7842 ++row_vpos;
7843 }
7844
7845 /* Find the right column within BEST_ROW. */
7846 lastcol = 0;
7847 current_x = best_row->x;
7848 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7849 {
7850 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7851 int charpos = glyph->charpos;
7852
7853 if (BUFFERP (glyph->object))
7854 {
7855 if (charpos == pos)
7856 {
7857 *hpos = i;
7858 *vpos = best_row_vpos;
7859 *x = current_x;
7860 *y = best_row->y;
7861 return 1;
7862 }
7863 else if (charpos > pos)
7864 break;
7865 }
7866 else if (EQ (glyph->object, stop))
7867 break;
7868
7869 if (charpos > 0)
7870 lastcol = i;
7871 current_x += glyph->pixel_width;
7872 }
7873
7874 /* If we're looking for the end of the buffer,
7875 and we didn't find it in the line we scanned,
7876 use the start of the following line. */
7877 if (maybe_next_line_p)
7878 {
7879 ++best_row;
7880 ++best_row_vpos;
7881 lastcol = 0;
7882 current_x = best_row->x;
7883 }
7884
7885 *vpos = best_row_vpos;
7886 *hpos = lastcol + 1;
7887 *x = current_x;
7888 *y = best_row->y;
7889 return 0;
7890 }
7891
7892 #endif /* not 0 */
7893
7894
7895 /* Find the position of the glyph for position POS in OBJECT in
7896 window W's current matrix, and return in *X/*Y the pixel
7897 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7898
7899 RIGHT_P non-zero means return the position of the right edge of the
7900 glyph, RIGHT_P zero means return the left edge position.
7901
7902 If no glyph for POS exists in the matrix, return the position of
7903 the glyph with the next smaller position that is in the matrix, if
7904 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7905 exists in the matrix, return the position of the glyph with the
7906 next larger position in OBJECT.
7907
7908 Value is non-zero if a glyph was found. */
7909
7910 static int
7911 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7912 struct window *w;
7913 int pos;
7914 Lisp_Object object;
7915 int *hpos, *vpos, *x, *y;
7916 int right_p;
7917 {
7918 int yb = window_text_bottom_y (w);
7919 struct glyph_row *r;
7920 struct glyph *best_glyph = NULL;
7921 struct glyph_row *best_row = NULL;
7922 int best_x = 0;
7923
7924 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7925 r->enabled_p && r->y < yb;
7926 ++r)
7927 {
7928 struct glyph *g = r->glyphs[TEXT_AREA];
7929 struct glyph *e = g + r->used[TEXT_AREA];
7930 int gx;
7931
7932 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7933 if (EQ (g->object, object))
7934 {
7935 if (g->charpos == pos)
7936 {
7937 best_glyph = g;
7938 best_x = gx;
7939 best_row = r;
7940 goto found;
7941 }
7942 else if (best_glyph == NULL
7943 || ((abs (g->charpos - pos)
7944 < abs (best_glyph->charpos - pos))
7945 && (right_p
7946 ? g->charpos < pos
7947 : g->charpos > pos)))
7948 {
7949 best_glyph = g;
7950 best_x = gx;
7951 best_row = r;
7952 }
7953 }
7954 }
7955
7956 found:
7957
7958 if (best_glyph)
7959 {
7960 *x = best_x;
7961 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7962
7963 if (right_p)
7964 {
7965 *x += best_glyph->pixel_width;
7966 ++*hpos;
7967 }
7968
7969 *y = best_row->y;
7970 *vpos = best_row - w->current_matrix->rows;
7971 }
7972
7973 return best_glyph != NULL;
7974 }
7975
7976
7977 /* Display the active region described by mouse_face_*
7978 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7979
7980 static void
7981 show_mouse_face (dpyinfo, draw)
7982 struct mac_display_info *dpyinfo;
7983 enum draw_glyphs_face draw;
7984 {
7985 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7986 struct frame *f = XFRAME (WINDOW_FRAME (w));
7987
7988 if (/* If window is in the process of being destroyed, don't bother
7989 to do anything. */
7990 w->current_matrix != NULL
7991 /* Don't update mouse highlight if hidden */
7992 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7993 /* Recognize when we are called to operate on rows that don't exist
7994 anymore. This can happen when a window is split. */
7995 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7996 {
7997 int phys_cursor_on_p = w->phys_cursor_on_p;
7998 struct glyph_row *row, *first, *last;
7999
8000 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
8001 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
8002
8003 for (row = first; row <= last && row->enabled_p; ++row)
8004 {
8005 int start_hpos, end_hpos, start_x;
8006
8007 /* For all but the first row, the highlight starts at column 0. */
8008 if (row == first)
8009 {
8010 start_hpos = dpyinfo->mouse_face_beg_col;
8011 start_x = dpyinfo->mouse_face_beg_x;
8012 }
8013 else
8014 {
8015 start_hpos = 0;
8016 start_x = 0;
8017 }
8018
8019 if (row == last)
8020 end_hpos = dpyinfo->mouse_face_end_col;
8021 else
8022 end_hpos = row->used[TEXT_AREA];
8023
8024 if (end_hpos > start_hpos)
8025 {
8026 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8027 start_hpos, end_hpos, draw, 0);
8028
8029 row->mouse_face_p
8030 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8031 }
8032 }
8033
8034 /* When we've written over the cursor, arrange for it to
8035 be displayed again. */
8036 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8037 x_display_cursor (w, 1,
8038 w->phys_cursor.hpos, w->phys_cursor.vpos,
8039 w->phys_cursor.x, w->phys_cursor.y);
8040 }
8041
8042 #if 0 /* MAC_TODO: mouse cursor */
8043 /* Change the mouse cursor. */
8044 if (draw == DRAW_NORMAL_TEXT)
8045 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8046 f->output_data.x->text_cursor);
8047 else if (draw == DRAW_MOUSE_FACE)
8048 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8049 f->output_data.x->cross_cursor);
8050 else
8051 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8052 f->output_data.x->nontext_cursor);
8053 #endif
8054 }
8055
8056 /* Clear out the mouse-highlighted active region.
8057 Redraw it un-highlighted first. */
8058
8059 static int
8060 clear_mouse_face (dpyinfo)
8061 struct mac_display_info *dpyinfo;
8062 {
8063 int cleared = 0;
8064
8065 if (! NILP (dpyinfo->mouse_face_window))
8066 {
8067 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8068 cleared = 1;
8069 }
8070
8071 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8072 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8073 dpyinfo->mouse_face_window = Qnil;
8074 dpyinfo->mouse_face_overlay = Qnil;
8075 return cleared;
8076 }
8077
8078
8079 /* Clear any mouse-face on window W. This function is part of the
8080 redisplay interface, and is called from try_window_id and similar
8081 functions to ensure the mouse-highlight is off. */
8082
8083 static void
8084 x_clear_mouse_face (w)
8085 struct window *w;
8086 {
8087 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8088 Lisp_Object window;
8089
8090 BLOCK_INPUT;
8091 XSETWINDOW (window, w);
8092 if (EQ (window, dpyinfo->mouse_face_window))
8093 clear_mouse_face (dpyinfo);
8094 UNBLOCK_INPUT;
8095 }
8096
8097
8098 /* Just discard the mouse face information for frame F, if any.
8099 This is used when the size of F is changed. */
8100
8101 void
8102 cancel_mouse_face (f)
8103 FRAME_PTR f;
8104 {
8105 Lisp_Object window;
8106 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8107
8108 window = dpyinfo->mouse_face_window;
8109 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8110 {
8111 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8112 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8113 dpyinfo->mouse_face_window = Qnil;
8114 }
8115 }
8116 \f
8117 static struct scroll_bar *x_window_to_scroll_bar ();
8118 static void x_scroll_bar_report_motion ();
8119 static void x_check_fullscreen P_ ((struct frame *));
8120 static void x_check_fullscreen_move P_ ((struct frame *));
8121 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8122
8123
8124 /* Try to determine frame pixel position and size of the glyph under
8125 frame pixel coordinates X/Y on frame F . Return the position and
8126 size in *RECT. Value is non-zero if we could compute these
8127 values. */
8128
8129 static int
8130 glyph_rect (f, x, y, rect)
8131 struct frame *f;
8132 int x, y;
8133 Rect *rect;
8134 {
8135 Lisp_Object window;
8136 int part;
8137
8138 window = window_from_coordinates (f, x, y, &part, 0);
8139 if (!NILP (window))
8140 {
8141 struct window *w = XWINDOW (window);
8142 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8143 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8144
8145 frame_to_window_pixel_xy (w, &x, &y);
8146
8147 for (; r < end && r->enabled_p; ++r)
8148 if (r->y <= y && r->y + r->height > y)
8149 {
8150 /* Found the row at y. */
8151 struct glyph *g = r->glyphs[TEXT_AREA];
8152 struct glyph *end = g + r->used[TEXT_AREA];
8153 int gx;
8154
8155 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8156 rect->bottom = rect->top + r->height;
8157
8158 if (x < r->x)
8159 {
8160 /* x is to the left of the first glyph in the row. */
8161 rect->left = XINT (w->left);
8162 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8163 return 1;
8164 }
8165
8166 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8167 if (gx <= x && gx + g->pixel_width > x)
8168 {
8169 /* x is on a glyph. */
8170 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8171 rect->right = rect->left + g->pixel_width;
8172 return 1;
8173 }
8174
8175 /* x is to the right of the last glyph in the row. */
8176 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8177 rect->right = XINT (w->left) + XINT (w->width);
8178 return 1;
8179 }
8180 }
8181
8182 /* The y is not on any row. */
8183 return 0;
8184 }
8185
8186 /* Record the position of the mouse in last_mouse_glyph. */
8187 static void
8188 remember_mouse_glyph (f1, gx, gy)
8189 struct frame * f1;
8190 int gx, gy;
8191 {
8192 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8193 {
8194 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8195 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8196
8197 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8198 round down even for negative values. */
8199 if (gx < 0)
8200 gx -= width - 1;
8201 if (gy < 0)
8202 gy -= height - 1;
8203 #if 0
8204 /* This was the original code from XTmouse_position, but it seems
8205 to give the position of the glyph diagonally next to the one
8206 the mouse is over. */
8207 gx = (gx + width - 1) / width * width;
8208 gy = (gy + height - 1) / height * height;
8209 #else
8210 gx = gx / width * width;
8211 gy = gy / height * height;
8212 #endif
8213
8214 last_mouse_glyph.left = gx;
8215 last_mouse_glyph.top = gy;
8216 last_mouse_glyph.right = gx + width;
8217 last_mouse_glyph.bottom = gy + height;
8218 }
8219 }
8220
8221 /* Return the current position of the mouse.
8222 *fp should be a frame which indicates which display to ask about.
8223
8224 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8225 and *part to the frame, window, and scroll bar part that the mouse
8226 is over. Set *x and *y to the portion and whole of the mouse's
8227 position on the scroll bar.
8228
8229 If the mouse movement started elsewhere, set *fp to the frame the
8230 mouse is on, *bar_window to nil, and *x and *y to the character cell
8231 the mouse is over.
8232
8233 Set *time to the server time-stamp for the time at which the mouse
8234 was at this position.
8235
8236 Don't store anything if we don't have a valid set of values to report.
8237
8238 This clears the mouse_moved flag, so we can wait for the next mouse
8239 movement. */
8240
8241 static void
8242 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8243 FRAME_PTR *fp;
8244 int insist;
8245 Lisp_Object *bar_window;
8246 enum scroll_bar_part *part;
8247 Lisp_Object *x, *y;
8248 unsigned long *time;
8249 {
8250 Point mouse_pos;
8251 int ignore1, ignore2;
8252 WindowPtr wp = FrontWindow ();
8253 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8254 Lisp_Object frame, tail;
8255
8256 BLOCK_INPUT;
8257
8258 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8259 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8260 else
8261 {
8262 /* Clear the mouse-moved flag for every frame on this display. */
8263 FOR_EACH_FRAME (tail, frame)
8264 XFRAME (frame)->mouse_moved = 0;
8265
8266 last_mouse_scroll_bar = Qnil;
8267
8268 #if TARGET_API_MAC_CARBON
8269 SetPort (GetWindowPort (wp));
8270 #else
8271 SetPort (wp);
8272 #endif
8273
8274 GetMouse (&mouse_pos);
8275
8276 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8277 &last_mouse_glyph, insist);
8278
8279 *bar_window = Qnil;
8280 *part = scroll_bar_handle;
8281 *fp = f;
8282 XSETINT (*x, mouse_pos.h);
8283 XSETINT (*y, mouse_pos.v);
8284 *time = last_mouse_movement_time;
8285 }
8286
8287 UNBLOCK_INPUT;
8288 }
8289
8290 \f
8291 /************************************************************************
8292 Scroll bars, general
8293 ************************************************************************/
8294
8295 /* Create a scroll bar and return the scroll bar vector for it. W is
8296 the Emacs window on which to create the scroll bar. TOP, LEFT,
8297 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8298 scroll bar. */
8299
8300 static struct scroll_bar *
8301 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8302 struct window *w;
8303 int top, left, width, height, disp_top, disp_height;
8304 {
8305 struct frame *f = XFRAME (w->frame);
8306 struct scroll_bar *bar
8307 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8308 Rect r;
8309 ControlHandle ch;
8310
8311 BLOCK_INPUT;
8312
8313 r.left = left;
8314 r.top = disp_top;
8315 r.right = left + width;
8316 r.bottom = disp_top + disp_height;
8317
8318 #ifdef TARGET_API_MAC_CARBON
8319 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8320 kControlScrollBarProc, 0L);
8321 #else
8322 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8323 0L);
8324 #endif
8325 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8326 SetControlReference (ch, (long) bar);
8327
8328 XSETWINDOW (bar->window, w);
8329 XSETINT (bar->top, top);
8330 XSETINT (bar->left, left);
8331 XSETINT (bar->width, width);
8332 XSETINT (bar->height, height);
8333 XSETINT (bar->start, 0);
8334 XSETINT (bar->end, 0);
8335 bar->dragging = Qnil;
8336
8337 /* Add bar to its frame's list of scroll bars. */
8338 bar->next = FRAME_SCROLL_BARS (f);
8339 bar->prev = Qnil;
8340 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8341 if (!NILP (bar->next))
8342 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8343
8344 UNBLOCK_INPUT;
8345 return bar;
8346 }
8347
8348
8349 /* Draw BAR's handle in the proper position.
8350
8351 If the handle is already drawn from START to END, don't bother
8352 redrawing it, unless REBUILD is non-zero; in that case, always
8353 redraw it. (REBUILD is handy for drawing the handle after expose
8354 events.)
8355
8356 Normally, we want to constrain the start and end of the handle to
8357 fit inside its rectangle, but if the user is dragging the scroll
8358 bar handle, we want to let them drag it down all the way, so that
8359 the bar's top is as far down as it goes; otherwise, there's no way
8360 to move to the very end of the buffer. */
8361
8362 static void
8363 x_scroll_bar_set_handle (bar, start, end, rebuild)
8364 struct scroll_bar *bar;
8365 int start, end;
8366 int rebuild;
8367 {
8368 int dragging = ! NILP (bar->dragging);
8369 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8370 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8371 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8372 int length = end - start;
8373
8374 /* If the display is already accurate, do nothing. */
8375 if (! rebuild
8376 && start == XINT (bar->start)
8377 && end == XINT (bar->end))
8378 return;
8379
8380 BLOCK_INPUT;
8381
8382 /* Make sure the values are reasonable, and try to preserve the
8383 distance between start and end. */
8384 if (start < 0)
8385 start = 0;
8386 else if (start > top_range)
8387 start = top_range;
8388 end = start + length;
8389
8390 if (end < start)
8391 end = start;
8392 else if (end > top_range && ! dragging)
8393 end = top_range;
8394
8395 /* Store the adjusted setting in the scroll bar. */
8396 XSETINT (bar->start, start);
8397 XSETINT (bar->end, end);
8398
8399 /* Clip the end position, just for display. */
8400 if (end > top_range)
8401 end = top_range;
8402
8403 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8404 top positions, to make sure the handle is always at least that
8405 many pixels tall. */
8406 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8407
8408 SetControlMinimum (ch, 0);
8409 /* Don't inadvertently activate deactivated scroll bars */
8410 if (GetControlMaximum (ch) != -1)
8411 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8412 - (end - start));
8413 SetControlValue (ch, start);
8414 #if TARGET_API_MAC_CARBON
8415 SetControlViewSize (ch, end - start);
8416 #endif
8417
8418 UNBLOCK_INPUT;
8419 }
8420
8421
8422 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8423 nil. */
8424
8425 static void
8426 x_scroll_bar_remove (bar)
8427 struct scroll_bar *bar;
8428 {
8429 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8430
8431 BLOCK_INPUT;
8432
8433 /* Destroy the Mac scroll bar control */
8434 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8435
8436 /* Disassociate this scroll bar from its window. */
8437 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8438
8439 UNBLOCK_INPUT;
8440 }
8441
8442 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8443 that we are displaying PORTION characters out of a total of WHOLE
8444 characters, starting at POSITION. If WINDOW has no scroll bar,
8445 create one. */
8446 static void
8447 XTset_vertical_scroll_bar (w, portion, whole, position)
8448 struct window *w;
8449 int portion, whole, position;
8450 {
8451 struct frame *f = XFRAME (w->frame);
8452 struct scroll_bar *bar;
8453 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8454 int window_x, window_y, window_width, window_height;
8455
8456 /* Get window dimensions. */
8457 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8458 top = window_y;
8459 #ifdef MAC_OSX
8460 width = 16;
8461 #else
8462 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8463 #endif
8464 height = window_height;
8465
8466 /* Compute the left edge of the scroll bar area. */
8467 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8468 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8469 else
8470 left = XFASTINT (w->left);
8471 left *= CANON_X_UNIT (f);
8472 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8473
8474 /* Compute the width of the scroll bar which might be less than
8475 the width of the area reserved for the scroll bar. */
8476 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8477 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8478 else
8479 sb_width = width;
8480
8481 /* Compute the left edge of the scroll bar. */
8482 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8483 sb_left = left + width - sb_width - (width - sb_width) / 2;
8484 else
8485 sb_left = left + (width - sb_width) / 2;
8486
8487 /* Adjustments according to Inside Macintosh to make it look nice */
8488 disp_top = top;
8489 disp_height = height;
8490 if (disp_top == 0)
8491 {
8492 disp_top = -1;
8493 disp_height++;
8494 }
8495 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8496 {
8497 disp_top++;
8498 disp_height--;
8499 }
8500
8501 if (sb_left + sb_width == PIXEL_WIDTH (f))
8502 sb_left++;
8503
8504 /* Does the scroll bar exist yet? */
8505 if (NILP (w->vertical_scroll_bar))
8506 {
8507 BLOCK_INPUT;
8508 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8509 left, top, width, height, 0);
8510 UNBLOCK_INPUT;
8511 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8512 disp_height);
8513 XSETVECTOR (w->vertical_scroll_bar, bar);
8514 }
8515 else
8516 {
8517 /* It may just need to be moved and resized. */
8518 ControlHandle ch;
8519
8520 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8521 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8522
8523 BLOCK_INPUT;
8524
8525 /* If already correctly positioned, do nothing. */
8526 if (XINT (bar->left) == sb_left
8527 && XINT (bar->top) == top
8528 && XINT (bar->width) == sb_width
8529 && XINT (bar->height) == height)
8530 Draw1Control (ch);
8531 else
8532 {
8533 /* Clear areas not covered by the scroll bar because it's not as
8534 wide as the area reserved for it . This makes sure a
8535 previous mode line display is cleared after C-x 2 C-x 1, for
8536 example. */
8537 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8538 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8539 left, top, area_width, height, 0);
8540
8541 #if 0
8542 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8543 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8544 sb_left - 1, top, 1, height, 0);
8545 #endif
8546
8547 HideControl (ch);
8548 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8549 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8550 disp_height);
8551 ShowControl (ch);
8552
8553 /* Remember new settings. */
8554 XSETINT (bar->left, sb_left);
8555 XSETINT (bar->top, top);
8556 XSETINT (bar->width, sb_width);
8557 XSETINT (bar->height, height);
8558 }
8559
8560 UNBLOCK_INPUT;
8561 }
8562
8563 /* Set the scroll bar's current state, unless we're currently being
8564 dragged. */
8565 if (NILP (bar->dragging))
8566 {
8567 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8568
8569 if (whole == 0)
8570 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8571 else
8572 {
8573 int start = ((double) position * top_range) / whole;
8574 int end = ((double) (position + portion) * top_range) / whole;
8575 x_scroll_bar_set_handle (bar, start, end, 0);
8576 }
8577 }
8578 }
8579
8580
8581 /* The following three hooks are used when we're doing a thorough
8582 redisplay of the frame. We don't explicitly know which scroll bars
8583 are going to be deleted, because keeping track of when windows go
8584 away is a real pain - "Can you say set-window-configuration, boys
8585 and girls?" Instead, we just assert at the beginning of redisplay
8586 that *all* scroll bars are to be removed, and then save a scroll bar
8587 from the fiery pit when we actually redisplay its window. */
8588
8589 /* Arrange for all scroll bars on FRAME to be removed at the next call
8590 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8591 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8592
8593 static void
8594 XTcondemn_scroll_bars (frame)
8595 FRAME_PTR frame;
8596 {
8597 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8598 while (! NILP (FRAME_SCROLL_BARS (frame)))
8599 {
8600 Lisp_Object bar;
8601 bar = FRAME_SCROLL_BARS (frame);
8602 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8603 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8604 XSCROLL_BAR (bar)->prev = Qnil;
8605 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8606 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8607 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8608 }
8609 }
8610
8611
8612 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8613 Note that WINDOW isn't necessarily condemned at all. */
8614
8615 static void
8616 XTredeem_scroll_bar (window)
8617 struct window *window;
8618 {
8619 struct scroll_bar *bar;
8620
8621 /* We can't redeem this window's scroll bar if it doesn't have one. */
8622 if (NILP (window->vertical_scroll_bar))
8623 abort ();
8624
8625 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8626
8627 /* Unlink it from the condemned list. */
8628 {
8629 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8630
8631 if (NILP (bar->prev))
8632 {
8633 /* If the prev pointer is nil, it must be the first in one of
8634 the lists. */
8635 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8636 /* It's not condemned. Everything's fine. */
8637 return;
8638 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8639 window->vertical_scroll_bar))
8640 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8641 else
8642 /* If its prev pointer is nil, it must be at the front of
8643 one or the other! */
8644 abort ();
8645 }
8646 else
8647 XSCROLL_BAR (bar->prev)->next = bar->next;
8648
8649 if (! NILP (bar->next))
8650 XSCROLL_BAR (bar->next)->prev = bar->prev;
8651
8652 bar->next = FRAME_SCROLL_BARS (f);
8653 bar->prev = Qnil;
8654 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8655 if (! NILP (bar->next))
8656 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8657 }
8658 }
8659
8660 /* Remove all scroll bars on FRAME that haven't been saved since the
8661 last call to `*condemn_scroll_bars_hook'. */
8662
8663 static void
8664 XTjudge_scroll_bars (f)
8665 FRAME_PTR f;
8666 {
8667 Lisp_Object bar, next;
8668
8669 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8670
8671 /* Clear out the condemned list now so we won't try to process any
8672 more events on the hapless scroll bars. */
8673 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8674
8675 for (; ! NILP (bar); bar = next)
8676 {
8677 struct scroll_bar *b = XSCROLL_BAR (bar);
8678
8679 x_scroll_bar_remove (b);
8680
8681 next = b->next;
8682 b->next = b->prev = Qnil;
8683 }
8684
8685 /* Now there should be no references to the condemned scroll bars,
8686 and they should get garbage-collected. */
8687 }
8688
8689
8690 static void
8691 activate_scroll_bars (frame)
8692 FRAME_PTR frame;
8693 {
8694 Lisp_Object bar;
8695 ControlHandle ch;
8696
8697 bar = FRAME_SCROLL_BARS (frame);
8698 while (! NILP (bar))
8699 {
8700 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8701 #ifdef TARGET_API_MAC_CARBON
8702 ActivateControl (ch);
8703 #else
8704 SetControlMaximum (ch,
8705 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8706 XINT (XSCROLL_BAR (bar)
8707 ->height)) - 1);
8708 #endif
8709 bar = XSCROLL_BAR (bar)->next;
8710 }
8711 }
8712
8713
8714 static void
8715 deactivate_scroll_bars (frame)
8716 FRAME_PTR frame;
8717 {
8718 Lisp_Object bar;
8719 ControlHandle ch;
8720
8721 bar = FRAME_SCROLL_BARS (frame);
8722 while (! NILP (bar))
8723 {
8724 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8725 #ifdef TARGET_API_MAC_CARBON
8726 DeactivateControl (ch);
8727 #else
8728 SetControlMaximum (ch, XINT (-1));
8729 #endif
8730 bar = XSCROLL_BAR (bar)->next;
8731 }
8732 }
8733
8734 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8735 is set to something other than NO_EVENT, it is enqueued.
8736
8737 This may be called from a signal handler, so we have to ignore GC
8738 mark bits. */
8739
8740 static void
8741 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8742 struct scroll_bar *bar;
8743 int part_code;
8744 EventRecord *er;
8745 struct input_event *bufp;
8746 {
8747 if (! GC_WINDOWP (bar->window))
8748 abort ();
8749
8750 bufp->kind = SCROLL_BAR_CLICK_EVENT;
8751 bufp->frame_or_window = bar->window;
8752 bufp->arg = Qnil;
8753
8754 bar->dragging = Qnil;
8755
8756 switch (part_code)
8757 {
8758 case kControlUpButtonPart:
8759 bufp->part = scroll_bar_up_arrow;
8760 break;
8761 case kControlDownButtonPart:
8762 bufp->part = scroll_bar_down_arrow;
8763 break;
8764 case kControlPageUpPart:
8765 bufp->part = scroll_bar_above_handle;
8766 break;
8767 case kControlPageDownPart:
8768 bufp->part = scroll_bar_below_handle;
8769 break;
8770 #ifdef TARGET_API_MAC_CARBON
8771 default:
8772 #else
8773 case kControlIndicatorPart:
8774 #endif
8775 if (er->what == mouseDown)
8776 bar->dragging = make_number (0);
8777 XSETVECTOR (last_mouse_scroll_bar, bar);
8778 bufp->part = scroll_bar_handle;
8779 break;
8780 }
8781 }
8782
8783
8784 /* Handle some mouse motion while someone is dragging the scroll bar.
8785
8786 This may be called from a signal handler, so we have to ignore GC
8787 mark bits. */
8788
8789 static void
8790 x_scroll_bar_note_movement (bar, y_pos, t)
8791 struct scroll_bar *bar;
8792 int y_pos;
8793 Time t;
8794 {
8795 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8796
8797 last_mouse_movement_time = t;
8798
8799 f->mouse_moved = 1;
8800 XSETVECTOR (last_mouse_scroll_bar, bar);
8801
8802 /* If we're dragging the bar, display it. */
8803 if (! GC_NILP (bar->dragging))
8804 {
8805 /* Where should the handle be now? */
8806 int new_start = y_pos - 24;
8807
8808 if (new_start != XINT (bar->start))
8809 {
8810 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8811
8812 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8813 }
8814 }
8815 }
8816
8817
8818 /* Return information to the user about the current position of the
8819 mouse on the scroll bar. */
8820
8821 static void
8822 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8823 FRAME_PTR *fp;
8824 Lisp_Object *bar_window;
8825 enum scroll_bar_part *part;
8826 Lisp_Object *x, *y;
8827 unsigned long *time;
8828 {
8829 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8830 WindowPtr wp = FrontWindow ();
8831 Point mouse_pos;
8832 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8833 int win_y, top_range;
8834
8835 #if TARGET_API_MAC_CARBON
8836 SetPort (GetWindowPort (wp));
8837 #else
8838 SetPort (wp);
8839 #endif
8840
8841 GetMouse (&mouse_pos);
8842
8843 win_y = mouse_pos.v - XINT (bar->top);
8844 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8845
8846 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8847
8848 win_y -= 24;
8849
8850 if (! NILP (bar->dragging))
8851 win_y -= XINT (bar->dragging);
8852
8853 if (win_y < 0)
8854 win_y = 0;
8855 if (win_y > top_range)
8856 win_y = top_range;
8857
8858 *fp = f;
8859 *bar_window = bar->window;
8860
8861 if (! NILP (bar->dragging))
8862 *part = scroll_bar_handle;
8863 else if (win_y < XINT (bar->start))
8864 *part = scroll_bar_above_handle;
8865 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8866 *part = scroll_bar_handle;
8867 else
8868 *part = scroll_bar_below_handle;
8869
8870 XSETINT (*x, win_y);
8871 XSETINT (*y, top_range);
8872
8873 f->mouse_moved = 0;
8874 last_mouse_scroll_bar = Qnil;
8875
8876 *time = last_mouse_movement_time;
8877 }
8878 \f
8879 /***********************************************************************
8880 Text Cursor
8881 ***********************************************************************/
8882
8883 /* Notice if the text cursor of window W has been overwritten by a
8884 drawing operation that outputs glyphs starting at START_X and
8885 ending at END_X in the line given by output_cursor.vpos.
8886 Coordinates are area-relative. END_X < 0 means all the rest
8887 of the line after START_X has been written. */
8888
8889 static void
8890 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
8891 struct window *w;
8892 enum glyph_row_area area;
8893 int x0, x1, y0, y1;
8894 {
8895 if (area == TEXT_AREA
8896 && w->phys_cursor_on_p
8897 && y0 <= w->phys_cursor.y
8898 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8899 && x0 <= w->phys_cursor.x
8900 && (x1 < 0 || x1 > w->phys_cursor.x))
8901 w->phys_cursor_on_p = 0;
8902 }
8903
8904
8905 /* Set clipping for output in glyph row ROW. W is the window in which
8906 we operate. GC is the graphics context to set clipping in.
8907 WHOLE_LINE_P non-zero means include the areas used for truncation
8908 mark display and alike in the clipping rectangle.
8909
8910 ROW may be a text row or, e.g., a mode line. Text rows must be
8911 clipped to the interior of the window dedicated to text display,
8912 mode lines must be clipped to the whole window. */
8913
8914 static void
8915 x_clip_to_row (w, row, gc, whole_line_p)
8916 struct window *w;
8917 struct glyph_row *row;
8918 GC gc;
8919 int whole_line_p;
8920 {
8921 struct frame *f = XFRAME (WINDOW_FRAME (w));
8922 Rect clip_rect;
8923 int window_x, window_y, window_width, window_height;
8924
8925 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8926
8927 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8928 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8929 clip_rect.top = max (clip_rect.top, window_y);
8930 clip_rect.right = clip_rect.left + window_width;
8931 clip_rect.bottom = clip_rect.top + row->visible_height;
8932
8933 /* If clipping to the whole line, including trunc marks, extend
8934 the rectangle to the left and increase its width. */
8935 if (whole_line_p)
8936 {
8937 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8938 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
8939 }
8940
8941 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8942 }
8943
8944
8945 /* Draw a hollow box cursor on window W in glyph row ROW. */
8946
8947 static void
8948 x_draw_hollow_cursor (w, row)
8949 struct window *w;
8950 struct glyph_row *row;
8951 {
8952 struct frame *f = XFRAME (WINDOW_FRAME (w));
8953 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8954 Display *dpy = FRAME_MAC_DISPLAY (f);
8955 int x, y, wd, h;
8956 XGCValues xgcv;
8957 struct glyph *cursor_glyph;
8958 GC gc;
8959
8960 /* Compute frame-relative coordinates from window-relative
8961 coordinates. */
8962 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8963 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8964 + row->ascent - w->phys_cursor_ascent);
8965 h = row->height - 1;
8966
8967 /* Get the glyph the cursor is on. If we can't tell because
8968 the current matrix is invalid or such, give up. */
8969 cursor_glyph = get_phys_cursor_glyph (w);
8970 if (cursor_glyph == NULL)
8971 return;
8972
8973 /* Compute the width of the rectangle to draw. If on a stretch
8974 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8975 rectangle as wide as the glyph, but use a canonical character
8976 width instead. */
8977 wd = cursor_glyph->pixel_width - 1;
8978 if (cursor_glyph->type == STRETCH_GLYPH
8979 && !x_stretch_cursor_p)
8980 wd = min (CANON_X_UNIT (f), wd);
8981
8982 /* The foreground of cursor_gc is typically the same as the normal
8983 background color, which can cause the cursor box to be invisible. */
8984 xgcv.foreground = f->output_data.mac->cursor_pixel;
8985 if (dpyinfo->scratch_cursor_gc)
8986 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8987 else
8988 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8989 GCForeground, &xgcv);
8990 gc = dpyinfo->scratch_cursor_gc;
8991
8992 /* Set clipping, draw the rectangle, and reset clipping again. */
8993 x_clip_to_row (w, row, gc, 0);
8994 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
8995 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8996 }
8997
8998
8999 /* Draw a bar cursor on window W in glyph row ROW.
9000
9001 Implementation note: One would like to draw a bar cursor with an
9002 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9003 Unfortunately, I didn't find a font yet that has this property set.
9004 --gerd. */
9005
9006 static void
9007 x_draw_bar_cursor (w, row, width)
9008 struct window *w;
9009 struct glyph_row *row;
9010 int width;
9011 {
9012 /* If cursor hpos is out of bounds, don't draw garbage. This can
9013 happen in mini-buffer windows when switching between echo area
9014 glyphs and mini-buffer. */
9015 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9016 {
9017 struct frame *f = XFRAME (w->frame);
9018 struct glyph *cursor_glyph;
9019 GC gc;
9020 int x;
9021 unsigned long mask;
9022 XGCValues xgcv;
9023 Display *dpy;
9024 Window window;
9025
9026 cursor_glyph = get_phys_cursor_glyph (w);
9027 if (cursor_glyph == NULL)
9028 return;
9029
9030 xgcv.background = f->output_data.mac->cursor_pixel;
9031 xgcv.foreground = f->output_data.mac->cursor_pixel;
9032 mask = GCForeground | GCBackground;
9033 dpy = FRAME_MAC_DISPLAY (f);
9034 window = FRAME_MAC_WINDOW (f);
9035 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9036
9037 if (gc)
9038 XChangeGC (dpy, gc, mask, &xgcv);
9039 else
9040 {
9041 gc = XCreateGC (dpy, window, mask, &xgcv);
9042 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9043 }
9044
9045 if (width < 0)
9046 width = f->output_data.mac->cursor_width;
9047
9048 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9049 x_clip_to_row (w, row, gc, 0);
9050 XFillRectangle (dpy, window, gc,
9051 x,
9052 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9053 min (cursor_glyph->pixel_width, width),
9054 row->height);
9055 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9056 }
9057 }
9058
9059
9060 /* Clear the cursor of window W to background color, and mark the
9061 cursor as not shown. This is used when the text where the cursor
9062 is is about to be rewritten. */
9063
9064 static void
9065 x_clear_cursor (w)
9066 struct window *w;
9067 {
9068 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9069 x_update_window_cursor (w, 0);
9070 }
9071
9072
9073 /* Draw the cursor glyph of window W in glyph row ROW. See the
9074 comment of x_draw_glyphs for the meaning of HL. */
9075
9076 static void
9077 x_draw_phys_cursor_glyph (w, row, hl)
9078 struct window *w;
9079 struct glyph_row *row;
9080 enum draw_glyphs_face hl;
9081 {
9082 /* If cursor hpos is out of bounds, don't draw garbage. This can
9083 happen in mini-buffer windows when switching between echo area
9084 glyphs and mini-buffer. */
9085 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9086 {
9087 int on_p = w->phys_cursor_on_p;
9088 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9089 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9090 hl, 0);
9091 w->phys_cursor_on_p = on_p;
9092
9093 /* When we erase the cursor, and ROW is overlapped by other
9094 rows, make sure that these overlapping parts of other rows
9095 are redrawn. */
9096 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9097 {
9098 if (row > w->current_matrix->rows
9099 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9100 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9101
9102 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9103 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9104 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9105 }
9106 }
9107 }
9108
9109
9110 /* Erase the image of a cursor of window W from the screen. */
9111
9112 static void
9113 x_erase_phys_cursor (w)
9114 struct window *w;
9115 {
9116 struct frame *f = XFRAME (w->frame);
9117 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9118 int hpos = w->phys_cursor.hpos;
9119 int vpos = w->phys_cursor.vpos;
9120 int mouse_face_here_p = 0;
9121 struct glyph_matrix *active_glyphs = w->current_matrix;
9122 struct glyph_row *cursor_row;
9123 struct glyph *cursor_glyph;
9124 enum draw_glyphs_face hl;
9125
9126 /* No cursor displayed or row invalidated => nothing to do on the
9127 screen. */
9128 if (w->phys_cursor_type == NO_CURSOR)
9129 goto mark_cursor_off;
9130
9131 /* VPOS >= active_glyphs->nrows means that window has been resized.
9132 Don't bother to erase the cursor. */
9133 if (vpos >= active_glyphs->nrows)
9134 goto mark_cursor_off;
9135
9136 /* If row containing cursor is marked invalid, there is nothing we
9137 can do. */
9138 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9139 if (!cursor_row->enabled_p)
9140 goto mark_cursor_off;
9141
9142 /* If row is completely invisible, don't attempt to delete a cursor which
9143 isn't there. This may happen if cursor is at top of window, and
9144 we switch to a buffer with a header line in that window. */
9145 if (cursor_row->visible_height <= 0)
9146 goto mark_cursor_off;
9147
9148 /* This can happen when the new row is shorter than the old one.
9149 In this case, either x_draw_glyphs or clear_end_of_line
9150 should have cleared the cursor. Note that we wouldn't be
9151 able to erase the cursor in this case because we don't have a
9152 cursor glyph at hand. */
9153 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9154 goto mark_cursor_off;
9155
9156 /* If the cursor is in the mouse face area, redisplay that when
9157 we clear the cursor. */
9158 if (! NILP (dpyinfo->mouse_face_window)
9159 && w == XWINDOW (dpyinfo->mouse_face_window)
9160 && (vpos > dpyinfo->mouse_face_beg_row
9161 || (vpos == dpyinfo->mouse_face_beg_row
9162 && hpos >= dpyinfo->mouse_face_beg_col))
9163 && (vpos < dpyinfo->mouse_face_end_row
9164 || (vpos == dpyinfo->mouse_face_end_row
9165 && hpos < dpyinfo->mouse_face_end_col))
9166 /* Don't redraw the cursor's spot in mouse face if it is at the
9167 end of a line (on a newline). The cursor appears there, but
9168 mouse highlighting does not. */
9169 && cursor_row->used[TEXT_AREA] > hpos)
9170 mouse_face_here_p = 1;
9171
9172 /* Maybe clear the display under the cursor. */
9173 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9174 {
9175 int x;
9176 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9177
9178 cursor_glyph = get_phys_cursor_glyph (w);
9179 if (cursor_glyph == NULL)
9180 goto mark_cursor_off;
9181
9182 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9183
9184 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9185 x,
9186 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9187 cursor_row->y)),
9188 cursor_glyph->pixel_width,
9189 cursor_row->visible_height,
9190 0);
9191 }
9192
9193 /* Erase the cursor by redrawing the character underneath it. */
9194 if (mouse_face_here_p)
9195 hl = DRAW_MOUSE_FACE;
9196 else
9197 hl = DRAW_NORMAL_TEXT;
9198 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9199
9200 mark_cursor_off:
9201 w->phys_cursor_on_p = 0;
9202 w->phys_cursor_type = NO_CURSOR;
9203 }
9204
9205
9206 /* Non-zero if physical cursor of window W is within mouse face. */
9207
9208 static int
9209 cursor_in_mouse_face_p (w)
9210 struct window *w;
9211 {
9212 struct mac_display_info *dpyinfo
9213 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9214 int in_mouse_face = 0;
9215
9216 if (WINDOWP (dpyinfo->mouse_face_window)
9217 && XWINDOW (dpyinfo->mouse_face_window) == w)
9218 {
9219 int hpos = w->phys_cursor.hpos;
9220 int vpos = w->phys_cursor.vpos;
9221
9222 if (vpos >= dpyinfo->mouse_face_beg_row
9223 && vpos <= dpyinfo->mouse_face_end_row
9224 && (vpos > dpyinfo->mouse_face_beg_row
9225 || hpos >= dpyinfo->mouse_face_beg_col)
9226 && (vpos < dpyinfo->mouse_face_end_row
9227 || hpos < dpyinfo->mouse_face_end_col
9228 || dpyinfo->mouse_face_past_end))
9229 in_mouse_face = 1;
9230 }
9231
9232 return in_mouse_face;
9233 }
9234
9235
9236 /* Display or clear cursor of window W. If ON is zero, clear the
9237 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9238 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9239
9240 void
9241 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9242 struct window *w;
9243 int on, hpos, vpos, x, y;
9244 {
9245 struct frame *f = XFRAME (w->frame);
9246 int new_cursor_type;
9247 int new_cursor_width;
9248 struct glyph_matrix *current_glyphs;
9249 struct glyph_row *glyph_row;
9250 struct glyph *glyph;
9251 int cursor_non_selected;
9252 int active_cursor = 1;
9253
9254 /* This is pointless on invisible frames, and dangerous on garbaged
9255 windows and frames; in the latter case, the frame or window may
9256 be in the midst of changing its size, and x and y may be off the
9257 window. */
9258 if (! FRAME_VISIBLE_P (f)
9259 || FRAME_GARBAGED_P (f)
9260 || vpos >= w->current_matrix->nrows
9261 || hpos >= w->current_matrix->matrix_w)
9262 return;
9263
9264 /* If cursor is off and we want it off, return quickly. */
9265 if (!on && !w->phys_cursor_on_p)
9266 return;
9267
9268 current_glyphs = w->current_matrix;
9269 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9270 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9271
9272 /* If cursor row is not enabled, we don't really know where to
9273 display the cursor. */
9274 if (!glyph_row->enabled_p)
9275 {
9276 w->phys_cursor_on_p = 0;
9277 return;
9278 }
9279
9280 xassert (interrupt_input_blocked);
9281
9282 /* Set new_cursor_type to the cursor we want to be displayed. In a
9283 mini-buffer window, we want the cursor only to appear if we are
9284 reading input from this window. For the selected window, we want
9285 the cursor type given by the frame parameter. If explicitly
9286 marked off, draw no cursor. In all other cases, we want a hollow
9287 box cursor. */
9288 cursor_non_selected
9289 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
9290 w->buffer));
9291 new_cursor_width = -1;
9292 if (cursor_in_echo_area
9293 && FRAME_HAS_MINIBUF_P (f)
9294 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
9295 {
9296 if (w == XWINDOW (echo_area_window))
9297 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9298 else
9299 {
9300 if (cursor_non_selected)
9301 new_cursor_type = HOLLOW_BOX_CURSOR;
9302 else
9303 new_cursor_type = NO_CURSOR;
9304 active_cursor = 0;
9305 }
9306 }
9307 else
9308 {
9309 if (f != FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame
9310 || w != XWINDOW (f->selected_window))
9311 {
9312 active_cursor = 0;
9313
9314 if (MINI_WINDOW_P (w)
9315 || !cursor_non_selected
9316 || NILP (XBUFFER (w->buffer)->cursor_type))
9317 new_cursor_type = NO_CURSOR;
9318 else
9319 new_cursor_type = HOLLOW_BOX_CURSOR;
9320 }
9321 else
9322 {
9323 struct buffer *b = XBUFFER (w->buffer);
9324
9325 if (EQ (b->cursor_type, Qt))
9326 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9327 else
9328 new_cursor_type = x_specified_cursor_type (b->cursor_type,
9329 &new_cursor_width);
9330 if (w->cursor_off_p)
9331 {
9332 if (new_cursor_type == FILLED_BOX_CURSOR)
9333 new_cursor_type = HOLLOW_BOX_CURSOR;
9334 else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
9335 new_cursor_width = 1;
9336 else
9337 new_cursor_type = NO_CURSOR;
9338 }
9339 }
9340 }
9341
9342 /* If cursor is currently being shown and we don't want it to be or
9343 it is in the wrong place, or the cursor type is not what we want,
9344 erase it. */
9345 if (w->phys_cursor_on_p
9346 && (!on
9347 || w->phys_cursor.x != x
9348 || w->phys_cursor.y != y
9349 || new_cursor_type != w->phys_cursor_type
9350 || (new_cursor_type == BAR_CURSOR
9351 && new_cursor_width != w->phys_cursor_width)))
9352 x_erase_phys_cursor (w);
9353
9354 /* If the cursor is now invisible and we want it to be visible,
9355 display it. */
9356 if (on && !w->phys_cursor_on_p)
9357 {
9358 w->phys_cursor_ascent = glyph_row->ascent;
9359 w->phys_cursor_height = glyph_row->height;
9360
9361 /* Set phys_cursor_.* before x_draw_.* is called because some
9362 of them may need the information. */
9363 w->phys_cursor.x = x;
9364 w->phys_cursor.y = glyph_row->y;
9365 w->phys_cursor.hpos = hpos;
9366 w->phys_cursor.vpos = vpos;
9367 w->phys_cursor_type = new_cursor_type;
9368 w->phys_cursor_width = new_cursor_width;
9369 w->phys_cursor_on_p = 1;
9370
9371 switch (new_cursor_type)
9372 {
9373 case HOLLOW_BOX_CURSOR:
9374 x_draw_hollow_cursor (w, glyph_row);
9375 break;
9376
9377 case FILLED_BOX_CURSOR:
9378 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9379 break;
9380
9381 case BAR_CURSOR:
9382 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9383 break;
9384
9385 case NO_CURSOR:
9386 break;
9387
9388 default:
9389 abort ();
9390 }
9391 }
9392 }
9393
9394
9395 /* Display the cursor on window W, or clear it. X and Y are window
9396 relative pixel coordinates. HPOS and VPOS are glyph matrix
9397 positions. If W is not the selected window, display a hollow
9398 cursor. ON non-zero means display the cursor at X, Y which
9399 correspond to HPOS, VPOS, otherwise it is cleared. */
9400
9401 void
9402 x_display_cursor (w, on, hpos, vpos, x, y)
9403 struct window *w;
9404 int on, hpos, vpos, x, y;
9405 {
9406 BLOCK_INPUT;
9407 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9408 UNBLOCK_INPUT;
9409 }
9410
9411
9412 /* Display the cursor on window W, or clear it, according to ON_P.
9413 Don't change the cursor's position. */
9414
9415 void
9416 x_update_cursor (f, on_p)
9417 struct frame *f;
9418 int on_p;
9419 {
9420 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9421 }
9422
9423
9424 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9425 in the window tree rooted at W. */
9426
9427 static void
9428 x_update_cursor_in_window_tree (w, on_p)
9429 struct window *w;
9430 int on_p;
9431 {
9432 while (w)
9433 {
9434 if (!NILP (w->hchild))
9435 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9436 else if (!NILP (w->vchild))
9437 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9438 else
9439 x_update_window_cursor (w, on_p);
9440
9441 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9442 }
9443 }
9444
9445
9446 /* Switch the display of W's cursor on or off, according to the value
9447 of ON. */
9448
9449 static void
9450 x_update_window_cursor (w, on)
9451 struct window *w;
9452 int on;
9453 {
9454 /* Don't update cursor in windows whose frame is in the process
9455 of being deleted. */
9456 if (w->current_matrix)
9457 {
9458 BLOCK_INPUT;
9459 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9460 w->phys_cursor.vpos, w->phys_cursor.x,
9461 w->phys_cursor.y);
9462 UNBLOCK_INPUT;
9463 }
9464 }
9465
9466
9467
9468 \f
9469 /* Icons. */
9470
9471 #if 0 /* MAC_TODO: no icon support yet. */
9472 int
9473 x_bitmap_icon (f, icon)
9474 struct frame *f;
9475 Lisp_Object icon;
9476 {
9477 HANDLE hicon;
9478
9479 if (FRAME_W32_WINDOW (f) == 0)
9480 return 1;
9481
9482 if (NILP (icon))
9483 hicon = LoadIcon (hinst, EMACS_CLASS);
9484 else if (STRINGP (icon))
9485 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
9486 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9487 else if (SYMBOLP (icon))
9488 {
9489 LPCTSTR name;
9490
9491 if (EQ (icon, intern ("application")))
9492 name = (LPCTSTR) IDI_APPLICATION;
9493 else if (EQ (icon, intern ("hand")))
9494 name = (LPCTSTR) IDI_HAND;
9495 else if (EQ (icon, intern ("question")))
9496 name = (LPCTSTR) IDI_QUESTION;
9497 else if (EQ (icon, intern ("exclamation")))
9498 name = (LPCTSTR) IDI_EXCLAMATION;
9499 else if (EQ (icon, intern ("asterisk")))
9500 name = (LPCTSTR) IDI_ASTERISK;
9501 else if (EQ (icon, intern ("winlogo")))
9502 name = (LPCTSTR) IDI_WINLOGO;
9503 else
9504 return 1;
9505
9506 hicon = LoadIcon (NULL, name);
9507 }
9508 else
9509 return 1;
9510
9511 if (hicon == NULL)
9512 return 1;
9513
9514 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9515 (LPARAM) hicon);
9516
9517 return 0;
9518 }
9519 #endif /* MAC_TODO */
9520 \f
9521 /************************************************************************
9522 Handling X errors
9523 ************************************************************************/
9524
9525 /* Display Error Handling functions not used on W32. Listing them here
9526 helps diff stay in step when comparing w32term.c with xterm.c.
9527
9528 x_error_catcher (display, error)
9529 x_catch_errors (dpy)
9530 x_catch_errors_unwind (old_val)
9531 x_check_errors (dpy, format)
9532 x_had_errors_p (dpy)
9533 x_clear_errors (dpy)
9534 x_uncatch_errors (dpy, count)
9535 x_trace_wire ()
9536 x_connection_signal (signalnum)
9537 x_connection_closed (dpy, error_message)
9538 x_error_quitter (display, error)
9539 x_error_handler (display, error)
9540 x_io_error_quitter (display)
9541
9542 */
9543
9544 \f
9545 /* Changing the font of the frame. */
9546
9547 /* Give frame F the font named FONTNAME as its default font, and
9548 return the full name of that font. FONTNAME may be a wildcard
9549 pattern; in that case, we choose some font that fits the pattern.
9550 The return value shows which font we chose. */
9551
9552 Lisp_Object
9553 x_new_font (f, fontname)
9554 struct frame *f;
9555 register char *fontname;
9556 {
9557 struct font_info *fontp
9558 = FS_LOAD_FONT (f, 0, fontname, -1);
9559
9560 if (!fontp)
9561 return Qnil;
9562
9563 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9564 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9565 FRAME_FONTSET (f) = -1;
9566
9567 /* Compute the scroll bar width in character columns. */
9568 if (f->scroll_bar_pixel_width > 0)
9569 {
9570 int wid = FONT_WIDTH (FRAME_FONT (f));
9571 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9572 }
9573 else
9574 {
9575 int wid = FONT_WIDTH (FRAME_FONT (f));
9576 f->scroll_bar_cols = (14 + wid - 1) / wid;
9577 }
9578
9579 /* Now make the frame display the given font. */
9580 if (FRAME_MAC_WINDOW (f) != 0)
9581 {
9582 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9583 f->output_data.mac->font);
9584 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9585 f->output_data.mac->font);
9586 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9587 f->output_data.mac->font);
9588
9589 frame_update_line_height (f);
9590 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9591 x_set_window_size (f, 0, f->width, f->height);
9592 }
9593 else
9594 /* If we are setting a new frame's font for the first time,
9595 there are no faces yet, so this font's height is the line height. */
9596 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
9597
9598 return build_string (fontp->full_name);
9599 }
9600 \f
9601 /* Give frame F the fontset named FONTSETNAME as its default font, and
9602 return the full name of that fontset. FONTSETNAME may be a wildcard
9603 pattern; in that case, we choose some fontset that fits the pattern.
9604 The return value shows which fontset we chose. */
9605
9606 Lisp_Object
9607 x_new_fontset (f, fontsetname)
9608 struct frame *f;
9609 char *fontsetname;
9610 {
9611 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9612 Lisp_Object result;
9613
9614 if (fontset < 0)
9615 return Qnil;
9616
9617 if (FRAME_FONTSET (f) == fontset)
9618 /* This fontset is already set in frame F. There's nothing more
9619 to do. */
9620 return fontset_name (fontset);
9621
9622 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
9623
9624 if (!STRINGP (result))
9625 /* Can't load ASCII font. */
9626 return Qnil;
9627
9628 /* Since x_new_font doesn't update any fontset information, do it now. */
9629 FRAME_FONTSET(f) = fontset;
9630
9631 return build_string (fontsetname);
9632 }
9633
9634 /* Compute actual fringe widths */
9635
9636 void
9637 x_compute_fringe_widths (f, redraw)
9638 struct frame *f;
9639 int redraw;
9640 {
9641 int o_left = f->output_data.mac->left_fringe_width;
9642 int o_right = f->output_data.mac->right_fringe_width;
9643 int o_cols = f->output_data.mac->fringe_cols;
9644
9645 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9646 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9647 int left_fringe_width, right_fringe_width;
9648
9649 if (!NILP (left_fringe))
9650 left_fringe = Fcdr (left_fringe);
9651 if (!NILP (right_fringe))
9652 right_fringe = Fcdr (right_fringe);
9653
9654 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9655 XINT (left_fringe));
9656 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9657 XINT (right_fringe));
9658
9659 if (left_fringe_width || right_fringe_width)
9660 {
9661 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9662 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9663 int conf_wid = left_wid + right_wid;
9664 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9665 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9666 int real_wid = cols * font_wid;
9667 if (left_wid && right_wid)
9668 {
9669 if (left_fringe_width < 0)
9670 {
9671 /* Left fringe width is fixed, adjust right fringe if necessary */
9672 f->output_data.mac->left_fringe_width = left_wid;
9673 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9674 }
9675 else if (right_fringe_width < 0)
9676 {
9677 /* Right fringe width is fixed, adjust left fringe if necessary */
9678 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9679 f->output_data.mac->right_fringe_width = right_wid;
9680 }
9681 else
9682 {
9683 /* Adjust both fringes with an equal amount.
9684 Note that we are doing integer arithmetic here, so don't
9685 lose a pixel if the total width is an odd number. */
9686 int fill = real_wid - conf_wid;
9687 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9688 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9689 }
9690 }
9691 else if (left_fringe_width)
9692 {
9693 f->output_data.mac->left_fringe_width = real_wid;
9694 f->output_data.mac->right_fringe_width = 0;
9695 }
9696 else
9697 {
9698 f->output_data.mac->left_fringe_width = 0;
9699 f->output_data.mac->right_fringe_width = real_wid;
9700 }
9701 f->output_data.mac->fringe_cols = cols;
9702 f->output_data.mac->fringes_extra = real_wid;
9703 }
9704 else
9705 {
9706 f->output_data.mac->left_fringe_width = 0;
9707 f->output_data.mac->right_fringe_width = 0;
9708 f->output_data.mac->fringe_cols = 0;
9709 f->output_data.mac->fringes_extra = 0;
9710 }
9711
9712 if (redraw && FRAME_VISIBLE_P (f))
9713 if (o_left != f->output_data.mac->left_fringe_width ||
9714 o_right != f->output_data.mac->right_fringe_width ||
9715 o_cols != f->output_data.mac->fringe_cols)
9716 redraw_frame (f);
9717 }
9718 \f
9719 /***********************************************************************
9720 TODO: W32 Input Methods
9721 ***********************************************************************/
9722 /* Listing missing functions from xterm.c helps diff stay in step.
9723
9724 xim_destroy_callback (xim, client_data, call_data)
9725 xim_open_dpy (dpyinfo, resource_name)
9726 struct xim_inst_t
9727 xim_instantiate_callback (display, client_data, call_data)
9728 xim_initialize (dpyinfo, resource_name)
9729 xim_close_dpy (dpyinfo)
9730
9731 */
9732
9733 \f
9734 /* Calculate the absolute position in frame F
9735 from its current recorded position values and gravity. */
9736
9737 void
9738 x_calc_absolute_position (f)
9739 struct frame *f;
9740 {
9741 Point pt;
9742 int flags = f->output_data.mac->size_hint_flags;
9743
9744 pt.h = pt.v = 0;
9745
9746 /* Find the position of the outside upper-left corner of
9747 the inner window, with respect to the outer window. */
9748 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9749 {
9750 GrafPtr savePort;
9751 GetPort (&savePort);
9752
9753 #if TARGET_API_MAC_CARBON
9754 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9755 #else
9756 SetPort (FRAME_MAC_WINDOW (f));
9757 #endif
9758
9759 #if TARGET_API_MAC_CARBON
9760 {
9761 Rect r;
9762
9763 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9764 SetPt(&pt, r.left, r.top);
9765 }
9766 #else /* not TARGET_API_MAC_CARBON */
9767 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
9768 #endif /* not TARGET_API_MAC_CARBON */
9769 LocalToGlobal (&pt);
9770 SetPort (savePort);
9771 }
9772
9773 /* Treat negative positions as relative to the leftmost bottommost
9774 position that fits on the screen. */
9775 if (flags & XNegative)
9776 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9777 - 2 * f->output_data.mac->border_width - pt.h
9778 - PIXEL_WIDTH (f)
9779 + f->output_data.mac->left_pos);
9780 /* NTEMACS_TODO: Subtract menubar height? */
9781 if (flags & YNegative)
9782 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9783 - 2 * f->output_data.mac->border_width - pt.v
9784 - PIXEL_HEIGHT (f)
9785 + f->output_data.mac->top_pos);
9786 /* The left_pos and top_pos
9787 are now relative to the top and left screen edges,
9788 so the flags should correspond. */
9789 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9790 }
9791
9792 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9793 to really change the position, and 0 when calling from
9794 x_make_frame_visible (in that case, XOFF and YOFF are the current
9795 position values). It is -1 when calling from x_set_frame_parameters,
9796 which means, do adjust for borders but don't change the gravity. */
9797
9798 void
9799 x_set_offset (f, xoff, yoff, change_gravity)
9800 struct frame *f;
9801 register int xoff, yoff;
9802 int change_gravity;
9803 {
9804 int modified_top, modified_left;
9805
9806 if (change_gravity > 0)
9807 {
9808 f->output_data.mac->top_pos = yoff;
9809 f->output_data.mac->left_pos = xoff;
9810 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9811 if (xoff < 0)
9812 f->output_data.mac->size_hint_flags |= XNegative;
9813 if (yoff < 0)
9814 f->output_data.mac->size_hint_flags |= YNegative;
9815 f->output_data.mac->win_gravity = NorthWestGravity;
9816 }
9817 x_calc_absolute_position (f);
9818
9819 BLOCK_INPUT;
9820 x_wm_set_size_hint (f, (long) 0, 0);
9821
9822 modified_left = f->output_data.mac->left_pos;
9823 modified_top = f->output_data.mac->top_pos;
9824
9825 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9826 modified_top + 42, false);
9827
9828 UNBLOCK_INPUT;
9829 }
9830
9831 /* Call this to change the size of frame F's x-window.
9832 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9833 for this size change and subsequent size changes.
9834 Otherwise we leave the window gravity unchanged. */
9835
9836 void
9837 x_set_window_size (f, change_gravity, cols, rows)
9838 struct frame *f;
9839 int change_gravity;
9840 int cols, rows;
9841 {
9842 int pixelwidth, pixelheight;
9843
9844 BLOCK_INPUT;
9845
9846 check_frame_size (f, &rows, &cols);
9847 f->output_data.mac->vertical_scroll_bar_extra
9848 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9849 ? 0
9850 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
9851
9852 x_compute_fringe_widths (f, 0);
9853
9854 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9855 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9856
9857 f->output_data.mac->win_gravity = NorthWestGravity;
9858 x_wm_set_size_hint (f, (long) 0, 0);
9859
9860 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9861
9862 /* Now, strictly speaking, we can't be sure that this is accurate,
9863 but the window manager will get around to dealing with the size
9864 change request eventually, and we'll hear how it went when the
9865 ConfigureNotify event gets here.
9866
9867 We could just not bother storing any of this information here,
9868 and let the ConfigureNotify event set everything up, but that
9869 might be kind of confusing to the Lisp code, since size changes
9870 wouldn't be reported in the frame parameters until some random
9871 point in the future when the ConfigureNotify event arrives.
9872
9873 We pass 1 for DELAY since we can't run Lisp code inside of
9874 a BLOCK_INPUT. */
9875 change_frame_size (f, rows, cols, 0, 1, 0);
9876 PIXEL_WIDTH (f) = pixelwidth;
9877 PIXEL_HEIGHT (f) = pixelheight;
9878
9879 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9880 receive in the ConfigureNotify event; if we get what we asked
9881 for, then the event won't cause the screen to become garbaged, so
9882 we have to make sure to do it here. */
9883 SET_FRAME_GARBAGED (f);
9884
9885 XFlush (FRAME_X_DISPLAY (f));
9886
9887 /* If cursor was outside the new size, mark it as off. */
9888 mark_window_cursors_off (XWINDOW (f->root_window));
9889
9890 /* Clear out any recollection of where the mouse highlighting was,
9891 since it might be in a place that's outside the new frame size.
9892 Actually checking whether it is outside is a pain in the neck,
9893 so don't try--just let the highlighting be done afresh with new size. */
9894 cancel_mouse_face (f);
9895
9896 UNBLOCK_INPUT;
9897 }
9898 \f
9899 /* Mouse warping. */
9900
9901 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9902
9903 void
9904 x_set_mouse_position (f, x, y)
9905 struct frame *f;
9906 int x, y;
9907 {
9908 int pix_x, pix_y;
9909
9910 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9911 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9912
9913 if (pix_x < 0) pix_x = 0;
9914 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9915
9916 if (pix_y < 0) pix_y = 0;
9917 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9918
9919 x_set_mouse_pixel_position (f, pix_x, pix_y);
9920 }
9921
9922 void
9923 x_set_mouse_pixel_position (f, pix_x, pix_y)
9924 struct frame *f;
9925 int pix_x, pix_y;
9926 {
9927 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9928 BLOCK_INPUT;
9929
9930 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9931 0, 0, 0, 0, pix_x, pix_y);
9932 UNBLOCK_INPUT;
9933 #endif
9934 }
9935
9936 \f
9937 /* focus shifting, raising and lowering. */
9938
9939 void
9940 x_focus_on_frame (f)
9941 struct frame *f;
9942 {
9943 #if 0 /* This proves to be unpleasant. */
9944 x_raise_frame (f);
9945 #endif
9946 #if 0
9947 /* I don't think that the ICCCM allows programs to do things like this
9948 without the interaction of the window manager. Whatever you end up
9949 doing with this code, do it to x_unfocus_frame too. */
9950 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9951 RevertToPointerRoot, CurrentTime);
9952 #endif /* ! 0 */
9953 }
9954
9955 void
9956 x_unfocus_frame (f)
9957 struct frame *f;
9958 {
9959 }
9960
9961 /* Raise frame F. */
9962 void
9963 x_raise_frame (f)
9964 struct frame *f;
9965 {
9966 if (f->async_visible)
9967 SelectWindow (FRAME_MAC_WINDOW (f));
9968 }
9969
9970 /* Lower frame F. */
9971 void
9972 x_lower_frame (f)
9973 struct frame *f;
9974 {
9975 if (f->async_visible)
9976 SendBehind (FRAME_MAC_WINDOW (f), nil);
9977 }
9978
9979 static void
9980 XTframe_raise_lower (f, raise_flag)
9981 FRAME_PTR f;
9982 int raise_flag;
9983 {
9984 if (raise_flag)
9985 x_raise_frame (f);
9986 else
9987 x_lower_frame (f);
9988 }
9989 \f
9990 /* Change of visibility. */
9991
9992 /* This tries to wait until the frame is really visible.
9993 However, if the window manager asks the user where to position
9994 the frame, this will return before the user finishes doing that.
9995 The frame will not actually be visible at that time,
9996 but it will become visible later when the window manager
9997 finishes with it. */
9998
9999 void
10000 x_make_frame_visible (f)
10001 struct frame *f;
10002 {
10003 Lisp_Object type;
10004 int original_top, original_left;
10005
10006 BLOCK_INPUT;
10007
10008 if (! FRAME_VISIBLE_P (f))
10009 {
10010 /* We test FRAME_GARBAGED_P here to make sure we don't
10011 call x_set_offset a second time
10012 if we get to x_make_frame_visible a second time
10013 before the window gets really visible. */
10014 if (! FRAME_ICONIFIED_P (f)
10015 && ! f->output_data.mac->asked_for_visible)
10016 x_set_offset (f, f->output_data.mac->left_pos,
10017 f->output_data.mac->top_pos, 0);
10018
10019 f->output_data.mac->asked_for_visible = 1;
10020
10021 ShowWindow (FRAME_MAC_WINDOW (f));
10022 }
10023
10024 XFlush (FRAME_MAC_DISPLAY (f));
10025
10026 #if 0 /* MAC_TODO */
10027 /* Synchronize to ensure Emacs knows the frame is visible
10028 before we do anything else. We do this loop with input not blocked
10029 so that incoming events are handled. */
10030 {
10031 Lisp_Object frame;
10032 int count;
10033
10034 /* This must come after we set COUNT. */
10035 UNBLOCK_INPUT;
10036
10037 XSETFRAME (frame, f);
10038
10039 /* Wait until the frame is visible. Process X events until a
10040 MapNotify event has been seen, or until we think we won't get a
10041 MapNotify at all.. */
10042 for (count = input_signal_count + 10;
10043 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10044 {
10045 /* Force processing of queued events. */
10046 x_sync (f);
10047
10048 /* Machines that do polling rather than SIGIO have been
10049 observed to go into a busy-wait here. So we'll fake an
10050 alarm signal to let the handler know that there's something
10051 to be read. We used to raise a real alarm, but it seems
10052 that the handler isn't always enabled here. This is
10053 probably a bug. */
10054 if (input_polling_used ())
10055 {
10056 /* It could be confusing if a real alarm arrives while
10057 processing the fake one. Turn it off and let the
10058 handler reset it. */
10059 extern void poll_for_input_1 P_ ((void));
10060 int old_poll_suppress_count = poll_suppress_count;
10061 poll_suppress_count = 1;
10062 poll_for_input_1 ();
10063 poll_suppress_count = old_poll_suppress_count;
10064 }
10065
10066 /* See if a MapNotify event has been processed. */
10067 FRAME_SAMPLE_VISIBILITY (f);
10068 }
10069 }
10070 #endif /* MAC_TODO */
10071 }
10072
10073 /* Change from mapped state to withdrawn state. */
10074
10075 /* Make the frame visible (mapped and not iconified). */
10076
10077 void
10078 x_make_frame_invisible (f)
10079 struct frame *f;
10080 {
10081 /* Don't keep the highlight on an invisible frame. */
10082 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10083 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10084
10085 BLOCK_INPUT;
10086
10087 HideWindow (FRAME_MAC_WINDOW (f));
10088
10089 /* We can't distinguish this from iconification
10090 just by the event that we get from the server.
10091 So we can't win using the usual strategy of letting
10092 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10093 and synchronize with the server to make sure we agree. */
10094 f->visible = 0;
10095 FRAME_ICONIFIED_P (f) = 0;
10096 f->async_visible = 0;
10097 f->async_iconified = 0;
10098
10099 UNBLOCK_INPUT;
10100 }
10101
10102 /* Change window state from mapped to iconified. */
10103
10104 void
10105 x_iconify_frame (f)
10106 struct frame *f;
10107 {
10108 /* Don't keep the highlight on an invisible frame. */
10109 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10110 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10111
10112 #if 0
10113 /* Review: Since window is still visible in dock, still allow updates? */
10114 if (f->async_iconified)
10115 return;
10116 #endif
10117
10118 BLOCK_INPUT;
10119
10120 CollapseWindow (FRAME_MAC_WINDOW (f), true);
10121
10122 UNBLOCK_INPUT;
10123 }
10124
10125 \f
10126 /* Destroy the X window of frame F. */
10127
10128 void
10129 x_destroy_window (f)
10130 struct frame *f;
10131 {
10132 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10133
10134 BLOCK_INPUT;
10135
10136 DisposeWindow (FRAME_MAC_WINDOW (f));
10137
10138 free_frame_menubar (f);
10139 free_frame_faces (f);
10140
10141 xfree (f->output_data.mac);
10142 f->output_data.mac = 0;
10143 if (f == dpyinfo->x_focus_frame)
10144 dpyinfo->x_focus_frame = 0;
10145 if (f == dpyinfo->x_focus_event_frame)
10146 dpyinfo->x_focus_event_frame = 0;
10147 if (f == dpyinfo->x_highlight_frame)
10148 dpyinfo->x_highlight_frame = 0;
10149
10150 dpyinfo->reference_count--;
10151
10152 if (f == dpyinfo->mouse_face_mouse_frame)
10153 {
10154 dpyinfo->mouse_face_beg_row
10155 = dpyinfo->mouse_face_beg_col = -1;
10156 dpyinfo->mouse_face_end_row
10157 = dpyinfo->mouse_face_end_col = -1;
10158 dpyinfo->mouse_face_window = Qnil;
10159 dpyinfo->mouse_face_deferred_gc = 0;
10160 dpyinfo->mouse_face_mouse_frame = 0;
10161 }
10162
10163 UNBLOCK_INPUT;
10164 }
10165 \f
10166 /* Setting window manager hints. */
10167
10168 /* Set the normal size hints for the window manager, for frame F.
10169 FLAGS is the flags word to use--or 0 meaning preserve the flags
10170 that the window now has.
10171 If USER_POSITION is nonzero, we set the USPosition
10172 flag (this is useful when FLAGS is 0). */
10173 void
10174 x_wm_set_size_hint (f, flags, user_position)
10175 struct frame *f;
10176 long flags;
10177 int user_position;
10178 {
10179 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
10180 XSizeHints size_hints;
10181
10182 #ifdef USE_X_TOOLKIT
10183 Arg al[2];
10184 int ac = 0;
10185 Dimension widget_width, widget_height;
10186 Window window = XtWindow (f->output_data.x->widget);
10187 #else /* not USE_X_TOOLKIT */
10188 Window window = FRAME_X_WINDOW (f);
10189 #endif /* not USE_X_TOOLKIT */
10190
10191 /* Setting PMaxSize caused various problems. */
10192 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10193
10194 size_hints.x = f->output_data.x->left_pos;
10195 size_hints.y = f->output_data.x->top_pos;
10196
10197 #ifdef USE_X_TOOLKIT
10198 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10199 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10200 XtGetValues (f->output_data.x->widget, al, ac);
10201 size_hints.height = widget_height;
10202 size_hints.width = widget_width;
10203 #else /* not USE_X_TOOLKIT */
10204 size_hints.height = PIXEL_HEIGHT (f);
10205 size_hints.width = PIXEL_WIDTH (f);
10206 #endif /* not USE_X_TOOLKIT */
10207
10208 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10209 size_hints.height_inc = f->output_data.x->line_height;
10210 size_hints.max_width
10211 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10212 size_hints.max_height
10213 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10214
10215 /* Calculate the base and minimum sizes.
10216
10217 (When we use the X toolkit, we don't do it here.
10218 Instead we copy the values that the widgets are using, below.) */
10219 #ifndef USE_X_TOOLKIT
10220 {
10221 int base_width, base_height;
10222 int min_rows = 0, min_cols = 0;
10223
10224 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10225 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10226
10227 check_frame_size (f, &min_rows, &min_cols);
10228
10229 /* The window manager uses the base width hints to calculate the
10230 current number of rows and columns in the frame while
10231 resizing; min_width and min_height aren't useful for this
10232 purpose, since they might not give the dimensions for a
10233 zero-row, zero-column frame.
10234
10235 We use the base_width and base_height members if we have
10236 them; otherwise, we set the min_width and min_height members
10237 to the size for a zero x zero frame. */
10238
10239 #ifdef HAVE_X11R4
10240 size_hints.flags |= PBaseSize;
10241 size_hints.base_width = base_width;
10242 size_hints.base_height = base_height;
10243 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10244 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10245 #else
10246 size_hints.min_width = base_width;
10247 size_hints.min_height = base_height;
10248 #endif
10249 }
10250
10251 /* If we don't need the old flags, we don't need the old hint at all. */
10252 if (flags)
10253 {
10254 size_hints.flags |= flags;
10255 goto no_read;
10256 }
10257 #endif /* not USE_X_TOOLKIT */
10258
10259 {
10260 XSizeHints hints; /* Sometimes I hate X Windows... */
10261 long supplied_return;
10262 int value;
10263
10264 #ifdef HAVE_X11R4
10265 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10266 &supplied_return);
10267 #else
10268 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10269 #endif
10270
10271 #ifdef USE_X_TOOLKIT
10272 size_hints.base_height = hints.base_height;
10273 size_hints.base_width = hints.base_width;
10274 size_hints.min_height = hints.min_height;
10275 size_hints.min_width = hints.min_width;
10276 #endif
10277
10278 if (flags)
10279 size_hints.flags |= flags;
10280 else
10281 {
10282 if (value == 0)
10283 hints.flags = 0;
10284 if (hints.flags & PSize)
10285 size_hints.flags |= PSize;
10286 if (hints.flags & PPosition)
10287 size_hints.flags |= PPosition;
10288 if (hints.flags & USPosition)
10289 size_hints.flags |= USPosition;
10290 if (hints.flags & USSize)
10291 size_hints.flags |= USSize;
10292 }
10293 }
10294
10295 #ifndef USE_X_TOOLKIT
10296 no_read:
10297 #endif
10298
10299 #ifdef PWinGravity
10300 size_hints.win_gravity = f->output_data.x->win_gravity;
10301 size_hints.flags |= PWinGravity;
10302
10303 if (user_position)
10304 {
10305 size_hints.flags &= ~ PPosition;
10306 size_hints.flags |= USPosition;
10307 }
10308 #endif /* PWinGravity */
10309
10310 #ifdef HAVE_X11R4
10311 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10312 #else
10313 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10314 #endif
10315 #endif /* MAC_TODO */
10316 }
10317
10318 #if 0 /* MAC_TODO: hide application instead of iconify? */
10319 /* Used for IconicState or NormalState */
10320
10321 void
10322 x_wm_set_window_state (f, state)
10323 struct frame *f;
10324 int state;
10325 {
10326 #ifdef USE_X_TOOLKIT
10327 Arg al[1];
10328
10329 XtSetArg (al[0], XtNinitialState, state);
10330 XtSetValues (f->output_data.x->widget, al, 1);
10331 #else /* not USE_X_TOOLKIT */
10332 Window window = FRAME_X_WINDOW (f);
10333
10334 f->output_data.x->wm_hints.flags |= StateHint;
10335 f->output_data.x->wm_hints.initial_state = state;
10336
10337 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10338 #endif /* not USE_X_TOOLKIT */
10339 }
10340
10341 void
10342 x_wm_set_icon_pixmap (f, pixmap_id)
10343 struct frame *f;
10344 int pixmap_id;
10345 {
10346 Pixmap icon_pixmap;
10347
10348 #ifndef USE_X_TOOLKIT
10349 Window window = FRAME_X_WINDOW (f);
10350 #endif
10351
10352 if (pixmap_id > 0)
10353 {
10354 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10355 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10356 }
10357 else
10358 {
10359 /* It seems there is no way to turn off use of an icon pixmap.
10360 The following line does it, only if no icon has yet been created,
10361 for some window managers. But with mwm it crashes.
10362 Some people say it should clear the IconPixmapHint bit in this case,
10363 but that doesn't work, and the X consortium said it isn't the
10364 right thing at all. Since there is no way to win,
10365 best to explicitly give up. */
10366 #if 0
10367 f->output_data.x->wm_hints.icon_pixmap = None;
10368 #else
10369 return;
10370 #endif
10371 }
10372
10373 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10374
10375 {
10376 Arg al[1];
10377 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10378 XtSetValues (f->output_data.x->widget, al, 1);
10379 }
10380
10381 #else /* not USE_X_TOOLKIT */
10382
10383 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10384 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10385
10386 #endif /* not USE_X_TOOLKIT */
10387 }
10388
10389 #endif /* MAC_TODO */
10390
10391 void
10392 x_wm_set_icon_position (f, icon_x, icon_y)
10393 struct frame *f;
10394 int icon_x, icon_y;
10395 {
10396 #if 0 /* MAC_TODO: no icons on Mac */
10397 #ifdef USE_X_TOOLKIT
10398 Window window = XtWindow (f->output_data.x->widget);
10399 #else
10400 Window window = FRAME_X_WINDOW (f);
10401 #endif
10402
10403 f->output_data.x->wm_hints.flags |= IconPositionHint;
10404 f->output_data.x->wm_hints.icon_x = icon_x;
10405 f->output_data.x->wm_hints.icon_y = icon_y;
10406
10407 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10408 #endif /* MAC_TODO */
10409 }
10410
10411 \f
10412 /***********************************************************************
10413 Fonts
10414 ***********************************************************************/
10415
10416 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10417
10418 struct font_info *
10419 x_get_font_info (f, font_idx)
10420 FRAME_PTR f;
10421 int font_idx;
10422 {
10423 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10424 }
10425
10426 /* the global font name table */
10427 char **font_name_table = NULL;
10428 int font_name_table_size = 0;
10429 int font_name_count = 0;
10430
10431 /* compare two strings ignoring case */
10432 static int
10433 stricmp (const char *s, const char *t)
10434 {
10435 for ( ; tolower (*s) == tolower (*t); s++, t++)
10436 if (*s == '\0')
10437 return 0;
10438 return tolower (*s) - tolower (*t);
10439 }
10440
10441 /* compare two strings ignoring case and handling wildcard */
10442 static int
10443 wildstrieq (char *s1, char *s2)
10444 {
10445 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10446 return true;
10447
10448 return stricmp (s1, s2) == 0;
10449 }
10450
10451 /* Assume parameter 1 is fully qualified, no wildcards. */
10452 static int
10453 mac_font_pattern_match (fontname, pattern)
10454 char * fontname;
10455 char * pattern;
10456 {
10457 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
10458 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10459 char *ptr;
10460
10461 /* Copy fontname so we can modify it during comparison. */
10462 strcpy (font_name_copy, fontname);
10463
10464 ptr = regex;
10465 *ptr++ = '^';
10466
10467 /* Turn pattern into a regexp and do a regexp match. */
10468 for (; *pattern; pattern++)
10469 {
10470 if (*pattern == '?')
10471 *ptr++ = '.';
10472 else if (*pattern == '*')
10473 {
10474 *ptr++ = '.';
10475 *ptr++ = '*';
10476 }
10477 else
10478 *ptr++ = *pattern;
10479 }
10480 *ptr = '$';
10481 *(ptr + 1) = '\0';
10482
10483 return (fast_c_string_match_ignore_case (build_string (regex),
10484 font_name_copy) >= 0);
10485 }
10486
10487 /* Two font specs are considered to match if their foundry, family,
10488 weight, slant, and charset match. */
10489 static int
10490 mac_font_match (char *mf, char *xf)
10491 {
10492 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10493 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10494
10495 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10496 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10497 return mac_font_pattern_match (mf, xf);
10498
10499 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10500 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10501 return mac_font_pattern_match (mf, xf);
10502
10503 return (wildstrieq (m_foundry, x_foundry)
10504 && wildstrieq (m_family, x_family)
10505 && wildstrieq (m_weight, x_weight)
10506 && wildstrieq (m_slant, x_slant)
10507 && wildstrieq (m_charset, x_charset))
10508 || mac_font_pattern_match (mf, xf);
10509 }
10510
10511
10512 static char *
10513 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10514 {
10515 char foundry[32], family[32], cs[32];
10516 char xf[255], *result, *p;
10517
10518 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10519 {
10520 strcpy(foundry, "Apple");
10521 strcpy(family, name);
10522
10523 switch (scriptcode)
10524 {
10525 case smTradChinese:
10526 strcpy(cs, "big5-0");
10527 break;
10528 case smSimpChinese:
10529 strcpy(cs, "gb2312.1980-0");
10530 break;
10531 case smJapanese:
10532 strcpy(cs, "jisx0208.1983-sjis");
10533 break;
10534 case -smJapanese:
10535 /* Each Apple Japanese font is entered into the font table
10536 twice: once as a jisx0208.1983-sjis font and once as a
10537 jisx0201.1976-0 font. The latter can be used to display
10538 the ascii charset and katakana-jisx0201 charset. A
10539 negative script code signals that the name of this latter
10540 font is being built. */
10541 strcpy(cs, "jisx0201.1976-0");
10542 break;
10543 case smKorean:
10544 strcpy(cs, "ksc5601.1989-0");
10545 break;
10546 default:
10547 strcpy(cs, "mac-roman");
10548 break;
10549 }
10550 }
10551
10552 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10553 foundry, family, style & bold ? "bold" : "medium",
10554 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10555
10556 result = (char *) xmalloc (strlen (xf) + 1);
10557 strcpy (result, xf);
10558 for (p = result; *p; p++)
10559 *p = tolower(*p);
10560 return result;
10561 }
10562
10563
10564 /* Convert an X font spec to the corresponding mac font name, which
10565 can then be passed to GetFNum after conversion to a Pascal string.
10566 For ordinary Mac fonts, this should just be their names, like
10567 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10568 collection contain their charset designation in their names, like
10569 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10570 names are handled accordingly. */
10571 static void
10572 x_font_name_to_mac_font_name (char *xf, char *mf)
10573 {
10574 char foundry[32], family[32], weight[20], slant[2], cs[32];
10575
10576 strcpy (mf, "");
10577
10578 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10579 foundry, family, weight, slant, cs) != 5 &&
10580 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10581 foundry, family, weight, slant, cs) != 5)
10582 return;
10583
10584 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
10585 || strcmp (cs, "jisx0208.1983-sjis") == 0
10586 || strcmp (cs, "jisx0201.1976-0") == 0
10587 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
10588 strcpy(mf, family);
10589 else
10590 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10591 }
10592
10593
10594 static void
10595 add_font_name_table_entry (char *font_name)
10596 {
10597 if (font_name_table_size == 0)
10598 {
10599 font_name_table_size = 16;
10600 font_name_table = (char **)
10601 xmalloc (font_name_table_size * sizeof (char *));
10602 }
10603 else if (font_name_count + 1 >= font_name_table_size)
10604 {
10605 font_name_table_size += 16;
10606 font_name_table = (char **)
10607 xrealloc (font_name_table,
10608 font_name_table_size * sizeof (char *));
10609 }
10610
10611 font_name_table[font_name_count++] = font_name;
10612 }
10613
10614 /* Sets up the table font_name_table to contain the list of all fonts
10615 in the system the first time the table is used so that the Resource
10616 Manager need not be accessed every time this information is
10617 needed. */
10618
10619 static void
10620 init_font_name_table ()
10621 {
10622 #if TARGET_API_MAC_CARBON
10623 SInt32 sv;
10624
10625 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10626 {
10627 FMFontFamilyIterator ffi;
10628 FMFontFamilyInstanceIterator ffii;
10629 FMFontFamily ff;
10630
10631 /* Create a dummy instance iterator here to avoid creating and
10632 destroying it in the loop. */
10633 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10634 return;
10635 /* Create an iterator to enumerate the font families. */
10636 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10637 != noErr)
10638 {
10639 FMDisposeFontFamilyInstanceIterator (&ffii);
10640 return;
10641 }
10642
10643 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10644 {
10645 Str255 name;
10646 FMFont font;
10647 FMFontStyle style;
10648 FMFontSize size;
10649 SInt16 sc;
10650
10651 if (FMGetFontFamilyName (ff, name) != noErr)
10652 break;
10653 p2cstr (name);
10654
10655 sc = FontToScript (ff);
10656
10657 /* Point the instance iterator at the current font family. */
10658 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10659 break;
10660
10661 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10662 == noErr)
10663 if (size == 0)
10664 {
10665 add_font_name_table_entry (mac_to_x_fontname (name, size,
10666 style, sc));
10667 add_font_name_table_entry (mac_to_x_fontname (name, size,
10668 italic, sc));
10669 add_font_name_table_entry (mac_to_x_fontname (name, size,
10670 bold, sc));
10671 add_font_name_table_entry (mac_to_x_fontname (name, size,
10672 italic | bold,
10673 sc));
10674 }
10675 else
10676 {
10677 add_font_name_table_entry (mac_to_x_fontname (name, size,
10678 style, sc));
10679 if (smJapanese == sc)
10680 add_font_name_table_entry (mac_to_x_fontname (name, size,
10681 style,
10682 -smJapanese));
10683 }
10684 }
10685
10686 /* Dispose of the iterators. */
10687 FMDisposeFontFamilyIterator (&ffi);
10688 FMDisposeFontFamilyInstanceIterator (&ffii);
10689 }
10690 else
10691 {
10692 #endif /* TARGET_API_MAC_CARBON */
10693 GrafPtr port;
10694 SInt16 fontnum, old_fontnum;
10695 int num_mac_fonts = CountResources('FOND');
10696 int i, j;
10697 Handle font_handle, font_handle_2;
10698 short id, scriptcode;
10699 ResType type;
10700 Str32 name;
10701 struct FontAssoc *fat;
10702 struct AsscEntry *assc_entry;
10703
10704 GetPort (&port); /* save the current font number used */
10705 #if TARGET_API_MAC_CARBON
10706 old_fontnum = GetPortTextFont (port);
10707 #else
10708 old_fontnum = port->txFont;
10709 #endif
10710
10711 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10712 {
10713 font_handle = GetIndResource ('FOND', i);
10714 if (!font_handle)
10715 continue;
10716
10717 GetResInfo (font_handle, &id, &type, name);
10718 GetFNum (name, &fontnum);
10719 p2cstr (name);
10720 if (fontnum == 0)
10721 continue;
10722
10723 TextFont (fontnum);
10724 scriptcode = FontToScript (fontnum);
10725 do
10726 {
10727 HLock (font_handle);
10728
10729 if (GetResourceSizeOnDisk (font_handle)
10730 >= sizeof (struct FamRec))
10731 {
10732 fat = (struct FontAssoc *) (*font_handle
10733 + sizeof (struct FamRec));
10734 assc_entry
10735 = (struct AsscEntry *) (*font_handle
10736 + sizeof (struct FamRec)
10737 + sizeof (struct FontAssoc));
10738
10739 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
10740 {
10741 if (font_name_table_size == 0)
10742 {
10743 font_name_table_size = 16;
10744 font_name_table = (char **)
10745 xmalloc (font_name_table_size * sizeof (char *));
10746 }
10747 else if (font_name_count >= font_name_table_size)
10748 {
10749 font_name_table_size += 16;
10750 font_name_table = (char **)
10751 xrealloc (font_name_table,
10752 font_name_table_size * sizeof (char *));
10753 }
10754 font_name_table[font_name_count++]
10755 = mac_to_x_fontname (name,
10756 assc_entry->fontSize,
10757 assc_entry->fontStyle,
10758 scriptcode);
10759 /* Both jisx0208.1983-sjis and
10760 jisx0201.1976-sjis parts are contained in
10761 Apple Japanese (SJIS) font. */
10762 if (smJapanese == scriptcode)
10763 {
10764 font_name_table[font_name_count++]
10765 = mac_to_x_fontname (name,
10766 assc_entry->fontSize,
10767 assc_entry->fontStyle,
10768 -smJapanese);
10769 }
10770 }
10771 }
10772
10773 HUnlock (font_handle);
10774 font_handle_2 = GetNextFOND (font_handle);
10775 ReleaseResource (font_handle);
10776 font_handle = font_handle_2;
10777 }
10778 while (ResError () == noErr && font_handle);
10779 }
10780
10781 TextFont (old_fontnum);
10782 #if TARGET_API_MAC_CARBON
10783 }
10784 #endif /* TARGET_API_MAC_CARBON */
10785 }
10786
10787
10788 /* Return a list of at most MAXNAMES font specs matching the one in
10789 PATTERN. Cache matching fonts for patterns in
10790 dpyinfo->name_list_element to avoid looking them up again by
10791 calling mac_font_pattern_match (slow). */
10792
10793 Lisp_Object
10794 x_list_fonts (struct frame *f,
10795 Lisp_Object pattern,
10796 int size,
10797 int maxnames)
10798 {
10799 char *ptnstr;
10800 Lisp_Object newlist = Qnil, tem, key;
10801 int n_fonts = 0;
10802 int i;
10803 struct gcpro gcpro1, gcpro2;
10804 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
10805
10806 if (font_name_table == NULL) /* Initialize when first used. */
10807 init_font_name_table ();
10808
10809 if (dpyinfo)
10810 {
10811 tem = XCDR (dpyinfo->name_list_element);
10812 key = Fcons (pattern, make_number (maxnames));
10813
10814 newlist = Fassoc (key, tem);
10815 if (!NILP (newlist))
10816 {
10817 newlist = Fcdr_safe (newlist);
10818 goto label_cached;
10819 }
10820 }
10821
10822 ptnstr = SDATA (pattern);
10823
10824 GCPRO2 (pattern, newlist);
10825
10826 /* Scan and matching bitmap fonts. */
10827 for (i = 0; i < font_name_count; i++)
10828 {
10829 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10830 {
10831 newlist = Fcons (build_string (font_name_table[i]), newlist);
10832
10833 n_fonts++;
10834 if (n_fonts >= maxnames)
10835 break;
10836 }
10837 }
10838
10839 /* MAC_TODO: add code for matching outline fonts here */
10840
10841 UNGCPRO;
10842
10843 if (dpyinfo)
10844 {
10845 XSETCDR (dpyinfo->name_list_element,
10846 Fcons (Fcons (key, newlist),
10847 XCDR (dpyinfo->name_list_element)));
10848 }
10849 label_cached:
10850
10851 return newlist;
10852 }
10853
10854
10855 #if GLYPH_DEBUG
10856
10857 /* Check that FONT is valid on frame F. It is if it can be found in F's
10858 font table. */
10859
10860 static void
10861 x_check_font (f, font)
10862 struct frame *f;
10863 XFontStruct *font;
10864 {
10865 int i;
10866 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10867
10868 xassert (font != NULL);
10869
10870 for (i = 0; i < dpyinfo->n_fonts; i++)
10871 if (dpyinfo->font_table[i].name
10872 && font == dpyinfo->font_table[i].font)
10873 break;
10874
10875 xassert (i < dpyinfo->n_fonts);
10876 }
10877
10878 #endif /* GLYPH_DEBUG != 0 */
10879
10880 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10881 Note: There are (broken) X fonts out there with invalid XFontStruct
10882 min_bounds contents. For example, handa@etl.go.jp reports that
10883 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10884 have font->min_bounds.width == 0. */
10885
10886 static INLINE void
10887 x_font_min_bounds (font, w, h)
10888 MacFontStruct *font;
10889 int *w, *h;
10890 {
10891 /*
10892 * TODO: Windows does not appear to offer min bound, only
10893 * average and maximum width, and maximum height.
10894 */
10895 *h = FONT_HEIGHT (font);
10896 *w = FONT_WIDTH (font);
10897 }
10898
10899
10900 /* Compute the smallest character width and smallest font height over
10901 all fonts available on frame F. Set the members smallest_char_width
10902 and smallest_font_height in F's x_display_info structure to
10903 the values computed. Value is non-zero if smallest_font_height or
10904 smallest_char_width become smaller than they were before. */
10905
10906 int
10907 x_compute_min_glyph_bounds (f)
10908 struct frame *f;
10909 {
10910 int i;
10911 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10912 MacFontStruct *font;
10913 int old_width = dpyinfo->smallest_char_width;
10914 int old_height = dpyinfo->smallest_font_height;
10915
10916 dpyinfo->smallest_font_height = 100000;
10917 dpyinfo->smallest_char_width = 100000;
10918
10919 for (i = 0; i < dpyinfo->n_fonts; ++i)
10920 if (dpyinfo->font_table[i].name)
10921 {
10922 struct font_info *fontp = dpyinfo->font_table + i;
10923 int w, h;
10924
10925 font = (MacFontStruct *) fontp->font;
10926 xassert (font != (MacFontStruct *) ~0);
10927 x_font_min_bounds (font, &w, &h);
10928
10929 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10930 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10931 }
10932
10933 xassert (dpyinfo->smallest_char_width > 0
10934 && dpyinfo->smallest_font_height > 0);
10935
10936 return (dpyinfo->n_fonts == 1
10937 || dpyinfo->smallest_char_width < old_width
10938 || dpyinfo->smallest_font_height < old_height);
10939 }
10940
10941
10942 /* Determine whether given string is a fully-specified XLFD: all 14
10943 fields are present, none is '*'. */
10944
10945 static int
10946 is_fully_specified_xlfd (char *p)
10947 {
10948 int i;
10949 char *q;
10950
10951 if (*p != '-')
10952 return 0;
10953
10954 for (i = 0; i < 13; i++)
10955 {
10956 q = strchr (p + 1, '-');
10957 if (q == NULL)
10958 return 0;
10959 if (q - p == 2 && *(p + 1) == '*')
10960 return 0;
10961 p = q;
10962 }
10963
10964 if (strchr (p + 1, '-') != NULL)
10965 return 0;
10966
10967 if (*(p + 1) == '*' && *(p + 2) == '\0')
10968 return 0;
10969
10970 return 1;
10971 }
10972
10973
10974 const int kDefaultFontSize = 9;
10975
10976
10977 /* XLoadQueryFont creates and returns an internal representation for a
10978 font in a MacFontStruct struct. There is really no concept
10979 corresponding to "loading" a font on the Mac. But we check its
10980 existence and find the font number and all other information for it
10981 and store them in the returned MacFontStruct. */
10982
10983 static MacFontStruct *
10984 XLoadQueryFont (Display *dpy, char *fontname)
10985 {
10986 int i, size, is_two_byte_font, char_width;
10987 char *name;
10988 GrafPtr port;
10989 SInt16 old_fontnum, old_fontsize;
10990 Style old_fontface;
10991 Str32 mfontname;
10992 SInt16 fontnum;
10993 Style fontface = normal;
10994 MacFontStruct *font;
10995 FontInfo the_fontinfo;
10996 char s_weight[7], c_slant;
10997
10998 if (is_fully_specified_xlfd (fontname))
10999 name = fontname;
11000 else
11001 {
11002 for (i = 0; i < font_name_count; i++)
11003 if (mac_font_pattern_match (font_name_table[i], fontname))
11004 break;
11005
11006 if (i >= font_name_count)
11007 return NULL;
11008
11009 name = font_name_table[i];
11010 }
11011
11012 GetPort (&port); /* save the current font number used */
11013 #if TARGET_API_MAC_CARBON
11014 old_fontnum = GetPortTextFont (port);
11015 old_fontsize = GetPortTextSize (port);
11016 old_fontface = GetPortTextFace (port);
11017 #else
11018 old_fontnum = port->txFont;
11019 old_fontsize = port->txSize;
11020 old_fontface = port->txFace;
11021 #endif
11022
11023 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11024 size = kDefaultFontSize;
11025
11026 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11027 if (strcmp (s_weight, "bold") == 0)
11028 fontface |= bold;
11029
11030 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11031 if (c_slant == 'i')
11032 fontface |= italic;
11033
11034 x_font_name_to_mac_font_name (name, mfontname);
11035 c2pstr (mfontname);
11036 GetFNum (mfontname, &fontnum);
11037 if (fontnum == 0)
11038 return NULL;
11039
11040 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
11041
11042 font->fontname = (char *) xmalloc (strlen (name) + 1);
11043 bcopy (name, font->fontname, strlen (name) + 1);
11044
11045 font->mac_fontnum = fontnum;
11046 font->mac_fontsize = size;
11047 font->mac_fontface = fontface;
11048 font->mac_scriptcode = FontToScript (fontnum);
11049
11050 /* Apple Japanese (SJIS) font is listed as both
11051 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
11052 (Roman script) in init_font_name_table (). The latter should be
11053 treated as a one-byte font. */
11054 {
11055 char cs[32];
11056
11057 if (sscanf (name,
11058 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11059 cs) == 1
11060 && 0 == strcmp (cs, "jisx0201.1976-0"))
11061 font->mac_scriptcode = smRoman;
11062 }
11063
11064 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11065 font->mac_scriptcode == smTradChinese ||
11066 font->mac_scriptcode == smSimpChinese ||
11067 font->mac_scriptcode == smKorean;
11068
11069 TextFont (fontnum);
11070 TextSize (size);
11071 TextFace (fontface);
11072
11073 GetFontInfo (&the_fontinfo);
11074
11075 font->ascent = the_fontinfo.ascent;
11076 font->descent = the_fontinfo.descent;
11077
11078 font->min_byte1 = 0;
11079 if (is_two_byte_font)
11080 font->max_byte1 = 1;
11081 else
11082 font->max_byte1 = 0;
11083 font->min_char_or_byte2 = 0x20;
11084 font->max_char_or_byte2 = 0xff;
11085
11086 if (is_two_byte_font)
11087 {
11088 /* Use the width of an "ideographic space" of that font because
11089 the_fontinfo.widMax returns the wrong width for some fonts. */
11090 switch (font->mac_scriptcode)
11091 {
11092 case smJapanese:
11093 char_width = StringWidth("\p\x81\x40");
11094 break;
11095 case smTradChinese:
11096 char_width = StringWidth("\p\xa1\x40");
11097 break;
11098 case smSimpChinese:
11099 char_width = StringWidth("\p\xa1\xa1");
11100 break;
11101 case smKorean:
11102 char_width = StringWidth("\p\xa1\xa1");
11103 break;
11104 }
11105 }
11106 else
11107 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11108 returns 15 for 12-point Monaco! */
11109 char_width = CharWidth ('m');
11110
11111 font->max_bounds.rbearing = char_width;
11112 font->max_bounds.lbearing = 0;
11113 font->max_bounds.width = char_width;
11114 font->max_bounds.ascent = the_fontinfo.ascent;
11115 font->max_bounds.descent = the_fontinfo.descent;
11116
11117 font->min_bounds = font->max_bounds;
11118
11119 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11120 font->per_char = NULL;
11121 else
11122 {
11123 font->per_char = (XCharStruct *)
11124 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11125 {
11126 int c;
11127
11128 for (c = 0x20; c <= 0xff; c++)
11129 {
11130 font->per_char[c - 0x20] = font->max_bounds;
11131 font->per_char[c - 0x20].width = CharWidth (c);
11132 }
11133 }
11134 }
11135
11136 TextFont (old_fontnum); /* restore previous font number, size and face */
11137 TextSize (old_fontsize);
11138 TextFace (old_fontface);
11139
11140 return font;
11141 }
11142
11143
11144 /* Load font named FONTNAME of the size SIZE for frame F, and return a
11145 pointer to the structure font_info while allocating it dynamically.
11146 If SIZE is 0, load any size of font.
11147 If loading is failed, return NULL. */
11148
11149 struct font_info *
11150 x_load_font (f, fontname, size)
11151 struct frame *f;
11152 register char *fontname;
11153 int size;
11154 {
11155 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11156 Lisp_Object font_names;
11157
11158 /* Get a list of all the fonts that match this name. Once we
11159 have a list of matching fonts, we compare them against the fonts
11160 we already have by comparing names. */
11161 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11162
11163 if (!NILP (font_names))
11164 {
11165 Lisp_Object tail;
11166 int i;
11167
11168 for (i = 0; i < dpyinfo->n_fonts; i++)
11169 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11170 if (dpyinfo->font_table[i].name
11171 && (!strcmp (dpyinfo->font_table[i].name,
11172 SDATA (XCAR (tail)))
11173 || !strcmp (dpyinfo->font_table[i].full_name,
11174 SDATA (XCAR (tail)))))
11175 return (dpyinfo->font_table + i);
11176 }
11177
11178 /* Load the font and add it to the table. */
11179 {
11180 char *full_name;
11181 struct MacFontStruct *font;
11182 struct font_info *fontp;
11183 unsigned long value;
11184 int i;
11185
11186 /* If we have found fonts by x_list_font, load one of them. If
11187 not, we still try to load a font by the name given as FONTNAME
11188 because XListFonts (called in x_list_font) of some X server has
11189 a bug of not finding a font even if the font surely exists and
11190 is loadable by XLoadQueryFont. */
11191 if (size > 0 && !NILP (font_names))
11192 fontname = (char *) SDATA (XCAR (font_names));
11193
11194 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11195 if (!font)
11196 return NULL;
11197
11198 /* Find a free slot in the font table. */
11199 for (i = 0; i < dpyinfo->n_fonts; ++i)
11200 if (dpyinfo->font_table[i].name == NULL)
11201 break;
11202
11203 /* If no free slot found, maybe enlarge the font table. */
11204 if (i == dpyinfo->n_fonts
11205 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11206 {
11207 int sz;
11208 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11209 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11210 dpyinfo->font_table
11211 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11212 }
11213
11214 fontp = dpyinfo->font_table + i;
11215 if (i == dpyinfo->n_fonts)
11216 ++dpyinfo->n_fonts;
11217
11218 /* Now fill in the slots of *FONTP. */
11219 BLOCK_INPUT;
11220 fontp->font = font;
11221 fontp->font_idx = i;
11222 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11223 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11224
11225 fontp->full_name = fontp->name;
11226
11227 fontp->size = font->max_bounds.width;
11228 fontp->height = FONT_HEIGHT (font);
11229 {
11230 /* For some font, ascent and descent in max_bounds field is
11231 larger than the above value. */
11232 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11233 if (max_height > fontp->height)
11234 fontp->height = max_height;
11235 }
11236
11237 /* The slot `encoding' specifies how to map a character
11238 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11239 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11240 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11241 2:0xA020..0xFF7F). For the moment, we don't know which charset
11242 uses this font. So, we set information in fontp->encoding[1]
11243 which is never used by any charset. If mapping can't be
11244 decided, set FONT_ENCODING_NOT_DECIDED. */
11245 if (font->mac_scriptcode == smJapanese)
11246 fontp->encoding[1] = 4;
11247 else
11248 {
11249 fontp->encoding[1]
11250 = (font->max_byte1 == 0
11251 /* 1-byte font */
11252 ? (font->min_char_or_byte2 < 0x80
11253 ? (font->max_char_or_byte2 < 0x80
11254 ? 0 /* 0x20..0x7F */
11255 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11256 : 1) /* 0xA0..0xFF */
11257 /* 2-byte font */
11258 : (font->min_byte1 < 0x80
11259 ? (font->max_byte1 < 0x80
11260 ? (font->min_char_or_byte2 < 0x80
11261 ? (font->max_char_or_byte2 < 0x80
11262 ? 0 /* 0x2020..0x7F7F */
11263 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11264 : 3) /* 0x20A0..0x7FFF */
11265 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11266 : (font->min_char_or_byte2 < 0x80
11267 ? (font->max_char_or_byte2 < 0x80
11268 ? 2 /* 0xA020..0xFF7F */
11269 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11270 : 1))); /* 0xA0A0..0xFFFF */
11271 }
11272
11273 #if 0 /* MAC_TODO: fill these out with more reasonably values */
11274 fontp->baseline_offset
11275 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11276 ? (long) value : 0);
11277 fontp->relative_compose
11278 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11279 ? (long) value : 0);
11280 fontp->default_ascent
11281 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11282 ? (long) value : 0);
11283 #else
11284 fontp->baseline_offset = 0;
11285 fontp->relative_compose = 0;
11286 fontp->default_ascent = 0;
11287 #endif
11288
11289 /* Set global flag fonts_changed_p to non-zero if the font loaded
11290 has a character with a smaller width than any other character
11291 before, or if the font loaded has a smalle>r height than any
11292 other font loaded before. If this happens, it will make a
11293 glyph matrix reallocation necessary. */
11294 fonts_changed_p = x_compute_min_glyph_bounds (f);
11295 UNBLOCK_INPUT;
11296 return fontp;
11297 }
11298 }
11299
11300
11301 /* Return a pointer to struct font_info of a font named FONTNAME for
11302 frame F. If no such font is loaded, return NULL. */
11303
11304 struct font_info *
11305 x_query_font (f, fontname)
11306 struct frame *f;
11307 register char *fontname;
11308 {
11309 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11310 int i;
11311
11312 for (i = 0; i < dpyinfo->n_fonts; i++)
11313 if (dpyinfo->font_table[i].name
11314 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11315 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11316 return (dpyinfo->font_table + i);
11317 return NULL;
11318 }
11319
11320
11321 /* Find a CCL program for a font specified by FONTP, and set the member
11322 `encoder' of the structure. */
11323
11324 void
11325 x_find_ccl_program (fontp)
11326 struct font_info *fontp;
11327 {
11328 Lisp_Object list, elt;
11329
11330 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11331 {
11332 elt = XCAR (list);
11333 if (CONSP (elt)
11334 && STRINGP (XCAR (elt))
11335 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11336 >= 0))
11337 break;
11338 }
11339 if (! NILP (list))
11340 {
11341 struct ccl_program *ccl
11342 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11343
11344 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11345 xfree (ccl);
11346 else
11347 fontp->font_encoder = ccl;
11348 }
11349 }
11350
11351
11352 \f
11353 /***********************************************************************
11354 Initialization
11355 ***********************************************************************/
11356
11357 #ifdef USE_X_TOOLKIT
11358 static XrmOptionDescRec emacs_options[] = {
11359 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11360 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11361
11362 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11363 XrmoptionSepArg, NULL},
11364 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11365
11366 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11367 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11368 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11369 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11370 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11371 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11372 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11373 };
11374 #endif /* USE_X_TOOLKIT */
11375
11376 static int x_initialized;
11377
11378 #ifdef MULTI_KBOARD
11379 /* Test whether two display-name strings agree up to the dot that separates
11380 the screen number from the server number. */
11381 static int
11382 same_x_server (name1, name2)
11383 char *name1, *name2;
11384 {
11385 int seen_colon = 0;
11386 unsigned char *system_name = SDATA (Vsystem_name);
11387 int system_name_length = strlen (system_name);
11388 int length_until_period = 0;
11389
11390 while (system_name[length_until_period] != 0
11391 && system_name[length_until_period] != '.')
11392 length_until_period++;
11393
11394 /* Treat `unix' like an empty host name. */
11395 if (! strncmp (name1, "unix:", 5))
11396 name1 += 4;
11397 if (! strncmp (name2, "unix:", 5))
11398 name2 += 4;
11399 /* Treat this host's name like an empty host name. */
11400 if (! strncmp (name1, system_name, system_name_length)
11401 && name1[system_name_length] == ':')
11402 name1 += system_name_length;
11403 if (! strncmp (name2, system_name, system_name_length)
11404 && name2[system_name_length] == ':')
11405 name2 += system_name_length;
11406 /* Treat this host's domainless name like an empty host name. */
11407 if (! strncmp (name1, system_name, length_until_period)
11408 && name1[length_until_period] == ':')
11409 name1 += length_until_period;
11410 if (! strncmp (name2, system_name, length_until_period)
11411 && name2[length_until_period] == ':')
11412 name2 += length_until_period;
11413
11414 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11415 {
11416 if (*name1 == ':')
11417 seen_colon++;
11418 if (seen_colon && *name1 == '.')
11419 return 1;
11420 }
11421 return (seen_colon
11422 && (*name1 == '.' || *name1 == '\0')
11423 && (*name2 == '.' || *name2 == '\0'));
11424 }
11425 #endif
11426
11427
11428 /* The Mac Event loop code */
11429
11430 #ifndef MAC_OSX
11431 #include <Events.h>
11432 #include <Quickdraw.h>
11433 #include <Balloons.h>
11434 #include <Devices.h>
11435 #include <Fonts.h>
11436 #include <Gestalt.h>
11437 #include <Menus.h>
11438 #include <Processes.h>
11439 #include <Sound.h>
11440 #include <ToolUtils.h>
11441 #include <TextUtils.h>
11442 #include <Dialogs.h>
11443 #include <Script.h>
11444 #include <Types.h>
11445 #include <TextEncodingConverter.h>
11446 #include <Resources.h>
11447
11448 #if __MWERKS__
11449 #include <unix.h>
11450 #endif
11451 #endif /* ! MAC_OSX */
11452
11453 #define M_APPLE 128
11454 #define I_ABOUT 1
11455
11456 #define WINDOW_RESOURCE 128
11457 #define TERM_WINDOW_RESOURCE 129
11458
11459 #define DEFAULT_NUM_COLS 80
11460
11461 #define MIN_DOC_SIZE 64
11462 #define MAX_DOC_SIZE 32767
11463
11464 /* sleep time for WaitNextEvent */
11465 #define WNE_SLEEP_AT_SUSPEND 10
11466 #define WNE_SLEEP_AT_RESUME 1
11467
11468 /* true when cannot handle any Mac OS events */
11469 static int handling_window_update = 0;
11470
11471 /* the flag appl_is_suspended is used both for determining the sleep
11472 time to be passed to WaitNextEvent and whether the cursor should be
11473 drawn when updating the display. The cursor is turned off when
11474 Emacs is suspended. Redrawing it is unnecessary and what needs to
11475 be done depends on whether the cursor lies inside or outside the
11476 redraw region. So we might as well skip drawing it when Emacs is
11477 suspended. */
11478 static Boolean app_is_suspended = false;
11479 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11480
11481 #define EXTRA_STACK_ALLOC (256 * 1024)
11482
11483 #define ARGV_STRING_LIST_ID 129
11484 #define ABOUT_ALERT_ID 128
11485 #define RAM_TOO_LARGE_ALERT_ID 129
11486
11487 Boolean terminate_flag = false;
11488
11489 /* True if using command key as meta key. */
11490 Lisp_Object Vmac_command_key_is_meta;
11491
11492 /* True if the ctrl and meta keys should be reversed. */
11493 Lisp_Object Vmac_reverse_ctrl_meta;
11494
11495 #if USE_CARBON_EVENTS
11496 /* True if the mouse wheel button (i.e. button 4) should map to
11497 mouse-2, instead of mouse-3. */
11498 Lisp_Object Vmac_wheel_button_is_mouse_2;
11499 #endif
11500
11501 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11502 to this text encoding */
11503 int mac_keyboard_text_encoding;
11504 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11505
11506 /* Set in term/mac-win.el to indicate that event loop can now generate
11507 drag and drop events. */
11508 Lisp_Object Qmac_ready_for_drag_n_drop;
11509
11510 Lisp_Object drag_and_drop_file_list;
11511
11512 Point saved_menu_event_location;
11513
11514 /* Apple Events */
11515 static void init_required_apple_events (void);
11516 static pascal OSErr
11517 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
11518 static pascal OSErr
11519 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
11520 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
11521 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
11522
11523 /* Drag and Drop */
11524 static OSErr init_mac_drag_n_drop ();
11525 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
11526
11527 #if USE_CARBON_EVENTS
11528 /* Preliminary Support for the OSX Services Menu */
11529 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
11530 static void init_service_handler ();
11531 #endif
11532
11533 extern void init_emacs_passwd_dir ();
11534 extern int emacs_main (int, char **, char **);
11535 extern void check_alarm ();
11536
11537 extern void initialize_applescript();
11538 extern void terminate_applescript();
11539
11540 static unsigned int
11541 #if USE_CARBON_EVENTS
11542 mac_to_emacs_modifiers (UInt32 mods)
11543 #else
11544 mac_to_emacs_modifiers (EventModifiers mods)
11545 #endif
11546 {
11547 unsigned int result = 0;
11548 if (mods & macShiftKey)
11549 result |= shift_modifier;
11550 if (mods & macCtrlKey)
11551 result |= ctrl_modifier;
11552 if (mods & macMetaKey)
11553 result |= meta_modifier;
11554 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
11555 result |= alt_modifier;
11556 return result;
11557 }
11558
11559 #if USE_CARBON_EVENTS
11560 /* Obtains the event modifiers from the event ref and then calls
11561 mac_to_emacs_modifiers. */
11562 static int
11563 mac_event_to_emacs_modifiers (EventRef eventRef)
11564 {
11565 UInt32 mods = 0;
11566 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
11567 sizeof (UInt32), NULL, &mods);
11568 return mac_to_emacs_modifiers (mods);
11569 }
11570
11571 /* Given an event ref, return the code to use for the mouse button
11572 code in the emacs input_event. */
11573 static int
11574 mac_get_mouse_btn (EventRef ref)
11575 {
11576 EventMouseButton result = kEventMouseButtonPrimary;
11577 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
11578 sizeof (EventMouseButton), NULL, &result);
11579 switch (result)
11580 {
11581 case kEventMouseButtonPrimary:
11582 return 0;
11583 case kEventMouseButtonSecondary:
11584 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
11585 case kEventMouseButtonTertiary:
11586 case 4: /* 4 is the number for the mouse wheel button */
11587 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
11588 default:
11589 return 0;
11590 }
11591 }
11592
11593 /* Normally, ConvertEventRefToEventRecord will correctly handle all
11594 events. However the click of the mouse wheel is not converted to a
11595 mouseDown or mouseUp event. This calls ConvertEventRef, but then
11596 checks to see if it is a mouse up or down carbon event that has not
11597 been converted, and if so, converts it by hand (to be picked up in
11598 the XTread_socket loop). */
11599 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
11600 {
11601 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
11602 /* Do special case for mouse wheel button. */
11603 if (!result && GetEventClass (eventRef) == kEventClassMouse)
11604 {
11605 UInt32 kind = GetEventKind (eventRef);
11606 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
11607 {
11608 eventRec->what = mouseDown;
11609 result=1;
11610 }
11611 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
11612 {
11613 eventRec->what = mouseUp;
11614 result=1;
11615 }
11616 if (result)
11617 {
11618 /* Need where and when. */
11619 UInt32 mods;
11620 GetEventParameter (eventRef, kEventParamMouseLocation,
11621 typeQDPoint, NULL, sizeof (Point),
11622 NULL, &eventRec->where);
11623 /* Use two step process because new event modifiers are
11624 32-bit and old are 16-bit. Currently, only loss is
11625 NumLock & Fn. */
11626 GetEventParameter (eventRef, kEventParamKeyModifiers,
11627 typeUInt32, NULL, sizeof (UInt32),
11628 NULL, &mods);
11629 eventRec->modifiers = mods;
11630
11631 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
11632 }
11633 }
11634 return result;
11635 }
11636
11637 #endif
11638
11639 static void
11640 do_get_menus (void)
11641 {
11642 Handle menubar_handle;
11643 MenuHandle menu_handle;
11644
11645 menubar_handle = GetNewMBar (128);
11646 if(menubar_handle == NULL)
11647 abort ();
11648 SetMenuBar (menubar_handle);
11649 DrawMenuBar ();
11650
11651 menu_handle = GetMenuHandle (M_APPLE);
11652 if(menu_handle != NULL)
11653 AppendResMenu (menu_handle,'DRVR');
11654 else
11655 abort ();
11656 }
11657
11658
11659 static void
11660 do_init_managers (void)
11661 {
11662 #if !TARGET_API_MAC_CARBON
11663 InitGraf (&qd.thePort);
11664 InitFonts ();
11665 FlushEvents (everyEvent, 0);
11666 InitWindows ();
11667 InitMenus ();
11668 TEInit ();
11669 InitDialogs (NULL);
11670 #endif /* !TARGET_API_MAC_CARBON */
11671 InitCursor ();
11672
11673 #if !TARGET_API_MAC_CARBON
11674 /* set up some extra stack space for use by emacs */
11675 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11676
11677 /* MaxApplZone must be called for AppleScript to execute more
11678 complicated scripts */
11679 MaxApplZone ();
11680 MoreMasters ();
11681 #endif /* !TARGET_API_MAC_CARBON */
11682 }
11683
11684 static void
11685 do_check_ram_size (void)
11686 {
11687 SInt32 physical_ram_size, logical_ram_size;
11688
11689 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11690 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11691 || physical_ram_size > 256 * 1024 * 1024
11692 || logical_ram_size > 256 * 1024 * 1024)
11693 {
11694 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11695 exit (1);
11696 }
11697 }
11698
11699 static void
11700 do_window_update (WindowPtr win)
11701 {
11702 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11703 struct frame *f = mwp->mFP;
11704
11705 if (f)
11706 {
11707 if (f->async_visible == 0)
11708 {
11709 f->async_visible = 1;
11710 f->async_iconified = 0;
11711 SET_FRAME_GARBAGED (f);
11712
11713 /* An update event is equivalent to MapNotify on X, so report
11714 visibility changes properly. */
11715 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11716 /* Force a redisplay sooner or later to update the
11717 frame titles in case this is the second frame. */
11718 record_asynch_buffer_change ();
11719 }
11720 else
11721 {
11722 BeginUpdate (win);
11723 handling_window_update = 1;
11724
11725 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
11726
11727 expose_frame (f, 0, 0, 0, 0);
11728
11729 handling_window_update = 0;
11730 EndUpdate (win);
11731 }
11732 }
11733 }
11734
11735 static int
11736 is_emacs_window (WindowPtr win)
11737 {
11738 Lisp_Object tail, frame;
11739
11740 if (!win)
11741 return 0;
11742
11743 FOR_EACH_FRAME (tail, frame)
11744 if (FRAME_MAC_P (XFRAME (frame)))
11745 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11746 return 1;
11747
11748 return 0;
11749 }
11750
11751 static void
11752 do_window_activate (WindowPtr win)
11753 {
11754 mac_output *mwp;
11755 struct frame *f;
11756
11757 if (is_emacs_window (win))
11758 {
11759 mwp = (mac_output *) GetWRefCon (win);
11760 f = mwp->mFP;
11761
11762 if (f)
11763 {
11764 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11765 activate_scroll_bars (f);
11766 }
11767 }
11768 }
11769
11770 static void
11771 do_window_deactivate (WindowPtr win)
11772 {
11773 mac_output *mwp;
11774 struct frame *f;
11775
11776 if (is_emacs_window (win))
11777 {
11778 mwp = (mac_output *) GetWRefCon (win);
11779 f = mwp->mFP;
11780
11781 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11782 {
11783 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11784 deactivate_scroll_bars (f);
11785 }
11786 }
11787 }
11788
11789 static void
11790 do_app_resume ()
11791 {
11792 WindowPtr wp;
11793 mac_output *mwp;
11794 struct frame *f;
11795
11796 wp = FrontWindow();
11797 if (is_emacs_window (wp))
11798 {
11799 mwp = (mac_output *) GetWRefCon (wp);
11800 f = mwp->mFP;
11801
11802 if (f)
11803 {
11804 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11805 activate_scroll_bars (f);
11806 }
11807 }
11808
11809 app_is_suspended = false;
11810 app_sleep_time = WNE_SLEEP_AT_RESUME;
11811 }
11812
11813 static void
11814 do_app_suspend ()
11815 {
11816 WindowPtr wp;
11817 mac_output *mwp;
11818 struct frame *f;
11819
11820 wp = FrontWindow();
11821 if (is_emacs_window (wp))
11822 {
11823 mwp = (mac_output *) GetWRefCon (wp);
11824 f = mwp->mFP;
11825
11826 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11827 {
11828 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11829 deactivate_scroll_bars (f);
11830 }
11831 }
11832
11833 app_is_suspended = true;
11834 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11835 }
11836
11837
11838 static void
11839 do_mouse_moved (Point mouse_pos)
11840 {
11841 WindowPtr wp = FrontWindow ();
11842 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11843
11844 #if TARGET_API_MAC_CARBON
11845 SetPort (GetWindowPort (wp));
11846 #else
11847 SetPort (wp);
11848 #endif
11849
11850 GlobalToLocal (&mouse_pos);
11851
11852 note_mouse_movement (f, &mouse_pos);
11853 }
11854
11855
11856 static void
11857 do_os_event (EventRecord *erp)
11858 {
11859 switch((erp->message >> 24) & 0x000000FF)
11860 {
11861 case suspendResumeMessage:
11862 if((erp->message & resumeFlag) == 1)
11863 do_app_resume ();
11864 else
11865 do_app_suspend ();
11866 break;
11867
11868 case mouseMovedMessage:
11869 do_mouse_moved (erp->where);
11870 break;
11871 }
11872 }
11873
11874 static void
11875 do_events (EventRecord *erp)
11876 {
11877 switch (erp->what)
11878 {
11879 case updateEvt:
11880 do_window_update ((WindowPtr) erp->message);
11881 break;
11882
11883 case osEvt:
11884 do_os_event (erp);
11885 break;
11886
11887 case activateEvt:
11888 if ((erp->modifiers & activeFlag) != 0)
11889 do_window_activate ((WindowPtr) erp->message);
11890 else
11891 do_window_deactivate ((WindowPtr) erp->message);
11892 break;
11893 }
11894 }
11895
11896 static void
11897 do_apple_menu (SInt16 menu_item)
11898 {
11899 #if !TARGET_API_MAC_CARBON
11900 Str255 item_name;
11901 SInt16 da_driver_refnum;
11902
11903 if (menu_item == I_ABOUT)
11904 NoteAlert (ABOUT_ALERT_ID, NULL);
11905 else
11906 {
11907 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11908 da_driver_refnum = OpenDeskAcc (item_name);
11909 }
11910 #endif /* !TARGET_API_MAC_CARBON */
11911 }
11912
11913 void
11914 do_menu_choice (SInt32 menu_choice)
11915 {
11916 SInt16 menu_id, menu_item;
11917
11918 menu_id = HiWord (menu_choice);
11919 menu_item = LoWord (menu_choice);
11920
11921 if (menu_id == 0)
11922 return;
11923
11924 switch (menu_id)
11925 {
11926 case M_APPLE:
11927 do_apple_menu (menu_item);
11928 break;
11929
11930 default:
11931 {
11932 WindowPtr wp = FrontWindow ();
11933 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11934 MenuHandle menu = GetMenuHandle (menu_id);
11935 if (menu)
11936 {
11937 UInt32 refcon;
11938
11939 GetMenuItemRefCon (menu, menu_item, &refcon);
11940 menubar_selection_callback (f, refcon);
11941 }
11942 }
11943 }
11944
11945 HiliteMenu (0);
11946 }
11947
11948
11949 /* Handle drags in size box. Based on code contributed by Ben
11950 Mesander and IM - Window Manager A. */
11951
11952 static void
11953 do_grow_window (WindowPtr w, EventRecord *e)
11954 {
11955 long grow_size;
11956 Rect limit_rect;
11957 int rows, columns;
11958 mac_output *mwp = (mac_output *) GetWRefCon (w);
11959 struct frame *f = mwp->mFP;
11960
11961 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11962
11963 grow_size = GrowWindow (w, e->where, &limit_rect);
11964
11965 /* see if it really changed size */
11966 if (grow_size != 0)
11967 {
11968 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11969 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11970
11971 x_set_window_size (f, 0, columns, rows);
11972 }
11973 }
11974
11975
11976 /* Handle clicks in zoom box. Calculation of "standard state" based
11977 on code in IM - Window Manager A and code contributed by Ben
11978 Mesander. The standard state of an Emacs window is 80-characters
11979 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11980
11981 static void
11982 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11983 {
11984 GrafPtr save_port;
11985 Rect zoom_rect, port_rect;
11986 Point top_left;
11987 int w_title_height, columns, rows, width, height, dummy, x, y;
11988 mac_output *mwp = (mac_output *) GetWRefCon (w);
11989 struct frame *f = mwp->mFP;
11990
11991 GetPort (&save_port);
11992
11993 #if TARGET_API_MAC_CARBON
11994 SetPort (GetWindowPort (w));
11995 #else
11996 SetPort (w);
11997 #endif
11998
11999 /* Clear window to avoid flicker. */
12000 #if TARGET_API_MAC_CARBON
12001 {
12002 Rect r;
12003 BitMap bm;
12004
12005 GetWindowPortBounds (w, &r);
12006 EraseRect (&r);
12007
12008 if (zoom_in_or_out == inZoomOut)
12009 {
12010 /* calculate height of window's title bar (hard card it for now). */
12011 w_title_height = 20 + GetMBarHeight ();
12012
12013 /* get maximum height of window into zoom_rect.bottom -
12014 zoom_rect.top */
12015 GetQDGlobalsScreenBits (&bm);
12016 zoom_rect = bm.bounds;
12017 zoom_rect.top += w_title_height;
12018 InsetRect (&zoom_rect, 8, 4); /* not too tight */
12019
12020 zoom_rect.right = zoom_rect.left
12021 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12022
12023 SetWindowStandardState (w, &zoom_rect);
12024 }
12025 }
12026 #else /* not TARGET_API_MAC_CARBON */
12027 EraseRect (&(w->portRect));
12028 if (zoom_in_or_out == inZoomOut)
12029 {
12030 SetPt (&top_left, w->portRect.left, w->portRect.top);
12031 LocalToGlobal (&top_left);
12032
12033 /* calculate height of window's title bar */
12034 w_title_height = top_left.v - 1
12035 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
12036
12037 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
12038 zoom_rect = qd.screenBits.bounds;
12039 zoom_rect.top += w_title_height;
12040 InsetRect (&zoom_rect, 8, 4); /* not too tight */
12041
12042 zoom_rect.right = zoom_rect.left
12043 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12044
12045 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
12046 = zoom_rect;
12047 }
12048 #endif /* not TARGET_API_MAC_CARBON */
12049
12050 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
12051
12052 /* retrieve window size and update application values */
12053 #if TARGET_API_MAC_CARBON
12054 GetWindowPortBounds (w, &port_rect);
12055 #else
12056 port_rect = w->portRect;
12057 #endif
12058 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
12059 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
12060 x_set_window_size (mwp->mFP, 0, columns, rows);
12061
12062 SetPort (save_port);
12063 }
12064
12065 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
12066 static OSErr
12067 init_mac_drag_n_drop ()
12068 {
12069 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
12070 return result;
12071 }
12072
12073 /* Intialize AppleEvent dispatcher table for the required events. */
12074 void
12075 init_required_apple_events ()
12076 {
12077 OSErr err;
12078 long result;
12079
12080 /* Make sure we have apple events before starting. */
12081 err = Gestalt (gestaltAppleEventsAttr, &result);
12082 if (err != noErr)
12083 abort ();
12084
12085 if (!(result & (1 << gestaltAppleEventsPresent)))
12086 abort ();
12087
12088 #if TARGET_API_MAC_CARBON
12089 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12090 NewAEEventHandlerUPP
12091 ((AEEventHandlerProcPtr) do_ae_open_application),
12092 0L, false);
12093 #else
12094 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12095 NewAEEventHandlerProc
12096 ((AEEventHandlerProcPtr) do_ae_open_application),
12097 0L, false);
12098 #endif
12099 if (err != noErr)
12100 abort ();
12101
12102 #if TARGET_API_MAC_CARBON
12103 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12104 NewAEEventHandlerUPP
12105 ((AEEventHandlerProcPtr) do_ae_open_documents),
12106 0L, false);
12107 #else
12108 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12109 NewAEEventHandlerProc
12110 ((AEEventHandlerProcPtr) do_ae_open_documents),
12111 0L, false);
12112 #endif
12113 if (err != noErr)
12114 abort ();
12115
12116 #if TARGET_API_MAC_CARBON
12117 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12118 NewAEEventHandlerUPP
12119 ((AEEventHandlerProcPtr) do_ae_print_documents),
12120 0L, false);
12121 #else
12122 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12123 NewAEEventHandlerProc
12124 ((AEEventHandlerProcPtr) do_ae_print_documents),
12125 0L, false);
12126 #endif
12127 if (err != noErr)
12128 abort ();
12129
12130 #if TARGET_API_MAC_CARBON
12131 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12132 NewAEEventHandlerUPP
12133 ((AEEventHandlerProcPtr) do_ae_quit_application),
12134 0L, false);
12135 #else
12136 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12137 NewAEEventHandlerProc
12138 ((AEEventHandlerProcPtr) do_ae_quit_application),
12139 0L, false);
12140 #endif
12141 if (err != noErr)
12142 abort ();
12143 }
12144
12145 #if USE_CARBON_EVENTS
12146
12147 void init_service_handler()
12148 {
12149 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
12150 {kEventClassService, kEventServiceCopy},
12151 {kEventClassService, kEventServicePaste}};
12152 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
12153 3, specs, NULL, NULL);
12154 }
12155
12156 /*
12157 MAC_TODO: Check to see if this is called by AEProcessDesc...
12158 */
12159 OSStatus mac_handle_service_event (EventHandlerCallRef callRef,
12160 EventRef event, void *data)
12161 {
12162 OSStatus err = noErr;
12163 switch (GetEventKind (event))
12164 {
12165 case kEventServiceGetTypes:
12166 {
12167 CFMutableArrayRef copyTypes, pasteTypes;
12168 CFStringRef type;
12169 Boolean selection = true;
12170 /*
12171 GetEventParameter(event, kEventParamServicePasteTypes,
12172 typeCFMutableArrayRef, NULL,
12173 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
12174 */
12175 GetEventParameter(event, kEventParamServiceCopyTypes,
12176 typeCFMutableArrayRef, NULL,
12177 sizeof (CFMutableArrayRef), NULL, &copyTypes);
12178 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
12179 if (type) {
12180 CFArrayAppendValue (copyTypes, type);
12181 //CFArrayAppendValue (pasteTypes, type);
12182 CFRelease (type);
12183 }
12184 }
12185 case kEventServiceCopy:
12186 {
12187 ScrapRef currentScrap, specificScrap;
12188 char * buf = "";
12189 Size byteCount = 0;
12190
12191 GetCurrentScrap (&currentScrap);
12192
12193 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
12194 if (err == noErr)
12195 {
12196 void *buffer = xmalloc (byteCount);
12197 if (buffer != NULL)
12198 {
12199 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
12200 sizeof (ScrapRef), NULL, &specificScrap);
12201
12202 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
12203 &byteCount, buffer);
12204 if (err == noErr)
12205 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
12206 kScrapFlavorMaskNone, byteCount, buffer);
12207 xfree (buffer);
12208 }
12209 }
12210 err = noErr;
12211 }
12212 case kEventServicePaste:
12213 {
12214 /*
12215 // Get the current location
12216 Size byteCount;
12217 ScrapRef specificScrap;
12218 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
12219 sizeof(ScrapRef), NULL, &specificScrap);
12220 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
12221 if (err == noErr) {
12222 void * buffer = xmalloc(byteCount);
12223 if (buffer != NULL ) {
12224 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
12225 &byteCount, buffer);
12226 if (err == noErr) {
12227 // Actually place in the buffer
12228 BLOCK_INPUT;
12229 // Get the current "selection" string here
12230 UNBLOCK_INPUT;
12231 }
12232 }
12233 xfree(buffer);
12234 }
12235 */
12236 }
12237 }
12238 return err;
12239 }
12240 #endif
12241
12242 /* Open Application Apple Event */
12243 static pascal OSErr
12244 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12245 {
12246 return noErr;
12247 }
12248
12249
12250 /* Defined in mac.c. */
12251 extern int
12252 path_from_vol_dir_name (char *, int, short, long, char *);
12253
12254
12255 /* Called when we receive an AppleEvent with an ID of
12256 "kAEOpenDocuments". This routine gets the direct parameter,
12257 extracts the FSSpecs in it, and puts their names on a list. */
12258 static pascal OSErr
12259 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12260 {
12261 OSErr err, err2;
12262 AEDesc the_desc;
12263 AEKeyword keyword;
12264 DescType actual_type;
12265 Size actual_size;
12266
12267 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12268 if (err != noErr)
12269 goto descriptor_error_exit;
12270
12271 /* Check to see that we got all of the required parameters from the
12272 event descriptor. For an 'odoc' event this should just be the
12273 file list. */
12274 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12275 &actual_type, (Ptr) &keyword,
12276 sizeof (keyword), &actual_size);
12277 /* No error means that we found some unused parameters.
12278 errAEDescNotFound means that there are no more parameters. If we
12279 get an error code other than that, flag it. */
12280 if ((err == noErr) || (err != errAEDescNotFound))
12281 {
12282 err = errAEEventNotHandled;
12283 goto error_exit;
12284 }
12285 err = noErr;
12286
12287 /* Got all the parameters we need. Now, go through the direct
12288 object list and parse it up. */
12289 {
12290 long num_files_to_open;
12291
12292 err = AECountItems (&the_desc, &num_files_to_open);
12293 if (err == noErr)
12294 {
12295 int i;
12296
12297 /* AE file list is one based so just use that for indexing here. */
12298 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
12299 {
12300 FSSpec fs;
12301 Str255 path_name, unix_path_name;
12302 #ifdef MAC_OSX
12303 FSRef fref;
12304 #endif
12305
12306 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12307 (Ptr) &fs, sizeof (fs), &actual_size);
12308 if (err != noErr) break;
12309
12310 #ifdef MAC_OSX
12311 err = FSpMakeFSRef (&fs, &fref);
12312 if (err != noErr) break;
12313
12314 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12315 #else
12316 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12317 fs.name) &&
12318 mac_to_posix_pathname (path_name, unix_path_name, 255))
12319 #endif
12320 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12321 drag_and_drop_file_list);
12322 }
12323 }
12324 }
12325
12326 error_exit:
12327 /* Nuke the coerced file list in any case */
12328 err2 = AEDisposeDesc(&the_desc);
12329
12330 descriptor_error_exit:
12331 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12332 return err;
12333 }
12334
12335
12336 static pascal OSErr mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
12337 DragReference theDrag)
12338 {
12339 short items;
12340 short index;
12341 FlavorFlags theFlags;
12342 Point mouse;
12343 OSErr result;
12344 ItemReference theItem;
12345 HFSFlavor data;
12346 FSRef fref;
12347 Size size = sizeof (HFSFlavor);
12348
12349 drag_and_drop_file_list = Qnil;
12350 GetDragMouse (theDrag, &mouse, 0L);
12351 CountDragItems (theDrag, &items);
12352 for (index = 1; index <= items; index++)
12353 {
12354 /* Only handle file references. */
12355 GetDragItemReferenceNumber (theDrag, index, &theItem);
12356 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
12357 if (result == noErr)
12358 {
12359 #ifdef MAC_OSX
12360 FSRef frref;
12361 #else
12362 Str255 path_name;
12363 #endif
12364 Str255 unix_path_name;
12365 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
12366 #ifdef MAC_OSX
12367 /* Use Carbon routines, otherwise it converts the file name
12368 to /Macintosh HD/..., which is not correct. */
12369 FSpMakeFSRef (&data.fileSpec, &fref);
12370 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
12371 #else
12372 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
12373 data.fileSpec.parID, data.fileSpec.name) &&
12374 mac_to_posix_pathname (path_name, unix_path_name, 255))
12375 #endif
12376 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12377 drag_and_drop_file_list);
12378 }
12379 else
12380 return;
12381 }
12382 /* If there are items in the list, construct an event and post it to
12383 the queue like an interrupt using kbd_buffer_store_event. */
12384 if (!NILP (drag_and_drop_file_list))
12385 {
12386 struct input_event event;
12387 Lisp_Object frame;
12388 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
12389 SetPort (GetWindowPort (window));
12390 GlobalToLocal (&mouse);
12391
12392 event.kind = DRAG_N_DROP_EVENT;
12393 event.code = 0;
12394 event.modifiers = 0;
12395 event.timestamp = TickCount () * (1000 / 60);
12396 XSETINT (event.x, mouse.h);
12397 XSETINT (event.y, mouse.v);
12398 XSETFRAME (frame, f);
12399 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
12400 event.arg = Qnil;
12401 /* Post to the interrupt queue */
12402 kbd_buffer_store_event (&event);
12403 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
12404 {
12405 ProcessSerialNumber psn;
12406 GetCurrentProcess (&psn);
12407 SetFrontProcess (&psn);
12408 }
12409 }
12410 }
12411
12412
12413 /* Print Document Apple Event */
12414 static pascal OSErr
12415 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12416 {
12417 return errAEEventNotHandled;
12418 }
12419
12420
12421 static pascal OSErr
12422 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12423 {
12424 /* FixMe: Do we need an unwind-protect or something here? And what
12425 do we do about unsaved files. Currently just forces quit rather
12426 than doing recursive callback to get user input. */
12427
12428 terminate_flag = true;
12429
12430 /* Fkill_emacs doesn't return. We have to return. (TI) */
12431 return noErr;
12432 }
12433
12434
12435 #if __profile__
12436 void
12437 profiler_exit_proc ()
12438 {
12439 ProfilerDump ("\pEmacs.prof");
12440 ProfilerTerm ();
12441 }
12442 #endif
12443
12444 /* These few functions implement Emacs as a normal Mac application
12445 (almost): set up the heap and the Toolbox, handle necessary
12446 system events plus a few simple menu events. They also set up
12447 Emacs's access to functions defined in the rest of this file.
12448 Emacs uses function hooks to perform all its terminal I/O. A
12449 complete list of these functions appear in termhooks.h. For what
12450 they do, read the comments there and see also w32term.c and
12451 xterm.c. What's noticeably missing here is the event loop, which
12452 is normally present in most Mac application. After performing the
12453 necessary Mac initializations, main passes off control to
12454 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12455 mac_read_socket (defined further below) to read input. This is
12456 where WaitNextEvent is called to process Mac events. This is also
12457 where check_alarm in sysdep.c is called to simulate alarm signals.
12458 This makes the cursor jump back to its correct position after
12459 briefly jumping to that of the matching parenthesis, print useful
12460 hints and prompts in the minibuffer after the user stops typing for
12461 a wait, etc. */
12462
12463 #if !TARGET_API_MAC_CARBON
12464 #undef main
12465 int
12466 main (void)
12467 {
12468 #if __profile__ /* is the profiler on? */
12469 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12470 exit(1);
12471 #endif
12472
12473 #if __MWERKS__
12474 /* set creator and type for files created by MSL */
12475 _fcreator = 'EMAx';
12476 _ftype = 'TEXT';
12477 #endif
12478
12479 do_init_managers ();
12480
12481 do_get_menus ();
12482
12483 do_check_ram_size ();
12484
12485 init_emacs_passwd_dir ();
12486
12487 init_environ ();
12488
12489 initialize_applescript ();
12490
12491 init_required_apple_events ();
12492
12493 {
12494 char **argv;
12495 int argc = 0;
12496
12497 /* set up argv array from STR# resource */
12498 get_string_list (&argv, ARGV_STRING_LIST_ID);
12499 while (argv[argc])
12500 argc++;
12501
12502 /* free up AppleScript resources on exit */
12503 atexit (terminate_applescript);
12504
12505 #if __profile__ /* is the profiler on? */
12506 atexit (profiler_exit_proc);
12507 #endif
12508
12509 /* 3rd param "envp" never used in emacs_main */
12510 (void) emacs_main (argc, argv, 0);
12511 }
12512
12513 /* Never reached - real exit in Fkill_emacs */
12514 return 0;
12515 }
12516 #endif
12517
12518 /* Table for translating Mac keycode to X keysym values. Contributed
12519 by Sudhir Shenoy. */
12520 static unsigned char keycode_to_xkeysym_table[] = {
12521 /* 0x00 - 0x3f */
12522 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 /* 0x40 */
12527 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12528 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12529 0, 0, 0, '\xaf' /* kp/ */,
12530 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
12531 /* 0x50 */
12532 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12533 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12534 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12535 '\xb9' /* kp9 */, 0, 0, 0,
12536 /* 0x60 */
12537 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12538 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12539 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12540 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
12541 /* 0x70 */
12542 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12543 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12544 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12545 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
12546 };
12547
12548 static int
12549 keycode_to_xkeysym (int keyCode, int *xKeySym)
12550 {
12551 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12552 return *xKeySym != 0;
12553 }
12554
12555 /* Emacs calls this whenever it wants to read an input event from the
12556 user. */
12557 int
12558 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12559 {
12560 int count = 0;
12561 #if USE_CARBON_EVENTS
12562 OSStatus rneResult;
12563 EventRef eventRef;
12564 EventMouseButton mouseBtn;
12565 #endif
12566 EventRecord er;
12567 int the_modifiers;
12568 EventMask event_mask;
12569
12570 #if 0
12571 if (interrupt_input_blocked)
12572 {
12573 interrupt_input_pending = 1;
12574 return -1;
12575 }
12576 #endif
12577
12578 interrupt_input_pending = 0;
12579 BLOCK_INPUT;
12580
12581 /* So people can tell when we have read the available input. */
12582 input_signal_count++;
12583
12584 if (numchars <= 0)
12585 abort ();
12586
12587 /* Don't poll for events to process (specifically updateEvt) if
12588 window update currently already in progress. A call to redisplay
12589 (in do_window_update) can be preempted by another call to
12590 redisplay, causing blank regions to be left on the screen and the
12591 cursor to be left at strange places. */
12592 if (handling_window_update)
12593 {
12594 UNBLOCK_INPUT;
12595 return 0;
12596 }
12597
12598 if (terminate_flag)
12599 Fkill_emacs (make_number (1));
12600
12601 /* It is necessary to set this (additional) argument slot of an
12602 event to nil because keyboard.c protects incompletely processed
12603 event from being garbage collected by placing them in the
12604 kbd_buffer_gcpro vector. */
12605 bufp->arg = Qnil;
12606
12607 event_mask = everyEvent;
12608 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
12609 event_mask -= highLevelEventMask;
12610
12611 #if USE_CARBON_EVENTS
12612 rneResult = ReceiveNextEvent (0, NULL,
12613 expected ? TicksToEventTime(app_sleep_time) : 0,
12614 true, &eventRef);
12615 if (!rneResult)
12616 {
12617 /* Handle new events */
12618 if (!mac_convert_event_ref (eventRef, &er))
12619 switch (GetEventClass (eventRef))
12620 {
12621 case kEventClassMouse:
12622 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
12623 {
12624 SInt32 delta;
12625 Point point;
12626 WindowPtr window_ptr = FrontWindow ();
12627 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12628 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
12629 typeSInt32, NULL, sizeof (SInt32),
12630 NULL, &delta);
12631 GetEventParameter(eventRef, kEventParamMouseLocation,
12632 typeQDPoint, NULL, sizeof (Point),
12633 NULL, &point);
12634 bufp->kind = MOUSE_WHEEL_EVENT;
12635 bufp->code = delta;
12636 bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
12637 SetPort (GetWindowPort (window_ptr));
12638 GlobalToLocal (&point);
12639 XSETINT (bufp->x, point.h);
12640 XSETINT (bufp->y, point.v);
12641 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12642 bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
12643 count++;
12644 }
12645 else
12646 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12647
12648 break;
12649 default:
12650 /* Send the event to the appropriate receiver. */
12651 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12652 }
12653 else
12654 #else
12655 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
12656 #endif /* USE_CARBON_EVENTS */
12657 switch (er.what)
12658 {
12659 case mouseDown:
12660 case mouseUp:
12661 {
12662 WindowPtr window_ptr = FrontWindow ();
12663 SInt16 part_code;
12664
12665 #if USE_CARBON_EVENTS
12666 /* This is needed to correctly */
12667 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12668 #endif
12669
12670 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12671 && er.what == mouseUp)
12672 {
12673 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12674 Point mouse_loc = er.where;
12675
12676 /* Convert to local coordinates of new window. */
12677 #if TARGET_API_MAC_CARBON
12678 SetPort (GetWindowPort (window_ptr));
12679 #else
12680 SetPort (window_ptr);
12681 #endif
12682
12683 GlobalToLocal (&mouse_loc);
12684
12685 #if USE_CARBON_EVENTS
12686 bufp->code = mac_get_mouse_btn (eventRef);
12687 #else
12688 bufp->code = 0; /* only one mouse button */
12689 #endif
12690 bufp->kind = SCROLL_BAR_CLICK_EVENT;
12691 bufp->frame_or_window = tracked_scroll_bar->window;
12692 bufp->part = scroll_bar_handle;
12693 #if USE_CARBON_EVENTS
12694 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12695 #else
12696 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12697 #endif
12698 bufp->modifiers |= up_modifier;
12699 bufp->timestamp = er.when * (1000 / 60);
12700 /* ticks to milliseconds */
12701
12702 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12703 XSETINT (bufp->y, mouse_loc.v - 24);
12704 tracked_scroll_bar->dragging = Qnil;
12705 mouse_tracking_in_progress = mouse_tracking_none;
12706 tracked_scroll_bar = NULL;
12707 count++;
12708 break;
12709 }
12710
12711 part_code = FindWindow (er.where, &window_ptr);
12712
12713 switch (part_code)
12714 {
12715 case inMenuBar:
12716 {
12717 struct frame *f = ((mac_output *)
12718 GetWRefCon (FrontWindow ()))->mFP;
12719 saved_menu_event_location = er.where;
12720 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
12721 XSETFRAME (bufp->frame_or_window, f);
12722 count++;
12723 }
12724 break;
12725
12726 case inContent:
12727 if (window_ptr != FrontWindow ())
12728 SelectWindow (window_ptr);
12729 else
12730 {
12731 SInt16 control_part_code;
12732 ControlHandle ch;
12733 struct mac_output *mwp = (mac_output *)
12734 GetWRefCon (window_ptr);
12735 Point mouse_loc = er.where;
12736
12737 /* convert to local coordinates of new window */
12738 #if TARGET_API_MAC_CARBON
12739 SetPort (GetWindowPort (window_ptr));
12740 #else
12741 SetPort (window_ptr);
12742 #endif
12743
12744 GlobalToLocal (&mouse_loc);
12745 #if TARGET_API_MAC_CARBON
12746 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12747 &control_part_code);
12748 #else
12749 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
12750 #endif
12751
12752 #if USE_CARBON_EVENTS
12753 bufp->code = mac_get_mouse_btn (eventRef);
12754 #else
12755 bufp->code = 0; /* only one mouse button */
12756 #endif
12757 XSETINT (bufp->x, mouse_loc.h);
12758 XSETINT (bufp->y, mouse_loc.v);
12759 bufp->timestamp = er.when * (1000 / 60);
12760 /* ticks to milliseconds */
12761
12762 #if TARGET_API_MAC_CARBON
12763 if (ch != 0)
12764 #else
12765 if (control_part_code != 0)
12766 #endif
12767 {
12768 struct scroll_bar *bar = (struct scroll_bar *)
12769 GetControlReference (ch);
12770 x_scroll_bar_handle_click (bar, control_part_code, &er,
12771 bufp);
12772 if (er.what == mouseDown
12773 && control_part_code == kControlIndicatorPart)
12774 {
12775 mouse_tracking_in_progress
12776 = mouse_tracking_scroll_bar;
12777 tracked_scroll_bar = bar;
12778 }
12779 else
12780 {
12781 mouse_tracking_in_progress = mouse_tracking_none;
12782 tracked_scroll_bar = NULL;
12783 }
12784 }
12785 else
12786 {
12787 bufp->kind = MOUSE_CLICK_EVENT;
12788 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12789 if (er.what == mouseDown)
12790 mouse_tracking_in_progress
12791 = mouse_tracking_mouse_movement;
12792 else
12793 mouse_tracking_in_progress = mouse_tracking_none;
12794 }
12795
12796 #if USE_CARBON_EVENTS
12797 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12798 #else
12799 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12800 #endif
12801
12802 switch (er.what)
12803 {
12804 case mouseDown:
12805 bufp->modifiers |= down_modifier;
12806 break;
12807 case mouseUp:
12808 bufp->modifiers |= up_modifier;
12809 break;
12810 }
12811
12812 count++;
12813 }
12814 break;
12815
12816 case inDrag:
12817 #if TARGET_API_MAC_CARBON
12818 {
12819 BitMap bm;
12820
12821 GetQDGlobalsScreenBits (&bm);
12822 DragWindow (window_ptr, er.where, &bm.bounds);
12823 }
12824 #else /* not TARGET_API_MAC_CARBON */
12825 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12826 #endif /* not TARGET_API_MAC_CARBON */
12827 break;
12828
12829 case inGoAway:
12830 if (TrackGoAway (window_ptr, er.where))
12831 {
12832 bufp->kind = DELETE_WINDOW_EVENT;
12833 XSETFRAME (bufp->frame_or_window,
12834 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12835 count++;
12836 }
12837 break;
12838
12839 /* window resize handling added --ben */
12840 case inGrow:
12841 do_grow_window(window_ptr, &er);
12842 break;
12843
12844 /* window zoom handling added --ben */
12845 case inZoomIn:
12846 case inZoomOut:
12847 if (TrackBox (window_ptr, er.where, part_code))
12848 do_zoom_window (window_ptr, part_code);
12849 break;
12850
12851 default:
12852 break;
12853 }
12854 }
12855 break;
12856
12857 case updateEvt:
12858 case osEvt:
12859 case activateEvt:
12860 #if USE_CARBON_EVENTS
12861 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12862 #endif
12863 do_events (&er);
12864 break;
12865
12866 case keyDown:
12867 case autoKey:
12868 {
12869 int keycode = (er.message & keyCodeMask) >> 8;
12870 int xkeysym;
12871
12872 ObscureCursor ();
12873
12874 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12875 {
12876 bufp->code = 0x7f;
12877 bufp->kind = ASCII_KEYSTROKE_EVENT;
12878 }
12879 else if (keycode_to_xkeysym (keycode, &xkeysym))
12880 {
12881 bufp->code = 0xff00 | xkeysym;
12882 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
12883 }
12884 else if (!NILP (Vmac_reverse_ctrl_meta) && (er.modifiers & controlKey))
12885 {
12886 /* This is a special case to deal with converting from
12887 a control character to non-control character */
12888 int new_modifiers = er.modifiers & ~controlKey;
12889 int new_keycode = keycode | new_modifiers;
12890 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12891 unsigned long some_state = 0;
12892 bufp->code = KeyTranslate (kchr_ptr, new_keycode, &some_state) & 0xff;
12893 bufp->kind = ASCII_KEYSTROKE_EVENT;
12894 }
12895 else
12896 {
12897 if (er.modifiers & macMetaKey)
12898 {
12899 /* This code comes from Keyboard Resource, Appendix
12900 C of IM - Text. This is necessary since shift is
12901 ignored in KCHR table translation when option or
12902 command is pressed. */
12903 int new_modifiers = er.modifiers & 0xf600;
12904 /* mask off option and command */
12905 int new_keycode = keycode | new_modifiers;
12906 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12907 unsigned long some_state = 0;
12908 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12909 &some_state) & 0xff;
12910 }
12911 #if USE_CARBON_EVENTS
12912 else if (er.modifiers & cmdKey &&
12913 (NILP (Vmac_command_key_is_meta)))
12914 {
12915 /* If this is a command key (and we are not overriding it),
12916 send back to the operating system */
12917 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12918 break;
12919 }
12920 #endif
12921 else
12922 bufp->code = er.message & charCodeMask;
12923 bufp->kind = ASCII_KEYSTROKE_EVENT;
12924 }
12925 }
12926
12927 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12928 convert non-ASCII characters typed at the Mac keyboard
12929 (presumed to be in the Mac Roman encoding) to iso-latin-1
12930 encoding before they are passed to Emacs. This enables the
12931 Mac keyboard to be used to enter non-ASCII iso-latin-1
12932 characters directly. */
12933 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12934 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
12935 {
12936 static TECObjectRef converter = NULL;
12937 OSStatus the_err = noErr;
12938 OSStatus convert_status = noErr;
12939
12940 if (converter == NULL)
12941 {
12942 the_err = TECCreateConverter (&converter,
12943 kTextEncodingMacRoman,
12944 mac_keyboard_text_encoding);
12945 current_mac_keyboard_text_encoding
12946 = mac_keyboard_text_encoding;
12947 }
12948 else if (mac_keyboard_text_encoding
12949 != current_mac_keyboard_text_encoding)
12950 {
12951 /* Free the converter for the current encoding before
12952 creating a new one. */
12953 TECDisposeConverter (converter);
12954 the_err = TECCreateConverter (&converter,
12955 kTextEncodingMacRoman,
12956 mac_keyboard_text_encoding);
12957 current_mac_keyboard_text_encoding
12958 = mac_keyboard_text_encoding;
12959 }
12960
12961 if (the_err == noErr)
12962 {
12963 unsigned char ch = bufp->code;
12964 ByteCount actual_input_length, actual_output_length;
12965 unsigned char outch;
12966
12967 convert_status = TECConvertText (converter, &ch, 1,
12968 &actual_input_length,
12969 &outch, 1,
12970 &actual_output_length);
12971 if (convert_status == noErr
12972 && actual_input_length == 1
12973 && actual_output_length == 1)
12974 bufp->code = outch;
12975 }
12976 }
12977
12978 #if USE_CARBON_EVENTS
12979 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12980 #else
12981 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12982 #endif
12983
12984 {
12985 mac_output *mwp
12986 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
12987 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12988 }
12989
12990 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
12991
12992 count++;
12993 break;
12994
12995 case kHighLevelEvent:
12996 drag_and_drop_file_list = Qnil;
12997
12998 AEProcessAppleEvent(&er);
12999
13000 /* Build a DRAG_N_DROP_EVENT type event as is done in
13001 constuct_drag_n_drop in w32term.c. */
13002 if (!NILP (drag_and_drop_file_list))
13003 {
13004 struct frame *f;
13005 WindowPtr wp;
13006 Lisp_Object frame;
13007
13008 wp = FrontWindow ();
13009 if (!wp)
13010 f = NULL;
13011 else
13012 f = ((mac_output *) GetWRefCon (wp))->mFP;
13013
13014 bufp->kind = DRAG_N_DROP_EVENT;
13015 bufp->code = 0;
13016 bufp->timestamp = er.when * (1000 / 60);
13017 /* ticks to milliseconds */
13018 #if USE_CARBON_EVENTS
13019 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13020 #else
13021 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13022 #endif
13023
13024 XSETINT (bufp->x, 0);
13025 XSETINT (bufp->y, 0);
13026
13027 XSETFRAME (frame, f);
13028 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
13029
13030 /* Regardless of whether Emacs was suspended or in the
13031 foreground, ask it to redraw its entire screen.
13032 Otherwise parts of the screen can be left in an
13033 inconsistent state. */
13034 if (wp)
13035 #if TARGET_API_MAC_CARBON
13036 {
13037 Rect r;
13038
13039 GetWindowPortBounds (wp, &r);
13040 InvalWindowRect (wp, &r);
13041 }
13042 #else /* not TARGET_API_MAC_CARBON */
13043 InvalRect (&(wp->portRect));
13044 #endif /* not TARGET_API_MAC_CARBON */
13045
13046 count++;
13047 }
13048 default:
13049 break;
13050 }
13051 #if USE_CARBON_EVENTS
13052 ReleaseEvent (eventRef);
13053 }
13054 #endif
13055
13056 /* If the focus was just given to an autoraising frame,
13057 raise it now. */
13058 /* ??? This ought to be able to handle more than one such frame. */
13059 if (pending_autoraise_frame)
13060 {
13061 x_raise_frame (pending_autoraise_frame);
13062 pending_autoraise_frame = 0;
13063 }
13064
13065 #if !TARGET_API_MAC_CARBON
13066 check_alarm (); /* simulate the handling of a SIGALRM */
13067 #endif
13068
13069 {
13070 static Point old_mouse_pos = { -1, -1 };
13071
13072 if (app_is_suspended)
13073 {
13074 old_mouse_pos.h = -1;
13075 old_mouse_pos.v = -1;
13076 }
13077 else
13078 {
13079 Point mouse_pos;
13080 WindowPtr wp;
13081 struct frame *f;
13082 Lisp_Object bar;
13083 struct scroll_bar *sb;
13084
13085 wp = FrontWindow ();
13086 if (is_emacs_window (wp))
13087 {
13088 f = ((mac_output *) GetWRefCon (wp))->mFP;
13089
13090 #if TARGET_API_MAC_CARBON
13091 SetPort (GetWindowPort (wp));
13092 #else
13093 SetPort (wp);
13094 #endif
13095
13096 GetMouse (&mouse_pos);
13097
13098 if (!EqualPt (mouse_pos, old_mouse_pos))
13099 {
13100 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
13101 && tracked_scroll_bar)
13102 x_scroll_bar_note_movement (tracked_scroll_bar,
13103 mouse_pos.v
13104 - XINT (tracked_scroll_bar->top),
13105 TickCount() * (1000 / 60));
13106 else
13107 note_mouse_movement (f, &mouse_pos);
13108
13109 old_mouse_pos = mouse_pos;
13110 }
13111 }
13112 }
13113 }
13114
13115 UNBLOCK_INPUT;
13116
13117 return count;
13118 }
13119
13120
13121 /* Need to override CodeWarrior's input function so no conversion is
13122 done on newlines Otherwise compiled functions in .elc files will be
13123 read incorrectly. Defined in ...:MSL C:MSL
13124 Common:Source:buffer_io.c. */
13125 #ifdef __MWERKS__
13126 void
13127 __convert_to_newlines (unsigned char * p, size_t * n)
13128 {
13129 #pragma unused(p,n)
13130 }
13131
13132 void
13133 __convert_from_newlines (unsigned char * p, size_t * n)
13134 {
13135 #pragma unused(p,n)
13136 }
13137 #endif
13138
13139
13140 /* Initialize the struct pointed to by MW to represent a new COLS x
13141 ROWS Macintosh window, using font with name FONTNAME and size
13142 FONTSIZE. */
13143 void
13144 NewMacWindow (FRAME_PTR fp)
13145 {
13146 mac_output *mwp;
13147 #if TARGET_API_MAC_CARBON
13148 static int making_terminal_window = 0;
13149 #else
13150 static int making_terminal_window = 1;
13151 #endif
13152
13153 mwp = fp->output_data.mac;
13154
13155 if (making_terminal_window)
13156 {
13157 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
13158 (WindowPtr) -1)))
13159 abort ();
13160 making_terminal_window = 0;
13161 }
13162 else
13163 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
13164 abort ();
13165
13166 SetWRefCon (mwp->mWP, (long) mwp);
13167 /* so that update events can find this mac_output struct */
13168 mwp->mFP = fp; /* point back to emacs frame */
13169
13170 #if TARGET_API_MAC_CARBON
13171 SetPort (GetWindowPort (mwp->mWP));
13172 #else
13173 SetPort (mwp->mWP);
13174 #endif
13175
13176 mwp->fontset = -1;
13177
13178 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
13179 ShowWindow (mwp->mWP);
13180
13181 }
13182
13183
13184 void make_mac_frame (struct frame *f)
13185 {
13186 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
13187 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
13188
13189 NewMacWindow(f);
13190
13191 f->output_data.mac->cursor_pixel = 0;
13192 f->output_data.mac->border_pixel = 0x00ff00;
13193 f->output_data.mac->mouse_pixel = 0xff00ff;
13194 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
13195
13196 f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
13197
13198 f->output_data.mac->fontset = -1;
13199 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13200 f->output_data.mac->scroll_bar_background_pixel = -1;
13201 f->output_data.mac->left_pos = 4;
13202 f->output_data.mac->top_pos = 4;
13203 f->output_data.mac->border_width = 0;
13204 f->output_data.mac->explicit_parent = 0;
13205
13206 f->output_data.mac->internal_border_width = 0;
13207
13208 f->output_method = output_mac;
13209
13210 f->auto_raise = 1;
13211 f->auto_lower = 1;
13212
13213 f->new_width = 0;
13214 f->new_height = 0;
13215 }
13216
13217 void make_mac_terminal_frame (struct frame *f)
13218 {
13219 Lisp_Object frame;
13220
13221 XSETFRAME (frame, f);
13222
13223 f->output_method = output_mac;
13224 f->output_data.mac = (struct mac_output *)
13225 xmalloc (sizeof (struct mac_output));
13226 bzero (f->output_data.mac, sizeof (struct mac_output));
13227 f->output_data.mac->fontset = -1;
13228 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13229 f->output_data.mac->scroll_bar_background_pixel = -1;
13230
13231 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
13232
13233 f->width = 96;
13234 f->height = 4;
13235
13236 make_mac_frame (f);
13237
13238 x_make_gc (f);
13239
13240 /* Need to be initialized for unshow_buffer in window.c. */
13241 selected_window = f->selected_window;
13242
13243 Fmodify_frame_parameters (frame,
13244 Fcons (Fcons (Qfont,
13245 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
13246 Fmodify_frame_parameters (frame,
13247 Fcons (Fcons (Qforeground_color,
13248 build_string ("black")), Qnil));
13249 Fmodify_frame_parameters (frame,
13250 Fcons (Fcons (Qbackground_color,
13251 build_string ("white")), Qnil));
13252 }
13253
13254 \f
13255 /***********************************************************************
13256 Initialization
13257 ***********************************************************************/
13258
13259 #ifdef USE_X_TOOLKIT
13260 static XrmOptionDescRec emacs_options[] = {
13261 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13262 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13263
13264 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13265 XrmoptionSepArg, NULL},
13266 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13267
13268 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13269 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13270 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13271 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13272 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13273 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13274 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13275 };
13276 #endif /* USE_X_TOOLKIT */
13277
13278 #ifdef MULTI_KBOARD
13279 /* Test whether two display-name strings agree up to the dot that separates
13280 the screen number from the server number. */
13281 static int
13282 same_x_server (name1, name2)
13283 char *name1, *name2;
13284 {
13285 int seen_colon = 0;
13286 unsigned char *system_name = SDATA (Vsystem_name);
13287 int system_name_length = strlen (system_name);
13288 int length_until_period = 0;
13289
13290 while (system_name[length_until_period] != 0
13291 && system_name[length_until_period] != '.')
13292 length_until_period++;
13293
13294 /* Treat `unix' like an empty host name. */
13295 if (! strncmp (name1, "unix:", 5))
13296 name1 += 4;
13297 if (! strncmp (name2, "unix:", 5))
13298 name2 += 4;
13299 /* Treat this host's name like an empty host name. */
13300 if (! strncmp (name1, system_name, system_name_length)
13301 && name1[system_name_length] == ':')
13302 name1 += system_name_length;
13303 if (! strncmp (name2, system_name, system_name_length)
13304 && name2[system_name_length] == ':')
13305 name2 += system_name_length;
13306 /* Treat this host's domainless name like an empty host name. */
13307 if (! strncmp (name1, system_name, length_until_period)
13308 && name1[length_until_period] == ':')
13309 name1 += length_until_period;
13310 if (! strncmp (name2, system_name, length_until_period)
13311 && name2[length_until_period] == ':')
13312 name2 += length_until_period;
13313
13314 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13315 {
13316 if (*name1 == ':')
13317 seen_colon++;
13318 if (seen_colon && *name1 == '.')
13319 return 1;
13320 }
13321 return (seen_colon
13322 && (*name1 == '.' || *name1 == '\0')
13323 && (*name2 == '.' || *name2 == '\0'));
13324 }
13325 #endif
13326
13327 int mac_initialized = 0;
13328
13329 void
13330 mac_initialize_display_info ()
13331 {
13332 struct mac_display_info *dpyinfo = &one_mac_display_info;
13333 GDHandle main_device_handle;
13334
13335 bzero (dpyinfo, sizeof (*dpyinfo));
13336
13337 /* Put it on x_display_name_list. */
13338 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13339 x_display_name_list);
13340 dpyinfo->name_list_element = XCAR (x_display_name_list);
13341
13342 #if 0
13343 dpyinfo->mac_id_name
13344 = (char *) xmalloc (SCHARS (Vinvocation_name)
13345 + SCHARS (Vsystem_name)
13346 + 2);
13347 sprintf (dpyinfo->mac_id_name, "%s@%s",
13348 SDATA (Vinvocation_name), SDATA (Vsystem_name));
13349 #else
13350 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13351 strcpy (dpyinfo->mac_id_name, "Mac Display");
13352 #endif
13353
13354 main_device_handle = LMGetMainDevice();
13355
13356 dpyinfo->reference_count = 0;
13357 dpyinfo->resx = 75.0;
13358 dpyinfo->resy = 75.0;
13359 dpyinfo->n_planes = 1;
13360 dpyinfo->n_cbits = 16;
13361 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13362 dpyinfo->width = (**main_device_handle).gdRect.right;
13363 dpyinfo->grabbed = 0;
13364 dpyinfo->root_window = NULL;
13365
13366 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13367 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13368 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13369 dpyinfo->mouse_face_window = Qnil;
13370 }
13371
13372 struct mac_display_info *
13373 mac_term_init (display_name, xrm_option, resource_name)
13374 Lisp_Object display_name;
13375 char *xrm_option;
13376 char *resource_name;
13377 {
13378 struct mac_display_info *dpyinfo;
13379 GDHandle main_device_handle;
13380
13381 if (!mac_initialized)
13382 {
13383 mac_initialize ();
13384 mac_initialized = 1;
13385 }
13386
13387 mac_initialize_display_info (display_name);
13388
13389 dpyinfo = &one_mac_display_info;
13390
13391 main_device_handle = LMGetMainDevice();
13392
13393 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13394 dpyinfo->width = (**main_device_handle).gdRect.right;
13395
13396 return dpyinfo;
13397 }
13398 \f
13399 /* Set up use of X before we make the first connection. */
13400
13401 static struct redisplay_interface x_redisplay_interface =
13402 {
13403 x_produce_glyphs,
13404 x_write_glyphs,
13405 x_insert_glyphs,
13406 x_clear_end_of_line,
13407 x_scroll_run,
13408 x_after_update_window_line,
13409 x_update_window_begin,
13410 x_update_window_end,
13411 XTcursor_to,
13412 x_flush,
13413 x_clear_mouse_face,
13414 x_get_glyph_overhangs,
13415 x_fix_overlapping_area
13416 };
13417
13418 void
13419 mac_initialize ()
13420 {
13421 rif = &x_redisplay_interface;
13422
13423 clear_frame_hook = x_clear_frame;
13424 ins_del_lines_hook = x_ins_del_lines;
13425 delete_glyphs_hook = x_delete_glyphs;
13426 ring_bell_hook = XTring_bell;
13427 reset_terminal_modes_hook = XTreset_terminal_modes;
13428 set_terminal_modes_hook = XTset_terminal_modes;
13429 update_begin_hook = x_update_begin;
13430 update_end_hook = x_update_end;
13431 set_terminal_window_hook = XTset_terminal_window;
13432 read_socket_hook = XTread_socket;
13433 frame_up_to_date_hook = XTframe_up_to_date;
13434 mouse_position_hook = XTmouse_position;
13435 frame_rehighlight_hook = XTframe_rehighlight;
13436 frame_raise_lower_hook = XTframe_raise_lower;
13437
13438 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13439 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13440 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13441 judge_scroll_bars_hook = XTjudge_scroll_bars;
13442
13443 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13444
13445 scroll_region_ok = 1; /* we'll scroll partial frames */
13446 char_ins_del_ok = 1;
13447 line_ins_del_ok = 1; /* we'll just blt 'em */
13448 fast_clear_end_of_line = 1; /* X does this well */
13449 memory_below_frame = 0; /* we don't remember what scrolls
13450 off the bottom */
13451 baud_rate = 19200;
13452
13453 x_noop_count = 0;
13454 last_tool_bar_item = -1;
13455 any_help_event_p = 0;
13456
13457 /* Try to use interrupt input; if we can't, then start polling. */
13458 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13459
13460 #ifdef USE_X_TOOLKIT
13461 XtToolkitInitialize ();
13462 Xt_app_con = XtCreateApplicationContext ();
13463 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13464
13465 /* Install an asynchronous timer that processes Xt timeout events
13466 every 0.1s. This is necessary because some widget sets use
13467 timeouts internally, for example the LessTif menu bar, or the
13468 Xaw3d scroll bar. When Xt timouts aren't processed, these
13469 widgets don't behave normally. */
13470 {
13471 EMACS_TIME interval;
13472 EMACS_SET_SECS_USECS (interval, 0, 100000);
13473 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13474 }
13475 #endif
13476
13477 #if USE_TOOLKIT_SCROLL_BARS
13478 xaw3d_arrow_scroll = False;
13479 xaw3d_pick_top = True;
13480 #endif
13481
13482 #if 0
13483 /* Note that there is no real way portable across R3/R4 to get the
13484 original error handler. */
13485 XSetErrorHandler (x_error_handler);
13486 XSetIOErrorHandler (x_io_error_quitter);
13487
13488 /* Disable Window Change signals; they are handled by X events. */
13489 #ifdef SIGWINCH
13490 signal (SIGWINCH, SIG_DFL);
13491 #endif /* ! defined (SIGWINCH) */
13492
13493 signal (SIGPIPE, x_connection_signal);
13494 #endif
13495
13496 mac_initialize_display_info ();
13497
13498 #if TARGET_API_MAC_CARBON
13499 init_required_apple_events ();
13500
13501 init_mac_drag_n_drop ();
13502
13503 #if USE_CARBON_EVENTS
13504 init_service_handler ();
13505 #endif
13506
13507 DisableMenuCommand (NULL, kHICommandQuit);
13508 #endif
13509 }
13510
13511
13512 void
13513 syms_of_macterm ()
13514 {
13515 #if 0
13516 staticpro (&x_error_message_string);
13517 x_error_message_string = Qnil;
13518 #endif
13519
13520 staticpro (&x_display_name_list);
13521 x_display_name_list = Qnil;
13522
13523 staticpro (&last_mouse_scroll_bar);
13524 last_mouse_scroll_bar = Qnil;
13525
13526 staticpro (&Qvendor_specific_keysyms);
13527 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13528
13529 staticpro (&last_mouse_press_frame);
13530 last_mouse_press_frame = Qnil;
13531
13532 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13533 staticpro (&Qmac_ready_for_drag_n_drop);
13534
13535 help_echo = Qnil;
13536 staticpro (&help_echo);
13537 help_echo_object = Qnil;
13538 staticpro (&help_echo_object);
13539 help_echo_window = Qnil;
13540 staticpro (&help_echo_window);
13541 previous_help_echo = Qnil;
13542 staticpro (&previous_help_echo);
13543 help_echo_pos = -1;
13544
13545 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13546 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13547 x_autoselect_window_p = 0;
13548
13549 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13550 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13551 For example, if a block cursor is over a tab, it will be drawn as
13552 wide as that tab on the display. */);
13553 x_stretch_cursor_p = 0;
13554
13555 #if 0 /* TODO: Setting underline position from font properties. */
13556 DEFVAR_BOOL ("x-use-underline-position-properties",
13557 &x_use_underline_position_properties,
13558 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13559 nil means ignore them. If you encounter fonts with bogus
13560 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13561 to 4.1, set this to nil. */);
13562 x_use_underline_position_properties = 1;
13563 #endif
13564
13565 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13566 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13567 Vx_toolkit_scroll_bars = Qt;
13568
13569 staticpro (&last_mouse_motion_frame);
13570 last_mouse_motion_frame = Qnil;
13571
13572 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
13573 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13574 Otherwise the option key is used. */);
13575 Vmac_command_key_is_meta = Qt;
13576
13577 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
13578 doc: /* Non-nil means that the control and meta keys are reversed. This is
13579 useful for non-standard keyboard layouts. */);
13580 Vmac_reverse_ctrl_meta = Qnil;
13581
13582 #if USE_CARBON_EVENTS
13583 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
13584 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
13585 the right click will be mouse-3.
13586 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
13587 Vmac_wheel_button_is_mouse_2 = Qt;
13588 #endif
13589
13590 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
13591 doc: /* One of the Text Encoding Base constant values defined in the
13592 Basic Text Constants section of Inside Macintosh - Text Encoding
13593 Conversion Manager. Its value determines the encoding characters
13594 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13595 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13596 its default value, no conversion takes place. If it is set to
13597 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13598 characters typed on Mac keyboard are first converted into the
13599 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13600 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13601 command, this enables the Mac keyboard to be used to enter non-ASCII
13602 characters directly. */);
13603 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13604 }