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