]> code.delx.au - gnu-emacs/blob - src/macterm.c
(x_specified_cursor_type): Remove prototype.
[gnu-emacs] / src / macterm.c
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
22
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.h"
29 #include "blockinput.h"
30
31 #include "macterm.h"
32
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
36
37 #ifdef MAC_OSX
38 #undef mktime
39 #undef DEBUG
40 #undef free
41 #undef malloc
42 #undef realloc
43 /* Macros max and min defined in lisp.h conflict with those in
44 precompiled header Carbon.h. */
45 #undef max
46 #undef min
47 #undef init_process
48 #include <Carbon/Carbon.h>
49 #undef free
50 #define free unexec_free
51 #undef malloc
52 #define malloc unexec_malloc
53 #undef realloc
54 #define realloc unexec_realloc
55 #undef min
56 #define min(a, b) ((a) < (b) ? (a) : (b))
57 #undef max
58 #define max(a, b) ((a) > (b) ? (a) : (b))
59 #undef init_process
60 #define init_process emacs_init_process
61 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
62 obtain events from the event queue. If set to 0, WaitNextEvent is
63 used instead. */
64 #define USE_CARBON_EVENTS 1
65 #else /* not MAC_OSX */
66 #include <Quickdraw.h>
67 #include <ToolUtils.h>
68 #include <Sound.h>
69 #include <Events.h>
70 #include <Script.h>
71 #include <Resources.h>
72 #include <Fonts.h>
73 #include <TextUtils.h>
74 #include <LowMem.h>
75 #include <Controls.h>
76 #if defined (__MRC__) || (__MSL__ >= 0x6000)
77 #include <ControlDefinitions.h>
78 #endif
79 #include <Gestalt.h>
80
81 #if __profile__
82 #include <profiler.h>
83 #endif
84 #endif /* not MAC_OSX */
85
86 #include "systty.h"
87 #include "systime.h"
88 #include "atimer.h"
89 #include "keymap.h"
90
91 #include <ctype.h>
92 #include <errno.h>
93 #include <setjmp.h>
94 #include <sys/stat.h>
95
96 #include "keyboard.h"
97 #include "frame.h"
98 #include "dispextern.h"
99 #include "fontset.h"
100 #include "termhooks.h"
101 #include "termopts.h"
102 #include "termchar.h"
103 #include "gnu.h"
104 #include "disptab.h"
105 #include "buffer.h"
106 #include "window.h"
107 #include "intervals.h"
108 #include "composite.h"
109 #include "coding.h"
110
111 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
112
113 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
114 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
115 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
116 #define macShiftKey (shiftKey)
117 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
118 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
119 : controlKey)
120 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
121
122 \f
123 /* Fringe bitmaps. */
124
125 enum fringe_bitmap_type
126 {
127 NO_FRINGE_BITMAP,
128 LEFT_TRUNCATION_BITMAP,
129 RIGHT_TRUNCATION_BITMAP,
130 OVERLAY_ARROW_BITMAP,
131 CONTINUED_LINE_BITMAP,
132 CONTINUATION_LINE_BITMAP,
133 ZV_LINE_BITMAP
134 };
135
136 /* Bitmap drawn to indicate lines not displaying text if
137 `indicate-empty-lines' is non-nil. */
138
139 #define zv_width 8
140 #define zv_height 72
141 #define zv_period 3
142 static unsigned char zv_bits[] = {
143 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
144 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
145 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
146 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
147 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
148 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
149 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
150 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
151
152 /* An arrow like this: `<-'. */
153
154 #define left_width 8
155 #define left_height 8
156 static unsigned char left_bits[] = {
157 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
158
159 /* Right truncation arrow bitmap `->'. */
160
161 #define right_width 8
162 #define right_height 8
163 static unsigned char right_bits[] = {
164 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
165
166 /* Marker for continued lines. */
167
168 #define continued_width 8
169 #define continued_height 8
170 static unsigned char continued_bits[] = {
171 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
172
173 /* Marker for continuation lines. */
174
175 #define continuation_width 8
176 #define continuation_height 8
177 static unsigned char continuation_bits[] = {
178 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
179
180 /* Overlay arrow bitmap. */
181
182 #if 0
183 /* A bomb. */
184 #define ov_width 8
185 #define ov_height 8
186 static unsigned char ov_bits[] = {
187 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
188 #else
189 /* A triangular arrow. */
190 #define ov_width 8
191 #define ov_height 8
192 static unsigned char ov_bits[] = {
193 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
194 #endif
195
196 extern Lisp_Object Qhelp_echo;
197
198 \f
199 /* Non-nil means Emacs uses toolkit scroll bars. */
200
201 Lisp_Object Vx_toolkit_scroll_bars;
202
203 /* If a string, XTread_socket generates an event to display that string.
204 (The display is done in read_char.) */
205
206 static Lisp_Object help_echo;
207 static Lisp_Object help_echo_window;
208 static Lisp_Object help_echo_object;
209 static int help_echo_pos;
210
211 /* Temporary variable for XTread_socket. */
212
213 static Lisp_Object previous_help_echo;
214
215 /* Non-zero means that a HELP_EVENT has been generated since Emacs
216 start. */
217
218 static int any_help_event_p;
219
220 /* Non-zero means autoselect window with the mouse cursor. */
221
222 int x_autoselect_window_p;
223
224 /* Non-zero means draw block and hollow cursor as wide as the glyph
225 under it. For example, if a block cursor is over a tab, it will be
226 drawn as wide as that tab on the display. */
227
228 int x_stretch_cursor_p;
229
230 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
231
232 int x_use_underline_position_properties;
233
234 /* This is a chain of structures for all the X displays currently in
235 use. */
236
237 struct x_display_info *x_display_list;
238
239 /* This is a list of cons cells, each of the form (NAME
240 . FONT-LIST-CACHE), one for each element of x_display_list and in
241 the same order. NAME is the name of the frame. FONT-LIST-CACHE
242 records previous values returned by x-list-fonts. */
243
244 Lisp_Object x_display_name_list;
245
246 /* This is display since Mac does not support multiple ones. */
247 struct mac_display_info one_mac_display_info;
248
249 /* Frame being updated by update_frame. This is declared in term.c.
250 This is set by update_begin and looked at by all the XT functions.
251 It is zero while not inside an update. In that case, the XT
252 functions assume that `selected_frame' is the frame to apply to. */
253
254 extern struct frame *updating_frame;
255
256 extern int waiting_for_input;
257
258 /* This is a frame waiting to be auto-raised, within XTread_socket. */
259
260 struct frame *pending_autoraise_frame;
261
262 /* Nominal cursor position -- where to draw output.
263 HPOS and VPOS are window relative glyph matrix coordinates.
264 X and Y are window relative pixel coordinates. */
265
266 struct cursor_pos output_cursor;
267
268 /* Non-zero means user is interacting with a toolkit scroll bar. */
269
270 static int toolkit_scroll_bar_interaction;
271
272 /* Mouse movement.
273
274 Formerly, we used PointerMotionHintMask (in standard_event_mask)
275 so that we would have to call XQueryPointer after each MotionNotify
276 event to ask for another such event. However, this made mouse tracking
277 slow, and there was a bug that made it eventually stop.
278
279 Simply asking for MotionNotify all the time seems to work better.
280
281 In order to avoid asking for motion events and then throwing most
282 of them away or busy-polling the server for mouse positions, we ask
283 the server for pointer motion hints. This means that we get only
284 one event per group of mouse movements. "Groups" are delimited by
285 other kinds of events (focus changes and button clicks, for
286 example), or by XQueryPointer calls; when one of these happens, we
287 get another MotionNotify event the next time the mouse moves. This
288 is at least as efficient as getting motion events when mouse
289 tracking is on, and I suspect only negligibly worse when tracking
290 is off. */
291
292 /* Where the mouse was last time we reported a mouse event. */
293
294 FRAME_PTR last_mouse_frame;
295 static Rect last_mouse_glyph;
296 static Lisp_Object last_mouse_press_frame;
297
298 /* The scroll bar in which the last X motion event occurred.
299
300 If the last X motion event occurred in a scroll bar, we set this so
301 XTmouse_position can know whether to report a scroll bar motion or
302 an ordinary motion.
303
304 If the last X motion event didn't occur in a scroll bar, we set
305 this to Qnil, to tell XTmouse_position to return an ordinary motion
306 event. */
307
308 static Lisp_Object last_mouse_scroll_bar;
309
310 /* This is a hack. We would really prefer that XTmouse_position would
311 return the time associated with the position it returns, but there
312 doesn't seem to be any way to wrest the time-stamp from the server
313 along with the position query. So, we just keep track of the time
314 of the last movement we received, and return that in hopes that
315 it's somewhat accurate. */
316
317 static Time last_mouse_movement_time;
318
319 enum mouse_tracking_type {
320 mouse_tracking_none,
321 mouse_tracking_mouse_movement,
322 mouse_tracking_scroll_bar
323 };
324
325 enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
326
327 struct scroll_bar *tracked_scroll_bar = NULL;
328
329 /* Incremented by XTread_socket whenever it really tries to read
330 events. */
331
332 #ifdef __STDC__
333 static int volatile input_signal_count;
334 #else
335 static int input_signal_count;
336 #endif
337
338 /* Used locally within XTread_socket. */
339
340 static int x_noop_count;
341
342 /* Initial values of argv and argc. */
343
344 extern char **initial_argv;
345 extern int initial_argc;
346
347 extern Lisp_Object Vcommand_line_args, Vsystem_name;
348
349 /* Tells if a window manager is present or not. */
350
351 extern Lisp_Object Vx_no_window_manager;
352
353 extern Lisp_Object Qface, Qmouse_face;
354
355 extern int errno;
356
357 /* A mask of extra modifier bits to put into every keyboard char. */
358
359 extern int extra_keyboard_modifiers;
360
361 static Lisp_Object Qvendor_specific_keysyms;
362
363 #if 0
364 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
365 #endif
366
367 extern Lisp_Object x_icon_type P_ ((struct frame *));
368
369 extern int inhibit_window_system;
370
371 #if __MRC__
372 QDGlobals qd; /* QuickDraw global information structure. */
373 #endif
374
375
376 /* Enumeration for overriding/changing the face to use for drawing
377 glyphs in x_draw_glyphs. */
378
379 enum draw_glyphs_face
380 {
381 DRAW_NORMAL_TEXT,
382 DRAW_INVERSE_VIDEO,
383 DRAW_CURSOR,
384 DRAW_MOUSE_FACE,
385 DRAW_IMAGE_RAISED,
386 DRAW_IMAGE_SUNKEN
387 };
388
389 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
390 struct mac_display_info *mac_display_info_for_display (Display *);
391 static void x_update_window_end P_ ((struct window *, int, int));
392 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
393 static int fast_find_position P_ ((struct window *, int, int *, int *,
394 int *, int *, Lisp_Object));
395 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
396 int *, int *, int *, int *, int));
397 static void set_output_cursor P_ ((struct cursor_pos *));
398 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
399 int *, int *, int *, int));
400 static void note_mode_line_highlight P_ ((struct window *, int, int));
401 static void note_mouse_highlight P_ ((struct frame *, int, int));
402 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
403 static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
404 static void show_mouse_face P_ ((struct x_display_info *,
405 enum draw_glyphs_face));
406 static int cursor_in_mouse_face_p P_ ((struct window *));
407 static int clear_mouse_face P_ ((struct mac_display_info *));
408 static int x_io_error_quitter P_ ((Display *));
409 int x_catch_errors P_ ((Display *));
410 void x_uncatch_errors P_ ((Display *, int));
411 void x_lower_frame P_ ((struct frame *));
412 void x_scroll_bar_clear P_ ((struct frame *));
413 int x_had_errors_p P_ ((Display *));
414 void x_wm_set_size_hint P_ ((struct frame *, long, int));
415 void x_raise_frame P_ ((struct frame *));
416 void x_set_window_size P_ ((struct frame *, int, int, int));
417 void x_wm_set_window_state P_ ((struct frame *, int));
418 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
419 void mac_initialize P_ ((void));
420 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
421 static int x_compute_min_glyph_bounds P_ ((struct frame *));
422 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 static int is_emacs_window (WindowPtr);
478
479 extern int image_ascent (struct image *, struct face *);
480 void x_set_offset (struct frame *, int, int, int);
481 int x_bitmap_icon (struct frame *, Lisp_Object);
482 void x_make_frame_visible (struct frame *);
483
484 extern void window_scroll (Lisp_Object, int, int, int);
485
486 /* Defined in macmenu.h. */
487 extern void menubar_selection_callback (FRAME_PTR, int);
488 extern void set_frame_menubar (FRAME_PTR, int, int);
489
490 /* X display function emulation */
491
492 /* Structure borrowed from Xlib.h to represent two-byte characters in
493 dumpglyphs. */
494
495 typedef struct {
496 unsigned char byte1;
497 unsigned char byte2;
498 } XChar2b;
499
500 static void
501 XFreePixmap (display, pixmap)
502 Display *display;
503 Pixmap pixmap;
504 {
505 PixMap *p = (PixMap *) pixmap;
506
507 xfree (p->baseAddr);
508 xfree (p);
509 }
510
511
512 /* Set foreground color for subsequent QuickDraw commands. Assume
513 graphic port has already been set. */
514
515 static void
516 mac_set_forecolor (unsigned long color)
517 {
518 RGBColor fg_color;
519
520 fg_color.red = RED_FROM_ULONG (color) * 256;
521 fg_color.green = GREEN_FROM_ULONG (color) * 256;
522 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
523
524 RGBForeColor (&fg_color);
525 }
526
527
528 /* Set background color for subsequent QuickDraw commands. Assume
529 graphic port has already been set. */
530
531 static void
532 mac_set_backcolor (unsigned long color)
533 {
534 RGBColor bg_color;
535
536 bg_color.red = RED_FROM_ULONG (color) * 256;
537 bg_color.green = GREEN_FROM_ULONG (color) * 256;
538 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
539
540 RGBBackColor (&bg_color);
541 }
542
543 /* Set foreground and background color for subsequent QuickDraw
544 commands. Assume that the graphic port has already been set. */
545
546 static void
547 mac_set_colors (GC gc)
548 {
549 mac_set_forecolor (gc->foreground);
550 mac_set_backcolor (gc->background);
551 }
552
553 /* Mac version of XDrawLine. */
554
555 static void
556 XDrawLine (display, w, gc, x1, y1, x2, y2)
557 Display *display;
558 WindowPtr w;
559 GC gc;
560 int x1, y1, x2, y2;
561 {
562 #if TARGET_API_MAC_CARBON
563 SetPort (GetWindowPort (w));
564 #else
565 SetPort (w);
566 #endif
567
568 mac_set_colors (gc);
569
570 MoveTo (x1, y1);
571 LineTo (x2, y2);
572 }
573
574 /* Mac version of XClearArea. */
575
576 void
577 XClearArea (display, w, x, y, width, height, exposures)
578 Display *display;
579 WindowPtr w;
580 int x, y;
581 unsigned int width, height;
582 int exposures;
583 {
584 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
585 Rect r;
586 XGCValues xgc;
587
588 xgc.foreground = mwp->x_compatible.foreground_pixel;
589 xgc.background = mwp->x_compatible.background_pixel;
590
591 #if TARGET_API_MAC_CARBON
592 SetPort (GetWindowPort (w));
593 #else
594 SetPort (w);
595 #endif
596
597 mac_set_colors (&xgc);
598 SetRect (&r, x, y, x + width, y + height);
599
600 EraseRect (&r);
601 }
602
603 /* Mac version of XClearWindow. */
604
605 static void
606 XClearWindow (display, w)
607 Display *display;
608 WindowPtr w;
609 {
610 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
611 XGCValues xgc;
612
613 xgc.foreground = mwp->x_compatible.foreground_pixel;
614 xgc.background = mwp->x_compatible.background_pixel;
615
616 #if TARGET_API_MAC_CARBON
617 SetPort (GetWindowPort (w));
618 #else
619 SetPort (w);
620 #endif
621
622 mac_set_colors (&xgc);
623
624 #if TARGET_API_MAC_CARBON
625 {
626 Rect r;
627
628 GetWindowPortBounds (w, &r);
629 EraseRect (&r);
630 }
631 #else /* not TARGET_API_MAC_CARBON */
632 EraseRect (&(w->portRect));
633 #endif /* not TARGET_API_MAC_CARBON */
634 }
635
636
637 /* Mac replacement for XCopyArea. */
638
639 static void
640 mac_draw_bitmap (display, w, gc, x, y, bitmap)
641 Display *display;
642 WindowPtr w;
643 GC gc;
644 int x, y;
645 BitMap *bitmap;
646 {
647 Rect r;
648
649 #if TARGET_API_MAC_CARBON
650 SetPort (GetWindowPort (w));
651 #else
652 SetPort (w);
653 #endif
654
655 mac_set_colors (gc);
656 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
657
658 #if TARGET_API_MAC_CARBON
659 {
660 PixMapHandle pmh;
661
662 LockPortBits (GetWindowPort (w));
663 pmh = GetPortPixMap (GetWindowPort (w));
664 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
665 UnlockPortBits (GetWindowPort (w));
666 }
667 #else /* not TARGET_API_MAC_CARBON */
668 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
669 #endif /* not TARGET_API_MAC_CARBON */
670 }
671
672
673 /* Mac replacement for XSetClipRectangles. */
674
675 static void
676 mac_set_clip_rectangle (display, w, r)
677 Display *display;
678 WindowPtr w;
679 Rect *r;
680 {
681 #if TARGET_API_MAC_CARBON
682 SetPort (GetWindowPort (w));
683 #else
684 SetPort (w);
685 #endif
686
687 ClipRect (r);
688 }
689
690
691 /* Mac replacement for XSetClipMask. */
692
693 static void
694 mac_reset_clipping (display, w)
695 Display *display;
696 WindowPtr w;
697 {
698 Rect r;
699
700 #if TARGET_API_MAC_CARBON
701 SetPort (GetWindowPort (w));
702 #else
703 SetPort (w);
704 #endif
705
706 SetRect (&r, -32767, -32767, 32767, 32767);
707 ClipRect (&r);
708 }
709
710
711 /* Mac replacement for XCreateBitmapFromBitmapData. */
712
713 static void
714 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
715 BitMap *bitmap;
716 char *bits;
717 int w, h;
718 {
719 int bytes_per_row, i, j;
720
721 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
722 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
723 if (!bitmap->baseAddr)
724 abort ();
725
726 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
727 for (i = 0; i < h; i++)
728 for (j = 0; j < w; j++)
729 if (BitTst (bits, i * w + j))
730 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
731
732 SetRect (&(bitmap->bounds), 0, 0, w, h);
733 }
734
735
736 static void
737 mac_free_bitmap (bitmap)
738 BitMap *bitmap;
739 {
740 xfree (bitmap->baseAddr);
741 }
742
743 /* Mac replacement for XFillRectangle. */
744
745 static void
746 XFillRectangle (display, w, gc, x, y, width, height)
747 Display *display;
748 WindowPtr w;
749 GC gc;
750 int x, y;
751 unsigned int width, height;
752 {
753 Rect r;
754
755 #if TARGET_API_MAC_CARBON
756 SetPort (GetWindowPort (w));
757 #else
758 SetPort (w);
759 #endif
760
761 mac_set_colors (gc);
762 SetRect (&r, x, y, x + width, y + height);
763
764 PaintRect (&r); /* using foreground color of gc */
765 }
766
767
768 /* Mac replacement for XDrawRectangle: dest is a window. */
769
770 static void
771 mac_draw_rectangle (display, w, gc, x, y, width, height)
772 Display *display;
773 WindowPtr w;
774 GC gc;
775 int x, y;
776 unsigned int width, height;
777 {
778 Rect r;
779
780 #if TARGET_API_MAC_CARBON
781 SetPort (GetWindowPort (w));
782 #else
783 SetPort (w);
784 #endif
785
786 mac_set_colors (gc);
787 SetRect (&r, x, y, x + width + 1, y + height + 1);
788
789 FrameRect (&r); /* using foreground color of gc */
790 }
791
792
793 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
794
795 static void
796 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
797 Display *display;
798 Pixmap p;
799 GC gc;
800 int x, y;
801 unsigned int width, height;
802 {
803 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
804 Rect r;
805
806 #if TARGET_API_MAC_CARBON
807 SetPort (GetWindowPort (w));
808 #else
809 SetPort (w);
810 #endif
811
812 mac_set_colors (gc);
813 SetRect (&r, x, y, x + width, y + height);
814
815 FrameRect (&r); /* using foreground color of gc */
816 #endif /* 0 */
817 }
818
819
820 static void
821 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
822 bytes_per_char)
823 Display *display;
824 WindowPtr w;
825 GC gc;
826 int x, y;
827 char *buf;
828 int nchars, mode, bytes_per_char;
829 {
830 #if TARGET_API_MAC_CARBON
831 SetPort (GetWindowPort (w));
832 #else
833 SetPort (w);
834 #endif
835
836 mac_set_colors (gc);
837
838 TextFont (gc->font->mac_fontnum);
839 TextSize (gc->font->mac_fontsize);
840 TextFace (gc->font->mac_fontface);
841 TextMode (mode);
842
843 MoveTo (x, y);
844 DrawText (buf, 0, nchars * bytes_per_char);
845 }
846
847
848 /* Mac replacement for XDrawString. */
849
850 static void
851 XDrawString (display, w, gc, x, y, buf, nchars)
852 Display *display;
853 WindowPtr w;
854 GC gc;
855 int x, y;
856 char *buf;
857 int nchars;
858 {
859 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
860 }
861
862
863 /* Mac replacement for XDrawString16. */
864
865 static void
866 XDrawString16 (display, w, gc, x, y, buf, nchars)
867 Display *display;
868 WindowPtr w;
869 GC gc;
870 int x, y;
871 XChar2b *buf;
872 int nchars;
873 {
874 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
875 2);
876 }
877
878
879 /* Mac replacement for XDrawImageString. */
880
881 static void
882 XDrawImageString (display, w, gc, x, y, buf, nchars)
883 Display *display;
884 WindowPtr w;
885 GC gc;
886 int x, y;
887 char *buf;
888 int nchars;
889 {
890 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
891 }
892
893
894 /* Mac replacement for XDrawString16. */
895
896 static void
897 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
898 Display *display;
899 WindowPtr w;
900 GC gc;
901 int x, y;
902 XChar2b *buf;
903 int nchars;
904 {
905 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
906 2);
907 }
908
909
910 /* Mac replacement for XCopyArea: dest must be window. */
911
912 static void
913 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
914 dest_y)
915 Display *display;
916 Pixmap src;
917 WindowPtr dest;
918 GC gc;
919 int src_x, src_y;
920 unsigned int width, height;
921 int dest_x, dest_y;
922 {
923 Rect src_r, dest_r;
924
925 #if TARGET_API_MAC_CARBON
926 SetPort (GetWindowPort (dest));
927 #else
928 SetPort (dest);
929 #endif
930
931 mac_set_colors (gc);
932
933 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
934 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
935
936 #if TARGET_API_MAC_CARBON
937 {
938 PixMapHandle pmh;
939
940 LockPortBits (GetWindowPort (dest));
941 pmh = GetPortPixMap (GetWindowPort (dest));
942 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
943 UnlockPortBits (GetWindowPort (dest));
944 }
945 #else /* not TARGET_API_MAC_CARBON */
946 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
947 #endif /* not TARGET_API_MAC_CARBON */
948 }
949
950
951 #if 0
952 /* Convert a pair of local coordinates to global (screen) coordinates.
953 Assume graphic port has been properly set. */
954 static void
955 local_to_global_coord (short *h, short *v)
956 {
957 Point p;
958
959 p.h = *h;
960 p.v = *v;
961
962 LocalToGlobal (&p);
963
964 *h = p.h;
965 *v = p.v;
966 }
967 #endif
968
969 /* Mac replacement for XCopyArea: used only for scrolling. */
970
971 static void
972 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
973 Display *display;
974 WindowPtr w;
975 GC gc;
976 int src_x, src_y;
977 unsigned int width, height;
978 int dest_x, dest_y;
979 {
980 #if TARGET_API_MAC_CARBON
981 Rect gw_r, src_r, dest_r;
982 PixMapHandle pmh;
983
984 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
985 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
986
987 SetPort (GetWindowPort (w));
988
989 ForeColor (blackColor);
990 BackColor (whiteColor);
991
992 LockPortBits (GetWindowPort (w));
993 pmh = GetPortPixMap (GetWindowPort (w));
994 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
995 UnlockPortBits (GetWindowPort (w));
996
997 mac_set_colors (gc);
998 #else /* not TARGET_API_MAC_CARBON */
999 Rect src_r, dest_r;
1000
1001 SetPort (w);
1002 #if 0
1003 mac_set_colors (gc);
1004 #endif
1005
1006 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1007 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1008
1009 #if 0
1010 /* Need to use global coordinates and screenBits since src and dest
1011 areas overlap in general. */
1012 local_to_global_coord (&src_r.left, &src_r.top);
1013 local_to_global_coord (&src_r.right, &src_r.bottom);
1014 local_to_global_coord (&dest_r.left, &dest_r.top);
1015 local_to_global_coord (&dest_r.right, &dest_r.bottom);
1016
1017 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
1018 #else
1019 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1020 color mapping in CopyBits. Otherwise, it will be slow. */
1021 ForeColor (blackColor);
1022 BackColor (whiteColor);
1023 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1024
1025 mac_set_colors (gc);
1026 #endif
1027 #endif /* not TARGET_API_MAC_CARBON */
1028 }
1029
1030
1031 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1032
1033 static void
1034 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1035 dest_x, dest_y)
1036 Display *display;
1037 Pixmap src;
1038 Pixmap dest;
1039 GC gc;
1040 int src_x, src_y;
1041 unsigned int width, height;
1042 int dest_x, dest_y;
1043 {
1044 Rect src_r, dest_r;
1045 int src_right = ((PixMap *) src)->bounds.right;
1046 int src_bottom = ((PixMap *) src)->bounds.bottom;
1047 int w = src_right - src_x;
1048 int h = src_bottom - src_y;
1049
1050 mac_set_colors (gc);
1051
1052 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1053 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1054
1055 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1056 }
1057
1058
1059 /* Mac replacement for XChangeGC. */
1060
1061 static void
1062 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1063 XGCValues *xgcv)
1064 {
1065 if (mask & GCForeground)
1066 gc->foreground = xgcv->foreground;
1067 if (mask & GCBackground)
1068 gc->background = xgcv->background;
1069 if (mask & GCFont)
1070 gc->font = xgcv->font;
1071 }
1072
1073
1074 /* Mac replacement for XCreateGC. */
1075
1076 XGCValues *
1077 XCreateGC (void * ignore, Window window, unsigned long mask,
1078 XGCValues *xgcv)
1079 {
1080 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1081 bzero (gc, sizeof (XGCValues));
1082
1083 XChangeGC (ignore, gc, mask, xgcv);
1084
1085 return gc;
1086 }
1087
1088
1089 /* Used in xfaces.c. */
1090
1091 void
1092 XFreeGC (display, gc)
1093 Display *display;
1094 GC gc;
1095 {
1096 xfree (gc);
1097 }
1098
1099
1100 /* Mac replacement for XGetGCValues. */
1101
1102 static void
1103 XGetGCValues (void* ignore, XGCValues *gc,
1104 unsigned long mask, XGCValues *xgcv)
1105 {
1106 XChangeGC (ignore, xgcv, mask, gc);
1107 }
1108
1109
1110 /* Mac replacement for XSetForeground. */
1111
1112 static void
1113 XSetForeground (display, gc, color)
1114 Display *display;
1115 GC gc;
1116 unsigned long color;
1117 {
1118 gc->foreground = color;
1119 }
1120
1121
1122 /* Mac replacement for XSetFont. */
1123
1124 static void
1125 XSetFont (display, gc, font)
1126 Display *display;
1127 GC gc;
1128 XFontStruct *font;
1129 {
1130 gc->font = font;
1131 }
1132
1133
1134 static void
1135 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1136 int *direction,int *font_ascent,
1137 int *font_descent, XCharStruct *cs)
1138 {
1139 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1140 }
1141
1142
1143 /* x_sync is a no-op on Mac. */
1144 void
1145 x_sync (f)
1146 void *f;
1147 {
1148 }
1149
1150
1151 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1152 Calls to XFlush should be unnecessary because the X output buffer
1153 is flushed automatically as needed by calls to XPending,
1154 XNextEvent, or XWindowEvent according to the XFlush man page.
1155 XTread_socket calls XPending. Removing XFlush improves
1156 performance. */
1157
1158 #if TARGET_API_MAC_CARBON
1159 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1160 #else
1161 #define XFlush(DISPLAY) (void) 0
1162 #endif
1163
1164 /* Flush display of frame F, or of all frames if F is null. */
1165
1166 void
1167 x_flush (f)
1168 struct frame *f;
1169 {
1170 #if TARGET_API_MAC_CARBON
1171 BLOCK_INPUT;
1172 if (f == NULL)
1173 {
1174 Lisp_Object rest, frame;
1175 FOR_EACH_FRAME (rest, frame)
1176 x_flush (XFRAME (frame));
1177 }
1178 else if (FRAME_X_P (f))
1179 XFlush (FRAME_MAC_DISPLAY (f));
1180 UNBLOCK_INPUT;
1181 #endif /* TARGET_API_MAC_CARBON */
1182 }
1183
1184
1185 \f
1186 /* Return the struct mac_display_info corresponding to DPY. There's
1187 only one. */
1188
1189 struct mac_display_info *
1190 mac_display_info_for_display (dpy)
1191 Display *dpy;
1192 {
1193 return &one_mac_display_info;
1194 }
1195
1196
1197 \f
1198 /***********************************************************************
1199 Starting and ending an update
1200 ***********************************************************************/
1201
1202 /* Start an update of frame F. This function is installed as a hook
1203 for update_begin, i.e. it is called when update_begin is called.
1204 This function is called prior to calls to x_update_window_begin for
1205 each window being updated. */
1206
1207 static void
1208 x_update_begin (f)
1209 struct frame *f;
1210 {
1211 /* Nothing to do. */
1212 }
1213
1214
1215 /* Start update of window W. Set the global variable updated_window
1216 to the window being updated and set output_cursor to the cursor
1217 position of W. */
1218
1219 static void
1220 x_update_window_begin (w)
1221 struct window *w;
1222 {
1223 struct frame *f = XFRAME (WINDOW_FRAME (w));
1224 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1225
1226 updated_window = w;
1227 set_output_cursor (&w->cursor);
1228
1229 BLOCK_INPUT;
1230
1231 if (f == display_info->mouse_face_mouse_frame)
1232 {
1233 /* Don't do highlighting for mouse motion during the update. */
1234 display_info->mouse_face_defer = 1;
1235
1236 /* If F needs to be redrawn, simply forget about any prior mouse
1237 highlighting. */
1238 if (FRAME_GARBAGED_P (f))
1239 display_info->mouse_face_window = Qnil;
1240
1241 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1242 their mouse_face_p flag set, which means that they are always
1243 unequal to rows in a desired matrix which never have that
1244 flag set. So, rows containing mouse-face glyphs are never
1245 scrolled, and we don't have to switch the mouse highlight off
1246 here to prevent it from being scrolled. */
1247
1248 /* Can we tell that this update does not affect the window
1249 where the mouse highlight is? If so, no need to turn off.
1250 Likewise, don't do anything if the frame is garbaged;
1251 in that case, the frame's current matrix that we would use
1252 is all wrong, and we will redisplay that line anyway. */
1253 if (!NILP (display_info->mouse_face_window)
1254 && w == XWINDOW (display_info->mouse_face_window))
1255 {
1256 int i;
1257
1258 for (i = 0; i < w->desired_matrix->nrows; ++i)
1259 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1260 break;
1261
1262 if (i < w->desired_matrix->nrows)
1263 clear_mouse_face (display_info);
1264 }
1265 #endif /* 0 */
1266 }
1267
1268 UNBLOCK_INPUT;
1269 }
1270
1271
1272 /* Draw a vertical window border to the right of window W if W doesn't
1273 have vertical scroll bars. */
1274
1275 static void
1276 x_draw_vertical_border (w)
1277 struct window *w;
1278 {
1279 struct frame *f = XFRAME (WINDOW_FRAME (w));
1280
1281 /* Redraw borders between horizontally adjacent windows. Don't
1282 do it for frames with vertical scroll bars because either the
1283 right scroll bar of a window, or the left scroll bar of its
1284 neighbor will suffice as a border. */
1285 if (!WINDOW_RIGHTMOST_P (w)
1286 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1287 {
1288 int x0, x1, y0, y1;
1289
1290 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1291 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1292 y1 -= 1;
1293
1294 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1295 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1296 }
1297 }
1298
1299
1300 /* End update of window W (which is equal to updated_window).
1301
1302 Draw vertical borders between horizontally adjacent windows, and
1303 display W's cursor if CURSOR_ON_P is non-zero.
1304
1305 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1306 glyphs in mouse-face were overwritten. In that case we have to
1307 make sure that the mouse-highlight is properly redrawn.
1308
1309 W may be a menu bar pseudo-window in case we don't have X toolkit
1310 support. Such windows don't have a cursor, so don't display it
1311 here. */
1312
1313 static void
1314 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1315 struct window *w;
1316 int cursor_on_p, mouse_face_overwritten_p;
1317 {
1318 struct mac_display_info *dpyinfo
1319 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1320
1321 if (!w->pseudo_window_p)
1322 {
1323 BLOCK_INPUT;
1324
1325 if (cursor_on_p)
1326 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1327 output_cursor.vpos,
1328 output_cursor.x, output_cursor.y);
1329
1330 x_draw_vertical_border (w);
1331 UNBLOCK_INPUT;
1332 }
1333
1334 /* If a row with mouse-face was overwritten, arrange for
1335 XTframe_up_to_date to redisplay the mouse highlight. */
1336 if (mouse_face_overwritten_p)
1337 {
1338 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1339 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1340 dpyinfo->mouse_face_window = Qnil;
1341 }
1342
1343 #if 0
1344 /* Unhide the caret. This won't actually show the cursor, unless it
1345 was visible before the corresponding call to HideCaret in
1346 x_update_window_begin. */
1347 if (w32_use_visible_system_caret)
1348 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1349 #endif
1350
1351 updated_window = NULL;
1352 }
1353
1354
1355 /* End update of frame F. This function is installed as a hook in
1356 update_end. */
1357
1358 static void
1359 x_update_end (f)
1360 struct frame *f;
1361 {
1362 /* Reset the background color of Mac OS Window to that of the frame after
1363 update so that it is used by Mac Toolbox to clear the update region before
1364 an update event is generated. */
1365 #if TARGET_API_MAC_CARBON
1366 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1367 #else
1368 SetPort (FRAME_MAC_WINDOW (f));
1369 #endif
1370
1371 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1372
1373 /* Mouse highlight may be displayed again. */
1374 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1375
1376 BLOCK_INPUT;
1377 XFlush (FRAME_MAC_DISPLAY (f));
1378 UNBLOCK_INPUT;
1379 }
1380
1381
1382 /* This function is called from various places in xdisp.c whenever a
1383 complete update has been performed. The global variable
1384 updated_window is not available here. */
1385
1386 static void
1387 XTframe_up_to_date (f)
1388 struct frame *f;
1389 {
1390 if (FRAME_X_P (f))
1391 {
1392 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1393
1394 if (dpyinfo->mouse_face_deferred_gc
1395 || f == dpyinfo->mouse_face_mouse_frame)
1396 {
1397 BLOCK_INPUT;
1398 if (dpyinfo->mouse_face_mouse_frame)
1399 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1400 dpyinfo->mouse_face_mouse_x,
1401 dpyinfo->mouse_face_mouse_y);
1402 dpyinfo->mouse_face_deferred_gc = 0;
1403 UNBLOCK_INPUT;
1404 }
1405 }
1406 }
1407
1408
1409 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1410 arrow bitmaps, or clear the fringes if no bitmaps are required
1411 before DESIRED_ROW is made current. The window being updated is
1412 found in updated_window. This function is called from
1413 update_window_line only if it is known that there are differences
1414 between bitmaps to be drawn between current row and DESIRED_ROW. */
1415
1416 static void
1417 x_after_update_window_line (desired_row)
1418 struct glyph_row *desired_row;
1419 {
1420 struct window *w = updated_window;
1421 struct frame *f;
1422 int width, height;
1423
1424 xassert (w);
1425
1426 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1427 {
1428 BLOCK_INPUT;
1429 x_draw_row_fringe_bitmaps (w, desired_row);
1430 UNBLOCK_INPUT;
1431 }
1432
1433 /* When a window has disappeared, make sure that no rest of
1434 full-width rows stays visible in the internal border. Could
1435 check here if updated_window is the leftmost/rightmost window,
1436 but I guess it's not worth doing since vertically split windows
1437 are almost never used, internal border is rarely set, and the
1438 overhead is very small. */
1439 if (windows_or_buffers_changed
1440 && desired_row->full_width_p
1441 && (f = XFRAME (w->frame),
1442 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1443 width != 0)
1444 && (height = desired_row->visible_height,
1445 height > 0))
1446 {
1447 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1448 /* Internal border is drawn below the tool bar. */
1449 if (WINDOWP (f->tool_bar_window)
1450 && w == XWINDOW (f->tool_bar_window))
1451 y -= width;
1452
1453 BLOCK_INPUT;
1454
1455 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1456 0, y, width, height, 0);
1457 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1458 f->output_data.mac->pixel_width - width, y,
1459 width, height, 0);
1460
1461 UNBLOCK_INPUT;
1462 }
1463 }
1464
1465
1466 /* Draw the bitmap WHICH in one of the left or right fringes of
1467 window W. ROW is the glyph row for which to display the bitmap; it
1468 determines the vertical position at which the bitmap has to be
1469 drawn. */
1470
1471 static void
1472 x_draw_fringe_bitmap (w, row, which, left_p)
1473 struct window *w;
1474 struct glyph_row *row;
1475 enum fringe_bitmap_type which;
1476 int left_p;
1477 {
1478 struct frame *f = XFRAME (WINDOW_FRAME (w));
1479 Display *display = FRAME_MAC_DISPLAY (f);
1480 WindowPtr window = FRAME_MAC_WINDOW (f);
1481 int x, y, wd, h, dy;
1482 int b1, b2;
1483 unsigned char *bits;
1484 BitMap bitmap;
1485 XGCValues gcv;
1486 GC gc = f->output_data.mac->normal_gc;
1487 struct face *face;
1488
1489 /* Must clip because of partially visible lines. */
1490 x_clip_to_row (w, row, gc, 1);
1491
1492 /* Convert row to frame coordinates. */
1493 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1494
1495 switch (which)
1496 {
1497 case NO_FRINGE_BITMAP:
1498 wd = 0;
1499 h = 0;
1500 break;
1501
1502 case LEFT_TRUNCATION_BITMAP:
1503 wd = left_width;
1504 h = left_height;
1505 bits = left_bits;
1506 break;
1507
1508 case OVERLAY_ARROW_BITMAP:
1509 wd = ov_width;
1510 h = ov_height;
1511 bits = ov_bits;
1512 break;
1513
1514 case RIGHT_TRUNCATION_BITMAP:
1515 wd = right_width;
1516 h = right_height;
1517 bits = right_bits;
1518 break;
1519
1520 case CONTINUED_LINE_BITMAP:
1521 wd = continued_width;
1522 h = continued_height;
1523 bits = continued_bits;
1524 break;
1525
1526 case CONTINUATION_LINE_BITMAP:
1527 wd = continuation_width;
1528 h = continuation_height;
1529 bits = continuation_bits;
1530 break;
1531
1532 case ZV_LINE_BITMAP:
1533 wd = zv_width;
1534 h = zv_height - (y % zv_period);
1535 bits = zv_bits + (y % zv_period);
1536 break;
1537
1538 default:
1539 abort ();
1540 }
1541
1542 /* Clip bitmap if too high. */
1543 if (h > row->height)
1544 h = row->height;
1545
1546 /* Set dy to the offset in the row to start drawing the bitmap. */
1547 dy = (row->height - h) / 2;
1548
1549 /* Draw the bitmap. */
1550 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
1551 PREPARE_FACE_FOR_DISPLAY (f, face);
1552
1553 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1554 the fringe. */
1555 b1 = -1;
1556 if (left_p)
1557 {
1558 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1559 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1560 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1561 - wd
1562 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1563 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1564 {
1565 /* If W has a vertical border to its left, don't draw over it. */
1566 int border = ((XFASTINT (w->left) > 0
1567 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1568 ? 1 : 0);
1569 b1 = (window_box_left (w, -1)
1570 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1571 + border);
1572 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1573 }
1574 }
1575 else
1576 {
1577 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1578 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1579 x = (window_box_right (w, -1)
1580 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1581 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1582 the fringe. */
1583 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1584 {
1585 b1 = window_box_right (w, -1);
1586 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1587 }
1588 }
1589
1590 if (b1 >= 0)
1591 {
1592 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1593 XGCValues gcv;
1594 gcv.foreground = face->background;
1595
1596 #if 0 /* MAC_TODO: stipple */
1597 /* In case the same realized face is used for fringes and
1598 for something displayed in the text (e.g. face `region' on
1599 mono-displays, the fill style may have been changed to
1600 FillSolid in x_draw_glyph_string_background. */
1601 if (face->stipple)
1602 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1603 else
1604 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1605 #endif
1606
1607 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1608 &gcv,
1609 b1,
1610 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1611 row->y)),
1612 b2,
1613 row->visible_height);
1614
1615 #if 0 /* MAC_TODO: stipple */
1616 if (!face->stipple)
1617 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1618 #endif
1619 }
1620
1621 if (which == NO_FRINGE_BITMAP)
1622 {
1623 mac_reset_clipping (display, window);
1624 return;
1625 }
1626
1627 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1628 gcv.foreground = face->foreground;
1629 gcv.background = face->background;
1630
1631 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1632
1633 mac_free_bitmap (&bitmap);
1634 mac_reset_clipping (display, window);
1635 }
1636
1637
1638 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1639 function with input blocked. */
1640
1641 static void
1642 x_draw_row_fringe_bitmaps (w, row)
1643 struct window *w;
1644 struct glyph_row *row;
1645 {
1646 struct frame *f = XFRAME (w->frame);
1647 enum fringe_bitmap_type bitmap;
1648
1649 xassert (interrupt_input_blocked);
1650
1651 /* If row is completely invisible, because of vscrolling, we
1652 don't have to draw anything. */
1653 if (row->visible_height <= 0)
1654 return;
1655
1656 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1657 {
1658 /* Decide which bitmap to draw in the left fringe. */
1659 if (row->overlay_arrow_p)
1660 bitmap = OVERLAY_ARROW_BITMAP;
1661 else if (row->truncated_on_left_p)
1662 bitmap = LEFT_TRUNCATION_BITMAP;
1663 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1664 bitmap = CONTINUATION_LINE_BITMAP;
1665 else if (row->indicate_empty_line_p)
1666 bitmap = ZV_LINE_BITMAP;
1667 else
1668 bitmap = NO_FRINGE_BITMAP;
1669
1670 x_draw_fringe_bitmap (w, row, bitmap, 1);
1671 }
1672
1673 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1674 {
1675 /* Decide which bitmap to draw in the right fringe. */
1676 if (row->truncated_on_right_p)
1677 bitmap = RIGHT_TRUNCATION_BITMAP;
1678 else if (row->continued_p)
1679 bitmap = CONTINUED_LINE_BITMAP;
1680 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1681 bitmap = ZV_LINE_BITMAP;
1682 else
1683 bitmap = NO_FRINGE_BITMAP;
1684
1685 x_draw_fringe_bitmap (w, row, bitmap, 0);
1686 }
1687 }
1688
1689 \f
1690 /* This is called when starting Emacs and when restarting after
1691 suspend. When starting Emacs, no window is mapped. And nothing
1692 must be done to Emacs's own window if it is suspended (though that
1693 rarely happens). */
1694
1695 static void
1696 XTset_terminal_modes ()
1697 {
1698 }
1699
1700 /* This is called when exiting or suspending Emacs. Exiting will make
1701 the windows go away, and suspending requires no action. */
1702
1703 static void
1704 XTreset_terminal_modes ()
1705 {
1706 }
1707
1708
1709 \f
1710 /***********************************************************************
1711 Output Cursor
1712 ***********************************************************************/
1713
1714 /* Set the global variable output_cursor to CURSOR. All cursor
1715 positions are relative to updated_window. */
1716
1717 static void
1718 set_output_cursor (cursor)
1719 struct cursor_pos *cursor;
1720 {
1721 output_cursor.hpos = cursor->hpos;
1722 output_cursor.vpos = cursor->vpos;
1723 output_cursor.x = cursor->x;
1724 output_cursor.y = cursor->y;
1725 }
1726
1727
1728 /* Set a nominal cursor position.
1729
1730 HPOS and VPOS are column/row positions in a window glyph matrix. X
1731 and Y are window text area relative pixel positions.
1732
1733 If this is done during an update, updated_window will contain the
1734 window that is being updated and the position is the future output
1735 cursor position for that window. If updated_window is null, use
1736 selected_window and display the cursor at the given position. */
1737
1738 static void
1739 XTcursor_to (vpos, hpos, y, x)
1740 int vpos, hpos, y, x;
1741 {
1742 struct window *w;
1743
1744 /* If updated_window is not set, work on selected_window. */
1745 if (updated_window)
1746 w = updated_window;
1747 else
1748 w = XWINDOW (selected_window);
1749
1750 /* Set the output cursor. */
1751 output_cursor.hpos = hpos;
1752 output_cursor.vpos = vpos;
1753 output_cursor.x = x;
1754 output_cursor.y = y;
1755
1756 /* If not called as part of an update, really display the cursor.
1757 This will also set the cursor position of W. */
1758 if (updated_window == NULL)
1759 {
1760 BLOCK_INPUT;
1761 x_display_cursor (w, 1, hpos, vpos, x, y);
1762 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1763 UNBLOCK_INPUT;
1764 }
1765 }
1766
1767
1768 \f
1769 /***********************************************************************
1770 Display Iterator
1771 ***********************************************************************/
1772
1773 /* Function prototypes of this page. */
1774
1775 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1776 struct glyph *,
1777 XChar2b *,
1778 int *));
1779 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1780 int, XChar2b *, int));
1781 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1782 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1783 static void x_append_glyph P_ ((struct it *));
1784 static void x_append_composite_glyph P_ ((struct it *));
1785 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1786 int, int, double));
1787 static void x_produce_glyphs P_ ((struct it *));
1788 static void x_produce_image_glyph P_ ((struct it *it));
1789
1790
1791 /* Return a pointer to per-char metric information in FONT of a
1792 character pointed by B which is a pointer to an XChar2b. */
1793
1794 #define PER_CHAR_METRIC(font, b) \
1795 ((font)->per_char \
1796 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1797 + (((font)->min_byte1 || (font)->max_byte1) \
1798 ? (((b)->byte1 - (font)->min_byte1) \
1799 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1800 : 0)) \
1801 : &((font)->max_bounds))
1802
1803
1804 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1805 is not contained in the font. */
1806
1807 static INLINE XCharStruct *
1808 x_per_char_metric (font, char2b)
1809 XFontStruct *font;
1810 XChar2b *char2b;
1811 {
1812 /* The result metric information. */
1813 XCharStruct *pcm = NULL;
1814
1815 xassert (font && char2b);
1816
1817 if (font->per_char != NULL)
1818 {
1819 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1820 {
1821 /* min_char_or_byte2 specifies the linear character index
1822 corresponding to the first element of the per_char array,
1823 max_char_or_byte2 is the index of the last character. A
1824 character with non-zero CHAR2B->byte1 is not in the font.
1825 A character with byte2 less than min_char_or_byte2 or
1826 greater max_char_or_byte2 is not in the font. */
1827 if (char2b->byte1 == 0
1828 && char2b->byte2 >= font->min_char_or_byte2
1829 && char2b->byte2 <= font->max_char_or_byte2)
1830 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1831 }
1832 else
1833 {
1834 /* If either min_byte1 or max_byte1 are nonzero, both
1835 min_char_or_byte2 and max_char_or_byte2 are less than
1836 256, and the 2-byte character index values corresponding
1837 to the per_char array element N (counting from 0) are:
1838
1839 byte1 = N/D + min_byte1
1840 byte2 = N\D + min_char_or_byte2
1841
1842 where:
1843
1844 D = max_char_or_byte2 - min_char_or_byte2 + 1
1845 / = integer division
1846 \ = integer modulus */
1847 if (char2b->byte1 >= font->min_byte1
1848 && char2b->byte1 <= font->max_byte1
1849 && char2b->byte2 >= font->min_char_or_byte2
1850 && char2b->byte2 <= font->max_char_or_byte2)
1851 {
1852 pcm = (font->per_char
1853 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1854 * (char2b->byte1 - font->min_byte1))
1855 + (char2b->byte2 - font->min_char_or_byte2));
1856 }
1857 }
1858 }
1859 else
1860 {
1861 /* If the per_char pointer is null, all glyphs between the first
1862 and last character indexes inclusive have the same
1863 information, as given by both min_bounds and max_bounds. */
1864 if (char2b->byte2 >= font->min_char_or_byte2
1865 && char2b->byte2 <= font->max_char_or_byte2)
1866 pcm = &font->max_bounds;
1867 }
1868
1869 return ((pcm == NULL
1870 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1871 ? NULL : pcm);
1872 }
1873
1874
1875 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1876 the two-byte form of C. Encoding is returned in *CHAR2B. */
1877
1878 static INLINE void
1879 x_encode_char (c, char2b, font_info)
1880 int c;
1881 XChar2b *char2b;
1882 struct font_info *font_info;
1883 {
1884 int charset = CHAR_CHARSET (c);
1885 XFontStruct *font = font_info->font;
1886
1887 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1888 This may be either a program in a special encoder language or a
1889 fixed encoding. */
1890 if (font_info->font_encoder)
1891 {
1892 /* It's a program. */
1893 struct ccl_program *ccl = font_info->font_encoder;
1894
1895 if (CHARSET_DIMENSION (charset) == 1)
1896 {
1897 ccl->reg[0] = charset;
1898 ccl->reg[1] = char2b->byte2;
1899 }
1900 else
1901 {
1902 ccl->reg[0] = charset;
1903 ccl->reg[1] = char2b->byte1;
1904 ccl->reg[2] = char2b->byte2;
1905 }
1906
1907 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1908
1909 /* We assume that MSBs are appropriately set/reset by CCL
1910 program. */
1911 if (font->max_byte1 == 0) /* 1-byte font */
1912 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1913 else
1914 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1915 }
1916 else if (font_info->encoding[charset])
1917 {
1918 /* Fixed encoding scheme. See fontset.h for the meaning of the
1919 encoding numbers. */
1920 int enc = font_info->encoding[charset];
1921
1922 if ((enc == 1 || enc == 2)
1923 && CHARSET_DIMENSION (charset) == 2)
1924 char2b->byte1 |= 0x80;
1925
1926 if (enc == 1 || enc == 3)
1927 char2b->byte2 |= 0x80;
1928
1929 if (enc == 4)
1930 {
1931 int sjis1, sjis2;
1932
1933 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1934 char2b->byte1 = sjis1;
1935 char2b->byte2 = sjis2;
1936 }
1937 }
1938 }
1939
1940
1941 /* Get face and two-byte form of character C in face FACE_ID on frame
1942 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1943 means we want to display multibyte text. Value is a pointer to a
1944 realized face that is ready for display. */
1945
1946 static INLINE struct face *
1947 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1948 struct frame *f;
1949 int c, face_id;
1950 XChar2b *char2b;
1951 int multibyte_p;
1952 {
1953 struct face *face = FACE_FROM_ID (f, face_id);
1954
1955 if (!multibyte_p)
1956 {
1957 /* Unibyte case. We don't have to encode, but we have to make
1958 sure to use a face suitable for unibyte. */
1959 char2b->byte1 = 0;
1960 char2b->byte2 = c;
1961 face_id = FACE_FOR_CHAR (f, face, c);
1962 face = FACE_FROM_ID (f, face_id);
1963 }
1964 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1965 {
1966 /* Case of ASCII in a face known to fit ASCII. */
1967 char2b->byte1 = 0;
1968 char2b->byte2 = c;
1969 }
1970 else
1971 {
1972 int c1, c2, charset;
1973
1974 /* Split characters into bytes. If c2 is -1 afterwards, C is
1975 really a one-byte character so that byte1 is zero. */
1976 SPLIT_CHAR (c, charset, c1, c2);
1977 if (c2 > 0)
1978 char2b->byte1 = c1, char2b->byte2 = c2;
1979 else
1980 char2b->byte1 = 0, char2b->byte2 = c1;
1981
1982 /* Maybe encode the character in *CHAR2B. */
1983 if (face->font != NULL)
1984 {
1985 struct font_info *font_info
1986 = FONT_INFO_FROM_ID (f, face->font_info_id);
1987 if (font_info)
1988 x_encode_char (c, char2b, font_info);
1989 }
1990 }
1991
1992 /* Make sure X resources of the face are allocated. */
1993 xassert (face != NULL);
1994 PREPARE_FACE_FOR_DISPLAY (f, face);
1995
1996 return face;
1997 }
1998
1999
2000 /* Get face and two-byte form of character glyph GLYPH on frame F.
2001 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
2002 a pointer to a realized face that is ready for display. */
2003
2004 static INLINE struct face *
2005 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
2006 struct frame *f;
2007 struct glyph *glyph;
2008 XChar2b *char2b;
2009 int *two_byte_p;
2010 {
2011 struct face *face;
2012
2013 xassert (glyph->type == CHAR_GLYPH);
2014 face = FACE_FROM_ID (f, glyph->face_id);
2015
2016 if (two_byte_p)
2017 *two_byte_p = 0;
2018
2019 if (!glyph->multibyte_p)
2020 {
2021 /* Unibyte case. We don't have to encode, but we have to make
2022 sure to use a face suitable for unibyte. */
2023 char2b->byte1 = 0;
2024 char2b->byte2 = glyph->u.ch;
2025 }
2026 else if (glyph->u.ch < 128
2027 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2028 {
2029 /* Case of ASCII in a face known to fit ASCII. */
2030 char2b->byte1 = 0;
2031 char2b->byte2 = glyph->u.ch;
2032 }
2033 else
2034 {
2035 int c1, c2, charset;
2036
2037 /* Split characters into bytes. If c2 is -1 afterwards, C is
2038 really a one-byte character so that byte1 is zero. */
2039 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2040 if (c2 > 0)
2041 char2b->byte1 = c1, char2b->byte2 = c2;
2042 else
2043 char2b->byte1 = 0, char2b->byte2 = c1;
2044
2045 /* Maybe encode the character in *CHAR2B. */
2046 if (charset != CHARSET_ASCII)
2047 {
2048 struct font_info *font_info
2049 = FONT_INFO_FROM_ID (f, face->font_info_id);
2050 if (font_info)
2051 {
2052 x_encode_char (glyph->u.ch, char2b, font_info);
2053 if (two_byte_p)
2054 *two_byte_p
2055 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2056 }
2057 }
2058 }
2059
2060 /* Make sure X resources of the face are allocated. */
2061 xassert (face != NULL);
2062 PREPARE_FACE_FOR_DISPLAY (f, face);
2063 return face;
2064 }
2065
2066
2067 /* Store one glyph for IT->char_to_display in IT->glyph_row.
2068 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2069
2070 static INLINE void
2071 x_append_glyph (it)
2072 struct it *it;
2073 {
2074 struct glyph *glyph;
2075 enum glyph_row_area area = it->area;
2076
2077 xassert (it->glyph_row);
2078 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2079
2080 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2081 if (glyph < it->glyph_row->glyphs[area + 1])
2082 {
2083 glyph->charpos = CHARPOS (it->position);
2084 glyph->object = it->object;
2085 glyph->pixel_width = it->pixel_width;
2086 glyph->voffset = it->voffset;
2087 glyph->type = CHAR_GLYPH;
2088 glyph->multibyte_p = it->multibyte_p;
2089 glyph->left_box_line_p = it->start_of_box_run_p;
2090 glyph->right_box_line_p = it->end_of_box_run_p;
2091 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2092 || it->phys_descent > it->descent);
2093 glyph->padding_p = 0;
2094 glyph->glyph_not_available_p = it->glyph_not_available_p;
2095 glyph->face_id = it->face_id;
2096 glyph->u.ch = it->char_to_display;
2097 ++it->glyph_row->used[area];
2098 }
2099 }
2100
2101 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2102 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2103
2104 static INLINE void
2105 x_append_composite_glyph (it)
2106 struct it *it;
2107 {
2108 struct glyph *glyph;
2109 enum glyph_row_area area = it->area;
2110
2111 xassert (it->glyph_row);
2112
2113 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2114 if (glyph < it->glyph_row->glyphs[area + 1])
2115 {
2116 glyph->charpos = CHARPOS (it->position);
2117 glyph->object = it->object;
2118 glyph->pixel_width = it->pixel_width;
2119 glyph->voffset = it->voffset;
2120 glyph->type = COMPOSITE_GLYPH;
2121 glyph->multibyte_p = it->multibyte_p;
2122 glyph->left_box_line_p = it->start_of_box_run_p;
2123 glyph->right_box_line_p = it->end_of_box_run_p;
2124 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2125 || it->phys_descent > it->descent);
2126 glyph->padding_p = 0;
2127 glyph->glyph_not_available_p = 0;
2128 glyph->face_id = it->face_id;
2129 glyph->u.cmp_id = it->cmp_id;
2130 ++it->glyph_row->used[area];
2131 }
2132 }
2133
2134
2135 /* Change IT->ascent and IT->height according to the setting of
2136 IT->voffset. */
2137
2138 static INLINE void
2139 take_vertical_position_into_account (it)
2140 struct it *it;
2141 {
2142 if (it->voffset)
2143 {
2144 if (it->voffset < 0)
2145 /* Increase the ascent so that we can display the text higher
2146 in the line. */
2147 it->ascent += abs (it->voffset);
2148 else
2149 /* Increase the descent so that we can display the text lower
2150 in the line. */
2151 it->descent += it->voffset;
2152 }
2153 }
2154
2155
2156 /* Produce glyphs/get display metrics for the image IT is loaded with.
2157 See the description of struct display_iterator in dispextern.h for
2158 an overview of struct display_iterator. */
2159
2160 static void
2161 x_produce_image_glyph (it)
2162 struct it *it;
2163 {
2164 struct image *img;
2165 struct face *face;
2166
2167 xassert (it->what == IT_IMAGE);
2168
2169 face = FACE_FROM_ID (it->f, it->face_id);
2170 img = IMAGE_FROM_ID (it->f, it->image_id);
2171 xassert (img);
2172
2173 /* Make sure X resources of the face and image are loaded. */
2174 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2175 prepare_image_for_display (it->f, img);
2176
2177 it->ascent = it->phys_ascent = image_ascent (img, face);
2178 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2179 it->pixel_width = img->width + 2 * img->hmargin;
2180
2181 it->nglyphs = 1;
2182
2183 if (face->box != FACE_NO_BOX)
2184 {
2185 if (face->box_line_width > 0)
2186 {
2187 it->ascent += face->box_line_width;
2188 it->descent += face->box_line_width;
2189 }
2190
2191 if (it->start_of_box_run_p)
2192 it->pixel_width += abs (face->box_line_width);
2193 if (it->end_of_box_run_p)
2194 it->pixel_width += abs (face->box_line_width);
2195 }
2196
2197 take_vertical_position_into_account (it);
2198
2199 if (it->glyph_row)
2200 {
2201 struct glyph *glyph;
2202 enum glyph_row_area area = it->area;
2203
2204 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2205 if (glyph < it->glyph_row->glyphs[area + 1])
2206 {
2207 glyph->charpos = CHARPOS (it->position);
2208 glyph->object = it->object;
2209 glyph->pixel_width = it->pixel_width;
2210 glyph->voffset = it->voffset;
2211 glyph->type = IMAGE_GLYPH;
2212 glyph->multibyte_p = it->multibyte_p;
2213 glyph->left_box_line_p = it->start_of_box_run_p;
2214 glyph->right_box_line_p = it->end_of_box_run_p;
2215 glyph->overlaps_vertically_p = 0;
2216 glyph->padding_p = 0;
2217 glyph->glyph_not_available_p = 0;
2218 glyph->face_id = it->face_id;
2219 glyph->u.img_id = img->id;
2220 ++it->glyph_row->used[area];
2221 }
2222 }
2223 }
2224
2225
2226 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2227 of the glyph, WIDTH and HEIGHT are the width and height of the
2228 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2229 ascent of the glyph (0 <= ASCENT <= 1). */
2230
2231 static void
2232 x_append_stretch_glyph (it, object, width, height, ascent)
2233 struct it *it;
2234 Lisp_Object object;
2235 int width, height;
2236 double ascent;
2237 {
2238 struct glyph *glyph;
2239 enum glyph_row_area area = it->area;
2240
2241 xassert (ascent >= 0 && ascent <= 1);
2242
2243 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2244 if (glyph < it->glyph_row->glyphs[area + 1])
2245 {
2246 glyph->charpos = CHARPOS (it->position);
2247 glyph->object = object;
2248 glyph->pixel_width = width;
2249 glyph->voffset = it->voffset;
2250 glyph->type = STRETCH_GLYPH;
2251 glyph->multibyte_p = it->multibyte_p;
2252 glyph->left_box_line_p = it->start_of_box_run_p;
2253 glyph->right_box_line_p = it->end_of_box_run_p;
2254 glyph->overlaps_vertically_p = 0;
2255 glyph->padding_p = 0;
2256 glyph->glyph_not_available_p = 0;
2257 glyph->face_id = it->face_id;
2258 glyph->u.stretch.ascent = height * ascent;
2259 glyph->u.stretch.height = height;
2260 ++it->glyph_row->used[area];
2261 }
2262 }
2263
2264
2265 /* Produce a stretch glyph for iterator IT. IT->object is the value
2266 of the glyph property displayed. The value must be a list
2267 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2268 being recognized:
2269
2270 1. `:width WIDTH' specifies that the space should be WIDTH *
2271 canonical char width wide. WIDTH may be an integer or floating
2272 point number.
2273
2274 2. `:relative-width FACTOR' specifies that the width of the stretch
2275 should be computed from the width of the first character having the
2276 `glyph' property, and should be FACTOR times that width.
2277
2278 3. `:align-to HPOS' specifies that the space should be wide enough
2279 to reach HPOS, a value in canonical character units.
2280
2281 Exactly one of the above pairs must be present.
2282
2283 4. `:height HEIGHT' specifies that the height of the stretch produced
2284 should be HEIGHT, measured in canonical character units.
2285
2286 5. `:relative-height FACTOR' specifies that the height of the
2287 stretch should be FACTOR times the height of the characters having
2288 the glyph property.
2289
2290 Either none or exactly one of 4 or 5 must be present.
2291
2292 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2293 of the stretch should be used for the ascent of the stretch.
2294 ASCENT must be in the range 0 <= ASCENT <= 100. */
2295
2296 #define NUMVAL(X) \
2297 ((INTEGERP (X) || FLOATP (X)) \
2298 ? XFLOATINT (X) \
2299 : - 1)
2300
2301
2302 static void
2303 x_produce_stretch_glyph (it)
2304 struct it *it;
2305 {
2306 /* (space :width WIDTH :height HEIGHT. */
2307 #if GLYPH_DEBUG
2308 extern Lisp_Object Qspace;
2309 #endif
2310 extern Lisp_Object QCwidth, QCheight, QCascent;
2311 extern Lisp_Object QCrelative_width, QCrelative_height;
2312 extern Lisp_Object QCalign_to;
2313 Lisp_Object prop, plist;
2314 double width = 0, height = 0, ascent = 0;
2315 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2316 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2317
2318 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2319
2320 /* List should start with `space'. */
2321 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2322 plist = XCDR (it->object);
2323
2324 /* Compute the width of the stretch. */
2325 if (prop = Fplist_get (plist, QCwidth),
2326 NUMVAL (prop) > 0)
2327 /* Absolute width `:width WIDTH' specified and valid. */
2328 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2329 else if (prop = Fplist_get (plist, QCrelative_width),
2330 NUMVAL (prop) > 0)
2331 {
2332 /* Relative width `:relative-width FACTOR' specified and valid.
2333 Compute the width of the characters having the `glyph'
2334 property. */
2335 struct it it2;
2336 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2337
2338 it2 = *it;
2339 if (it->multibyte_p)
2340 {
2341 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2342 - IT_BYTEPOS (*it));
2343 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2344 }
2345 else
2346 it2.c = *p, it2.len = 1;
2347
2348 it2.glyph_row = NULL;
2349 it2.what = IT_CHARACTER;
2350 x_produce_glyphs (&it2);
2351 width = NUMVAL (prop) * it2.pixel_width;
2352 }
2353 else if (prop = Fplist_get (plist, QCalign_to),
2354 NUMVAL (prop) > 0)
2355 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2356 else
2357 /* Nothing specified -> width defaults to canonical char width. */
2358 width = CANON_X_UNIT (it->f);
2359
2360 /* Compute height. */
2361 if (prop = Fplist_get (plist, QCheight),
2362 NUMVAL (prop) > 0)
2363 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2364 else if (prop = Fplist_get (plist, QCrelative_height),
2365 NUMVAL (prop) > 0)
2366 height = FONT_HEIGHT (font) * NUMVAL (prop);
2367 else
2368 height = FONT_HEIGHT (font);
2369
2370 /* Compute percentage of height used for ascent. If
2371 `:ascent ASCENT' is present and valid, use that. Otherwise,
2372 derive the ascent from the font in use. */
2373 if (prop = Fplist_get (plist, QCascent),
2374 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2375 ascent = NUMVAL (prop) / 100.0;
2376 else
2377 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
2378
2379 if (width <= 0)
2380 width = 1;
2381 if (height <= 0)
2382 height = 1;
2383
2384 if (it->glyph_row)
2385 {
2386 Lisp_Object object = it->stack[it->sp - 1].string;
2387 if (!STRINGP (object))
2388 object = it->w->buffer;
2389 x_append_stretch_glyph (it, object, width, height, ascent);
2390 }
2391
2392 it->pixel_width = width;
2393 it->ascent = it->phys_ascent = height * ascent;
2394 it->descent = it->phys_descent = height - it->ascent;
2395 it->nglyphs = 1;
2396
2397 if (face->box != FACE_NO_BOX)
2398 {
2399 if (face->box_line_width > 0)
2400 {
2401 it->ascent += face->box_line_width;
2402 it->descent += face->box_line_width;
2403 }
2404
2405 if (it->start_of_box_run_p)
2406 it->pixel_width += abs (face->box_line_width);
2407 if (it->end_of_box_run_p)
2408 it->pixel_width += abs (face->box_line_width);
2409 }
2410
2411 take_vertical_position_into_account (it);
2412 }
2413
2414 /* Return proper value to be used as baseline offset of font that has
2415 ASCENT and DESCENT to draw characters by the font at the vertical
2416 center of the line of frame F.
2417
2418 Here, out task is to find the value of BOFF in the following figure;
2419
2420 -------------------------+-----------+-
2421 -+-+---------+-+ | |
2422 | | | | | |
2423 | | | | F_ASCENT F_HEIGHT
2424 | | | ASCENT | |
2425 HEIGHT | | | | |
2426 | | |-|-+------+-----------|------- baseline
2427 | | | | BOFF | |
2428 | |---------|-+-+ | |
2429 | | | DESCENT | |
2430 -+-+---------+-+ F_DESCENT |
2431 -------------------------+-----------+-
2432
2433 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2434 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2435 DESCENT = FONT->descent
2436 HEIGHT = FONT_HEIGHT (FONT)
2437 F_DESCENT = (F->output_data.x->font->descent
2438 - F->output_data.x->baseline_offset)
2439 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2440 */
2441
2442 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2443 (FONT_DESCENT (FONT) \
2444 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2445 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2446 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2447
2448 /* Produce glyphs/get display metrics for the display element IT is
2449 loaded with. See the description of struct display_iterator in
2450 dispextern.h for an overview of struct display_iterator. */
2451
2452 static void
2453 x_produce_glyphs (it)
2454 struct it *it;
2455 {
2456 it->glyph_not_available_p = 0;
2457
2458 if (it->what == IT_CHARACTER)
2459 {
2460 XChar2b char2b;
2461 XFontStruct *font;
2462 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2463 XCharStruct *pcm;
2464 int font_not_found_p;
2465 struct font_info *font_info;
2466 int boff; /* baseline offset */
2467 /* We may change it->multibyte_p upon unibyte<->multibyte
2468 conversion. So, save the current value now and restore it
2469 later.
2470
2471 Note: It seems that we don't have to record multibyte_p in
2472 struct glyph because the character code itself tells if or
2473 not the character is multibyte. Thus, in the future, we must
2474 consider eliminating the field `multibyte_p' in the struct
2475 glyph.
2476 */
2477 int saved_multibyte_p = it->multibyte_p;
2478
2479 /* Maybe translate single-byte characters to multibyte, or the
2480 other way. */
2481 it->char_to_display = it->c;
2482 if (!ASCII_BYTE_P (it->c))
2483 {
2484 if (unibyte_display_via_language_environment
2485 && SINGLE_BYTE_CHAR_P (it->c)
2486 && (it->c >= 0240
2487 || !NILP (Vnonascii_translation_table)))
2488 {
2489 it->char_to_display = unibyte_char_to_multibyte (it->c);
2490 it->multibyte_p = 1;
2491 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2492 face = FACE_FROM_ID (it->f, it->face_id);
2493 }
2494 else if (!SINGLE_BYTE_CHAR_P (it->c)
2495 && !it->multibyte_p)
2496 {
2497 it->multibyte_p = 1;
2498 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2499 face = FACE_FROM_ID (it->f, it->face_id);
2500 }
2501 }
2502
2503 /* Get font to use. Encode IT->char_to_display. */
2504 x_get_char_face_and_encoding (it->f, it->char_to_display,
2505 it->face_id, &char2b,
2506 it->multibyte_p);
2507 font = face->font;
2508
2509 /* When no suitable font found, use the default font. */
2510 font_not_found_p = font == NULL;
2511 if (font_not_found_p)
2512 {
2513 font = FRAME_FONT (it->f);
2514 boff = it->f->output_data.mac->baseline_offset;
2515 font_info = NULL;
2516 }
2517 else
2518 {
2519 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2520 boff = font_info->baseline_offset;
2521 if (font_info->vertical_centering)
2522 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2523 }
2524
2525 if (it->char_to_display >= ' '
2526 && (!it->multibyte_p || it->char_to_display < 128))
2527 {
2528 /* Either unibyte or ASCII. */
2529 int stretched_p;
2530
2531 it->nglyphs = 1;
2532
2533 pcm = x_per_char_metric (font, &char2b);
2534 it->ascent = FONT_BASE (font) + boff;
2535 it->descent = FONT_DESCENT (font) - boff;
2536
2537 if (pcm)
2538 {
2539 it->phys_ascent = pcm->ascent + boff;
2540 it->phys_descent = pcm->descent - boff;
2541 it->pixel_width = pcm->width;
2542 }
2543 else
2544 {
2545 it->glyph_not_available_p = 1;
2546 it->phys_ascent = FONT_BASE (font) + boff;
2547 it->phys_descent = FONT_DESCENT (font) - boff;
2548 it->pixel_width = FONT_WIDTH (font);
2549 }
2550
2551 /* If this is a space inside a region of text with
2552 `space-width' property, change its width. */
2553 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2554 if (stretched_p)
2555 it->pixel_width *= XFLOATINT (it->space_width);
2556
2557 /* If face has a box, add the box thickness to the character
2558 height. If character has a box line to the left and/or
2559 right, add the box line width to the character's width. */
2560 if (face->box != FACE_NO_BOX)
2561 {
2562 int thick = face->box_line_width;
2563
2564 if (thick > 0)
2565 {
2566 it->ascent += thick;
2567 it->descent += thick;
2568 }
2569 else
2570 thick = -thick;
2571
2572 if (it->start_of_box_run_p)
2573 it->pixel_width += thick;
2574 if (it->end_of_box_run_p)
2575 it->pixel_width += thick;
2576 }
2577
2578 /* If face has an overline, add the height of the overline
2579 (1 pixel) and a 1 pixel margin to the character height. */
2580 if (face->overline_p)
2581 it->ascent += 2;
2582
2583 take_vertical_position_into_account (it);
2584
2585 /* If we have to actually produce glyphs, do it. */
2586 if (it->glyph_row)
2587 {
2588 if (stretched_p)
2589 {
2590 /* Translate a space with a `space-width' property
2591 into a stretch glyph. */
2592 double ascent = (double) FONT_BASE (font)
2593 / FONT_HEIGHT (font);
2594 x_append_stretch_glyph (it, it->object, it->pixel_width,
2595 it->ascent + it->descent, ascent);
2596 }
2597 else
2598 x_append_glyph (it);
2599
2600 /* If characters with lbearing or rbearing are displayed
2601 in this line, record that fact in a flag of the
2602 glyph row. This is used to optimize X output code. */
2603 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2604 it->glyph_row->contains_overlapping_glyphs_p = 1;
2605 }
2606 }
2607 else if (it->char_to_display == '\n')
2608 {
2609 /* A newline has no width but we need the height of the line. */
2610 it->pixel_width = 0;
2611 it->nglyphs = 0;
2612 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2613 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2614
2615 if (face->box != FACE_NO_BOX
2616 && face->box_line_width > 0)
2617 {
2618 it->ascent += face->box_line_width;
2619 it->descent += face->box_line_width;
2620 }
2621 }
2622 else if (it->char_to_display == '\t')
2623 {
2624 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2625 int x = it->current_x + it->continuation_lines_width;
2626 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2627
2628 /* If the distance from the current position to the next tab
2629 stop is less than a canonical character width, use the
2630 tab stop after that. */
2631 if (next_tab_x - x < CANON_X_UNIT (it->f))
2632 next_tab_x += tab_width;
2633
2634 it->pixel_width = next_tab_x - x;
2635 it->nglyphs = 1;
2636 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2637 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2638
2639 if (it->glyph_row)
2640 {
2641 double ascent = (double) it->ascent / (it->ascent + it->descent);
2642 x_append_stretch_glyph (it, it->object, it->pixel_width,
2643 it->ascent + it->descent, ascent);
2644 }
2645 }
2646 else
2647 {
2648 /* A multi-byte character. Assume that the display width of the
2649 character is the width of the character multiplied by the
2650 width of the font. */
2651
2652 /* If we found a font, this font should give us the right
2653 metrics. If we didn't find a font, use the frame's
2654 default font and calculate the width of the character
2655 from the charset width; this is what old redisplay code
2656 did. */
2657 pcm = x_per_char_metric (font, &char2b);
2658 if (font_not_found_p || !pcm)
2659 {
2660 int charset = CHAR_CHARSET (it->char_to_display);
2661
2662 it->glyph_not_available_p = 1;
2663 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2664 * CHARSET_WIDTH (charset));
2665 it->phys_ascent = FONT_BASE (font) + boff;
2666 it->phys_descent = FONT_DESCENT (font) - boff;
2667 }
2668 else
2669 {
2670 it->pixel_width = pcm->width;
2671 it->phys_ascent = pcm->ascent + boff;
2672 it->phys_descent = pcm->descent - boff;
2673 if (it->glyph_row
2674 && (pcm->lbearing < 0
2675 || pcm->rbearing > pcm->width))
2676 it->glyph_row->contains_overlapping_glyphs_p = 1;
2677 }
2678 it->nglyphs = 1;
2679 it->ascent = FONT_BASE (font) + boff;
2680 it->descent = FONT_DESCENT (font) - boff;
2681 if (face->box != FACE_NO_BOX)
2682 {
2683 int thick = face->box_line_width;
2684
2685 if (thick > 0)
2686 {
2687 it->ascent += thick;
2688 it->descent += thick;
2689 }
2690 else
2691 thick = - thick;
2692
2693 if (it->start_of_box_run_p)
2694 it->pixel_width += thick;
2695 if (it->end_of_box_run_p)
2696 it->pixel_width += thick;
2697 }
2698
2699 /* If face has an overline, add the height of the overline
2700 (1 pixel) and a 1 pixel margin to the character height. */
2701 if (face->overline_p)
2702 it->ascent += 2;
2703
2704 take_vertical_position_into_account (it);
2705
2706 if (it->glyph_row)
2707 x_append_glyph (it);
2708 }
2709 it->multibyte_p = saved_multibyte_p;
2710 }
2711 else if (it->what == IT_COMPOSITION)
2712 {
2713 /* Note: A composition is represented as one glyph in the
2714 glyph matrix. There are no padding glyphs. */
2715 XChar2b char2b;
2716 XFontStruct *font;
2717 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2718 XCharStruct *pcm;
2719 int font_not_found_p;
2720 struct font_info *font_info;
2721 int boff; /* baseline offset */
2722 struct composition *cmp = composition_table[it->cmp_id];
2723
2724 /* Maybe translate single-byte characters to multibyte. */
2725 it->char_to_display = it->c;
2726 if (unibyte_display_via_language_environment
2727 && SINGLE_BYTE_CHAR_P (it->c)
2728 && (it->c >= 0240
2729 || (it->c >= 0200
2730 && !NILP (Vnonascii_translation_table))))
2731 {
2732 it->char_to_display = unibyte_char_to_multibyte (it->c);
2733 }
2734
2735 /* Get face and font to use. Encode IT->char_to_display. */
2736 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2737 face = FACE_FROM_ID (it->f, it->face_id);
2738 x_get_char_face_and_encoding (it->f, it->char_to_display,
2739 it->face_id, &char2b, it->multibyte_p);
2740 font = face->font;
2741
2742 /* When no suitable font found, use the default font. */
2743 font_not_found_p = font == NULL;
2744 if (font_not_found_p)
2745 {
2746 font = FRAME_FONT (it->f);
2747 boff = it->f->output_data.mac->baseline_offset;
2748 font_info = NULL;
2749 }
2750 else
2751 {
2752 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2753 boff = font_info->baseline_offset;
2754 if (font_info->vertical_centering)
2755 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2756 }
2757
2758 /* There are no padding glyphs, so there is only one glyph to
2759 produce for the composition. Important is that pixel_width,
2760 ascent and descent are the values of what is drawn by
2761 draw_glyphs (i.e. the values of the overall glyphs composed). */
2762 it->nglyphs = 1;
2763
2764 /* If we have not yet calculated pixel size data of glyphs of
2765 the composition for the current face font, calculate them
2766 now. Theoretically, we have to check all fonts for the
2767 glyphs, but that requires much time and memory space. So,
2768 here we check only the font of the first glyph. This leads
2769 to incorrect display very rarely, and C-l (recenter) can
2770 correct the display anyway. */
2771 if (cmp->font != (void *) font)
2772 {
2773 /* Ascent and descent of the font of the first character of
2774 this composition (adjusted by baseline offset). Ascent
2775 and descent of overall glyphs should not be less than
2776 them respectively. */
2777 int font_ascent = FONT_BASE (font) + boff;
2778 int font_descent = FONT_DESCENT (font) - boff;
2779 /* Bounding box of the overall glyphs. */
2780 int leftmost, rightmost, lowest, highest;
2781 int i, width, ascent, descent;
2782
2783 cmp->font = (void *) font;
2784
2785 /* Initialize the bounding box. */
2786 pcm = x_per_char_metric (font, &char2b);
2787 if (pcm)
2788 {
2789 width = pcm->width;
2790 ascent = pcm->ascent;
2791 descent = pcm->descent;
2792 }
2793 else
2794 {
2795 width = FONT_WIDTH (font);
2796 ascent = FONT_BASE (font);
2797 descent = FONT_DESCENT (font);
2798 }
2799
2800 rightmost = width;
2801 lowest = - descent + boff;
2802 highest = ascent + boff;
2803 leftmost = 0;
2804
2805 if (font_info
2806 && font_info->default_ascent
2807 && CHAR_TABLE_P (Vuse_default_ascent)
2808 && !NILP (Faref (Vuse_default_ascent,
2809 make_number (it->char_to_display))))
2810 highest = font_info->default_ascent + boff;
2811
2812 /* Draw the first glyph at the normal position. It may be
2813 shifted to right later if some other glyphs are drawn at
2814 the left. */
2815 cmp->offsets[0] = 0;
2816 cmp->offsets[1] = boff;
2817
2818 /* Set cmp->offsets for the remaining glyphs. */
2819 for (i = 1; i < cmp->glyph_len; i++)
2820 {
2821 int left, right, btm, top;
2822 int ch = COMPOSITION_GLYPH (cmp, i);
2823 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2824
2825 face = FACE_FROM_ID (it->f, face_id);
2826 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2827 it->multibyte_p);
2828 font = face->font;
2829 if (font == NULL)
2830 {
2831 font = FRAME_FONT (it->f);
2832 boff = it->f->output_data.mac->baseline_offset;
2833 font_info = NULL;
2834 }
2835 else
2836 {
2837 font_info
2838 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2839 boff = font_info->baseline_offset;
2840 if (font_info->vertical_centering)
2841 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2842 }
2843
2844 pcm = x_per_char_metric (font, &char2b);
2845 if (pcm)
2846 {
2847 width = pcm->width;
2848 ascent = pcm->ascent;
2849 descent = pcm->descent;
2850 }
2851 else
2852 {
2853 width = FONT_WIDTH (font);
2854 ascent = 1;
2855 descent = 0;
2856 }
2857
2858 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2859 {
2860 /* Relative composition with or without
2861 alternate chars. */
2862 left = (leftmost + rightmost - width) / 2;
2863 btm = - descent + boff;
2864 if (font_info && font_info->relative_compose
2865 && (! CHAR_TABLE_P (Vignore_relative_composition)
2866 || NILP (Faref (Vignore_relative_composition,
2867 make_number (ch)))))
2868 {
2869
2870 if (- descent >= font_info->relative_compose)
2871 /* One extra pixel between two glyphs. */
2872 btm = highest + 1;
2873 else if (ascent <= 0)
2874 /* One extra pixel between two glyphs. */
2875 btm = lowest - 1 - ascent - descent;
2876 }
2877 }
2878 else
2879 {
2880 /* A composition rule is specified by an integer
2881 value that encodes global and new reference
2882 points (GREF and NREF). GREF and NREF are
2883 specified by numbers as below:
2884
2885 0---1---2 -- ascent
2886 | |
2887 | |
2888 | |
2889 9--10--11 -- center
2890 | |
2891 ---3---4---5--- baseline
2892 | |
2893 6---7---8 -- descent
2894 */
2895 int rule = COMPOSITION_RULE (cmp, i);
2896 int gref, nref, grefx, grefy, nrefx, nrefy;
2897
2898 COMPOSITION_DECODE_RULE (rule, gref, nref);
2899 grefx = gref % 3, nrefx = nref % 3;
2900 grefy = gref / 3, nrefy = nref / 3;
2901
2902 left = (leftmost
2903 + grefx * (rightmost - leftmost) / 2
2904 - nrefx * width / 2);
2905 btm = ((grefy == 0 ? highest
2906 : grefy == 1 ? 0
2907 : grefy == 2 ? lowest
2908 : (highest + lowest) / 2)
2909 - (nrefy == 0 ? ascent + descent
2910 : nrefy == 1 ? descent - boff
2911 : nrefy == 2 ? 0
2912 : (ascent + descent) / 2));
2913 }
2914
2915 cmp->offsets[i * 2] = left;
2916 cmp->offsets[i * 2 + 1] = btm + descent;
2917
2918 /* Update the bounding box of the overall glyphs. */
2919 right = left + width;
2920 top = btm + descent + ascent;
2921 if (left < leftmost)
2922 leftmost = left;
2923 if (right > rightmost)
2924 rightmost = right;
2925 if (top > highest)
2926 highest = top;
2927 if (btm < lowest)
2928 lowest = btm;
2929 }
2930
2931 /* If there are glyphs whose x-offsets are negative,
2932 shift all glyphs to the right and make all x-offsets
2933 non-negative. */
2934 if (leftmost < 0)
2935 {
2936 for (i = 0; i < cmp->glyph_len; i++)
2937 cmp->offsets[i * 2] -= leftmost;
2938 rightmost -= leftmost;
2939 }
2940
2941 cmp->pixel_width = rightmost;
2942 cmp->ascent = highest;
2943 cmp->descent = - lowest;
2944 if (cmp->ascent < font_ascent)
2945 cmp->ascent = font_ascent;
2946 if (cmp->descent < font_descent)
2947 cmp->descent = font_descent;
2948 }
2949
2950 it->pixel_width = cmp->pixel_width;
2951 it->ascent = it->phys_ascent = cmp->ascent;
2952 it->descent = it->phys_descent = cmp->descent;
2953
2954 if (face->box != FACE_NO_BOX)
2955 {
2956 int thick = face->box_line_width;
2957
2958 if (thick > 0)
2959 {
2960 it->ascent += thick;
2961 it->descent += thick;
2962 }
2963 else
2964 thick = - thick;
2965
2966 if (it->start_of_box_run_p)
2967 it->pixel_width += thick;
2968 if (it->end_of_box_run_p)
2969 it->pixel_width += thick;
2970 }
2971
2972 /* If face has an overline, add the height of the overline
2973 (1 pixel) and a 1 pixel margin to the character height. */
2974 if (face->overline_p)
2975 it->ascent += 2;
2976
2977 take_vertical_position_into_account (it);
2978
2979 if (it->glyph_row)
2980 x_append_composite_glyph (it);
2981 }
2982 else if (it->what == IT_IMAGE)
2983 x_produce_image_glyph (it);
2984 else if (it->what == IT_STRETCH)
2985 x_produce_stretch_glyph (it);
2986
2987 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2988 because this isn't true for images with `:ascent 100'. */
2989 xassert (it->ascent >= 0 && it->descent >= 0);
2990 if (it->area == TEXT_AREA)
2991 it->current_x += it->pixel_width;
2992
2993 it->descent += it->extra_line_spacing;
2994
2995 it->max_ascent = max (it->max_ascent, it->ascent);
2996 it->max_descent = max (it->max_descent, it->descent);
2997 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2998 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2999 }
3000
3001
3002 /* Estimate the pixel height of the mode or top line on frame F.
3003 FACE_ID specifies what line's height to estimate. */
3004
3005 int
3006 x_estimate_mode_line_height (f, face_id)
3007 struct frame *f;
3008 enum face_id face_id;
3009 {
3010 int height = FONT_HEIGHT (FRAME_FONT (f));
3011
3012 /* This function is called so early when Emacs starts that the face
3013 cache and mode line face are not yet initialized. */
3014 if (FRAME_FACE_CACHE (f))
3015 {
3016 struct face *face = FACE_FROM_ID (f, face_id);
3017 if (face)
3018 {
3019 if (face->font)
3020 height = FONT_HEIGHT (face->font);
3021 if (face->box_line_width > 0)
3022 height += 2 * face->box_line_width;
3023 }
3024 }
3025
3026 return height;
3027 }
3028
3029 \f
3030 /***********************************************************************
3031 Glyph display
3032 ***********************************************************************/
3033
3034 /* A sequence of glyphs to be drawn in the same face.
3035
3036 This data structure is not really completely X specific, so it
3037 could possibly, at least partially, be useful for other systems. It
3038 is currently not part of the external redisplay interface because
3039 it's not clear what other systems will need. */
3040
3041 struct glyph_string
3042 {
3043 /* X-origin of the string. */
3044 int x;
3045
3046 /* Y-origin and y-position of the base line of this string. */
3047 int y, ybase;
3048
3049 /* The width of the string, not including a face extension. */
3050 int width;
3051
3052 /* The width of the string, including a face extension. */
3053 int background_width;
3054
3055 /* The height of this string. This is the height of the line this
3056 string is drawn in, and can be different from the height of the
3057 font the string is drawn in. */
3058 int height;
3059
3060 /* Number of pixels this string overwrites in front of its x-origin.
3061 This number is zero if the string has an lbearing >= 0; it is
3062 -lbearing, if the string has an lbearing < 0. */
3063 int left_overhang;
3064
3065 /* Number of pixels this string overwrites past its right-most
3066 nominal x-position, i.e. x + width. Zero if the string's
3067 rbearing is <= its nominal width, rbearing - width otherwise. */
3068 int right_overhang;
3069
3070 /* The frame on which the glyph string is drawn. */
3071 struct frame *f;
3072
3073 /* The window on which the glyph string is drawn. */
3074 struct window *w;
3075
3076 /* X display and window for convenience. */
3077 Display *display;
3078 Window window;
3079
3080 /* The glyph row for which this string was built. It determines the
3081 y-origin and height of the string. */
3082 struct glyph_row *row;
3083
3084 /* The area within row. */
3085 enum glyph_row_area area;
3086
3087 /* Characters to be drawn, and number of characters. */
3088 XChar2b *char2b;
3089 int nchars;
3090
3091 /* A face-override for drawing cursors, mouse face and similar. */
3092 enum draw_glyphs_face hl;
3093
3094 /* Face in which this string is to be drawn. */
3095 struct face *face;
3096
3097 /* Font in which this string is to be drawn. */
3098 XFontStruct *font;
3099
3100 /* Font info for this string. */
3101 struct font_info *font_info;
3102
3103 /* Non-null means this string describes (part of) a composition.
3104 All characters from char2b are drawn composed. */
3105 struct composition *cmp;
3106
3107 /* Index of this glyph string's first character in the glyph
3108 definition of CMP. If this is zero, this glyph string describes
3109 the first character of a composition. */
3110 int gidx;
3111
3112 /* 1 means this glyph strings face has to be drawn to the right end
3113 of the window's drawing area. */
3114 unsigned extends_to_end_of_line_p : 1;
3115
3116 /* 1 means the background of this string has been drawn. */
3117 unsigned background_filled_p : 1;
3118
3119 /* 1 means glyph string must be drawn with 16-bit functions. */
3120 unsigned two_byte_p : 1;
3121
3122 /* 1 means that the original font determined for drawing this glyph
3123 string could not be loaded. The member `font' has been set to
3124 the frame's default font in this case. */
3125 unsigned font_not_found_p : 1;
3126
3127 /* 1 means that the face in which this glyph string is drawn has a
3128 stipple pattern. */
3129 unsigned stippled_p : 1;
3130
3131 /* 1 means only the foreground of this glyph string must be drawn,
3132 and we should use the physical height of the line this glyph
3133 string appears in as clip rect. */
3134 unsigned for_overlaps_p : 1;
3135
3136 /* The GC to use for drawing this glyph string. */
3137 GC gc;
3138
3139 /* A pointer to the first glyph in the string. This glyph
3140 corresponds to char2b[0]. Needed to draw rectangles if
3141 font_not_found_p is 1. */
3142 struct glyph *first_glyph;
3143
3144 /* Image, if any. */
3145 struct image *img;
3146
3147 struct glyph_string *next, *prev;
3148 };
3149
3150
3151 #if 0
3152
3153 static void
3154 x_dump_glyph_string (s)
3155 struct glyph_string *s;
3156 {
3157 fprintf (stderr, "glyph string\n");
3158 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3159 s->x, s->y, s->width, s->height);
3160 fprintf (stderr, " ybase = %d\n", s->ybase);
3161 fprintf (stderr, " hl = %d\n", s->hl);
3162 fprintf (stderr, " left overhang = %d, right = %d\n",
3163 s->left_overhang, s->right_overhang);
3164 fprintf (stderr, " nchars = %d\n", s->nchars);
3165 fprintf (stderr, " extends to end of line = %d\n",
3166 s->extends_to_end_of_line_p);
3167 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3168 fprintf (stderr, " bg width = %d\n", s->background_width);
3169 }
3170
3171 #endif /* GLYPH_DEBUG */
3172
3173
3174
3175 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3176 struct glyph_string **,
3177 struct glyph_string *,
3178 struct glyph_string *));
3179 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3180 struct glyph_string **,
3181 struct glyph_string *,
3182 struct glyph_string *));
3183 static void x_append_glyph_string P_ ((struct glyph_string **,
3184 struct glyph_string **,
3185 struct glyph_string *));
3186 static int x_left_overwritten P_ ((struct glyph_string *));
3187 static int x_left_overwriting P_ ((struct glyph_string *));
3188 static int x_right_overwritten P_ ((struct glyph_string *));
3189 static int x_right_overwriting P_ ((struct glyph_string *));
3190 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3191 int));
3192 static void x_init_glyph_string P_ ((struct glyph_string *,
3193 XChar2b *, struct window *,
3194 struct glyph_row *,
3195 enum glyph_row_area, int,
3196 enum draw_glyphs_face));
3197 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3198 enum glyph_row_area, int, int,
3199 enum draw_glyphs_face, int));
3200 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3201 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3202 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3203 int));
3204 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3205 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3206 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3207 static void x_draw_glyph_string P_ ((struct glyph_string *));
3208 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3209 static void x_set_cursor_gc P_ ((struct glyph_string *));
3210 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3211 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3212 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3213 int *, int *));
3214 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
3215 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3216 unsigned long *, double, int));*/
3217 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3218 double, int, unsigned long));
3219 static void x_setup_relief_colors P_ ((struct glyph_string *));
3220 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3221 static void x_draw_image_relief P_ ((struct glyph_string *));
3222 static void x_draw_image_foreground P_ ((struct glyph_string *));
3223 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3224 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3225 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3226 int, int, int));
3227 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
3228 int, int, int, int, Rect *));
3229 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
3230 int, int, int, Rect *));
3231 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3232 enum glyph_row_area));
3233 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3234 struct glyph_row *,
3235 enum glyph_row_area, int, int));
3236
3237 #if GLYPH_DEBUG
3238 static void x_check_font P_ ((struct frame *, XFontStruct *));
3239 #endif
3240
3241
3242 /* Append the list of glyph strings with head H and tail T to the list
3243 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3244
3245 static INLINE void
3246 x_append_glyph_string_lists (head, tail, h, t)
3247 struct glyph_string **head, **tail;
3248 struct glyph_string *h, *t;
3249 {
3250 if (h)
3251 {
3252 if (*head)
3253 (*tail)->next = h;
3254 else
3255 *head = h;
3256 h->prev = *tail;
3257 *tail = t;
3258 }
3259 }
3260
3261
3262 /* Prepend the list of glyph strings with head H and tail T to the
3263 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3264 result. */
3265
3266 static INLINE void
3267 x_prepend_glyph_string_lists (head, tail, h, t)
3268 struct glyph_string **head, **tail;
3269 struct glyph_string *h, *t;
3270 {
3271 if (h)
3272 {
3273 if (*head)
3274 (*head)->prev = t;
3275 else
3276 *tail = t;
3277 t->next = *head;
3278 *head = h;
3279 }
3280 }
3281
3282
3283 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3284 Set *HEAD and *TAIL to the resulting list. */
3285
3286 static INLINE void
3287 x_append_glyph_string (head, tail, s)
3288 struct glyph_string **head, **tail;
3289 struct glyph_string *s;
3290 {
3291 s->next = s->prev = NULL;
3292 x_append_glyph_string_lists (head, tail, s, s);
3293 }
3294
3295
3296 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3297 face. */
3298
3299 static void
3300 x_set_cursor_gc (s)
3301 struct glyph_string *s;
3302 {
3303 if (s->font == FRAME_FONT (s->f)
3304 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3305 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3306 && !s->cmp)
3307 s->gc = s->f->output_data.mac->cursor_gc;
3308 else
3309 {
3310 /* Cursor on non-default face: must merge. */
3311 XGCValues xgcv;
3312 unsigned long mask;
3313
3314 xgcv.background = s->f->output_data.mac->cursor_pixel;
3315 xgcv.foreground = s->face->background;
3316
3317 /* If the glyph would be invisible, try a different foreground. */
3318 if (xgcv.foreground == xgcv.background)
3319 xgcv.foreground = s->face->foreground;
3320 if (xgcv.foreground == xgcv.background)
3321 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3322 if (xgcv.foreground == xgcv.background)
3323 xgcv.foreground = s->face->foreground;
3324
3325 /* Make sure the cursor is distinct from text in this face. */
3326 if (xgcv.background == s->face->background
3327 && xgcv.foreground == s->face->foreground)
3328 {
3329 xgcv.background = s->face->foreground;
3330 xgcv.foreground = s->face->background;
3331 }
3332
3333 IF_DEBUG (x_check_font (s->f, s->font));
3334 xgcv.font = s->font;
3335 mask = GCForeground | GCBackground | GCFont;
3336
3337 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3338 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3339 mask, &xgcv);
3340 else
3341 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3342 = XCreateGC (s->display, s->window, mask, &xgcv);
3343
3344 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3345 }
3346 }
3347
3348
3349 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3350
3351 static void
3352 x_set_mouse_face_gc (s)
3353 struct glyph_string *s;
3354 {
3355 int face_id;
3356 struct face *face;
3357
3358 /* What face has to be used last for the mouse face? */
3359 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3360 face = FACE_FROM_ID (s->f, face_id);
3361 if (face == NULL)
3362 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3363
3364 if (s->first_glyph->type == CHAR_GLYPH)
3365 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3366 else
3367 face_id = FACE_FOR_CHAR (s->f, face, 0);
3368 s->face = FACE_FROM_ID (s->f, face_id);
3369 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3370
3371 /* If font in this face is same as S->font, use it. */
3372 if (s->font == s->face->font)
3373 s->gc = s->face->gc;
3374 else
3375 {
3376 /* Otherwise construct scratch_cursor_gc with values from FACE
3377 but font FONT. */
3378 XGCValues xgcv;
3379 unsigned long mask;
3380
3381 xgcv.background = s->face->background;
3382 xgcv.foreground = s->face->foreground;
3383 IF_DEBUG (x_check_font (s->f, s->font));
3384 xgcv.font = s->font;
3385 mask = GCForeground | GCBackground | GCFont;
3386
3387 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3388 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3389 mask, &xgcv);
3390 else
3391 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3392 = XCreateGC (s->display, s->window, mask, &xgcv);
3393
3394 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3395 }
3396
3397 xassert (s->gc != 0);
3398 }
3399
3400
3401 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3402 Faces to use in the mode line have already been computed when the
3403 matrix was built, so there isn't much to do, here. */
3404
3405 static INLINE void
3406 x_set_mode_line_face_gc (s)
3407 struct glyph_string *s;
3408 {
3409 s->gc = s->face->gc;
3410 }
3411
3412
3413 /* Set S->gc of glyph string S for drawing that glyph string. Set
3414 S->stippled_p to a non-zero value if the face of S has a stipple
3415 pattern. */
3416
3417 static INLINE void
3418 x_set_glyph_string_gc (s)
3419 struct glyph_string *s;
3420 {
3421 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3422
3423 if (s->hl == DRAW_NORMAL_TEXT)
3424 {
3425 s->gc = s->face->gc;
3426 s->stippled_p = s->face->stipple != 0;
3427 }
3428 else if (s->hl == DRAW_INVERSE_VIDEO)
3429 {
3430 x_set_mode_line_face_gc (s);
3431 s->stippled_p = s->face->stipple != 0;
3432 }
3433 else if (s->hl == DRAW_CURSOR)
3434 {
3435 x_set_cursor_gc (s);
3436 s->stippled_p = 0;
3437 }
3438 else if (s->hl == DRAW_MOUSE_FACE)
3439 {
3440 x_set_mouse_face_gc (s);
3441 s->stippled_p = s->face->stipple != 0;
3442 }
3443 else if (s->hl == DRAW_IMAGE_RAISED
3444 || s->hl == DRAW_IMAGE_SUNKEN)
3445 {
3446 s->gc = s->face->gc;
3447 s->stippled_p = s->face->stipple != 0;
3448 }
3449 else
3450 {
3451 s->gc = s->face->gc;
3452 s->stippled_p = s->face->stipple != 0;
3453 }
3454
3455 /* GC must have been set. */
3456 xassert (s->gc != 0);
3457 }
3458
3459
3460 /* Return in *R the clipping rectangle for glyph string S. */
3461
3462 static void
3463 x_get_glyph_string_clip_rect (s, r)
3464 struct glyph_string *s;
3465 Rect *r;
3466 {
3467 int r_height, r_width;
3468
3469 if (s->row->full_width_p)
3470 {
3471 /* Draw full-width. X coordinates are relative to S->w->left. */
3472 int canon_x = CANON_X_UNIT (s->f);
3473
3474 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3475 r_width = XFASTINT (s->w->width) * canon_x;
3476
3477 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3478 {
3479 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3480 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3481 r->left -= width;
3482 }
3483
3484 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3485
3486 /* Unless displaying a mode or menu bar line, which are always
3487 fully visible, clip to the visible part of the row. */
3488 if (s->w->pseudo_window_p)
3489 r_height = s->row->visible_height;
3490 else
3491 r_height = s->height;
3492 }
3493 else
3494 {
3495 /* This is a text line that may be partially visible. */
3496 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3497 r_width = window_box_width (s->w, s->area);
3498 r_height = s->row->visible_height;
3499 }
3500
3501 /* If S draws overlapping rows, it's sufficient to use the top and
3502 bottom of the window for clipping because this glyph string
3503 intentionally draws over other lines. */
3504 if (s->for_overlaps_p)
3505 {
3506 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3507 r_height = window_text_bottom_y (s->w) - r->top;
3508 }
3509 else
3510 {
3511 /* Don't use S->y for clipping because it doesn't take partially
3512 visible lines into account. For example, it can be negative for
3513 partially visible lines at the top of a window. */
3514 if (!s->row->full_width_p
3515 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3516 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3517 else
3518 r->top = max (0, s->row->y);
3519
3520 /* If drawing a tool-bar window, draw it over the internal border
3521 at the top of the window. */
3522 if (s->w == XWINDOW (s->f->tool_bar_window))
3523 r->top -= s->f->output_data.mac->internal_border_width;
3524 }
3525
3526 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3527
3528 r->bottom = r->top + r_height;
3529 r->right = r->left + r_width;
3530 }
3531
3532
3533 /* Set clipping for output of glyph string S. S may be part of a mode
3534 line or menu if we don't have X toolkit support. */
3535
3536 static INLINE void
3537 x_set_glyph_string_clipping (s)
3538 struct glyph_string *s;
3539 {
3540 Rect r;
3541 x_get_glyph_string_clip_rect (s, &r);
3542 mac_set_clip_rectangle (s->display, s->window, &r);
3543 }
3544
3545
3546 /* Compute left and right overhang of glyph string S. If S is a glyph
3547 string for a composition, assume overhangs don't exist. */
3548
3549 static INLINE void
3550 x_compute_glyph_string_overhangs (s)
3551 struct glyph_string *s;
3552 {
3553 if (s->cmp == NULL
3554 && s->first_glyph->type == CHAR_GLYPH)
3555 {
3556 XCharStruct cs;
3557 int direction, font_ascent, font_descent;
3558 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3559 &font_ascent, &font_descent, &cs);
3560 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3561 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3562 }
3563 }
3564
3565
3566 /* Compute overhangs and x-positions for glyph string S and its
3567 predecessors, or successors. X is the starting x-position for S.
3568 BACKWARD_P non-zero means process predecessors. */
3569
3570 static void
3571 x_compute_overhangs_and_x (s, x, backward_p)
3572 struct glyph_string *s;
3573 int x;
3574 int backward_p;
3575 {
3576 if (backward_p)
3577 {
3578 while (s)
3579 {
3580 x_compute_glyph_string_overhangs (s);
3581 x -= s->width;
3582 s->x = x;
3583 s = s->prev;
3584 }
3585 }
3586 else
3587 {
3588 while (s)
3589 {
3590 x_compute_glyph_string_overhangs (s);
3591 s->x = x;
3592 x += s->width;
3593 s = s->next;
3594 }
3595 }
3596 }
3597
3598
3599 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3600 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3601 assumed to be zero. */
3602
3603 void
3604 x_get_glyph_overhangs (glyph, f, left, right)
3605 struct glyph *glyph;
3606 struct frame *f;
3607 int *left, *right;
3608 {
3609 *left = *right = 0;
3610
3611 if (glyph->type == CHAR_GLYPH)
3612 {
3613 XFontStruct *font;
3614 struct face *face;
3615 struct font_info *font_info;
3616 XChar2b char2b;
3617 XCharStruct *pcm;
3618
3619 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3620 font = face->font;
3621 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3622 if (font
3623 && (pcm = x_per_char_metric (font, &char2b)))
3624 {
3625 if (pcm->rbearing > pcm->width)
3626 *right = pcm->rbearing - pcm->width;
3627 if (pcm->lbearing < 0)
3628 *left = -pcm->lbearing;
3629 }
3630 }
3631 }
3632
3633
3634 /* Return the index of the first glyph preceding glyph string S that
3635 is overwritten by S because of S's left overhang. Value is -1
3636 if no glyphs are overwritten. */
3637
3638 static int
3639 x_left_overwritten (s)
3640 struct glyph_string *s;
3641 {
3642 int k;
3643
3644 if (s->left_overhang)
3645 {
3646 int x = 0, i;
3647 struct glyph *glyphs = s->row->glyphs[s->area];
3648 int first = s->first_glyph - glyphs;
3649
3650 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3651 x -= glyphs[i].pixel_width;
3652
3653 k = i + 1;
3654 }
3655 else
3656 k = -1;
3657
3658 return k;
3659 }
3660
3661
3662 /* Return the index of the first glyph preceding glyph string S that
3663 is overwriting S because of its right overhang. Value is -1 if no
3664 glyph in front of S overwrites S. */
3665
3666 static int
3667 x_left_overwriting (s)
3668 struct glyph_string *s;
3669 {
3670 int i, k, x;
3671 struct glyph *glyphs = s->row->glyphs[s->area];
3672 int first = s->first_glyph - glyphs;
3673
3674 k = -1;
3675 x = 0;
3676 for (i = first - 1; i >= 0; --i)
3677 {
3678 int left, right;
3679 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3680 if (x + right > 0)
3681 k = i;
3682 x -= glyphs[i].pixel_width;
3683 }
3684
3685 return k;
3686 }
3687
3688
3689 /* Return the index of the last glyph following glyph string S that is
3690 not overwritten by S because of S's right overhang. Value is -1 if
3691 no such glyph is found. */
3692
3693 static int
3694 x_right_overwritten (s)
3695 struct glyph_string *s;
3696 {
3697 int k = -1;
3698
3699 if (s->right_overhang)
3700 {
3701 int x = 0, i;
3702 struct glyph *glyphs = s->row->glyphs[s->area];
3703 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3704 int end = s->row->used[s->area];
3705
3706 for (i = first; i < end && s->right_overhang > x; ++i)
3707 x += glyphs[i].pixel_width;
3708
3709 k = i;
3710 }
3711
3712 return k;
3713 }
3714
3715
3716 /* Return the index of the last glyph following glyph string S that
3717 overwrites S because of its left overhang. Value is negative
3718 if no such glyph is found. */
3719
3720 static int
3721 x_right_overwriting (s)
3722 struct glyph_string *s;
3723 {
3724 int i, k, x;
3725 int end = s->row->used[s->area];
3726 struct glyph *glyphs = s->row->glyphs[s->area];
3727 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3728
3729 k = -1;
3730 x = 0;
3731 for (i = first; i < end; ++i)
3732 {
3733 int left, right;
3734 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3735 if (x - left < 0)
3736 k = i;
3737 x += glyphs[i].pixel_width;
3738 }
3739
3740 return k;
3741 }
3742
3743
3744 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3745
3746 static INLINE void
3747 x_clear_glyph_string_rect (s, x, y, w, h)
3748 struct glyph_string *s;
3749 int x, y, w, h;
3750 {
3751 XGCValues xgcv;
3752
3753 xgcv.foreground = s->gc->background;
3754 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3755 }
3756
3757
3758 /* Draw the background of glyph_string S. If S->background_filled_p
3759 is non-zero don't draw it. FORCE_P non-zero means draw the
3760 background even if it wouldn't be drawn normally. This is used
3761 when a string preceding S draws into the background of S, or S
3762 contains the first component of a composition. */
3763
3764 static void
3765 x_draw_glyph_string_background (s, force_p)
3766 struct glyph_string *s;
3767 int force_p;
3768 {
3769 /* Nothing to do if background has already been drawn or if it
3770 shouldn't be drawn in the first place. */
3771 if (!s->background_filled_p)
3772 {
3773 int box_line_width = max (s->face->box_line_width, 0);
3774
3775 #if 0 /* MAC_TODO: stipple */
3776 if (s->stippled_p)
3777 {
3778 /* Fill background with a stipple pattern. */
3779 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3780 XFillRectangle (s->display, s->window, s->gc, s->x,
3781 s->y + box_line_width,
3782 s->background_width,
3783 s->height - 2 * box_line_width);
3784 XSetFillStyle (s->display, s->gc, FillSolid);
3785 s->background_filled_p = 1;
3786 }
3787 else
3788 #endif
3789 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3790 || s->font_not_found_p
3791 || s->extends_to_end_of_line_p
3792 || force_p)
3793 {
3794 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3795 s->background_width,
3796 s->height - 2 * box_line_width);
3797 s->background_filled_p = 1;
3798 }
3799 }
3800 }
3801
3802
3803 /* Draw the foreground of glyph string S. */
3804
3805 static void
3806 x_draw_glyph_string_foreground (s)
3807 struct glyph_string *s;
3808 {
3809 int i, x;
3810
3811 /* If first glyph of S has a left box line, start drawing the text
3812 of S to the right of that box line. */
3813 if (s->face->box != FACE_NO_BOX
3814 && s->first_glyph->left_box_line_p)
3815 x = s->x + abs (s->face->box_line_width);
3816 else
3817 x = s->x;
3818
3819 /* Draw characters of S as rectangles if S's font could not be
3820 loaded. */
3821 if (s->font_not_found_p)
3822 {
3823 for (i = 0; i < s->nchars; ++i)
3824 {
3825 struct glyph *g = s->first_glyph + i;
3826 mac_draw_rectangle (s->display, s->window,
3827 s->gc, x, s->y, g->pixel_width - 1,
3828 s->height - 1);
3829 x += g->pixel_width;
3830 }
3831 }
3832 else
3833 {
3834 char *char1b = (char *) s->char2b;
3835 int boff = s->font_info->baseline_offset;
3836
3837 if (s->font_info->vertical_centering)
3838 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3839
3840 /* If we can use 8-bit functions, condense S->char2b. */
3841 if (!s->two_byte_p)
3842 for (i = 0; i < s->nchars; ++i)
3843 char1b[i] = s->char2b[i].byte2;
3844
3845 /* Draw text with XDrawString if background has already been
3846 filled. Otherwise, use XDrawImageString. (Note that
3847 XDrawImageString is usually faster than XDrawString.) Always
3848 use XDrawImageString when drawing the cursor so that there is
3849 no chance that characters under a box cursor are invisible. */
3850 if (s->for_overlaps_p
3851 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3852 {
3853 /* Draw characters with 16-bit or 8-bit functions. */
3854 if (s->two_byte_p)
3855 XDrawString16 (s->display, s->window, s->gc, x,
3856 s->ybase - boff, s->char2b, s->nchars);
3857 else
3858 XDrawString (s->display, s->window, s->gc, x,
3859 s->ybase - boff, char1b, s->nchars);
3860 }
3861 else
3862 {
3863 if (s->two_byte_p)
3864 XDrawImageString16 (s->display, s->window, s->gc, x,
3865 s->ybase - boff, s->char2b, s->nchars);
3866 else
3867 XDrawImageString (s->display, s->window, s->gc, x,
3868 s->ybase - boff, char1b, s->nchars);
3869 }
3870 }
3871 }
3872
3873 /* Draw the foreground of composite glyph string S. */
3874
3875 static void
3876 x_draw_composite_glyph_string_foreground (s)
3877 struct glyph_string *s;
3878 {
3879 int i, x;
3880
3881 /* If first glyph of S has a left box line, start drawing the text
3882 of S to the right of that box line. */
3883 if (s->face->box != FACE_NO_BOX
3884 && s->first_glyph->left_box_line_p)
3885 x = s->x + abs (s->face->box_line_width);
3886 else
3887 x = s->x;
3888
3889 /* S is a glyph string for a composition. S->gidx is the index of
3890 the first character drawn for glyphs of this composition.
3891 S->gidx == 0 means we are drawing the very first character of
3892 this composition. */
3893
3894 /* Draw a rectangle for the composition if the font for the very
3895 first character of the composition could not be loaded. */
3896 if (s->font_not_found_p)
3897 {
3898 if (s->gidx == 0)
3899 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3900 s->width - 1, s->height - 1);
3901 }
3902 else
3903 {
3904 for (i = 0; i < s->nchars; i++, ++s->gidx)
3905 XDrawString16 (s->display, s->window, s->gc,
3906 x + s->cmp->offsets[s->gidx * 2],
3907 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3908 s->char2b + i, 1);
3909 }
3910 }
3911
3912
3913 #ifdef USE_X_TOOLKIT
3914
3915 static struct frame *x_frame_of_widget P_ ((Widget));
3916
3917
3918 /* Return the frame on which widget WIDGET is used.. Abort if frame
3919 cannot be determined. */
3920
3921 static struct frame *
3922 x_frame_of_widget (widget)
3923 Widget widget;
3924 {
3925 struct x_display_info *dpyinfo;
3926 Lisp_Object tail;
3927 struct frame *f;
3928
3929 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3930
3931 /* Find the top-level shell of the widget. Note that this function
3932 can be called when the widget is not yet realized, so XtWindow
3933 (widget) == 0. That's the reason we can't simply use
3934 x_any_window_to_frame. */
3935 while (!XtIsTopLevelShell (widget))
3936 widget = XtParent (widget);
3937
3938 /* Look for a frame with that top-level widget. Allocate the color
3939 on that frame to get the right gamma correction value. */
3940 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3941 if (GC_FRAMEP (XCAR (tail))
3942 && (f = XFRAME (XCAR (tail)),
3943 (f->output_data.nothing != 1
3944 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3945 && f->output_data.x->widget == widget)
3946 return f;
3947
3948 abort ();
3949 }
3950
3951
3952 /* Allocate the color COLOR->pixel on the screen and display of
3953 widget WIDGET in colormap CMAP. If an exact match cannot be
3954 allocated, try the nearest color available. Value is non-zero
3955 if successful. This is called from lwlib. */
3956
3957 int
3958 x_alloc_nearest_color_for_widget (widget, cmap, color)
3959 Widget widget;
3960 Colormap cmap;
3961 XColor *color;
3962 {
3963 struct frame *f = x_frame_of_widget (widget);
3964 return x_alloc_nearest_color (f, cmap, color);
3965 }
3966
3967
3968 #endif /* USE_X_TOOLKIT */
3969
3970 #if 0 /* MAC_TODO */
3971
3972 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3973 CMAP. If an exact match can't be allocated, try the nearest color
3974 available. Value is non-zero if successful. Set *COLOR to the
3975 color allocated. */
3976
3977 int
3978 x_alloc_nearest_color (f, cmap, color)
3979 struct frame *f;
3980 Colormap cmap;
3981 XColor *color;
3982 {
3983 Display *display = FRAME_X_DISPLAY (f);
3984 Screen *screen = FRAME_X_SCREEN (f);
3985 int rc;
3986
3987 gamma_correct (f, color);
3988 rc = XAllocColor (display, cmap, color);
3989 if (rc == 0)
3990 {
3991 /* If we got to this point, the colormap is full, so we're going
3992 to try to get the next closest color. The algorithm used is
3993 a least-squares matching, which is what X uses for closest
3994 color matching with StaticColor visuals. */
3995 int nearest, i;
3996 unsigned long nearest_delta = ~0;
3997 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3998 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3999
4000 for (i = 0; i < ncells; ++i)
4001 cells[i].pixel = i;
4002 XQueryColors (display, cmap, cells, ncells);
4003
4004 for (nearest = i = 0; i < ncells; ++i)
4005 {
4006 long dred = (color->red >> 8) - (cells[i].red >> 8);
4007 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
4008 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
4009 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
4010
4011 if (delta < nearest_delta)
4012 {
4013 nearest = i;
4014 nearest_delta = delta;
4015 }
4016 }
4017
4018 color->red = cells[nearest].red;
4019 color->green = cells[nearest].green;
4020 color->blue = cells[nearest].blue;
4021 rc = XAllocColor (display, cmap, color);
4022 }
4023
4024 #ifdef DEBUG_X_COLORS
4025 if (rc)
4026 register_color (color->pixel);
4027 #endif /* DEBUG_X_COLORS */
4028
4029 return rc;
4030 }
4031
4032
4033 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4034 It's necessary to do this instead of just using PIXEL directly to
4035 get color reference counts right. */
4036
4037 unsigned long
4038 x_copy_color (f, pixel)
4039 struct frame *f;
4040 unsigned long pixel;
4041 {
4042 XColor color;
4043
4044 color.pixel = pixel;
4045 BLOCK_INPUT;
4046 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4047 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4048 UNBLOCK_INPUT;
4049 #ifdef DEBUG_X_COLORS
4050 register_color (pixel);
4051 #endif
4052 return color.pixel;
4053 }
4054
4055
4056 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4057 It's necessary to do this instead of just using PIXEL directly to
4058 get color reference counts right. */
4059
4060 unsigned long
4061 x_copy_dpy_color (dpy, cmap, pixel)
4062 Display *dpy;
4063 Colormap cmap;
4064 unsigned long pixel;
4065 {
4066 XColor color;
4067
4068 color.pixel = pixel;
4069 BLOCK_INPUT;
4070 XQueryColor (dpy, cmap, &color);
4071 XAllocColor (dpy, cmap, &color);
4072 UNBLOCK_INPUT;
4073 #ifdef DEBUG_X_COLORS
4074 register_color (pixel);
4075 #endif
4076 return color.pixel;
4077 }
4078
4079 #endif /* MAC_TODO */
4080
4081 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
4082 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4083 If this produces the same color as COLOR, try a color where all RGB
4084 values have DELTA added. Return the allocated color in *COLOR.
4085 DISPLAY is the X display, CMAP is the colormap to operate on.
4086 Value is non-zero if successful. */
4087
4088 static int
4089 mac_alloc_lighter_color (f, color, factor, delta)
4090 struct frame *f;
4091 unsigned long *color;
4092 double factor;
4093 int delta;
4094 {
4095 unsigned long new;
4096
4097 /* Change RGB values by specified FACTOR. Avoid overflow! */
4098 xassert (factor >= 0);
4099 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4100 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4101 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4102 if (new == *color)
4103 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4104 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4105 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4106
4107 /* MAC_TODO: Map to palette and retry with delta if same? */
4108 /* MAC_TODO: Free colors (if using palette)? */
4109
4110 if (new == *color)
4111 return 0;
4112
4113 *color = new;
4114
4115 return 1;
4116 }
4117
4118
4119 /* Set up the foreground color for drawing relief lines of glyph
4120 string S. RELIEF is a pointer to a struct relief containing the GC
4121 with which lines will be drawn. Use a color that is FACTOR or
4122 DELTA lighter or darker than the relief's background which is found
4123 in S->f->output_data.x->relief_background. If such a color cannot
4124 be allocated, use DEFAULT_PIXEL, instead. */
4125
4126 static void
4127 x_setup_relief_color (f, relief, factor, delta, default_pixel)
4128 struct frame *f;
4129 struct relief *relief;
4130 double factor;
4131 int delta;
4132 unsigned long default_pixel;
4133 {
4134 XGCValues xgcv;
4135 struct mac_output *di = f->output_data.mac;
4136 unsigned long mask = GCForeground;
4137 unsigned long pixel;
4138 unsigned long background = di->relief_background;
4139 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4140
4141 /* MAC_TODO: Free colors (if using palette)? */
4142
4143 /* Allocate new color. */
4144 xgcv.foreground = default_pixel;
4145 pixel = background;
4146 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4147 {
4148 relief->allocated_p = 1;
4149 xgcv.foreground = relief->pixel = pixel;
4150 }
4151
4152 if (relief->gc == 0)
4153 {
4154 #if 0 /* MAC_TODO: stipple */
4155 xgcv.stipple = dpyinfo->gray;
4156 mask |= GCStipple;
4157 #endif
4158 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4159 }
4160 else
4161 XChangeGC (NULL, relief->gc, mask, &xgcv);
4162 }
4163
4164
4165 /* Set up colors for the relief lines around glyph string S. */
4166
4167 static void
4168 x_setup_relief_colors (s)
4169 struct glyph_string *s;
4170 {
4171 struct mac_output *di = s->f->output_data.mac;
4172 unsigned long color;
4173
4174 if (s->face->use_box_color_for_shadows_p)
4175 color = s->face->box_color;
4176 else
4177 {
4178 XGCValues xgcv;
4179
4180 /* Get the background color of the face. */
4181 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4182 color = xgcv.background;
4183 }
4184
4185 if (di->white_relief.gc == 0
4186 || color != di->relief_background)
4187 {
4188 di->relief_background = color;
4189 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4190 WHITE_PIX_DEFAULT (s->f));
4191 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4192 BLACK_PIX_DEFAULT (s->f));
4193 }
4194 }
4195
4196
4197 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4198 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4199 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4200 relief. LEFT_P non-zero means draw a relief on the left side of
4201 the rectangle. RIGHT_P non-zero means draw a relief on the right
4202 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4203 when drawing. */
4204
4205 static void
4206 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4207 raised_p, left_p, right_p, clip_rect)
4208 struct frame *f;
4209 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4210 Rect *clip_rect;
4211 {
4212 int i;
4213 GC gc;
4214
4215 if (raised_p)
4216 gc = f->output_data.mac->white_relief.gc;
4217 else
4218 gc = f->output_data.mac->black_relief.gc;
4219 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4220
4221 /* Top. */
4222 for (i = 0; i < width; ++i)
4223 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4224 left_x + i * left_p, top_y + i,
4225 right_x + 1 - i * right_p, top_y + i);
4226
4227 /* Left. */
4228 if (left_p)
4229 for (i = 0; i < width; ++i)
4230 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4231 left_x + i, top_y + i, left_x + i, bottom_y - i);
4232
4233 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4234 if (raised_p)
4235 gc = f->output_data.mac->black_relief.gc;
4236 else
4237 gc = f->output_data.mac->white_relief.gc;
4238 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4239 clip_rect);
4240
4241 /* Bottom. */
4242 for (i = 0; i < width; ++i)
4243 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4244 left_x + i * left_p, bottom_y - i,
4245 right_x + 1 - i * right_p, bottom_y - i);
4246
4247 /* Right. */
4248 if (right_p)
4249 for (i = 0; i < width; ++i)
4250 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4251 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4252
4253 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4254 }
4255
4256
4257 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4258 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4259 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4260 left side of the rectangle. RIGHT_P non-zero means draw a line
4261 on the right side of the rectangle. CLIP_RECT is the clipping
4262 rectangle to use when drawing. */
4263
4264 static void
4265 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4266 left_p, right_p, clip_rect)
4267 struct glyph_string *s;
4268 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4269 Rect *clip_rect;
4270 {
4271 XGCValues xgcv;
4272
4273 xgcv.foreground = s->face->box_color;
4274 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4275
4276 /* Top. */
4277 XFillRectangle (s->display, s->window, &xgcv,
4278 left_x, top_y, right_x - left_x, width);
4279
4280 /* Left. */
4281 if (left_p)
4282 XFillRectangle (s->display, s->window, &xgcv,
4283 left_x, top_y, width, bottom_y - top_y);
4284
4285 /* Bottom. */
4286 XFillRectangle (s->display, s->window, &xgcv,
4287 left_x, bottom_y - width, right_x - left_x, width);
4288
4289 /* Right. */
4290 if (right_p)
4291 XFillRectangle (s->display, s->window, &xgcv,
4292 right_x - width, top_y, width, bottom_y - top_y);
4293
4294 mac_reset_clipping (s->display, s->window);
4295 }
4296
4297
4298 /* Draw a box around glyph string S. */
4299
4300 static void
4301 x_draw_glyph_string_box (s)
4302 struct glyph_string *s;
4303 {
4304 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4305 int left_p, right_p;
4306 struct glyph *last_glyph;
4307 Rect clip_rect;
4308
4309 last_x = window_box_right (s->w, s->area);
4310 if (s->row->full_width_p
4311 && !s->w->pseudo_window_p)
4312 {
4313 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4314 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4315 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4316 }
4317
4318 /* The glyph that may have a right box line. */
4319 last_glyph = (s->cmp || s->img
4320 ? s->first_glyph
4321 : s->first_glyph + s->nchars - 1);
4322
4323 width = abs (s->face->box_line_width);
4324 raised_p = s->face->box == FACE_RAISED_BOX;
4325 left_x = s->x;
4326 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
4327 ? last_x - 1
4328 : min (last_x, s->x + s->background_width) - 1));
4329 top_y = s->y;
4330 bottom_y = top_y + s->height - 1;
4331
4332 left_p = (s->first_glyph->left_box_line_p
4333 || (s->hl == DRAW_MOUSE_FACE
4334 && (s->prev == NULL
4335 || s->prev->hl != s->hl)));
4336 right_p = (last_glyph->right_box_line_p
4337 || (s->hl == DRAW_MOUSE_FACE
4338 && (s->next == NULL
4339 || s->next->hl != s->hl)));
4340
4341 x_get_glyph_string_clip_rect (s, &clip_rect);
4342
4343 if (s->face->box == FACE_SIMPLE_BOX)
4344 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4345 left_p, right_p, &clip_rect);
4346 else
4347 {
4348 x_setup_relief_colors (s);
4349 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4350 width, raised_p, left_p, right_p, &clip_rect);
4351 }
4352 }
4353
4354
4355 /* Draw foreground of image glyph string S. */
4356
4357 static void
4358 x_draw_image_foreground (s)
4359 struct glyph_string *s;
4360 {
4361 int x;
4362 int y = s->ybase - image_ascent (s->img, s->face);
4363
4364 /* If first glyph of S has a left box line, start drawing it to the
4365 right of that line. */
4366 if (s->face->box != FACE_NO_BOX
4367 && s->first_glyph->left_box_line_p)
4368 x = s->x + abs (s->face->box_line_width);
4369 else
4370 x = s->x;
4371
4372 /* If there is a margin around the image, adjust x- and y-position
4373 by that margin. */
4374 x += s->img->hmargin;
4375 y += s->img->vmargin;
4376
4377 if (s->img->pixmap)
4378 {
4379 #if 0 /* MAC_TODO: image mask */
4380 if (s->img->mask)
4381 {
4382 /* We can't set both a clip mask and use XSetClipRectangles
4383 because the latter also sets a clip mask. We also can't
4384 trust on the shape extension to be available
4385 (XShapeCombineRegion). So, compute the rectangle to draw
4386 manually. */
4387 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4388 | GCFunction);
4389 XGCValues xgcv;
4390 XRectangle clip_rect, image_rect, r;
4391
4392 xgcv.clip_mask = s->img->mask;
4393 xgcv.clip_x_origin = x;
4394 xgcv.clip_y_origin = y;
4395 xgcv.function = GXcopy;
4396 XChangeGC (s->display, s->gc, mask, &xgcv);
4397
4398 x_get_glyph_string_clip_rect (s, &clip_rect);
4399 image_rect.x = x;
4400 image_rect.y = y;
4401 image_rect.width = s->img->width;
4402 image_rect.height = s->img->height;
4403 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4404 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4405 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4406 }
4407 else
4408 #endif /* MAC_TODO */
4409 {
4410 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4411 0, 0, s->img->width, s->img->height, x, y);
4412
4413 /* When the image has a mask, we can expect that at
4414 least part of a mouse highlight or a block cursor will
4415 be visible. If the image doesn't have a mask, make
4416 a block cursor visible by drawing a rectangle around
4417 the image. I believe it's looking better if we do
4418 nothing here for mouse-face. */
4419 if (s->hl == DRAW_CURSOR)
4420 {
4421 int r = s->img->relief;
4422 if (r < 0) r = -r;
4423 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4424 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4425 }
4426 }
4427 }
4428 else
4429 /* Draw a rectangle if image could not be loaded. */
4430 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4431 s->img->width - 1, s->img->height - 1);
4432 }
4433
4434
4435
4436 /* Draw a relief around the image glyph string S. */
4437
4438 static void
4439 x_draw_image_relief (s)
4440 struct glyph_string *s;
4441 {
4442 int x0, y0, x1, y1, thick, raised_p;
4443 Rect r;
4444 int x;
4445 int y = s->ybase - image_ascent (s->img, s->face);
4446
4447 /* If first glyph of S has a left box line, start drawing it to the
4448 right of that line. */
4449 if (s->face->box != FACE_NO_BOX
4450 && s->first_glyph->left_box_line_p)
4451 x = s->x + abs (s->face->box_line_width);
4452 else
4453 x = s->x;
4454
4455 /* If there is a margin around the image, adjust x- and y-position
4456 by that margin. */
4457 x += s->img->hmargin;
4458 y += s->img->vmargin;
4459
4460 if (s->hl == DRAW_IMAGE_SUNKEN
4461 || s->hl == DRAW_IMAGE_RAISED)
4462 {
4463 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4464 raised_p = s->hl == DRAW_IMAGE_RAISED;
4465 }
4466 else
4467 {
4468 thick = abs (s->img->relief);
4469 raised_p = s->img->relief > 0;
4470 }
4471
4472 x0 = x - thick;
4473 y0 = y - thick;
4474 x1 = x + s->img->width + thick - 1;
4475 y1 = y + s->img->height + thick - 1;
4476
4477 x_setup_relief_colors (s);
4478 x_get_glyph_string_clip_rect (s, &r);
4479 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4480 }
4481
4482
4483 /* Draw the foreground of image glyph string S to PIXMAP. */
4484
4485 static void
4486 x_draw_image_foreground_1 (s, pixmap)
4487 struct glyph_string *s;
4488 Pixmap pixmap;
4489 {
4490 int x;
4491 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4492
4493 /* If first glyph of S has a left box line, start drawing it to the
4494 right of that line. */
4495 if (s->face->box != FACE_NO_BOX
4496 && s->first_glyph->left_box_line_p)
4497 x = abs (s->face->box_line_width);
4498 else
4499 x = 0;
4500
4501 /* If there is a margin around the image, adjust x- and y-position
4502 by that margin. */
4503 x += s->img->hmargin;
4504 y += s->img->vmargin;
4505
4506 if (s->img->pixmap)
4507 {
4508 #if 0 /* MAC_TODO: image mask */
4509 if (s->img->mask)
4510 {
4511 /* We can't set both a clip mask and use XSetClipRectangles
4512 because the latter also sets a clip mask. We also can't
4513 trust on the shape extension to be available
4514 (XShapeCombineRegion). So, compute the rectangle to draw
4515 manually. */
4516 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4517 | GCFunction);
4518 XGCValues xgcv;
4519
4520 xgcv.clip_mask = s->img->mask;
4521 xgcv.clip_x_origin = x;
4522 xgcv.clip_y_origin = y;
4523 xgcv.function = GXcopy;
4524 XChangeGC (s->display, s->gc, mask, &xgcv);
4525
4526 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4527 0, 0, s->img->width, s->img->height, x, y);
4528 XSetClipMask (s->display, s->gc, None);
4529 }
4530 else
4531 #endif /* MAC_TODO */
4532 {
4533 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4534 0, 0, s->img->width, s->img->height, x, y);
4535
4536 /* When the image has a mask, we can expect that at
4537 least part of a mouse highlight or a block cursor will
4538 be visible. If the image doesn't have a mask, make
4539 a block cursor visible by drawing a rectangle around
4540 the image. I believe it's looking better if we do
4541 nothing here for mouse-face. */
4542 if (s->hl == DRAW_CURSOR)
4543 {
4544 int r = s->img->relief;
4545 if (r < 0) r = -r;
4546 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4547 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4548 }
4549 }
4550 }
4551 else
4552 /* Draw a rectangle if image could not be loaded. */
4553 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4554 s->img->width - 1, s->img->height - 1);
4555 }
4556
4557
4558 /* Draw part of the background of glyph string S. X, Y, W, and H
4559 give the rectangle to draw. */
4560
4561 static void
4562 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4563 struct glyph_string *s;
4564 int x, y, w, h;
4565 {
4566 #if 0 /* MAC_TODO: stipple */
4567 if (s->stippled_p)
4568 {
4569 /* Fill background with a stipple pattern. */
4570 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4571 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4572 XSetFillStyle (s->display, s->gc, FillSolid);
4573 }
4574 else
4575 #endif /* MAC_TODO */
4576 x_clear_glyph_string_rect (s, x, y, w, h);
4577 }
4578
4579
4580 /* Draw image glyph string S.
4581
4582 s->y
4583 s->x +-------------------------
4584 | s->face->box
4585 |
4586 | +-------------------------
4587 | | s->img->vmargin
4588 | |
4589 | | +-------------------
4590 | | | the image
4591
4592 */
4593
4594 static void
4595 x_draw_image_glyph_string (s)
4596 struct glyph_string *s;
4597 {
4598 int x, y;
4599 int box_line_hwidth = abs (s->face->box_line_width);
4600 int box_line_vwidth = max (s->face->box_line_width, 0);
4601 int height;
4602 Pixmap pixmap = 0;
4603
4604 height = s->height - 2 * box_line_vwidth;
4605
4606 /* Fill background with face under the image. Do it only if row is
4607 taller than image or if image has a clip mask to reduce
4608 flickering. */
4609 s->stippled_p = s->face->stipple != 0;
4610 if (height > s->img->height
4611 || s->img->hmargin
4612 || s->img->vmargin
4613 #if 0 /* TODO: image mask */
4614 || s->img->mask
4615 #endif
4616 || s->img->pixmap == 0
4617 || s->width != s->background_width)
4618 {
4619 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4620 x = s->x + box_line_hwidth;
4621 else
4622 x = s->x;
4623
4624 y = s->y + box_line_vwidth;
4625 #if 0 /* TODO: image mask */
4626 if (s->img->mask)
4627 {
4628 /* Create a pixmap as large as the glyph string. Fill it
4629 with the background color. Copy the image to it, using
4630 its mask. Copy the temporary pixmap to the display. */
4631 Screen *screen = FRAME_X_SCREEN (s->f);
4632 int depth = DefaultDepthOfScreen (screen);
4633
4634 /* Create a pixmap as large as the glyph string. */
4635 pixmap = XCreatePixmap (s->display, s->window,
4636 s->background_width,
4637 s->height, depth);
4638
4639 /* Don't clip in the following because we're working on the
4640 pixmap. */
4641 XSetClipMask (s->display, s->gc, None);
4642
4643 /* Fill the pixmap with the background color/stipple. */
4644 if (s->stippled_p)
4645 {
4646 /* Fill background with a stipple pattern. */
4647 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4648 XFillRectangle (s->display, pixmap, s->gc,
4649 0, 0, s->background_width, s->height);
4650 XSetFillStyle (s->display, s->gc, FillSolid);
4651 }
4652 else
4653 {
4654 XGCValues xgcv;
4655 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4656 &xgcv);
4657 XSetForeground (s->display, s->gc, xgcv.background);
4658 XFillRectangle (s->display, pixmap, s->gc,
4659 0, 0, s->background_width, s->height);
4660 XSetForeground (s->display, s->gc, xgcv.foreground);
4661 }
4662 }
4663 else
4664 #endif
4665 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4666
4667 s->background_filled_p = 1;
4668 }
4669
4670 /* Draw the foreground. */
4671 if (pixmap != 0)
4672 {
4673 x_draw_image_foreground_1 (s, pixmap);
4674 x_set_glyph_string_clipping (s);
4675 mac_copy_area (s->display, pixmap, s->window, s->gc,
4676 0, 0, s->background_width, s->height, s->x, s->y);
4677 mac_reset_clipping (s->display, s->window);
4678 XFreePixmap (s->display, pixmap);
4679 }
4680 else
4681 x_draw_image_foreground (s);
4682
4683 /* If we must draw a relief around the image, do it. */
4684 if (s->img->relief
4685 || s->hl == DRAW_IMAGE_RAISED
4686 || s->hl == DRAW_IMAGE_SUNKEN)
4687 x_draw_image_relief (s);
4688 }
4689
4690
4691 /* Draw stretch glyph string S. */
4692
4693 static void
4694 x_draw_stretch_glyph_string (s)
4695 struct glyph_string *s;
4696 {
4697 xassert (s->first_glyph->type == STRETCH_GLYPH);
4698 s->stippled_p = s->face->stipple != 0;
4699
4700 if (s->hl == DRAW_CURSOR
4701 && !x_stretch_cursor_p)
4702 {
4703 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4704 as wide as the stretch glyph. */
4705 int width = min (CANON_X_UNIT (s->f), s->background_width);
4706
4707 /* Draw cursor. */
4708 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4709
4710 /* Clear rest using the GC of the original non-cursor face. */
4711 if (width < s->background_width)
4712 {
4713 GC gc = s->face->gc;
4714 int x = s->x + width, y = s->y;
4715 int w = s->background_width - width, h = s->height;
4716 Rect r;
4717
4718 if (s->row->mouse_face_p
4719 && cursor_in_mouse_face_p (s->w))
4720 {
4721 x_set_mouse_face_gc (s);
4722 gc = s->gc;
4723 }
4724 else
4725 gc = s->face->gc;
4726
4727 x_get_glyph_string_clip_rect (s, &r);
4728 mac_set_clip_rectangle (s->display, s->window, &r);
4729
4730 #if 0 /* MAC_TODO: stipple */
4731 if (s->face->stipple)
4732 {
4733 /* Fill background with a stipple pattern. */
4734 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4735 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4736 XSetFillStyle (s->display, gc, FillSolid);
4737 }
4738 else
4739 #endif /* MAC_TODO */
4740 {
4741 XGCValues xgcv;
4742 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4743 XSetForeground (s->display, gc, xgcv.background);
4744 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4745 XSetForeground (s->display, gc, xgcv.foreground);
4746 }
4747
4748 mac_reset_clipping (s->display, s->window);
4749 }
4750 }
4751 else if (!s->background_filled_p)
4752 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4753 s->height);
4754
4755 s->background_filled_p = 1;
4756 }
4757
4758
4759 /* Draw glyph string S. */
4760
4761 static void
4762 x_draw_glyph_string (s)
4763 struct glyph_string *s;
4764 {
4765 int relief_drawn_p = 0;
4766
4767 /* If S draws into the background of its successor, draw the
4768 background of the successor first so that S can draw into it.
4769 This makes S->next use XDrawString instead of XDrawImageString. */
4770 if (s->next && s->right_overhang && !s->for_overlaps_p)
4771 {
4772 xassert (s->next->img == NULL);
4773 x_set_glyph_string_gc (s->next);
4774 x_set_glyph_string_clipping (s->next);
4775 x_draw_glyph_string_background (s->next, 1);
4776
4777 }
4778
4779 /* Set up S->gc, set clipping and draw S. */
4780 x_set_glyph_string_gc (s);
4781
4782 /* Draw relief (if any) in advance for char/composition so that the
4783 glyph string can be drawn over it. */
4784 if (!s->for_overlaps_p
4785 && s->face->box != FACE_NO_BOX
4786 && (s->first_glyph->type == CHAR_GLYPH
4787 || s->first_glyph->type == COMPOSITE_GLYPH))
4788
4789 {
4790 x_set_glyph_string_clipping (s);
4791 x_draw_glyph_string_background (s, 1);
4792 x_draw_glyph_string_box (s);
4793 x_set_glyph_string_clipping (s);
4794 relief_drawn_p = 1;
4795 }
4796 else
4797 x_set_glyph_string_clipping (s);
4798
4799 switch (s->first_glyph->type)
4800 {
4801 case IMAGE_GLYPH:
4802 x_draw_image_glyph_string (s);
4803 break;
4804
4805 case STRETCH_GLYPH:
4806 x_draw_stretch_glyph_string (s);
4807 break;
4808
4809 case CHAR_GLYPH:
4810 if (s->for_overlaps_p)
4811 s->background_filled_p = 1;
4812 else
4813 x_draw_glyph_string_background (s, 0);
4814 x_draw_glyph_string_foreground (s);
4815 break;
4816
4817 case COMPOSITE_GLYPH:
4818 if (s->for_overlaps_p || s->gidx > 0)
4819 s->background_filled_p = 1;
4820 else
4821 x_draw_glyph_string_background (s, 1);
4822 x_draw_composite_glyph_string_foreground (s);
4823 break;
4824
4825 default:
4826 abort ();
4827 }
4828
4829 if (!s->for_overlaps_p)
4830 {
4831 /* Draw underline. */
4832 if (s->face->underline_p)
4833 {
4834 unsigned long h = 1;
4835 unsigned long dy = s->height - h;
4836
4837 if (s->face->underline_defaulted_p)
4838 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4839 s->width, h);
4840 else
4841 {
4842 XGCValues xgcv;
4843 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4844 XSetForeground (s->display, s->gc, s->face->underline_color);
4845 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4846 s->width, h);
4847 XSetForeground (s->display, s->gc, xgcv.foreground);
4848 }
4849 }
4850
4851 /* Draw overline. */
4852 if (s->face->overline_p)
4853 {
4854 unsigned long dy = 0, h = 1;
4855
4856 if (s->face->overline_color_defaulted_p)
4857 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4858 s->width, h);
4859 else
4860 {
4861 XGCValues xgcv;
4862 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4863 XSetForeground (s->display, s->gc, s->face->overline_color);
4864 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4865 s->width, h);
4866 XSetForeground (s->display, s->gc, xgcv.foreground);
4867 }
4868 }
4869
4870 /* Draw strike-through. */
4871 if (s->face->strike_through_p)
4872 {
4873 unsigned long h = 1;
4874 unsigned long dy = (s->height - h) / 2;
4875
4876 if (s->face->strike_through_color_defaulted_p)
4877 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4878 s->width, h);
4879 else
4880 {
4881 XGCValues xgcv;
4882 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4883 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4884 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4885 s->width, h);
4886 XSetForeground (s->display, s->gc, xgcv.foreground);
4887 }
4888 }
4889
4890 /* Draw relief. */
4891 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4892 x_draw_glyph_string_box (s);
4893 }
4894
4895 /* Reset clipping. */
4896 mac_reset_clipping (s->display, s->window);
4897 }
4898
4899
4900 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4901 struct face **, int));
4902
4903
4904 /* Fill glyph string S with composition components specified by S->cmp.
4905
4906 FACES is an array of faces for all components of this composition.
4907 S->gidx is the index of the first component for S.
4908 OVERLAPS_P non-zero means S should draw the foreground only, and
4909 use its physical height for clipping.
4910
4911 Value is the index of a component not in S. */
4912
4913 static int
4914 x_fill_composite_glyph_string (s, faces, overlaps_p)
4915 struct glyph_string *s;
4916 struct face **faces;
4917 int overlaps_p;
4918 {
4919 int i;
4920
4921 xassert (s);
4922
4923 s->for_overlaps_p = overlaps_p;
4924
4925 s->face = faces[s->gidx];
4926 s->font = s->face->font;
4927 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4928
4929 /* For all glyphs of this composition, starting at the offset
4930 S->gidx, until we reach the end of the definition or encounter a
4931 glyph that requires the different face, add it to S. */
4932 ++s->nchars;
4933 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4934 ++s->nchars;
4935
4936 /* All glyph strings for the same composition has the same width,
4937 i.e. the width set for the first component of the composition. */
4938
4939 s->width = s->first_glyph->pixel_width;
4940
4941 /* If the specified font could not be loaded, use the frame's
4942 default font, but record the fact that we couldn't load it in
4943 the glyph string so that we can draw rectangles for the
4944 characters of the glyph string. */
4945 if (s->font == NULL)
4946 {
4947 s->font_not_found_p = 1;
4948 s->font = FRAME_FONT (s->f);
4949 }
4950
4951 /* Adjust base line for subscript/superscript text. */
4952 s->ybase += s->first_glyph->voffset;
4953
4954 xassert (s->face && s->face->gc);
4955
4956 /* This glyph string must always be drawn with 16-bit functions. */
4957 s->two_byte_p = 1;
4958
4959 return s->gidx + s->nchars;
4960 }
4961
4962
4963 /* Fill glyph string S from a sequence of character glyphs.
4964
4965 FACE_ID is the face id of the string. START is the index of the
4966 first glyph to consider, END is the index of the last + 1.
4967 OVERLAPS_P non-zero means S should draw the foreground only, and
4968 use its physical height for clipping.
4969
4970 Value is the index of the first glyph not in S. */
4971
4972 static int
4973 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4974 struct glyph_string *s;
4975 int face_id;
4976 int start, end, overlaps_p;
4977 {
4978 struct glyph *glyph, *last;
4979 int voffset;
4980 int glyph_not_available_p;
4981
4982 xassert (s->f == XFRAME (s->w->frame));
4983 xassert (s->nchars == 0);
4984 xassert (start >= 0 && end > start);
4985
4986 s->for_overlaps_p = overlaps_p;
4987 glyph = s->row->glyphs[s->area] + start;
4988 last = s->row->glyphs[s->area] + end;
4989 voffset = glyph->voffset;
4990
4991 glyph_not_available_p = glyph->glyph_not_available_p;
4992
4993 while (glyph < last
4994 && glyph->type == CHAR_GLYPH
4995 && glyph->voffset == voffset
4996 /* Same face id implies same font, nowadays. */
4997 && glyph->face_id == face_id
4998 && glyph->glyph_not_available_p == glyph_not_available_p)
4999 {
5000 int two_byte_p;
5001
5002 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
5003 s->char2b + s->nchars,
5004 &two_byte_p);
5005 s->two_byte_p = two_byte_p;
5006 ++s->nchars;
5007 xassert (s->nchars <= end - start);
5008 s->width += glyph->pixel_width;
5009 ++glyph;
5010 }
5011
5012 s->font = s->face->font;
5013 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5014
5015 /* If the specified font could not be loaded, use the frame's font,
5016 but record the fact that we couldn't load it in
5017 S->font_not_found_p so that we can draw rectangles for the
5018 characters of the glyph string. */
5019 if (s->font == NULL || glyph_not_available_p)
5020 {
5021 s->font_not_found_p = 1;
5022 s->font = FRAME_FONT (s->f);
5023 }
5024
5025 /* Adjust base line for subscript/superscript text. */
5026 s->ybase += voffset;
5027
5028 xassert (s->face && s->face->gc);
5029 return glyph - s->row->glyphs[s->area];
5030 }
5031
5032
5033 /* Fill glyph string S from image glyph S->first_glyph. */
5034
5035 static void
5036 x_fill_image_glyph_string (s)
5037 struct glyph_string *s;
5038 {
5039 xassert (s->first_glyph->type == IMAGE_GLYPH);
5040 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5041 xassert (s->img);
5042 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5043 s->font = s->face->font;
5044 s->width = s->first_glyph->pixel_width;
5045
5046 /* Adjust base line for subscript/superscript text. */
5047 s->ybase += s->first_glyph->voffset;
5048 }
5049
5050
5051 /* Fill glyph string S from a sequence of stretch glyphs.
5052
5053 ROW is the glyph row in which the glyphs are found, AREA is the
5054 area within the row. START is the index of the first glyph to
5055 consider, END is the index of the last + 1.
5056
5057 Value is the index of the first glyph not in S. */
5058
5059 static int
5060 x_fill_stretch_glyph_string (s, row, area, start, end)
5061 struct glyph_string *s;
5062 struct glyph_row *row;
5063 enum glyph_row_area area;
5064 int start, end;
5065 {
5066 struct glyph *glyph, *last;
5067 int voffset, face_id;
5068
5069 xassert (s->first_glyph->type == STRETCH_GLYPH);
5070
5071 glyph = s->row->glyphs[s->area] + start;
5072 last = s->row->glyphs[s->area] + end;
5073 face_id = glyph->face_id;
5074 s->face = FACE_FROM_ID (s->f, face_id);
5075 s->font = s->face->font;
5076 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5077 s->width = glyph->pixel_width;
5078 voffset = glyph->voffset;
5079
5080 for (++glyph;
5081 (glyph < last
5082 && glyph->type == STRETCH_GLYPH
5083 && glyph->voffset == voffset
5084 && glyph->face_id == face_id);
5085 ++glyph)
5086 s->width += glyph->pixel_width;
5087
5088 /* Adjust base line for subscript/superscript text. */
5089 s->ybase += voffset;
5090
5091 xassert (s->face);
5092 return glyph - s->row->glyphs[s->area];
5093 }
5094
5095
5096 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
5097 of XChar2b structures for S; it can't be allocated in
5098 x_init_glyph_string because it must be allocated via `alloca'. W
5099 is the window on which S is drawn. ROW and AREA are the glyph row
5100 and area within the row from which S is constructed. START is the
5101 index of the first glyph structure covered by S. HL is a
5102 face-override for drawing S. */
5103
5104 static void
5105 x_init_glyph_string (s, char2b, w, row, area, start, hl)
5106 struct glyph_string *s;
5107 XChar2b *char2b;
5108 struct window *w;
5109 struct glyph_row *row;
5110 enum glyph_row_area area;
5111 int start;
5112 enum draw_glyphs_face hl;
5113 {
5114 bzero (s, sizeof *s);
5115 s->w = w;
5116 s->f = XFRAME (w->frame);
5117 s->display = FRAME_MAC_DISPLAY (s->f);
5118 s->window = FRAME_MAC_WINDOW (s->f);
5119 s->char2b = char2b;
5120 s->hl = hl;
5121 s->row = row;
5122 s->area = area;
5123 s->first_glyph = row->glyphs[area] + start;
5124 s->height = row->height;
5125 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5126
5127 /* Display the internal border below the tool-bar window. */
5128 if (s->w == XWINDOW (s->f->tool_bar_window))
5129 s->y -= s->f->output_data.mac->internal_border_width;
5130
5131 s->ybase = s->y + row->ascent;
5132 }
5133
5134
5135 /* Set background width of glyph string S. START is the index of the
5136 first glyph following S. LAST_X is the right-most x-position + 1
5137 in the drawing area. */
5138
5139 static INLINE void
5140 x_set_glyph_string_background_width (s, start, last_x)
5141 struct glyph_string *s;
5142 int start;
5143 int last_x;
5144 {
5145 /* If the face of this glyph string has to be drawn to the end of
5146 the drawing area, set S->extends_to_end_of_line_p. */
5147 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
5148
5149 if (start == s->row->used[s->area]
5150 && s->area == TEXT_AREA
5151 && ((s->hl == DRAW_NORMAL_TEXT
5152 && (s->row->fill_line_p
5153 || s->face->background != default_face->background
5154 || s->face->stipple != default_face->stipple
5155 || s->row->mouse_face_p))
5156 || s->hl == DRAW_MOUSE_FACE
5157 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5158 && s->row->fill_line_p)))
5159 s->extends_to_end_of_line_p = 1;
5160
5161 /* If S extends its face to the end of the line, set its
5162 background_width to the distance to the right edge of the drawing
5163 area. */
5164 if (s->extends_to_end_of_line_p)
5165 s->background_width = last_x - s->x + 1;
5166 else
5167 s->background_width = s->width;
5168 }
5169
5170
5171 /* Add a glyph string for a stretch glyph to the list of strings
5172 between HEAD and TAIL. START is the index of the stretch glyph in
5173 row area AREA of glyph row ROW. END is the index of the last glyph
5174 in that glyph row area. X is the current output position assigned
5175 to the new glyph string constructed. HL overrides that face of the
5176 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5177 is the right-most x-position of the drawing area. */
5178
5179 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5180 and below -- keep them on one line. */
5181 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5182 do \
5183 { \
5184 s = (struct glyph_string *) alloca (sizeof *s); \
5185 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5186 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5187 x_append_glyph_string (&HEAD, &TAIL, s); \
5188 s->x = (X); \
5189 } \
5190 while (0)
5191
5192
5193 /* Add a glyph string for an image glyph to the list of strings
5194 between HEAD and TAIL. START is the index of the image glyph in
5195 row area AREA of glyph row ROW. END is the index of the last glyph
5196 in that glyph row area. X is the current output position assigned
5197 to the new glyph string constructed. HL overrides that face of the
5198 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5199 is the right-most x-position of the drawing area. */
5200
5201 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5202 do \
5203 { \
5204 s = (struct glyph_string *) alloca (sizeof *s); \
5205 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5206 x_fill_image_glyph_string (s); \
5207 x_append_glyph_string (&HEAD, &TAIL, s); \
5208 ++START; \
5209 s->x = (X); \
5210 } \
5211 while (0)
5212
5213
5214 /* Add a glyph string for a sequence of character glyphs to the list
5215 of strings between HEAD and TAIL. START is the index of the first
5216 glyph in row area AREA of glyph row ROW that is part of the new
5217 glyph string. END is the index of the last glyph in that glyph row
5218 area. X is the current output position assigned to the new glyph
5219 string constructed. HL overrides that face of the glyph; e.g. it
5220 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5221 right-most x-position of the drawing area. */
5222
5223 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5224 do \
5225 { \
5226 int c, face_id; \
5227 XChar2b *char2b; \
5228 \
5229 c = (ROW)->glyphs[AREA][START].u.ch; \
5230 face_id = (ROW)->glyphs[AREA][START].face_id; \
5231 \
5232 s = (struct glyph_string *) alloca (sizeof *s); \
5233 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5234 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5235 x_append_glyph_string (&HEAD, &TAIL, s); \
5236 s->x = (X); \
5237 START = x_fill_glyph_string (s, face_id, START, END, \
5238 OVERLAPS_P); \
5239 } \
5240 while (0)
5241
5242
5243 /* Add a glyph string for a composite sequence to the list of strings
5244 between HEAD and TAIL. START is the index of the first glyph in
5245 row area AREA of glyph row ROW that is part of the new glyph
5246 string. END is the index of the last glyph in that glyph row area.
5247 X is the current output position assigned to the new glyph string
5248 constructed. HL overrides that face of the glyph; e.g. it is
5249 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5250 x-position of the drawing area. */
5251
5252 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5253 do { \
5254 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5255 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5256 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5257 struct composition *cmp = composition_table[cmp_id]; \
5258 int glyph_len = cmp->glyph_len; \
5259 XChar2b *char2b; \
5260 struct face **faces; \
5261 struct glyph_string *first_s = NULL; \
5262 int n; \
5263 \
5264 base_face = base_face->ascii_face; \
5265 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5266 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5267 /* At first, fill in `char2b' and `faces'. */ \
5268 for (n = 0; n < glyph_len; n++) \
5269 { \
5270 int c = COMPOSITION_GLYPH (cmp, n); \
5271 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5272 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5273 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5274 this_face_id, char2b + n, 1); \
5275 } \
5276 \
5277 /* Make glyph_strings for each glyph sequence that is drawable by \
5278 the same face, and append them to HEAD/TAIL. */ \
5279 for (n = 0; n < cmp->glyph_len;) \
5280 { \
5281 s = (struct glyph_string *) alloca (sizeof *s); \
5282 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5283 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5284 s->cmp = cmp; \
5285 s->gidx = n; \
5286 s->x = (X); \
5287 \
5288 if (n == 0) \
5289 first_s = s; \
5290 \
5291 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5292 } \
5293 \
5294 ++START; \
5295 s = first_s; \
5296 } while (0)
5297
5298
5299 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5300 of AREA of glyph row ROW on window W between indices START and END.
5301 HL overrides the face for drawing glyph strings, e.g. it is
5302 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5303 x-positions of the drawing area.
5304
5305 This is an ugly monster macro construct because we must use alloca
5306 to allocate glyph strings (because x_draw_glyphs can be called
5307 asynchronously). */
5308
5309 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5310 do \
5311 { \
5312 HEAD = TAIL = NULL; \
5313 while (START < END) \
5314 { \
5315 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5316 switch (first_glyph->type) \
5317 { \
5318 case CHAR_GLYPH: \
5319 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5320 TAIL, HL, X, LAST_X, \
5321 OVERLAPS_P); \
5322 break; \
5323 \
5324 case COMPOSITE_GLYPH: \
5325 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5326 HEAD, TAIL, HL, X, LAST_X,\
5327 OVERLAPS_P); \
5328 break; \
5329 \
5330 case STRETCH_GLYPH: \
5331 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5332 HEAD, TAIL, HL, X, LAST_X); \
5333 break; \
5334 \
5335 case IMAGE_GLYPH: \
5336 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5337 TAIL, HL, X, LAST_X); \
5338 break; \
5339 \
5340 default: \
5341 abort (); \
5342 } \
5343 \
5344 x_set_glyph_string_background_width (s, START, LAST_X); \
5345 (X) += s->width; \
5346 } \
5347 } \
5348 while (0)
5349
5350
5351 /* Draw glyphs between START and END in AREA of ROW on window W,
5352 starting at x-position X. X is relative to AREA in W. HL is a
5353 face-override with the following meaning:
5354
5355 DRAW_NORMAL_TEXT draw normally
5356 DRAW_CURSOR draw in cursor face
5357 DRAW_MOUSE_FACE draw in mouse face.
5358 DRAW_INVERSE_VIDEO draw in mode line face
5359 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5360 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5361
5362 If OVERLAPS_P is non-zero, draw only the foreground of characters
5363 and clip to the physical height of ROW.
5364
5365 Value is the x-position reached, relative to AREA of W. */
5366
5367 static int
5368 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5369 struct window *w;
5370 int x;
5371 struct glyph_row *row;
5372 enum glyph_row_area area;
5373 int start, end;
5374 enum draw_glyphs_face hl;
5375 int overlaps_p;
5376 {
5377 struct glyph_string *head, *tail;
5378 struct glyph_string *s;
5379 int last_x, area_width;
5380 int x_reached;
5381 int i, j;
5382
5383 /* Let's rather be paranoid than getting a SEGV. */
5384 end = min (end, row->used[area]);
5385 start = max (0, start);
5386 start = min (end, start);
5387
5388 /* Translate X to frame coordinates. Set last_x to the right
5389 end of the drawing area. */
5390 if (row->full_width_p)
5391 {
5392 /* X is relative to the left edge of W, without scroll bars
5393 or fringes. */
5394 struct frame *f = XFRAME (WINDOW_FRAME (w));
5395 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5396
5397 x += window_left_x;
5398 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5399 last_x = window_left_x + area_width;
5400
5401 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5402 {
5403 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5404 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5405 last_x += width;
5406 else
5407 x -= width;
5408 }
5409
5410 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5411 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5412 }
5413 else
5414 {
5415 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5416 area_width = window_box_width (w, area);
5417 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5418 }
5419
5420 /* Build a doubly-linked list of glyph_string structures between
5421 head and tail from what we have to draw. Note that the macro
5422 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5423 the reason we use a separate variable `i'. */
5424 i = start;
5425 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5426 overlaps_p);
5427 if (tail)
5428 x_reached = tail->x + tail->background_width;
5429 else
5430 x_reached = x;
5431
5432 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5433 the row, redraw some glyphs in front or following the glyph
5434 strings built above. */
5435 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5436 {
5437 int dummy_x = 0;
5438 struct glyph_string *h, *t;
5439
5440 /* Compute overhangs for all glyph strings. */
5441 for (s = head; s; s = s->next)
5442 x_compute_glyph_string_overhangs (s);
5443
5444 /* Prepend glyph strings for glyphs in front of the first glyph
5445 string that are overwritten because of the first glyph
5446 string's left overhang. The background of all strings
5447 prepended must be drawn because the first glyph string
5448 draws over it. */
5449 i = x_left_overwritten (head);
5450 if (i >= 0)
5451 {
5452 j = i;
5453 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5454 DRAW_NORMAL_TEXT, dummy_x, last_x,
5455 overlaps_p);
5456 start = i;
5457 x_compute_overhangs_and_x (t, head->x, 1);
5458 x_prepend_glyph_string_lists (&head, &tail, h, t);
5459 }
5460
5461 /* Prepend glyph strings for glyphs in front of the first glyph
5462 string that overwrite that glyph string because of their
5463 right overhang. For these strings, only the foreground must
5464 be drawn, because it draws over the glyph string at `head'.
5465 The background must not be drawn because this would overwrite
5466 right overhangs of preceding glyphs for which no glyph
5467 strings exist. */
5468 i = x_left_overwriting (head);
5469 if (i >= 0)
5470 {
5471 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5472 DRAW_NORMAL_TEXT, dummy_x, last_x,
5473 overlaps_p);
5474 for (s = h; s; s = s->next)
5475 s->background_filled_p = 1;
5476 x_compute_overhangs_and_x (t, head->x, 1);
5477 x_prepend_glyph_string_lists (&head, &tail, h, t);
5478 }
5479
5480 /* Append glyphs strings for glyphs following the last glyph
5481 string tail that are overwritten by tail. The background of
5482 these strings has to be drawn because tail's foreground draws
5483 over it. */
5484 i = x_right_overwritten (tail);
5485 if (i >= 0)
5486 {
5487 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5488 DRAW_NORMAL_TEXT, x, last_x,
5489 overlaps_p);
5490 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5491 x_append_glyph_string_lists (&head, &tail, h, t);
5492 }
5493
5494 /* Append glyph strings for glyphs following the last glyph
5495 string tail that overwrite tail. The foreground of such
5496 glyphs has to be drawn because it writes into the background
5497 of tail. The background must not be drawn because it could
5498 paint over the foreground of following glyphs. */
5499 i = x_right_overwriting (tail);
5500 if (i >= 0)
5501 {
5502 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5503 DRAW_NORMAL_TEXT, x, last_x,
5504 overlaps_p);
5505 for (s = h; s; s = s->next)
5506 s->background_filled_p = 1;
5507 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5508 x_append_glyph_string_lists (&head, &tail, h, t);
5509 }
5510 }
5511
5512 /* Draw all strings. */
5513 for (s = head; s; s = s->next)
5514 x_draw_glyph_string (s);
5515
5516 if (area == TEXT_AREA
5517 && !row->full_width_p
5518 /* When drawing overlapping rows, only the glyph strings'
5519 foreground is drawn, which doesn't erase a cursor
5520 completely. */
5521 && !overlaps_p)
5522 {
5523 int x0 = head ? head->x : x;
5524 int x1 = tail ? tail->x + tail->background_width : x;
5525
5526 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5527 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5528
5529 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5530 {
5531 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5532 x0 -= left_area_width;
5533 x1 -= left_area_width;
5534 }
5535
5536 notice_overwritten_cursor (w, area, x0, x1,
5537 row->y, MATRIX_ROW_BOTTOM_Y (row));
5538 }
5539
5540 /* Value is the x-position up to which drawn, relative to AREA of W.
5541 This doesn't include parts drawn because of overhangs. */
5542 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5543 if (!row->full_width_p)
5544 {
5545 if (area > LEFT_MARGIN_AREA)
5546 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5547 if (area > TEXT_AREA)
5548 x_reached -= window_box_width (w, TEXT_AREA);
5549 }
5550
5551 return x_reached;
5552 }
5553
5554
5555 /* Fix the display of area AREA of overlapping row ROW in window W. */
5556
5557 static void
5558 x_fix_overlapping_area (w, row, area)
5559 struct window *w;
5560 struct glyph_row *row;
5561 enum glyph_row_area area;
5562 {
5563 int i, x;
5564
5565 BLOCK_INPUT;
5566
5567 if (area == LEFT_MARGIN_AREA)
5568 x = 0;
5569 else if (area == TEXT_AREA)
5570 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5571 else
5572 x = (window_box_width (w, LEFT_MARGIN_AREA)
5573 + window_box_width (w, TEXT_AREA));
5574
5575 for (i = 0; i < row->used[area];)
5576 {
5577 if (row->glyphs[area][i].overlaps_vertically_p)
5578 {
5579 int start = i, start_x = x;
5580
5581 do
5582 {
5583 x += row->glyphs[area][i].pixel_width;
5584 ++i;
5585 }
5586 while (i < row->used[area]
5587 && row->glyphs[area][i].overlaps_vertically_p);
5588
5589 x_draw_glyphs (w, start_x, row, area, start, i,
5590 DRAW_NORMAL_TEXT, 1);
5591 }
5592 else
5593 {
5594 x += row->glyphs[area][i].pixel_width;
5595 ++i;
5596 }
5597 }
5598
5599 UNBLOCK_INPUT;
5600 }
5601
5602
5603 /* Output LEN glyphs starting at START at the nominal cursor position.
5604 Advance the nominal cursor over the text. The global variable
5605 updated_window contains the window being updated, updated_row is
5606 the glyph row being updated, and updated_area is the area of that
5607 row being updated. */
5608
5609 static void
5610 x_write_glyphs (start, len)
5611 struct glyph *start;
5612 int len;
5613 {
5614 int x, hpos;
5615
5616 xassert (updated_window && updated_row);
5617 BLOCK_INPUT;
5618
5619 /* Write glyphs. */
5620
5621 hpos = start - updated_row->glyphs[updated_area];
5622 x = x_draw_glyphs (updated_window, output_cursor.x,
5623 updated_row, updated_area,
5624 hpos, hpos + len,
5625 DRAW_NORMAL_TEXT, 0);
5626
5627 UNBLOCK_INPUT;
5628
5629 /* Advance the output cursor. */
5630 output_cursor.hpos += len;
5631 output_cursor.x = x;
5632 }
5633
5634
5635 /* Insert LEN glyphs from START at the nominal cursor position. */
5636
5637 static void
5638 x_insert_glyphs (start, len)
5639 struct glyph *start;
5640 register int len;
5641 {
5642 struct frame *f;
5643 struct window *w;
5644 int line_height, shift_by_width, shifted_region_width;
5645 struct glyph_row *row;
5646 struct glyph *glyph;
5647 int frame_x, frame_y, hpos;
5648
5649 xassert (updated_window && updated_row);
5650 BLOCK_INPUT;
5651 w = updated_window;
5652 f = XFRAME (WINDOW_FRAME (w));
5653
5654 /* Get the height of the line we are in. */
5655 row = updated_row;
5656 line_height = row->height;
5657
5658 /* Get the width of the glyphs to insert. */
5659 shift_by_width = 0;
5660 for (glyph = start; glyph < start + len; ++glyph)
5661 shift_by_width += glyph->pixel_width;
5662
5663 /* Get the width of the region to shift right. */
5664 shifted_region_width = (window_box_width (w, updated_area)
5665 - output_cursor.x
5666 - shift_by_width);
5667
5668 /* Shift right. */
5669 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5670 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5671
5672 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5673 f->output_data.mac->normal_gc,
5674 frame_x, frame_y,
5675 shifted_region_width, line_height,
5676 frame_x + shift_by_width, frame_y);
5677
5678 /* Write the glyphs. */
5679 hpos = start - row->glyphs[updated_area];
5680 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5681 DRAW_NORMAL_TEXT, 0);
5682
5683 /* Advance the output cursor. */
5684 output_cursor.hpos += len;
5685 output_cursor.x += shift_by_width;
5686 UNBLOCK_INPUT;
5687 }
5688
5689
5690 /* Delete N glyphs at the nominal cursor position. Not implemented
5691 for X frames. */
5692
5693 static void
5694 x_delete_glyphs (n)
5695 register int n;
5696 {
5697 abort ();
5698 }
5699
5700
5701 /* Erase the current text line from the nominal cursor position
5702 (inclusive) to pixel column TO_X (exclusive). The idea is that
5703 everything from TO_X onward is already erased.
5704
5705 TO_X is a pixel position relative to updated_area of
5706 updated_window. TO_X == -1 means clear to the end of this area. */
5707
5708 static void
5709 x_clear_end_of_line (to_x)
5710 int to_x;
5711 {
5712 struct frame *f;
5713 struct window *w = updated_window;
5714 int max_x, min_y, max_y;
5715 int from_x, from_y, to_y;
5716
5717 xassert (updated_window && updated_row);
5718 f = XFRAME (w->frame);
5719
5720 if (updated_row->full_width_p)
5721 {
5722 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5723 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5724 && !w->pseudo_window_p)
5725 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5726 }
5727 else
5728 max_x = window_box_width (w, updated_area);
5729 max_y = window_text_bottom_y (w);
5730
5731 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5732 of window. For TO_X > 0, truncate to end of drawing area. */
5733 if (to_x == 0)
5734 return;
5735 else if (to_x < 0)
5736 to_x = max_x;
5737 else
5738 to_x = min (to_x, max_x);
5739
5740 to_y = min (max_y, output_cursor.y + updated_row->height);
5741
5742 /* Notice if the cursor will be cleared by this operation. */
5743 if (!updated_row->full_width_p)
5744 notice_overwritten_cursor (w, updated_area,
5745 output_cursor.x, -1,
5746 updated_row->y,
5747 MATRIX_ROW_BOTTOM_Y (updated_row));
5748
5749 from_x = output_cursor.x;
5750
5751 /* Translate to frame coordinates. */
5752 if (updated_row->full_width_p)
5753 {
5754 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5755 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5756 }
5757 else
5758 {
5759 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5760 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5761 }
5762
5763 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5764 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5765 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5766
5767 /* Prevent inadvertently clearing to end of the X window. */
5768 if (to_x > from_x && to_y > from_y)
5769 {
5770 BLOCK_INPUT;
5771 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5772 from_x, from_y, to_x - from_x, to_y - from_y,
5773 0);
5774 UNBLOCK_INPUT;
5775 }
5776 }
5777
5778
5779 /* Clear entire frame. If updating_frame is non-null, clear that
5780 frame. Otherwise clear the selected frame. */
5781
5782 static void
5783 x_clear_frame ()
5784 {
5785 struct frame *f;
5786
5787 if (updating_frame)
5788 f = updating_frame;
5789 else
5790 f = SELECTED_FRAME ();
5791
5792 /* Clearing the frame will erase any cursor, so mark them all as no
5793 longer visible. */
5794 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5795 output_cursor.hpos = output_cursor.vpos = 0;
5796 output_cursor.x = -1;
5797
5798 /* We don't set the output cursor here because there will always
5799 follow an explicit cursor_to. */
5800 BLOCK_INPUT;
5801 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5802
5803 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5804 /* We have to clear the scroll bars, too. If we have changed
5805 colors or something like that, then they should be notified. */
5806 x_scroll_bar_clear (f);
5807 #endif
5808
5809 XFlush (FRAME_MAC_DISPLAY (f));
5810 UNBLOCK_INPUT;
5811 }
5812
5813
5814 \f
5815 /* Invert the middle quarter of the frame for .15 sec. */
5816
5817 /* We use the select system call to do the waiting, so we have to make
5818 sure it's available. If it isn't, we just won't do visual bells. */
5819
5820 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5821
5822 /* Subtract the `struct timeval' values X and Y, storing the result in
5823 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5824
5825 static int
5826 timeval_subtract (result, x, y)
5827 struct timeval *result, x, y;
5828 {
5829 /* Perform the carry for the later subtraction by updating y. This
5830 is safer because on some systems the tv_sec member is unsigned. */
5831 if (x.tv_usec < y.tv_usec)
5832 {
5833 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5834 y.tv_usec -= 1000000 * nsec;
5835 y.tv_sec += nsec;
5836 }
5837
5838 if (x.tv_usec - y.tv_usec > 1000000)
5839 {
5840 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5841 y.tv_usec += 1000000 * nsec;
5842 y.tv_sec -= nsec;
5843 }
5844
5845 /* Compute the time remaining to wait. tv_usec is certainly
5846 positive. */
5847 result->tv_sec = x.tv_sec - y.tv_sec;
5848 result->tv_usec = x.tv_usec - y.tv_usec;
5849
5850 /* Return indication of whether the result should be considered
5851 negative. */
5852 return x.tv_sec < y.tv_sec;
5853 }
5854
5855 void
5856 XTflash (f)
5857 struct frame *f;
5858 {
5859 BLOCK_INPUT;
5860
5861 FlashMenuBar (0);
5862
5863 {
5864 struct timeval wakeup;
5865
5866 EMACS_GET_TIME (wakeup);
5867
5868 /* Compute time to wait until, propagating carry from usecs. */
5869 wakeup.tv_usec += 150000;
5870 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5871 wakeup.tv_usec %= 1000000;
5872
5873 /* Keep waiting until past the time wakeup. */
5874 while (1)
5875 {
5876 struct timeval timeout;
5877
5878 EMACS_GET_TIME (timeout);
5879
5880 /* In effect, timeout = wakeup - timeout.
5881 Break if result would be negative. */
5882 if (timeval_subtract (&timeout, wakeup, timeout))
5883 break;
5884
5885 /* Try to wait that long--but we might wake up sooner. */
5886 select (0, NULL, NULL, NULL, &timeout);
5887 }
5888 }
5889
5890 FlashMenuBar (0);
5891
5892 UNBLOCK_INPUT;
5893 }
5894
5895 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5896
5897
5898 /* Make audible bell. */
5899
5900 void
5901 XTring_bell ()
5902 {
5903 struct frame *f = SELECTED_FRAME ();
5904
5905 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5906 if (visible_bell)
5907 XTflash (f);
5908 else
5909 #endif
5910 {
5911 BLOCK_INPUT;
5912 SysBeep (1);
5913 XFlush (FRAME_MAC_DISPLAY (f));
5914 UNBLOCK_INPUT;
5915 }
5916 }
5917
5918
5919 \f
5920 /* Specify how many text lines, from the top of the window,
5921 should be affected by insert-lines and delete-lines operations.
5922 This, and those operations, are used only within an update
5923 that is bounded by calls to x_update_begin and x_update_end. */
5924
5925 void
5926 XTset_terminal_window (n)
5927 register int n;
5928 {
5929 /* This function intentionally left blank. */
5930 }
5931
5932
5933 \f
5934 /***********************************************************************
5935 Line Dance
5936 ***********************************************************************/
5937
5938 /* Perform an insert-lines or delete-lines operation, inserting N
5939 lines or deleting -N lines at vertical position VPOS. */
5940
5941 static void
5942 x_ins_del_lines (vpos, n)
5943 int vpos, n;
5944 {
5945 abort ();
5946 }
5947
5948
5949 /* Scroll part of the display as described by RUN. */
5950
5951 static void
5952 x_scroll_run (w, run)
5953 struct window *w;
5954 struct run *run;
5955 {
5956 struct frame *f = XFRAME (w->frame);
5957 int x, y, width, height, from_y, to_y, bottom_y;
5958
5959 /* Get frame-relative bounding box of the text display area of W,
5960 without mode lines. Include in this box the left and right
5961 fringes of W. */
5962 window_box (w, -1, &x, &y, &width, &height);
5963 width += FRAME_X_FRINGE_WIDTH (f);
5964 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5965
5966 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5967 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5968 bottom_y = y + height;
5969
5970 if (to_y < from_y)
5971 {
5972 /* Scrolling up. Make sure we don't copy part of the mode
5973 line at the bottom. */
5974 if (from_y + run->height > bottom_y)
5975 height = bottom_y - from_y;
5976 else
5977 height = run->height;
5978 }
5979 else
5980 {
5981 /* Scolling down. Make sure we don't copy over the mode line.
5982 at the bottom. */
5983 if (to_y + run->height > bottom_y)
5984 height = bottom_y - to_y;
5985 else
5986 height = run->height;
5987 }
5988
5989 BLOCK_INPUT;
5990
5991 /* Cursor off. Will be switched on again in x_update_window_end. */
5992 updated_window = w;
5993 x_clear_cursor (w);
5994
5995 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5996 f->output_data.mac->normal_gc,
5997 x, from_y,
5998 width, height,
5999 x, to_y);
6000
6001 UNBLOCK_INPUT;
6002 }
6003
6004
6005 \f
6006 /***********************************************************************
6007 Exposure Events
6008 ***********************************************************************/
6009
6010 /* Redisplay an exposed area of frame F. X and Y are the upper-left
6011 corner of the exposed rectangle. W and H are width and height of
6012 the exposed area. All are pixel values. W or H zero means redraw
6013 the entire frame. */
6014
6015 static void
6016 expose_frame (f, x, y, w, h)
6017 struct frame *f;
6018 int x, y, w, h;
6019 {
6020 Rect r;
6021 int mouse_face_overwritten_p = 0;
6022
6023 TRACE ((stderr, "expose_frame "));
6024
6025 /* No need to redraw if frame will be redrawn soon. */
6026 if (FRAME_GARBAGED_P (f))
6027 {
6028 TRACE ((stderr, " garbaged\n"));
6029 return;
6030 }
6031
6032 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6033 or deactivated here, for unknown reasons, activated scroll bars
6034 are shown in deactivated frames in some instances. */
6035 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6036 activate_scroll_bars (f);
6037 else
6038 deactivate_scroll_bars (f);
6039
6040 /* If basic faces haven't been realized yet, there is no point in
6041 trying to redraw anything. This can happen when we get an expose
6042 event while Emacs is starting, e.g. by moving another window. */
6043 if (FRAME_FACE_CACHE (f) == NULL
6044 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6045 {
6046 TRACE ((stderr, " no faces\n"));
6047 return;
6048 }
6049
6050 if (w == 0 || h == 0)
6051 {
6052 r.left = r.top = 0;
6053 r.right = CANON_X_UNIT (f) * f->width;
6054 r.bottom = CANON_Y_UNIT (f) * f->height;
6055 }
6056 else
6057 {
6058 r.left = x;
6059 r.top = y;
6060 r.right = x + w;
6061 r.bottom = y + h;
6062 }
6063
6064 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
6065 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
6066
6067 if (WINDOWP (f->tool_bar_window))
6068 mouse_face_overwritten_p
6069 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6070
6071 /* Some window managers support a focus-follows-mouse style with
6072 delayed raising of frames. Imagine a partially obscured frame,
6073 and moving the mouse into partially obscured mouse-face on that
6074 frame. The visible part of the mouse-face will be highlighted,
6075 then the WM raises the obscured frame. With at least one WM, KDE
6076 2.1, Emacs is not getting any event for the raising of the frame
6077 (even tried with SubstructureRedirectMask), only Expose events.
6078 These expose events will draw text normally, i.e. not
6079 highlighted. Which means we must redo the highlight here.
6080 Subsume it under ``we love X''. --gerd 2001-08-15 */
6081 /* Included in Windows version because Windows most likely does not
6082 do the right thing if any third party tool offers
6083 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6084 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
6085 {
6086 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6087 if (f == dpyinfo->mouse_face_mouse_frame)
6088 {
6089 int x = dpyinfo->mouse_face_mouse_x;
6090 int y = dpyinfo->mouse_face_mouse_y;
6091 clear_mouse_face (dpyinfo);
6092 note_mouse_highlight (f, x, y);
6093 }
6094 }
6095 }
6096
6097
6098 /* Redraw (parts) of all windows in the window tree rooted at W that
6099 intersect R. R contains frame pixel coordinates. */
6100
6101 static int
6102 expose_window_tree (w, r)
6103 struct window *w;
6104 Rect *r;
6105 {
6106 struct frame *f = XFRAME (w->frame);
6107 int mouse_face_overwritten_p = 0;
6108
6109 while (w && !FRAME_GARBAGED_P (f))
6110 {
6111 if (!NILP (w->hchild))
6112 mouse_face_overwritten_p
6113 |= expose_window_tree (XWINDOW (w->hchild), r);
6114 else if (!NILP (w->vchild))
6115 mouse_face_overwritten_p
6116 |= expose_window_tree (XWINDOW (w->vchild), r);
6117 else
6118 mouse_face_overwritten_p |= expose_window (w, r);
6119
6120 w = NILP (w->next) ? NULL : XWINDOW (w->next);
6121 }
6122
6123 return mouse_face_overwritten_p;
6124 }
6125
6126
6127 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
6128 which intersects rectangle R. R is in window-relative coordinates. */
6129
6130 static void
6131 expose_area (w, row, r, area)
6132 struct window *w;
6133 struct glyph_row *row;
6134 Rect *r;
6135 enum glyph_row_area area;
6136 {
6137 struct glyph *first = row->glyphs[area];
6138 struct glyph *end = row->glyphs[area] + row->used[area];
6139 struct glyph *last;
6140 int first_x, start_x, x;
6141
6142 if (area == TEXT_AREA && row->fill_line_p)
6143 /* If row extends face to end of line write the whole line. */
6144 x_draw_glyphs (w, 0, row, area,
6145 0, row->used[area],
6146 DRAW_NORMAL_TEXT, 0);
6147 else
6148 {
6149 /* Set START_X to the window-relative start position for drawing glyphs of
6150 AREA. The first glyph of the text area can be partially visible.
6151 The first glyphs of other areas cannot. */
6152 if (area == LEFT_MARGIN_AREA)
6153 start_x = 0;
6154 else if (area == TEXT_AREA)
6155 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6156 else
6157 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6158 + window_box_width (w, TEXT_AREA));
6159 x = start_x;
6160
6161 /* Find the first glyph that must be redrawn. */
6162 while (first < end
6163 && x + first->pixel_width < r->left)
6164 {
6165 x += first->pixel_width;
6166 ++first;
6167 }
6168
6169 /* Find the last one. */
6170 last = first;
6171 first_x = x;
6172 while (last < end
6173 && x < r->right)
6174 {
6175 x += last->pixel_width;
6176 ++last;
6177 }
6178
6179 /* Repaint. */
6180 if (last > first)
6181 x_draw_glyphs (w, first_x - start_x, row, area,
6182 first - row->glyphs[area],
6183 last - row->glyphs[area],
6184 DRAW_NORMAL_TEXT, 0);
6185 }
6186 }
6187
6188
6189 /* Redraw the parts of the glyph row ROW on window W intersecting
6190 rectangle R. R is in window-relative coordinates. Value is
6191 non-zero if mouse face was overwritten. */
6192
6193 static int
6194 expose_line (w, row, r)
6195 struct window *w;
6196 struct glyph_row *row;
6197 Rect *r;
6198 {
6199 xassert (row->enabled_p);
6200
6201 if (row->mode_line_p || w->pseudo_window_p)
6202 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6203 DRAW_NORMAL_TEXT, 0);
6204 else
6205 {
6206 if (row->used[LEFT_MARGIN_AREA])
6207 expose_area (w, row, r, LEFT_MARGIN_AREA);
6208 if (row->used[TEXT_AREA])
6209 expose_area (w, row, r, TEXT_AREA);
6210 if (row->used[RIGHT_MARGIN_AREA])
6211 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6212 x_draw_row_fringe_bitmaps (w, row);
6213 }
6214
6215 return row->mouse_face_p;
6216 }
6217
6218
6219 /* Return non-zero if W's cursor intersects rectangle R. */
6220
6221 static int
6222 x_phys_cursor_in_rect_p (w, r)
6223 struct window *w;
6224 Rect *r;
6225 {
6226 Rect cr, result;
6227 struct glyph *cursor_glyph;
6228
6229 cursor_glyph = get_phys_cursor_glyph (w);
6230 if (cursor_glyph)
6231 {
6232 cr.left = w->phys_cursor.x;
6233 cr.top = w->phys_cursor.y;
6234 cr.right = cr.left + cursor_glyph->pixel_width;
6235 cr.bottom = cr.top + w->phys_cursor_height;
6236 return x_intersect_rectangles (&cr, r, &result);
6237 }
6238 else
6239 return 0;
6240 }
6241
6242
6243 /* Redraw the part of window W intersection rectagle FR. Pixel
6244 coordinates in FR are frame relative. Call this function with
6245 input blocked. Value is non-zero if the exposure overwrites
6246 mouse-face. */
6247
6248 static int
6249 expose_window (w, fr)
6250 struct window *w;
6251 Rect *fr;
6252 {
6253 struct frame *f = XFRAME (w->frame);
6254 Rect wr, r;
6255 int mouse_face_overwritten_p = 0;
6256
6257 /* If window is not yet fully initialized, do nothing. This can
6258 happen when toolkit scroll bars are used and a window is split.
6259 Reconfiguring the scroll bar will generate an expose for a newly
6260 created window. */
6261 if (w->current_matrix == NULL)
6262 return 0;
6263
6264 /* When we're currently updating the window, display and current
6265 matrix usually don't agree. Arrange for a thorough display
6266 later. */
6267 if (w == updated_window)
6268 {
6269 SET_FRAME_GARBAGED (f);
6270 return 0;
6271 }
6272
6273 /* Frame-relative pixel rectangle of W. */
6274 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6275 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6276 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6277 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6278
6279 if (x_intersect_rectangles (fr, &wr, &r))
6280 {
6281 int yb = window_text_bottom_y (w);
6282 struct glyph_row *row;
6283 int cursor_cleared_p;
6284
6285 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6286 r.left, r.top, r.right, r.bottom));
6287
6288 /* Convert to window coordinates. */
6289 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6290 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6291 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6292 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6293
6294 /* Turn off the cursor. */
6295 if (!w->pseudo_window_p
6296 && x_phys_cursor_in_rect_p (w, &r))
6297 {
6298 x_clear_cursor (w);
6299 cursor_cleared_p = 1;
6300 }
6301 else
6302 cursor_cleared_p = 0;
6303
6304 /* Find the first row intersecting the rectangle R. */
6305 for (row = w->current_matrix->rows;
6306 row->enabled_p;
6307 ++row)
6308 {
6309 int y0 = row->y;
6310 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6311
6312 if ((y0 >= r.top && y0 < r.bottom)
6313 || (y1 > r.top && y1 < r.bottom)
6314 || (r.top >= y0 && r.top < y1)
6315 || (r.bottom > y0 && r.bottom < y1))
6316 {
6317 if (expose_line (w, row, &r))
6318 mouse_face_overwritten_p = 1;
6319 }
6320
6321 if (y1 >= yb)
6322 break;
6323 }
6324
6325 /* Display the mode line if there is one. */
6326 if (WINDOW_WANTS_MODELINE_P (w)
6327 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6328 row->enabled_p)
6329 && row->y < r.bottom)
6330 {
6331 if (expose_line (w, row, &r))
6332 mouse_face_overwritten_p = 1;
6333 }
6334
6335 if (!w->pseudo_window_p)
6336 {
6337 /* Draw border between windows. */
6338 x_draw_vertical_border (w);
6339
6340 /* Turn the cursor on again. */
6341 if (cursor_cleared_p)
6342 x_update_window_cursor (w, 1);
6343 }
6344 }
6345
6346 /* Display scroll bar for this window. */
6347 if (!NILP (w->vertical_scroll_bar))
6348 {
6349 ControlHandle ch
6350 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6351
6352 Draw1Control (ch);
6353 }
6354
6355 return mouse_face_overwritten_p;
6356 }
6357
6358 static int
6359 x_intersect_rectangles (r1, r2, result)
6360 Rect *r1, *r2, *result;
6361 {
6362 Rect *left, *right;
6363 Rect *upper, *lower;
6364 int intersection_p = 0;
6365
6366 /* Rerrange so that R1 is the left-most rectangle. */
6367 if (r1->left < r2->left)
6368 left = r1, right = r2;
6369 else
6370 left = r2, right = r1;
6371
6372 /* X0 of the intersection is right.x0, if this is inside R1,
6373 otherwise there is no intersection. */
6374 if (right->left <= left->right)
6375 {
6376 result->left = right->left;
6377
6378 /* The right end of the intersection is the minimum of the
6379 the right ends of left and right. */
6380 result->right = min (left->right, right->right);
6381
6382 /* Same game for Y. */
6383 if (r1->top < r2->top)
6384 upper = r1, lower = r2;
6385 else
6386 upper = r2, lower = r1;
6387
6388 /* The upper end of the intersection is lower.y0, if this is inside
6389 of upper. Otherwise, there is no intersection. */
6390 if (lower->top <= upper->bottom)
6391 {
6392 result->top = lower->top;
6393
6394 /* The lower end of the intersection is the minimum of the lower
6395 ends of upper and lower. */
6396 result->bottom = min (lower->bottom, upper->bottom);
6397 intersection_p = 1;
6398 }
6399 }
6400
6401 return intersection_p;
6402 }
6403
6404
6405
6406
6407 \f
6408 static void
6409 frame_highlight (f)
6410 struct frame *f;
6411 {
6412 x_update_cursor (f, 1);
6413 }
6414
6415 static void
6416 frame_unhighlight (f)
6417 struct frame *f;
6418 {
6419 x_update_cursor (f, 1);
6420 }
6421
6422 /* The focus has changed. Update the frames as necessary to reflect
6423 the new situation. Note that we can't change the selected frame
6424 here, because the Lisp code we are interrupting might become confused.
6425 Each event gets marked with the frame in which it occurred, so the
6426 Lisp code can tell when the switch took place by examining the events. */
6427
6428 static void
6429 x_new_focus_frame (dpyinfo, frame)
6430 struct x_display_info *dpyinfo;
6431 struct frame *frame;
6432 {
6433 struct frame *old_focus = dpyinfo->x_focus_frame;
6434
6435 if (frame != dpyinfo->x_focus_frame)
6436 {
6437 /* Set this before calling other routines, so that they see
6438 the correct value of x_focus_frame. */
6439 dpyinfo->x_focus_frame = frame;
6440
6441 if (old_focus && old_focus->auto_lower)
6442 x_lower_frame (old_focus);
6443
6444 #if 0
6445 selected_frame = frame;
6446 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6447 selected_frame);
6448 Fselect_window (selected_frame->selected_window);
6449 choose_minibuf_frame ();
6450 #endif /* ! 0 */
6451
6452 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6453 pending_autoraise_frame = dpyinfo->x_focus_frame;
6454 else
6455 pending_autoraise_frame = 0;
6456 }
6457
6458 x_frame_rehighlight (dpyinfo);
6459 }
6460
6461 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6462
6463 void
6464 x_mouse_leave (dpyinfo)
6465 struct x_display_info *dpyinfo;
6466 {
6467 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6468 }
6469
6470 /* The focus has changed, or we have redirected a frame's focus to
6471 another frame (this happens when a frame uses a surrogate
6472 mini-buffer frame). Shift the highlight as appropriate.
6473
6474 The FRAME argument doesn't necessarily have anything to do with which
6475 frame is being highlighted or un-highlighted; we only use it to find
6476 the appropriate X display info. */
6477
6478 static void
6479 XTframe_rehighlight (frame)
6480 struct frame *frame;
6481 {
6482 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6483 }
6484
6485 static void
6486 x_frame_rehighlight (dpyinfo)
6487 struct x_display_info *dpyinfo;
6488 {
6489 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6490
6491 if (dpyinfo->x_focus_frame)
6492 {
6493 dpyinfo->x_highlight_frame
6494 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6495 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6496 : dpyinfo->x_focus_frame);
6497 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6498 {
6499 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6500 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6501 }
6502 }
6503 else
6504 dpyinfo->x_highlight_frame = 0;
6505
6506 if (dpyinfo->x_highlight_frame != old_highlight)
6507 {
6508 if (old_highlight)
6509 frame_unhighlight (old_highlight);
6510 if (dpyinfo->x_highlight_frame)
6511 frame_highlight (dpyinfo->x_highlight_frame);
6512 }
6513 }
6514
6515
6516 \f
6517 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6518
6519 #if 0 /* MAC_TODO */
6520 /* Initialize mode_switch_bit and modifier_meaning. */
6521 static void
6522 x_find_modifier_meanings (dpyinfo)
6523 struct x_display_info *dpyinfo;
6524 {
6525 int min_code, max_code;
6526 KeySym *syms;
6527 int syms_per_code;
6528 XModifierKeymap *mods;
6529
6530 dpyinfo->meta_mod_mask = 0;
6531 dpyinfo->shift_lock_mask = 0;
6532 dpyinfo->alt_mod_mask = 0;
6533 dpyinfo->super_mod_mask = 0;
6534 dpyinfo->hyper_mod_mask = 0;
6535
6536 #ifdef HAVE_X11R4
6537 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6538 #else
6539 min_code = dpyinfo->display->min_keycode;
6540 max_code = dpyinfo->display->max_keycode;
6541 #endif
6542
6543 syms = XGetKeyboardMapping (dpyinfo->display,
6544 min_code, max_code - min_code + 1,
6545 &syms_per_code);
6546 mods = XGetModifierMapping (dpyinfo->display);
6547
6548 /* Scan the modifier table to see which modifier bits the Meta and
6549 Alt keysyms are on. */
6550 {
6551 int row, col; /* The row and column in the modifier table. */
6552
6553 for (row = 3; row < 8; row++)
6554 for (col = 0; col < mods->max_keypermod; col++)
6555 {
6556 KeyCode code
6557 = mods->modifiermap[(row * mods->max_keypermod) + col];
6558
6559 /* Zeroes are used for filler. Skip them. */
6560 if (code == 0)
6561 continue;
6562
6563 /* Are any of this keycode's keysyms a meta key? */
6564 {
6565 int code_col;
6566
6567 for (code_col = 0; code_col < syms_per_code; code_col++)
6568 {
6569 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6570
6571 switch (sym)
6572 {
6573 case XK_Meta_L:
6574 case XK_Meta_R:
6575 dpyinfo->meta_mod_mask |= (1 << row);
6576 break;
6577
6578 case XK_Alt_L:
6579 case XK_Alt_R:
6580 dpyinfo->alt_mod_mask |= (1 << row);
6581 break;
6582
6583 case XK_Hyper_L:
6584 case XK_Hyper_R:
6585 dpyinfo->hyper_mod_mask |= (1 << row);
6586 break;
6587
6588 case XK_Super_L:
6589 case XK_Super_R:
6590 dpyinfo->super_mod_mask |= (1 << row);
6591 break;
6592
6593 case XK_Shift_Lock:
6594 /* Ignore this if it's not on the lock modifier. */
6595 if ((1 << row) == LockMask)
6596 dpyinfo->shift_lock_mask = LockMask;
6597 break;
6598 }
6599 }
6600 }
6601 }
6602 }
6603
6604 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6605 if (! dpyinfo->meta_mod_mask)
6606 {
6607 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6608 dpyinfo->alt_mod_mask = 0;
6609 }
6610
6611 /* If some keys are both alt and meta,
6612 make them just meta, not alt. */
6613 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6614 {
6615 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6616 }
6617
6618 XFree ((char *) syms);
6619 XFreeModifiermap (mods);
6620 }
6621
6622 #endif /* MAC_TODO */
6623
6624 /* Convert between the modifier bits X uses and the modifier bits
6625 Emacs uses. */
6626
6627 static unsigned int
6628 x_mac_to_emacs_modifiers (dpyinfo, state)
6629 struct x_display_info *dpyinfo;
6630 unsigned short state;
6631 {
6632 return (((state & shiftKey) ? shift_modifier : 0)
6633 | ((state & controlKey) ? ctrl_modifier : 0)
6634 | ((state & cmdKey) ? meta_modifier : 0)
6635 | ((state & optionKey) ? alt_modifier : 0));
6636 }
6637
6638 #if 0 /* MAC_TODO */
6639 static unsigned short
6640 x_emacs_to_x_modifiers (dpyinfo, state)
6641 struct x_display_info *dpyinfo;
6642 unsigned int state;
6643 {
6644 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6645 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6646 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6647 | ((state & shift_modifier) ? ShiftMask : 0)
6648 | ((state & ctrl_modifier) ? ControlMask : 0)
6649 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6650 }
6651 #endif /* MAC_TODO */
6652
6653 /* Convert a keysym to its name. */
6654
6655 char *
6656 x_get_keysym_name (keysym)
6657 int keysym;
6658 {
6659 char *value;
6660
6661 BLOCK_INPUT;
6662 #if 0
6663 value = XKeysymToString (keysym);
6664 #else
6665 value = 0;
6666 #endif
6667 UNBLOCK_INPUT;
6668
6669 return value;
6670 }
6671
6672
6673 \f
6674 /* Mouse clicks and mouse movement. Rah. */
6675
6676 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6677 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6678 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6679 not force the value into range. */
6680
6681 void
6682 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6683 FRAME_PTR f;
6684 register int pix_x, pix_y;
6685 register int *x, *y;
6686 Rect *bounds;
6687 int noclip;
6688 {
6689 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6690 if (NILP (Vwindow_system))
6691 {
6692 *x = pix_x;
6693 *y = pix_y;
6694 return;
6695 }
6696
6697 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6698 even for negative values. */
6699 if (pix_x < 0)
6700 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6701 if (pix_y < 0)
6702 pix_y -= (f)->output_data.mac->line_height - 1;
6703
6704 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6705 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6706
6707 if (bounds)
6708 {
6709 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6710 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6711 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6712 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
6713 }
6714
6715 if (!noclip)
6716 {
6717 if (pix_x < 0)
6718 pix_x = 0;
6719 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6720 pix_x = FRAME_WINDOW_WIDTH (f);
6721
6722 if (pix_y < 0)
6723 pix_y = 0;
6724 else if (pix_y > f->height)
6725 pix_y = f->height;
6726 }
6727
6728 *x = pix_x;
6729 *y = pix_y;
6730 }
6731
6732
6733 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6734 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6735 can't tell the positions because W's display is not up to date,
6736 return 0. */
6737
6738 int
6739 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6740 struct window *w;
6741 int hpos, vpos;
6742 int *frame_x, *frame_y;
6743 {
6744 int success_p;
6745
6746 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6747 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6748
6749 if (display_completed)
6750 {
6751 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6752 struct glyph *glyph = row->glyphs[TEXT_AREA];
6753 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6754
6755 *frame_y = row->y;
6756 *frame_x = row->x;
6757 while (glyph < end)
6758 {
6759 *frame_x += glyph->pixel_width;
6760 ++glyph;
6761 }
6762
6763 success_p = 1;
6764 }
6765 else
6766 {
6767 *frame_y = *frame_x = 0;
6768 success_p = 0;
6769 }
6770
6771 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6772 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6773 return success_p;
6774 }
6775
6776
6777 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6778
6779 If the event is a button press, then note that we have grabbed
6780 the mouse. */
6781
6782 static Lisp_Object
6783 construct_mouse_click (result, event, f)
6784 struct input_event *result;
6785 EventRecord *event;
6786 struct frame *f;
6787 {
6788 Point mouseLoc;
6789
6790 result->kind = MOUSE_CLICK_EVENT;
6791 result->code = 0; /* only one mouse button */
6792 result->timestamp = event->when;
6793 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6794
6795 mouseLoc = event->where;
6796
6797 #if TARGET_API_MAC_CARBON
6798 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6799 #else
6800 SetPort (FRAME_MAC_WINDOW (f));
6801 #endif
6802
6803 GlobalToLocal (&mouseLoc);
6804 XSETINT (result->x, mouseLoc.h);
6805 XSETINT (result->y, mouseLoc.v);
6806
6807 XSETFRAME (result->frame_or_window, f);
6808
6809 result->arg = Qnil;
6810 return Qnil;
6811 }
6812
6813 \f
6814 /* Function to report a mouse movement to the mainstream Emacs code.
6815 The input handler calls this.
6816
6817 We have received a mouse movement event, which is given in *event.
6818 If the mouse is over a different glyph than it was last time, tell
6819 the mainstream emacs code by setting mouse_moved. If not, ask for
6820 another motion event, so we can check again the next time it moves. */
6821
6822 static Point last_mouse_motion_position;
6823 static Lisp_Object last_mouse_motion_frame;
6824
6825 static void
6826 note_mouse_movement (frame, pos)
6827 FRAME_PTR frame;
6828 Point *pos;
6829 {
6830 #if TARGET_API_MAC_CARBON
6831 Rect r;
6832 #endif
6833
6834 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6835 last_mouse_motion_position = *pos;
6836 XSETFRAME (last_mouse_motion_frame, frame);
6837
6838 #if TARGET_API_MAC_CARBON
6839 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6840 #else
6841 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6842 #endif
6843 {
6844 frame->mouse_moved = 1;
6845 last_mouse_scroll_bar = Qnil;
6846 note_mouse_highlight (frame, -1, -1);
6847 }
6848 /* Has the mouse moved off the glyph it was on at the last sighting? */
6849 else if (pos->h < last_mouse_glyph.left
6850 || pos->h >= last_mouse_glyph.right
6851 || pos->v < last_mouse_glyph.top
6852 || pos->v >= last_mouse_glyph.bottom)
6853 {
6854 frame->mouse_moved = 1;
6855 last_mouse_scroll_bar = Qnil;
6856 note_mouse_highlight (frame, pos->h, pos->v);
6857 }
6858 }
6859
6860 /* This is used for debugging, to turn off note_mouse_highlight. */
6861
6862 int disable_mouse_highlight;
6863
6864
6865 \f
6866 /************************************************************************
6867 Mouse Face
6868 ************************************************************************/
6869
6870 /* Find the glyph under window-relative coordinates X/Y in window W.
6871 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6872 strings. Return in *HPOS and *VPOS the row and column number of
6873 the glyph found. Return in *AREA the glyph area containing X.
6874 Value is a pointer to the glyph found or null if X/Y is not on
6875 text, or we can't tell because W's current matrix is not up to
6876 date. */
6877
6878 static struct glyph *
6879 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6880 struct window *w;
6881 int x, y;
6882 int *hpos, *vpos, *area;
6883 int buffer_only_p;
6884 {
6885 struct glyph *glyph, *end;
6886 struct glyph_row *row = NULL;
6887 int x0, i, left_area_width;
6888
6889 /* Find row containing Y. Give up if some row is not enabled. */
6890 for (i = 0; i < w->current_matrix->nrows; ++i)
6891 {
6892 row = MATRIX_ROW (w->current_matrix, i);
6893 if (!row->enabled_p)
6894 return NULL;
6895 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6896 break;
6897 }
6898
6899 *vpos = i;
6900 *hpos = 0;
6901
6902 /* Give up if Y is not in the window. */
6903 if (i == w->current_matrix->nrows)
6904 return NULL;
6905
6906 /* Get the glyph area containing X. */
6907 if (w->pseudo_window_p)
6908 {
6909 *area = TEXT_AREA;
6910 x0 = 0;
6911 }
6912 else
6913 {
6914 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6915 if (x < left_area_width)
6916 {
6917 *area = LEFT_MARGIN_AREA;
6918 x0 = 0;
6919 }
6920 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6921 {
6922 *area = TEXT_AREA;
6923 x0 = row->x + left_area_width;
6924 }
6925 else
6926 {
6927 *area = RIGHT_MARGIN_AREA;
6928 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6929 }
6930 }
6931
6932 /* Find glyph containing X. */
6933 glyph = row->glyphs[*area];
6934 end = glyph + row->used[*area];
6935 while (glyph < end)
6936 {
6937 if (x < x0 + glyph->pixel_width)
6938 {
6939 if (w->pseudo_window_p)
6940 break;
6941 else if (!buffer_only_p || BUFFERP (glyph->object))
6942 break;
6943 }
6944
6945 x0 += glyph->pixel_width;
6946 ++glyph;
6947 }
6948
6949 if (glyph == end)
6950 return NULL;
6951
6952 *hpos = glyph - row->glyphs[*area];
6953 return glyph;
6954 }
6955
6956
6957 /* Convert frame-relative x/y to coordinates relative to window W.
6958 Takes pseudo-windows into account. */
6959
6960 static void
6961 frame_to_window_pixel_xy (w, x, y)
6962 struct window *w;
6963 int *x, *y;
6964 {
6965 if (w->pseudo_window_p)
6966 {
6967 /* A pseudo-window is always full-width, and starts at the
6968 left edge of the frame, plus a frame border. */
6969 struct frame *f = XFRAME (w->frame);
6970 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6971 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6972 }
6973 else
6974 {
6975 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6976 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6977 }
6978 }
6979
6980
6981 /* Take proper action when mouse has moved to the mode or header line of
6982 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6983 mode line. X is relative to the start of the text display area of
6984 W, so the width of fringes and scroll bars must be subtracted
6985 to get a position relative to the start of the mode line. */
6986
6987 static void
6988 note_mode_line_highlight (w, x, mode_line_p)
6989 struct window *w;
6990 int x, mode_line_p;
6991 {
6992 struct frame *f = XFRAME (w->frame);
6993 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6994 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
6995 struct glyph_row *row;
6996
6997 if (mode_line_p)
6998 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6999 else
7000 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
7001
7002 if (row->enabled_p)
7003 {
7004 struct glyph *glyph, *end;
7005 Lisp_Object help, map;
7006 int x0;
7007
7008 /* Find the glyph under X. */
7009 glyph = row->glyphs[TEXT_AREA];
7010 end = glyph + row->used[TEXT_AREA];
7011 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
7012 + FRAME_X_LEFT_FRINGE_WIDTH (f));
7013
7014 while (glyph < end
7015 && x >= x0 + glyph->pixel_width)
7016 {
7017 x0 += glyph->pixel_width;
7018 ++glyph;
7019 }
7020
7021 if (glyph < end
7022 && STRINGP (glyph->object)
7023 && STRING_INTERVALS (glyph->object)
7024 && glyph->charpos >= 0
7025 && glyph->charpos < SCHARS (glyph->object))
7026 {
7027 /* If we're on a string with `help-echo' text property,
7028 arrange for the help to be displayed. This is done by
7029 setting the global variable help_echo to the help string. */
7030 help = Fget_text_property (make_number (glyph->charpos),
7031 Qhelp_echo, glyph->object);
7032 if (!NILP (help))
7033 {
7034 help_echo = help;
7035 XSETWINDOW (help_echo_window, w);
7036 help_echo_object = glyph->object;
7037 help_echo_pos = glyph->charpos;
7038 }
7039
7040 /* Change the mouse pointer according to what is under X/Y. */
7041 map = Fget_text_property (make_number (glyph->charpos),
7042 Qlocal_map, glyph->object);
7043 if (KEYMAPP (map))
7044 cursor = f->output_data.mac->nontext_cursor;
7045 else
7046 {
7047 map = Fget_text_property (make_number (glyph->charpos),
7048 Qkeymap, glyph->object);
7049 if (KEYMAPP (map))
7050 cursor = f->output_data.mac->nontext_cursor;
7051 }
7052 }
7053 }
7054
7055 #if 0 /* MAC_TODO: mouse cursor */
7056 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7057 #endif
7058 }
7059
7060
7061 /* Take proper action when the mouse has moved to position X, Y on
7062 frame F as regards highlighting characters that have mouse-face
7063 properties. Also de-highlighting chars where the mouse was before.
7064 X and Y can be negative or out of range. */
7065
7066 static void
7067 note_mouse_highlight (f, x, y)
7068 struct frame *f;
7069 int x, y;
7070 {
7071 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7072 int portion;
7073 Lisp_Object window;
7074 struct window *w;
7075 struct buffer *b;
7076
7077 #if 0
7078 /* When a menu is active, don't highlight because this looks odd. */
7079 if (popup_activated ())
7080 return;
7081 #endif
7082
7083 if (NILP (Vmouse_highlight)
7084 || !f->glyphs_initialized_p)
7085 return;
7086
7087 dpyinfo->mouse_face_mouse_x = x;
7088 dpyinfo->mouse_face_mouse_y = y;
7089 dpyinfo->mouse_face_mouse_frame = f;
7090
7091 if (dpyinfo->mouse_face_defer)
7092 return;
7093
7094 if (gc_in_progress)
7095 {
7096 dpyinfo->mouse_face_deferred_gc = 1;
7097 return;
7098 }
7099
7100 /* Which window is that in? */
7101 window = window_from_coordinates (f, x, y, &portion, 1);
7102
7103 /* If we were displaying active text in another window, clear that. */
7104 if (! EQ (window, dpyinfo->mouse_face_window))
7105 clear_mouse_face (dpyinfo);
7106
7107 /* Not on a window -> return. */
7108 if (!WINDOWP (window))
7109 return;
7110
7111 /* Reset help_echo. It will get recomputed below. */
7112 help_echo = Qnil;
7113
7114 /* Convert to window-relative pixel coordinates. */
7115 w = XWINDOW (window);
7116 frame_to_window_pixel_xy (w, &x, &y);
7117
7118 /* Handle tool-bar window differently since it doesn't display a
7119 buffer. */
7120 if (EQ (window, f->tool_bar_window))
7121 {
7122 note_tool_bar_highlight (f, x, y);
7123 return;
7124 }
7125
7126 /* Mouse is on the mode or header line? */
7127 if (portion == 1 || portion == 3)
7128 {
7129 note_mode_line_highlight (w, x, portion == 1);
7130 return;
7131 }
7132 #if 0 /* TODO: mouse cursor */
7133 if (portion == 2)
7134 cursor = f->output_data.x->horizontal_drag_cursor;
7135 else
7136 cursor = f->output_data.x->text_cursor;
7137 #endif
7138 /* Are we in a window whose display is up to date?
7139 And verify the buffer's text has not changed. */
7140 b = XBUFFER (w->buffer);
7141 if (/* Within text portion of the window. */
7142 portion == 0
7143 && EQ (w->window_end_valid, w->buffer)
7144 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7145 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7146 {
7147 int hpos, vpos, pos, i, area;
7148 struct glyph *glyph;
7149 Lisp_Object object;
7150 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7151 Lisp_Object *overlay_vec = NULL;
7152 int len, noverlays;
7153 struct buffer *obuf;
7154 int obegv, ozv, same_region;
7155
7156 /* Find the glyph under X/Y. */
7157 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7158
7159 /* Clear mouse face if X/Y not over text. */
7160 if (glyph == NULL
7161 || area != TEXT_AREA
7162 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7163 {
7164 clear_mouse_face (dpyinfo);
7165 /* TODO: mouse cursor */
7166 goto set_cursor;
7167 }
7168
7169 pos = glyph->charpos;
7170 object = glyph->object;
7171 if (!STRINGP (object) && !BUFFERP (object))
7172 goto set_cursor;
7173
7174 /* If we get an out-of-range value, return now; avoid an error. */
7175 if (BUFFERP (object) && pos > BUF_Z (b))
7176 goto set_cursor;
7177
7178 /* Make the window's buffer temporarily current for
7179 overlays_at and compute_char_face. */
7180 obuf = current_buffer;
7181 current_buffer = b;
7182 obegv = BEGV;
7183 ozv = ZV;
7184 BEGV = BEG;
7185 ZV = Z;
7186
7187 /* Is this char mouse-active or does it have help-echo? */
7188 position = make_number (pos);
7189
7190 if (BUFFERP (object))
7191 {
7192 /* Put all the overlays we want in a vector in overlay_vec.
7193 Store the length in len. If there are more than 10, make
7194 enough space for all, and try again. */
7195 len = 10;
7196 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7197 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7198 if (noverlays > len)
7199 {
7200 len = noverlays;
7201 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7202 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7203 }
7204
7205 /* Sort overlays into increasing priority order. */
7206 noverlays = sort_overlays (overlay_vec, noverlays, w);
7207 }
7208 else
7209 noverlays = 0;
7210
7211 same_region = (EQ (window, dpyinfo->mouse_face_window)
7212 && vpos >= dpyinfo->mouse_face_beg_row
7213 && vpos <= dpyinfo->mouse_face_end_row
7214 && (vpos > dpyinfo->mouse_face_beg_row
7215 || hpos >= dpyinfo->mouse_face_beg_col)
7216 && (vpos < dpyinfo->mouse_face_end_row
7217 || hpos < dpyinfo->mouse_face_end_col
7218 || dpyinfo->mouse_face_past_end));
7219
7220 /* TODO: if (same_region)
7221 mouse cursor */
7222
7223 /* Check mouse-face highlighting. */
7224 if (! same_region
7225 /* If there exists an overlay with mouse-face overlapping
7226 the one we are currently highlighting, we have to
7227 check if we enter the overlapping overlay, and then
7228 highlight that. */
7229 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7230 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7231 {
7232 /* Find the highest priority overlay that has a mouse-face
7233 property. */
7234 overlay = Qnil;
7235 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7236 {
7237 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7238 if (!NILP (mouse_face))
7239 overlay = overlay_vec[i];
7240 }
7241
7242 /* If we're actually highlighting the same overlay as
7243 before, there's no need to do that again. */
7244 if (!NILP (overlay)
7245 && EQ (overlay, dpyinfo->mouse_face_overlay))
7246 goto check_help_echo;
7247
7248 dpyinfo->mouse_face_overlay = overlay;
7249
7250 /* Clear the display of the old active region, if any. */
7251 clear_mouse_face (dpyinfo);
7252 /* TODO: mouse cursor changes. */
7253
7254 /* If no overlay applies, get a text property. */
7255 if (NILP (overlay))
7256 mouse_face = Fget_text_property (position, Qmouse_face, object);
7257
7258 /* Handle the overlay case. */
7259 if (!NILP (overlay))
7260 {
7261 /* Find the range of text around this char that
7262 should be active. */
7263 Lisp_Object before, after;
7264 int ignore;
7265
7266 before = Foverlay_start (overlay);
7267 after = Foverlay_end (overlay);
7268 /* Record this as the current active region. */
7269 fast_find_position (w, XFASTINT (before),
7270 &dpyinfo->mouse_face_beg_col,
7271 &dpyinfo->mouse_face_beg_row,
7272 &dpyinfo->mouse_face_beg_x,
7273 &dpyinfo->mouse_face_beg_y, Qnil);
7274
7275 dpyinfo->mouse_face_past_end
7276 = !fast_find_position (w, XFASTINT (after),
7277 &dpyinfo->mouse_face_end_col,
7278 &dpyinfo->mouse_face_end_row,
7279 &dpyinfo->mouse_face_end_x,
7280 &dpyinfo->mouse_face_end_y, Qnil);
7281 dpyinfo->mouse_face_window = window;
7282
7283 dpyinfo->mouse_face_face_id
7284 = face_at_buffer_position (w, pos, 0, 0,
7285 &ignore, pos + 1, 1);
7286
7287 /* Display it as active. */
7288 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7289 /* TODO: mouse cursor changes. */
7290 }
7291 /* Handle the text property case. */
7292 else if (! NILP (mouse_face) && BUFFERP (object))
7293 {
7294 /* Find the range of text around this char that
7295 should be active. */
7296 Lisp_Object before, after, beginning, end;
7297 int ignore;
7298
7299 beginning = Fmarker_position (w->start);
7300 end = make_number (BUF_Z (XBUFFER (object))
7301 - XFASTINT (w->window_end_pos));
7302 before
7303 = Fprevious_single_property_change (make_number (pos + 1),
7304 Qmouse_face,
7305 object, beginning);
7306 after
7307 = Fnext_single_property_change (position, Qmouse_face,
7308 object, end);
7309
7310 /* Record this as the current active region. */
7311 fast_find_position (w, XFASTINT (before),
7312 &dpyinfo->mouse_face_beg_col,
7313 &dpyinfo->mouse_face_beg_row,
7314 &dpyinfo->mouse_face_beg_x,
7315 &dpyinfo->mouse_face_beg_y, Qnil);
7316 dpyinfo->mouse_face_past_end
7317 = !fast_find_position (w, XFASTINT (after),
7318 &dpyinfo->mouse_face_end_col,
7319 &dpyinfo->mouse_face_end_row,
7320 &dpyinfo->mouse_face_end_x,
7321 &dpyinfo->mouse_face_end_y, Qnil);
7322 dpyinfo->mouse_face_window = window;
7323
7324 if (BUFFERP (object))
7325 dpyinfo->mouse_face_face_id
7326 = face_at_buffer_position (w, pos, 0, 0,
7327 &ignore, pos + 1, 1);
7328
7329 /* Display it as active. */
7330 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7331 /* TODO: mouse cursor changes. */
7332 }
7333 else if (!NILP (mouse_face) && STRINGP (object))
7334 {
7335 Lisp_Object b, e;
7336 int ignore;
7337
7338 b = Fprevious_single_property_change (make_number (pos + 1),
7339 Qmouse_face,
7340 object, Qnil);
7341 e = Fnext_single_property_change (position, Qmouse_face,
7342 object, Qnil);
7343 if (NILP (b))
7344 b = make_number (0);
7345 if (NILP (e))
7346 e = make_number (SCHARS (object) - 1);
7347 fast_find_string_pos (w, XINT (b), object,
7348 &dpyinfo->mouse_face_beg_col,
7349 &dpyinfo->mouse_face_beg_row,
7350 &dpyinfo->mouse_face_beg_x,
7351 &dpyinfo->mouse_face_beg_y, 0);
7352 fast_find_string_pos (w, XINT (e), object,
7353 &dpyinfo->mouse_face_end_col,
7354 &dpyinfo->mouse_face_end_row,
7355 &dpyinfo->mouse_face_end_x,
7356 &dpyinfo->mouse_face_end_y, 1);
7357 dpyinfo->mouse_face_past_end = 0;
7358 dpyinfo->mouse_face_window = window;
7359 dpyinfo->mouse_face_face_id
7360 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7361 glyph->face_id, 1);
7362 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7363 /* TODO: mouse cursor changes. */
7364 }
7365 else if (STRINGP (object) && NILP (mouse_face))
7366 {
7367 /* A string which doesn't have mouse-face, but
7368 the text ``under'' it might have. */
7369 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7370 int start = MATRIX_ROW_START_CHARPOS (r);
7371
7372 pos = string_buffer_position (w, object, start);
7373 if (pos > 0)
7374 mouse_face = get_char_property_and_overlay (make_number (pos),
7375 Qmouse_face,
7376 w->buffer,
7377 &overlay);
7378 if (!NILP (mouse_face) && !NILP (overlay))
7379 {
7380 Lisp_Object before = Foverlay_start (overlay);
7381 Lisp_Object after = Foverlay_end (overlay);
7382 int ignore;
7383
7384 /* Note that we might not be able to find position
7385 BEFORE in the glyph matrix if the overlay is
7386 entirely covered by a `display' property. In
7387 this case, we overshoot. So let's stop in
7388 the glyph matrix before glyphs for OBJECT. */
7389 fast_find_position (w, XFASTINT (before),
7390 &dpyinfo->mouse_face_beg_col,
7391 &dpyinfo->mouse_face_beg_row,
7392 &dpyinfo->mouse_face_beg_x,
7393 &dpyinfo->mouse_face_beg_y,
7394 object);
7395
7396 dpyinfo->mouse_face_past_end
7397 = !fast_find_position (w, XFASTINT (after),
7398 &dpyinfo->mouse_face_end_col,
7399 &dpyinfo->mouse_face_end_row,
7400 &dpyinfo->mouse_face_end_x,
7401 &dpyinfo->mouse_face_end_y,
7402 Qnil);
7403 dpyinfo->mouse_face_window = window;
7404 dpyinfo->mouse_face_face_id
7405 = face_at_buffer_position (w, pos, 0, 0,
7406 &ignore, pos + 1, 1);
7407
7408 /* Display it as active. */
7409 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7410 /* TODO: mouse cursor changes. */
7411 }
7412 }
7413 }
7414
7415 check_help_echo:
7416
7417 /* Look for a `help-echo' property. */
7418 {
7419 Lisp_Object help, overlay;
7420
7421 /* Check overlays first. */
7422 help = overlay = Qnil;
7423 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7424 {
7425 overlay = overlay_vec[i];
7426 help = Foverlay_get (overlay, Qhelp_echo);
7427 }
7428
7429 if (!NILP (help))
7430 {
7431 help_echo = help;
7432 help_echo_window = window;
7433 help_echo_object = overlay;
7434 help_echo_pos = pos;
7435 }
7436 else
7437 {
7438 Lisp_Object object = glyph->object;
7439 int charpos = glyph->charpos;
7440
7441 /* Try text properties. */
7442 if (STRINGP (object)
7443 && charpos >= 0
7444 && charpos < SCHARS (object))
7445 {
7446 help = Fget_text_property (make_number (charpos),
7447 Qhelp_echo, object);
7448 if (NILP (help))
7449 {
7450 /* If the string itself doesn't specify a help-echo,
7451 see if the buffer text ``under'' it does. */
7452 struct glyph_row *r
7453 = MATRIX_ROW (w->current_matrix, vpos);
7454 int start = MATRIX_ROW_START_CHARPOS (r);
7455 int pos = string_buffer_position (w, object, start);
7456 if (pos > 0)
7457 {
7458 help = Fget_char_property (make_number (pos),
7459 Qhelp_echo, w->buffer);
7460 if (!NILP (help))
7461 {
7462 charpos = pos;
7463 object = w->buffer;
7464 }
7465 }
7466 }
7467 }
7468 else if (BUFFERP (object)
7469 && charpos >= BEGV
7470 && charpos < ZV)
7471 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7472 object);
7473
7474 if (!NILP (help))
7475 {
7476 help_echo = help;
7477 help_echo_window = window;
7478 help_echo_object = object;
7479 help_echo_pos = charpos;
7480 }
7481 }
7482 }
7483
7484 BEGV = obegv;
7485 ZV = ozv;
7486 current_buffer = obuf;
7487 }
7488
7489 set_cursor:
7490 /* TODO: mouse cursor changes. */
7491 ;
7492 }
7493
7494 static void
7495 redo_mouse_highlight ()
7496 {
7497 if (!NILP (last_mouse_motion_frame)
7498 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7499 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7500 last_mouse_motion_position.h,
7501 last_mouse_motion_position.v);
7502 }
7503
7504
7505 \f
7506 /***********************************************************************
7507 Tool-bars
7508 ***********************************************************************/
7509
7510 static int x_tool_bar_item P_ ((struct frame *, int, int,
7511 struct glyph **, int *, int *, int *));
7512
7513 /* Tool-bar item index of the item on which a mouse button was pressed
7514 or -1. */
7515
7516 static int last_tool_bar_item;
7517
7518
7519 /* Get information about the tool-bar item at position X/Y on frame F.
7520 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7521 the current matrix of the tool-bar window of F, or NULL if not
7522 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7523 item in F->current_tool_bar_items. Value is
7524
7525 -1 if X/Y is not on a tool-bar item
7526 0 if X/Y is on the same item that was highlighted before.
7527 1 otherwise. */
7528
7529 static int
7530 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7531 struct frame *f;
7532 int x, y;
7533 struct glyph **glyph;
7534 int *hpos, *vpos, *prop_idx;
7535 {
7536 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7537 struct window *w = XWINDOW (f->tool_bar_window);
7538 int area;
7539
7540 /* Find the glyph under X/Y. */
7541 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7542 if (*glyph == NULL)
7543 return -1;
7544
7545 /* Get the start of this tool-bar item's properties in
7546 f->current_tool_bar_items. */
7547 if (!tool_bar_item_info (f, *glyph, prop_idx))
7548 return -1;
7549
7550 /* Is mouse on the highlighted item? */
7551 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7552 && *vpos >= dpyinfo->mouse_face_beg_row
7553 && *vpos <= dpyinfo->mouse_face_end_row
7554 && (*vpos > dpyinfo->mouse_face_beg_row
7555 || *hpos >= dpyinfo->mouse_face_beg_col)
7556 && (*vpos < dpyinfo->mouse_face_end_row
7557 || *hpos < dpyinfo->mouse_face_end_col
7558 || dpyinfo->mouse_face_past_end))
7559 return 0;
7560
7561 return 1;
7562 }
7563
7564
7565 /* Handle mouse button event on the tool-bar of frame F, at
7566 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7567 or ButtonRelase. */
7568
7569 static void
7570 x_handle_tool_bar_click (f, button_event)
7571 struct frame *f;
7572 EventRecord *button_event;
7573 {
7574 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7575 struct window *w = XWINDOW (f->tool_bar_window);
7576 int hpos, vpos, prop_idx;
7577 struct glyph *glyph;
7578 Lisp_Object enabled_p;
7579 int x = button_event->where.h;
7580 int y = button_event->where.v;
7581
7582 /* If not on the highlighted tool-bar item, return. */
7583 frame_to_window_pixel_xy (w, &x, &y);
7584 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7585 return;
7586
7587 /* If item is disabled, do nothing. */
7588 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7589 if (NILP (enabled_p))
7590 return;
7591
7592 if (button_event->what == mouseDown)
7593 {
7594 /* Show item in pressed state. */
7595 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7596 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7597 last_tool_bar_item = prop_idx;
7598 }
7599 else
7600 {
7601 Lisp_Object key, frame;
7602 struct input_event event;
7603
7604 /* Show item in released state. */
7605 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7606 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7607
7608 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7609
7610 XSETFRAME (frame, f);
7611 event.kind = TOOL_BAR_EVENT;
7612 event.frame_or_window = frame;
7613 event.arg = frame;
7614 kbd_buffer_store_event (&event);
7615
7616 event.kind = TOOL_BAR_EVENT;
7617 event.frame_or_window = frame;
7618 event.arg = key;
7619 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7620 button_event->modifiers);
7621 kbd_buffer_store_event (&event);
7622 last_tool_bar_item = -1;
7623 }
7624 }
7625
7626
7627 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7628 tool-bar window-relative coordinates X/Y. Called from
7629 note_mouse_highlight. */
7630
7631 static void
7632 note_tool_bar_highlight (f, x, y)
7633 struct frame *f;
7634 int x, y;
7635 {
7636 Lisp_Object window = f->tool_bar_window;
7637 struct window *w = XWINDOW (window);
7638 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7639 int hpos, vpos;
7640 struct glyph *glyph;
7641 struct glyph_row *row;
7642 int i;
7643 Lisp_Object enabled_p;
7644 int prop_idx;
7645 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7646 int mouse_down_p, rc;
7647
7648 /* Function note_mouse_highlight is called with negative x(y
7649 values when mouse moves outside of the frame. */
7650 if (x <= 0 || y <= 0)
7651 {
7652 clear_mouse_face (dpyinfo);
7653 return;
7654 }
7655
7656 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7657 if (rc < 0)
7658 {
7659 /* Not on tool-bar item. */
7660 clear_mouse_face (dpyinfo);
7661 return;
7662 }
7663 else if (rc == 0)
7664 /* On same tool-bar item as before. */
7665 goto set_help_echo;
7666
7667 clear_mouse_face (dpyinfo);
7668
7669 /* Mouse is down, but on different tool-bar item? */
7670 mouse_down_p = (dpyinfo->grabbed
7671 && f == last_mouse_frame
7672 && FRAME_LIVE_P (f));
7673 if (mouse_down_p
7674 && last_tool_bar_item != prop_idx)
7675 return;
7676
7677 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7678 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7679
7680 /* If tool-bar item is not enabled, don't highlight it. */
7681 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7682 if (!NILP (enabled_p))
7683 {
7684 /* Compute the x-position of the glyph. In front and past the
7685 image is a space. We include this is the highlighted area. */
7686 row = MATRIX_ROW (w->current_matrix, vpos);
7687 for (i = x = 0; i < hpos; ++i)
7688 x += row->glyphs[TEXT_AREA][i].pixel_width;
7689
7690 /* Record this as the current active region. */
7691 dpyinfo->mouse_face_beg_col = hpos;
7692 dpyinfo->mouse_face_beg_row = vpos;
7693 dpyinfo->mouse_face_beg_x = x;
7694 dpyinfo->mouse_face_beg_y = row->y;
7695 dpyinfo->mouse_face_past_end = 0;
7696
7697 dpyinfo->mouse_face_end_col = hpos + 1;
7698 dpyinfo->mouse_face_end_row = vpos;
7699 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7700 dpyinfo->mouse_face_end_y = row->y;
7701 dpyinfo->mouse_face_window = window;
7702 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7703
7704 /* Display it as active. */
7705 show_mouse_face (dpyinfo, draw);
7706 dpyinfo->mouse_face_image_state = draw;
7707 }
7708
7709 set_help_echo:
7710
7711 /* Set help_echo to a help string.to display for this tool-bar item.
7712 XTread_socket does the rest. */
7713 help_echo_object = help_echo_window = Qnil;
7714 help_echo_pos = -1;
7715 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7716 if (NILP (help_echo))
7717 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7718 }
7719
7720
7721 \f
7722 /* Find the glyph matrix position of buffer position CHARPOS in window
7723 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7724 current glyphs must be up to date. If CHARPOS is above window
7725 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7726 of last line in W. In the row containing CHARPOS, stop before glyphs
7727 having STOP as object. */
7728
7729 #if 0 /* This is a version of fast_find_position that's more correct
7730 in the presence of hscrolling, for example. I didn't install
7731 it right away because the problem fixed is minor, it failed
7732 in 20.x as well, and I think it's too risky to install
7733 so near the release of 21.1. 2001-09-25 gerd. */
7734
7735 static int
7736 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7737 struct window *w;
7738 int charpos;
7739 int *hpos, *vpos, *x, *y;
7740 Lisp_Object stop;
7741 {
7742 struct glyph_row *row, *first;
7743 struct glyph *glyph, *end;
7744 int i, past_end = 0;
7745
7746 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7747 row = row_containing_pos (w, charpos, first, NULL, 0);
7748 if (row == NULL)
7749 {
7750 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7751 {
7752 *x = *y = *hpos = *vpos = 0;
7753 return 0;
7754 }
7755 else
7756 {
7757 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7758 past_end = 1;
7759 }
7760 }
7761
7762 *x = row->x;
7763 *y = row->y;
7764 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7765
7766 glyph = row->glyphs[TEXT_AREA];
7767 end = glyph + row->used[TEXT_AREA];
7768
7769 /* Skip over glyphs not having an object at the start of the row.
7770 These are special glyphs like truncation marks on terminal
7771 frames. */
7772 if (row->displays_text_p)
7773 while (glyph < end
7774 && INTEGERP (glyph->object)
7775 && !EQ (stop, glyph->object)
7776 && glyph->charpos < 0)
7777 {
7778 *x += glyph->pixel_width;
7779 ++glyph;
7780 }
7781
7782 while (glyph < end
7783 && !INTEGERP (glyph->object)
7784 && !EQ (stop, glyph->object)
7785 && (!BUFFERP (glyph->object)
7786 || glyph->charpos < charpos))
7787 {
7788 *x += glyph->pixel_width;
7789 ++glyph;
7790 }
7791
7792 *hpos = glyph - row->glyphs[TEXT_AREA];
7793 return past_end;
7794 }
7795
7796 #else /* not 0 */
7797
7798 static int
7799 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7800 struct window *w;
7801 int pos;
7802 int *hpos, *vpos, *x, *y;
7803 Lisp_Object stop;
7804 {
7805 int i;
7806 int lastcol;
7807 int maybe_next_line_p = 0;
7808 int line_start_position;
7809 int yb = window_text_bottom_y (w);
7810 struct glyph_row *row, *best_row;
7811 int row_vpos, best_row_vpos;
7812 int current_x;
7813
7814 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7815 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7816
7817 while (row->y < yb)
7818 {
7819 if (row->used[TEXT_AREA])
7820 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7821 else
7822 line_start_position = 0;
7823
7824 if (line_start_position > pos)
7825 break;
7826 /* If the position sought is the end of the buffer,
7827 don't include the blank lines at the bottom of the window. */
7828 else if (line_start_position == pos
7829 && pos == BUF_ZV (XBUFFER (w->buffer)))
7830 {
7831 maybe_next_line_p = 1;
7832 break;
7833 }
7834 else if (line_start_position > 0)
7835 {
7836 best_row = row;
7837 best_row_vpos = row_vpos;
7838 }
7839
7840 if (row->y + row->height >= yb)
7841 break;
7842
7843 ++row;
7844 ++row_vpos;
7845 }
7846
7847 /* Find the right column within BEST_ROW. */
7848 lastcol = 0;
7849 current_x = best_row->x;
7850 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7851 {
7852 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7853 int charpos = glyph->charpos;
7854
7855 if (BUFFERP (glyph->object))
7856 {
7857 if (charpos == pos)
7858 {
7859 *hpos = i;
7860 *vpos = best_row_vpos;
7861 *x = current_x;
7862 *y = best_row->y;
7863 return 1;
7864 }
7865 else if (charpos > pos)
7866 break;
7867 }
7868 else if (EQ (glyph->object, stop))
7869 break;
7870
7871 if (charpos > 0)
7872 lastcol = i;
7873 current_x += glyph->pixel_width;
7874 }
7875
7876 /* If we're looking for the end of the buffer,
7877 and we didn't find it in the line we scanned,
7878 use the start of the following line. */
7879 if (maybe_next_line_p)
7880 {
7881 ++best_row;
7882 ++best_row_vpos;
7883 lastcol = 0;
7884 current_x = best_row->x;
7885 }
7886
7887 *vpos = best_row_vpos;
7888 *hpos = lastcol + 1;
7889 *x = current_x;
7890 *y = best_row->y;
7891 return 0;
7892 }
7893
7894 #endif /* not 0 */
7895
7896
7897 /* Find the position of the glyph for position POS in OBJECT in
7898 window W's current matrix, and return in *X/*Y the pixel
7899 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7900
7901 RIGHT_P non-zero means return the position of the right edge of the
7902 glyph, RIGHT_P zero means return the left edge position.
7903
7904 If no glyph for POS exists in the matrix, return the position of
7905 the glyph with the next smaller position that is in the matrix, if
7906 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7907 exists in the matrix, return the position of the glyph with the
7908 next larger position in OBJECT.
7909
7910 Value is non-zero if a glyph was found. */
7911
7912 static int
7913 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7914 struct window *w;
7915 int pos;
7916 Lisp_Object object;
7917 int *hpos, *vpos, *x, *y;
7918 int right_p;
7919 {
7920 int yb = window_text_bottom_y (w);
7921 struct glyph_row *r;
7922 struct glyph *best_glyph = NULL;
7923 struct glyph_row *best_row = NULL;
7924 int best_x = 0;
7925
7926 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7927 r->enabled_p && r->y < yb;
7928 ++r)
7929 {
7930 struct glyph *g = r->glyphs[TEXT_AREA];
7931 struct glyph *e = g + r->used[TEXT_AREA];
7932 int gx;
7933
7934 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7935 if (EQ (g->object, object))
7936 {
7937 if (g->charpos == pos)
7938 {
7939 best_glyph = g;
7940 best_x = gx;
7941 best_row = r;
7942 goto found;
7943 }
7944 else if (best_glyph == NULL
7945 || ((abs (g->charpos - pos)
7946 < abs (best_glyph->charpos - pos))
7947 && (right_p
7948 ? g->charpos < pos
7949 : g->charpos > pos)))
7950 {
7951 best_glyph = g;
7952 best_x = gx;
7953 best_row = r;
7954 }
7955 }
7956 }
7957
7958 found:
7959
7960 if (best_glyph)
7961 {
7962 *x = best_x;
7963 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7964
7965 if (right_p)
7966 {
7967 *x += best_glyph->pixel_width;
7968 ++*hpos;
7969 }
7970
7971 *y = best_row->y;
7972 *vpos = best_row - w->current_matrix->rows;
7973 }
7974
7975 return best_glyph != NULL;
7976 }
7977
7978
7979 /* Display the active region described by mouse_face_*
7980 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7981
7982 static void
7983 show_mouse_face (dpyinfo, draw)
7984 struct mac_display_info *dpyinfo;
7985 enum draw_glyphs_face draw;
7986 {
7987 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7988 struct frame *f = XFRAME (WINDOW_FRAME (w));
7989
7990 if (/* If window is in the process of being destroyed, don't bother
7991 to do anything. */
7992 w->current_matrix != NULL
7993 /* Don't update mouse highlight if hidden */
7994 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7995 /* Recognize when we are called to operate on rows that don't exist
7996 anymore. This can happen when a window is split. */
7997 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7998 {
7999 int phys_cursor_on_p = w->phys_cursor_on_p;
8000 struct glyph_row *row, *first, *last;
8001
8002 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
8003 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
8004
8005 for (row = first; row <= last && row->enabled_p; ++row)
8006 {
8007 int start_hpos, end_hpos, start_x;
8008
8009 /* For all but the first row, the highlight starts at column 0. */
8010 if (row == first)
8011 {
8012 start_hpos = dpyinfo->mouse_face_beg_col;
8013 start_x = dpyinfo->mouse_face_beg_x;
8014 }
8015 else
8016 {
8017 start_hpos = 0;
8018 start_x = 0;
8019 }
8020
8021 if (row == last)
8022 end_hpos = dpyinfo->mouse_face_end_col;
8023 else
8024 end_hpos = row->used[TEXT_AREA];
8025
8026 if (end_hpos > start_hpos)
8027 {
8028 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8029 start_hpos, end_hpos, draw, 0);
8030
8031 row->mouse_face_p
8032 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8033 }
8034 }
8035
8036 /* When we've written over the cursor, arrange for it to
8037 be displayed again. */
8038 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8039 x_display_cursor (w, 1,
8040 w->phys_cursor.hpos, w->phys_cursor.vpos,
8041 w->phys_cursor.x, w->phys_cursor.y);
8042 }
8043
8044 #if 0 /* MAC_TODO: mouse cursor */
8045 /* Change the mouse cursor. */
8046 if (draw == DRAW_NORMAL_TEXT)
8047 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8048 f->output_data.x->text_cursor);
8049 else if (draw == DRAW_MOUSE_FACE)
8050 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8051 f->output_data.x->cross_cursor);
8052 else
8053 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8054 f->output_data.x->nontext_cursor);
8055 #endif
8056 }
8057
8058 /* Clear out the mouse-highlighted active region.
8059 Redraw it un-highlighted first. */
8060
8061 static int
8062 clear_mouse_face (dpyinfo)
8063 struct mac_display_info *dpyinfo;
8064 {
8065 int cleared = 0;
8066
8067 if (! NILP (dpyinfo->mouse_face_window))
8068 {
8069 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8070 cleared = 1;
8071 }
8072
8073 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8074 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8075 dpyinfo->mouse_face_window = Qnil;
8076 dpyinfo->mouse_face_overlay = Qnil;
8077 return cleared;
8078 }
8079
8080
8081 /* Clear any mouse-face on window W. This function is part of the
8082 redisplay interface, and is called from try_window_id and similar
8083 functions to ensure the mouse-highlight is off. */
8084
8085 static void
8086 x_clear_mouse_face (w)
8087 struct window *w;
8088 {
8089 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8090 Lisp_Object window;
8091
8092 BLOCK_INPUT;
8093 XSETWINDOW (window, w);
8094 if (EQ (window, dpyinfo->mouse_face_window))
8095 clear_mouse_face (dpyinfo);
8096 UNBLOCK_INPUT;
8097 }
8098
8099
8100 /* Just discard the mouse face information for frame F, if any.
8101 This is used when the size of F is changed. */
8102
8103 void
8104 cancel_mouse_face (f)
8105 FRAME_PTR f;
8106 {
8107 Lisp_Object window;
8108 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8109
8110 window = dpyinfo->mouse_face_window;
8111 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8112 {
8113 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8114 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8115 dpyinfo->mouse_face_window = Qnil;
8116 }
8117 }
8118 \f
8119 static struct scroll_bar *x_window_to_scroll_bar ();
8120 static void x_scroll_bar_report_motion ();
8121 static void x_check_fullscreen P_ ((struct frame *));
8122 static void x_check_fullscreen_move P_ ((struct frame *));
8123 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8124
8125
8126 /* Try to determine frame pixel position and size of the glyph under
8127 frame pixel coordinates X/Y on frame F . Return the position and
8128 size in *RECT. Value is non-zero if we could compute these
8129 values. */
8130
8131 static int
8132 glyph_rect (f, x, y, rect)
8133 struct frame *f;
8134 int x, y;
8135 Rect *rect;
8136 {
8137 Lisp_Object window;
8138 int part;
8139
8140 window = window_from_coordinates (f, x, y, &part, 0);
8141 if (!NILP (window))
8142 {
8143 struct window *w = XWINDOW (window);
8144 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8145 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8146
8147 frame_to_window_pixel_xy (w, &x, &y);
8148
8149 for (; r < end && r->enabled_p; ++r)
8150 if (r->y <= y && r->y + r->height > y)
8151 {
8152 /* Found the row at y. */
8153 struct glyph *g = r->glyphs[TEXT_AREA];
8154 struct glyph *end = g + r->used[TEXT_AREA];
8155 int gx;
8156
8157 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8158 rect->bottom = rect->top + r->height;
8159
8160 if (x < r->x)
8161 {
8162 /* x is to the left of the first glyph in the row. */
8163 rect->left = XINT (w->left);
8164 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8165 return 1;
8166 }
8167
8168 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8169 if (gx <= x && gx + g->pixel_width > x)
8170 {
8171 /* x is on a glyph. */
8172 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8173 rect->right = rect->left + g->pixel_width;
8174 return 1;
8175 }
8176
8177 /* x is to the right of the last glyph in the row. */
8178 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8179 rect->right = XINT (w->left) + XINT (w->width);
8180 return 1;
8181 }
8182 }
8183
8184 /* The y is not on any row. */
8185 return 0;
8186 }
8187
8188 /* Record the position of the mouse in last_mouse_glyph. */
8189 static void
8190 remember_mouse_glyph (f1, gx, gy)
8191 struct frame * f1;
8192 int gx, gy;
8193 {
8194 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8195 {
8196 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8197 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8198
8199 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8200 round down even for negative values. */
8201 if (gx < 0)
8202 gx -= width - 1;
8203 if (gy < 0)
8204 gy -= height - 1;
8205 #if 0
8206 /* This was the original code from XTmouse_position, but it seems
8207 to give the position of the glyph diagonally next to the one
8208 the mouse is over. */
8209 gx = (gx + width - 1) / width * width;
8210 gy = (gy + height - 1) / height * height;
8211 #else
8212 gx = gx / width * width;
8213 gy = gy / height * height;
8214 #endif
8215
8216 last_mouse_glyph.left = gx;
8217 last_mouse_glyph.top = gy;
8218 last_mouse_glyph.right = gx + width;
8219 last_mouse_glyph.bottom = gy + height;
8220 }
8221 }
8222
8223 /* Return the current position of the mouse.
8224 *fp should be a frame which indicates which display to ask about.
8225
8226 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8227 and *part to the frame, window, and scroll bar part that the mouse
8228 is over. Set *x and *y to the portion and whole of the mouse's
8229 position on the scroll bar.
8230
8231 If the mouse movement started elsewhere, set *fp to the frame the
8232 mouse is on, *bar_window to nil, and *x and *y to the character cell
8233 the mouse is over.
8234
8235 Set *time to the server time-stamp for the time at which the mouse
8236 was at this position.
8237
8238 Don't store anything if we don't have a valid set of values to report.
8239
8240 This clears the mouse_moved flag, so we can wait for the next mouse
8241 movement. */
8242
8243 static void
8244 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8245 FRAME_PTR *fp;
8246 int insist;
8247 Lisp_Object *bar_window;
8248 enum scroll_bar_part *part;
8249 Lisp_Object *x, *y;
8250 unsigned long *time;
8251 {
8252 Point mouse_pos;
8253 int ignore1, ignore2;
8254 WindowPtr wp = FrontWindow ();
8255 struct frame *f;
8256 Lisp_Object frame, tail;
8257
8258 if (is_emacs_window(wp))
8259 f = ((mac_output *) GetWRefCon (wp))->mFP;
8260
8261 BLOCK_INPUT;
8262
8263 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8264 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8265 else
8266 {
8267 /* Clear the mouse-moved flag for every frame on this display. */
8268 FOR_EACH_FRAME (tail, frame)
8269 XFRAME (frame)->mouse_moved = 0;
8270
8271 last_mouse_scroll_bar = Qnil;
8272
8273 #if TARGET_API_MAC_CARBON
8274 SetPort (GetWindowPort (wp));
8275 #else
8276 SetPort (wp);
8277 #endif
8278
8279 GetMouse (&mouse_pos);
8280
8281 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8282 &last_mouse_glyph, insist);
8283
8284 *bar_window = Qnil;
8285 *part = scroll_bar_handle;
8286 *fp = f;
8287 XSETINT (*x, mouse_pos.h);
8288 XSETINT (*y, mouse_pos.v);
8289 *time = last_mouse_movement_time;
8290 }
8291
8292 UNBLOCK_INPUT;
8293 }
8294
8295 \f
8296 /************************************************************************
8297 Scroll bars, general
8298 ************************************************************************/
8299
8300 /* Create a scroll bar and return the scroll bar vector for it. W is
8301 the Emacs window on which to create the scroll bar. TOP, LEFT,
8302 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8303 scroll bar. */
8304
8305 static struct scroll_bar *
8306 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8307 struct window *w;
8308 int top, left, width, height, disp_top, disp_height;
8309 {
8310 struct frame *f = XFRAME (w->frame);
8311 struct scroll_bar *bar
8312 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8313 Rect r;
8314 ControlHandle ch;
8315
8316 BLOCK_INPUT;
8317
8318 r.left = left;
8319 r.top = disp_top;
8320 r.right = left + width;
8321 r.bottom = disp_top + disp_height;
8322
8323 #ifdef TARGET_API_MAC_CARBON
8324 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8325 kControlScrollBarProc, 0L);
8326 #else
8327 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8328 0L);
8329 #endif
8330 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8331 SetControlReference (ch, (long) bar);
8332
8333 XSETWINDOW (bar->window, w);
8334 XSETINT (bar->top, top);
8335 XSETINT (bar->left, left);
8336 XSETINT (bar->width, width);
8337 XSETINT (bar->height, height);
8338 XSETINT (bar->start, 0);
8339 XSETINT (bar->end, 0);
8340 bar->dragging = Qnil;
8341
8342 /* Add bar to its frame's list of scroll bars. */
8343 bar->next = FRAME_SCROLL_BARS (f);
8344 bar->prev = Qnil;
8345 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8346 if (!NILP (bar->next))
8347 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8348
8349 UNBLOCK_INPUT;
8350 return bar;
8351 }
8352
8353
8354 /* Draw BAR's handle in the proper position.
8355
8356 If the handle is already drawn from START to END, don't bother
8357 redrawing it, unless REBUILD is non-zero; in that case, always
8358 redraw it. (REBUILD is handy for drawing the handle after expose
8359 events.)
8360
8361 Normally, we want to constrain the start and end of the handle to
8362 fit inside its rectangle, but if the user is dragging the scroll
8363 bar handle, we want to let them drag it down all the way, so that
8364 the bar's top is as far down as it goes; otherwise, there's no way
8365 to move to the very end of the buffer. */
8366
8367 static void
8368 x_scroll_bar_set_handle (bar, start, end, rebuild)
8369 struct scroll_bar *bar;
8370 int start, end;
8371 int rebuild;
8372 {
8373 int dragging = ! NILP (bar->dragging);
8374 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8375 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8376 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8377 int length = end - start;
8378
8379 /* If the display is already accurate, do nothing. */
8380 if (! rebuild
8381 && start == XINT (bar->start)
8382 && end == XINT (bar->end))
8383 return;
8384
8385 BLOCK_INPUT;
8386
8387 /* Make sure the values are reasonable, and try to preserve the
8388 distance between start and end. */
8389 if (start < 0)
8390 start = 0;
8391 else if (start > top_range)
8392 start = top_range;
8393 end = start + length;
8394
8395 if (end < start)
8396 end = start;
8397 else if (end > top_range && ! dragging)
8398 end = top_range;
8399
8400 /* Store the adjusted setting in the scroll bar. */
8401 XSETINT (bar->start, start);
8402 XSETINT (bar->end, end);
8403
8404 /* Clip the end position, just for display. */
8405 if (end > top_range)
8406 end = top_range;
8407
8408 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8409 top positions, to make sure the handle is always at least that
8410 many pixels tall. */
8411 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8412
8413 SetControlMinimum (ch, 0);
8414 /* Don't inadvertently activate deactivated scroll bars */
8415 if (GetControlMaximum (ch) != -1)
8416 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8417 - (end - start));
8418 SetControlValue (ch, start);
8419 #if TARGET_API_MAC_CARBON
8420 SetControlViewSize (ch, end - start);
8421 #endif
8422
8423 UNBLOCK_INPUT;
8424 }
8425
8426
8427 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8428 nil. */
8429
8430 static void
8431 x_scroll_bar_remove (bar)
8432 struct scroll_bar *bar;
8433 {
8434 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8435
8436 BLOCK_INPUT;
8437
8438 /* Destroy the Mac scroll bar control */
8439 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8440
8441 /* Disassociate this scroll bar from its window. */
8442 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8443
8444 UNBLOCK_INPUT;
8445 }
8446
8447 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8448 that we are displaying PORTION characters out of a total of WHOLE
8449 characters, starting at POSITION. If WINDOW has no scroll bar,
8450 create one. */
8451 static void
8452 XTset_vertical_scroll_bar (w, portion, whole, position)
8453 struct window *w;
8454 int portion, whole, position;
8455 {
8456 struct frame *f = XFRAME (w->frame);
8457 struct scroll_bar *bar;
8458 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8459 int window_x, window_y, window_width, window_height;
8460
8461 /* Get window dimensions. */
8462 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8463 top = window_y;
8464 #ifdef MAC_OSX
8465 width = 16;
8466 #else
8467 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8468 #endif
8469 height = window_height;
8470
8471 /* Compute the left edge of the scroll bar area. */
8472 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8473 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8474 else
8475 left = XFASTINT (w->left);
8476 left *= CANON_X_UNIT (f);
8477 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8478
8479 /* Compute the width of the scroll bar which might be less than
8480 the width of the area reserved for the scroll bar. */
8481 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8482 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8483 else
8484 sb_width = width;
8485
8486 /* Compute the left edge of the scroll bar. */
8487 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8488 sb_left = left + width - sb_width - (width - sb_width) / 2;
8489 else
8490 sb_left = left + (width - sb_width) / 2;
8491
8492 /* Adjustments according to Inside Macintosh to make it look nice */
8493 disp_top = top;
8494 disp_height = height;
8495 if (disp_top == 0)
8496 {
8497 disp_top = -1;
8498 disp_height++;
8499 }
8500 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8501 {
8502 disp_top++;
8503 disp_height--;
8504 }
8505
8506 if (sb_left + sb_width == PIXEL_WIDTH (f))
8507 sb_left++;
8508
8509 /* Does the scroll bar exist yet? */
8510 if (NILP (w->vertical_scroll_bar))
8511 {
8512 BLOCK_INPUT;
8513 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8514 left, top, width, height, 0);
8515 UNBLOCK_INPUT;
8516 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8517 disp_height);
8518 XSETVECTOR (w->vertical_scroll_bar, bar);
8519 }
8520 else
8521 {
8522 /* It may just need to be moved and resized. */
8523 ControlHandle ch;
8524
8525 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8526 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8527
8528 BLOCK_INPUT;
8529
8530 /* If already correctly positioned, do nothing. */
8531 if (XINT (bar->left) == sb_left
8532 && XINT (bar->top) == top
8533 && XINT (bar->width) == sb_width
8534 && XINT (bar->height) == height)
8535 Draw1Control (ch);
8536 else
8537 {
8538 /* Clear areas not covered by the scroll bar because it's not as
8539 wide as the area reserved for it . This makes sure a
8540 previous mode line display is cleared after C-x 2 C-x 1, for
8541 example. */
8542 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8543 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8544 left, top, area_width, height, 0);
8545
8546 #if 0
8547 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8548 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8549 sb_left - 1, top, 1, height, 0);
8550 #endif
8551
8552 HideControl (ch);
8553 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8554 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8555 disp_height);
8556 ShowControl (ch);
8557
8558 /* Remember new settings. */
8559 XSETINT (bar->left, sb_left);
8560 XSETINT (bar->top, top);
8561 XSETINT (bar->width, sb_width);
8562 XSETINT (bar->height, height);
8563 }
8564
8565 UNBLOCK_INPUT;
8566 }
8567
8568 /* Set the scroll bar's current state, unless we're currently being
8569 dragged. */
8570 if (NILP (bar->dragging))
8571 {
8572 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8573
8574 if (whole == 0)
8575 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8576 else
8577 {
8578 int start = ((double) position * top_range) / whole;
8579 int end = ((double) (position + portion) * top_range) / whole;
8580 x_scroll_bar_set_handle (bar, start, end, 0);
8581 }
8582 }
8583 }
8584
8585
8586 /* The following three hooks are used when we're doing a thorough
8587 redisplay of the frame. We don't explicitly know which scroll bars
8588 are going to be deleted, because keeping track of when windows go
8589 away is a real pain - "Can you say set-window-configuration, boys
8590 and girls?" Instead, we just assert at the beginning of redisplay
8591 that *all* scroll bars are to be removed, and then save a scroll bar
8592 from the fiery pit when we actually redisplay its window. */
8593
8594 /* Arrange for all scroll bars on FRAME to be removed at the next call
8595 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8596 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8597
8598 static void
8599 XTcondemn_scroll_bars (frame)
8600 FRAME_PTR frame;
8601 {
8602 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8603 while (! NILP (FRAME_SCROLL_BARS (frame)))
8604 {
8605 Lisp_Object bar;
8606 bar = FRAME_SCROLL_BARS (frame);
8607 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8608 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8609 XSCROLL_BAR (bar)->prev = Qnil;
8610 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8611 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8612 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8613 }
8614 }
8615
8616
8617 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8618 Note that WINDOW isn't necessarily condemned at all. */
8619
8620 static void
8621 XTredeem_scroll_bar (window)
8622 struct window *window;
8623 {
8624 struct scroll_bar *bar;
8625
8626 /* We can't redeem this window's scroll bar if it doesn't have one. */
8627 if (NILP (window->vertical_scroll_bar))
8628 abort ();
8629
8630 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8631
8632 /* Unlink it from the condemned list. */
8633 {
8634 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8635
8636 if (NILP (bar->prev))
8637 {
8638 /* If the prev pointer is nil, it must be the first in one of
8639 the lists. */
8640 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8641 /* It's not condemned. Everything's fine. */
8642 return;
8643 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8644 window->vertical_scroll_bar))
8645 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8646 else
8647 /* If its prev pointer is nil, it must be at the front of
8648 one or the other! */
8649 abort ();
8650 }
8651 else
8652 XSCROLL_BAR (bar->prev)->next = bar->next;
8653
8654 if (! NILP (bar->next))
8655 XSCROLL_BAR (bar->next)->prev = bar->prev;
8656
8657 bar->next = FRAME_SCROLL_BARS (f);
8658 bar->prev = Qnil;
8659 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8660 if (! NILP (bar->next))
8661 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8662 }
8663 }
8664
8665 /* Remove all scroll bars on FRAME that haven't been saved since the
8666 last call to `*condemn_scroll_bars_hook'. */
8667
8668 static void
8669 XTjudge_scroll_bars (f)
8670 FRAME_PTR f;
8671 {
8672 Lisp_Object bar, next;
8673
8674 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8675
8676 /* Clear out the condemned list now so we won't try to process any
8677 more events on the hapless scroll bars. */
8678 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8679
8680 for (; ! NILP (bar); bar = next)
8681 {
8682 struct scroll_bar *b = XSCROLL_BAR (bar);
8683
8684 x_scroll_bar_remove (b);
8685
8686 next = b->next;
8687 b->next = b->prev = Qnil;
8688 }
8689
8690 /* Now there should be no references to the condemned scroll bars,
8691 and they should get garbage-collected. */
8692 }
8693
8694
8695 static void
8696 activate_scroll_bars (frame)
8697 FRAME_PTR frame;
8698 {
8699 Lisp_Object bar;
8700 ControlHandle ch;
8701
8702 bar = FRAME_SCROLL_BARS (frame);
8703 while (! NILP (bar))
8704 {
8705 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8706 #ifdef TARGET_API_MAC_CARBON
8707 ActivateControl (ch);
8708 #else
8709 SetControlMaximum (ch,
8710 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8711 XINT (XSCROLL_BAR (bar)
8712 ->height)) - 1);
8713 #endif
8714 bar = XSCROLL_BAR (bar)->next;
8715 }
8716 }
8717
8718
8719 static void
8720 deactivate_scroll_bars (frame)
8721 FRAME_PTR frame;
8722 {
8723 Lisp_Object bar;
8724 ControlHandle ch;
8725
8726 bar = FRAME_SCROLL_BARS (frame);
8727 while (! NILP (bar))
8728 {
8729 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8730 #ifdef TARGET_API_MAC_CARBON
8731 DeactivateControl (ch);
8732 #else
8733 SetControlMaximum (ch, XINT (-1));
8734 #endif
8735 bar = XSCROLL_BAR (bar)->next;
8736 }
8737 }
8738
8739 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8740 is set to something other than NO_EVENT, it is enqueued.
8741
8742 This may be called from a signal handler, so we have to ignore GC
8743 mark bits. */
8744
8745 static void
8746 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8747 struct scroll_bar *bar;
8748 int part_code;
8749 EventRecord *er;
8750 struct input_event *bufp;
8751 {
8752 if (! GC_WINDOWP (bar->window))
8753 abort ();
8754
8755 bufp->kind = SCROLL_BAR_CLICK_EVENT;
8756 bufp->frame_or_window = bar->window;
8757 bufp->arg = Qnil;
8758
8759 bar->dragging = Qnil;
8760
8761 switch (part_code)
8762 {
8763 case kControlUpButtonPart:
8764 bufp->part = scroll_bar_up_arrow;
8765 break;
8766 case kControlDownButtonPart:
8767 bufp->part = scroll_bar_down_arrow;
8768 break;
8769 case kControlPageUpPart:
8770 bufp->part = scroll_bar_above_handle;
8771 break;
8772 case kControlPageDownPart:
8773 bufp->part = scroll_bar_below_handle;
8774 break;
8775 #ifdef TARGET_API_MAC_CARBON
8776 default:
8777 #else
8778 case kControlIndicatorPart:
8779 #endif
8780 if (er->what == mouseDown)
8781 bar->dragging = make_number (0);
8782 XSETVECTOR (last_mouse_scroll_bar, bar);
8783 bufp->part = scroll_bar_handle;
8784 break;
8785 }
8786 }
8787
8788
8789 /* Handle some mouse motion while someone is dragging the scroll bar.
8790
8791 This may be called from a signal handler, so we have to ignore GC
8792 mark bits. */
8793
8794 static void
8795 x_scroll_bar_note_movement (bar, y_pos, t)
8796 struct scroll_bar *bar;
8797 int y_pos;
8798 Time t;
8799 {
8800 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8801
8802 last_mouse_movement_time = t;
8803
8804 f->mouse_moved = 1;
8805 XSETVECTOR (last_mouse_scroll_bar, bar);
8806
8807 /* If we're dragging the bar, display it. */
8808 if (! GC_NILP (bar->dragging))
8809 {
8810 /* Where should the handle be now? */
8811 int new_start = y_pos - 24;
8812
8813 if (new_start != XINT (bar->start))
8814 {
8815 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8816
8817 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8818 }
8819 }
8820 }
8821
8822
8823 /* Return information to the user about the current position of the
8824 mouse on the scroll bar. */
8825
8826 static void
8827 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8828 FRAME_PTR *fp;
8829 Lisp_Object *bar_window;
8830 enum scroll_bar_part *part;
8831 Lisp_Object *x, *y;
8832 unsigned long *time;
8833 {
8834 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8835 WindowPtr wp = FrontWindow ();
8836 Point mouse_pos;
8837 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8838 int win_y, top_range;
8839
8840 #if TARGET_API_MAC_CARBON
8841 SetPort (GetWindowPort (wp));
8842 #else
8843 SetPort (wp);
8844 #endif
8845
8846 GetMouse (&mouse_pos);
8847
8848 win_y = mouse_pos.v - XINT (bar->top);
8849 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8850
8851 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8852
8853 win_y -= 24;
8854
8855 if (! NILP (bar->dragging))
8856 win_y -= XINT (bar->dragging);
8857
8858 if (win_y < 0)
8859 win_y = 0;
8860 if (win_y > top_range)
8861 win_y = top_range;
8862
8863 *fp = f;
8864 *bar_window = bar->window;
8865
8866 if (! NILP (bar->dragging))
8867 *part = scroll_bar_handle;
8868 else if (win_y < XINT (bar->start))
8869 *part = scroll_bar_above_handle;
8870 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8871 *part = scroll_bar_handle;
8872 else
8873 *part = scroll_bar_below_handle;
8874
8875 XSETINT (*x, win_y);
8876 XSETINT (*y, top_range);
8877
8878 f->mouse_moved = 0;
8879 last_mouse_scroll_bar = Qnil;
8880
8881 *time = last_mouse_movement_time;
8882 }
8883 \f
8884 /***********************************************************************
8885 Text Cursor
8886 ***********************************************************************/
8887
8888 /* Notice if the text cursor of window W has been overwritten by a
8889 drawing operation that outputs glyphs starting at START_X and
8890 ending at END_X in the line given by output_cursor.vpos.
8891 Coordinates are area-relative. END_X < 0 means all the rest
8892 of the line after START_X has been written. */
8893
8894 static void
8895 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
8896 struct window *w;
8897 enum glyph_row_area area;
8898 int x0, x1, y0, y1;
8899 {
8900 if (area == TEXT_AREA
8901 && w->phys_cursor_on_p
8902 && y0 <= w->phys_cursor.y
8903 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8904 && x0 <= w->phys_cursor.x
8905 && (x1 < 0 || x1 > w->phys_cursor.x))
8906 w->phys_cursor_on_p = 0;
8907 }
8908
8909
8910 /* Set clipping for output in glyph row ROW. W is the window in which
8911 we operate. GC is the graphics context to set clipping in.
8912 WHOLE_LINE_P non-zero means include the areas used for truncation
8913 mark display and alike in the clipping rectangle.
8914
8915 ROW may be a text row or, e.g., a mode line. Text rows must be
8916 clipped to the interior of the window dedicated to text display,
8917 mode lines must be clipped to the whole window. */
8918
8919 static void
8920 x_clip_to_row (w, row, gc, whole_line_p)
8921 struct window *w;
8922 struct glyph_row *row;
8923 GC gc;
8924 int whole_line_p;
8925 {
8926 struct frame *f = XFRAME (WINDOW_FRAME (w));
8927 Rect clip_rect;
8928 int window_x, window_y, window_width, window_height;
8929
8930 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8931
8932 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8933 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8934 clip_rect.top = max (clip_rect.top, window_y);
8935 clip_rect.right = clip_rect.left + window_width;
8936 clip_rect.bottom = clip_rect.top + row->visible_height;
8937
8938 /* If clipping to the whole line, including trunc marks, extend
8939 the rectangle to the left and increase its width. */
8940 if (whole_line_p)
8941 {
8942 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8943 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
8944 }
8945
8946 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8947 }
8948
8949
8950 /* Draw a hollow box cursor on window W in glyph row ROW. */
8951
8952 static void
8953 x_draw_hollow_cursor (w, row)
8954 struct window *w;
8955 struct glyph_row *row;
8956 {
8957 struct frame *f = XFRAME (WINDOW_FRAME (w));
8958 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8959 Display *dpy = FRAME_MAC_DISPLAY (f);
8960 int x, y, wd, h;
8961 XGCValues xgcv;
8962 struct glyph *cursor_glyph;
8963 GC gc;
8964
8965 /* Compute frame-relative coordinates from window-relative
8966 coordinates. */
8967 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8968 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8969 + row->ascent - w->phys_cursor_ascent);
8970 h = row->height - 1;
8971
8972 /* Get the glyph the cursor is on. If we can't tell because
8973 the current matrix is invalid or such, give up. */
8974 cursor_glyph = get_phys_cursor_glyph (w);
8975 if (cursor_glyph == NULL)
8976 return;
8977
8978 /* Compute the width of the rectangle to draw. If on a stretch
8979 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8980 rectangle as wide as the glyph, but use a canonical character
8981 width instead. */
8982 wd = cursor_glyph->pixel_width - 1;
8983 if (cursor_glyph->type == STRETCH_GLYPH
8984 && !x_stretch_cursor_p)
8985 wd = min (CANON_X_UNIT (f), wd);
8986
8987 /* The foreground of cursor_gc is typically the same as the normal
8988 background color, which can cause the cursor box to be invisible. */
8989 xgcv.foreground = f->output_data.mac->cursor_pixel;
8990 if (dpyinfo->scratch_cursor_gc)
8991 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8992 else
8993 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8994 GCForeground, &xgcv);
8995 gc = dpyinfo->scratch_cursor_gc;
8996
8997 /* Set clipping, draw the rectangle, and reset clipping again. */
8998 x_clip_to_row (w, row, gc, 0);
8999 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
9000 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9001 }
9002
9003
9004 /* Draw a bar cursor on window W in glyph row ROW.
9005
9006 Implementation note: One would like to draw a bar cursor with an
9007 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9008 Unfortunately, I didn't find a font yet that has this property set.
9009 --gerd. */
9010
9011 static void
9012 x_draw_bar_cursor (w, row, width)
9013 struct window *w;
9014 struct glyph_row *row;
9015 int width;
9016 {
9017 /* If cursor hpos is out of bounds, don't draw garbage. This can
9018 happen in mini-buffer windows when switching between echo area
9019 glyphs and mini-buffer. */
9020 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9021 {
9022 struct frame *f = XFRAME (w->frame);
9023 struct glyph *cursor_glyph;
9024 GC gc;
9025 int x;
9026 unsigned long mask;
9027 XGCValues xgcv;
9028 Display *dpy;
9029 Window window;
9030
9031 cursor_glyph = get_phys_cursor_glyph (w);
9032 if (cursor_glyph == NULL)
9033 return;
9034
9035 xgcv.background = f->output_data.mac->cursor_pixel;
9036 xgcv.foreground = f->output_data.mac->cursor_pixel;
9037 mask = GCForeground | GCBackground;
9038 dpy = FRAME_MAC_DISPLAY (f);
9039 window = FRAME_MAC_WINDOW (f);
9040 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9041
9042 if (gc)
9043 XChangeGC (dpy, gc, mask, &xgcv);
9044 else
9045 {
9046 gc = XCreateGC (dpy, window, mask, &xgcv);
9047 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9048 }
9049
9050 if (width < 0)
9051 width = FRAME_CURSOR_WIDTH (f);
9052
9053 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9054 x_clip_to_row (w, row, gc, 0);
9055 XFillRectangle (dpy, window, gc,
9056 x,
9057 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9058 min (cursor_glyph->pixel_width, width),
9059 row->height);
9060 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9061 }
9062 }
9063
9064
9065 /* Clear the cursor of window W to background color, and mark the
9066 cursor as not shown. This is used when the text where the cursor
9067 is is about to be rewritten. */
9068
9069 static void
9070 x_clear_cursor (w)
9071 struct window *w;
9072 {
9073 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9074 x_update_window_cursor (w, 0);
9075 }
9076
9077
9078 /* Draw the cursor glyph of window W in glyph row ROW. See the
9079 comment of x_draw_glyphs for the meaning of HL. */
9080
9081 static void
9082 x_draw_phys_cursor_glyph (w, row, hl)
9083 struct window *w;
9084 struct glyph_row *row;
9085 enum draw_glyphs_face hl;
9086 {
9087 /* If cursor hpos is out of bounds, don't draw garbage. This can
9088 happen in mini-buffer windows when switching between echo area
9089 glyphs and mini-buffer. */
9090 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9091 {
9092 int on_p = w->phys_cursor_on_p;
9093 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9094 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9095 hl, 0);
9096 w->phys_cursor_on_p = on_p;
9097
9098 /* When we erase the cursor, and ROW is overlapped by other
9099 rows, make sure that these overlapping parts of other rows
9100 are redrawn. */
9101 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9102 {
9103 if (row > w->current_matrix->rows
9104 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9105 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9106
9107 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9108 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9109 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9110 }
9111 }
9112 }
9113
9114
9115 /* Erase the image of a cursor of window W from the screen. */
9116
9117 static void
9118 x_erase_phys_cursor (w)
9119 struct window *w;
9120 {
9121 struct frame *f = XFRAME (w->frame);
9122 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9123 int hpos = w->phys_cursor.hpos;
9124 int vpos = w->phys_cursor.vpos;
9125 int mouse_face_here_p = 0;
9126 struct glyph_matrix *active_glyphs = w->current_matrix;
9127 struct glyph_row *cursor_row;
9128 struct glyph *cursor_glyph;
9129 enum draw_glyphs_face hl;
9130
9131 /* No cursor displayed or row invalidated => nothing to do on the
9132 screen. */
9133 if (w->phys_cursor_type == NO_CURSOR)
9134 goto mark_cursor_off;
9135
9136 /* VPOS >= active_glyphs->nrows means that window has been resized.
9137 Don't bother to erase the cursor. */
9138 if (vpos >= active_glyphs->nrows)
9139 goto mark_cursor_off;
9140
9141 /* If row containing cursor is marked invalid, there is nothing we
9142 can do. */
9143 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9144 if (!cursor_row->enabled_p)
9145 goto mark_cursor_off;
9146
9147 /* If row is completely invisible, don't attempt to delete a cursor which
9148 isn't there. This may happen if cursor is at top of window, and
9149 we switch to a buffer with a header line in that window. */
9150 if (cursor_row->visible_height <= 0)
9151 goto mark_cursor_off;
9152
9153 /* This can happen when the new row is shorter than the old one.
9154 In this case, either x_draw_glyphs or clear_end_of_line
9155 should have cleared the cursor. Note that we wouldn't be
9156 able to erase the cursor in this case because we don't have a
9157 cursor glyph at hand. */
9158 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9159 goto mark_cursor_off;
9160
9161 /* If the cursor is in the mouse face area, redisplay that when
9162 we clear the cursor. */
9163 if (! NILP (dpyinfo->mouse_face_window)
9164 && w == XWINDOW (dpyinfo->mouse_face_window)
9165 && (vpos > dpyinfo->mouse_face_beg_row
9166 || (vpos == dpyinfo->mouse_face_beg_row
9167 && hpos >= dpyinfo->mouse_face_beg_col))
9168 && (vpos < dpyinfo->mouse_face_end_row
9169 || (vpos == dpyinfo->mouse_face_end_row
9170 && hpos < dpyinfo->mouse_face_end_col))
9171 /* Don't redraw the cursor's spot in mouse face if it is at the
9172 end of a line (on a newline). The cursor appears there, but
9173 mouse highlighting does not. */
9174 && cursor_row->used[TEXT_AREA] > hpos)
9175 mouse_face_here_p = 1;
9176
9177 /* Maybe clear the display under the cursor. */
9178 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9179 {
9180 int x;
9181 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9182
9183 cursor_glyph = get_phys_cursor_glyph (w);
9184 if (cursor_glyph == NULL)
9185 goto mark_cursor_off;
9186
9187 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9188
9189 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9190 x,
9191 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9192 cursor_row->y)),
9193 cursor_glyph->pixel_width,
9194 cursor_row->visible_height,
9195 0);
9196 }
9197
9198 /* Erase the cursor by redrawing the character underneath it. */
9199 if (mouse_face_here_p)
9200 hl = DRAW_MOUSE_FACE;
9201 else
9202 hl = DRAW_NORMAL_TEXT;
9203 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9204
9205 mark_cursor_off:
9206 w->phys_cursor_on_p = 0;
9207 w->phys_cursor_type = NO_CURSOR;
9208 }
9209
9210
9211 /* Non-zero if physical cursor of window W is within mouse face. */
9212
9213 static int
9214 cursor_in_mouse_face_p (w)
9215 struct window *w;
9216 {
9217 struct mac_display_info *dpyinfo
9218 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9219 int in_mouse_face = 0;
9220
9221 if (WINDOWP (dpyinfo->mouse_face_window)
9222 && XWINDOW (dpyinfo->mouse_face_window) == w)
9223 {
9224 int hpos = w->phys_cursor.hpos;
9225 int vpos = w->phys_cursor.vpos;
9226
9227 if (vpos >= dpyinfo->mouse_face_beg_row
9228 && vpos <= dpyinfo->mouse_face_end_row
9229 && (vpos > dpyinfo->mouse_face_beg_row
9230 || hpos >= dpyinfo->mouse_face_beg_col)
9231 && (vpos < dpyinfo->mouse_face_end_row
9232 || hpos < dpyinfo->mouse_face_end_col
9233 || dpyinfo->mouse_face_past_end))
9234 in_mouse_face = 1;
9235 }
9236
9237 return in_mouse_face;
9238 }
9239
9240
9241 /* Display or clear cursor of window W. If ON is zero, clear the
9242 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9243 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9244
9245 void
9246 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9247 struct window *w;
9248 int on, hpos, vpos, x, y;
9249 {
9250 struct frame *f = XFRAME (w->frame);
9251 int new_cursor_type;
9252 int new_cursor_width;
9253 struct glyph_matrix *current_glyphs;
9254 struct glyph_row *glyph_row;
9255 struct glyph *glyph;
9256
9257 /* This is pointless on invisible frames, and dangerous on garbaged
9258 windows and frames; in the latter case, the frame or window may
9259 be in the midst of changing its size, and x and y may be off the
9260 window. */
9261 if (! FRAME_VISIBLE_P (f)
9262 || FRAME_GARBAGED_P (f)
9263 || vpos >= w->current_matrix->nrows
9264 || hpos >= w->current_matrix->matrix_w)
9265 return;
9266
9267 /* If cursor is off and we want it off, return quickly. */
9268 if (!on && !w->phys_cursor_on_p)
9269 return;
9270
9271 current_glyphs = w->current_matrix;
9272 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9273 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9274
9275 /* If cursor row is not enabled, we don't really know where to
9276 display the cursor. */
9277 if (!glyph_row->enabled_p)
9278 {
9279 w->phys_cursor_on_p = 0;
9280 return;
9281 }
9282
9283 xassert (interrupt_input_blocked);
9284
9285 /* Set new_cursor_type to the cursor we want to be displayed. */
9286 new_cursor_type = get_window_cursor_type (w, &new_cursor_width);
9287
9288
9289 /* If cursor is currently being shown and we don't want it to be or
9290 it is in the wrong place, or the cursor type is not what we want,
9291 erase it. */
9292 if (w->phys_cursor_on_p
9293 && (!on
9294 || w->phys_cursor.x != x
9295 || w->phys_cursor.y != y
9296 || new_cursor_type != w->phys_cursor_type
9297 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
9298 && new_cursor_width != w->phys_cursor_width)))
9299 x_erase_phys_cursor (w);
9300
9301 /* If the cursor is now invisible and we want it to be visible,
9302 display it. */
9303 if (on && !w->phys_cursor_on_p)
9304 {
9305 w->phys_cursor_ascent = glyph_row->ascent;
9306 w->phys_cursor_height = glyph_row->height;
9307
9308 /* Set phys_cursor_.* before x_draw_.* is called because some
9309 of them may need the information. */
9310 w->phys_cursor.x = x;
9311 w->phys_cursor.y = glyph_row->y;
9312 w->phys_cursor.hpos = hpos;
9313 w->phys_cursor.vpos = vpos;
9314 w->phys_cursor_type = new_cursor_type;
9315 w->phys_cursor_width = new_cursor_width;
9316 w->phys_cursor_on_p = 1;
9317
9318 switch (new_cursor_type)
9319 {
9320 case HOLLOW_BOX_CURSOR:
9321 x_draw_hollow_cursor (w, glyph_row);
9322 break;
9323
9324 case FILLED_BOX_CURSOR:
9325 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9326 break;
9327
9328 case HBAR_CURSOR:
9329 /* TODO. For now, just draw bar cursor. */
9330 case BAR_CURSOR:
9331 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9332 break;
9333
9334 case NO_CURSOR:
9335 break;
9336
9337 default:
9338 abort ();
9339 }
9340 }
9341 }
9342
9343
9344 /* Display the cursor on window W, or clear it. X and Y are window
9345 relative pixel coordinates. HPOS and VPOS are glyph matrix
9346 positions. If W is not the selected window, display a hollow
9347 cursor. ON non-zero means display the cursor at X, Y which
9348 correspond to HPOS, VPOS, otherwise it is cleared. */
9349
9350 void
9351 x_display_cursor (w, on, hpos, vpos, x, y)
9352 struct window *w;
9353 int on, hpos, vpos, x, y;
9354 {
9355 BLOCK_INPUT;
9356 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9357 UNBLOCK_INPUT;
9358 }
9359
9360
9361 /* Display the cursor on window W, or clear it, according to ON_P.
9362 Don't change the cursor's position. */
9363
9364 void
9365 x_update_cursor (f, on_p)
9366 struct frame *f;
9367 int on_p;
9368 {
9369 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9370 }
9371
9372
9373 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9374 in the window tree rooted at W. */
9375
9376 static void
9377 x_update_cursor_in_window_tree (w, on_p)
9378 struct window *w;
9379 int on_p;
9380 {
9381 while (w)
9382 {
9383 if (!NILP (w->hchild))
9384 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9385 else if (!NILP (w->vchild))
9386 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9387 else
9388 x_update_window_cursor (w, on_p);
9389
9390 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9391 }
9392 }
9393
9394
9395 /* Switch the display of W's cursor on or off, according to the value
9396 of ON. */
9397
9398 static void
9399 x_update_window_cursor (w, on)
9400 struct window *w;
9401 int on;
9402 {
9403 /* Don't update cursor in windows whose frame is in the process
9404 of being deleted. */
9405 if (w->current_matrix)
9406 {
9407 BLOCK_INPUT;
9408 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9409 w->phys_cursor.vpos, w->phys_cursor.x,
9410 w->phys_cursor.y);
9411 UNBLOCK_INPUT;
9412 }
9413 }
9414
9415
9416
9417 \f
9418 /* Icons. */
9419
9420 #if 0 /* MAC_TODO: no icon support yet. */
9421 int
9422 x_bitmap_icon (f, icon)
9423 struct frame *f;
9424 Lisp_Object icon;
9425 {
9426 HANDLE hicon;
9427
9428 if (FRAME_W32_WINDOW (f) == 0)
9429 return 1;
9430
9431 if (NILP (icon))
9432 hicon = LoadIcon (hinst, EMACS_CLASS);
9433 else if (STRINGP (icon))
9434 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
9435 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9436 else if (SYMBOLP (icon))
9437 {
9438 LPCTSTR name;
9439
9440 if (EQ (icon, intern ("application")))
9441 name = (LPCTSTR) IDI_APPLICATION;
9442 else if (EQ (icon, intern ("hand")))
9443 name = (LPCTSTR) IDI_HAND;
9444 else if (EQ (icon, intern ("question")))
9445 name = (LPCTSTR) IDI_QUESTION;
9446 else if (EQ (icon, intern ("exclamation")))
9447 name = (LPCTSTR) IDI_EXCLAMATION;
9448 else if (EQ (icon, intern ("asterisk")))
9449 name = (LPCTSTR) IDI_ASTERISK;
9450 else if (EQ (icon, intern ("winlogo")))
9451 name = (LPCTSTR) IDI_WINLOGO;
9452 else
9453 return 1;
9454
9455 hicon = LoadIcon (NULL, name);
9456 }
9457 else
9458 return 1;
9459
9460 if (hicon == NULL)
9461 return 1;
9462
9463 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9464 (LPARAM) hicon);
9465
9466 return 0;
9467 }
9468 #endif /* MAC_TODO */
9469 \f
9470 /************************************************************************
9471 Handling X errors
9472 ************************************************************************/
9473
9474 /* Display Error Handling functions not used on W32. Listing them here
9475 helps diff stay in step when comparing w32term.c with xterm.c.
9476
9477 x_error_catcher (display, error)
9478 x_catch_errors (dpy)
9479 x_catch_errors_unwind (old_val)
9480 x_check_errors (dpy, format)
9481 x_had_errors_p (dpy)
9482 x_clear_errors (dpy)
9483 x_uncatch_errors (dpy, count)
9484 x_trace_wire ()
9485 x_connection_signal (signalnum)
9486 x_connection_closed (dpy, error_message)
9487 x_error_quitter (display, error)
9488 x_error_handler (display, error)
9489 x_io_error_quitter (display)
9490
9491 */
9492
9493 \f
9494 /* Changing the font of the frame. */
9495
9496 /* Give frame F the font named FONTNAME as its default font, and
9497 return the full name of that font. FONTNAME may be a wildcard
9498 pattern; in that case, we choose some font that fits the pattern.
9499 The return value shows which font we chose. */
9500
9501 Lisp_Object
9502 x_new_font (f, fontname)
9503 struct frame *f;
9504 register char *fontname;
9505 {
9506 struct font_info *fontp
9507 = FS_LOAD_FONT (f, 0, fontname, -1);
9508
9509 if (!fontp)
9510 return Qnil;
9511
9512 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9513 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9514 FRAME_FONTSET (f) = -1;
9515
9516 /* Compute the scroll bar width in character columns. */
9517 if (f->scroll_bar_pixel_width > 0)
9518 {
9519 int wid = FONT_WIDTH (FRAME_FONT (f));
9520 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9521 }
9522 else
9523 {
9524 int wid = FONT_WIDTH (FRAME_FONT (f));
9525 f->scroll_bar_cols = (14 + wid - 1) / wid;
9526 }
9527
9528 /* Now make the frame display the given font. */
9529 if (FRAME_MAC_WINDOW (f) != 0)
9530 {
9531 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9532 f->output_data.mac->font);
9533 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9534 f->output_data.mac->font);
9535 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9536 f->output_data.mac->font);
9537
9538 frame_update_line_height (f);
9539 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9540 x_set_window_size (f, 0, f->width, f->height);
9541 }
9542 else
9543 /* If we are setting a new frame's font for the first time,
9544 there are no faces yet, so this font's height is the line height. */
9545 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
9546
9547 return build_string (fontp->full_name);
9548 }
9549 \f
9550 /* Give frame F the fontset named FONTSETNAME as its default font, and
9551 return the full name of that fontset. FONTSETNAME may be a wildcard
9552 pattern; in that case, we choose some fontset that fits the pattern.
9553 The return value shows which fontset we chose. */
9554
9555 Lisp_Object
9556 x_new_fontset (f, fontsetname)
9557 struct frame *f;
9558 char *fontsetname;
9559 {
9560 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9561 Lisp_Object result;
9562
9563 if (fontset < 0)
9564 return Qnil;
9565
9566 if (FRAME_FONTSET (f) == fontset)
9567 /* This fontset is already set in frame F. There's nothing more
9568 to do. */
9569 return fontset_name (fontset);
9570
9571 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
9572
9573 if (!STRINGP (result))
9574 /* Can't load ASCII font. */
9575 return Qnil;
9576
9577 /* Since x_new_font doesn't update any fontset information, do it now. */
9578 FRAME_FONTSET(f) = fontset;
9579
9580 return build_string (fontsetname);
9581 }
9582
9583 /* Compute actual fringe widths */
9584
9585 void
9586 x_compute_fringe_widths (f, redraw)
9587 struct frame *f;
9588 int redraw;
9589 {
9590 int o_left = f->output_data.mac->left_fringe_width;
9591 int o_right = f->output_data.mac->right_fringe_width;
9592 int o_cols = f->output_data.mac->fringe_cols;
9593
9594 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9595 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9596 int left_fringe_width, right_fringe_width;
9597
9598 if (!NILP (left_fringe))
9599 left_fringe = Fcdr (left_fringe);
9600 if (!NILP (right_fringe))
9601 right_fringe = Fcdr (right_fringe);
9602
9603 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9604 XINT (left_fringe));
9605 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9606 XINT (right_fringe));
9607
9608 if (left_fringe_width || right_fringe_width)
9609 {
9610 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9611 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9612 int conf_wid = left_wid + right_wid;
9613 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9614 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9615 int real_wid = cols * font_wid;
9616 if (left_wid && right_wid)
9617 {
9618 if (left_fringe_width < 0)
9619 {
9620 /* Left fringe width is fixed, adjust right fringe if necessary */
9621 f->output_data.mac->left_fringe_width = left_wid;
9622 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9623 }
9624 else if (right_fringe_width < 0)
9625 {
9626 /* Right fringe width is fixed, adjust left fringe if necessary */
9627 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9628 f->output_data.mac->right_fringe_width = right_wid;
9629 }
9630 else
9631 {
9632 /* Adjust both fringes with an equal amount.
9633 Note that we are doing integer arithmetic here, so don't
9634 lose a pixel if the total width is an odd number. */
9635 int fill = real_wid - conf_wid;
9636 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9637 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9638 }
9639 }
9640 else if (left_fringe_width)
9641 {
9642 f->output_data.mac->left_fringe_width = real_wid;
9643 f->output_data.mac->right_fringe_width = 0;
9644 }
9645 else
9646 {
9647 f->output_data.mac->left_fringe_width = 0;
9648 f->output_data.mac->right_fringe_width = real_wid;
9649 }
9650 f->output_data.mac->fringe_cols = cols;
9651 f->output_data.mac->fringes_extra = real_wid;
9652 }
9653 else
9654 {
9655 f->output_data.mac->left_fringe_width = 0;
9656 f->output_data.mac->right_fringe_width = 0;
9657 f->output_data.mac->fringe_cols = 0;
9658 f->output_data.mac->fringes_extra = 0;
9659 }
9660
9661 if (redraw && FRAME_VISIBLE_P (f))
9662 if (o_left != f->output_data.mac->left_fringe_width ||
9663 o_right != f->output_data.mac->right_fringe_width ||
9664 o_cols != f->output_data.mac->fringe_cols)
9665 redraw_frame (f);
9666 }
9667 \f
9668 /***********************************************************************
9669 TODO: W32 Input Methods
9670 ***********************************************************************/
9671 /* Listing missing functions from xterm.c helps diff stay in step.
9672
9673 xim_destroy_callback (xim, client_data, call_data)
9674 xim_open_dpy (dpyinfo, resource_name)
9675 struct xim_inst_t
9676 xim_instantiate_callback (display, client_data, call_data)
9677 xim_initialize (dpyinfo, resource_name)
9678 xim_close_dpy (dpyinfo)
9679
9680 */
9681
9682 \f
9683 /* Calculate the absolute position in frame F
9684 from its current recorded position values and gravity. */
9685
9686 void
9687 x_calc_absolute_position (f)
9688 struct frame *f;
9689 {
9690 Point pt;
9691 int flags = f->output_data.mac->size_hint_flags;
9692
9693 pt.h = pt.v = 0;
9694
9695 /* Find the position of the outside upper-left corner of
9696 the inner window, with respect to the outer window. */
9697 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9698 {
9699 GrafPtr savePort;
9700 GetPort (&savePort);
9701
9702 #if TARGET_API_MAC_CARBON
9703 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9704 #else
9705 SetPort (FRAME_MAC_WINDOW (f));
9706 #endif
9707
9708 #if TARGET_API_MAC_CARBON
9709 {
9710 Rect r;
9711
9712 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9713 SetPt(&pt, r.left, r.top);
9714 }
9715 #else /* not TARGET_API_MAC_CARBON */
9716 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
9717 #endif /* not TARGET_API_MAC_CARBON */
9718 LocalToGlobal (&pt);
9719 SetPort (savePort);
9720 }
9721
9722 /* Treat negative positions as relative to the leftmost bottommost
9723 position that fits on the screen. */
9724 if (flags & XNegative)
9725 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9726 - 2 * f->output_data.mac->border_width - pt.h
9727 - PIXEL_WIDTH (f)
9728 + f->output_data.mac->left_pos);
9729 /* NTEMACS_TODO: Subtract menubar height? */
9730 if (flags & YNegative)
9731 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9732 - 2 * f->output_data.mac->border_width - pt.v
9733 - PIXEL_HEIGHT (f)
9734 + f->output_data.mac->top_pos);
9735 /* The left_pos and top_pos
9736 are now relative to the top and left screen edges,
9737 so the flags should correspond. */
9738 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9739 }
9740
9741 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9742 to really change the position, and 0 when calling from
9743 x_make_frame_visible (in that case, XOFF and YOFF are the current
9744 position values). It is -1 when calling from x_set_frame_parameters,
9745 which means, do adjust for borders but don't change the gravity. */
9746
9747 void
9748 x_set_offset (f, xoff, yoff, change_gravity)
9749 struct frame *f;
9750 register int xoff, yoff;
9751 int change_gravity;
9752 {
9753 int modified_top, modified_left;
9754
9755 if (change_gravity > 0)
9756 {
9757 f->output_data.mac->top_pos = yoff;
9758 f->output_data.mac->left_pos = xoff;
9759 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9760 if (xoff < 0)
9761 f->output_data.mac->size_hint_flags |= XNegative;
9762 if (yoff < 0)
9763 f->output_data.mac->size_hint_flags |= YNegative;
9764 f->output_data.mac->win_gravity = NorthWestGravity;
9765 }
9766 x_calc_absolute_position (f);
9767
9768 BLOCK_INPUT;
9769 x_wm_set_size_hint (f, (long) 0, 0);
9770
9771 modified_left = f->output_data.mac->left_pos;
9772 modified_top = f->output_data.mac->top_pos;
9773
9774 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9775 modified_top + 42, false);
9776
9777 UNBLOCK_INPUT;
9778 }
9779
9780 /* Call this to change the size of frame F's x-window.
9781 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9782 for this size change and subsequent size changes.
9783 Otherwise we leave the window gravity unchanged. */
9784
9785 void
9786 x_set_window_size (f, change_gravity, cols, rows)
9787 struct frame *f;
9788 int change_gravity;
9789 int cols, rows;
9790 {
9791 int pixelwidth, pixelheight;
9792
9793 BLOCK_INPUT;
9794
9795 check_frame_size (f, &rows, &cols);
9796 f->output_data.mac->vertical_scroll_bar_extra
9797 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9798 ? 0
9799 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
9800
9801 x_compute_fringe_widths (f, 0);
9802
9803 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9804 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9805
9806 f->output_data.mac->win_gravity = NorthWestGravity;
9807 x_wm_set_size_hint (f, (long) 0, 0);
9808
9809 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9810
9811 /* Now, strictly speaking, we can't be sure that this is accurate,
9812 but the window manager will get around to dealing with the size
9813 change request eventually, and we'll hear how it went when the
9814 ConfigureNotify event gets here.
9815
9816 We could just not bother storing any of this information here,
9817 and let the ConfigureNotify event set everything up, but that
9818 might be kind of confusing to the Lisp code, since size changes
9819 wouldn't be reported in the frame parameters until some random
9820 point in the future when the ConfigureNotify event arrives.
9821
9822 We pass 1 for DELAY since we can't run Lisp code inside of
9823 a BLOCK_INPUT. */
9824 change_frame_size (f, rows, cols, 0, 1, 0);
9825 PIXEL_WIDTH (f) = pixelwidth;
9826 PIXEL_HEIGHT (f) = pixelheight;
9827
9828 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9829 receive in the ConfigureNotify event; if we get what we asked
9830 for, then the event won't cause the screen to become garbaged, so
9831 we have to make sure to do it here. */
9832 SET_FRAME_GARBAGED (f);
9833
9834 XFlush (FRAME_X_DISPLAY (f));
9835
9836 /* If cursor was outside the new size, mark it as off. */
9837 mark_window_cursors_off (XWINDOW (f->root_window));
9838
9839 /* Clear out any recollection of where the mouse highlighting was,
9840 since it might be in a place that's outside the new frame size.
9841 Actually checking whether it is outside is a pain in the neck,
9842 so don't try--just let the highlighting be done afresh with new size. */
9843 cancel_mouse_face (f);
9844
9845 UNBLOCK_INPUT;
9846 }
9847 \f
9848 /* Mouse warping. */
9849
9850 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9851
9852 void
9853 x_set_mouse_position (f, x, y)
9854 struct frame *f;
9855 int x, y;
9856 {
9857 int pix_x, pix_y;
9858
9859 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9860 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9861
9862 if (pix_x < 0) pix_x = 0;
9863 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9864
9865 if (pix_y < 0) pix_y = 0;
9866 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9867
9868 x_set_mouse_pixel_position (f, pix_x, pix_y);
9869 }
9870
9871 void
9872 x_set_mouse_pixel_position (f, pix_x, pix_y)
9873 struct frame *f;
9874 int pix_x, pix_y;
9875 {
9876 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9877 BLOCK_INPUT;
9878
9879 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9880 0, 0, 0, 0, pix_x, pix_y);
9881 UNBLOCK_INPUT;
9882 #endif
9883 }
9884
9885 \f
9886 /* focus shifting, raising and lowering. */
9887
9888 void
9889 x_focus_on_frame (f)
9890 struct frame *f;
9891 {
9892 #if 0 /* This proves to be unpleasant. */
9893 x_raise_frame (f);
9894 #endif
9895 #if 0
9896 /* I don't think that the ICCCM allows programs to do things like this
9897 without the interaction of the window manager. Whatever you end up
9898 doing with this code, do it to x_unfocus_frame too. */
9899 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9900 RevertToPointerRoot, CurrentTime);
9901 #endif /* ! 0 */
9902 }
9903
9904 void
9905 x_unfocus_frame (f)
9906 struct frame *f;
9907 {
9908 }
9909
9910 /* Raise frame F. */
9911 void
9912 x_raise_frame (f)
9913 struct frame *f;
9914 {
9915 if (f->async_visible)
9916 SelectWindow (FRAME_MAC_WINDOW (f));
9917 }
9918
9919 /* Lower frame F. */
9920 void
9921 x_lower_frame (f)
9922 struct frame *f;
9923 {
9924 if (f->async_visible)
9925 SendBehind (FRAME_MAC_WINDOW (f), nil);
9926 }
9927
9928 static void
9929 XTframe_raise_lower (f, raise_flag)
9930 FRAME_PTR f;
9931 int raise_flag;
9932 {
9933 if (raise_flag)
9934 x_raise_frame (f);
9935 else
9936 x_lower_frame (f);
9937 }
9938 \f
9939 /* Change of visibility. */
9940
9941 /* This tries to wait until the frame is really visible.
9942 However, if the window manager asks the user where to position
9943 the frame, this will return before the user finishes doing that.
9944 The frame will not actually be visible at that time,
9945 but it will become visible later when the window manager
9946 finishes with it. */
9947
9948 void
9949 x_make_frame_visible (f)
9950 struct frame *f;
9951 {
9952 Lisp_Object type;
9953 int original_top, original_left;
9954
9955 BLOCK_INPUT;
9956
9957 if (! FRAME_VISIBLE_P (f))
9958 {
9959 /* We test FRAME_GARBAGED_P here to make sure we don't
9960 call x_set_offset a second time
9961 if we get to x_make_frame_visible a second time
9962 before the window gets really visible. */
9963 if (! FRAME_ICONIFIED_P (f)
9964 && ! f->output_data.mac->asked_for_visible)
9965 x_set_offset (f, f->output_data.mac->left_pos,
9966 f->output_data.mac->top_pos, 0);
9967
9968 f->output_data.mac->asked_for_visible = 1;
9969
9970 ShowWindow (FRAME_MAC_WINDOW (f));
9971 }
9972
9973 XFlush (FRAME_MAC_DISPLAY (f));
9974
9975 #if 0 /* MAC_TODO */
9976 /* Synchronize to ensure Emacs knows the frame is visible
9977 before we do anything else. We do this loop with input not blocked
9978 so that incoming events are handled. */
9979 {
9980 Lisp_Object frame;
9981 int count;
9982
9983 /* This must come after we set COUNT. */
9984 UNBLOCK_INPUT;
9985
9986 XSETFRAME (frame, f);
9987
9988 /* Wait until the frame is visible. Process X events until a
9989 MapNotify event has been seen, or until we think we won't get a
9990 MapNotify at all.. */
9991 for (count = input_signal_count + 10;
9992 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9993 {
9994 /* Force processing of queued events. */
9995 x_sync (f);
9996
9997 /* Machines that do polling rather than SIGIO have been
9998 observed to go into a busy-wait here. So we'll fake an
9999 alarm signal to let the handler know that there's something
10000 to be read. We used to raise a real alarm, but it seems
10001 that the handler isn't always enabled here. This is
10002 probably a bug. */
10003 if (input_polling_used ())
10004 {
10005 /* It could be confusing if a real alarm arrives while
10006 processing the fake one. Turn it off and let the
10007 handler reset it. */
10008 extern void poll_for_input_1 P_ ((void));
10009 int old_poll_suppress_count = poll_suppress_count;
10010 poll_suppress_count = 1;
10011 poll_for_input_1 ();
10012 poll_suppress_count = old_poll_suppress_count;
10013 }
10014
10015 /* See if a MapNotify event has been processed. */
10016 FRAME_SAMPLE_VISIBILITY (f);
10017 }
10018 }
10019 #endif /* MAC_TODO */
10020 }
10021
10022 /* Change from mapped state to withdrawn state. */
10023
10024 /* Make the frame visible (mapped and not iconified). */
10025
10026 void
10027 x_make_frame_invisible (f)
10028 struct frame *f;
10029 {
10030 /* Don't keep the highlight on an invisible frame. */
10031 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10032 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10033
10034 BLOCK_INPUT;
10035
10036 HideWindow (FRAME_MAC_WINDOW (f));
10037
10038 /* We can't distinguish this from iconification
10039 just by the event that we get from the server.
10040 So we can't win using the usual strategy of letting
10041 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10042 and synchronize with the server to make sure we agree. */
10043 f->visible = 0;
10044 FRAME_ICONIFIED_P (f) = 0;
10045 f->async_visible = 0;
10046 f->async_iconified = 0;
10047
10048 UNBLOCK_INPUT;
10049 }
10050
10051 /* Change window state from mapped to iconified. */
10052
10053 void
10054 x_iconify_frame (f)
10055 struct frame *f;
10056 {
10057 /* Don't keep the highlight on an invisible frame. */
10058 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10059 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10060
10061 #if 0
10062 /* Review: Since window is still visible in dock, still allow updates? */
10063 if (f->async_iconified)
10064 return;
10065 #endif
10066
10067 BLOCK_INPUT;
10068
10069 CollapseWindow (FRAME_MAC_WINDOW (f), true);
10070
10071 UNBLOCK_INPUT;
10072 }
10073
10074 \f
10075 /* Destroy the X window of frame F. */
10076
10077 void
10078 x_destroy_window (f)
10079 struct frame *f;
10080 {
10081 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10082
10083 BLOCK_INPUT;
10084
10085 DisposeWindow (FRAME_MAC_WINDOW (f));
10086
10087 free_frame_menubar (f);
10088 free_frame_faces (f);
10089
10090 xfree (f->output_data.mac);
10091 f->output_data.mac = 0;
10092 if (f == dpyinfo->x_focus_frame)
10093 dpyinfo->x_focus_frame = 0;
10094 if (f == dpyinfo->x_focus_event_frame)
10095 dpyinfo->x_focus_event_frame = 0;
10096 if (f == dpyinfo->x_highlight_frame)
10097 dpyinfo->x_highlight_frame = 0;
10098
10099 dpyinfo->reference_count--;
10100
10101 if (f == dpyinfo->mouse_face_mouse_frame)
10102 {
10103 dpyinfo->mouse_face_beg_row
10104 = dpyinfo->mouse_face_beg_col = -1;
10105 dpyinfo->mouse_face_end_row
10106 = dpyinfo->mouse_face_end_col = -1;
10107 dpyinfo->mouse_face_window = Qnil;
10108 dpyinfo->mouse_face_deferred_gc = 0;
10109 dpyinfo->mouse_face_mouse_frame = 0;
10110 }
10111
10112 UNBLOCK_INPUT;
10113 }
10114 \f
10115 /* Setting window manager hints. */
10116
10117 /* Set the normal size hints for the window manager, for frame F.
10118 FLAGS is the flags word to use--or 0 meaning preserve the flags
10119 that the window now has.
10120 If USER_POSITION is nonzero, we set the USPosition
10121 flag (this is useful when FLAGS is 0). */
10122 void
10123 x_wm_set_size_hint (f, flags, user_position)
10124 struct frame *f;
10125 long flags;
10126 int user_position;
10127 {
10128 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
10129 XSizeHints size_hints;
10130
10131 #ifdef USE_X_TOOLKIT
10132 Arg al[2];
10133 int ac = 0;
10134 Dimension widget_width, widget_height;
10135 Window window = XtWindow (f->output_data.x->widget);
10136 #else /* not USE_X_TOOLKIT */
10137 Window window = FRAME_X_WINDOW (f);
10138 #endif /* not USE_X_TOOLKIT */
10139
10140 /* Setting PMaxSize caused various problems. */
10141 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10142
10143 size_hints.x = f->output_data.x->left_pos;
10144 size_hints.y = f->output_data.x->top_pos;
10145
10146 #ifdef USE_X_TOOLKIT
10147 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10148 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10149 XtGetValues (f->output_data.x->widget, al, ac);
10150 size_hints.height = widget_height;
10151 size_hints.width = widget_width;
10152 #else /* not USE_X_TOOLKIT */
10153 size_hints.height = PIXEL_HEIGHT (f);
10154 size_hints.width = PIXEL_WIDTH (f);
10155 #endif /* not USE_X_TOOLKIT */
10156
10157 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10158 size_hints.height_inc = f->output_data.x->line_height;
10159 size_hints.max_width
10160 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10161 size_hints.max_height
10162 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10163
10164 /* Calculate the base and minimum sizes.
10165
10166 (When we use the X toolkit, we don't do it here.
10167 Instead we copy the values that the widgets are using, below.) */
10168 #ifndef USE_X_TOOLKIT
10169 {
10170 int base_width, base_height;
10171 int min_rows = 0, min_cols = 0;
10172
10173 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10174 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10175
10176 check_frame_size (f, &min_rows, &min_cols);
10177
10178 /* The window manager uses the base width hints to calculate the
10179 current number of rows and columns in the frame while
10180 resizing; min_width and min_height aren't useful for this
10181 purpose, since they might not give the dimensions for a
10182 zero-row, zero-column frame.
10183
10184 We use the base_width and base_height members if we have
10185 them; otherwise, we set the min_width and min_height members
10186 to the size for a zero x zero frame. */
10187
10188 #ifdef HAVE_X11R4
10189 size_hints.flags |= PBaseSize;
10190 size_hints.base_width = base_width;
10191 size_hints.base_height = base_height;
10192 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10193 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10194 #else
10195 size_hints.min_width = base_width;
10196 size_hints.min_height = base_height;
10197 #endif
10198 }
10199
10200 /* If we don't need the old flags, we don't need the old hint at all. */
10201 if (flags)
10202 {
10203 size_hints.flags |= flags;
10204 goto no_read;
10205 }
10206 #endif /* not USE_X_TOOLKIT */
10207
10208 {
10209 XSizeHints hints; /* Sometimes I hate X Windows... */
10210 long supplied_return;
10211 int value;
10212
10213 #ifdef HAVE_X11R4
10214 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10215 &supplied_return);
10216 #else
10217 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10218 #endif
10219
10220 #ifdef USE_X_TOOLKIT
10221 size_hints.base_height = hints.base_height;
10222 size_hints.base_width = hints.base_width;
10223 size_hints.min_height = hints.min_height;
10224 size_hints.min_width = hints.min_width;
10225 #endif
10226
10227 if (flags)
10228 size_hints.flags |= flags;
10229 else
10230 {
10231 if (value == 0)
10232 hints.flags = 0;
10233 if (hints.flags & PSize)
10234 size_hints.flags |= PSize;
10235 if (hints.flags & PPosition)
10236 size_hints.flags |= PPosition;
10237 if (hints.flags & USPosition)
10238 size_hints.flags |= USPosition;
10239 if (hints.flags & USSize)
10240 size_hints.flags |= USSize;
10241 }
10242 }
10243
10244 #ifndef USE_X_TOOLKIT
10245 no_read:
10246 #endif
10247
10248 #ifdef PWinGravity
10249 size_hints.win_gravity = f->output_data.x->win_gravity;
10250 size_hints.flags |= PWinGravity;
10251
10252 if (user_position)
10253 {
10254 size_hints.flags &= ~ PPosition;
10255 size_hints.flags |= USPosition;
10256 }
10257 #endif /* PWinGravity */
10258
10259 #ifdef HAVE_X11R4
10260 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10261 #else
10262 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10263 #endif
10264 #endif /* MAC_TODO */
10265 }
10266
10267 #if 0 /* MAC_TODO: hide application instead of iconify? */
10268 /* Used for IconicState or NormalState */
10269
10270 void
10271 x_wm_set_window_state (f, state)
10272 struct frame *f;
10273 int state;
10274 {
10275 #ifdef USE_X_TOOLKIT
10276 Arg al[1];
10277
10278 XtSetArg (al[0], XtNinitialState, state);
10279 XtSetValues (f->output_data.x->widget, al, 1);
10280 #else /* not USE_X_TOOLKIT */
10281 Window window = FRAME_X_WINDOW (f);
10282
10283 f->output_data.x->wm_hints.flags |= StateHint;
10284 f->output_data.x->wm_hints.initial_state = state;
10285
10286 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10287 #endif /* not USE_X_TOOLKIT */
10288 }
10289
10290 void
10291 x_wm_set_icon_pixmap (f, pixmap_id)
10292 struct frame *f;
10293 int pixmap_id;
10294 {
10295 Pixmap icon_pixmap;
10296
10297 #ifndef USE_X_TOOLKIT
10298 Window window = FRAME_X_WINDOW (f);
10299 #endif
10300
10301 if (pixmap_id > 0)
10302 {
10303 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10304 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10305 }
10306 else
10307 {
10308 /* It seems there is no way to turn off use of an icon pixmap.
10309 The following line does it, only if no icon has yet been created,
10310 for some window managers. But with mwm it crashes.
10311 Some people say it should clear the IconPixmapHint bit in this case,
10312 but that doesn't work, and the X consortium said it isn't the
10313 right thing at all. Since there is no way to win,
10314 best to explicitly give up. */
10315 #if 0
10316 f->output_data.x->wm_hints.icon_pixmap = None;
10317 #else
10318 return;
10319 #endif
10320 }
10321
10322 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10323
10324 {
10325 Arg al[1];
10326 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10327 XtSetValues (f->output_data.x->widget, al, 1);
10328 }
10329
10330 #else /* not USE_X_TOOLKIT */
10331
10332 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10333 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10334
10335 #endif /* not USE_X_TOOLKIT */
10336 }
10337
10338 #endif /* MAC_TODO */
10339
10340 void
10341 x_wm_set_icon_position (f, icon_x, icon_y)
10342 struct frame *f;
10343 int icon_x, icon_y;
10344 {
10345 #if 0 /* MAC_TODO: no icons on Mac */
10346 #ifdef USE_X_TOOLKIT
10347 Window window = XtWindow (f->output_data.x->widget);
10348 #else
10349 Window window = FRAME_X_WINDOW (f);
10350 #endif
10351
10352 f->output_data.x->wm_hints.flags |= IconPositionHint;
10353 f->output_data.x->wm_hints.icon_x = icon_x;
10354 f->output_data.x->wm_hints.icon_y = icon_y;
10355
10356 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10357 #endif /* MAC_TODO */
10358 }
10359
10360 \f
10361 /***********************************************************************
10362 Fonts
10363 ***********************************************************************/
10364
10365 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10366
10367 struct font_info *
10368 x_get_font_info (f, font_idx)
10369 FRAME_PTR f;
10370 int font_idx;
10371 {
10372 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10373 }
10374
10375 /* the global font name table */
10376 char **font_name_table = NULL;
10377 int font_name_table_size = 0;
10378 int font_name_count = 0;
10379
10380 /* compare two strings ignoring case */
10381 static int
10382 stricmp (const char *s, const char *t)
10383 {
10384 for ( ; tolower (*s) == tolower (*t); s++, t++)
10385 if (*s == '\0')
10386 return 0;
10387 return tolower (*s) - tolower (*t);
10388 }
10389
10390 /* compare two strings ignoring case and handling wildcard */
10391 static int
10392 wildstrieq (char *s1, char *s2)
10393 {
10394 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10395 return true;
10396
10397 return stricmp (s1, s2) == 0;
10398 }
10399
10400 /* Assume parameter 1 is fully qualified, no wildcards. */
10401 static int
10402 mac_font_pattern_match (fontname, pattern)
10403 char * fontname;
10404 char * pattern;
10405 {
10406 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
10407 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10408 char *ptr;
10409
10410 /* Copy fontname so we can modify it during comparison. */
10411 strcpy (font_name_copy, fontname);
10412
10413 ptr = regex;
10414 *ptr++ = '^';
10415
10416 /* Turn pattern into a regexp and do a regexp match. */
10417 for (; *pattern; pattern++)
10418 {
10419 if (*pattern == '?')
10420 *ptr++ = '.';
10421 else if (*pattern == '*')
10422 {
10423 *ptr++ = '.';
10424 *ptr++ = '*';
10425 }
10426 else
10427 *ptr++ = *pattern;
10428 }
10429 *ptr = '$';
10430 *(ptr + 1) = '\0';
10431
10432 return (fast_c_string_match_ignore_case (build_string (regex),
10433 font_name_copy) >= 0);
10434 }
10435
10436 /* Two font specs are considered to match if their foundry, family,
10437 weight, slant, and charset match. */
10438 static int
10439 mac_font_match (char *mf, char *xf)
10440 {
10441 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10442 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10443
10444 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10445 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10446 return mac_font_pattern_match (mf, xf);
10447
10448 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10449 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10450 return mac_font_pattern_match (mf, xf);
10451
10452 return (wildstrieq (m_foundry, x_foundry)
10453 && wildstrieq (m_family, x_family)
10454 && wildstrieq (m_weight, x_weight)
10455 && wildstrieq (m_slant, x_slant)
10456 && wildstrieq (m_charset, x_charset))
10457 || mac_font_pattern_match (mf, xf);
10458 }
10459
10460
10461 static char *
10462 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10463 {
10464 char foundry[32], family[32], cs[32];
10465 char xf[255], *result, *p;
10466
10467 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10468 {
10469 strcpy(foundry, "Apple");
10470 strcpy(family, name);
10471
10472 switch (scriptcode)
10473 {
10474 case smTradChinese:
10475 strcpy(cs, "big5-0");
10476 break;
10477 case smSimpChinese:
10478 strcpy(cs, "gb2312.1980-0");
10479 break;
10480 case smJapanese:
10481 strcpy(cs, "jisx0208.1983-sjis");
10482 break;
10483 case -smJapanese:
10484 /* Each Apple Japanese font is entered into the font table
10485 twice: once as a jisx0208.1983-sjis font and once as a
10486 jisx0201.1976-0 font. The latter can be used to display
10487 the ascii charset and katakana-jisx0201 charset. A
10488 negative script code signals that the name of this latter
10489 font is being built. */
10490 strcpy(cs, "jisx0201.1976-0");
10491 break;
10492 case smKorean:
10493 strcpy(cs, "ksc5601.1989-0");
10494 break;
10495 default:
10496 strcpy(cs, "mac-roman");
10497 break;
10498 }
10499 }
10500
10501 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10502 foundry, family, style & bold ? "bold" : "medium",
10503 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10504
10505 result = (char *) xmalloc (strlen (xf) + 1);
10506 strcpy (result, xf);
10507 for (p = result; *p; p++)
10508 *p = tolower(*p);
10509 return result;
10510 }
10511
10512
10513 /* Convert an X font spec to the corresponding mac font name, which
10514 can then be passed to GetFNum after conversion to a Pascal string.
10515 For ordinary Mac fonts, this should just be their names, like
10516 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10517 collection contain their charset designation in their names, like
10518 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10519 names are handled accordingly. */
10520 static void
10521 x_font_name_to_mac_font_name (char *xf, char *mf)
10522 {
10523 char foundry[32], family[32], weight[20], slant[2], cs[32];
10524
10525 strcpy (mf, "");
10526
10527 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10528 foundry, family, weight, slant, cs) != 5 &&
10529 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10530 foundry, family, weight, slant, cs) != 5)
10531 return;
10532
10533 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
10534 || strcmp (cs, "jisx0208.1983-sjis") == 0
10535 || strcmp (cs, "jisx0201.1976-0") == 0
10536 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
10537 strcpy(mf, family);
10538 else
10539 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10540 }
10541
10542
10543 static void
10544 add_font_name_table_entry (char *font_name)
10545 {
10546 if (font_name_table_size == 0)
10547 {
10548 font_name_table_size = 16;
10549 font_name_table = (char **)
10550 xmalloc (font_name_table_size * sizeof (char *));
10551 }
10552 else if (font_name_count + 1 >= font_name_table_size)
10553 {
10554 font_name_table_size += 16;
10555 font_name_table = (char **)
10556 xrealloc (font_name_table,
10557 font_name_table_size * sizeof (char *));
10558 }
10559
10560 font_name_table[font_name_count++] = font_name;
10561 }
10562
10563 /* Sets up the table font_name_table to contain the list of all fonts
10564 in the system the first time the table is used so that the Resource
10565 Manager need not be accessed every time this information is
10566 needed. */
10567
10568 static void
10569 init_font_name_table ()
10570 {
10571 #if TARGET_API_MAC_CARBON
10572 SInt32 sv;
10573
10574 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10575 {
10576 FMFontFamilyIterator ffi;
10577 FMFontFamilyInstanceIterator ffii;
10578 FMFontFamily ff;
10579
10580 /* Create a dummy instance iterator here to avoid creating and
10581 destroying it in the loop. */
10582 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10583 return;
10584 /* Create an iterator to enumerate the font families. */
10585 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10586 != noErr)
10587 {
10588 FMDisposeFontFamilyInstanceIterator (&ffii);
10589 return;
10590 }
10591
10592 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10593 {
10594 Str255 name;
10595 FMFont font;
10596 FMFontStyle style;
10597 FMFontSize size;
10598 SInt16 sc;
10599
10600 if (FMGetFontFamilyName (ff, name) != noErr)
10601 break;
10602 p2cstr (name);
10603
10604 sc = FontToScript (ff);
10605
10606 /* Point the instance iterator at the current font family. */
10607 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10608 break;
10609
10610 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10611 == noErr)
10612 if (size == 0)
10613 {
10614 add_font_name_table_entry (mac_to_x_fontname (name, size,
10615 style, sc));
10616 add_font_name_table_entry (mac_to_x_fontname (name, size,
10617 italic, sc));
10618 add_font_name_table_entry (mac_to_x_fontname (name, size,
10619 bold, sc));
10620 add_font_name_table_entry (mac_to_x_fontname (name, size,
10621 italic | bold,
10622 sc));
10623 }
10624 else
10625 {
10626 add_font_name_table_entry (mac_to_x_fontname (name, size,
10627 style, sc));
10628 if (smJapanese == sc)
10629 add_font_name_table_entry (mac_to_x_fontname (name, size,
10630 style,
10631 -smJapanese));
10632 }
10633 }
10634
10635 /* Dispose of the iterators. */
10636 FMDisposeFontFamilyIterator (&ffi);
10637 FMDisposeFontFamilyInstanceIterator (&ffii);
10638 }
10639 else
10640 {
10641 #endif /* TARGET_API_MAC_CARBON */
10642 GrafPtr port;
10643 SInt16 fontnum, old_fontnum;
10644 int num_mac_fonts = CountResources('FOND');
10645 int i, j;
10646 Handle font_handle, font_handle_2;
10647 short id, scriptcode;
10648 ResType type;
10649 Str32 name;
10650 struct FontAssoc *fat;
10651 struct AsscEntry *assc_entry;
10652
10653 GetPort (&port); /* save the current font number used */
10654 #if TARGET_API_MAC_CARBON
10655 old_fontnum = GetPortTextFont (port);
10656 #else
10657 old_fontnum = port->txFont;
10658 #endif
10659
10660 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10661 {
10662 font_handle = GetIndResource ('FOND', i);
10663 if (!font_handle)
10664 continue;
10665
10666 GetResInfo (font_handle, &id, &type, name);
10667 GetFNum (name, &fontnum);
10668 p2cstr (name);
10669 if (fontnum == 0)
10670 continue;
10671
10672 TextFont (fontnum);
10673 scriptcode = FontToScript (fontnum);
10674 do
10675 {
10676 HLock (font_handle);
10677
10678 if (GetResourceSizeOnDisk (font_handle)
10679 >= sizeof (struct FamRec))
10680 {
10681 fat = (struct FontAssoc *) (*font_handle
10682 + sizeof (struct FamRec));
10683 assc_entry
10684 = (struct AsscEntry *) (*font_handle
10685 + sizeof (struct FamRec)
10686 + sizeof (struct FontAssoc));
10687
10688 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
10689 {
10690 if (font_name_table_size == 0)
10691 {
10692 font_name_table_size = 16;
10693 font_name_table = (char **)
10694 xmalloc (font_name_table_size * sizeof (char *));
10695 }
10696 else if (font_name_count >= font_name_table_size)
10697 {
10698 font_name_table_size += 16;
10699 font_name_table = (char **)
10700 xrealloc (font_name_table,
10701 font_name_table_size * sizeof (char *));
10702 }
10703 font_name_table[font_name_count++]
10704 = mac_to_x_fontname (name,
10705 assc_entry->fontSize,
10706 assc_entry->fontStyle,
10707 scriptcode);
10708 /* Both jisx0208.1983-sjis and
10709 jisx0201.1976-sjis parts are contained in
10710 Apple Japanese (SJIS) font. */
10711 if (smJapanese == scriptcode)
10712 {
10713 font_name_table[font_name_count++]
10714 = mac_to_x_fontname (name,
10715 assc_entry->fontSize,
10716 assc_entry->fontStyle,
10717 -smJapanese);
10718 }
10719 }
10720 }
10721
10722 HUnlock (font_handle);
10723 font_handle_2 = GetNextFOND (font_handle);
10724 ReleaseResource (font_handle);
10725 font_handle = font_handle_2;
10726 }
10727 while (ResError () == noErr && font_handle);
10728 }
10729
10730 TextFont (old_fontnum);
10731 #if TARGET_API_MAC_CARBON
10732 }
10733 #endif /* TARGET_API_MAC_CARBON */
10734 }
10735
10736
10737 /* Return a list of at most MAXNAMES font specs matching the one in
10738 PATTERN. Cache matching fonts for patterns in
10739 dpyinfo->name_list_element to avoid looking them up again by
10740 calling mac_font_pattern_match (slow). */
10741
10742 Lisp_Object
10743 x_list_fonts (struct frame *f,
10744 Lisp_Object pattern,
10745 int size,
10746 int maxnames)
10747 {
10748 char *ptnstr;
10749 Lisp_Object newlist = Qnil, tem, key;
10750 int n_fonts = 0;
10751 int i;
10752 struct gcpro gcpro1, gcpro2;
10753 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
10754
10755 if (font_name_table == NULL) /* Initialize when first used. */
10756 init_font_name_table ();
10757
10758 if (dpyinfo)
10759 {
10760 tem = XCDR (dpyinfo->name_list_element);
10761 key = Fcons (pattern, make_number (maxnames));
10762
10763 newlist = Fassoc (key, tem);
10764 if (!NILP (newlist))
10765 {
10766 newlist = Fcdr_safe (newlist);
10767 goto label_cached;
10768 }
10769 }
10770
10771 ptnstr = SDATA (pattern);
10772
10773 GCPRO2 (pattern, newlist);
10774
10775 /* Scan and matching bitmap fonts. */
10776 for (i = 0; i < font_name_count; i++)
10777 {
10778 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10779 {
10780 newlist = Fcons (build_string (font_name_table[i]), newlist);
10781
10782 n_fonts++;
10783 if (n_fonts >= maxnames)
10784 break;
10785 }
10786 }
10787
10788 /* MAC_TODO: add code for matching outline fonts here */
10789
10790 UNGCPRO;
10791
10792 if (dpyinfo)
10793 {
10794 XSETCDR (dpyinfo->name_list_element,
10795 Fcons (Fcons (key, newlist),
10796 XCDR (dpyinfo->name_list_element)));
10797 }
10798 label_cached:
10799
10800 return newlist;
10801 }
10802
10803
10804 #if GLYPH_DEBUG
10805
10806 /* Check that FONT is valid on frame F. It is if it can be found in F's
10807 font table. */
10808
10809 static void
10810 x_check_font (f, font)
10811 struct frame *f;
10812 XFontStruct *font;
10813 {
10814 int i;
10815 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10816
10817 xassert (font != NULL);
10818
10819 for (i = 0; i < dpyinfo->n_fonts; i++)
10820 if (dpyinfo->font_table[i].name
10821 && font == dpyinfo->font_table[i].font)
10822 break;
10823
10824 xassert (i < dpyinfo->n_fonts);
10825 }
10826
10827 #endif /* GLYPH_DEBUG != 0 */
10828
10829 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10830 Note: There are (broken) X fonts out there with invalid XFontStruct
10831 min_bounds contents. For example, handa@etl.go.jp reports that
10832 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10833 have font->min_bounds.width == 0. */
10834
10835 static INLINE void
10836 x_font_min_bounds (font, w, h)
10837 MacFontStruct *font;
10838 int *w, *h;
10839 {
10840 /*
10841 * TODO: Windows does not appear to offer min bound, only
10842 * average and maximum width, and maximum height.
10843 */
10844 *h = FONT_HEIGHT (font);
10845 *w = FONT_WIDTH (font);
10846 }
10847
10848
10849 /* Compute the smallest character width and smallest font height over
10850 all fonts available on frame F. Set the members smallest_char_width
10851 and smallest_font_height in F's x_display_info structure to
10852 the values computed. Value is non-zero if smallest_font_height or
10853 smallest_char_width become smaller than they were before. */
10854
10855 int
10856 x_compute_min_glyph_bounds (f)
10857 struct frame *f;
10858 {
10859 int i;
10860 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10861 MacFontStruct *font;
10862 int old_width = dpyinfo->smallest_char_width;
10863 int old_height = dpyinfo->smallest_font_height;
10864
10865 dpyinfo->smallest_font_height = 100000;
10866 dpyinfo->smallest_char_width = 100000;
10867
10868 for (i = 0; i < dpyinfo->n_fonts; ++i)
10869 if (dpyinfo->font_table[i].name)
10870 {
10871 struct font_info *fontp = dpyinfo->font_table + i;
10872 int w, h;
10873
10874 font = (MacFontStruct *) fontp->font;
10875 xassert (font != (MacFontStruct *) ~0);
10876 x_font_min_bounds (font, &w, &h);
10877
10878 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10879 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10880 }
10881
10882 xassert (dpyinfo->smallest_char_width > 0
10883 && dpyinfo->smallest_font_height > 0);
10884
10885 return (dpyinfo->n_fonts == 1
10886 || dpyinfo->smallest_char_width < old_width
10887 || dpyinfo->smallest_font_height < old_height);
10888 }
10889
10890
10891 /* Determine whether given string is a fully-specified XLFD: all 14
10892 fields are present, none is '*'. */
10893
10894 static int
10895 is_fully_specified_xlfd (char *p)
10896 {
10897 int i;
10898 char *q;
10899
10900 if (*p != '-')
10901 return 0;
10902
10903 for (i = 0; i < 13; i++)
10904 {
10905 q = strchr (p + 1, '-');
10906 if (q == NULL)
10907 return 0;
10908 if (q - p == 2 && *(p + 1) == '*')
10909 return 0;
10910 p = q;
10911 }
10912
10913 if (strchr (p + 1, '-') != NULL)
10914 return 0;
10915
10916 if (*(p + 1) == '*' && *(p + 2) == '\0')
10917 return 0;
10918
10919 return 1;
10920 }
10921
10922
10923 const int kDefaultFontSize = 9;
10924
10925
10926 /* XLoadQueryFont creates and returns an internal representation for a
10927 font in a MacFontStruct struct. There is really no concept
10928 corresponding to "loading" a font on the Mac. But we check its
10929 existence and find the font number and all other information for it
10930 and store them in the returned MacFontStruct. */
10931
10932 static MacFontStruct *
10933 XLoadQueryFont (Display *dpy, char *fontname)
10934 {
10935 int i, size, is_two_byte_font, char_width;
10936 char *name;
10937 GrafPtr port;
10938 SInt16 old_fontnum, old_fontsize;
10939 Style old_fontface;
10940 Str32 mfontname;
10941 SInt16 fontnum;
10942 Style fontface = normal;
10943 MacFontStruct *font;
10944 FontInfo the_fontinfo;
10945 char s_weight[7], c_slant;
10946
10947 if (is_fully_specified_xlfd (fontname))
10948 name = fontname;
10949 else
10950 {
10951 for (i = 0; i < font_name_count; i++)
10952 if (mac_font_pattern_match (font_name_table[i], fontname))
10953 break;
10954
10955 if (i >= font_name_count)
10956 return NULL;
10957
10958 name = font_name_table[i];
10959 }
10960
10961 GetPort (&port); /* save the current font number used */
10962 #if TARGET_API_MAC_CARBON
10963 old_fontnum = GetPortTextFont (port);
10964 old_fontsize = GetPortTextSize (port);
10965 old_fontface = GetPortTextFace (port);
10966 #else
10967 old_fontnum = port->txFont;
10968 old_fontsize = port->txSize;
10969 old_fontface = port->txFace;
10970 #endif
10971
10972 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
10973 size = kDefaultFontSize;
10974
10975 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
10976 if (strcmp (s_weight, "bold") == 0)
10977 fontface |= bold;
10978
10979 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
10980 if (c_slant == 'i')
10981 fontface |= italic;
10982
10983 x_font_name_to_mac_font_name (name, mfontname);
10984 c2pstr (mfontname);
10985 GetFNum (mfontname, &fontnum);
10986 if (fontnum == 0)
10987 return NULL;
10988
10989 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
10990
10991 font->fontname = (char *) xmalloc (strlen (name) + 1);
10992 bcopy (name, font->fontname, strlen (name) + 1);
10993
10994 font->mac_fontnum = fontnum;
10995 font->mac_fontsize = size;
10996 font->mac_fontface = fontface;
10997 font->mac_scriptcode = FontToScript (fontnum);
10998
10999 /* Apple Japanese (SJIS) font is listed as both
11000 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
11001 (Roman script) in init_font_name_table (). The latter should be
11002 treated as a one-byte font. */
11003 {
11004 char cs[32];
11005
11006 if (sscanf (name,
11007 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11008 cs) == 1
11009 && 0 == strcmp (cs, "jisx0201.1976-0"))
11010 font->mac_scriptcode = smRoman;
11011 }
11012
11013 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11014 font->mac_scriptcode == smTradChinese ||
11015 font->mac_scriptcode == smSimpChinese ||
11016 font->mac_scriptcode == smKorean;
11017
11018 TextFont (fontnum);
11019 TextSize (size);
11020 TextFace (fontface);
11021
11022 GetFontInfo (&the_fontinfo);
11023
11024 font->ascent = the_fontinfo.ascent;
11025 font->descent = the_fontinfo.descent;
11026
11027 font->min_byte1 = 0;
11028 if (is_two_byte_font)
11029 font->max_byte1 = 1;
11030 else
11031 font->max_byte1 = 0;
11032 font->min_char_or_byte2 = 0x20;
11033 font->max_char_or_byte2 = 0xff;
11034
11035 if (is_two_byte_font)
11036 {
11037 /* Use the width of an "ideographic space" of that font because
11038 the_fontinfo.widMax returns the wrong width for some fonts. */
11039 switch (font->mac_scriptcode)
11040 {
11041 case smJapanese:
11042 char_width = StringWidth("\p\x81\x40");
11043 break;
11044 case smTradChinese:
11045 char_width = StringWidth("\p\xa1\x40");
11046 break;
11047 case smSimpChinese:
11048 char_width = StringWidth("\p\xa1\xa1");
11049 break;
11050 case smKorean:
11051 char_width = StringWidth("\p\xa1\xa1");
11052 break;
11053 }
11054 }
11055 else
11056 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11057 returns 15 for 12-point Monaco! */
11058 char_width = CharWidth ('m');
11059
11060 font->max_bounds.rbearing = char_width;
11061 font->max_bounds.lbearing = 0;
11062 font->max_bounds.width = char_width;
11063 font->max_bounds.ascent = the_fontinfo.ascent;
11064 font->max_bounds.descent = the_fontinfo.descent;
11065
11066 font->min_bounds = font->max_bounds;
11067
11068 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11069 font->per_char = NULL;
11070 else
11071 {
11072 font->per_char = (XCharStruct *)
11073 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11074 {
11075 int c;
11076
11077 for (c = 0x20; c <= 0xff; c++)
11078 {
11079 font->per_char[c - 0x20] = font->max_bounds;
11080 font->per_char[c - 0x20].width = CharWidth (c);
11081 }
11082 }
11083 }
11084
11085 TextFont (old_fontnum); /* restore previous font number, size and face */
11086 TextSize (old_fontsize);
11087 TextFace (old_fontface);
11088
11089 return font;
11090 }
11091
11092
11093 /* Load font named FONTNAME of the size SIZE for frame F, and return a
11094 pointer to the structure font_info while allocating it dynamically.
11095 If SIZE is 0, load any size of font.
11096 If loading is failed, return NULL. */
11097
11098 struct font_info *
11099 x_load_font (f, fontname, size)
11100 struct frame *f;
11101 register char *fontname;
11102 int size;
11103 {
11104 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11105 Lisp_Object font_names;
11106
11107 /* Get a list of all the fonts that match this name. Once we
11108 have a list of matching fonts, we compare them against the fonts
11109 we already have by comparing names. */
11110 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11111
11112 if (!NILP (font_names))
11113 {
11114 Lisp_Object tail;
11115 int i;
11116
11117 for (i = 0; i < dpyinfo->n_fonts; i++)
11118 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11119 if (dpyinfo->font_table[i].name
11120 && (!strcmp (dpyinfo->font_table[i].name,
11121 SDATA (XCAR (tail)))
11122 || !strcmp (dpyinfo->font_table[i].full_name,
11123 SDATA (XCAR (tail)))))
11124 return (dpyinfo->font_table + i);
11125 }
11126
11127 /* Load the font and add it to the table. */
11128 {
11129 char *full_name;
11130 struct MacFontStruct *font;
11131 struct font_info *fontp;
11132 unsigned long value;
11133 int i;
11134
11135 /* If we have found fonts by x_list_font, load one of them. If
11136 not, we still try to load a font by the name given as FONTNAME
11137 because XListFonts (called in x_list_font) of some X server has
11138 a bug of not finding a font even if the font surely exists and
11139 is loadable by XLoadQueryFont. */
11140 if (size > 0 && !NILP (font_names))
11141 fontname = (char *) SDATA (XCAR (font_names));
11142
11143 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11144 if (!font)
11145 return NULL;
11146
11147 /* Find a free slot in the font table. */
11148 for (i = 0; i < dpyinfo->n_fonts; ++i)
11149 if (dpyinfo->font_table[i].name == NULL)
11150 break;
11151
11152 /* If no free slot found, maybe enlarge the font table. */
11153 if (i == dpyinfo->n_fonts
11154 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11155 {
11156 int sz;
11157 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11158 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11159 dpyinfo->font_table
11160 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11161 }
11162
11163 fontp = dpyinfo->font_table + i;
11164 if (i == dpyinfo->n_fonts)
11165 ++dpyinfo->n_fonts;
11166
11167 /* Now fill in the slots of *FONTP. */
11168 BLOCK_INPUT;
11169 fontp->font = font;
11170 fontp->font_idx = i;
11171 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11172 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11173
11174 fontp->full_name = fontp->name;
11175
11176 fontp->size = font->max_bounds.width;
11177 fontp->height = FONT_HEIGHT (font);
11178 {
11179 /* For some font, ascent and descent in max_bounds field is
11180 larger than the above value. */
11181 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11182 if (max_height > fontp->height)
11183 fontp->height = max_height;
11184 }
11185
11186 /* The slot `encoding' specifies how to map a character
11187 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11188 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11189 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11190 2:0xA020..0xFF7F). For the moment, we don't know which charset
11191 uses this font. So, we set information in fontp->encoding[1]
11192 which is never used by any charset. If mapping can't be
11193 decided, set FONT_ENCODING_NOT_DECIDED. */
11194 if (font->mac_scriptcode == smJapanese)
11195 fontp->encoding[1] = 4;
11196 else
11197 {
11198 fontp->encoding[1]
11199 = (font->max_byte1 == 0
11200 /* 1-byte font */
11201 ? (font->min_char_or_byte2 < 0x80
11202 ? (font->max_char_or_byte2 < 0x80
11203 ? 0 /* 0x20..0x7F */
11204 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11205 : 1) /* 0xA0..0xFF */
11206 /* 2-byte font */
11207 : (font->min_byte1 < 0x80
11208 ? (font->max_byte1 < 0x80
11209 ? (font->min_char_or_byte2 < 0x80
11210 ? (font->max_char_or_byte2 < 0x80
11211 ? 0 /* 0x2020..0x7F7F */
11212 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11213 : 3) /* 0x20A0..0x7FFF */
11214 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11215 : (font->min_char_or_byte2 < 0x80
11216 ? (font->max_char_or_byte2 < 0x80
11217 ? 2 /* 0xA020..0xFF7F */
11218 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11219 : 1))); /* 0xA0A0..0xFFFF */
11220 }
11221
11222 #if 0 /* MAC_TODO: fill these out with more reasonably values */
11223 fontp->baseline_offset
11224 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11225 ? (long) value : 0);
11226 fontp->relative_compose
11227 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11228 ? (long) value : 0);
11229 fontp->default_ascent
11230 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11231 ? (long) value : 0);
11232 #else
11233 fontp->baseline_offset = 0;
11234 fontp->relative_compose = 0;
11235 fontp->default_ascent = 0;
11236 #endif
11237
11238 /* Set global flag fonts_changed_p to non-zero if the font loaded
11239 has a character with a smaller width than any other character
11240 before, or if the font loaded has a smalle>r height than any
11241 other font loaded before. If this happens, it will make a
11242 glyph matrix reallocation necessary. */
11243 fonts_changed_p = x_compute_min_glyph_bounds (f);
11244 UNBLOCK_INPUT;
11245 return fontp;
11246 }
11247 }
11248
11249
11250 /* Return a pointer to struct font_info of a font named FONTNAME for
11251 frame F. If no such font is loaded, return NULL. */
11252
11253 struct font_info *
11254 x_query_font (f, fontname)
11255 struct frame *f;
11256 register char *fontname;
11257 {
11258 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11259 int i;
11260
11261 for (i = 0; i < dpyinfo->n_fonts; i++)
11262 if (dpyinfo->font_table[i].name
11263 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11264 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11265 return (dpyinfo->font_table + i);
11266 return NULL;
11267 }
11268
11269
11270 /* Find a CCL program for a font specified by FONTP, and set the member
11271 `encoder' of the structure. */
11272
11273 void
11274 x_find_ccl_program (fontp)
11275 struct font_info *fontp;
11276 {
11277 Lisp_Object list, elt;
11278
11279 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11280 {
11281 elt = XCAR (list);
11282 if (CONSP (elt)
11283 && STRINGP (XCAR (elt))
11284 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11285 >= 0))
11286 break;
11287 }
11288 if (! NILP (list))
11289 {
11290 struct ccl_program *ccl
11291 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11292
11293 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11294 xfree (ccl);
11295 else
11296 fontp->font_encoder = ccl;
11297 }
11298 }
11299
11300
11301 \f
11302 /***********************************************************************
11303 Initialization
11304 ***********************************************************************/
11305
11306 #ifdef USE_X_TOOLKIT
11307 static XrmOptionDescRec emacs_options[] = {
11308 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11309 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11310
11311 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11312 XrmoptionSepArg, NULL},
11313 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11314
11315 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11316 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11317 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11318 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11319 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11320 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11321 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11322 };
11323 #endif /* USE_X_TOOLKIT */
11324
11325 static int x_initialized;
11326
11327 #ifdef MULTI_KBOARD
11328 /* Test whether two display-name strings agree up to the dot that separates
11329 the screen number from the server number. */
11330 static int
11331 same_x_server (name1, name2)
11332 char *name1, *name2;
11333 {
11334 int seen_colon = 0;
11335 unsigned char *system_name = SDATA (Vsystem_name);
11336 int system_name_length = strlen (system_name);
11337 int length_until_period = 0;
11338
11339 while (system_name[length_until_period] != 0
11340 && system_name[length_until_period] != '.')
11341 length_until_period++;
11342
11343 /* Treat `unix' like an empty host name. */
11344 if (! strncmp (name1, "unix:", 5))
11345 name1 += 4;
11346 if (! strncmp (name2, "unix:", 5))
11347 name2 += 4;
11348 /* Treat this host's name like an empty host name. */
11349 if (! strncmp (name1, system_name, system_name_length)
11350 && name1[system_name_length] == ':')
11351 name1 += system_name_length;
11352 if (! strncmp (name2, system_name, system_name_length)
11353 && name2[system_name_length] == ':')
11354 name2 += system_name_length;
11355 /* Treat this host's domainless name like an empty host name. */
11356 if (! strncmp (name1, system_name, length_until_period)
11357 && name1[length_until_period] == ':')
11358 name1 += length_until_period;
11359 if (! strncmp (name2, system_name, length_until_period)
11360 && name2[length_until_period] == ':')
11361 name2 += length_until_period;
11362
11363 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11364 {
11365 if (*name1 == ':')
11366 seen_colon++;
11367 if (seen_colon && *name1 == '.')
11368 return 1;
11369 }
11370 return (seen_colon
11371 && (*name1 == '.' || *name1 == '\0')
11372 && (*name2 == '.' || *name2 == '\0'));
11373 }
11374 #endif
11375
11376
11377 /* The Mac Event loop code */
11378
11379 #ifndef MAC_OSX
11380 #include <Events.h>
11381 #include <Quickdraw.h>
11382 #include <Balloons.h>
11383 #include <Devices.h>
11384 #include <Fonts.h>
11385 #include <Gestalt.h>
11386 #include <Menus.h>
11387 #include <Processes.h>
11388 #include <Sound.h>
11389 #include <ToolUtils.h>
11390 #include <TextUtils.h>
11391 #include <Dialogs.h>
11392 #include <Script.h>
11393 #include <Types.h>
11394 #include <TextEncodingConverter.h>
11395 #include <Resources.h>
11396
11397 #if __MWERKS__
11398 #include <unix.h>
11399 #endif
11400 #endif /* ! MAC_OSX */
11401
11402 #define M_APPLE 128
11403 #define I_ABOUT 1
11404
11405 #define WINDOW_RESOURCE 128
11406 #define TERM_WINDOW_RESOURCE 129
11407
11408 #define DEFAULT_NUM_COLS 80
11409
11410 #define MIN_DOC_SIZE 64
11411 #define MAX_DOC_SIZE 32767
11412
11413 /* sleep time for WaitNextEvent */
11414 #define WNE_SLEEP_AT_SUSPEND 10
11415 #define WNE_SLEEP_AT_RESUME 1
11416
11417 /* true when cannot handle any Mac OS events */
11418 static int handling_window_update = 0;
11419
11420 /* the flag appl_is_suspended is used both for determining the sleep
11421 time to be passed to WaitNextEvent and whether the cursor should be
11422 drawn when updating the display. The cursor is turned off when
11423 Emacs is suspended. Redrawing it is unnecessary and what needs to
11424 be done depends on whether the cursor lies inside or outside the
11425 redraw region. So we might as well skip drawing it when Emacs is
11426 suspended. */
11427 static Boolean app_is_suspended = false;
11428 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11429
11430 #define EXTRA_STACK_ALLOC (256 * 1024)
11431
11432 #define ARGV_STRING_LIST_ID 129
11433 #define ABOUT_ALERT_ID 128
11434 #define RAM_TOO_LARGE_ALERT_ID 129
11435
11436 Boolean terminate_flag = false;
11437
11438 /* True if using command key as meta key. */
11439 Lisp_Object Vmac_command_key_is_meta;
11440
11441 /* True if the ctrl and meta keys should be reversed. */
11442 Lisp_Object Vmac_reverse_ctrl_meta;
11443
11444 #if USE_CARBON_EVENTS
11445 /* True if the mouse wheel button (i.e. button 4) should map to
11446 mouse-2, instead of mouse-3. */
11447 Lisp_Object Vmac_wheel_button_is_mouse_2;
11448
11449 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
11450 for processing before Emacs sees it. */
11451 Lisp_Object Vmac_pass_command_to_system;
11452
11453 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
11454 for processing before Emacs sees it. */
11455 Lisp_Object Vmac_pass_control_to_system;
11456 #endif
11457
11458 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11459 to this text encoding */
11460 int mac_keyboard_text_encoding;
11461 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11462
11463 /* Set in term/mac-win.el to indicate that event loop can now generate
11464 drag and drop events. */
11465 Lisp_Object Qmac_ready_for_drag_n_drop;
11466
11467 Lisp_Object drag_and_drop_file_list;
11468
11469 Point saved_menu_event_location;
11470
11471 /* Apple Events */
11472 static void init_required_apple_events (void);
11473 static pascal OSErr
11474 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
11475 static pascal OSErr
11476 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
11477 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
11478 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
11479
11480 /* Drag and Drop */
11481 static OSErr init_mac_drag_n_drop ();
11482 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
11483
11484 #if USE_CARBON_EVENTS
11485 /* Preliminary Support for the OSX Services Menu */
11486 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
11487 static void init_service_handler ();
11488 #endif
11489
11490 extern void init_emacs_passwd_dir ();
11491 extern int emacs_main (int, char **, char **);
11492 extern void check_alarm ();
11493
11494 extern void initialize_applescript();
11495 extern void terminate_applescript();
11496
11497 static unsigned int
11498 #if USE_CARBON_EVENTS
11499 mac_to_emacs_modifiers (UInt32 mods)
11500 #else
11501 mac_to_emacs_modifiers (EventModifiers mods)
11502 #endif
11503 {
11504 unsigned int result = 0;
11505 if (mods & macShiftKey)
11506 result |= shift_modifier;
11507 if (mods & macCtrlKey)
11508 result |= ctrl_modifier;
11509 if (mods & macMetaKey)
11510 result |= meta_modifier;
11511 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
11512 result |= alt_modifier;
11513 return result;
11514 }
11515
11516 #if USE_CARBON_EVENTS
11517 /* Obtains the event modifiers from the event ref and then calls
11518 mac_to_emacs_modifiers. */
11519 static int
11520 mac_event_to_emacs_modifiers (EventRef eventRef)
11521 {
11522 UInt32 mods = 0;
11523 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
11524 sizeof (UInt32), NULL, &mods);
11525 return mac_to_emacs_modifiers (mods);
11526 }
11527
11528 /* Given an event ref, return the code to use for the mouse button
11529 code in the emacs input_event. */
11530 static int
11531 mac_get_mouse_btn (EventRef ref)
11532 {
11533 EventMouseButton result = kEventMouseButtonPrimary;
11534 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
11535 sizeof (EventMouseButton), NULL, &result);
11536 switch (result)
11537 {
11538 case kEventMouseButtonPrimary:
11539 return 0;
11540 case kEventMouseButtonSecondary:
11541 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
11542 case kEventMouseButtonTertiary:
11543 case 4: /* 4 is the number for the mouse wheel button */
11544 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
11545 default:
11546 return 0;
11547 }
11548 }
11549
11550 /* Normally, ConvertEventRefToEventRecord will correctly handle all
11551 events. However the click of the mouse wheel is not converted to a
11552 mouseDown or mouseUp event. This calls ConvertEventRef, but then
11553 checks to see if it is a mouse up or down carbon event that has not
11554 been converted, and if so, converts it by hand (to be picked up in
11555 the XTread_socket loop). */
11556 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
11557 {
11558 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
11559 /* Do special case for mouse wheel button. */
11560 if (!result && GetEventClass (eventRef) == kEventClassMouse)
11561 {
11562 UInt32 kind = GetEventKind (eventRef);
11563 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
11564 {
11565 eventRec->what = mouseDown;
11566 result=1;
11567 }
11568 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
11569 {
11570 eventRec->what = mouseUp;
11571 result=1;
11572 }
11573 if (result)
11574 {
11575 /* Need where and when. */
11576 UInt32 mods;
11577 GetEventParameter (eventRef, kEventParamMouseLocation,
11578 typeQDPoint, NULL, sizeof (Point),
11579 NULL, &eventRec->where);
11580 /* Use two step process because new event modifiers are
11581 32-bit and old are 16-bit. Currently, only loss is
11582 NumLock & Fn. */
11583 GetEventParameter (eventRef, kEventParamKeyModifiers,
11584 typeUInt32, NULL, sizeof (UInt32),
11585 NULL, &mods);
11586 eventRec->modifiers = mods;
11587
11588 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
11589 }
11590 }
11591 return result;
11592 }
11593
11594 #endif
11595
11596 static void
11597 do_get_menus (void)
11598 {
11599 Handle menubar_handle;
11600 MenuHandle menu_handle;
11601
11602 menubar_handle = GetNewMBar (128);
11603 if(menubar_handle == NULL)
11604 abort ();
11605 SetMenuBar (menubar_handle);
11606 DrawMenuBar ();
11607
11608 menu_handle = GetMenuHandle (M_APPLE);
11609 if(menu_handle != NULL)
11610 AppendResMenu (menu_handle,'DRVR');
11611 else
11612 abort ();
11613 }
11614
11615
11616 static void
11617 do_init_managers (void)
11618 {
11619 #if !TARGET_API_MAC_CARBON
11620 InitGraf (&qd.thePort);
11621 InitFonts ();
11622 FlushEvents (everyEvent, 0);
11623 InitWindows ();
11624 InitMenus ();
11625 TEInit ();
11626 InitDialogs (NULL);
11627 #endif /* !TARGET_API_MAC_CARBON */
11628 InitCursor ();
11629
11630 #if !TARGET_API_MAC_CARBON
11631 /* set up some extra stack space for use by emacs */
11632 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11633
11634 /* MaxApplZone must be called for AppleScript to execute more
11635 complicated scripts */
11636 MaxApplZone ();
11637 MoreMasters ();
11638 #endif /* !TARGET_API_MAC_CARBON */
11639 }
11640
11641 static void
11642 do_check_ram_size (void)
11643 {
11644 SInt32 physical_ram_size, logical_ram_size;
11645
11646 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11647 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11648 || physical_ram_size > 256 * 1024 * 1024
11649 || logical_ram_size > 256 * 1024 * 1024)
11650 {
11651 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11652 exit (1);
11653 }
11654 }
11655
11656 static void
11657 do_window_update (WindowPtr win)
11658 {
11659 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11660 struct frame *f = mwp->mFP;
11661
11662 if (f)
11663 {
11664 if (f->async_visible == 0)
11665 {
11666 f->async_visible = 1;
11667 f->async_iconified = 0;
11668 SET_FRAME_GARBAGED (f);
11669
11670 /* An update event is equivalent to MapNotify on X, so report
11671 visibility changes properly. */
11672 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11673 /* Force a redisplay sooner or later to update the
11674 frame titles in case this is the second frame. */
11675 record_asynch_buffer_change ();
11676 }
11677 else
11678 {
11679 BeginUpdate (win);
11680 handling_window_update = 1;
11681
11682 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
11683
11684 expose_frame (f, 0, 0, 0, 0);
11685
11686 handling_window_update = 0;
11687 EndUpdate (win);
11688 }
11689 }
11690 }
11691
11692 static int
11693 is_emacs_window (WindowPtr win)
11694 {
11695 Lisp_Object tail, frame;
11696
11697 if (!win)
11698 return 0;
11699
11700 FOR_EACH_FRAME (tail, frame)
11701 if (FRAME_MAC_P (XFRAME (frame)))
11702 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11703 return 1;
11704
11705 return 0;
11706 }
11707
11708 static void
11709 do_window_activate (WindowPtr win)
11710 {
11711 mac_output *mwp;
11712 struct frame *f;
11713
11714 if (is_emacs_window (win))
11715 {
11716 mwp = (mac_output *) GetWRefCon (win);
11717 f = mwp->mFP;
11718
11719 if (f)
11720 {
11721 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11722 activate_scroll_bars (f);
11723 }
11724 }
11725 }
11726
11727 static void
11728 do_window_deactivate (WindowPtr win)
11729 {
11730 mac_output *mwp;
11731 struct frame *f;
11732
11733 if (is_emacs_window (win))
11734 {
11735 mwp = (mac_output *) GetWRefCon (win);
11736 f = mwp->mFP;
11737
11738 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11739 {
11740 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11741 deactivate_scroll_bars (f);
11742 }
11743 }
11744 }
11745
11746 static void
11747 do_app_resume ()
11748 {
11749 WindowPtr wp;
11750 mac_output *mwp;
11751 struct frame *f;
11752
11753 wp = FrontWindow();
11754 if (is_emacs_window (wp))
11755 {
11756 mwp = (mac_output *) GetWRefCon (wp);
11757 f = mwp->mFP;
11758
11759 if (f)
11760 {
11761 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11762 activate_scroll_bars (f);
11763 }
11764 }
11765
11766 app_is_suspended = false;
11767 app_sleep_time = WNE_SLEEP_AT_RESUME;
11768 }
11769
11770 static void
11771 do_app_suspend ()
11772 {
11773 WindowPtr wp;
11774 mac_output *mwp;
11775 struct frame *f;
11776
11777 wp = FrontWindow();
11778 if (is_emacs_window (wp))
11779 {
11780 mwp = (mac_output *) GetWRefCon (wp);
11781 f = mwp->mFP;
11782
11783 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11784 {
11785 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11786 deactivate_scroll_bars (f);
11787 }
11788 }
11789
11790 app_is_suspended = true;
11791 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11792 }
11793
11794
11795 static void
11796 do_mouse_moved (Point mouse_pos)
11797 {
11798 WindowPtr wp = FrontWindow ();
11799 struct frame *f;
11800
11801 if (is_emacs_window (wp))
11802 {
11803 f = ((mac_output *) GetWRefCon (wp))->mFP;
11804
11805 #if TARGET_API_MAC_CARBON
11806 SetPort (GetWindowPort (wp));
11807 #else
11808 SetPort (wp);
11809 #endif
11810
11811 GlobalToLocal (&mouse_pos);
11812
11813 note_mouse_movement (f, &mouse_pos);
11814 }
11815 }
11816
11817
11818 static void
11819 do_os_event (EventRecord *erp)
11820 {
11821 switch((erp->message >> 24) & 0x000000FF)
11822 {
11823 case suspendResumeMessage:
11824 if((erp->message & resumeFlag) == 1)
11825 do_app_resume ();
11826 else
11827 do_app_suspend ();
11828 break;
11829
11830 case mouseMovedMessage:
11831 do_mouse_moved (erp->where);
11832 break;
11833 }
11834 }
11835
11836 static void
11837 do_events (EventRecord *erp)
11838 {
11839 switch (erp->what)
11840 {
11841 case updateEvt:
11842 do_window_update ((WindowPtr) erp->message);
11843 break;
11844
11845 case osEvt:
11846 do_os_event (erp);
11847 break;
11848
11849 case activateEvt:
11850 if ((erp->modifiers & activeFlag) != 0)
11851 do_window_activate ((WindowPtr) erp->message);
11852 else
11853 do_window_deactivate ((WindowPtr) erp->message);
11854 break;
11855 }
11856 }
11857
11858 static void
11859 do_apple_menu (SInt16 menu_item)
11860 {
11861 #if !TARGET_API_MAC_CARBON
11862 Str255 item_name;
11863 SInt16 da_driver_refnum;
11864
11865 if (menu_item == I_ABOUT)
11866 NoteAlert (ABOUT_ALERT_ID, NULL);
11867 else
11868 {
11869 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11870 da_driver_refnum = OpenDeskAcc (item_name);
11871 }
11872 #endif /* !TARGET_API_MAC_CARBON */
11873 }
11874
11875 void
11876 do_menu_choice (SInt32 menu_choice)
11877 {
11878 SInt16 menu_id, menu_item;
11879
11880 menu_id = HiWord (menu_choice);
11881 menu_item = LoWord (menu_choice);
11882
11883 if (menu_id == 0)
11884 return;
11885
11886 switch (menu_id)
11887 {
11888 case M_APPLE:
11889 do_apple_menu (menu_item);
11890 break;
11891
11892 default:
11893 {
11894 WindowPtr wp = FrontWindow ();
11895 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11896 MenuHandle menu = GetMenuHandle (menu_id);
11897 if (menu)
11898 {
11899 UInt32 refcon;
11900
11901 GetMenuItemRefCon (menu, menu_item, &refcon);
11902 menubar_selection_callback (f, refcon);
11903 }
11904 }
11905 }
11906
11907 HiliteMenu (0);
11908 }
11909
11910
11911 /* Handle drags in size box. Based on code contributed by Ben
11912 Mesander and IM - Window Manager A. */
11913
11914 static void
11915 do_grow_window (WindowPtr w, EventRecord *e)
11916 {
11917 long grow_size;
11918 Rect limit_rect;
11919 int rows, columns;
11920 mac_output *mwp = (mac_output *) GetWRefCon (w);
11921 struct frame *f = mwp->mFP;
11922
11923 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11924
11925 grow_size = GrowWindow (w, e->where, &limit_rect);
11926
11927 /* see if it really changed size */
11928 if (grow_size != 0)
11929 {
11930 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11931 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11932
11933 x_set_window_size (f, 0, columns, rows);
11934 }
11935 }
11936
11937
11938 /* Handle clicks in zoom box. Calculation of "standard state" based
11939 on code in IM - Window Manager A and code contributed by Ben
11940 Mesander. The standard state of an Emacs window is 80-characters
11941 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11942
11943 static void
11944 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11945 {
11946 GrafPtr save_port;
11947 Rect zoom_rect, port_rect;
11948 Point top_left;
11949 int w_title_height, columns, rows, width, height, dummy, x, y;
11950 mac_output *mwp = (mac_output *) GetWRefCon (w);
11951 struct frame *f = mwp->mFP;
11952
11953 GetPort (&save_port);
11954
11955 #if TARGET_API_MAC_CARBON
11956 SetPort (GetWindowPort (w));
11957 #else
11958 SetPort (w);
11959 #endif
11960
11961 /* Clear window to avoid flicker. */
11962 #if TARGET_API_MAC_CARBON
11963 {
11964 Rect r;
11965 BitMap bm;
11966
11967 GetWindowPortBounds (w, &r);
11968 EraseRect (&r);
11969
11970 if (zoom_in_or_out == inZoomOut)
11971 {
11972 /* calculate height of window's title bar (hard card it for now). */
11973 w_title_height = 20 + GetMBarHeight ();
11974
11975 /* get maximum height of window into zoom_rect.bottom -
11976 zoom_rect.top */
11977 GetQDGlobalsScreenBits (&bm);
11978 zoom_rect = bm.bounds;
11979 zoom_rect.top += w_title_height;
11980 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11981
11982 zoom_rect.right = zoom_rect.left
11983 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11984
11985 SetWindowStandardState (w, &zoom_rect);
11986 }
11987 }
11988 #else /* not TARGET_API_MAC_CARBON */
11989 EraseRect (&(w->portRect));
11990 if (zoom_in_or_out == inZoomOut)
11991 {
11992 SetPt (&top_left, w->portRect.left, w->portRect.top);
11993 LocalToGlobal (&top_left);
11994
11995 /* calculate height of window's title bar */
11996 w_title_height = top_left.v - 1
11997 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
11998
11999 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
12000 zoom_rect = qd.screenBits.bounds;
12001 zoom_rect.top += w_title_height;
12002 InsetRect (&zoom_rect, 8, 4); /* not too tight */
12003
12004 zoom_rect.right = zoom_rect.left
12005 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12006
12007 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
12008 = zoom_rect;
12009 }
12010 #endif /* not TARGET_API_MAC_CARBON */
12011
12012 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
12013
12014 /* retrieve window size and update application values */
12015 #if TARGET_API_MAC_CARBON
12016 GetWindowPortBounds (w, &port_rect);
12017 #else
12018 port_rect = w->portRect;
12019 #endif
12020 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
12021 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
12022 x_set_window_size (mwp->mFP, 0, columns, rows);
12023
12024 SetPort (save_port);
12025 }
12026
12027 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
12028 static OSErr
12029 init_mac_drag_n_drop ()
12030 {
12031 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
12032 return result;
12033 }
12034
12035 /* Intialize AppleEvent dispatcher table for the required events. */
12036 void
12037 init_required_apple_events ()
12038 {
12039 OSErr err;
12040 long result;
12041
12042 /* Make sure we have apple events before starting. */
12043 err = Gestalt (gestaltAppleEventsAttr, &result);
12044 if (err != noErr)
12045 abort ();
12046
12047 if (!(result & (1 << gestaltAppleEventsPresent)))
12048 abort ();
12049
12050 #if TARGET_API_MAC_CARBON
12051 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12052 NewAEEventHandlerUPP
12053 ((AEEventHandlerProcPtr) do_ae_open_application),
12054 0L, false);
12055 #else
12056 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12057 NewAEEventHandlerProc
12058 ((AEEventHandlerProcPtr) do_ae_open_application),
12059 0L, false);
12060 #endif
12061 if (err != noErr)
12062 abort ();
12063
12064 #if TARGET_API_MAC_CARBON
12065 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12066 NewAEEventHandlerUPP
12067 ((AEEventHandlerProcPtr) do_ae_open_documents),
12068 0L, false);
12069 #else
12070 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12071 NewAEEventHandlerProc
12072 ((AEEventHandlerProcPtr) do_ae_open_documents),
12073 0L, false);
12074 #endif
12075 if (err != noErr)
12076 abort ();
12077
12078 #if TARGET_API_MAC_CARBON
12079 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12080 NewAEEventHandlerUPP
12081 ((AEEventHandlerProcPtr) do_ae_print_documents),
12082 0L, false);
12083 #else
12084 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12085 NewAEEventHandlerProc
12086 ((AEEventHandlerProcPtr) do_ae_print_documents),
12087 0L, false);
12088 #endif
12089 if (err != noErr)
12090 abort ();
12091
12092 #if TARGET_API_MAC_CARBON
12093 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12094 NewAEEventHandlerUPP
12095 ((AEEventHandlerProcPtr) do_ae_quit_application),
12096 0L, false);
12097 #else
12098 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12099 NewAEEventHandlerProc
12100 ((AEEventHandlerProcPtr) do_ae_quit_application),
12101 0L, false);
12102 #endif
12103 if (err != noErr)
12104 abort ();
12105 }
12106
12107 #if USE_CARBON_EVENTS
12108
12109 void init_service_handler()
12110 {
12111 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
12112 {kEventClassService, kEventServiceCopy},
12113 {kEventClassService, kEventServicePaste}};
12114 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
12115 3, specs, NULL, NULL);
12116 }
12117
12118 /*
12119 MAC_TODO: Check to see if this is called by AEProcessDesc...
12120 */
12121 OSStatus mac_handle_service_event (EventHandlerCallRef callRef,
12122 EventRef event, void *data)
12123 {
12124 OSStatus err = noErr;
12125 switch (GetEventKind (event))
12126 {
12127 case kEventServiceGetTypes:
12128 {
12129 CFMutableArrayRef copyTypes, pasteTypes;
12130 CFStringRef type;
12131 Boolean selection = true;
12132 /*
12133 GetEventParameter(event, kEventParamServicePasteTypes,
12134 typeCFMutableArrayRef, NULL,
12135 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
12136 */
12137 GetEventParameter(event, kEventParamServiceCopyTypes,
12138 typeCFMutableArrayRef, NULL,
12139 sizeof (CFMutableArrayRef), NULL, &copyTypes);
12140 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
12141 if (type) {
12142 CFArrayAppendValue (copyTypes, type);
12143 //CFArrayAppendValue (pasteTypes, type);
12144 CFRelease (type);
12145 }
12146 }
12147 case kEventServiceCopy:
12148 {
12149 ScrapRef currentScrap, specificScrap;
12150 char * buf = "";
12151 Size byteCount = 0;
12152
12153 GetCurrentScrap (&currentScrap);
12154
12155 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
12156 if (err == noErr)
12157 {
12158 void *buffer = xmalloc (byteCount);
12159 if (buffer != NULL)
12160 {
12161 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
12162 sizeof (ScrapRef), NULL, &specificScrap);
12163
12164 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
12165 &byteCount, buffer);
12166 if (err == noErr)
12167 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
12168 kScrapFlavorMaskNone, byteCount, buffer);
12169 xfree (buffer);
12170 }
12171 }
12172 err = noErr;
12173 }
12174 case kEventServicePaste:
12175 {
12176 /*
12177 // Get the current location
12178 Size byteCount;
12179 ScrapRef specificScrap;
12180 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
12181 sizeof(ScrapRef), NULL, &specificScrap);
12182 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
12183 if (err == noErr) {
12184 void * buffer = xmalloc(byteCount);
12185 if (buffer != NULL ) {
12186 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
12187 &byteCount, buffer);
12188 if (err == noErr) {
12189 // Actually place in the buffer
12190 BLOCK_INPUT;
12191 // Get the current "selection" string here
12192 UNBLOCK_INPUT;
12193 }
12194 }
12195 xfree(buffer);
12196 }
12197 */
12198 }
12199 }
12200 return err;
12201 }
12202 #endif
12203
12204 /* Open Application Apple Event */
12205 static pascal OSErr
12206 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12207 {
12208 return noErr;
12209 }
12210
12211
12212 /* Defined in mac.c. */
12213 extern int
12214 path_from_vol_dir_name (char *, int, short, long, char *);
12215
12216
12217 /* Called when we receive an AppleEvent with an ID of
12218 "kAEOpenDocuments". This routine gets the direct parameter,
12219 extracts the FSSpecs in it, and puts their names on a list. */
12220 static pascal OSErr
12221 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12222 {
12223 OSErr err, err2;
12224 AEDesc the_desc;
12225 AEKeyword keyword;
12226 DescType actual_type;
12227 Size actual_size;
12228
12229 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12230 if (err != noErr)
12231 goto descriptor_error_exit;
12232
12233 /* Check to see that we got all of the required parameters from the
12234 event descriptor. For an 'odoc' event this should just be the
12235 file list. */
12236 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12237 &actual_type, (Ptr) &keyword,
12238 sizeof (keyword), &actual_size);
12239 /* No error means that we found some unused parameters.
12240 errAEDescNotFound means that there are no more parameters. If we
12241 get an error code other than that, flag it. */
12242 if ((err == noErr) || (err != errAEDescNotFound))
12243 {
12244 err = errAEEventNotHandled;
12245 goto error_exit;
12246 }
12247 err = noErr;
12248
12249 /* Got all the parameters we need. Now, go through the direct
12250 object list and parse it up. */
12251 {
12252 long num_files_to_open;
12253
12254 err = AECountItems (&the_desc, &num_files_to_open);
12255 if (err == noErr)
12256 {
12257 int i;
12258
12259 /* AE file list is one based so just use that for indexing here. */
12260 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
12261 {
12262 FSSpec fs;
12263 Str255 path_name, unix_path_name;
12264 #ifdef MAC_OSX
12265 FSRef fref;
12266 #endif
12267
12268 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12269 (Ptr) &fs, sizeof (fs), &actual_size);
12270 if (err != noErr) break;
12271
12272 #ifdef MAC_OSX
12273 err = FSpMakeFSRef (&fs, &fref);
12274 if (err != noErr) break;
12275
12276 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12277 #else
12278 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12279 fs.name) &&
12280 mac_to_posix_pathname (path_name, unix_path_name, 255))
12281 #endif
12282 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12283 drag_and_drop_file_list);
12284 }
12285 }
12286 }
12287
12288 error_exit:
12289 /* Nuke the coerced file list in any case */
12290 err2 = AEDisposeDesc(&the_desc);
12291
12292 descriptor_error_exit:
12293 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12294 return err;
12295 }
12296
12297
12298 static pascal OSErr mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
12299 DragReference theDrag)
12300 {
12301 short items;
12302 short index;
12303 FlavorFlags theFlags;
12304 Point mouse;
12305 OSErr result;
12306 ItemReference theItem;
12307 HFSFlavor data;
12308 FSRef fref;
12309 Size size = sizeof (HFSFlavor);
12310
12311 drag_and_drop_file_list = Qnil;
12312 GetDragMouse (theDrag, &mouse, 0L);
12313 CountDragItems (theDrag, &items);
12314 for (index = 1; index <= items; index++)
12315 {
12316 /* Only handle file references. */
12317 GetDragItemReferenceNumber (theDrag, index, &theItem);
12318 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
12319 if (result == noErr)
12320 {
12321 #ifdef MAC_OSX
12322 FSRef frref;
12323 #else
12324 Str255 path_name;
12325 #endif
12326 Str255 unix_path_name;
12327 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
12328 #ifdef MAC_OSX
12329 /* Use Carbon routines, otherwise it converts the file name
12330 to /Macintosh HD/..., which is not correct. */
12331 FSpMakeFSRef (&data.fileSpec, &fref);
12332 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
12333 #else
12334 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
12335 data.fileSpec.parID, data.fileSpec.name) &&
12336 mac_to_posix_pathname (path_name, unix_path_name, 255))
12337 #endif
12338 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12339 drag_and_drop_file_list);
12340 }
12341 else
12342 return;
12343 }
12344 /* If there are items in the list, construct an event and post it to
12345 the queue like an interrupt using kbd_buffer_store_event. */
12346 if (!NILP (drag_and_drop_file_list))
12347 {
12348 struct input_event event;
12349 Lisp_Object frame;
12350 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
12351 SetPort (GetWindowPort (window));
12352 GlobalToLocal (&mouse);
12353
12354 event.kind = DRAG_N_DROP_EVENT;
12355 event.code = 0;
12356 event.modifiers = 0;
12357 event.timestamp = TickCount () * (1000 / 60);
12358 XSETINT (event.x, mouse.h);
12359 XSETINT (event.y, mouse.v);
12360 XSETFRAME (frame, f);
12361 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
12362 event.arg = Qnil;
12363 /* Post to the interrupt queue */
12364 kbd_buffer_store_event (&event);
12365 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
12366 {
12367 ProcessSerialNumber psn;
12368 GetCurrentProcess (&psn);
12369 SetFrontProcess (&psn);
12370 }
12371 }
12372 }
12373
12374
12375 /* Print Document Apple Event */
12376 static pascal OSErr
12377 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12378 {
12379 return errAEEventNotHandled;
12380 }
12381
12382
12383 static pascal OSErr
12384 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12385 {
12386 /* FixMe: Do we need an unwind-protect or something here? And what
12387 do we do about unsaved files. Currently just forces quit rather
12388 than doing recursive callback to get user input. */
12389
12390 terminate_flag = true;
12391
12392 /* Fkill_emacs doesn't return. We have to return. (TI) */
12393 return noErr;
12394 }
12395
12396
12397 #if __profile__
12398 void
12399 profiler_exit_proc ()
12400 {
12401 ProfilerDump ("\pEmacs.prof");
12402 ProfilerTerm ();
12403 }
12404 #endif
12405
12406 /* These few functions implement Emacs as a normal Mac application
12407 (almost): set up the heap and the Toolbox, handle necessary
12408 system events plus a few simple menu events. They also set up
12409 Emacs's access to functions defined in the rest of this file.
12410 Emacs uses function hooks to perform all its terminal I/O. A
12411 complete list of these functions appear in termhooks.h. For what
12412 they do, read the comments there and see also w32term.c and
12413 xterm.c. What's noticeably missing here is the event loop, which
12414 is normally present in most Mac application. After performing the
12415 necessary Mac initializations, main passes off control to
12416 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12417 mac_read_socket (defined further below) to read input. This is
12418 where WaitNextEvent is called to process Mac events. This is also
12419 where check_alarm in sysdep.c is called to simulate alarm signals.
12420 This makes the cursor jump back to its correct position after
12421 briefly jumping to that of the matching parenthesis, print useful
12422 hints and prompts in the minibuffer after the user stops typing for
12423 a wait, etc. */
12424
12425 #if !TARGET_API_MAC_CARBON
12426 #undef main
12427 int
12428 main (void)
12429 {
12430 #if __profile__ /* is the profiler on? */
12431 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12432 exit(1);
12433 #endif
12434
12435 #if __MWERKS__
12436 /* set creator and type for files created by MSL */
12437 _fcreator = 'EMAx';
12438 _ftype = 'TEXT';
12439 #endif
12440
12441 do_init_managers ();
12442
12443 do_get_menus ();
12444
12445 do_check_ram_size ();
12446
12447 init_emacs_passwd_dir ();
12448
12449 init_environ ();
12450
12451 initialize_applescript ();
12452
12453 init_required_apple_events ();
12454
12455 {
12456 char **argv;
12457 int argc = 0;
12458
12459 /* set up argv array from STR# resource */
12460 get_string_list (&argv, ARGV_STRING_LIST_ID);
12461 while (argv[argc])
12462 argc++;
12463
12464 /* free up AppleScript resources on exit */
12465 atexit (terminate_applescript);
12466
12467 #if __profile__ /* is the profiler on? */
12468 atexit (profiler_exit_proc);
12469 #endif
12470
12471 /* 3rd param "envp" never used in emacs_main */
12472 (void) emacs_main (argc, argv, 0);
12473 }
12474
12475 /* Never reached - real exit in Fkill_emacs */
12476 return 0;
12477 }
12478 #endif
12479
12480 /* Table for translating Mac keycode to X keysym values. Contributed
12481 by Sudhir Shenoy. */
12482 static unsigned char keycode_to_xkeysym_table[] = {
12483 /* 0x00 - 0x3f */
12484 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12485 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12486 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12487 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12488 /* 0x40 */
12489 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12490 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12491 0, 0, 0, '\xaf' /* kp/ */,
12492 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
12493 /* 0x50 */
12494 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12495 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12496 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12497 '\xb9' /* kp9 */, 0, 0, 0,
12498 /* 0x60 */
12499 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12500 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12501 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12502 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
12503 /* 0x70 */
12504 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12505 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12506 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12507 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
12508 };
12509
12510 static int
12511 keycode_to_xkeysym (int keyCode, int *xKeySym)
12512 {
12513 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12514 return *xKeySym != 0;
12515 }
12516
12517 /* Emacs calls this whenever it wants to read an input event from the
12518 user. */
12519 int
12520 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12521 {
12522 int count = 0;
12523 #if USE_CARBON_EVENTS
12524 OSStatus rneResult;
12525 EventRef eventRef;
12526 EventMouseButton mouseBtn;
12527 #endif
12528 EventRecord er;
12529 int the_modifiers;
12530 EventMask event_mask;
12531
12532 #if 0
12533 if (interrupt_input_blocked)
12534 {
12535 interrupt_input_pending = 1;
12536 return -1;
12537 }
12538 #endif
12539
12540 interrupt_input_pending = 0;
12541 BLOCK_INPUT;
12542
12543 /* So people can tell when we have read the available input. */
12544 input_signal_count++;
12545
12546 if (numchars <= 0)
12547 abort ();
12548
12549 /* Don't poll for events to process (specifically updateEvt) if
12550 window update currently already in progress. A call to redisplay
12551 (in do_window_update) can be preempted by another call to
12552 redisplay, causing blank regions to be left on the screen and the
12553 cursor to be left at strange places. */
12554 if (handling_window_update)
12555 {
12556 UNBLOCK_INPUT;
12557 return 0;
12558 }
12559
12560 if (terminate_flag)
12561 Fkill_emacs (make_number (1));
12562
12563 /* It is necessary to set this (additional) argument slot of an
12564 event to nil because keyboard.c protects incompletely processed
12565 event from being garbage collected by placing them in the
12566 kbd_buffer_gcpro vector. */
12567 bufp->arg = Qnil;
12568
12569 event_mask = everyEvent;
12570 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
12571 event_mask -= highLevelEventMask;
12572
12573 #if USE_CARBON_EVENTS
12574 rneResult = ReceiveNextEvent (0, NULL,
12575 expected
12576 ? TicksToEventTime (app_sleep_time)
12577 : 0,
12578 true, &eventRef);
12579 if (!rneResult)
12580 {
12581 /* Handle new events */
12582 if (!mac_convert_event_ref (eventRef, &er))
12583 switch (GetEventClass (eventRef))
12584 {
12585 case kEventClassMouse:
12586 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
12587 {
12588 SInt32 delta;
12589 Point point;
12590 WindowPtr window_ptr = FrontNonFloatingWindow ();
12591 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12592 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
12593 typeSInt32, NULL, sizeof (SInt32),
12594 NULL, &delta);
12595 GetEventParameter(eventRef, kEventParamMouseLocation,
12596 typeQDPoint, NULL, sizeof (Point),
12597 NULL, &point);
12598 bufp->kind = MOUSE_WHEEL_EVENT;
12599 bufp->code = delta;
12600 bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
12601 SetPort (GetWindowPort (window_ptr));
12602 GlobalToLocal (&point);
12603 XSETINT (bufp->x, point.h);
12604 XSETINT (bufp->y, point.v);
12605 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12606 bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
12607 count++;
12608 }
12609 else
12610 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12611
12612 break;
12613 default:
12614 /* Send the event to the appropriate receiver. */
12615 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12616 }
12617 else
12618 #else
12619 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
12620 #endif /* USE_CARBON_EVENTS */
12621 switch (er.what)
12622 {
12623 case mouseDown:
12624 case mouseUp:
12625 {
12626 WindowPtr window_ptr = FrontWindow ();
12627 SInt16 part_code;
12628
12629 #if USE_CARBON_EVENTS
12630 /* This is needed to send mouse events like aqua window buttons
12631 to the correct handler. */
12632 if (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
12633 break;
12634 }
12635
12636 if (!is_emacs_window(window_ptr))
12637 break;
12638 #endif
12639
12640 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12641 && er.what == mouseUp)
12642 {
12643 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12644 Point mouse_loc = er.where;
12645
12646 /* Convert to local coordinates of new window. */
12647 #if TARGET_API_MAC_CARBON
12648 SetPort (GetWindowPort (window_ptr));
12649 #else
12650 SetPort (window_ptr);
12651 #endif
12652
12653 GlobalToLocal (&mouse_loc);
12654
12655 #if USE_CARBON_EVENTS
12656 bufp->code = mac_get_mouse_btn (eventRef);
12657 #else
12658 bufp->code = 0; /* only one mouse button */
12659 #endif
12660 bufp->kind = SCROLL_BAR_CLICK_EVENT;
12661 bufp->frame_or_window = tracked_scroll_bar->window;
12662 bufp->part = scroll_bar_handle;
12663 #if USE_CARBON_EVENTS
12664 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12665 #else
12666 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12667 #endif
12668 bufp->modifiers |= up_modifier;
12669 bufp->timestamp = er.when * (1000 / 60);
12670 /* ticks to milliseconds */
12671
12672 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12673 XSETINT (bufp->y, mouse_loc.v - 24);
12674 tracked_scroll_bar->dragging = Qnil;
12675 mouse_tracking_in_progress = mouse_tracking_none;
12676 tracked_scroll_bar = NULL;
12677 count++;
12678 break;
12679 }
12680
12681 part_code = FindWindow (er.where, &window_ptr);
12682
12683 switch (part_code)
12684 {
12685 case inMenuBar:
12686 {
12687 struct frame *f = ((mac_output *)
12688 GetWRefCon (FrontWindow ()))->mFP;
12689 saved_menu_event_location = er.where;
12690 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
12691 XSETFRAME (bufp->frame_or_window, f);
12692 count++;
12693 }
12694 break;
12695
12696 case inContent:
12697 if (window_ptr != FrontWindow ())
12698 SelectWindow (window_ptr);
12699 else
12700 {
12701 SInt16 control_part_code;
12702 ControlHandle ch;
12703 struct mac_output *mwp = (mac_output *)
12704 GetWRefCon (window_ptr);
12705 Point mouse_loc = er.where;
12706
12707 /* convert to local coordinates of new window */
12708 #if TARGET_API_MAC_CARBON
12709 SetPort (GetWindowPort (window_ptr));
12710 #else
12711 SetPort (window_ptr);
12712 #endif
12713
12714 GlobalToLocal (&mouse_loc);
12715 #if TARGET_API_MAC_CARBON
12716 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12717 &control_part_code);
12718 #else
12719 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
12720 #endif
12721
12722 #if USE_CARBON_EVENTS
12723 bufp->code = mac_get_mouse_btn (eventRef);
12724 #else
12725 bufp->code = 0; /* only one mouse button */
12726 #endif
12727 XSETINT (bufp->x, mouse_loc.h);
12728 XSETINT (bufp->y, mouse_loc.v);
12729 bufp->timestamp = er.when * (1000 / 60);
12730 /* ticks to milliseconds */
12731
12732 #if TARGET_API_MAC_CARBON
12733 if (ch != 0)
12734 #else
12735 if (control_part_code != 0)
12736 #endif
12737 {
12738 struct scroll_bar *bar = (struct scroll_bar *)
12739 GetControlReference (ch);
12740 x_scroll_bar_handle_click (bar, control_part_code, &er,
12741 bufp);
12742 if (er.what == mouseDown
12743 && control_part_code == kControlIndicatorPart)
12744 {
12745 mouse_tracking_in_progress
12746 = mouse_tracking_scroll_bar;
12747 tracked_scroll_bar = bar;
12748 }
12749 else
12750 {
12751 mouse_tracking_in_progress = mouse_tracking_none;
12752 tracked_scroll_bar = NULL;
12753 }
12754 }
12755 else
12756 {
12757 bufp->kind = MOUSE_CLICK_EVENT;
12758 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12759 if (er.what == mouseDown)
12760 mouse_tracking_in_progress
12761 = mouse_tracking_mouse_movement;
12762 else
12763 mouse_tracking_in_progress = mouse_tracking_none;
12764 }
12765
12766 #if USE_CARBON_EVENTS
12767 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12768 #else
12769 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12770 #endif
12771
12772 switch (er.what)
12773 {
12774 case mouseDown:
12775 bufp->modifiers |= down_modifier;
12776 break;
12777 case mouseUp:
12778 bufp->modifiers |= up_modifier;
12779 break;
12780 }
12781
12782 count++;
12783 }
12784 break;
12785
12786 case inDrag:
12787 #if TARGET_API_MAC_CARBON
12788 {
12789 BitMap bm;
12790
12791 GetQDGlobalsScreenBits (&bm);
12792 DragWindow (window_ptr, er.where, &bm.bounds);
12793 }
12794 #else /* not TARGET_API_MAC_CARBON */
12795 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12796 #endif /* not TARGET_API_MAC_CARBON */
12797 break;
12798
12799 case inGoAway:
12800 if (TrackGoAway (window_ptr, er.where))
12801 {
12802 bufp->kind = DELETE_WINDOW_EVENT;
12803 XSETFRAME (bufp->frame_or_window,
12804 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12805 count++;
12806 }
12807 break;
12808
12809 /* window resize handling added --ben */
12810 case inGrow:
12811 do_grow_window(window_ptr, &er);
12812 break;
12813
12814 /* window zoom handling added --ben */
12815 case inZoomIn:
12816 case inZoomOut:
12817 if (TrackBox (window_ptr, er.where, part_code))
12818 do_zoom_window (window_ptr, part_code);
12819 break;
12820
12821 default:
12822 break;
12823 }
12824 }
12825 break;
12826
12827 case updateEvt:
12828 case osEvt:
12829 case activateEvt:
12830 #if USE_CARBON_EVENTS
12831 if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
12832 #endif
12833 do_events (&er);
12834 break;
12835
12836 case keyDown:
12837 case autoKey:
12838 {
12839 int keycode = (er.message & keyCodeMask) >> 8;
12840 int xkeysym;
12841
12842 #if USE_CARBON_EVENTS
12843 /* When using Carbon Events, we need to pass raw keyboard events
12844 to the TSM ourselves. If TSM handles it, it will pass back
12845 noErr, otherwise it will pass back "eventNotHandledErr" and
12846 we can process it normally. */
12847 if ((!NILP (Vmac_pass_command_to_system)
12848 || !(er.modifiers & cmdKey))
12849 && (!NILP (Vmac_pass_control_to_system)
12850 || !(er.modifiers & controlKey)))
12851 {
12852 OSStatus err;
12853 err = SendEventToEventTarget (eventRef,
12854 GetEventDispatcherTarget ());
12855 if (err != eventNotHandledErr)
12856 break;
12857 }
12858 #endif
12859
12860 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
12861 {
12862 SysBeep (1);
12863 UNBLOCK_INPUT;
12864 return 0;
12865 }
12866
12867 ObscureCursor ();
12868
12869 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12870 {
12871 bufp->code = 0x7f;
12872 bufp->kind = ASCII_KEYSTROKE_EVENT;
12873 }
12874 else if (keycode_to_xkeysym (keycode, &xkeysym))
12875 {
12876 bufp->code = 0xff00 | xkeysym;
12877 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
12878 }
12879 else if (!NILP (Vmac_reverse_ctrl_meta) && (er.modifiers & controlKey))
12880 {
12881 /* This is a special case to deal with converting from
12882 a control character to non-control character */
12883 int new_modifiers = er.modifiers & ~controlKey;
12884 int new_keycode = keycode | new_modifiers;
12885 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12886 unsigned long some_state = 0;
12887 bufp->code = KeyTranslate (kchr_ptr, new_keycode, &some_state) & 0xff;
12888 bufp->kind = ASCII_KEYSTROKE_EVENT;
12889 }
12890 else
12891 {
12892 if (er.modifiers & macMetaKey)
12893 {
12894 /* This code comes from Keyboard Resource, Appendix
12895 C of IM - Text. This is necessary since shift is
12896 ignored in KCHR table translation when option or
12897 command is pressed. */
12898 int new_modifiers = er.modifiers & 0xf600;
12899 /* mask off option and command */
12900 int new_keycode = keycode | new_modifiers;
12901 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12902 unsigned long some_state = 0;
12903 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12904 &some_state) & 0xff;
12905 }
12906 else
12907 bufp->code = er.message & charCodeMask;
12908 bufp->kind = ASCII_KEYSTROKE_EVENT;
12909 }
12910 }
12911
12912 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12913 convert non-ASCII characters typed at the Mac keyboard
12914 (presumed to be in the Mac Roman encoding) to iso-latin-1
12915 encoding before they are passed to Emacs. This enables the
12916 Mac keyboard to be used to enter non-ASCII iso-latin-1
12917 characters directly. */
12918 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12919 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
12920 {
12921 static TECObjectRef converter = NULL;
12922 OSStatus the_err = noErr;
12923 OSStatus convert_status = noErr;
12924
12925 if (converter == NULL)
12926 {
12927 the_err = TECCreateConverter (&converter,
12928 kTextEncodingMacRoman,
12929 mac_keyboard_text_encoding);
12930 current_mac_keyboard_text_encoding
12931 = mac_keyboard_text_encoding;
12932 }
12933 else if (mac_keyboard_text_encoding
12934 != current_mac_keyboard_text_encoding)
12935 {
12936 /* Free the converter for the current encoding before
12937 creating a new one. */
12938 TECDisposeConverter (converter);
12939 the_err = TECCreateConverter (&converter,
12940 kTextEncodingMacRoman,
12941 mac_keyboard_text_encoding);
12942 current_mac_keyboard_text_encoding
12943 = mac_keyboard_text_encoding;
12944 }
12945
12946 if (the_err == noErr)
12947 {
12948 unsigned char ch = bufp->code;
12949 ByteCount actual_input_length, actual_output_length;
12950 unsigned char outch;
12951
12952 convert_status = TECConvertText (converter, &ch, 1,
12953 &actual_input_length,
12954 &outch, 1,
12955 &actual_output_length);
12956 if (convert_status == noErr
12957 && actual_input_length == 1
12958 && actual_output_length == 1)
12959 bufp->code = outch;
12960 }
12961 }
12962
12963 #if USE_CARBON_EVENTS
12964 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12965 #else
12966 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12967 #endif
12968
12969 {
12970 mac_output *mwp
12971 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
12972 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12973 }
12974
12975 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
12976
12977 count++;
12978 break;
12979
12980 case kHighLevelEvent:
12981 drag_and_drop_file_list = Qnil;
12982
12983 AEProcessAppleEvent(&er);
12984
12985 /* Build a DRAG_N_DROP_EVENT type event as is done in
12986 constuct_drag_n_drop in w32term.c. */
12987 if (!NILP (drag_and_drop_file_list))
12988 {
12989 struct frame *f = NULL;
12990 WindowPtr wp;
12991 Lisp_Object frame;
12992
12993 wp = FrontNonFloatingWindow ();
12994 if (wp && is_emacs_window(wp))
12995 f = ((mac_output *) GetWRefCon (wp))->mFP;
12996
12997 bufp->kind = DRAG_N_DROP_EVENT;
12998 bufp->code = 0;
12999 bufp->timestamp = er.when * (1000 / 60);
13000 /* ticks to milliseconds */
13001 #if USE_CARBON_EVENTS
13002 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13003 #else
13004 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13005 #endif
13006
13007 XSETINT (bufp->x, 0);
13008 XSETINT (bufp->y, 0);
13009
13010 XSETFRAME (frame, f);
13011 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
13012
13013 /* Regardless of whether Emacs was suspended or in the
13014 foreground, ask it to redraw its entire screen.
13015 Otherwise parts of the screen can be left in an
13016 inconsistent state. */
13017 if (wp)
13018 #if TARGET_API_MAC_CARBON
13019 {
13020 Rect r;
13021
13022 GetWindowPortBounds (wp, &r);
13023 InvalWindowRect (wp, &r);
13024 }
13025 #else /* not TARGET_API_MAC_CARBON */
13026 InvalRect (&(wp->portRect));
13027 #endif /* not TARGET_API_MAC_CARBON */
13028
13029 count++;
13030 }
13031 default:
13032 break;
13033 }
13034 #if USE_CARBON_EVENTS
13035 ReleaseEvent (eventRef);
13036 }
13037 #endif
13038
13039 /* If the focus was just given to an autoraising frame,
13040 raise it now. */
13041 /* ??? This ought to be able to handle more than one such frame. */
13042 if (pending_autoraise_frame)
13043 {
13044 x_raise_frame (pending_autoraise_frame);
13045 pending_autoraise_frame = 0;
13046 }
13047
13048 #if !TARGET_API_MAC_CARBON
13049 check_alarm (); /* simulate the handling of a SIGALRM */
13050 #endif
13051
13052 {
13053 static Point old_mouse_pos = { -1, -1 };
13054
13055 if (app_is_suspended)
13056 {
13057 old_mouse_pos.h = -1;
13058 old_mouse_pos.v = -1;
13059 }
13060 else
13061 {
13062 Point mouse_pos;
13063 WindowPtr wp;
13064 struct frame *f;
13065 Lisp_Object bar;
13066 struct scroll_bar *sb;
13067
13068 wp = FrontWindow ();
13069 if (is_emacs_window (wp))
13070 {
13071 f = ((mac_output *) GetWRefCon (wp))->mFP;
13072
13073 #if TARGET_API_MAC_CARBON
13074 SetPort (GetWindowPort (wp));
13075 #else
13076 SetPort (wp);
13077 #endif
13078
13079 GetMouse (&mouse_pos);
13080
13081 if (!EqualPt (mouse_pos, old_mouse_pos))
13082 {
13083 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
13084 && tracked_scroll_bar)
13085 x_scroll_bar_note_movement (tracked_scroll_bar,
13086 mouse_pos.v
13087 - XINT (tracked_scroll_bar->top),
13088 TickCount() * (1000 / 60));
13089 else
13090 note_mouse_movement (f, &mouse_pos);
13091
13092 old_mouse_pos = mouse_pos;
13093 }
13094 }
13095 }
13096 }
13097
13098 UNBLOCK_INPUT;
13099
13100 return count;
13101 }
13102
13103
13104 /* Need to override CodeWarrior's input function so no conversion is
13105 done on newlines Otherwise compiled functions in .elc files will be
13106 read incorrectly. Defined in ...:MSL C:MSL
13107 Common:Source:buffer_io.c. */
13108 #ifdef __MWERKS__
13109 void
13110 __convert_to_newlines (unsigned char * p, size_t * n)
13111 {
13112 #pragma unused(p,n)
13113 }
13114
13115 void
13116 __convert_from_newlines (unsigned char * p, size_t * n)
13117 {
13118 #pragma unused(p,n)
13119 }
13120 #endif
13121
13122
13123 /* Initialize the struct pointed to by MW to represent a new COLS x
13124 ROWS Macintosh window, using font with name FONTNAME and size
13125 FONTSIZE. */
13126 void
13127 NewMacWindow (FRAME_PTR fp)
13128 {
13129 mac_output *mwp;
13130 #if TARGET_API_MAC_CARBON
13131 static int making_terminal_window = 0;
13132 #else
13133 static int making_terminal_window = 1;
13134 #endif
13135
13136 mwp = fp->output_data.mac;
13137
13138 if (making_terminal_window)
13139 {
13140 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
13141 (WindowPtr) -1)))
13142 abort ();
13143 making_terminal_window = 0;
13144 }
13145 else
13146 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
13147 abort ();
13148
13149 SetWRefCon (mwp->mWP, (long) mwp);
13150 /* so that update events can find this mac_output struct */
13151 mwp->mFP = fp; /* point back to emacs frame */
13152
13153 #if TARGET_API_MAC_CARBON
13154 SetPort (GetWindowPort (mwp->mWP));
13155 #else
13156 SetPort (mwp->mWP);
13157 #endif
13158
13159 mwp->fontset = -1;
13160
13161 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
13162 ShowWindow (mwp->mWP);
13163
13164 }
13165
13166
13167 void make_mac_frame (struct frame *f)
13168 {
13169 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
13170 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
13171
13172 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
13173
13174 NewMacWindow(f);
13175
13176 f->output_data.mac->cursor_pixel = 0;
13177 f->output_data.mac->border_pixel = 0x00ff00;
13178 f->output_data.mac->mouse_pixel = 0xff00ff;
13179 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
13180
13181 f->output_data.mac->fontset = -1;
13182 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13183 f->output_data.mac->scroll_bar_background_pixel = -1;
13184 f->output_data.mac->left_pos = 4;
13185 f->output_data.mac->top_pos = 4;
13186 f->output_data.mac->border_width = 0;
13187 f->output_data.mac->explicit_parent = 0;
13188
13189 f->output_data.mac->internal_border_width = 0;
13190
13191 f->output_method = output_mac;
13192
13193 f->auto_raise = 1;
13194 f->auto_lower = 1;
13195
13196 f->new_width = 0;
13197 f->new_height = 0;
13198 }
13199
13200 void make_mac_terminal_frame (struct frame *f)
13201 {
13202 Lisp_Object frame;
13203
13204 XSETFRAME (frame, f);
13205
13206 f->output_method = output_mac;
13207 f->output_data.mac = (struct mac_output *)
13208 xmalloc (sizeof (struct mac_output));
13209 bzero (f->output_data.mac, sizeof (struct mac_output));
13210 f->output_data.mac->fontset = -1;
13211 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13212 f->output_data.mac->scroll_bar_background_pixel = -1;
13213
13214 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
13215
13216 f->width = 96;
13217 f->height = 4;
13218
13219 make_mac_frame (f);
13220
13221 x_make_gc (f);
13222
13223 /* Need to be initialized for unshow_buffer in window.c. */
13224 selected_window = f->selected_window;
13225
13226 Fmodify_frame_parameters (frame,
13227 Fcons (Fcons (Qfont,
13228 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
13229 Fmodify_frame_parameters (frame,
13230 Fcons (Fcons (Qforeground_color,
13231 build_string ("black")), Qnil));
13232 Fmodify_frame_parameters (frame,
13233 Fcons (Fcons (Qbackground_color,
13234 build_string ("white")), Qnil));
13235 }
13236
13237 \f
13238 /***********************************************************************
13239 Initialization
13240 ***********************************************************************/
13241
13242 #ifdef USE_X_TOOLKIT
13243 static XrmOptionDescRec emacs_options[] = {
13244 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13245 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13246
13247 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13248 XrmoptionSepArg, NULL},
13249 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13250
13251 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13252 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13253 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13254 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13255 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13256 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13257 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13258 };
13259 #endif /* USE_X_TOOLKIT */
13260
13261 #ifdef MULTI_KBOARD
13262 /* Test whether two display-name strings agree up to the dot that separates
13263 the screen number from the server number. */
13264 static int
13265 same_x_server (name1, name2)
13266 char *name1, *name2;
13267 {
13268 int seen_colon = 0;
13269 unsigned char *system_name = SDATA (Vsystem_name);
13270 int system_name_length = strlen (system_name);
13271 int length_until_period = 0;
13272
13273 while (system_name[length_until_period] != 0
13274 && system_name[length_until_period] != '.')
13275 length_until_period++;
13276
13277 /* Treat `unix' like an empty host name. */
13278 if (! strncmp (name1, "unix:", 5))
13279 name1 += 4;
13280 if (! strncmp (name2, "unix:", 5))
13281 name2 += 4;
13282 /* Treat this host's name like an empty host name. */
13283 if (! strncmp (name1, system_name, system_name_length)
13284 && name1[system_name_length] == ':')
13285 name1 += system_name_length;
13286 if (! strncmp (name2, system_name, system_name_length)
13287 && name2[system_name_length] == ':')
13288 name2 += system_name_length;
13289 /* Treat this host's domainless name like an empty host name. */
13290 if (! strncmp (name1, system_name, length_until_period)
13291 && name1[length_until_period] == ':')
13292 name1 += length_until_period;
13293 if (! strncmp (name2, system_name, length_until_period)
13294 && name2[length_until_period] == ':')
13295 name2 += length_until_period;
13296
13297 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13298 {
13299 if (*name1 == ':')
13300 seen_colon++;
13301 if (seen_colon && *name1 == '.')
13302 return 1;
13303 }
13304 return (seen_colon
13305 && (*name1 == '.' || *name1 == '\0')
13306 && (*name2 == '.' || *name2 == '\0'));
13307 }
13308 #endif
13309
13310 int mac_initialized = 0;
13311
13312 void
13313 mac_initialize_display_info ()
13314 {
13315 struct mac_display_info *dpyinfo = &one_mac_display_info;
13316 GDHandle main_device_handle;
13317
13318 bzero (dpyinfo, sizeof (*dpyinfo));
13319
13320 /* Put it on x_display_name_list. */
13321 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13322 x_display_name_list);
13323 dpyinfo->name_list_element = XCAR (x_display_name_list);
13324
13325 #if 0
13326 dpyinfo->mac_id_name
13327 = (char *) xmalloc (SCHARS (Vinvocation_name)
13328 + SCHARS (Vsystem_name)
13329 + 2);
13330 sprintf (dpyinfo->mac_id_name, "%s@%s",
13331 SDATA (Vinvocation_name), SDATA (Vsystem_name));
13332 #else
13333 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13334 strcpy (dpyinfo->mac_id_name, "Mac Display");
13335 #endif
13336
13337 main_device_handle = LMGetMainDevice();
13338
13339 dpyinfo->reference_count = 0;
13340 dpyinfo->resx = 75.0;
13341 dpyinfo->resy = 75.0;
13342 dpyinfo->n_planes = 1;
13343 dpyinfo->n_cbits = 16;
13344 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13345 dpyinfo->width = (**main_device_handle).gdRect.right;
13346 dpyinfo->grabbed = 0;
13347 dpyinfo->root_window = NULL;
13348
13349 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13350 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13351 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13352 dpyinfo->mouse_face_window = Qnil;
13353 }
13354
13355 struct mac_display_info *
13356 mac_term_init (display_name, xrm_option, resource_name)
13357 Lisp_Object display_name;
13358 char *xrm_option;
13359 char *resource_name;
13360 {
13361 struct mac_display_info *dpyinfo;
13362 GDHandle main_device_handle;
13363
13364 if (!mac_initialized)
13365 {
13366 mac_initialize ();
13367 mac_initialized = 1;
13368 }
13369
13370 mac_initialize_display_info (display_name);
13371
13372 dpyinfo = &one_mac_display_info;
13373
13374 main_device_handle = LMGetMainDevice();
13375
13376 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13377 dpyinfo->width = (**main_device_handle).gdRect.right;
13378
13379 return dpyinfo;
13380 }
13381 \f
13382 #ifdef MAC_OSX
13383 void MakeMeTheFrontProcess ()
13384 {
13385 ProcessSerialNumber psn;
13386 OSErr err;
13387
13388 err = GetCurrentProcess (&psn);
13389 if (err == noErr)
13390 (void) SetFrontProcess (&psn);
13391 }
13392 #endif /* MAC_OSX */
13393
13394 /* Set up use of X before we make the first connection. */
13395
13396 static struct redisplay_interface x_redisplay_interface =
13397 {
13398 x_produce_glyphs,
13399 x_write_glyphs,
13400 x_insert_glyphs,
13401 x_clear_end_of_line,
13402 x_scroll_run,
13403 x_after_update_window_line,
13404 x_update_window_begin,
13405 x_update_window_end,
13406 XTcursor_to,
13407 x_flush,
13408 x_clear_mouse_face,
13409 x_get_glyph_overhangs,
13410 x_fix_overlapping_area
13411 };
13412
13413 void
13414 mac_initialize ()
13415 {
13416 rif = &x_redisplay_interface;
13417
13418 clear_frame_hook = x_clear_frame;
13419 ins_del_lines_hook = x_ins_del_lines;
13420 delete_glyphs_hook = x_delete_glyphs;
13421 ring_bell_hook = XTring_bell;
13422 reset_terminal_modes_hook = XTreset_terminal_modes;
13423 set_terminal_modes_hook = XTset_terminal_modes;
13424 update_begin_hook = x_update_begin;
13425 update_end_hook = x_update_end;
13426 set_terminal_window_hook = XTset_terminal_window;
13427 read_socket_hook = XTread_socket;
13428 frame_up_to_date_hook = XTframe_up_to_date;
13429 mouse_position_hook = XTmouse_position;
13430 frame_rehighlight_hook = XTframe_rehighlight;
13431 frame_raise_lower_hook = XTframe_raise_lower;
13432
13433 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13434 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13435 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13436 judge_scroll_bars_hook = XTjudge_scroll_bars;
13437
13438 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13439
13440 scroll_region_ok = 1; /* we'll scroll partial frames */
13441 char_ins_del_ok = 1;
13442 line_ins_del_ok = 1; /* we'll just blt 'em */
13443 fast_clear_end_of_line = 1; /* X does this well */
13444 memory_below_frame = 0; /* we don't remember what scrolls
13445 off the bottom */
13446 baud_rate = 19200;
13447
13448 x_noop_count = 0;
13449 last_tool_bar_item = -1;
13450 any_help_event_p = 0;
13451
13452 /* Try to use interrupt input; if we can't, then start polling. */
13453 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13454
13455 #ifdef USE_X_TOOLKIT
13456 XtToolkitInitialize ();
13457 Xt_app_con = XtCreateApplicationContext ();
13458 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13459
13460 /* Install an asynchronous timer that processes Xt timeout events
13461 every 0.1s. This is necessary because some widget sets use
13462 timeouts internally, for example the LessTif menu bar, or the
13463 Xaw3d scroll bar. When Xt timouts aren't processed, these
13464 widgets don't behave normally. */
13465 {
13466 EMACS_TIME interval;
13467 EMACS_SET_SECS_USECS (interval, 0, 100000);
13468 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13469 }
13470 #endif
13471
13472 #if USE_TOOLKIT_SCROLL_BARS
13473 xaw3d_arrow_scroll = False;
13474 xaw3d_pick_top = True;
13475 #endif
13476
13477 #if 0
13478 /* Note that there is no real way portable across R3/R4 to get the
13479 original error handler. */
13480 XSetErrorHandler (x_error_handler);
13481 XSetIOErrorHandler (x_io_error_quitter);
13482
13483 /* Disable Window Change signals; they are handled by X events. */
13484 #ifdef SIGWINCH
13485 signal (SIGWINCH, SIG_DFL);
13486 #endif /* ! defined (SIGWINCH) */
13487
13488 signal (SIGPIPE, x_connection_signal);
13489 #endif
13490
13491 mac_initialize_display_info ();
13492
13493 #if TARGET_API_MAC_CARBON
13494 init_required_apple_events ();
13495
13496 init_mac_drag_n_drop ();
13497
13498 #if USE_CARBON_EVENTS
13499 init_service_handler ();
13500 #endif
13501
13502 DisableMenuCommand (NULL, kHICommandQuit);
13503
13504 if (!inhibit_window_system)
13505 MakeMeTheFrontProcess ();
13506 #endif
13507 }
13508
13509
13510 void
13511 syms_of_macterm ()
13512 {
13513 #if 0
13514 staticpro (&x_error_message_string);
13515 x_error_message_string = Qnil;
13516 #endif
13517
13518 staticpro (&x_display_name_list);
13519 x_display_name_list = Qnil;
13520
13521 staticpro (&last_mouse_scroll_bar);
13522 last_mouse_scroll_bar = Qnil;
13523
13524 staticpro (&Qvendor_specific_keysyms);
13525 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13526
13527 staticpro (&last_mouse_press_frame);
13528 last_mouse_press_frame = Qnil;
13529
13530 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13531 staticpro (&Qmac_ready_for_drag_n_drop);
13532
13533 help_echo = Qnil;
13534 staticpro (&help_echo);
13535 help_echo_object = Qnil;
13536 staticpro (&help_echo_object);
13537 help_echo_window = Qnil;
13538 staticpro (&help_echo_window);
13539 previous_help_echo = Qnil;
13540 staticpro (&previous_help_echo);
13541 help_echo_pos = -1;
13542
13543 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13544 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13545 x_autoselect_window_p = 0;
13546
13547 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13548 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13549 For example, if a block cursor is over a tab, it will be drawn as
13550 wide as that tab on the display. */);
13551 x_stretch_cursor_p = 0;
13552
13553 #if 0 /* TODO: Setting underline position from font properties. */
13554 DEFVAR_BOOL ("x-use-underline-position-properties",
13555 &x_use_underline_position_properties,
13556 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13557 nil means ignore them. If you encounter fonts with bogus
13558 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13559 to 4.1, set this to nil. */);
13560 x_use_underline_position_properties = 1;
13561 #endif
13562
13563 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13564 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13565 Vx_toolkit_scroll_bars = Qt;
13566
13567 staticpro (&last_mouse_motion_frame);
13568 last_mouse_motion_frame = Qnil;
13569
13570 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
13571 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13572 Otherwise the option key is used. */);
13573 Vmac_command_key_is_meta = Qt;
13574
13575 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
13576 doc: /* Non-nil means that the control and meta keys are reversed. This is
13577 useful for non-standard keyboard layouts. */);
13578 Vmac_reverse_ctrl_meta = Qnil;
13579
13580 #if USE_CARBON_EVENTS
13581 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
13582 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
13583 the right click will be mouse-3.
13584 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
13585 Vmac_wheel_button_is_mouse_2 = Qt;
13586
13587 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
13588 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
13589 Toolbox for processing before Emacs sees it. */);
13590 Vmac_pass_command_to_system = Qt;
13591
13592 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
13593 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
13594 Toolbox for processing before Emacs sees it. */);
13595 Vmac_pass_control_to_system = Qt;
13596 #endif
13597
13598 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
13599 doc: /* One of the Text Encoding Base constant values defined in the
13600 Basic Text Constants section of Inside Macintosh - Text Encoding
13601 Conversion Manager. Its value determines the encoding characters
13602 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13603 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13604 its default value, no conversion takes place. If it is set to
13605 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13606 characters typed on Mac keyboard are first converted into the
13607 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13608 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13609 command, this enables the Mac keyboard to be used to enter non-ASCII
13610 characters directly. */);
13611 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13612 }