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