Fix last change.
[bpt/emacs.git] / src / macterm.c
CommitLineData
1a578e9b 1/* Implementation of GUI terminal on the Mac OS.
e0f712ba 2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
1a578e9b
AC
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
e0f712ba 21/* Contributed by Andrew Choi (akochoi@mac.com). */
1a578e9b
AC
22
23#include <config.h>
1a578e9b 24#include <signal.h>
1a578e9b 25#include <stdio.h>
e0f712ba 26#include <stdlib.h>
1a578e9b 27#include "lisp.h"
e0f712ba 28#include "charset.h"
1a578e9b
AC
29#include "blockinput.h"
30
1a578e9b
AC
31#include "macterm.h"
32
e0f712ba 33#ifndef MAC_OSX
1a578e9b 34#include <alloca.h>
e0f712ba 35#endif
1a578e9b 36
e0f712ba
AC
37#ifdef MAC_OSX
38#undef mktime
39#undef DEBUG
40#undef free
41#undef malloc
42#undef realloc
43/* Macros max and min defined in lisp.h conflict with those in
44 precompiled header Carbon.h. */
45#undef max
46#undef min
47#include <Carbon/Carbon.h>
48#undef free
49#define free unexec_free
50#undef malloc
51#define malloc unexec_malloc
52#undef realloc
53#define realloc unexec_realloc
54#undef min
55#define min(a, b) ((a) < (b) ? (a) : (b))
56#undef max
57#define max(a, b) ((a) > (b) ? (a) : (b))
58#else /* not MAC_OSX */
1a578e9b
AC
59#include <Quickdraw.h>
60#include <ToolUtils.h>
61#include <Sound.h>
62#include <Events.h>
63#include <Script.h>
64#include <Resources.h>
65#include <Fonts.h>
66#include <TextUtils.h>
67#include <LowMem.h>
68#include <Controls.h>
e0f712ba 69#if defined (__MRC__) || (__MSL__ >= 0x6000)
1a578e9b
AC
70#include <ControlDefinitions.h>
71#endif
e0f712ba 72#include <Gestalt.h>
1a578e9b
AC
73
74#if __profile__
75#include <profiler.h>
76#endif
e0f712ba 77#endif /* not MAC_OSX */
1a578e9b
AC
78
79#include "systty.h"
80#include "systime.h"
e0f712ba
AC
81#include "atimer.h"
82#include "keymap.h"
1a578e9b 83
1a578e9b
AC
84#include <ctype.h>
85#include <errno.h>
86#include <setjmp.h>
87#include <sys/stat.h>
88
e0f712ba 89#include "keyboard.h"
1a578e9b
AC
90#include "frame.h"
91#include "dispextern.h"
92#include "fontset.h"
93#include "termhooks.h"
94#include "termopts.h"
95#include "termchar.h"
96#include "gnu.h"
97#include "disptab.h"
98#include "buffer.h"
99#include "window.h"
1a578e9b 100#include "intervals.h"
e0f712ba 101#include "composite.h"
1a578e9b
AC
102#include "coding.h"
103
1a578e9b
AC
104#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
105
106\f
3f332ef3 107/* Fringe bitmaps. */
1a578e9b 108
3f332ef3 109enum fringe_bitmap_type
1a578e9b 110{
3f332ef3 111 NO_FRINGE_BITMAP,
1a578e9b
AC
112 LEFT_TRUNCATION_BITMAP,
113 RIGHT_TRUNCATION_BITMAP,
114 OVERLAY_ARROW_BITMAP,
115 CONTINUED_LINE_BITMAP,
116 CONTINUATION_LINE_BITMAP,
117 ZV_LINE_BITMAP
118};
119
120/* Bitmap drawn to indicate lines not displaying text if
121 `indicate-empty-lines' is non-nil. */
122
123#define zv_width 8
d33c49e8
KS
124#define zv_height 72
125#define zv_period 3
1a578e9b 126static unsigned char zv_bits[] = {
d33c49e8
KS
127 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
128 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
129 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
130 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
131 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
132 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
133 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
134 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
1a578e9b
AC
135
136/* An arrow like this: `<-'. */
137
138#define left_width 8
139#define left_height 8
140static unsigned char left_bits[] = {
141 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
142
143/* Right truncation arrow bitmap `->'. */
144
145#define right_width 8
146#define right_height 8
147static unsigned char right_bits[] = {
148 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
149
150/* Marker for continued lines. */
151
152#define continued_width 8
153#define continued_height 8
154static unsigned char continued_bits[] = {
155 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
156
157/* Marker for continuation lines. */
158
159#define continuation_width 8
160#define continuation_height 8
161static unsigned char continuation_bits[] = {
162 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
163
164/* Overlay arrow bitmap. */
165
166#if 0
167/* A bomb. */
168#define ov_width 8
169#define ov_height 8
170static unsigned char ov_bits[] = {
171 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
172#else
173/* A triangular arrow. */
174#define ov_width 8
175#define ov_height 8
176static unsigned char ov_bits[] = {
177 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
178#endif
179
180extern Lisp_Object Qhelp_echo;
181
182\f
e0f712ba 183/* Non-nil means Emacs uses toolkit scroll bars. */
1a578e9b 184
e0f712ba 185Lisp_Object Vx_toolkit_scroll_bars;
1a578e9b
AC
186
187/* If a string, XTread_socket generates an event to display that string.
188 (The display is done in read_char.) */
189
190static Lisp_Object help_echo;
191static Lisp_Object help_echo_window;
192static Lisp_Object help_echo_object;
193static int help_echo_pos;
194
195/* Temporary variable for XTread_socket. */
196
197static Lisp_Object previous_help_echo;
198
199/* Non-zero means that a HELP_EVENT has been generated since Emacs
200 start. */
201
202static int any_help_event_p;
203
e0f712ba
AC
204/* Non-zero means autoselect window with the mouse cursor. */
205
206int x_autoselect_window_p;
207
1a578e9b
AC
208/* Non-zero means draw block and hollow cursor as wide as the glyph
209 under it. For example, if a block cursor is over a tab, it will be
210 drawn as wide as that tab on the display. */
211
212int x_stretch_cursor_p;
213
e0f712ba
AC
214/* Non-zero means make use of UNDERLINE_POSITION font properties. */
215
216int x_use_underline_position_properties;
217
1a578e9b
AC
218/* This is a chain of structures for all the X displays currently in
219 use. */
220
221struct x_display_info *x_display_list;
222
223/* This is a list of cons cells, each of the form (NAME
224 . FONT-LIST-CACHE), one for each element of x_display_list and in
225 the same order. NAME is the name of the frame. FONT-LIST-CACHE
226 records previous values returned by x-list-fonts. */
227
228Lisp_Object x_display_name_list;
229
230/* This is display since Mac does not support multiple ones. */
231struct mac_display_info one_mac_display_info;
232
233/* Frame being updated by update_frame. This is declared in term.c.
234 This is set by update_begin and looked at by all the XT functions.
235 It is zero while not inside an update. In that case, the XT
236 functions assume that `selected_frame' is the frame to apply to. */
237
238extern struct frame *updating_frame;
239
e0f712ba
AC
240extern int waiting_for_input;
241
1a578e9b
AC
242/* This is a frame waiting to be auto-raised, within XTread_socket. */
243
244struct frame *pending_autoraise_frame;
245
246/* Nominal cursor position -- where to draw output.
247 HPOS and VPOS are window relative glyph matrix coordinates.
248 X and Y are window relative pixel coordinates. */
249
250struct cursor_pos output_cursor;
251
252/* Non-zero means user is interacting with a toolkit scroll bar. */
253
254static int toolkit_scroll_bar_interaction;
255
256/* Mouse movement.
257
258 Formerly, we used PointerMotionHintMask (in standard_event_mask)
259 so that we would have to call XQueryPointer after each MotionNotify
260 event to ask for another such event. However, this made mouse tracking
261 slow, and there was a bug that made it eventually stop.
262
263 Simply asking for MotionNotify all the time seems to work better.
264
265 In order to avoid asking for motion events and then throwing most
266 of them away or busy-polling the server for mouse positions, we ask
267 the server for pointer motion hints. This means that we get only
268 one event per group of mouse movements. "Groups" are delimited by
269 other kinds of events (focus changes and button clicks, for
270 example), or by XQueryPointer calls; when one of these happens, we
271 get another MotionNotify event the next time the mouse moves. This
272 is at least as efficient as getting motion events when mouse
273 tracking is on, and I suspect only negligibly worse when tracking
274 is off. */
275
276/* Where the mouse was last time we reported a mouse event. */
277
278FRAME_PTR last_mouse_frame;
279static Rect last_mouse_glyph;
280static Lisp_Object last_mouse_press_frame;
281
282/* The scroll bar in which the last X motion event occurred.
283
284 If the last X motion event occurred in a scroll bar, we set this so
285 XTmouse_position can know whether to report a scroll bar motion or
286 an ordinary motion.
287
288 If the last X motion event didn't occur in a scroll bar, we set
289 this to Qnil, to tell XTmouse_position to return an ordinary motion
290 event. */
291
292static Lisp_Object last_mouse_scroll_bar;
293
294/* This is a hack. We would really prefer that XTmouse_position would
295 return the time associated with the position it returns, but there
296 doesn't seem to be any way to wrest the time-stamp from the server
297 along with the position query. So, we just keep track of the time
298 of the last movement we received, and return that in hopes that
299 it's somewhat accurate. */
300
301static Time last_mouse_movement_time;
302
303enum mouse_tracking_type {
304 mouse_tracking_none,
305 mouse_tracking_mouse_movement,
306 mouse_tracking_scroll_bar
307};
308
309enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
310
311struct scroll_bar *tracked_scroll_bar = NULL;
312
313/* Incremented by XTread_socket whenever it really tries to read
314 events. */
315
316#ifdef __STDC__
317static int volatile input_signal_count;
318#else
319static int input_signal_count;
320#endif
321
322/* Used locally within XTread_socket. */
323
324static int x_noop_count;
325
326/* Initial values of argv and argc. */
327
328extern char **initial_argv;
329extern int initial_argc;
330
331extern Lisp_Object Vcommand_line_args, Vsystem_name;
332
333/* Tells if a window manager is present or not. */
334
335extern Lisp_Object Vx_no_window_manager;
336
337extern Lisp_Object Qface, Qmouse_face;
338
339extern int errno;
340
341/* A mask of extra modifier bits to put into every keyboard char. */
342
343extern int extra_keyboard_modifiers;
344
345static Lisp_Object Qvendor_specific_keysyms;
346
347#if 0
348extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
349#endif
350
351extern Lisp_Object x_icon_type P_ ((struct frame *));
352
353
354#if __MRC__
355QDGlobals qd; /* QuickDraw global information structure. */
356#endif
357
358
359/* Enumeration for overriding/changing the face to use for drawing
360 glyphs in x_draw_glyphs. */
361
362enum draw_glyphs_face
363{
364 DRAW_NORMAL_TEXT,
365 DRAW_INVERSE_VIDEO,
366 DRAW_CURSOR,
367 DRAW_MOUSE_FACE,
368 DRAW_IMAGE_RAISED,
369 DRAW_IMAGE_SUNKEN
370};
371
372struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
373struct mac_display_info *mac_display_info_for_display (Display *);
374static void x_update_window_end P_ ((struct window *, int, int));
375static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
1a578e9b 376static int fast_find_position P_ ((struct window *, int, int *, int *,
e0f712ba
AC
377 int *, int *, Lisp_Object));
378static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
379 int *, int *, int *, int *, int));
1a578e9b
AC
380static void set_output_cursor P_ ((struct cursor_pos *));
381static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
e0f712ba 382 int *, int *, int *, int));
1a578e9b
AC
383static void note_mode_line_highlight P_ ((struct window *, int, int));
384static void note_mouse_highlight P_ ((struct frame *, int, int));
385static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
e0f712ba 386static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
1a578e9b
AC
387static void show_mouse_face P_ ((struct x_display_info *,
388 enum draw_glyphs_face));
e0f712ba
AC
389static int cursor_in_mouse_face_p P_ ((struct window *));
390static int clear_mouse_face P_ ((struct mac_display_info *));
1a578e9b
AC
391static int x_io_error_quitter P_ ((Display *));
392int x_catch_errors P_ ((Display *));
393void x_uncatch_errors P_ ((Display *, int));
394void x_lower_frame P_ ((struct frame *));
395void x_scroll_bar_clear P_ ((struct frame *));
396int x_had_errors_p P_ ((Display *));
397void x_wm_set_size_hint P_ ((struct frame *, long, int));
398void x_raise_frame P_ ((struct frame *));
399void x_set_window_size P_ ((struct frame *, int, int, int));
400void x_wm_set_window_state P_ ((struct frame *, int));
401void x_wm_set_icon_pixmap P_ ((struct frame *, int));
e0f712ba 402void mac_initialize P_ ((void));
1a578e9b
AC
403static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
404static int x_compute_min_glyph_bounds P_ ((struct frame *));
405enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
406static void x_draw_phys_cursor_glyph P_ ((struct window *,
407 struct glyph_row *,
408 enum draw_glyphs_face));
409static void x_update_end P_ ((struct frame *));
410static void XTframe_up_to_date P_ ((struct frame *));
411static void XTreassert_line_highlight P_ ((int, int));
412static void x_change_line_highlight P_ ((int, int, int, int));
413static void XTset_terminal_modes P_ ((void));
414static void XTreset_terminal_modes P_ ((void));
415static void XTcursor_to P_ ((int, int, int, int));
416static void x_write_glyphs P_ ((struct glyph *, int));
417static void x_clear_end_of_line P_ ((int));
418static void x_clear_frame P_ ((void));
419static void x_clear_cursor P_ ((struct window *));
420static void frame_highlight P_ ((struct frame *));
421static void frame_unhighlight P_ ((struct frame *));
422static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
423static void XTframe_rehighlight P_ ((struct frame *));
424static void x_frame_rehighlight P_ ((struct x_display_info *));
425static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
426static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
427static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
428static void expose_frame P_ ((struct frame *, int, int, int, int));
e0f712ba
AC
429static int expose_window_tree P_ ((struct window *, Rect *));
430static int expose_window P_ ((struct window *, Rect *));
1a578e9b 431static void expose_area P_ ((struct window *, struct glyph_row *,
e0f712ba
AC
432 Rect *, enum glyph_row_area));
433static int expose_line P_ ((struct window *, struct glyph_row *,
434 Rect *));
1a578e9b
AC
435void x_display_cursor (struct window *, int, int, int, int, int);
436void x_update_cursor P_ ((struct frame *, int));
437static void x_update_cursor_in_window_tree P_ ((struct window *, int));
438static void x_update_window_cursor P_ ((struct window *, int));
439static void x_erase_phys_cursor P_ ((struct window *));
440void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
3f332ef3 441static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
d33c49e8 442 enum fringe_bitmap_type, int left_p));
1a578e9b
AC
443static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
444 GC, int));
445static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
3f332ef3 446static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
e0f712ba
AC
447static void notice_overwritten_cursor P_ ((struct window *,
448 enum glyph_row_area,
449 int, int, int, int));
1a578e9b
AC
450static void x_flush P_ ((struct frame *f));
451static void x_update_begin P_ ((struct frame *));
452static void x_update_window_begin P_ ((struct window *));
453static void x_draw_vertical_border P_ ((struct window *));
454static void x_after_update_window_line P_ ((struct glyph_row *));
455static INLINE void take_vertical_position_into_account P_ ((struct it *));
456static void x_produce_stretch_glyph P_ ((struct it *));
457
458static void activate_scroll_bars (FRAME_PTR);
459static void deactivate_scroll_bars (FRAME_PTR);
460
461extern int image_ascent (struct image *, struct face *);
462void x_set_offset (struct frame *, int, int, int);
463int x_bitmap_icon (struct frame *, Lisp_Object);
464void x_make_frame_visible (struct frame *);
465
466extern void window_scroll (Lisp_Object, int, int, int);
467
468/* Defined in macmenu.h. */
469extern void menubar_selection_callback (FRAME_PTR, int);
470extern void set_frame_menubar (FRAME_PTR, int, int);
471
472/* X display function emulation */
473
474/* Structure borrowed from Xlib.h to represent two-byte characters in
475 dumpglyphs. */
476
477typedef struct {
478 unsigned char byte1;
479 unsigned char byte2;
480} XChar2b;
481
482static void
483XFreePixmap (display, pixmap)
484 Display *display;
485 Pixmap pixmap;
486{
487 PixMap *p = (PixMap *) pixmap;
488
489 xfree (p->baseAddr);
490 xfree (p);
491}
492
493
494/* Set foreground color for subsequent QuickDraw commands. Assume
495 graphic port has already been set. */
496
497static void
498mac_set_forecolor (unsigned long color)
499{
500 RGBColor fg_color;
501
502 fg_color.red = RED_FROM_ULONG (color) * 256;
503 fg_color.green = GREEN_FROM_ULONG (color) * 256;
504 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
505
506 RGBForeColor (&fg_color);
507}
508
509
510/* Set background color for subsequent QuickDraw commands. Assume
511 graphic port has already been set. */
512
513static void
514mac_set_backcolor (unsigned long color)
515{
516 RGBColor bg_color;
517
518 bg_color.red = RED_FROM_ULONG (color) * 256;
519 bg_color.green = GREEN_FROM_ULONG (color) * 256;
520 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
521
522 RGBBackColor (&bg_color);
523}
524
525/* Set foreground and background color for subsequent QuickDraw
526 commands. Assume that the graphic port has already been set. */
527
528static void
529mac_set_colors (GC gc)
530{
531 mac_set_forecolor (gc->foreground);
532 mac_set_backcolor (gc->background);
533}
534
535/* Mac version of XDrawLine. */
536
537static void
538XDrawLine (display, w, gc, x1, y1, x2, y2)
539 Display *display;
540 WindowPtr w;
541 GC gc;
542 int x1, y1, x2, y2;
543{
e0f712ba
AC
544#if TARGET_API_MAC_CARBON
545 SetPort (GetWindowPort (w));
546#else
1a578e9b 547 SetPort (w);
e0f712ba
AC
548#endif
549
1a578e9b
AC
550 mac_set_colors (gc);
551
552 MoveTo (x1, y1);
553 LineTo (x2, y2);
554}
555
556/* Mac version of XClearArea. */
557
2e875e36 558void
1a578e9b
AC
559XClearArea (display, w, x, y, width, height, exposures)
560 Display *display;
561 WindowPtr w;
562 int x, y;
563 unsigned int width, height;
564 int exposures;
565{
566 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
567 Rect r;
568 XGCValues xgc;
569
e0f712ba
AC
570 xgc.foreground = mwp->x_compatible.foreground_pixel;
571 xgc.background = mwp->x_compatible.background_pixel;
1a578e9b 572
e0f712ba
AC
573#if TARGET_API_MAC_CARBON
574 SetPort (GetWindowPort (w));
575#else
1a578e9b 576 SetPort (w);
e0f712ba
AC
577#endif
578
1a578e9b
AC
579 mac_set_colors (&xgc);
580 SetRect (&r, x, y, x + width, y + height);
581
582 EraseRect (&r);
583}
584
585/* Mac version of XClearWindow. */
586
587static void
588XClearWindow (display, w)
589 Display *display;
590 WindowPtr w;
591{
592 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
593 XGCValues xgc;
594
e0f712ba
AC
595 xgc.foreground = mwp->x_compatible.foreground_pixel;
596 xgc.background = mwp->x_compatible.background_pixel;
1a578e9b 597
e0f712ba
AC
598#if TARGET_API_MAC_CARBON
599 SetPort (GetWindowPort (w));
600#else
1a578e9b 601 SetPort (w);
e0f712ba
AC
602#endif
603
1a578e9b
AC
604 mac_set_colors (&xgc);
605
e0f712ba
AC
606#if TARGET_API_MAC_CARBON
607 {
608 Rect r;
609
610 GetWindowPortBounds (w, &r);
611 EraseRect (&r);
612 }
613#else /* not TARGET_API_MAC_CARBON */
614 EraseRect (&(w->portRect));
615#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
616}
617
618
619/* Mac replacement for XCopyArea. */
620
621static void
622mac_draw_bitmap (display, w, gc, x, y, bitmap)
623 Display *display;
624 WindowPtr w;
625 GC gc;
626 int x, y;
627 BitMap *bitmap;
628{
629 Rect r;
630
e0f712ba
AC
631#if TARGET_API_MAC_CARBON
632 SetPort (GetWindowPort (w));
633#else
1a578e9b 634 SetPort (w);
e0f712ba
AC
635#endif
636
1a578e9b
AC
637 mac_set_colors (gc);
638 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
639
e0f712ba
AC
640#if TARGET_API_MAC_CARBON
641 {
642 PixMapHandle pmh;
643
644 LockPortBits (GetWindowPort (w));
645 pmh = GetPortPixMap (GetWindowPort (w));
646 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
647 UnlockPortBits (GetWindowPort (w));
648 }
649#else /* not TARGET_API_MAC_CARBON */
1a578e9b 650 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
e0f712ba 651#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
652}
653
654
655/* Mac replacement for XSetClipRectangles. */
656
657static void
658mac_set_clip_rectangle (display, w, r)
659 Display *display;
660 WindowPtr w;
661 Rect *r;
662{
e0f712ba
AC
663#if TARGET_API_MAC_CARBON
664 SetPort (GetWindowPort (w));
665#else
1a578e9b 666 SetPort (w);
e0f712ba 667#endif
1a578e9b
AC
668
669 ClipRect (r);
670}
671
672
673/* Mac replacement for XSetClipMask. */
674
675static void
676mac_reset_clipping (display, w)
677 Display *display;
678 WindowPtr w;
679{
680 Rect r;
681
e0f712ba
AC
682#if TARGET_API_MAC_CARBON
683 SetPort (GetWindowPort (w));
684#else
1a578e9b 685 SetPort (w);
e0f712ba 686#endif
1a578e9b
AC
687
688 SetRect (&r, -32767, -32767, 32767, 32767);
689 ClipRect (&r);
690}
691
692
693/* Mac replacement for XCreateBitmapFromBitmapData. */
694
695static void
696mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
697 BitMap *bitmap;
698 char *bits;
699 int w, h;
700{
701 int bytes_per_row, i, j;
702
703 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
704 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
705 if (!bitmap->baseAddr)
706 abort ();
707
708 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
709 for (i = 0; i < h; i++)
710 for (j = 0; j < w; j++)
711 if (BitTst (bits, i * w + j))
712 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
713
714 SetRect (&(bitmap->bounds), 0, 0, w, h);
715}
716
717
718static void
719mac_free_bitmap (bitmap)
720 BitMap *bitmap;
721{
722 xfree (bitmap->baseAddr);
723}
724
725/* Mac replacement for XFillRectangle. */
726
727static void
728XFillRectangle (display, w, gc, x, y, width, height)
729 Display *display;
730 WindowPtr w;
731 GC gc;
732 int x, y;
733 unsigned int width, height;
734{
735 Rect r;
736
e0f712ba
AC
737#if TARGET_API_MAC_CARBON
738 SetPort (GetWindowPort (w));
739#else
1a578e9b 740 SetPort (w);
e0f712ba
AC
741#endif
742
1a578e9b
AC
743 mac_set_colors (gc);
744 SetRect (&r, x, y, x + width, y + height);
745
746 PaintRect (&r); /* using foreground color of gc */
747}
748
749
750/* Mac replacement for XDrawRectangle: dest is a window. */
751
752static void
753mac_draw_rectangle (display, w, gc, x, y, width, height)
754 Display *display;
755 WindowPtr w;
756 GC gc;
757 int x, y;
758 unsigned int width, height;
759{
760 Rect r;
761
e0f712ba
AC
762#if TARGET_API_MAC_CARBON
763 SetPort (GetWindowPort (w));
764#else
1a578e9b 765 SetPort (w);
e0f712ba
AC
766#endif
767
1a578e9b
AC
768 mac_set_colors (gc);
769 SetRect (&r, x, y, x + width + 1, y + height + 1);
770
771 FrameRect (&r); /* using foreground color of gc */
772}
773
774
775/* Mac replacement for XDrawRectangle: dest is a Pixmap. */
776
777static void
778mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
779 Display *display;
780 Pixmap p;
781 GC gc;
782 int x, y;
783 unsigned int width, height;
784{
785#if 0 /* MAC_TODO: draw a rectangle in a PixMap */
786 Rect r;
787
e0f712ba
AC
788#if TARGET_API_MAC_CARBON
789 SetPort (GetWindowPort (w));
790#else
1a578e9b 791 SetPort (w);
e0f712ba
AC
792#endif
793
1a578e9b
AC
794 mac_set_colors (gc);
795 SetRect (&r, x, y, x + width, y + height);
796
797 FrameRect (&r); /* using foreground color of gc */
e0f712ba 798#endif /* 0 */
1a578e9b
AC
799}
800
801
802static void
803mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
804 bytes_per_char)
805 Display *display;
806 WindowPtr w;
807 GC gc;
808 int x, y;
809 char *buf;
810 int nchars, mode, bytes_per_char;
811{
e0f712ba
AC
812#if TARGET_API_MAC_CARBON
813 SetPort (GetWindowPort (w));
814#else
1a578e9b 815 SetPort (w);
e0f712ba
AC
816#endif
817
1a578e9b
AC
818 mac_set_colors (gc);
819
820 TextFont (gc->font->mac_fontnum);
821 TextSize (gc->font->mac_fontsize);
822 TextFace (gc->font->mac_fontface);
823 TextMode (mode);
824
825 MoveTo (x, y);
826 DrawText (buf, 0, nchars * bytes_per_char);
827}
828
829
830/* Mac replacement for XDrawString. */
831
832static void
833XDrawString (display, w, gc, x, y, buf, nchars)
834 Display *display;
835 WindowPtr w;
836 GC gc;
837 int x, y;
838 char *buf;
839 int nchars;
840{
841 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
842}
843
844
845/* Mac replacement for XDrawString16. */
846
847static void
848XDrawString16 (display, w, gc, x, y, buf, nchars)
849 Display *display;
850 WindowPtr w;
851 GC gc;
852 int x, y;
853 XChar2b *buf;
854 int nchars;
855{
856 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
857 2);
858}
859
860
861/* Mac replacement for XDrawImageString. */
862
863static void
864XDrawImageString (display, w, gc, x, y, buf, nchars)
865 Display *display;
866 WindowPtr w;
867 GC gc;
868 int x, y;
869 char *buf;
870 int nchars;
871{
872 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
873}
874
875
876/* Mac replacement for XDrawString16. */
877
878static void
879XDrawImageString16 (display, w, gc, x, y, buf, nchars)
880 Display *display;
881 WindowPtr w;
882 GC gc;
883 int x, y;
884 XChar2b *buf;
885 int nchars;
886{
887 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
888 2);
889}
890
891
892/* Mac replacement for XCopyArea: dest must be window. */
893
894static void
895mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
896 dest_y)
897 Display *display;
898 Pixmap src;
899 WindowPtr dest;
900 GC gc;
901 int src_x, src_y;
902 unsigned int width, height;
903 int dest_x, dest_y;
904{
905 Rect src_r, dest_r;
906
e0f712ba
AC
907#if TARGET_API_MAC_CARBON
908 SetPort (GetWindowPort (dest));
909#else
1a578e9b 910 SetPort (dest);
e0f712ba
AC
911#endif
912
1a578e9b
AC
913 mac_set_colors (gc);
914
915 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
916 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
917
e0f712ba
AC
918#if TARGET_API_MAC_CARBON
919 {
920 PixMapHandle pmh;
921
922 LockPortBits (GetWindowPort (dest));
923 pmh = GetPortPixMap (GetWindowPort (dest));
924 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
925 UnlockPortBits (GetWindowPort (dest));
926 }
927#else /* not TARGET_API_MAC_CARBON */
928 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
929#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
930}
931
932
f9e25d0c 933#if 0
1a578e9b
AC
934/* Convert a pair of local coordinates to global (screen) coordinates.
935 Assume graphic port has been properly set. */
936static void
937local_to_global_coord (short *h, short *v)
938{
939 Point p;
940
941 p.h = *h;
942 p.v = *v;
943
944 LocalToGlobal (&p);
945
946 *h = p.h;
947 *v = p.v;
948}
f9e25d0c 949#endif
1a578e9b
AC
950
951/* Mac replacement for XCopyArea: used only for scrolling. */
952
953static void
954mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
955 Display *display;
956 WindowPtr w;
957 GC gc;
958 int src_x, src_y;
959 unsigned int width, height;
960 int dest_x, dest_y;
961{
e0f712ba
AC
962#if TARGET_API_MAC_CARBON
963 Rect gw_r, src_r, dest_r;
964 PixMapHandle pmh;
965
966 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
967 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
968
969 SetPort (GetWindowPort (w));
970 mac_set_colors (gc);
971
972 LockPortBits (GetWindowPort (w));
973 pmh = GetPortPixMap (GetWindowPort (w));
974 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
975 UnlockPortBits (GetWindowPort (w));
976#else /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
977 Rect src_r, dest_r;
978
979 SetPort (w);
f9e25d0c 980#if 0
1a578e9b 981 mac_set_colors (gc);
f9e25d0c 982#endif
1a578e9b
AC
983
984 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
985 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
986
f9e25d0c 987#if 0
1a578e9b
AC
988 /* Need to use global coordinates and screenBits since src and dest
989 areas overlap in general. */
990 local_to_global_coord (&src_r.left, &src_r.top);
991 local_to_global_coord (&src_r.right, &src_r.bottom);
992 local_to_global_coord (&dest_r.left, &dest_r.top);
993 local_to_global_coord (&dest_r.right, &dest_r.bottom);
994
995 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
f9e25d0c
AC
996#else
997 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
998 color mapping in CopyBits. Otherwise, it will be slow. */
999 ForeColor (blackColor);
1000 BackColor (whiteColor);
1001 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1002
1003 mac_set_colors (gc);
1004#endif
e0f712ba 1005#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
1006}
1007
1008
1009/* Mac replacement for XCopyArea: dest must be Pixmap. */
1010
1011static void
1012mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1013 dest_x, dest_y)
1014 Display *display;
1015 Pixmap src;
1016 Pixmap dest;
1017 GC gc;
1018 int src_x, src_y;
1019 unsigned int width, height;
1020 int dest_x, dest_y;
1021{
1022 Rect src_r, dest_r;
1023 int src_right = ((PixMap *) src)->bounds.right;
1024 int src_bottom = ((PixMap *) src)->bounds.bottom;
1025 int w = src_right - src_x;
1026 int h = src_bottom - src_y;
1027
1028 mac_set_colors (gc);
1029
1030 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1031 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1032
e0f712ba 1033 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1a578e9b
AC
1034}
1035
1036
1037/* Mac replacement for XChangeGC. */
1038
1039static void
1040XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1041 XGCValues *xgcv)
1042{
1043 if (mask & GCForeground)
1044 gc->foreground = xgcv->foreground;
1045 if (mask & GCBackground)
1046 gc->background = xgcv->background;
1047 if (mask & GCFont)
1048 gc->font = xgcv->font;
1049}
1050
1051
1052/* Mac replacement for XCreateGC. */
1053
1054XGCValues *
1055XCreateGC (void * ignore, Window window, unsigned long mask,
1056 XGCValues *xgcv)
1057{
1058 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1059 bzero (gc, sizeof (XGCValues));
1060
1061 XChangeGC (ignore, gc, mask, xgcv);
1062
1063 return gc;
1064}
1065
1066
1067/* Used in xfaces.c. */
1068
1069void
1070XFreeGC (display, gc)
1071 Display *display;
1072 GC gc;
1073{
1074 xfree (gc);
1075}
1076
1077
1078/* Mac replacement for XGetGCValues. */
1079
1080static void
1081XGetGCValues (void* ignore, XGCValues *gc,
1082 unsigned long mask, XGCValues *xgcv)
1083{
1084 XChangeGC (ignore, xgcv, mask, gc);
1085}
1086
1087
1088/* Mac replacement for XSetForeground. */
1089
1090static void
1091XSetForeground (display, gc, color)
1092 Display *display;
1093 GC gc;
1094 unsigned long color;
1095{
1096 gc->foreground = color;
1097}
1098
1099
1100/* Mac replacement for XSetFont. */
1101
1102static void
1103XSetFont (display, gc, font)
1104 Display *display;
1105 GC gc;
1106 XFontStruct *font;
1107{
1108 gc->font = font;
1109}
1110
1111
1112static void
1113XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1114 int *direction,int *font_ascent,
1115 int *font_descent, XCharStruct *cs)
1116{
1117 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1118}
1119
1120
1121/* x_sync is a no-op on Mac. */
1122void
1123x_sync (f)
1124 void *f;
1125{
1126}
1127
1128
e0f712ba
AC
1129/* Remove calls to XFlush by defining XFlush to an empty replacement.
1130 Calls to XFlush should be unnecessary because the X output buffer
1131 is flushed automatically as needed by calls to XPending,
1132 XNextEvent, or XWindowEvent according to the XFlush man page.
1133 XTread_socket calls XPending. Removing XFlush improves
1134 performance. */
1135
1136#if TARGET_API_MAC_CARBON
1137#define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1138#else
1139#define XFlush(DISPLAY) (void) 0
1140#endif
1141
1a578e9b
AC
1142/* Flush display of frame F, or of all frames if F is null. */
1143
1144void
1145x_flush (f)
1146 struct frame *f;
1147{
e0f712ba 1148#if TARGET_API_MAC_CARBON
1a578e9b
AC
1149 BLOCK_INPUT;
1150 if (f == NULL)
1151 {
1152 Lisp_Object rest, frame;
1153 FOR_EACH_FRAME (rest, frame)
1154 x_flush (XFRAME (frame));
1155 }
1156 else if (FRAME_X_P (f))
1157 XFlush (FRAME_MAC_DISPLAY (f));
1158 UNBLOCK_INPUT;
e0f712ba 1159#endif /* TARGET_API_MAC_CARBON */
1a578e9b
AC
1160}
1161
1162
1a578e9b
AC
1163\f
1164/* Return the struct mac_display_info corresponding to DPY. There's
1165 only one. */
1166
1167struct mac_display_info *
1168mac_display_info_for_display (dpy)
1169 Display *dpy;
1170{
1171 return &one_mac_display_info;
1172}
1173
1174
1175\f
1176/***********************************************************************
1177 Starting and ending an update
1178 ***********************************************************************/
1179
1180/* Start an update of frame F. This function is installed as a hook
1181 for update_begin, i.e. it is called when update_begin is called.
1182 This function is called prior to calls to x_update_window_begin for
e0f712ba 1183 each window being updated. */
1a578e9b 1184
e0f712ba 1185static void
1a578e9b
AC
1186x_update_begin (f)
1187 struct frame *f;
1188{
1189 /* Nothing to do. */
1190}
1191
1192
1193/* Start update of window W. Set the global variable updated_window
1194 to the window being updated and set output_cursor to the cursor
1195 position of W. */
1196
e0f712ba 1197static void
1a578e9b
AC
1198x_update_window_begin (w)
1199 struct window *w;
1200{
1201 struct frame *f = XFRAME (WINDOW_FRAME (w));
1202 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1203
1204 updated_window = w;
1205 set_output_cursor (&w->cursor);
1206
1207 BLOCK_INPUT;
1208
1209 if (f == display_info->mouse_face_mouse_frame)
1210 {
1211 /* Don't do highlighting for mouse motion during the update. */
1212 display_info->mouse_face_defer = 1;
1213
1214 /* If F needs to be redrawn, simply forget about any prior mouse
1215 highlighting. */
1216 if (FRAME_GARBAGED_P (f))
1217 display_info->mouse_face_window = Qnil;
1218
1219#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1220 their mouse_face_p flag set, which means that they are always
1221 unequal to rows in a desired matrix which never have that
1222 flag set. So, rows containing mouse-face glyphs are never
1223 scrolled, and we don't have to switch the mouse highlight off
1224 here to prevent it from being scrolled. */
1225
1226 /* Can we tell that this update does not affect the window
1227 where the mouse highlight is? If so, no need to turn off.
1228 Likewise, don't do anything if the frame is garbaged;
1229 in that case, the frame's current matrix that we would use
1230 is all wrong, and we will redisplay that line anyway. */
1231 if (!NILP (display_info->mouse_face_window)
1232 && w == XWINDOW (display_info->mouse_face_window))
1233 {
1234 int i;
1235
e0f712ba 1236 for (i = 0; i < w->desired_matrix->nrows; ++i)
1a578e9b
AC
1237 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1238 break;
1239
1240 if (i < w->desired_matrix->nrows)
1241 clear_mouse_face (display_info);
1242 }
1243#endif /* 0 */
1244 }
1245
1246 UNBLOCK_INPUT;
1247}
1248
1249
1250/* Draw a vertical window border to the right of window W if W doesn't
1251 have vertical scroll bars. */
1252
1253static void
1254x_draw_vertical_border (w)
1255 struct window *w;
1256{
1257 struct frame *f = XFRAME (WINDOW_FRAME (w));
1258
1259 /* Redraw borders between horizontally adjacent windows. Don't
1260 do it for frames with vertical scroll bars because either the
1261 right scroll bar of a window, or the left scroll bar of its
1262 neighbor will suffice as a border. */
1263 if (!WINDOW_RIGHTMOST_P (w)
1264 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1265 {
1266 int x0, x1, y0, y1;
1267
1268 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
3f332ef3 1269 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1a578e9b
AC
1270 y1 -= 1;
1271
1272 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1273 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1274 }
1275}
e0f712ba 1276
1a578e9b
AC
1277
1278/* End update of window W (which is equal to updated_window).
1279
1280 Draw vertical borders between horizontally adjacent windows, and
1281 display W's cursor if CURSOR_ON_P is non-zero.
1282
1283 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1284 glyphs in mouse-face were overwritten. In that case we have to
1285 make sure that the mouse-highlight is properly redrawn.
1286
1287 W may be a menu bar pseudo-window in case we don't have X toolkit
e0f712ba
AC
1288 support. Such windows don't have a cursor, so don't display it
1289 here. */
1a578e9b 1290
e0f712ba 1291static void
1a578e9b
AC
1292x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1293 struct window *w;
1294 int cursor_on_p, mouse_face_overwritten_p;
1295{
e0f712ba
AC
1296 struct mac_display_info *dpyinfo
1297 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1298
1a578e9b
AC
1299 if (!w->pseudo_window_p)
1300 {
1a578e9b
AC
1301 BLOCK_INPUT;
1302
1a578e9b
AC
1303 if (cursor_on_p)
1304 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1305 output_cursor.vpos,
1306 output_cursor.x, output_cursor.y);
1307
1308 x_draw_vertical_border (w);
1309 UNBLOCK_INPUT;
1310 }
e0f712ba
AC
1311
1312 /* If a row with mouse-face was overwritten, arrange for
1313 XTframe_up_to_date to redisplay the mouse highlight. */
1314 if (mouse_face_overwritten_p)
1315 {
1316 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1317 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1318 dpyinfo->mouse_face_window = Qnil;
1319 }
1320
1321#if 0
1322 /* Unhide the caret. This won't actually show the cursor, unless it
1323 was visible before the corresponding call to HideCaret in
1324 x_update_window_begin. */
1325 if (w32_use_visible_system_caret)
1326 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1327#endif
1328
1a578e9b
AC
1329 updated_window = NULL;
1330}
1331
1332
1333/* End update of frame F. This function is installed as a hook in
1334 update_end. */
1335
e0f712ba 1336static void
1a578e9b
AC
1337x_update_end (f)
1338 struct frame *f;
1339{
1340 /* Reset the background color of Mac OS Window to that of the frame after
1341 update so that it is used by Mac Toolbox to clear the update region before
1342 an update event is generated. */
e0f712ba
AC
1343#if TARGET_API_MAC_CARBON
1344 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1345#else
1a578e9b 1346 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
1347#endif
1348
1a578e9b
AC
1349 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1350
1351 /* Mouse highlight may be displayed again. */
1352 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1353
1354 BLOCK_INPUT;
1355 XFlush (FRAME_MAC_DISPLAY (f));
1356 UNBLOCK_INPUT;
1357}
1358
1359
1360/* This function is called from various places in xdisp.c whenever a
1361 complete update has been performed. The global variable
1362 updated_window is not available here. */
1363
e0f712ba 1364static void
1a578e9b
AC
1365XTframe_up_to_date (f)
1366 struct frame *f;
1367{
1368 if (FRAME_X_P (f))
1369 {
1370 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1371
1372 if (dpyinfo->mouse_face_deferred_gc
1373 || f == dpyinfo->mouse_face_mouse_frame)
1374 {
1375 BLOCK_INPUT;
1376 if (dpyinfo->mouse_face_mouse_frame)
1377 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1378 dpyinfo->mouse_face_mouse_x,
1379 dpyinfo->mouse_face_mouse_y);
1380 dpyinfo->mouse_face_deferred_gc = 0;
1381 UNBLOCK_INPUT;
1382 }
1383 }
1384}
1385
1386
1387/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
3f332ef3 1388 arrow bitmaps, or clear the fringes if no bitmaps are required
1a578e9b 1389 before DESIRED_ROW is made current. The window being updated is
e0f712ba 1390 found in updated_window. This function is called from
1a578e9b
AC
1391 update_window_line only if it is known that there are differences
1392 between bitmaps to be drawn between current row and DESIRED_ROW. */
1393
e0f712ba 1394static void
1a578e9b
AC
1395x_after_update_window_line (desired_row)
1396 struct glyph_row *desired_row;
1397{
1398 struct window *w = updated_window;
e0f712ba
AC
1399 struct frame *f;
1400 int width, height;
1401
1a578e9b
AC
1402 xassert (w);
1403
1404 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1405 {
1406 BLOCK_INPUT;
3f332ef3 1407 x_draw_row_fringe_bitmaps (w, desired_row);
e0f712ba
AC
1408 UNBLOCK_INPUT;
1409 }
1a578e9b 1410
e0f712ba
AC
1411 /* When a window has disappeared, make sure that no rest of
1412 full-width rows stays visible in the internal border. Could
1413 check here if updated_window is the leftmost/rightmost window,
1414 but I guess it's not worth doing since vertically split windows
1415 are almost never used, internal border is rarely set, and the
1416 overhead is very small. */
1417 if (windows_or_buffers_changed
1418 && desired_row->full_width_p
1419 && (f = XFRAME (w->frame),
1420 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1421 width != 0)
1422 && (height = desired_row->visible_height,
1423 height > 0))
1424 {
1425 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1426 /* Internal border is drawn below the tool bar. */
1427 if (WINDOWP (f->tool_bar_window)
1428 && w == XWINDOW (f->tool_bar_window))
1429 y -= width;
1a578e9b 1430
e0f712ba
AC
1431 BLOCK_INPUT;
1432
1433 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1434 0, y, width, height, 0);
1435 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1436 f->output_data.mac->pixel_width - width, y,
1437 width, height, 0);
1a578e9b
AC
1438
1439 UNBLOCK_INPUT;
1440 }
1441}
1442
1443
3f332ef3 1444/* Draw the bitmap WHICH in one of the left or right fringes of
1a578e9b
AC
1445 window W. ROW is the glyph row for which to display the bitmap; it
1446 determines the vertical position at which the bitmap has to be
1447 drawn. */
1448
1449static void
d33c49e8 1450x_draw_fringe_bitmap (w, row, which, left_p)
1a578e9b
AC
1451 struct window *w;
1452 struct glyph_row *row;
3f332ef3 1453 enum fringe_bitmap_type which;
d33c49e8 1454 int left_p;
1a578e9b
AC
1455{
1456 struct frame *f = XFRAME (WINDOW_FRAME (w));
1457 Display *display = FRAME_MAC_DISPLAY (f);
1458 WindowPtr window = FRAME_MAC_WINDOW (f);
1459 int x, y, wd, h, dy;
d33c49e8 1460 int b1, b2;
1a578e9b
AC
1461 unsigned char *bits;
1462 BitMap bitmap;
1463 XGCValues gcv;
e0f712ba 1464 GC gc = f->output_data.mac->normal_gc;
1a578e9b
AC
1465 struct face *face;
1466
1467 /* Must clip because of partially visible lines. */
e0f712ba 1468 x_clip_to_row (w, row, gc, 1);
1a578e9b 1469
d33c49e8
KS
1470 /* Convert row to frame coordinates. */
1471 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1472
1a578e9b
AC
1473 switch (which)
1474 {
d33c49e8
KS
1475 case NO_FRINGE_BITMAP:
1476 wd = 0;
1477 h = 0;
1478 break;
1479
1a578e9b
AC
1480 case LEFT_TRUNCATION_BITMAP:
1481 wd = left_width;
1482 h = left_height;
1483 bits = left_bits;
1a578e9b
AC
1484 break;
1485
1486 case OVERLAY_ARROW_BITMAP:
d33c49e8
KS
1487 wd = ov_width;
1488 h = ov_height;
1a578e9b 1489 bits = ov_bits;
1a578e9b
AC
1490 break;
1491
1492 case RIGHT_TRUNCATION_BITMAP:
1493 wd = right_width;
1494 h = right_height;
1495 bits = right_bits;
1a578e9b
AC
1496 break;
1497
1498 case CONTINUED_LINE_BITMAP:
d33c49e8
KS
1499 wd = continued_width;
1500 h = continued_height;
1a578e9b 1501 bits = continued_bits;
1a578e9b
AC
1502 break;
1503
1504 case CONTINUATION_LINE_BITMAP:
1505 wd = continuation_width;
1506 h = continuation_height;
1507 bits = continuation_bits;
1a578e9b
AC
1508 break;
1509
1510 case ZV_LINE_BITMAP:
1511 wd = zv_width;
d33c49e8
KS
1512 h = zv_height - (y % zv_period);
1513 bits = zv_bits + (y % zv_period);
1a578e9b
AC
1514 break;
1515
1516 default:
1517 abort ();
1518 }
1519
d33c49e8
KS
1520 /* Clip bitmap if too high. */
1521 if (h > row->height)
1522 h = row->height;
1523
1524 /* Set dy to the offset in the row to start drawing the bitmap. */
1a578e9b
AC
1525 dy = (row->height - h) / 2;
1526
e0f712ba 1527 /* Draw the bitmap. */
3f332ef3 1528 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
d33c49e8
KS
1529 PREPARE_FACE_FOR_DISPLAY (f, face);
1530
1531 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1532 the fringe. */
1533 b1 = -1;
1534 if (left_p)
1535 {
1536 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1537 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1538 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1539 - wd
1540 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1541 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1542 {
1543 /* If W has a vertical border to its left, don't draw over it. */
1544 int border = ((XFASTINT (w->left) > 0
1545 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1546 ? 1 : 0);
1547 b1 = (window_box_left (w, -1)
1548 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1549 + border);
1550 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1551 }
1552 }
1553 else
1554 {
1555 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1556 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1557 x = (window_box_right (w, -1)
1558 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1559 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1560 the fringe. */
1561 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1562 {
1563 b1 = window_box_right (w, -1);
1564 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1565 }
1566 }
1567
1568 if (b1 >= 0)
1569 {
1570 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1571 XGCValues gcv;
1572 gcv.foreground = face->background;
1573
1574#if 0 /* MAC_TODO: stipple */
1575 /* In case the same realized face is used for fringes and
1576 for something displayed in the text (e.g. face `region' on
1577 mono-displays, the fill style may have been changed to
1578 FillSolid in x_draw_glyph_string_background. */
1579 if (face->stipple)
1580 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1581 else
1582 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1583#endif
1584
1585 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1586 &gcv,
1587 b1,
1588 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1589 row->y)),
1590 b2,
1591 row->visible_height);
1592
1593#if 0 /* MAC_TODO: stipple */
1594 if (!face->stipple)
1595 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1596#endif
1597 }
1598
1599 if (which == NO_FRINGE_BITMAP)
e0f712ba
AC
1600 {
1601 mac_reset_clipping (display, window);
1602 return;
1603 }
1a578e9b
AC
1604
1605 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1606 gcv.foreground = face->foreground;
1607 gcv.background = face->background;
1608
1609 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1610
1611 mac_free_bitmap (&bitmap);
1612 mac_reset_clipping (display, window);
1613}
1614
1615
3f332ef3 1616/* Draw fringe bitmaps for glyph row ROW on window W. Call this
1a578e9b
AC
1617 function with input blocked. */
1618
1619static void
3f332ef3 1620x_draw_row_fringe_bitmaps (w, row)
1a578e9b
AC
1621 struct window *w;
1622 struct glyph_row *row;
1623{
1624 struct frame *f = XFRAME (w->frame);
3f332ef3 1625 enum fringe_bitmap_type bitmap;
1a578e9b
AC
1626
1627 xassert (interrupt_input_blocked);
1628
1629 /* If row is completely invisible, because of vscrolling, we
1630 don't have to draw anything. */
1631 if (row->visible_height <= 0)
1632 return;
1633
d33c49e8
KS
1634 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1635 {
1636 /* Decide which bitmap to draw in the left fringe. */
1637 if (row->overlay_arrow_p)
1638 bitmap = OVERLAY_ARROW_BITMAP;
1639 else if (row->truncated_on_left_p)
1640 bitmap = LEFT_TRUNCATION_BITMAP;
1641 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1642 bitmap = CONTINUATION_LINE_BITMAP;
1643 else if (row->indicate_empty_line_p)
1644 bitmap = ZV_LINE_BITMAP;
1a578e9b 1645 else
d33c49e8 1646 bitmap = NO_FRINGE_BITMAP;
1a578e9b 1647
d33c49e8
KS
1648 x_draw_fringe_bitmap (w, row, bitmap, 1);
1649 }
1a578e9b 1650
d33c49e8 1651 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1a578e9b 1652 {
d33c49e8
KS
1653 /* Decide which bitmap to draw in the right fringe. */
1654 if (row->truncated_on_right_p)
1655 bitmap = RIGHT_TRUNCATION_BITMAP;
1656 else if (row->continued_p)
1657 bitmap = CONTINUED_LINE_BITMAP;
1658 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1659 bitmap = ZV_LINE_BITMAP;
1a578e9b 1660 else
d33c49e8 1661 bitmap = NO_FRINGE_BITMAP;
1a578e9b 1662
d33c49e8 1663 x_draw_fringe_bitmap (w, row, bitmap, 0);
1a578e9b 1664 }
1a578e9b
AC
1665}
1666
1667\f
1a578e9b 1668/* This is called when starting Emacs and when restarting after
e0f712ba 1669 suspend. When starting Emacs, no window is mapped. And nothing
1a578e9b
AC
1670 must be done to Emacs's own window if it is suspended (though that
1671 rarely happens). */
1672
e0f712ba 1673static void
1a578e9b
AC
1674XTset_terminal_modes ()
1675{
1676}
1677
1678/* This is called when exiting or suspending Emacs. Exiting will make
e0f712ba 1679 the windows go away, and suspending requires no action. */
1a578e9b 1680
e0f712ba 1681static void
1a578e9b
AC
1682XTreset_terminal_modes ()
1683{
1684}
1685
1686
1687\f
1688/***********************************************************************
1689 Output Cursor
1690 ***********************************************************************/
1691
1692/* Set the global variable output_cursor to CURSOR. All cursor
1693 positions are relative to updated_window. */
1694
1695static void
1696set_output_cursor (cursor)
1697 struct cursor_pos *cursor;
1698{
1699 output_cursor.hpos = cursor->hpos;
1700 output_cursor.vpos = cursor->vpos;
1701 output_cursor.x = cursor->x;
1702 output_cursor.y = cursor->y;
1703}
1704
1705
1706/* Set a nominal cursor position.
1707
1708 HPOS and VPOS are column/row positions in a window glyph matrix. X
1709 and Y are window text area relative pixel positions.
1710
1711 If this is done during an update, updated_window will contain the
1712 window that is being updated and the position is the future output
1713 cursor position for that window. If updated_window is null, use
1714 selected_window and display the cursor at the given position. */
1715
e0f712ba 1716static void
1a578e9b
AC
1717XTcursor_to (vpos, hpos, y, x)
1718 int vpos, hpos, y, x;
1719{
1720 struct window *w;
1721
1722 /* If updated_window is not set, work on selected_window. */
1723 if (updated_window)
1724 w = updated_window;
1725 else
1726 w = XWINDOW (selected_window);
1727
1728 /* Set the output cursor. */
1729 output_cursor.hpos = hpos;
1730 output_cursor.vpos = vpos;
1731 output_cursor.x = x;
1732 output_cursor.y = y;
1733
1734 /* If not called as part of an update, really display the cursor.
1735 This will also set the cursor position of W. */
1736 if (updated_window == NULL)
1737 {
1738 BLOCK_INPUT;
1739 x_display_cursor (w, 1, hpos, vpos, x, y);
1740 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1741 UNBLOCK_INPUT;
1742 }
1743}
1744
1745
1746\f
1747/***********************************************************************
1748 Display Iterator
1749 ***********************************************************************/
1750
1751/* Function prototypes of this page. */
1752
1753static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1754 struct glyph *,
1755 XChar2b *,
1756 int *));
1757static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1758 int, XChar2b *, int));
1759static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1760static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1761static void x_append_glyph P_ ((struct it *));
1762static void x_append_composite_glyph P_ ((struct it *));
1763static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1764 int, int, double));
1765static void x_produce_glyphs P_ ((struct it *));
1766static void x_produce_image_glyph P_ ((struct it *it));
1767
1768
1769/* Return a pointer to per-char metric information in FONT of a
1770 character pointed by B which is a pointer to an XChar2b. */
1771
1772#define PER_CHAR_METRIC(font, b) \
1773 ((font)->per_char \
1774 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1775 + (((font)->min_byte1 || (font)->max_byte1) \
1776 ? (((b)->byte1 - (font)->min_byte1) \
1777 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1778 : 0)) \
1779 : &((font)->max_bounds))
1780
1781
1782/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1783 is not contained in the font. */
1784
1785static INLINE XCharStruct *
1786x_per_char_metric (font, char2b)
1787 XFontStruct *font;
1788 XChar2b *char2b;
1789{
1790 /* The result metric information. */
1791 XCharStruct *pcm = NULL;
1792
1793 xassert (font && char2b);
1794
1795 if (font->per_char != NULL)
1796 {
1797 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1798 {
1799 /* min_char_or_byte2 specifies the linear character index
1800 corresponding to the first element of the per_char array,
1801 max_char_or_byte2 is the index of the last character. A
1802 character with non-zero CHAR2B->byte1 is not in the font.
1803 A character with byte2 less than min_char_or_byte2 or
1804 greater max_char_or_byte2 is not in the font. */
1805 if (char2b->byte1 == 0
1806 && char2b->byte2 >= font->min_char_or_byte2
1807 && char2b->byte2 <= font->max_char_or_byte2)
1808 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1809 }
1810 else
1811 {
1812 /* If either min_byte1 or max_byte1 are nonzero, both
1813 min_char_or_byte2 and max_char_or_byte2 are less than
1814 256, and the 2-byte character index values corresponding
1815 to the per_char array element N (counting from 0) are:
1816
1817 byte1 = N/D + min_byte1
1818 byte2 = N\D + min_char_or_byte2
1819
1820 where:
1821
1822 D = max_char_or_byte2 - min_char_or_byte2 + 1
1823 / = integer division
1824 \ = integer modulus */
1825 if (char2b->byte1 >= font->min_byte1
1826 && char2b->byte1 <= font->max_byte1
1827 && char2b->byte2 >= font->min_char_or_byte2
1828 && char2b->byte2 <= font->max_char_or_byte2)
1829 {
1830 pcm = (font->per_char
1831 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1832 * (char2b->byte1 - font->min_byte1))
1833 + (char2b->byte2 - font->min_char_or_byte2));
1834 }
1835 }
1836 }
1837 else
1838 {
1839 /* If the per_char pointer is null, all glyphs between the first
1840 and last character indexes inclusive have the same
1841 information, as given by both min_bounds and max_bounds. */
1842 if (char2b->byte2 >= font->min_char_or_byte2
1843 && char2b->byte2 <= font->max_char_or_byte2)
1844 pcm = &font->max_bounds;
1845 }
1846
1847 return ((pcm == NULL
1848 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1849 ? NULL : pcm);
1850}
1851
1852
1853/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1854 the two-byte form of C. Encoding is returned in *CHAR2B. */
1855
1856static INLINE void
1857x_encode_char (c, char2b, font_info)
1858 int c;
1859 XChar2b *char2b;
1860 struct font_info *font_info;
1861{
1862 int charset = CHAR_CHARSET (c);
1863 XFontStruct *font = font_info->font;
1864
1865 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1866 This may be either a program in a special encoder language or a
1867 fixed encoding. */
1868 if (font_info->font_encoder)
1869 {
1870 /* It's a program. */
1871 struct ccl_program *ccl = font_info->font_encoder;
1872
1873 if (CHARSET_DIMENSION (charset) == 1)
1874 {
1875 ccl->reg[0] = charset;
1876 ccl->reg[1] = char2b->byte2;
1877 }
1878 else
1879 {
1880 ccl->reg[0] = charset;
1881 ccl->reg[1] = char2b->byte1;
1882 ccl->reg[2] = char2b->byte2;
1883 }
1884
1885 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1886
1887 /* We assume that MSBs are appropriately set/reset by CCL
1888 program. */
1889 if (font->max_byte1 == 0) /* 1-byte font */
1890 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1891 else
1892 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1893 }
1894 else if (font_info->encoding[charset])
1895 {
1896 /* Fixed encoding scheme. See fontset.h for the meaning of the
1897 encoding numbers. */
1898 int enc = font_info->encoding[charset];
1899
1900 if ((enc == 1 || enc == 2)
1901 && CHARSET_DIMENSION (charset) == 2)
1902 char2b->byte1 |= 0x80;
1903
1904 if (enc == 1 || enc == 3)
1905 char2b->byte2 |= 0x80;
1906
1907 if (enc == 4)
1908 {
1909 int sjis1, sjis2;
1910
1911 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1912 char2b->byte1 = sjis1;
1913 char2b->byte2 = sjis2;
1914 }
1915 }
1916}
1917
1918
1919/* Get face and two-byte form of character C in face FACE_ID on frame
1920 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1921 means we want to display multibyte text. Value is a pointer to a
1922 realized face that is ready for display. */
1923
1924static INLINE struct face *
1925x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1926 struct frame *f;
1927 int c, face_id;
1928 XChar2b *char2b;
1929 int multibyte_p;
1930{
1931 struct face *face = FACE_FROM_ID (f, face_id);
1932
1933 if (!multibyte_p)
1934 {
1935 /* Unibyte case. We don't have to encode, but we have to make
1936 sure to use a face suitable for unibyte. */
1937 char2b->byte1 = 0;
1938 char2b->byte2 = c;
1939 face_id = FACE_FOR_CHAR (f, face, c);
1940 face = FACE_FROM_ID (f, face_id);
1941 }
1942 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1943 {
1944 /* Case of ASCII in a face known to fit ASCII. */
1945 char2b->byte1 = 0;
1946 char2b->byte2 = c;
1947 }
1948 else
1949 {
1950 int c1, c2, charset;
1951
1952 /* Split characters into bytes. If c2 is -1 afterwards, C is
1953 really a one-byte character so that byte1 is zero. */
1954 SPLIT_CHAR (c, charset, c1, c2);
1955 if (c2 > 0)
1956 char2b->byte1 = c1, char2b->byte2 = c2;
1957 else
1958 char2b->byte1 = 0, char2b->byte2 = c1;
1959
1960 /* Maybe encode the character in *CHAR2B. */
1961 if (face->font != NULL)
1962 {
1963 struct font_info *font_info
1964 = FONT_INFO_FROM_ID (f, face->font_info_id);
1965 if (font_info)
1966 x_encode_char (c, char2b, font_info);
1967 }
1968 }
1969
1970 /* Make sure X resources of the face are allocated. */
1971 xassert (face != NULL);
1972 PREPARE_FACE_FOR_DISPLAY (f, face);
1973
1974 return face;
1975}
1976
1977
1978/* Get face and two-byte form of character glyph GLYPH on frame F.
1979 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1980 a pointer to a realized face that is ready for display. */
1981
1982static INLINE struct face *
1983x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1984 struct frame *f;
1985 struct glyph *glyph;
1986 XChar2b *char2b;
1987 int *two_byte_p;
1988{
1989 struct face *face;
1990
1991 xassert (glyph->type == CHAR_GLYPH);
1992 face = FACE_FROM_ID (f, glyph->face_id);
1993
1994 if (two_byte_p)
1995 *two_byte_p = 0;
1996
1997 if (!glyph->multibyte_p)
1998 {
1999 /* Unibyte case. We don't have to encode, but we have to make
2000 sure to use a face suitable for unibyte. */
2001 char2b->byte1 = 0;
2002 char2b->byte2 = glyph->u.ch;
2003 }
2004 else if (glyph->u.ch < 128
2005 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2006 {
2007 /* Case of ASCII in a face known to fit ASCII. */
2008 char2b->byte1 = 0;
2009 char2b->byte2 = glyph->u.ch;
2010 }
2011 else
2012 {
2013 int c1, c2, charset;
2014
2015 /* Split characters into bytes. If c2 is -1 afterwards, C is
2016 really a one-byte character so that byte1 is zero. */
2017 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2018 if (c2 > 0)
2019 char2b->byte1 = c1, char2b->byte2 = c2;
2020 else
2021 char2b->byte1 = 0, char2b->byte2 = c1;
2022
2023 /* Maybe encode the character in *CHAR2B. */
2024 if (charset != CHARSET_ASCII)
2025 {
2026 struct font_info *font_info
2027 = FONT_INFO_FROM_ID (f, face->font_info_id);
2028 if (font_info)
2029 {
2030 x_encode_char (glyph->u.ch, char2b, font_info);
2031 if (two_byte_p)
2032 *two_byte_p
2033 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2034 }
2035 }
2036 }
2037
2038 /* Make sure X resources of the face are allocated. */
2039 xassert (face != NULL);
2040 PREPARE_FACE_FOR_DISPLAY (f, face);
2041 return face;
2042}
2043
2044
2045/* Store one glyph for IT->char_to_display in IT->glyph_row.
2046 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2047
2048static INLINE void
2049x_append_glyph (it)
2050 struct it *it;
2051{
2052 struct glyph *glyph;
2053 enum glyph_row_area area = it->area;
2054
2055 xassert (it->glyph_row);
2056 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2057
2058 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2059 if (glyph < it->glyph_row->glyphs[area + 1])
2060 {
2061 glyph->charpos = CHARPOS (it->position);
2062 glyph->object = it->object;
2063 glyph->pixel_width = it->pixel_width;
2064 glyph->voffset = it->voffset;
2065 glyph->type = CHAR_GLYPH;
2066 glyph->multibyte_p = it->multibyte_p;
2067 glyph->left_box_line_p = it->start_of_box_run_p;
2068 glyph->right_box_line_p = it->end_of_box_run_p;
2069 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2070 || it->phys_descent > it->descent);
2071 glyph->padding_p = 0;
2072 glyph->glyph_not_available_p = it->glyph_not_available_p;
2073 glyph->face_id = it->face_id;
2074 glyph->u.ch = it->char_to_display;
2075 ++it->glyph_row->used[area];
2076 }
2077}
2078
2079/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2080 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2081
2082static INLINE void
2083x_append_composite_glyph (it)
2084 struct it *it;
2085{
2086 struct glyph *glyph;
2087 enum glyph_row_area area = it->area;
2088
2089 xassert (it->glyph_row);
2090
2091 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2092 if (glyph < it->glyph_row->glyphs[area + 1])
2093 {
2094 glyph->charpos = CHARPOS (it->position);
2095 glyph->object = it->object;
2096 glyph->pixel_width = it->pixel_width;
2097 glyph->voffset = it->voffset;
2098 glyph->type = COMPOSITE_GLYPH;
2099 glyph->multibyte_p = it->multibyte_p;
2100 glyph->left_box_line_p = it->start_of_box_run_p;
2101 glyph->right_box_line_p = it->end_of_box_run_p;
2102 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2103 || it->phys_descent > it->descent);
2104 glyph->padding_p = 0;
2105 glyph->glyph_not_available_p = 0;
2106 glyph->face_id = it->face_id;
2107 glyph->u.cmp_id = it->cmp_id;
2108 ++it->glyph_row->used[area];
2109 }
2110}
2111
2112
2113/* Change IT->ascent and IT->height according to the setting of
2114 IT->voffset. */
2115
2116static INLINE void
2117take_vertical_position_into_account (it)
2118 struct it *it;
2119{
2120 if (it->voffset)
2121 {
2122 if (it->voffset < 0)
2123 /* Increase the ascent so that we can display the text higher
2124 in the line. */
2125 it->ascent += abs (it->voffset);
2126 else
2127 /* Increase the descent so that we can display the text lower
2128 in the line. */
2129 it->descent += it->voffset;
2130 }
2131}
2132
2133
2134/* Produce glyphs/get display metrics for the image IT is loaded with.
2135 See the description of struct display_iterator in dispextern.h for
2136 an overview of struct display_iterator. */
2137
2138static void
2139x_produce_image_glyph (it)
2140 struct it *it;
2141{
2142 struct image *img;
2143 struct face *face;
2144
2145 xassert (it->what == IT_IMAGE);
2146
2147 face = FACE_FROM_ID (it->f, it->face_id);
2148 img = IMAGE_FROM_ID (it->f, it->image_id);
2149 xassert (img);
2150
2151 /* Make sure X resources of the face and image are loaded. */
2152 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2153 prepare_image_for_display (it->f, img);
2154
2155 it->ascent = it->phys_ascent = image_ascent (img, face);
83a96b4d
AC
2156 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2157 it->pixel_width = img->width + 2 * img->hmargin;
1a578e9b
AC
2158
2159 it->nglyphs = 1;
2160
2161 if (face->box != FACE_NO_BOX)
2162 {
e0f712ba
AC
2163 if (face->box_line_width > 0)
2164 {
2165 it->ascent += face->box_line_width;
2166 it->descent += face->box_line_width;
2167 }
1a578e9b
AC
2168
2169 if (it->start_of_box_run_p)
e0f712ba 2170 it->pixel_width += abs (face->box_line_width);
1a578e9b 2171 if (it->end_of_box_run_p)
e0f712ba 2172 it->pixel_width += abs (face->box_line_width);
1a578e9b
AC
2173 }
2174
2175 take_vertical_position_into_account (it);
2176
2177 if (it->glyph_row)
2178 {
2179 struct glyph *glyph;
2180 enum glyph_row_area area = it->area;
2181
2182 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2183 if (glyph < it->glyph_row->glyphs[area + 1])
2184 {
2185 glyph->charpos = CHARPOS (it->position);
2186 glyph->object = it->object;
2187 glyph->pixel_width = it->pixel_width;
2188 glyph->voffset = it->voffset;
2189 glyph->type = IMAGE_GLYPH;
2190 glyph->multibyte_p = it->multibyte_p;
2191 glyph->left_box_line_p = it->start_of_box_run_p;
2192 glyph->right_box_line_p = it->end_of_box_run_p;
2193 glyph->overlaps_vertically_p = 0;
2194 glyph->padding_p = 0;
2195 glyph->glyph_not_available_p = 0;
2196 glyph->face_id = it->face_id;
2197 glyph->u.img_id = img->id;
2198 ++it->glyph_row->used[area];
2199 }
2200 }
2201}
2202
2203
2204/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2205 of the glyph, WIDTH and HEIGHT are the width and height of the
2206 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2207 ascent of the glyph (0 <= ASCENT <= 1). */
2208
2209static void
2210x_append_stretch_glyph (it, object, width, height, ascent)
2211 struct it *it;
2212 Lisp_Object object;
2213 int width, height;
2214 double ascent;
2215{
2216 struct glyph *glyph;
2217 enum glyph_row_area area = it->area;
2218
2219 xassert (ascent >= 0 && ascent <= 1);
2220
2221 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2222 if (glyph < it->glyph_row->glyphs[area + 1])
2223 {
2224 glyph->charpos = CHARPOS (it->position);
2225 glyph->object = object;
2226 glyph->pixel_width = width;
2227 glyph->voffset = it->voffset;
2228 glyph->type = STRETCH_GLYPH;
2229 glyph->multibyte_p = it->multibyte_p;
2230 glyph->left_box_line_p = it->start_of_box_run_p;
2231 glyph->right_box_line_p = it->end_of_box_run_p;
2232 glyph->overlaps_vertically_p = 0;
2233 glyph->padding_p = 0;
2234 glyph->glyph_not_available_p = 0;
2235 glyph->face_id = it->face_id;
2236 glyph->u.stretch.ascent = height * ascent;
2237 glyph->u.stretch.height = height;
2238 ++it->glyph_row->used[area];
2239 }
2240}
2241
2242
2243/* Produce a stretch glyph for iterator IT. IT->object is the value
2244 of the glyph property displayed. The value must be a list
2245 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2246 being recognized:
2247
2248 1. `:width WIDTH' specifies that the space should be WIDTH *
2249 canonical char width wide. WIDTH may be an integer or floating
2250 point number.
2251
2252 2. `:relative-width FACTOR' specifies that the width of the stretch
2253 should be computed from the width of the first character having the
2254 `glyph' property, and should be FACTOR times that width.
2255
2256 3. `:align-to HPOS' specifies that the space should be wide enough
2257 to reach HPOS, a value in canonical character units.
2258
2259 Exactly one of the above pairs must be present.
2260
2261 4. `:height HEIGHT' specifies that the height of the stretch produced
2262 should be HEIGHT, measured in canonical character units.
2263
e0f712ba
AC
2264 5. `:relative-height FACTOR' specifies that the height of the
2265 stretch should be FACTOR times the height of the characters having
2266 the glyph property.
1a578e9b
AC
2267
2268 Either none or exactly one of 4 or 5 must be present.
2269
2270 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2271 of the stretch should be used for the ascent of the stretch.
2272 ASCENT must be in the range 0 <= ASCENT <= 100. */
2273
2274#define NUMVAL(X) \
2275 ((INTEGERP (X) || FLOATP (X)) \
2276 ? XFLOATINT (X) \
2277 : - 1)
2278
2279
2280static void
2281x_produce_stretch_glyph (it)
2282 struct it *it;
2283{
2284 /* (space :width WIDTH :height HEIGHT. */
2285#if GLYPH_DEBUG
2286 extern Lisp_Object Qspace;
2287#endif
2288 extern Lisp_Object QCwidth, QCheight, QCascent;
2289 extern Lisp_Object QCrelative_width, QCrelative_height;
2290 extern Lisp_Object QCalign_to;
2291 Lisp_Object prop, plist;
2292 double width = 0, height = 0, ascent = 0;
2293 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2294 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2295
2296 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2297
2298 /* List should start with `space'. */
2299 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2300 plist = XCDR (it->object);
2301
2302 /* Compute the width of the stretch. */
2303 if (prop = Fplist_get (plist, QCwidth),
2304 NUMVAL (prop) > 0)
2305 /* Absolute width `:width WIDTH' specified and valid. */
2306 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2307 else if (prop = Fplist_get (plist, QCrelative_width),
2308 NUMVAL (prop) > 0)
2309 {
2310 /* Relative width `:relative-width FACTOR' specified and valid.
2311 Compute the width of the characters having the `glyph'
2312 property. */
2313 struct it it2;
2314 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2315
2316 it2 = *it;
2317 if (it->multibyte_p)
2318 {
2319 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2320 - IT_BYTEPOS (*it));
2321 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2322 }
2323 else
2324 it2.c = *p, it2.len = 1;
2325
2326 it2.glyph_row = NULL;
2327 it2.what = IT_CHARACTER;
2328 x_produce_glyphs (&it2);
2329 width = NUMVAL (prop) * it2.pixel_width;
2330 }
2331 else if (prop = Fplist_get (plist, QCalign_to),
2332 NUMVAL (prop) > 0)
2333 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2334 else
2335 /* Nothing specified -> width defaults to canonical char width. */
2336 width = CANON_X_UNIT (it->f);
2337
2338 /* Compute height. */
2339 if (prop = Fplist_get (plist, QCheight),
2340 NUMVAL (prop) > 0)
2341 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2342 else if (prop = Fplist_get (plist, QCrelative_height),
2343 NUMVAL (prop) > 0)
2344 height = FONT_HEIGHT (font) * NUMVAL (prop);
2345 else
2346 height = FONT_HEIGHT (font);
2347
2348 /* Compute percentage of height used for ascent. If
2349 `:ascent ASCENT' is present and valid, use that. Otherwise,
2350 derive the ascent from the font in use. */
2351 if (prop = Fplist_get (plist, QCascent),
2352 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2353 ascent = NUMVAL (prop) / 100.0;
2354 else
e0f712ba 2355 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
1a578e9b
AC
2356
2357 if (width <= 0)
2358 width = 1;
2359 if (height <= 0)
2360 height = 1;
2361
2362 if (it->glyph_row)
2363 {
2364 Lisp_Object object = it->stack[it->sp - 1].string;
2365 if (!STRINGP (object))
2366 object = it->w->buffer;
2367 x_append_stretch_glyph (it, object, width, height, ascent);
2368 }
2369
2370 it->pixel_width = width;
2371 it->ascent = it->phys_ascent = height * ascent;
2372 it->descent = it->phys_descent = height - it->ascent;
2373 it->nglyphs = 1;
2374
2375 if (face->box != FACE_NO_BOX)
2376 {
e0f712ba
AC
2377 if (face->box_line_width > 0)
2378 {
2379 it->ascent += face->box_line_width;
2380 it->descent += face->box_line_width;
2381 }
1a578e9b
AC
2382
2383 if (it->start_of_box_run_p)
e0f712ba 2384 it->pixel_width += abs (face->box_line_width);
1a578e9b 2385 if (it->end_of_box_run_p)
e0f712ba 2386 it->pixel_width += abs (face->box_line_width);
1a578e9b
AC
2387 }
2388
2389 take_vertical_position_into_account (it);
2390}
2391
2392/* Return proper value to be used as baseline offset of font that has
2393 ASCENT and DESCENT to draw characters by the font at the vertical
2394 center of the line of frame F.
2395
2396 Here, out task is to find the value of BOFF in the following figure;
2397
2398 -------------------------+-----------+-
2399 -+-+---------+-+ | |
2400 | | | | | |
2401 | | | | F_ASCENT F_HEIGHT
2402 | | | ASCENT | |
2403 HEIGHT | | | | |
2404 | | |-|-+------+-----------|------- baseline
2405 | | | | BOFF | |
2406 | |---------|-+-+ | |
2407 | | | DESCENT | |
2408 -+-+---------+-+ F_DESCENT |
2409 -------------------------+-----------+-
2410
2411 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2412 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2413 DESCENT = FONT->descent
2414 HEIGHT = FONT_HEIGHT (FONT)
2415 F_DESCENT = (F->output_data.x->font->descent
2416 - F->output_data.x->baseline_offset)
2417 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2418*/
2419
e0f712ba
AC
2420#define VCENTER_BASELINE_OFFSET(FONT, F) \
2421 (FONT_DESCENT (FONT) \
2422 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2423 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2424 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
1a578e9b
AC
2425
2426/* Produce glyphs/get display metrics for the display element IT is
2427 loaded with. See the description of struct display_iterator in
2428 dispextern.h for an overview of struct display_iterator. */
2429
e0f712ba 2430static void
1a578e9b
AC
2431x_produce_glyphs (it)
2432 struct it *it;
2433{
2434 it->glyph_not_available_p = 0;
2435
2436 if (it->what == IT_CHARACTER)
2437 {
2438 XChar2b char2b;
2439 XFontStruct *font;
2440 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2441 XCharStruct *pcm;
2442 int font_not_found_p;
2443 struct font_info *font_info;
e0f712ba
AC
2444 int boff; /* baseline offset */
2445 /* We may change it->multibyte_p upon unibyte<->multibyte
2446 conversion. So, save the current value now and restore it
2447 later.
2448
2449 Note: It seems that we don't have to record multibyte_p in
2450 struct glyph because the character code itself tells if or
2451 not the character is multibyte. Thus, in the future, we must
2452 consider eliminating the field `multibyte_p' in the struct
2453 glyph.
2454 */
2455 int saved_multibyte_p = it->multibyte_p;
1a578e9b
AC
2456
2457 /* Maybe translate single-byte characters to multibyte, or the
e0f712ba 2458 other way. */
1a578e9b
AC
2459 it->char_to_display = it->c;
2460 if (!ASCII_BYTE_P (it->c))
e0f712ba
AC
2461 {
2462 if (unibyte_display_via_language_environment
2463 && SINGLE_BYTE_CHAR_P (it->c)
2464 && (it->c >= 0240
2465 || !NILP (Vnonascii_translation_table)))
2466 {
2467 it->char_to_display = unibyte_char_to_multibyte (it->c);
2468 it->multibyte_p = 1;
1a578e9b
AC
2469 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2470 face = FACE_FROM_ID (it->f, it->face_id);
2471 }
2472 else if (!SINGLE_BYTE_CHAR_P (it->c)
2473 && !it->multibyte_p)
2474 {
e0f712ba 2475 it->multibyte_p = 1;
1a578e9b
AC
2476 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2477 face = FACE_FROM_ID (it->f, it->face_id);
2478 }
e0f712ba 2479 }
1a578e9b
AC
2480
2481 /* Get font to use. Encode IT->char_to_display. */
2482 x_get_char_face_and_encoding (it->f, it->char_to_display,
e0f712ba
AC
2483 it->face_id, &char2b,
2484 it->multibyte_p);
1a578e9b
AC
2485 font = face->font;
2486
2487 /* When no suitable font found, use the default font. */
2488 font_not_found_p = font == NULL;
2489 if (font_not_found_p)
2490 {
2491 font = FRAME_FONT (it->f);
2492 boff = it->f->output_data.mac->baseline_offset;
2493 font_info = NULL;
2494 }
2495 else
2496 {
2497 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2498 boff = font_info->baseline_offset;
2499 if (font_info->vertical_centering)
2500 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2501 }
2502
2503 if (it->char_to_display >= ' '
2504 && (!it->multibyte_p || it->char_to_display < 128))
2505 {
2506 /* Either unibyte or ASCII. */
2507 int stretched_p;
2508
2509 it->nglyphs = 1;
2510
e0f712ba
AC
2511 pcm = x_per_char_metric (font, &char2b);
2512 it->ascent = FONT_BASE (font) + boff;
2513 it->descent = FONT_DESCENT (font) - boff;
1a578e9b 2514
e0f712ba
AC
2515 if (pcm)
2516 {
2517 it->phys_ascent = pcm->ascent + boff;
2518 it->phys_descent = pcm->descent - boff;
2519 it->pixel_width = pcm->width;
2520 }
2521 else
2522 {
2523 it->glyph_not_available_p = 1;
2524 it->phys_ascent = FONT_BASE (font) + boff;
2525 it->phys_descent = FONT_DESCENT (font) - boff;
2526 it->pixel_width = FONT_WIDTH (font);
2527 }
2528
1a578e9b
AC
2529 /* If this is a space inside a region of text with
2530 `space-width' property, change its width. */
2531 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2532 if (stretched_p)
2533 it->pixel_width *= XFLOATINT (it->space_width);
2534
2535 /* If face has a box, add the box thickness to the character
2536 height. If character has a box line to the left and/or
2537 right, add the box line width to the character's width. */
2538 if (face->box != FACE_NO_BOX)
2539 {
2540 int thick = face->box_line_width;
2541
e0f712ba
AC
2542 if (thick > 0)
2543 {
2544 it->ascent += thick;
2545 it->descent += thick;
2546 }
2547 else
2548 thick = -thick;
1a578e9b
AC
2549
2550 if (it->start_of_box_run_p)
2551 it->pixel_width += thick;
2552 if (it->end_of_box_run_p)
2553 it->pixel_width += thick;
2554 }
2555
2556 /* If face has an overline, add the height of the overline
2557 (1 pixel) and a 1 pixel margin to the character height. */
2558 if (face->overline_p)
2559 it->ascent += 2;
2560
2561 take_vertical_position_into_account (it);
2562
2563 /* If we have to actually produce glyphs, do it. */
2564 if (it->glyph_row)
2565 {
2566 if (stretched_p)
2567 {
2568 /* Translate a space with a `space-width' property
2569 into a stretch glyph. */
e0f712ba
AC
2570 double ascent = (double) FONT_BASE (font)
2571 / FONT_HEIGHT (font);
1a578e9b
AC
2572 x_append_stretch_glyph (it, it->object, it->pixel_width,
2573 it->ascent + it->descent, ascent);
2574 }
2575 else
2576 x_append_glyph (it);
2577
2578 /* If characters with lbearing or rbearing are displayed
2579 in this line, record that fact in a flag of the
2580 glyph row. This is used to optimize X output code. */
2581 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2582 it->glyph_row->contains_overlapping_glyphs_p = 1;
2583 }
2584 }
2585 else if (it->char_to_display == '\n')
2586 {
2587 /* A newline has no width but we need the height of the line. */
2588 it->pixel_width = 0;
2589 it->nglyphs = 0;
e0f712ba
AC
2590 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2591 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1a578e9b 2592
e0f712ba
AC
2593 if (face->box != FACE_NO_BOX
2594 && face->box_line_width > 0)
1a578e9b 2595 {
e0f712ba
AC
2596 it->ascent += face->box_line_width;
2597 it->descent += face->box_line_width;
1a578e9b
AC
2598 }
2599 }
2600 else if (it->char_to_display == '\t')
2601 {
2602 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2603 int x = it->current_x + it->continuation_lines_width;
2604 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2605
e0f712ba
AC
2606 /* If the distance from the current position to the next tab
2607 stop is less than a canonical character width, use the
2608 tab stop after that. */
2609 if (next_tab_x - x < CANON_X_UNIT (it->f))
2610 next_tab_x += tab_width;
2611
1a578e9b
AC
2612 it->pixel_width = next_tab_x - x;
2613 it->nglyphs = 1;
e0f712ba
AC
2614 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2615 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2616
2617 if (it->glyph_row)
2618 {
2619 double ascent = (double) it->ascent / (it->ascent + it->descent);
2620 x_append_stretch_glyph (it, it->object, it->pixel_width,
2621 it->ascent + it->descent, ascent);
2622 }
2623 }
2624 else
2625 {
2626 /* A multi-byte character. Assume that the display width of the
2627 character is the width of the character multiplied by the
2628 width of the font. */
2629
2630 /* If we found a font, this font should give us the right
2631 metrics. If we didn't find a font, use the frame's
2632 default font and calculate the width of the character
2633 from the charset width; this is what old redisplay code
2634 did. */
2635 pcm = x_per_char_metric (font, &char2b);
2636 if (font_not_found_p || !pcm)
2637 {
2638 int charset = CHAR_CHARSET (it->char_to_display);
2639
2640 it->glyph_not_available_p = 1;
2641 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2642 * CHARSET_WIDTH (charset));
e0f712ba
AC
2643 it->phys_ascent = FONT_BASE (font) + boff;
2644 it->phys_descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2645 }
2646 else
2647 {
2648 it->pixel_width = pcm->width;
e0f712ba
AC
2649 it->phys_ascent = pcm->ascent + boff;
2650 it->phys_descent = pcm->descent - boff;
2651 if (it->glyph_row
2652 && (pcm->lbearing < 0
2653 || pcm->rbearing > pcm->width))
2654 it->glyph_row->contains_overlapping_glyphs_p = 1;
2655 }
2656 it->nglyphs = 1;
2657 it->ascent = FONT_BASE (font) + boff;
2658 it->descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2659 if (face->box != FACE_NO_BOX)
2660 {
2661 int thick = face->box_line_width;
e0f712ba
AC
2662
2663 if (thick > 0)
2664 {
2665 it->ascent += thick;
2666 it->descent += thick;
2667 }
2668 else
2669 thick = - thick;
1a578e9b
AC
2670
2671 if (it->start_of_box_run_p)
2672 it->pixel_width += thick;
2673 if (it->end_of_box_run_p)
2674 it->pixel_width += thick;
2675 }
2676
2677 /* If face has an overline, add the height of the overline
2678 (1 pixel) and a 1 pixel margin to the character height. */
2679 if (face->overline_p)
2680 it->ascent += 2;
2681
2682 take_vertical_position_into_account (it);
2683
2684 if (it->glyph_row)
2685 x_append_glyph (it);
2686 }
e0f712ba 2687 it->multibyte_p = saved_multibyte_p;
1a578e9b
AC
2688 }
2689 else if (it->what == IT_COMPOSITION)
2690 {
2691 /* Note: A composition is represented as one glyph in the
2692 glyph matrix. There are no padding glyphs. */
2693 XChar2b char2b;
2694 XFontStruct *font;
2695 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2696 XCharStruct *pcm;
2697 int font_not_found_p;
2698 struct font_info *font_info;
2699 int boff; /* baseline offset */
2700 struct composition *cmp = composition_table[it->cmp_id];
2701
2702 /* Maybe translate single-byte characters to multibyte. */
2703 it->char_to_display = it->c;
2704 if (unibyte_display_via_language_environment
2705 && SINGLE_BYTE_CHAR_P (it->c)
2706 && (it->c >= 0240
2707 || (it->c >= 0200
2708 && !NILP (Vnonascii_translation_table))))
2709 {
2710 it->char_to_display = unibyte_char_to_multibyte (it->c);
2711 }
e0f712ba 2712
1a578e9b
AC
2713 /* Get face and font to use. Encode IT->char_to_display. */
2714 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2715 face = FACE_FROM_ID (it->f, it->face_id);
2716 x_get_char_face_and_encoding (it->f, it->char_to_display,
2717 it->face_id, &char2b, it->multibyte_p);
2718 font = face->font;
2719
2720 /* When no suitable font found, use the default font. */
2721 font_not_found_p = font == NULL;
2722 if (font_not_found_p)
2723 {
2724 font = FRAME_FONT (it->f);
2725 boff = it->f->output_data.mac->baseline_offset;
2726 font_info = NULL;
2727 }
2728 else
2729 {
2730 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2731 boff = font_info->baseline_offset;
2732 if (font_info->vertical_centering)
2733 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2734 }
2735
2736 /* There are no padding glyphs, so there is only one glyph to
2737 produce for the composition. Important is that pixel_width,
2738 ascent and descent are the values of what is drawn by
2739 draw_glyphs (i.e. the values of the overall glyphs composed). */
2740 it->nglyphs = 1;
2741
2742 /* If we have not yet calculated pixel size data of glyphs of
2743 the composition for the current face font, calculate them
2744 now. Theoretically, we have to check all fonts for the
2745 glyphs, but that requires much time and memory space. So,
2746 here we check only the font of the first glyph. This leads
2747 to incorrect display very rarely, and C-l (recenter) can
2748 correct the display anyway. */
2749 if (cmp->font != (void *) font)
2750 {
2751 /* Ascent and descent of the font of the first character of
2752 this composition (adjusted by baseline offset). Ascent
2753 and descent of overall glyphs should not be less than
2754 them respectively. */
e0f712ba
AC
2755 int font_ascent = FONT_BASE (font) + boff;
2756 int font_descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2757 /* Bounding box of the overall glyphs. */
2758 int leftmost, rightmost, lowest, highest;
2759 int i, width, ascent, descent;
2760
2761 cmp->font = (void *) font;
2762
2763 /* Initialize the bounding box. */
2764 pcm = x_per_char_metric (font, &char2b);
2765 if (pcm)
2766 {
2767 width = pcm->width;
2768 ascent = pcm->ascent;
2769 descent = pcm->descent;
2770 }
2771 else
2772 {
2773 width = FONT_WIDTH (font);
e0f712ba
AC
2774 ascent = FONT_BASE (font);
2775 descent = FONT_DESCENT (font);
1a578e9b
AC
2776 }
2777
2778 rightmost = width;
2779 lowest = - descent + boff;
2780 highest = ascent + boff;
2781 leftmost = 0;
2782
2783 if (font_info
2784 && font_info->default_ascent
2785 && CHAR_TABLE_P (Vuse_default_ascent)
2786 && !NILP (Faref (Vuse_default_ascent,
2787 make_number (it->char_to_display))))
2788 highest = font_info->default_ascent + boff;
2789
2790 /* Draw the first glyph at the normal position. It may be
2791 shifted to right later if some other glyphs are drawn at
2792 the left. */
2793 cmp->offsets[0] = 0;
2794 cmp->offsets[1] = boff;
2795
2796 /* Set cmp->offsets for the remaining glyphs. */
2797 for (i = 1; i < cmp->glyph_len; i++)
2798 {
2799 int left, right, btm, top;
2800 int ch = COMPOSITION_GLYPH (cmp, i);
2801 int face_id = FACE_FOR_CHAR (it->f, face, ch);
e0f712ba 2802
1a578e9b
AC
2803 face = FACE_FROM_ID (it->f, face_id);
2804 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2805 it->multibyte_p);
2806 font = face->font;
2807 if (font == NULL)
2808 {
2809 font = FRAME_FONT (it->f);
2810 boff = it->f->output_data.mac->baseline_offset;
2811 font_info = NULL;
2812 }
2813 else
2814 {
2815 font_info
2816 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2817 boff = font_info->baseline_offset;
2818 if (font_info->vertical_centering)
2819 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2820 }
2821
2822 pcm = x_per_char_metric (font, &char2b);
2823 if (pcm)
2824 {
2825 width = pcm->width;
2826 ascent = pcm->ascent;
2827 descent = pcm->descent;
2828 }
2829 else
2830 {
2831 width = FONT_WIDTH (font);
e0f712ba
AC
2832 ascent = 1;
2833 descent = 0;
1a578e9b
AC
2834 }
2835
2836 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2837 {
2838 /* Relative composition with or without
2839 alternate chars. */
2840 left = (leftmost + rightmost - width) / 2;
2841 btm = - descent + boff;
2842 if (font_info && font_info->relative_compose
2843 && (! CHAR_TABLE_P (Vignore_relative_composition)
2844 || NILP (Faref (Vignore_relative_composition,
2845 make_number (ch)))))
2846 {
2847
2848 if (- descent >= font_info->relative_compose)
2849 /* One extra pixel between two glyphs. */
2850 btm = highest + 1;
2851 else if (ascent <= 0)
2852 /* One extra pixel between two glyphs. */
2853 btm = lowest - 1 - ascent - descent;
2854 }
2855 }
2856 else
2857 {
2858 /* A composition rule is specified by an integer
2859 value that encodes global and new reference
2860 points (GREF and NREF). GREF and NREF are
2861 specified by numbers as below:
2862
2863 0---1---2 -- ascent
2864 | |
2865 | |
2866 | |
2867 9--10--11 -- center
2868 | |
2869 ---3---4---5--- baseline
2870 | |
2871 6---7---8 -- descent
2872 */
2873 int rule = COMPOSITION_RULE (cmp, i);
2874 int gref, nref, grefx, grefy, nrefx, nrefy;
2875
2876 COMPOSITION_DECODE_RULE (rule, gref, nref);
2877 grefx = gref % 3, nrefx = nref % 3;
2878 grefy = gref / 3, nrefy = nref / 3;
2879
2880 left = (leftmost
2881 + grefx * (rightmost - leftmost) / 2
2882 - nrefx * width / 2);
2883 btm = ((grefy == 0 ? highest
2884 : grefy == 1 ? 0
2885 : grefy == 2 ? lowest
2886 : (highest + lowest) / 2)
2887 - (nrefy == 0 ? ascent + descent
2888 : nrefy == 1 ? descent - boff
2889 : nrefy == 2 ? 0
2890 : (ascent + descent) / 2));
2891 }
2892
2893 cmp->offsets[i * 2] = left;
2894 cmp->offsets[i * 2 + 1] = btm + descent;
2895
2896 /* Update the bounding box of the overall glyphs. */
2897 right = left + width;
2898 top = btm + descent + ascent;
2899 if (left < leftmost)
2900 leftmost = left;
2901 if (right > rightmost)
2902 rightmost = right;
2903 if (top > highest)
2904 highest = top;
2905 if (btm < lowest)
2906 lowest = btm;
2907 }
2908
2909 /* If there are glyphs whose x-offsets are negative,
2910 shift all glyphs to the right and make all x-offsets
2911 non-negative. */
2912 if (leftmost < 0)
2913 {
2914 for (i = 0; i < cmp->glyph_len; i++)
2915 cmp->offsets[i * 2] -= leftmost;
2916 rightmost -= leftmost;
2917 }
2918
2919 cmp->pixel_width = rightmost;
2920 cmp->ascent = highest;
2921 cmp->descent = - lowest;
2922 if (cmp->ascent < font_ascent)
2923 cmp->ascent = font_ascent;
2924 if (cmp->descent < font_descent)
2925 cmp->descent = font_descent;
2926 }
2927
2928 it->pixel_width = cmp->pixel_width;
2929 it->ascent = it->phys_ascent = cmp->ascent;
2930 it->descent = it->phys_descent = cmp->descent;
2931
2932 if (face->box != FACE_NO_BOX)
2933 {
2934 int thick = face->box_line_width;
e0f712ba
AC
2935
2936 if (thick > 0)
2937 {
2938 it->ascent += thick;
2939 it->descent += thick;
2940 }
2941 else
2942 thick = - thick;
1a578e9b
AC
2943
2944 if (it->start_of_box_run_p)
2945 it->pixel_width += thick;
2946 if (it->end_of_box_run_p)
2947 it->pixel_width += thick;
2948 }
2949
2950 /* If face has an overline, add the height of the overline
2951 (1 pixel) and a 1 pixel margin to the character height. */
2952 if (face->overline_p)
2953 it->ascent += 2;
2954
2955 take_vertical_position_into_account (it);
2956
2957 if (it->glyph_row)
2958 x_append_composite_glyph (it);
2959 }
2960 else if (it->what == IT_IMAGE)
2961 x_produce_image_glyph (it);
2962 else if (it->what == IT_STRETCH)
2963 x_produce_stretch_glyph (it);
2964
2965 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2966 because this isn't true for images with `:ascent 100'. */
2967 xassert (it->ascent >= 0 && it->descent >= 0);
2968 if (it->area == TEXT_AREA)
2969 it->current_x += it->pixel_width;
e0f712ba 2970
1a578e9b 2971 it->descent += it->extra_line_spacing;
e0f712ba 2972
1a578e9b
AC
2973 it->max_ascent = max (it->max_ascent, it->ascent);
2974 it->max_descent = max (it->max_descent, it->descent);
2975 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2976 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2977}
2978
2979
2980/* Estimate the pixel height of the mode or top line on frame F.
2981 FACE_ID specifies what line's height to estimate. */
2982
2983int
2984x_estimate_mode_line_height (f, face_id)
2985 struct frame *f;
2986 enum face_id face_id;
2987{
e0f712ba 2988 int height = FONT_HEIGHT (FRAME_FONT (f));
1a578e9b
AC
2989
2990 /* This function is called so early when Emacs starts that the face
2991 cache and mode line face are not yet initialized. */
2992 if (FRAME_FACE_CACHE (f))
2993 {
2994 struct face *face = FACE_FROM_ID (f, face_id);
2995 if (face)
e0f712ba
AC
2996 {
2997 if (face->font)
2998 height = FONT_HEIGHT (face->font);
2999 if (face->box_line_width > 0)
3000 height += 2 * face->box_line_width;
3001 }
1a578e9b
AC
3002 }
3003
3004 return height;
3005}
3006
3007\f
3008/***********************************************************************
3009 Glyph display
3010 ***********************************************************************/
3011
3012/* A sequence of glyphs to be drawn in the same face.
3013
3014 This data structure is not really completely X specific, so it
3015 could possibly, at least partially, be useful for other systems. It
3016 is currently not part of the external redisplay interface because
3017 it's not clear what other systems will need. */
3018
3019struct glyph_string
3020{
3021 /* X-origin of the string. */
3022 int x;
3023
3024 /* Y-origin and y-position of the base line of this string. */
3025 int y, ybase;
3026
3027 /* The width of the string, not including a face extension. */
3028 int width;
3029
3030 /* The width of the string, including a face extension. */
3031 int background_width;
3032
3033 /* The height of this string. This is the height of the line this
3034 string is drawn in, and can be different from the height of the
3035 font the string is drawn in. */
3036 int height;
3037
3038 /* Number of pixels this string overwrites in front of its x-origin.
3039 This number is zero if the string has an lbearing >= 0; it is
3040 -lbearing, if the string has an lbearing < 0. */
3041 int left_overhang;
3042
3043 /* Number of pixels this string overwrites past its right-most
3044 nominal x-position, i.e. x + width. Zero if the string's
3045 rbearing is <= its nominal width, rbearing - width otherwise. */
3046 int right_overhang;
3047
3048 /* The frame on which the glyph string is drawn. */
3049 struct frame *f;
3050
3051 /* The window on which the glyph string is drawn. */
3052 struct window *w;
3053
3054 /* X display and window for convenience. */
3055 Display *display;
3056 Window window;
3057
3058 /* The glyph row for which this string was built. It determines the
3059 y-origin and height of the string. */
3060 struct glyph_row *row;
3061
3062 /* The area within row. */
3063 enum glyph_row_area area;
3064
3065 /* Characters to be drawn, and number of characters. */
3066 XChar2b *char2b;
3067 int nchars;
3068
3069 /* A face-override for drawing cursors, mouse face and similar. */
3070 enum draw_glyphs_face hl;
3071
3072 /* Face in which this string is to be drawn. */
3073 struct face *face;
3074
3075 /* Font in which this string is to be drawn. */
3076 XFontStruct *font;
3077
3078 /* Font info for this string. */
3079 struct font_info *font_info;
3080
3081 /* Non-null means this string describes (part of) a composition.
3082 All characters from char2b are drawn composed. */
3083 struct composition *cmp;
3084
3085 /* Index of this glyph string's first character in the glyph
3086 definition of CMP. If this is zero, this glyph string describes
3087 the first character of a composition. */
3088 int gidx;
3089
3090 /* 1 means this glyph strings face has to be drawn to the right end
3091 of the window's drawing area. */
3092 unsigned extends_to_end_of_line_p : 1;
3093
3094 /* 1 means the background of this string has been drawn. */
3095 unsigned background_filled_p : 1;
3096
3097 /* 1 means glyph string must be drawn with 16-bit functions. */
3098 unsigned two_byte_p : 1;
3099
3100 /* 1 means that the original font determined for drawing this glyph
3101 string could not be loaded. The member `font' has been set to
3102 the frame's default font in this case. */
3103 unsigned font_not_found_p : 1;
3104
3105 /* 1 means that the face in which this glyph string is drawn has a
3106 stipple pattern. */
3107 unsigned stippled_p : 1;
3108
3109 /* 1 means only the foreground of this glyph string must be drawn,
3110 and we should use the physical height of the line this glyph
3111 string appears in as clip rect. */
3112 unsigned for_overlaps_p : 1;
3113
3114 /* The GC to use for drawing this glyph string. */
3115 GC gc;
3116
3117 /* A pointer to the first glyph in the string. This glyph
3118 corresponds to char2b[0]. Needed to draw rectangles if
3119 font_not_found_p is 1. */
3120 struct glyph *first_glyph;
3121
3122 /* Image, if any. */
3123 struct image *img;
3124
3125 struct glyph_string *next, *prev;
3126};
3127
3128
3129#if 0
3130
3131static void
3132x_dump_glyph_string (s)
3133 struct glyph_string *s;
3134{
3135 fprintf (stderr, "glyph string\n");
3136 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3137 s->x, s->y, s->width, s->height);
3138 fprintf (stderr, " ybase = %d\n", s->ybase);
3139 fprintf (stderr, " hl = %d\n", s->hl);
3140 fprintf (stderr, " left overhang = %d, right = %d\n",
3141 s->left_overhang, s->right_overhang);
3142 fprintf (stderr, " nchars = %d\n", s->nchars);
3143 fprintf (stderr, " extends to end of line = %d\n",
3144 s->extends_to_end_of_line_p);
3145 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3146 fprintf (stderr, " bg width = %d\n", s->background_width);
3147}
3148
3149#endif /* GLYPH_DEBUG */
3150
3151
3152
3153static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3154 struct glyph_string **,
3155 struct glyph_string *,
3156 struct glyph_string *));
3157static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3158 struct glyph_string **,
3159 struct glyph_string *,
3160 struct glyph_string *));
3161static void x_append_glyph_string P_ ((struct glyph_string **,
3162 struct glyph_string **,
3163 struct glyph_string *));
3164static int x_left_overwritten P_ ((struct glyph_string *));
3165static int x_left_overwriting P_ ((struct glyph_string *));
3166static int x_right_overwritten P_ ((struct glyph_string *));
3167static int x_right_overwriting P_ ((struct glyph_string *));
3168static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3169 int));
3170static void x_init_glyph_string P_ ((struct glyph_string *,
3171 XChar2b *, struct window *,
3172 struct glyph_row *,
3173 enum glyph_row_area, int,
3174 enum draw_glyphs_face));
3175static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3176 enum glyph_row_area, int, int,
e0f712ba 3177 enum draw_glyphs_face, int));
1a578e9b
AC
3178static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3179static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3180static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3181 int));
3182static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3183static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3184static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3185static void x_draw_glyph_string P_ ((struct glyph_string *));
3186static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3187static void x_set_cursor_gc P_ ((struct glyph_string *));
3188static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3189static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3190static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3191 int *, int *));
3192static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
e0f712ba
AC
3193/*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3194 unsigned long *, double, int));*/
1a578e9b
AC
3195static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3196 double, int, unsigned long));
3197static void x_setup_relief_colors P_ ((struct glyph_string *));
3198static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3199static void x_draw_image_relief P_ ((struct glyph_string *));
3200static void x_draw_image_foreground P_ ((struct glyph_string *));
3201static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3202static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3203static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3204 int, int, int));
3205static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
e0f712ba 3206 int, int, int, int, Rect *));
1a578e9b 3207static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
e0f712ba 3208 int, int, int, Rect *));
1a578e9b
AC
3209static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3210 enum glyph_row_area));
3211static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3212 struct glyph_row *,
3213 enum glyph_row_area, int, int));
3214
3215#if GLYPH_DEBUG
3216static void x_check_font P_ ((struct frame *, XFontStruct *));
3217#endif
3218
e0f712ba 3219
1a578e9b
AC
3220/* Append the list of glyph strings with head H and tail T to the list
3221 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3222
3223static INLINE void
3224x_append_glyph_string_lists (head, tail, h, t)
3225 struct glyph_string **head, **tail;
3226 struct glyph_string *h, *t;
3227{
3228 if (h)
3229 {
3230 if (*head)
3231 (*tail)->next = h;
3232 else
3233 *head = h;
3234 h->prev = *tail;
3235 *tail = t;
3236 }
3237}
3238
3239
3240/* Prepend the list of glyph strings with head H and tail T to the
3241 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3242 result. */
3243
3244static INLINE void
3245x_prepend_glyph_string_lists (head, tail, h, t)
3246 struct glyph_string **head, **tail;
3247 struct glyph_string *h, *t;
3248{
3249 if (h)
3250 {
3251 if (*head)
3252 (*head)->prev = t;
3253 else
3254 *tail = t;
3255 t->next = *head;
3256 *head = h;
3257 }
3258}
3259
3260
3261/* Append glyph string S to the list with head *HEAD and tail *TAIL.
3262 Set *HEAD and *TAIL to the resulting list. */
3263
3264static INLINE void
3265x_append_glyph_string (head, tail, s)
3266 struct glyph_string **head, **tail;
3267 struct glyph_string *s;
3268{
3269 s->next = s->prev = NULL;
3270 x_append_glyph_string_lists (head, tail, s, s);
3271}
3272
3273
3274/* Set S->gc to a suitable GC for drawing glyph string S in cursor
3275 face. */
3276
3277static void
3278x_set_cursor_gc (s)
3279 struct glyph_string *s;
3280{
3281 if (s->font == FRAME_FONT (s->f)
3282 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3283 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3284 && !s->cmp)
3285 s->gc = s->f->output_data.mac->cursor_gc;
3286 else
3287 {
3288 /* Cursor on non-default face: must merge. */
3289 XGCValues xgcv;
3290 unsigned long mask;
3291
3292 xgcv.background = s->f->output_data.mac->cursor_pixel;
3293 xgcv.foreground = s->face->background;
3294
3295 /* If the glyph would be invisible, try a different foreground. */
3296 if (xgcv.foreground == xgcv.background)
3297 xgcv.foreground = s->face->foreground;
3298 if (xgcv.foreground == xgcv.background)
3299 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3300 if (xgcv.foreground == xgcv.background)
3301 xgcv.foreground = s->face->foreground;
3302
3303 /* Make sure the cursor is distinct from text in this face. */
3304 if (xgcv.background == s->face->background
3305 && xgcv.foreground == s->face->foreground)
3306 {
3307 xgcv.background = s->face->foreground;
3308 xgcv.foreground = s->face->background;
3309 }
3310
3311 IF_DEBUG (x_check_font (s->f, s->font));
3312 xgcv.font = s->font;
3313 mask = GCForeground | GCBackground | GCFont;
3314
3315 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3316 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3317 mask, &xgcv);
3318 else
3319 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3320 = XCreateGC (s->display, s->window, mask, &xgcv);
3321
3322 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3323 }
3324}
3325
3326
3327/* Set up S->gc of glyph string S for drawing text in mouse face. */
3328
3329static void
3330x_set_mouse_face_gc (s)
3331 struct glyph_string *s;
3332{
3333 int face_id;
3334 struct face *face;
3335
e0f712ba 3336 /* What face has to be used last for the mouse face? */
1a578e9b
AC
3337 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3338 face = FACE_FROM_ID (s->f, face_id);
e0f712ba
AC
3339 if (face == NULL)
3340 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3341
1a578e9b
AC
3342 if (s->first_glyph->type == CHAR_GLYPH)
3343 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3344 else
3345 face_id = FACE_FOR_CHAR (s->f, face, 0);
3346 s->face = FACE_FROM_ID (s->f, face_id);
3347 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3348
3349 /* If font in this face is same as S->font, use it. */
3350 if (s->font == s->face->font)
3351 s->gc = s->face->gc;
3352 else
3353 {
3354 /* Otherwise construct scratch_cursor_gc with values from FACE
3355 but font FONT. */
3356 XGCValues xgcv;
3357 unsigned long mask;
3358
3359 xgcv.background = s->face->background;
3360 xgcv.foreground = s->face->foreground;
3361 IF_DEBUG (x_check_font (s->f, s->font));
3362 xgcv.font = s->font;
3363 mask = GCForeground | GCBackground | GCFont;
3364
3365 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3366 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3367 mask, &xgcv);
3368 else
3369 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3370 = XCreateGC (s->display, s->window, mask, &xgcv);
3371
3372 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3373 }
3374
3375 xassert (s->gc != 0);
3376}
3377
3378
3379/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3380 Faces to use in the mode line have already been computed when the
3381 matrix was built, so there isn't much to do, here. */
3382
3383static INLINE void
3384x_set_mode_line_face_gc (s)
3385 struct glyph_string *s;
3386{
3387 s->gc = s->face->gc;
3388}
3389
3390
3391/* Set S->gc of glyph string S for drawing that glyph string. Set
3392 S->stippled_p to a non-zero value if the face of S has a stipple
3393 pattern. */
3394
3395static INLINE void
3396x_set_glyph_string_gc (s)
3397 struct glyph_string *s;
3398{
3399 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3400
3401 if (s->hl == DRAW_NORMAL_TEXT)
3402 {
3403 s->gc = s->face->gc;
3404 s->stippled_p = s->face->stipple != 0;
3405 }
3406 else if (s->hl == DRAW_INVERSE_VIDEO)
3407 {
3408 x_set_mode_line_face_gc (s);
3409 s->stippled_p = s->face->stipple != 0;
3410 }
3411 else if (s->hl == DRAW_CURSOR)
3412 {
3413 x_set_cursor_gc (s);
3414 s->stippled_p = 0;
3415 }
3416 else if (s->hl == DRAW_MOUSE_FACE)
3417 {
3418 x_set_mouse_face_gc (s);
3419 s->stippled_p = s->face->stipple != 0;
3420 }
3421 else if (s->hl == DRAW_IMAGE_RAISED
3422 || s->hl == DRAW_IMAGE_SUNKEN)
3423 {
3424 s->gc = s->face->gc;
3425 s->stippled_p = s->face->stipple != 0;
3426 }
3427 else
3428 {
3429 s->gc = s->face->gc;
3430 s->stippled_p = s->face->stipple != 0;
3431 }
3432
3433 /* GC must have been set. */
3434 xassert (s->gc != 0);
3435}
3436
3437
3438/* Return in *R the clipping rectangle for glyph string S. */
3439
3440static void
3441x_get_glyph_string_clip_rect (s, r)
3442 struct glyph_string *s;
3443 Rect *r;
3444{
3445 int r_height, r_width;
3446
3447 if (s->row->full_width_p)
3448 {
3449 /* Draw full-width. X coordinates are relative to S->w->left. */
3450 int canon_x = CANON_X_UNIT (s->f);
3451
3452 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3453 r_width = XFASTINT (s->w->width) * canon_x;
3454
3455 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3456 {
3457 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3458 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3459 r->left -= width;
3460 }
3461
3462 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3463
3464 /* Unless displaying a mode or menu bar line, which are always
3465 fully visible, clip to the visible part of the row. */
3466 if (s->w->pseudo_window_p)
3467 r_height = s->row->visible_height;
3468 else
3469 r_height = s->height;
3470 }
3471 else
3472 {
3473 /* This is a text line that may be partially visible. */
3474 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3475 r_width = window_box_width (s->w, s->area);
3476 r_height = s->row->visible_height;
3477 }
3478
1a578e9b
AC
3479 /* If S draws overlapping rows, it's sufficient to use the top and
3480 bottom of the window for clipping because this glyph string
3481 intentionally draws over other lines. */
3482 if (s->for_overlaps_p)
3483 {
3484 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3485 r_height = window_text_bottom_y (s->w) - r->top;
3486 }
e0f712ba
AC
3487 else
3488 {
3489 /* Don't use S->y for clipping because it doesn't take partially
3490 visible lines into account. For example, it can be negative for
3491 partially visible lines at the top of a window. */
3492 if (!s->row->full_width_p
3493 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3494 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3495 else
3496 r->top = max (0, s->row->y);
3497
3498 /* If drawing a tool-bar window, draw it over the internal border
3499 at the top of the window. */
3500 if (s->w == XWINDOW (s->f->tool_bar_window))
3501 r->top -= s->f->output_data.mac->internal_border_width;
3502 }
3503
1a578e9b
AC
3504 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3505
3506 r->bottom = r->top + r_height;
3507 r->right = r->left + r_width;
3508}
3509
3510
3511/* Set clipping for output of glyph string S. S may be part of a mode
3512 line or menu if we don't have X toolkit support. */
3513
3514static INLINE void
3515x_set_glyph_string_clipping (s)
3516 struct glyph_string *s;
3517{
3518 Rect r;
3519 x_get_glyph_string_clip_rect (s, &r);
3520 mac_set_clip_rectangle (s->display, s->window, &r);
3521}
3522
3523
3524/* Compute left and right overhang of glyph string S. If S is a glyph
3525 string for a composition, assume overhangs don't exist. */
3526
3527static INLINE void
3528x_compute_glyph_string_overhangs (s)
3529 struct glyph_string *s;
3530{
3531 if (s->cmp == NULL
3532 && s->first_glyph->type == CHAR_GLYPH)
3533 {
3534 XCharStruct cs;
3535 int direction, font_ascent, font_descent;
3536 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3537 &font_ascent, &font_descent, &cs);
3538 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3539 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3540 }
3541}
3542
3543
3544/* Compute overhangs and x-positions for glyph string S and its
3545 predecessors, or successors. X is the starting x-position for S.
3546 BACKWARD_P non-zero means process predecessors. */
3547
3548static void
3549x_compute_overhangs_and_x (s, x, backward_p)
3550 struct glyph_string *s;
3551 int x;
3552 int backward_p;
3553{
3554 if (backward_p)
3555 {
3556 while (s)
3557 {
3558 x_compute_glyph_string_overhangs (s);
3559 x -= s->width;
3560 s->x = x;
3561 s = s->prev;
3562 }
3563 }
3564 else
3565 {
3566 while (s)
3567 {
3568 x_compute_glyph_string_overhangs (s);
3569 s->x = x;
3570 x += s->width;
3571 s = s->next;
3572 }
3573 }
3574}
3575
3576
3577/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3578 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3579 assumed to be zero. */
3580
3581void
3582x_get_glyph_overhangs (glyph, f, left, right)
3583 struct glyph *glyph;
3584 struct frame *f;
3585 int *left, *right;
3586{
3587 *left = *right = 0;
3588
3589 if (glyph->type == CHAR_GLYPH)
3590 {
3591 XFontStruct *font;
3592 struct face *face;
3593 struct font_info *font_info;
3594 XChar2b char2b;
3595 XCharStruct *pcm;
3596
3597 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3598 font = face->font;
3599 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3600 if (font
3601 && (pcm = x_per_char_metric (font, &char2b)))
3602 {
3603 if (pcm->rbearing > pcm->width)
3604 *right = pcm->rbearing - pcm->width;
3605 if (pcm->lbearing < 0)
3606 *left = -pcm->lbearing;
3607 }
3608 }
3609}
3610
3611
3612/* Return the index of the first glyph preceding glyph string S that
3613 is overwritten by S because of S's left overhang. Value is -1
3614 if no glyphs are overwritten. */
3615
3616static int
3617x_left_overwritten (s)
3618 struct glyph_string *s;
3619{
3620 int k;
3621
3622 if (s->left_overhang)
3623 {
3624 int x = 0, i;
3625 struct glyph *glyphs = s->row->glyphs[s->area];
3626 int first = s->first_glyph - glyphs;
3627
3628 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3629 x -= glyphs[i].pixel_width;
3630
3631 k = i + 1;
3632 }
3633 else
3634 k = -1;
3635
3636 return k;
3637}
3638
3639
3640/* Return the index of the first glyph preceding glyph string S that
3641 is overwriting S because of its right overhang. Value is -1 if no
3642 glyph in front of S overwrites S. */
3643
3644static int
3645x_left_overwriting (s)
3646 struct glyph_string *s;
3647{
3648 int i, k, x;
3649 struct glyph *glyphs = s->row->glyphs[s->area];
3650 int first = s->first_glyph - glyphs;
3651
3652 k = -1;
3653 x = 0;
3654 for (i = first - 1; i >= 0; --i)
3655 {
3656 int left, right;
3657 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3658 if (x + right > 0)
3659 k = i;
3660 x -= glyphs[i].pixel_width;
3661 }
3662
3663 return k;
3664}
3665
3666
3667/* Return the index of the last glyph following glyph string S that is
3668 not overwritten by S because of S's right overhang. Value is -1 if
3669 no such glyph is found. */
3670
3671static int
3672x_right_overwritten (s)
3673 struct glyph_string *s;
3674{
3675 int k = -1;
3676
3677 if (s->right_overhang)
3678 {
3679 int x = 0, i;
3680 struct glyph *glyphs = s->row->glyphs[s->area];
3681 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3682 int end = s->row->used[s->area];
3683
3684 for (i = first; i < end && s->right_overhang > x; ++i)
3685 x += glyphs[i].pixel_width;
3686
3687 k = i;
3688 }
3689
3690 return k;
3691}
3692
3693
3694/* Return the index of the last glyph following glyph string S that
3695 overwrites S because of its left overhang. Value is negative
3696 if no such glyph is found. */
3697
3698static int
3699x_right_overwriting (s)
3700 struct glyph_string *s;
3701{
3702 int i, k, x;
3703 int end = s->row->used[s->area];
3704 struct glyph *glyphs = s->row->glyphs[s->area];
3705 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3706
3707 k = -1;
3708 x = 0;
3709 for (i = first; i < end; ++i)
3710 {
3711 int left, right;
3712 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3713 if (x - left < 0)
3714 k = i;
3715 x += glyphs[i].pixel_width;
3716 }
3717
3718 return k;
3719}
3720
3721
3722/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3723
3724static INLINE void
3725x_clear_glyph_string_rect (s, x, y, w, h)
3726 struct glyph_string *s;
3727 int x, y, w, h;
3728{
3729 XGCValues xgcv;
3730
3731 xgcv.foreground = s->gc->background;
3732 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3733}
3734
3735
3736/* Draw the background of glyph_string S. If S->background_filled_p
3737 is non-zero don't draw it. FORCE_P non-zero means draw the
3738 background even if it wouldn't be drawn normally. This is used
3739 when a string preceding S draws into the background of S, or S
3740 contains the first component of a composition. */
3741
3742static void
3743x_draw_glyph_string_background (s, force_p)
3744 struct glyph_string *s;
3745 int force_p;
3746{
3747 /* Nothing to do if background has already been drawn or if it
3748 shouldn't be drawn in the first place. */
3749 if (!s->background_filled_p)
3750 {
e0f712ba
AC
3751 int box_line_width = max (s->face->box_line_width, 0);
3752
1a578e9b
AC
3753#if 0 /* MAC_TODO: stipple */
3754 if (s->stippled_p)
3755 {
3756 /* Fill background with a stipple pattern. */
3757 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3758 XFillRectangle (s->display, s->window, s->gc, s->x,
e0f712ba 3759 s->y + box_line_width,
1a578e9b 3760 s->background_width,
e0f712ba 3761 s->height - 2 * box_line_width);
1a578e9b
AC
3762 XSetFillStyle (s->display, s->gc, FillSolid);
3763 s->background_filled_p = 1;
3764 }
3765 else
3766#endif
e0f712ba 3767 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1a578e9b
AC
3768 || s->font_not_found_p
3769 || s->extends_to_end_of_line_p
3770 || force_p)
3771 {
e0f712ba 3772 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1a578e9b 3773 s->background_width,
e0f712ba 3774 s->height - 2 * box_line_width);
1a578e9b
AC
3775 s->background_filled_p = 1;
3776 }
3777 }
3778}
3779
3780
3781/* Draw the foreground of glyph string S. */
3782
3783static void
3784x_draw_glyph_string_foreground (s)
3785 struct glyph_string *s;
3786{
3787 int i, x;
3788
3789 /* If first glyph of S has a left box line, start drawing the text
3790 of S to the right of that box line. */
3791 if (s->face->box != FACE_NO_BOX
3792 && s->first_glyph->left_box_line_p)
e0f712ba 3793 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
3794 else
3795 x = s->x;
3796
3797 /* Draw characters of S as rectangles if S's font could not be
3798 loaded. */
3799 if (s->font_not_found_p)
3800 {
3801 for (i = 0; i < s->nchars; ++i)
3802 {
3803 struct glyph *g = s->first_glyph + i;
3804 mac_draw_rectangle (s->display, s->window,
3805 s->gc, x, s->y, g->pixel_width - 1,
3806 s->height - 1);
3807 x += g->pixel_width;
3808 }
3809 }
3810 else
3811 {
3812 char *char1b = (char *) s->char2b;
3813 int boff = s->font_info->baseline_offset;
3814
3815 if (s->font_info->vertical_centering)
3816 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3817
3818 /* If we can use 8-bit functions, condense S->char2b. */
3819 if (!s->two_byte_p)
3820 for (i = 0; i < s->nchars; ++i)
3821 char1b[i] = s->char2b[i].byte2;
3822
3823 /* Draw text with XDrawString if background has already been
3824 filled. Otherwise, use XDrawImageString. (Note that
3825 XDrawImageString is usually faster than XDrawString.) Always
3826 use XDrawImageString when drawing the cursor so that there is
3827 no chance that characters under a box cursor are invisible. */
3828 if (s->for_overlaps_p
3829 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3830 {
3831 /* Draw characters with 16-bit or 8-bit functions. */
3832 if (s->two_byte_p)
3833 XDrawString16 (s->display, s->window, s->gc, x,
3834 s->ybase - boff, s->char2b, s->nchars);
3835 else
3836 XDrawString (s->display, s->window, s->gc, x,
3837 s->ybase - boff, char1b, s->nchars);
3838 }
3839 else
3840 {
3841 if (s->two_byte_p)
3842 XDrawImageString16 (s->display, s->window, s->gc, x,
3843 s->ybase - boff, s->char2b, s->nchars);
3844 else
3845 XDrawImageString (s->display, s->window, s->gc, x,
3846 s->ybase - boff, char1b, s->nchars);
3847 }
3848 }
3849}
3850
3851/* Draw the foreground of composite glyph string S. */
3852
3853static void
3854x_draw_composite_glyph_string_foreground (s)
3855 struct glyph_string *s;
3856{
3857 int i, x;
3858
3859 /* If first glyph of S has a left box line, start drawing the text
3860 of S to the right of that box line. */
3861 if (s->face->box != FACE_NO_BOX
3862 && s->first_glyph->left_box_line_p)
e0f712ba 3863 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
3864 else
3865 x = s->x;
3866
3867 /* S is a glyph string for a composition. S->gidx is the index of
3868 the first character drawn for glyphs of this composition.
3869 S->gidx == 0 means we are drawing the very first character of
3870 this composition. */
3871
3872 /* Draw a rectangle for the composition if the font for the very
3873 first character of the composition could not be loaded. */
3874 if (s->font_not_found_p)
3875 {
3876 if (s->gidx == 0)
3877 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3878 s->width - 1, s->height - 1);
3879 }
3880 else
3881 {
3882 for (i = 0; i < s->nchars; i++, ++s->gidx)
3883 XDrawString16 (s->display, s->window, s->gc,
3884 x + s->cmp->offsets[s->gidx * 2],
3885 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3886 s->char2b + i, 1);
3887 }
3888}
3889
3890
3891#ifdef USE_X_TOOLKIT
3892
3893static struct frame *x_frame_of_widget P_ ((Widget));
3894
3895
3896/* Return the frame on which widget WIDGET is used.. Abort if frame
3897 cannot be determined. */
3898
3899static struct frame *
3900x_frame_of_widget (widget)
3901 Widget widget;
3902{
3903 struct x_display_info *dpyinfo;
3904 Lisp_Object tail;
3905 struct frame *f;
3906
3907 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3908
3909 /* Find the top-level shell of the widget. Note that this function
3910 can be called when the widget is not yet realized, so XtWindow
3911 (widget) == 0. That's the reason we can't simply use
3912 x_any_window_to_frame. */
3913 while (!XtIsTopLevelShell (widget))
3914 widget = XtParent (widget);
3915
3916 /* Look for a frame with that top-level widget. Allocate the color
3917 on that frame to get the right gamma correction value. */
3918 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3919 if (GC_FRAMEP (XCAR (tail))
3920 && (f = XFRAME (XCAR (tail)),
3921 (f->output_data.nothing != 1
3922 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3923 && f->output_data.x->widget == widget)
3924 return f;
3925
3926 abort ();
3927}
3928
3929
3930/* Allocate the color COLOR->pixel on the screen and display of
3931 widget WIDGET in colormap CMAP. If an exact match cannot be
3932 allocated, try the nearest color available. Value is non-zero
3933 if successful. This is called from lwlib. */
3934
3935int
3936x_alloc_nearest_color_for_widget (widget, cmap, color)
3937 Widget widget;
3938 Colormap cmap;
3939 XColor *color;
3940{
3941 struct frame *f = x_frame_of_widget (widget);
3942 return x_alloc_nearest_color (f, cmap, color);
3943}
3944
3945
3946#endif /* USE_X_TOOLKIT */
3947
e0f712ba 3948#if 0 /* MAC_TODO */
1a578e9b
AC
3949
3950/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3951 CMAP. If an exact match can't be allocated, try the nearest color
3952 available. Value is non-zero if successful. Set *COLOR to the
3953 color allocated. */
3954
3955int
3956x_alloc_nearest_color (f, cmap, color)
3957 struct frame *f;
3958 Colormap cmap;
3959 XColor *color;
3960{
3961 Display *display = FRAME_X_DISPLAY (f);
3962 Screen *screen = FRAME_X_SCREEN (f);
3963 int rc;
3964
3965 gamma_correct (f, color);
3966 rc = XAllocColor (display, cmap, color);
3967 if (rc == 0)
3968 {
3969 /* If we got to this point, the colormap is full, so we're going
3970 to try to get the next closest color. The algorithm used is
3971 a least-squares matching, which is what X uses for closest
3972 color matching with StaticColor visuals. */
3973 int nearest, i;
3974 unsigned long nearest_delta = ~0;
3975 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3976 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3977
3978 for (i = 0; i < ncells; ++i)
3979 cells[i].pixel = i;
3980 XQueryColors (display, cmap, cells, ncells);
3981
3982 for (nearest = i = 0; i < ncells; ++i)
3983 {
3984 long dred = (color->red >> 8) - (cells[i].red >> 8);
3985 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3986 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3987 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3988
3989 if (delta < nearest_delta)
3990 {
3991 nearest = i;
3992 nearest_delta = delta;
3993 }
3994 }
3995
3996 color->red = cells[nearest].red;
3997 color->green = cells[nearest].green;
3998 color->blue = cells[nearest].blue;
3999 rc = XAllocColor (display, cmap, color);
4000 }
4001
4002#ifdef DEBUG_X_COLORS
4003 if (rc)
4004 register_color (color->pixel);
4005#endif /* DEBUG_X_COLORS */
4006
4007 return rc;
4008}
4009
4010
4011/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4012 It's necessary to do this instead of just using PIXEL directly to
4013 get color reference counts right. */
4014
4015unsigned long
4016x_copy_color (f, pixel)
4017 struct frame *f;
4018 unsigned long pixel;
4019{
4020 XColor color;
4021
4022 color.pixel = pixel;
4023 BLOCK_INPUT;
4024 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4025 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4026 UNBLOCK_INPUT;
4027#ifdef DEBUG_X_COLORS
4028 register_color (pixel);
4029#endif
4030 return color.pixel;
4031}
4032
4033
4034/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4035 It's necessary to do this instead of just using PIXEL directly to
4036 get color reference counts right. */
4037
4038unsigned long
4039x_copy_dpy_color (dpy, cmap, pixel)
4040 Display *dpy;
4041 Colormap cmap;
4042 unsigned long pixel;
4043{
4044 XColor color;
4045
4046 color.pixel = pixel;
4047 BLOCK_INPUT;
4048 XQueryColor (dpy, cmap, &color);
4049 XAllocColor (dpy, cmap, &color);
4050 UNBLOCK_INPUT;
4051#ifdef DEBUG_X_COLORS
4052 register_color (pixel);
4053#endif
4054 return color.pixel;
4055}
4056
e0f712ba 4057#endif /* MAC_TODO */
1a578e9b
AC
4058
4059/* Allocate a color which is lighter or darker than *COLOR by FACTOR
4060 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4061 If this produces the same color as COLOR, try a color where all RGB
4062 values have DELTA added. Return the allocated color in *COLOR.
4063 DISPLAY is the X display, CMAP is the colormap to operate on.
4064 Value is non-zero if successful. */
4065
4066static int
4067mac_alloc_lighter_color (f, color, factor, delta)
4068 struct frame *f;
4069 unsigned long *color;
4070 double factor;
4071 int delta;
4072{
4073 unsigned long new;
4074
4075 /* Change RGB values by specified FACTOR. Avoid overflow! */
4076 xassert (factor >= 0);
4077 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4078 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4079 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4080 if (new == *color)
4081 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4082 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4083 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4084
4085 /* MAC_TODO: Map to palette and retry with delta if same? */
4086 /* MAC_TODO: Free colors (if using palette)? */
4087
4088 if (new == *color)
4089 return 0;
4090
4091 *color = new;
4092
4093 return 1;
4094}
4095
4096
4097/* Set up the foreground color for drawing relief lines of glyph
4098 string S. RELIEF is a pointer to a struct relief containing the GC
4099 with which lines will be drawn. Use a color that is FACTOR or
4100 DELTA lighter or darker than the relief's background which is found
4101 in S->f->output_data.x->relief_background. If such a color cannot
4102 be allocated, use DEFAULT_PIXEL, instead. */
4103
4104static void
4105x_setup_relief_color (f, relief, factor, delta, default_pixel)
4106 struct frame *f;
4107 struct relief *relief;
4108 double factor;
4109 int delta;
4110 unsigned long default_pixel;
4111{
4112 XGCValues xgcv;
4113 struct mac_output *di = f->output_data.mac;
4114 unsigned long mask = GCForeground;
4115 unsigned long pixel;
4116 unsigned long background = di->relief_background;
4117 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4118
4119 /* MAC_TODO: Free colors (if using palette)? */
4120
4121 /* Allocate new color. */
4122 xgcv.foreground = default_pixel;
4123 pixel = background;
4124 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4125 {
4126 relief->allocated_p = 1;
4127 xgcv.foreground = relief->pixel = pixel;
4128 }
4129
4130 if (relief->gc == 0)
4131 {
4132#if 0 /* MAC_TODO: stipple */
4133 xgcv.stipple = dpyinfo->gray;
4134 mask |= GCStipple;
4135#endif
4136 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4137 }
4138 else
4139 XChangeGC (NULL, relief->gc, mask, &xgcv);
4140}
4141
4142
4143/* Set up colors for the relief lines around glyph string S. */
4144
4145static void
4146x_setup_relief_colors (s)
4147 struct glyph_string *s;
4148{
4149 struct mac_output *di = s->f->output_data.mac;
4150 unsigned long color;
4151
4152 if (s->face->use_box_color_for_shadows_p)
4153 color = s->face->box_color;
4154 else
4155 {
4156 XGCValues xgcv;
4157
4158 /* Get the background color of the face. */
4159 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4160 color = xgcv.background;
4161 }
4162
4163 if (di->white_relief.gc == 0
4164 || color != di->relief_background)
4165 {
4166 di->relief_background = color;
4167 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4168 WHITE_PIX_DEFAULT (s->f));
4169 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4170 BLACK_PIX_DEFAULT (s->f));
4171 }
4172}
4173
4174
4175/* Draw a relief on frame F inside the rectangle given by LEFT_X,
4176 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4177 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4178 relief. LEFT_P non-zero means draw a relief on the left side of
4179 the rectangle. RIGHT_P non-zero means draw a relief on the right
4180 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4181 when drawing. */
4182
4183static void
4184x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4185 raised_p, left_p, right_p, clip_rect)
4186 struct frame *f;
4187 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4188 Rect *clip_rect;
4189{
4190 int i;
4191 GC gc;
4192
4193 if (raised_p)
4194 gc = f->output_data.mac->white_relief.gc;
4195 else
4196 gc = f->output_data.mac->black_relief.gc;
4197 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4198
4199 /* Top. */
4200 for (i = 0; i < width; ++i)
4201 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4202 left_x + i * left_p, top_y + i,
4203 right_x + 1 - i * right_p, top_y + i);
4204
4205 /* Left. */
4206 if (left_p)
4207 for (i = 0; i < width; ++i)
4208 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4209 left_x + i, top_y + i, left_x + i, bottom_y - i);
4210
4211 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4212 if (raised_p)
4213 gc = f->output_data.mac->black_relief.gc;
4214 else
4215 gc = f->output_data.mac->white_relief.gc;
e0f712ba
AC
4216 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4217 clip_rect);
1a578e9b
AC
4218
4219 /* Bottom. */
4220 for (i = 0; i < width; ++i)
4221 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4222 left_x + i * left_p, bottom_y - i,
4223 right_x + 1 - i * right_p, bottom_y - i);
4224
4225 /* Right. */
4226 if (right_p)
4227 for (i = 0; i < width; ++i)
4228 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4229 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4230
4231 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4232}
4233
4234
4235/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4236 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4237 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4238 left side of the rectangle. RIGHT_P non-zero means draw a line
4239 on the right side of the rectangle. CLIP_RECT is the clipping
4240 rectangle to use when drawing. */
4241
4242static void
4243x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4244 left_p, right_p, clip_rect)
4245 struct glyph_string *s;
4246 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4247 Rect *clip_rect;
4248{
4249 XGCValues xgcv;
4250
4251 xgcv.foreground = s->face->box_color;
4252 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4253
4254 /* Top. */
4255 XFillRectangle (s->display, s->window, &xgcv,
4256 left_x, top_y, right_x - left_x, width);
4257
4258 /* Left. */
4259 if (left_p)
4260 XFillRectangle (s->display, s->window, &xgcv,
4261 left_x, top_y, width, bottom_y - top_y);
4262
4263 /* Bottom. */
4264 XFillRectangle (s->display, s->window, &xgcv,
4265 left_x, bottom_y - width, right_x - left_x, width);
4266
4267 /* Right. */
4268 if (right_p)
4269 XFillRectangle (s->display, s->window, &xgcv,
4270 right_x - width, top_y, width, bottom_y - top_y);
4271
4272 mac_reset_clipping (s->display, s->window);
4273}
4274
4275
4276/* Draw a box around glyph string S. */
4277
4278static void
4279x_draw_glyph_string_box (s)
4280 struct glyph_string *s;
4281{
4282 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4283 int left_p, right_p;
4284 struct glyph *last_glyph;
4285 Rect clip_rect;
4286
4287 last_x = window_box_right (s->w, s->area);
4288 if (s->row->full_width_p
4289 && !s->w->pseudo_window_p)
4290 {
3f332ef3 4291 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
1a578e9b
AC
4292 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4293 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4294 }
4295
4296 /* The glyph that may have a right box line. */
4297 last_glyph = (s->cmp || s->img
4298 ? s->first_glyph
4299 : s->first_glyph + s->nchars - 1);
4300
e0f712ba 4301 width = abs (s->face->box_line_width);
1a578e9b
AC
4302 raised_p = s->face->box == FACE_RAISED_BOX;
4303 left_x = s->x;
e0f712ba 4304 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
1a578e9b
AC
4305 ? last_x - 1
4306 : min (last_x, s->x + s->background_width) - 1));
4307 top_y = s->y;
4308 bottom_y = top_y + s->height - 1;
4309
4310 left_p = (s->first_glyph->left_box_line_p
4311 || (s->hl == DRAW_MOUSE_FACE
4312 && (s->prev == NULL
4313 || s->prev->hl != s->hl)));
4314 right_p = (last_glyph->right_box_line_p
4315 || (s->hl == DRAW_MOUSE_FACE
4316 && (s->next == NULL
4317 || s->next->hl != s->hl)));
4318
4319 x_get_glyph_string_clip_rect (s, &clip_rect);
4320
4321 if (s->face->box == FACE_SIMPLE_BOX)
4322 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4323 left_p, right_p, &clip_rect);
4324 else
4325 {
4326 x_setup_relief_colors (s);
4327 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4328 width, raised_p, left_p, right_p, &clip_rect);
4329 }
4330}
4331
4332
4333/* Draw foreground of image glyph string S. */
4334
4335static void
4336x_draw_image_foreground (s)
4337 struct glyph_string *s;
4338{
4339 int x;
4340 int y = s->ybase - image_ascent (s->img, s->face);
4341
4342 /* If first glyph of S has a left box line, start drawing it to the
4343 right of that line. */
4344 if (s->face->box != FACE_NO_BOX
4345 && s->first_glyph->left_box_line_p)
e0f712ba 4346 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
4347 else
4348 x = s->x;
4349
4350 /* If there is a margin around the image, adjust x- and y-position
4351 by that margin. */
83a96b4d
AC
4352 x += s->img->hmargin;
4353 y += s->img->vmargin;
1a578e9b
AC
4354
4355 if (s->img->pixmap)
4356 {
4357#if 0 /* MAC_TODO: image mask */
4358 if (s->img->mask)
4359 {
4360 /* We can't set both a clip mask and use XSetClipRectangles
4361 because the latter also sets a clip mask. We also can't
4362 trust on the shape extension to be available
4363 (XShapeCombineRegion). So, compute the rectangle to draw
4364 manually. */
4365 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4366 | GCFunction);
4367 XGCValues xgcv;
4368 XRectangle clip_rect, image_rect, r;
4369
4370 xgcv.clip_mask = s->img->mask;
4371 xgcv.clip_x_origin = x;
4372 xgcv.clip_y_origin = y;
4373 xgcv.function = GXcopy;
4374 XChangeGC (s->display, s->gc, mask, &xgcv);
4375
4376 x_get_glyph_string_clip_rect (s, &clip_rect);
4377 image_rect.x = x;
4378 image_rect.y = y;
4379 image_rect.width = s->img->width;
4380 image_rect.height = s->img->height;
4381 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4382 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4383 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4384 }
4385 else
e0f712ba 4386#endif /* MAC_TODO */
1a578e9b
AC
4387 {
4388 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4389 0, 0, s->img->width, s->img->height, x, y);
4390
4391 /* When the image has a mask, we can expect that at
4392 least part of a mouse highlight or a block cursor will
4393 be visible. If the image doesn't have a mask, make
4394 a block cursor visible by drawing a rectangle around
4395 the image. I believe it's looking better if we do
4396 nothing here for mouse-face. */
4397 if (s->hl == DRAW_CURSOR)
4398 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4399 s->img->width - 1, s->img->height - 1);
4400 }
4401 }
4402 else
4403 /* Draw a rectangle if image could not be loaded. */
4404 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4405 s->img->width - 1, s->img->height - 1);
4406}
4407
4408
e0f712ba 4409
1a578e9b
AC
4410/* Draw a relief around the image glyph string S. */
4411
4412static void
4413x_draw_image_relief (s)
4414 struct glyph_string *s;
4415{
4416 int x0, y0, x1, y1, thick, raised_p;
4417 Rect r;
4418 int x;
4419 int y = s->ybase - image_ascent (s->img, s->face);
e0f712ba 4420
1a578e9b
AC
4421 /* If first glyph of S has a left box line, start drawing it to the
4422 right of that line. */
4423 if (s->face->box != FACE_NO_BOX
4424 && s->first_glyph->left_box_line_p)
e0f712ba 4425 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
4426 else
4427 x = s->x;
4428
4429 /* If there is a margin around the image, adjust x- and y-position
4430 by that margin. */
83a96b4d
AC
4431 x += s->img->hmargin;
4432 y += s->img->vmargin;
1a578e9b
AC
4433
4434 if (s->hl == DRAW_IMAGE_SUNKEN
4435 || s->hl == DRAW_IMAGE_RAISED)
4436 {
e0f712ba 4437 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1a578e9b
AC
4438 raised_p = s->hl == DRAW_IMAGE_RAISED;
4439 }
4440 else
4441 {
4442 thick = abs (s->img->relief);
4443 raised_p = s->img->relief > 0;
4444 }
4445
4446 x0 = x - thick;
4447 y0 = y - thick;
4448 x1 = x + s->img->width + thick - 1;
4449 y1 = y + s->img->height + thick - 1;
4450
4451 x_setup_relief_colors (s);
4452 x_get_glyph_string_clip_rect (s, &r);
4453 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4454}
4455
4456
4457/* Draw the foreground of image glyph string S to PIXMAP. */
4458
4459static void
4460x_draw_image_foreground_1 (s, pixmap)
4461 struct glyph_string *s;
4462 Pixmap pixmap;
4463{
4464 int x;
4465 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4466
4467 /* If first glyph of S has a left box line, start drawing it to the
4468 right of that line. */
4469 if (s->face->box != FACE_NO_BOX
4470 && s->first_glyph->left_box_line_p)
e0f712ba 4471 x = abs (s->face->box_line_width);
1a578e9b
AC
4472 else
4473 x = 0;
4474
4475 /* If there is a margin around the image, adjust x- and y-position
4476 by that margin. */
83a96b4d
AC
4477 x += s->img->hmargin;
4478 y += s->img->vmargin;
1a578e9b
AC
4479
4480 if (s->img->pixmap)
4481 {
4482#if 0 /* MAC_TODO: image mask */
4483 if (s->img->mask)
4484 {
4485 /* We can't set both a clip mask and use XSetClipRectangles
4486 because the latter also sets a clip mask. We also can't
4487 trust on the shape extension to be available
4488 (XShapeCombineRegion). So, compute the rectangle to draw
4489 manually. */
4490 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4491 | GCFunction);
4492 XGCValues xgcv;
4493
4494 xgcv.clip_mask = s->img->mask;
4495 xgcv.clip_x_origin = x;
4496 xgcv.clip_y_origin = y;
4497 xgcv.function = GXcopy;
4498 XChangeGC (s->display, s->gc, mask, &xgcv);
4499
4500 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4501 0, 0, s->img->width, s->img->height, x, y);
4502 XSetClipMask (s->display, s->gc, None);
4503 }
4504 else
e0f712ba 4505#endif /* MAC_TODO */
1a578e9b
AC
4506 {
4507 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4508 0, 0, s->img->width, s->img->height, x, y);
4509
4510 /* When the image has a mask, we can expect that at
4511 least part of a mouse highlight or a block cursor will
4512 be visible. If the image doesn't have a mask, make
4513 a block cursor visible by drawing a rectangle around
4514 the image. I believe it's looking better if we do
4515 nothing here for mouse-face. */
4516 if (s->hl == DRAW_CURSOR)
4517 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4518 s->img->width - 1, s->img->height - 1);
4519 }
4520 }
4521 else
4522 /* Draw a rectangle if image could not be loaded. */
4523 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4524 s->img->width - 1, s->img->height - 1);
4525}
4526
4527
4528/* Draw part of the background of glyph string S. X, Y, W, and H
4529 give the rectangle to draw. */
4530
4531static void
4532x_draw_glyph_string_bg_rect (s, x, y, w, h)
4533 struct glyph_string *s;
4534 int x, y, w, h;
4535{
4536#if 0 /* MAC_TODO: stipple */
4537 if (s->stippled_p)
4538 {
4539 /* Fill background with a stipple pattern. */
4540 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4541 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4542 XSetFillStyle (s->display, s->gc, FillSolid);
4543 }
4544 else
e0f712ba 4545#endif /* MAC_TODO */
1a578e9b
AC
4546 x_clear_glyph_string_rect (s, x, y, w, h);
4547}
4548
4549
4550/* Draw image glyph string S.
4551
4552 s->y
4553 s->x +-------------------------
4554 | s->face->box
4555 |
4556 | +-------------------------
83a96b4d 4557 | | s->img->vmargin
1a578e9b
AC
4558 | |
4559 | | +-------------------
4560 | | | the image
4561
4562 */
4563
4564static void
4565x_draw_image_glyph_string (s)
4566 struct glyph_string *s;
4567{
4568 int x, y;
e0f712ba
AC
4569 int box_line_hwidth = abs (s->face->box_line_width);
4570 int box_line_vwidth = max (s->face->box_line_width, 0);
1a578e9b
AC
4571 int height;
4572 Pixmap pixmap = 0;
4573
e0f712ba 4574 height = s->height - 2 * box_line_vwidth;
1a578e9b
AC
4575
4576 /* Fill background with face under the image. Do it only if row is
4577 taller than image or if image has a clip mask to reduce
4578 flickering. */
4579 s->stippled_p = s->face->stipple != 0;
4580 if (height > s->img->height
83a96b4d 4581 || s->img->hmargin
e0f712ba
AC
4582 || s->img->vmargin
4583#if 0 /* TODO: image mask */
1a578e9b
AC
4584 || s->img->mask
4585#endif
4586 || s->img->pixmap == 0
4587 || s->width != s->background_width)
4588 {
e0f712ba
AC
4589 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4590 x = s->x + box_line_hwidth;
1a578e9b
AC
4591 else
4592 x = s->x;
4593
e0f712ba
AC
4594 y = s->y + box_line_vwidth;
4595#if 0 /* TODO: image mask */
1a578e9b
AC
4596 if (s->img->mask)
4597 {
e0f712ba
AC
4598 /* Create a pixmap as large as the glyph string. Fill it
4599 with the background color. Copy the image to it, using
4600 its mask. Copy the temporary pixmap to the display. */
1a578e9b
AC
4601 Screen *screen = FRAME_X_SCREEN (s->f);
4602 int depth = DefaultDepthOfScreen (screen);
4603
4604 /* Create a pixmap as large as the glyph string. */
4605 pixmap = XCreatePixmap (s->display, s->window,
4606 s->background_width,
4607 s->height, depth);
4608
4609 /* Don't clip in the following because we're working on the
4610 pixmap. */
4611 XSetClipMask (s->display, s->gc, None);
4612
4613 /* Fill the pixmap with the background color/stipple. */
4614 if (s->stippled_p)
4615 {
4616 /* Fill background with a stipple pattern. */
4617 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4618 XFillRectangle (s->display, pixmap, s->gc,
4619 0, 0, s->background_width, s->height);
4620 XSetFillStyle (s->display, s->gc, FillSolid);
4621 }
4622 else
4623 {
4624 XGCValues xgcv;
4625 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4626 &xgcv);
4627 XSetForeground (s->display, s->gc, xgcv.background);
4628 XFillRectangle (s->display, pixmap, s->gc,
4629 0, 0, s->background_width, s->height);
4630 XSetForeground (s->display, s->gc, xgcv.foreground);
4631 }
4632 }
4633 else
4634#endif
1a578e9b
AC
4635 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4636
4637 s->background_filled_p = 1;
4638 }
4639
4640 /* Draw the foreground. */
4641 if (pixmap != 0)
4642 {
4643 x_draw_image_foreground_1 (s, pixmap);
4644 x_set_glyph_string_clipping (s);
4645 mac_copy_area (s->display, pixmap, s->window, s->gc,
4646 0, 0, s->background_width, s->height, s->x, s->y);
e0f712ba 4647 mac_reset_clipping (s->display, s->window);
1a578e9b
AC
4648 XFreePixmap (s->display, pixmap);
4649 }
4650 else
4651 x_draw_image_foreground (s);
4652
4653 /* If we must draw a relief around the image, do it. */
4654 if (s->img->relief
4655 || s->hl == DRAW_IMAGE_RAISED
4656 || s->hl == DRAW_IMAGE_SUNKEN)
4657 x_draw_image_relief (s);
4658}
4659
4660
4661/* Draw stretch glyph string S. */
4662
4663static void
4664x_draw_stretch_glyph_string (s)
4665 struct glyph_string *s;
4666{
4667 xassert (s->first_glyph->type == STRETCH_GLYPH);
4668 s->stippled_p = s->face->stipple != 0;
4669
4670 if (s->hl == DRAW_CURSOR
4671 && !x_stretch_cursor_p)
4672 {
4673 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4674 as wide as the stretch glyph. */
4675 int width = min (CANON_X_UNIT (s->f), s->background_width);
4676
4677 /* Draw cursor. */
4678 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4679
4680 /* Clear rest using the GC of the original non-cursor face. */
4681 if (width < s->background_width)
4682 {
4683 GC gc = s->face->gc;
4684 int x = s->x + width, y = s->y;
4685 int w = s->background_width - width, h = s->height;
4686 Rect r;
4687
e0f712ba
AC
4688 if (s->row->mouse_face_p
4689 && cursor_in_mouse_face_p (s->w))
4690 {
4691 x_set_mouse_face_gc (s);
4692 gc = s->gc;
4693 }
4694 else
4695 gc = s->face->gc;
4696
1a578e9b
AC
4697 x_get_glyph_string_clip_rect (s, &r);
4698 mac_set_clip_rectangle (s->display, s->window, &r);
4699
4700#if 0 /* MAC_TODO: stipple */
4701 if (s->face->stipple)
4702 {
4703 /* Fill background with a stipple pattern. */
4704 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4705 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4706 XSetFillStyle (s->display, gc, FillSolid);
4707 }
4708 else
e0f712ba 4709#endif /* MAC_TODO */
1a578e9b
AC
4710 {
4711 XGCValues xgcv;
4712 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4713 XSetForeground (s->display, gc, xgcv.background);
4714 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4715 XSetForeground (s->display, gc, xgcv.foreground);
4716 }
e0f712ba
AC
4717
4718 mac_reset_clipping (s->display, s->window);
1a578e9b
AC
4719 }
4720 }
e0f712ba 4721 else if (!s->background_filled_p)
1a578e9b
AC
4722 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4723 s->height);
4724
4725 s->background_filled_p = 1;
4726}
4727
4728
4729/* Draw glyph string S. */
4730
4731static void
4732x_draw_glyph_string (s)
4733 struct glyph_string *s;
4734{
e0f712ba
AC
4735 int relief_drawn_p = 0;
4736
1a578e9b
AC
4737 /* If S draws into the background of its successor, draw the
4738 background of the successor first so that S can draw into it.
4739 This makes S->next use XDrawString instead of XDrawImageString. */
4740 if (s->next && s->right_overhang && !s->for_overlaps_p)
4741 {
4742 xassert (s->next->img == NULL);
4743 x_set_glyph_string_gc (s->next);
4744 x_set_glyph_string_clipping (s->next);
4745 x_draw_glyph_string_background (s->next, 1);
e0f712ba 4746
1a578e9b
AC
4747 }
4748
4749 /* Set up S->gc, set clipping and draw S. */
4750 x_set_glyph_string_gc (s);
e0f712ba
AC
4751
4752 /* Draw relief (if any) in advance for char/composition so that the
4753 glyph string can be drawn over it. */
4754 if (!s->for_overlaps_p
4755 && s->face->box != FACE_NO_BOX
4756 && (s->first_glyph->type == CHAR_GLYPH
4757 || s->first_glyph->type == COMPOSITE_GLYPH))
4758
4759 {
4760 x_set_glyph_string_clipping (s);
4761 x_draw_glyph_string_background (s, 1);
4762 x_draw_glyph_string_box (s);
4763 x_set_glyph_string_clipping (s);
4764 relief_drawn_p = 1;
4765 }
4766 else
4767 x_set_glyph_string_clipping (s);
1a578e9b
AC
4768
4769 switch (s->first_glyph->type)
4770 {
4771 case IMAGE_GLYPH:
4772 x_draw_image_glyph_string (s);
4773 break;
4774
4775 case STRETCH_GLYPH:
4776 x_draw_stretch_glyph_string (s);
4777 break;
4778
4779 case CHAR_GLYPH:
4780 if (s->for_overlaps_p)
4781 s->background_filled_p = 1;
4782 else
e0f712ba 4783 x_draw_glyph_string_background (s, 0);
1a578e9b
AC
4784 x_draw_glyph_string_foreground (s);
4785 break;
4786
4787 case COMPOSITE_GLYPH:
4788 if (s->for_overlaps_p || s->gidx > 0)
4789 s->background_filled_p = 1;
4790 else
4791 x_draw_glyph_string_background (s, 1);
4792 x_draw_composite_glyph_string_foreground (s);
4793 break;
4794
4795 default:
4796 abort ();
4797 }
4798
4799 if (!s->for_overlaps_p)
4800 {
4801 /* Draw underline. */
4802 if (s->face->underline_p)
4803 {
4804 unsigned long h = 1;
4805 unsigned long dy = s->height - h;
4806
4807 if (s->face->underline_defaulted_p)
4808 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4809 s->width, h);
4810 else
4811 {
4812 XGCValues xgcv;
4813 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4814 XSetForeground (s->display, s->gc, s->face->underline_color);
4815 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4816 s->width, h);
4817 XSetForeground (s->display, s->gc, xgcv.foreground);
4818 }
4819 }
4820
4821 /* Draw overline. */
4822 if (s->face->overline_p)
4823 {
4824 unsigned long dy = 0, h = 1;
4825
4826 if (s->face->overline_color_defaulted_p)
4827 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4828 s->width, h);
4829 else
4830 {
4831 XGCValues xgcv;
4832 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4833 XSetForeground (s->display, s->gc, s->face->overline_color);
4834 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4835 s->width, h);
4836 XSetForeground (s->display, s->gc, xgcv.foreground);
4837 }
4838 }
4839
4840 /* Draw strike-through. */
4841 if (s->face->strike_through_p)
4842 {
4843 unsigned long h = 1;
4844 unsigned long dy = (s->height - h) / 2;
4845
4846 if (s->face->strike_through_color_defaulted_p)
4847 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4848 s->width, h);
4849 else
4850 {
4851 XGCValues xgcv;
4852 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4853 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4854 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4855 s->width, h);
4856 XSetForeground (s->display, s->gc, xgcv.foreground);
4857 }
4858 }
4859
4860 /* Draw relief. */
e0f712ba
AC
4861 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4862 x_draw_glyph_string_box (s);
1a578e9b 4863 }
e0f712ba 4864
1a578e9b
AC
4865 /* Reset clipping. */
4866 mac_reset_clipping (s->display, s->window);
4867}
4868
4869
4870static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4871 struct face **, int));
4872
4873
4874/* Fill glyph string S with composition components specified by S->cmp.
4875
4876 FACES is an array of faces for all components of this composition.
4877 S->gidx is the index of the first component for S.
4878 OVERLAPS_P non-zero means S should draw the foreground only, and
4879 use its physical height for clipping.
4880
4881 Value is the index of a component not in S. */
4882
4883static int
4884x_fill_composite_glyph_string (s, faces, overlaps_p)
4885 struct glyph_string *s;
4886 struct face **faces;
4887 int overlaps_p;
4888{
4889 int i;
4890
4891 xassert (s);
4892
4893 s->for_overlaps_p = overlaps_p;
e0f712ba 4894
1a578e9b
AC
4895 s->face = faces[s->gidx];
4896 s->font = s->face->font;
4897 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4898
4899 /* For all glyphs of this composition, starting at the offset
4900 S->gidx, until we reach the end of the definition or encounter a
4901 glyph that requires the different face, add it to S. */
4902 ++s->nchars;
4903 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4904 ++s->nchars;
4905
4906 /* All glyph strings for the same composition has the same width,
4907 i.e. the width set for the first component of the composition. */
4908
4909 s->width = s->first_glyph->pixel_width;
4910
4911 /* If the specified font could not be loaded, use the frame's
4912 default font, but record the fact that we couldn't load it in
4913 the glyph string so that we can draw rectangles for the
4914 characters of the glyph string. */
4915 if (s->font == NULL)
4916 {
4917 s->font_not_found_p = 1;
4918 s->font = FRAME_FONT (s->f);
4919 }
4920
4921 /* Adjust base line for subscript/superscript text. */
4922 s->ybase += s->first_glyph->voffset;
4923
4924 xassert (s->face && s->face->gc);
4925
4926 /* This glyph string must always be drawn with 16-bit functions. */
4927 s->two_byte_p = 1;
4928
4929 return s->gidx + s->nchars;
4930}
4931
4932
4933/* Fill glyph string S from a sequence of character glyphs.
4934
4935 FACE_ID is the face id of the string. START is the index of the
4936 first glyph to consider, END is the index of the last + 1.
4937 OVERLAPS_P non-zero means S should draw the foreground only, and
4938 use its physical height for clipping.
4939
4940 Value is the index of the first glyph not in S. */
4941
4942static int
4943x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4944 struct glyph_string *s;
4945 int face_id;
4946 int start, end, overlaps_p;
4947{
4948 struct glyph *glyph, *last;
4949 int voffset;
4950 int glyph_not_available_p;
e0f712ba 4951
1a578e9b
AC
4952 xassert (s->f == XFRAME (s->w->frame));
4953 xassert (s->nchars == 0);
4954 xassert (start >= 0 && end > start);
4955
e0f712ba 4956 s->for_overlaps_p = overlaps_p;
1a578e9b
AC
4957 glyph = s->row->glyphs[s->area] + start;
4958 last = s->row->glyphs[s->area] + end;
4959 voffset = glyph->voffset;
e0f712ba 4960
1a578e9b
AC
4961 glyph_not_available_p = glyph->glyph_not_available_p;
4962
4963 while (glyph < last
4964 && glyph->type == CHAR_GLYPH
4965 && glyph->voffset == voffset
4966 /* Same face id implies same font, nowadays. */
4967 && glyph->face_id == face_id
e0f712ba 4968 && glyph->glyph_not_available_p == glyph_not_available_p)
1a578e9b
AC
4969 {
4970 int two_byte_p;
4971
4972 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4973 s->char2b + s->nchars,
e0f712ba 4974 &two_byte_p);
1a578e9b
AC
4975 s->two_byte_p = two_byte_p;
4976 ++s->nchars;
4977 xassert (s->nchars <= end - start);
4978 s->width += glyph->pixel_width;
4979 ++glyph;
4980 }
4981
4982 s->font = s->face->font;
4983 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4984
4985 /* If the specified font could not be loaded, use the frame's font,
4986 but record the fact that we couldn't load it in
4987 S->font_not_found_p so that we can draw rectangles for the
4988 characters of the glyph string. */
4989 if (s->font == NULL || glyph_not_available_p)
4990 {
4991 s->font_not_found_p = 1;
4992 s->font = FRAME_FONT (s->f);
4993 }
4994
4995 /* Adjust base line for subscript/superscript text. */
4996 s->ybase += voffset;
e0f712ba 4997
1a578e9b
AC
4998 xassert (s->face && s->face->gc);
4999 return glyph - s->row->glyphs[s->area];
5000}
5001
5002
5003/* Fill glyph string S from image glyph S->first_glyph. */
5004
5005static void
5006x_fill_image_glyph_string (s)
5007 struct glyph_string *s;
5008{
5009 xassert (s->first_glyph->type == IMAGE_GLYPH);
5010 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5011 xassert (s->img);
5012 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5013 s->font = s->face->font;
5014 s->width = s->first_glyph->pixel_width;
5015
5016 /* Adjust base line for subscript/superscript text. */
5017 s->ybase += s->first_glyph->voffset;
5018}
5019
5020
5021/* Fill glyph string S from a sequence of stretch glyphs.
5022
5023 ROW is the glyph row in which the glyphs are found, AREA is the
5024 area within the row. START is the index of the first glyph to
5025 consider, END is the index of the last + 1.
5026
5027 Value is the index of the first glyph not in S. */
5028
5029static int
5030x_fill_stretch_glyph_string (s, row, area, start, end)
5031 struct glyph_string *s;
5032 struct glyph_row *row;
5033 enum glyph_row_area area;
5034 int start, end;
5035{
5036 struct glyph *glyph, *last;
5037 int voffset, face_id;
5038
5039 xassert (s->first_glyph->type == STRETCH_GLYPH);
5040
5041 glyph = s->row->glyphs[s->area] + start;
5042 last = s->row->glyphs[s->area] + end;
5043 face_id = glyph->face_id;
5044 s->face = FACE_FROM_ID (s->f, face_id);
5045 s->font = s->face->font;
5046 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5047 s->width = glyph->pixel_width;
5048 voffset = glyph->voffset;
5049
5050 for (++glyph;
5051 (glyph < last
5052 && glyph->type == STRETCH_GLYPH
5053 && glyph->voffset == voffset
5054 && glyph->face_id == face_id);
5055 ++glyph)
5056 s->width += glyph->pixel_width;
5057
5058 /* Adjust base line for subscript/superscript text. */
5059 s->ybase += voffset;
5060
e0f712ba 5061 xassert (s->face);
1a578e9b
AC
5062 return glyph - s->row->glyphs[s->area];
5063}
5064
5065
5066/* Initialize glyph string S. CHAR2B is a suitably allocated vector
5067 of XChar2b structures for S; it can't be allocated in
5068 x_init_glyph_string because it must be allocated via `alloca'. W
5069 is the window on which S is drawn. ROW and AREA are the glyph row
5070 and area within the row from which S is constructed. START is the
5071 index of the first glyph structure covered by S. HL is a
5072 face-override for drawing S. */
5073
5074static void
5075x_init_glyph_string (s, char2b, w, row, area, start, hl)
5076 struct glyph_string *s;
5077 XChar2b *char2b;
5078 struct window *w;
5079 struct glyph_row *row;
5080 enum glyph_row_area area;
5081 int start;
5082 enum draw_glyphs_face hl;
5083{
5084 bzero (s, sizeof *s);
5085 s->w = w;
5086 s->f = XFRAME (w->frame);
5087 s->display = FRAME_MAC_DISPLAY (s->f);
5088 s->window = FRAME_MAC_WINDOW (s->f);
5089 s->char2b = char2b;
5090 s->hl = hl;
5091 s->row = row;
5092 s->area = area;
5093 s->first_glyph = row->glyphs[area] + start;
5094 s->height = row->height;
5095 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5096
5097 /* Display the internal border below the tool-bar window. */
5098 if (s->w == XWINDOW (s->f->tool_bar_window))
5099 s->y -= s->f->output_data.mac->internal_border_width;
5100
5101 s->ybase = s->y + row->ascent;
5102}
5103
5104
5105/* Set background width of glyph string S. START is the index of the
5106 first glyph following S. LAST_X is the right-most x-position + 1
5107 in the drawing area. */
5108
5109static INLINE void
5110x_set_glyph_string_background_width (s, start, last_x)
5111 struct glyph_string *s;
5112 int start;
5113 int last_x;
5114{
5115 /* If the face of this glyph string has to be drawn to the end of
5116 the drawing area, set S->extends_to_end_of_line_p. */
5117 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
5118
5119 if (start == s->row->used[s->area]
e0f712ba
AC
5120 && s->area == TEXT_AREA
5121 && ((s->hl == DRAW_NORMAL_TEXT
5122 && (s->row->fill_line_p
5123 || s->face->background != default_face->background
5124 || s->face->stipple != default_face->stipple
5125 || s->row->mouse_face_p))
5126 || s->hl == DRAW_MOUSE_FACE
5127 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5128 && s->row->fill_line_p)))
1a578e9b
AC
5129 s->extends_to_end_of_line_p = 1;
5130
5131 /* If S extends its face to the end of the line, set its
5132 background_width to the distance to the right edge of the drawing
5133 area. */
5134 if (s->extends_to_end_of_line_p)
5135 s->background_width = last_x - s->x + 1;
5136 else
5137 s->background_width = s->width;
5138}
5139
5140
5141/* Add a glyph string for a stretch glyph to the list of strings
5142 between HEAD and TAIL. START is the index of the stretch glyph in
5143 row area AREA of glyph row ROW. END is the index of the last glyph
5144 in that glyph row area. X is the current output position assigned
5145 to the new glyph string constructed. HL overrides that face of the
5146 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5147 is the right-most x-position of the drawing area. */
5148
5149/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5150 and below -- keep them on one line. */
5151#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5152 do \
5153 { \
5154 s = (struct glyph_string *) alloca (sizeof *s); \
5155 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5156 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5157 x_append_glyph_string (&HEAD, &TAIL, s); \
5158 s->x = (X); \
5159 } \
5160 while (0)
5161
5162
5163/* Add a glyph string for an image glyph to the list of strings
5164 between HEAD and TAIL. START is the index of the image glyph in
5165 row area AREA of glyph row ROW. END is the index of the last glyph
5166 in that glyph row area. X is the current output position assigned
5167 to the new glyph string constructed. HL overrides that face of the
5168 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5169 is the right-most x-position of the drawing area. */
5170
5171#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5172 do \
5173 { \
5174 s = (struct glyph_string *) alloca (sizeof *s); \
5175 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5176 x_fill_image_glyph_string (s); \
5177 x_append_glyph_string (&HEAD, &TAIL, s); \
5178 ++START; \
5179 s->x = (X); \
5180 } \
5181 while (0)
5182
5183
5184/* Add a glyph string for a sequence of character glyphs to the list
5185 of strings between HEAD and TAIL. START is the index of the first
5186 glyph in row area AREA of glyph row ROW that is part of the new
5187 glyph string. END is the index of the last glyph in that glyph row
5188 area. X is the current output position assigned to the new glyph
5189 string constructed. HL overrides that face of the glyph; e.g. it
5190 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5191 right-most x-position of the drawing area. */
5192
5193#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5194 do \
5195 { \
5196 int c, face_id; \
5197 XChar2b *char2b; \
5198 \
5199 c = (ROW)->glyphs[AREA][START].u.ch; \
5200 face_id = (ROW)->glyphs[AREA][START].face_id; \
5201 \
5202 s = (struct glyph_string *) alloca (sizeof *s); \
5203 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5204 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5205 x_append_glyph_string (&HEAD, &TAIL, s); \
5206 s->x = (X); \
5207 START = x_fill_glyph_string (s, face_id, START, END, \
5208 OVERLAPS_P); \
5209 } \
5210 while (0)
5211
5212
5213/* Add a glyph string for a composite sequence to the list of strings
5214 between HEAD and TAIL. START is the index of the first glyph in
5215 row area AREA of glyph row ROW that is part of the new glyph
5216 string. END is the index of the last glyph in that glyph row area.
5217 X is the current output position assigned to the new glyph string
5218 constructed. HL overrides that face of the glyph; e.g. it is
5219 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5220 x-position of the drawing area. */
5221
5222#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5223 do { \
5224 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5225 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5226 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5227 struct composition *cmp = composition_table[cmp_id]; \
5228 int glyph_len = cmp->glyph_len; \
5229 XChar2b *char2b; \
5230 struct face **faces; \
5231 struct glyph_string *first_s = NULL; \
5232 int n; \
5233 \
5234 base_face = base_face->ascii_face; \
5235 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5236 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5237 /* At first, fill in `char2b' and `faces'. */ \
5238 for (n = 0; n < glyph_len; n++) \
5239 { \
5240 int c = COMPOSITION_GLYPH (cmp, n); \
5241 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5242 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5243 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5244 this_face_id, char2b + n, 1); \
5245 } \
5246 \
5247 /* Make glyph_strings for each glyph sequence that is drawable by \
5248 the same face, and append them to HEAD/TAIL. */ \
5249 for (n = 0; n < cmp->glyph_len;) \
5250 { \
5251 s = (struct glyph_string *) alloca (sizeof *s); \
5252 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5253 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5254 s->cmp = cmp; \
5255 s->gidx = n; \
5256 s->x = (X); \
5257 \
5258 if (n == 0) \
5259 first_s = s; \
5260 \
5261 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5262 } \
5263 \
5264 ++START; \
5265 s = first_s; \
5266 } while (0)
5267
5268
5269/* Build a list of glyph strings between HEAD and TAIL for the glyphs
5270 of AREA of glyph row ROW on window W between indices START and END.
5271 HL overrides the face for drawing glyph strings, e.g. it is
5272 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5273 x-positions of the drawing area.
5274
5275 This is an ugly monster macro construct because we must use alloca
5276 to allocate glyph strings (because x_draw_glyphs can be called
5277 asynchronously). */
5278
5279#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5280 do \
5281 { \
5282 HEAD = TAIL = NULL; \
5283 while (START < END) \
5284 { \
5285 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5286 switch (first_glyph->type) \
5287 { \
5288 case CHAR_GLYPH: \
5289 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5290 TAIL, HL, X, LAST_X, \
5291 OVERLAPS_P); \
5292 break; \
5293 \
5294 case COMPOSITE_GLYPH: \
5295 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5296 HEAD, TAIL, HL, X, LAST_X,\
5297 OVERLAPS_P); \
5298 break; \
5299 \
5300 case STRETCH_GLYPH: \
5301 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5302 HEAD, TAIL, HL, X, LAST_X); \
5303 break; \
5304 \
5305 case IMAGE_GLYPH: \
5306 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5307 TAIL, HL, X, LAST_X); \
5308 break; \
5309 \
5310 default: \
5311 abort (); \
5312 } \
5313 \
5314 x_set_glyph_string_background_width (s, START, LAST_X); \
5315 (X) += s->width; \
5316 } \
5317 } \
5318 while (0)
5319
5320
5321/* Draw glyphs between START and END in AREA of ROW on window W,
5322 starting at x-position X. X is relative to AREA in W. HL is a
5323 face-override with the following meaning:
5324
5325 DRAW_NORMAL_TEXT draw normally
5326 DRAW_CURSOR draw in cursor face
5327 DRAW_MOUSE_FACE draw in mouse face.
5328 DRAW_INVERSE_VIDEO draw in mode line face
5329 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5330 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5331
1a578e9b
AC
5332 If OVERLAPS_P is non-zero, draw only the foreground of characters
5333 and clip to the physical height of ROW.
5334
5335 Value is the x-position reached, relative to AREA of W. */
5336
5337static int
e0f712ba 5338x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
1a578e9b
AC
5339 struct window *w;
5340 int x;
5341 struct glyph_row *row;
5342 enum glyph_row_area area;
5343 int start, end;
5344 enum draw_glyphs_face hl;
1a578e9b
AC
5345 int overlaps_p;
5346{
5347 struct glyph_string *head, *tail;
5348 struct glyph_string *s;
5349 int last_x, area_width;
5350 int x_reached;
5351 int i, j;
5352
5353 /* Let's rather be paranoid than getting a SEGV. */
1a578e9b 5354 end = min (end, row->used[area]);
e0f712ba
AC
5355 start = max (0, start);
5356 start = min (end, start);
1a578e9b
AC
5357
5358 /* Translate X to frame coordinates. Set last_x to the right
5359 end of the drawing area. */
5360 if (row->full_width_p)
5361 {
5362 /* X is relative to the left edge of W, without scroll bars
3f332ef3 5363 or fringes. */
e0f712ba 5364 struct frame *f = XFRAME (WINDOW_FRAME (w));
1a578e9b
AC
5365 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5366
5367 x += window_left_x;
5368 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5369 last_x = window_left_x + area_width;
5370
5371 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5372 {
5373 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5374 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5375 last_x += width;
5376 else
5377 x -= width;
5378 }
5379
5380 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5381 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5382 }
5383 else
5384 {
5385 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5386 area_width = window_box_width (w, area);
5387 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5388 }
5389
5390 /* Build a doubly-linked list of glyph_string structures between
5391 head and tail from what we have to draw. Note that the macro
5392 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5393 the reason we use a separate variable `i'. */
5394 i = start;
5395 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
e0f712ba 5396 overlaps_p);
1a578e9b
AC
5397 if (tail)
5398 x_reached = tail->x + tail->background_width;
5399 else
5400 x_reached = x;
5401
5402 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5403 the row, redraw some glyphs in front or following the glyph
5404 strings built above. */
e0f712ba 5405 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
1a578e9b
AC
5406 {
5407 int dummy_x = 0;
5408 struct glyph_string *h, *t;
5409
5410 /* Compute overhangs for all glyph strings. */
5411 for (s = head; s; s = s->next)
5412 x_compute_glyph_string_overhangs (s);
5413
5414 /* Prepend glyph strings for glyphs in front of the first glyph
5415 string that are overwritten because of the first glyph
5416 string's left overhang. The background of all strings
5417 prepended must be drawn because the first glyph string
5418 draws over it. */
5419 i = x_left_overwritten (head);
5420 if (i >= 0)
5421 {
5422 j = i;
5423 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5424 DRAW_NORMAL_TEXT, dummy_x, last_x,
e0f712ba 5425 overlaps_p);
1a578e9b 5426 start = i;
1a578e9b
AC
5427 x_compute_overhangs_and_x (t, head->x, 1);
5428 x_prepend_glyph_string_lists (&head, &tail, h, t);
5429 }
5430
5431 /* Prepend glyph strings for glyphs in front of the first glyph
5432 string that overwrite that glyph string because of their
5433 right overhang. For these strings, only the foreground must
5434 be drawn, because it draws over the glyph string at `head'.
5435 The background must not be drawn because this would overwrite
5436 right overhangs of preceding glyphs for which no glyph
5437 strings exist. */
5438 i = x_left_overwriting (head);
5439 if (i >= 0)
5440 {
5441 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5442 DRAW_NORMAL_TEXT, dummy_x, last_x,
e0f712ba 5443 overlaps_p);
1a578e9b
AC
5444 for (s = h; s; s = s->next)
5445 s->background_filled_p = 1;
1a578e9b
AC
5446 x_compute_overhangs_and_x (t, head->x, 1);
5447 x_prepend_glyph_string_lists (&head, &tail, h, t);
5448 }
5449
5450 /* Append glyphs strings for glyphs following the last glyph
5451 string tail that are overwritten by tail. The background of
5452 these strings has to be drawn because tail's foreground draws
5453 over it. */
5454 i = x_right_overwritten (tail);
5455 if (i >= 0)
5456 {
5457 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5458 DRAW_NORMAL_TEXT, x, last_x,
e0f712ba 5459 overlaps_p);
1a578e9b
AC
5460 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5461 x_append_glyph_string_lists (&head, &tail, h, t);
1a578e9b
AC
5462 }
5463
5464 /* Append glyph strings for glyphs following the last glyph
5465 string tail that overwrite tail. The foreground of such
5466 glyphs has to be drawn because it writes into the background
5467 of tail. The background must not be drawn because it could
5468 paint over the foreground of following glyphs. */
5469 i = x_right_overwriting (tail);
5470 if (i >= 0)
5471 {
5472 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5473 DRAW_NORMAL_TEXT, x, last_x,
e0f712ba 5474 overlaps_p);
1a578e9b
AC
5475 for (s = h; s; s = s->next)
5476 s->background_filled_p = 1;
5477 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5478 x_append_glyph_string_lists (&head, &tail, h, t);
1a578e9b
AC
5479 }
5480 }
5481
5482 /* Draw all strings. */
5483 for (s = head; s; s = s->next)
5484 x_draw_glyph_string (s);
5485
e0f712ba
AC
5486 if (area == TEXT_AREA
5487 && !row->full_width_p
5488 /* When drawing overlapping rows, only the glyph strings'
5489 foreground is drawn, which doesn't erase a cursor
5490 completely. */
5491 && !overlaps_p)
5492 {
5493 int x0 = head ? head->x : x;
5494 int x1 = tail ? tail->x + tail->background_width : x;
5495
5496 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5497 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5498
5499 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5500 {
5501 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5502 x0 -= left_area_width;
5503 x1 -= left_area_width;
5504 }
5505
5506 notice_overwritten_cursor (w, area, x0, x1,
5507 row->y, MATRIX_ROW_BOTTOM_Y (row));
5508 }
5509
1a578e9b
AC
5510 /* Value is the x-position up to which drawn, relative to AREA of W.
5511 This doesn't include parts drawn because of overhangs. */
5512 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5513 if (!row->full_width_p)
5514 {
5515 if (area > LEFT_MARGIN_AREA)
5516 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5517 if (area > TEXT_AREA)
5518 x_reached -= window_box_width (w, TEXT_AREA);
5519 }
e0f712ba 5520
1a578e9b
AC
5521 return x_reached;
5522}
5523
5524
5525/* Fix the display of area AREA of overlapping row ROW in window W. */
5526
e0f712ba 5527static void
1a578e9b
AC
5528x_fix_overlapping_area (w, row, area)
5529 struct window *w;
5530 struct glyph_row *row;
5531 enum glyph_row_area area;
5532{
5533 int i, x;
5534
5535 BLOCK_INPUT;
5536
5537 if (area == LEFT_MARGIN_AREA)
5538 x = 0;
5539 else if (area == TEXT_AREA)
5540 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5541 else
5542 x = (window_box_width (w, LEFT_MARGIN_AREA)
5543 + window_box_width (w, TEXT_AREA));
5544
5545 for (i = 0; i < row->used[area];)
5546 {
5547 if (row->glyphs[area][i].overlaps_vertically_p)
5548 {
5549 int start = i, start_x = x;
5550
5551 do
5552 {
5553 x += row->glyphs[area][i].pixel_width;
5554 ++i;
5555 }
5556 while (i < row->used[area]
5557 && row->glyphs[area][i].overlaps_vertically_p);
5558
5559 x_draw_glyphs (w, start_x, row, area, start, i,
e0f712ba 5560 DRAW_NORMAL_TEXT, 1);
1a578e9b
AC
5561 }
5562 else
5563 {
5564 x += row->glyphs[area][i].pixel_width;
5565 ++i;
5566 }
5567 }
5568
5569 UNBLOCK_INPUT;
5570}
5571
5572
5573/* Output LEN glyphs starting at START at the nominal cursor position.
5574 Advance the nominal cursor over the text. The global variable
5575 updated_window contains the window being updated, updated_row is
5576 the glyph row being updated, and updated_area is the area of that
5577 row being updated. */
5578
e0f712ba 5579static void
1a578e9b
AC
5580x_write_glyphs (start, len)
5581 struct glyph *start;
5582 int len;
5583{
e0f712ba 5584 int x, hpos;
1a578e9b
AC
5585
5586 xassert (updated_window && updated_row);
5587 BLOCK_INPUT;
5588
5589 /* Write glyphs. */
5590
5591 hpos = start - updated_row->glyphs[updated_area];
5592 x = x_draw_glyphs (updated_window, output_cursor.x,
5593 updated_row, updated_area,
5594 hpos, hpos + len,
e0f712ba 5595 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
5596
5597 UNBLOCK_INPUT;
5598
5599 /* Advance the output cursor. */
5600 output_cursor.hpos += len;
5601 output_cursor.x = x;
5602}
5603
5604
5605/* Insert LEN glyphs from START at the nominal cursor position. */
5606
e0f712ba 5607static void
1a578e9b
AC
5608x_insert_glyphs (start, len)
5609 struct glyph *start;
5610 register int len;
5611{
5612 struct frame *f;
5613 struct window *w;
5614 int line_height, shift_by_width, shifted_region_width;
5615 struct glyph_row *row;
5616 struct glyph *glyph;
e0f712ba 5617 int frame_x, frame_y, hpos;
1a578e9b
AC
5618
5619 xassert (updated_window && updated_row);
5620 BLOCK_INPUT;
5621 w = updated_window;
5622 f = XFRAME (WINDOW_FRAME (w));
5623
5624 /* Get the height of the line we are in. */
5625 row = updated_row;
5626 line_height = row->height;
5627
5628 /* Get the width of the glyphs to insert. */
5629 shift_by_width = 0;
5630 for (glyph = start; glyph < start + len; ++glyph)
5631 shift_by_width += glyph->pixel_width;
5632
5633 /* Get the width of the region to shift right. */
5634 shifted_region_width = (window_box_width (w, updated_area)
5635 - output_cursor.x
5636 - shift_by_width);
5637
5638 /* Shift right. */
e0f712ba 5639 frame_x = window_box_left (w, updated_area) + output_cursor.x;
1a578e9b
AC
5640 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5641
5642 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5643 f->output_data.mac->normal_gc,
5644 frame_x, frame_y,
5645 shifted_region_width, line_height,
5646 frame_x + shift_by_width, frame_y);
5647
5648 /* Write the glyphs. */
5649 hpos = start - row->glyphs[updated_area];
5650 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
e0f712ba
AC
5651 DRAW_NORMAL_TEXT, 0);
5652
1a578e9b
AC
5653 /* Advance the output cursor. */
5654 output_cursor.hpos += len;
5655 output_cursor.x += shift_by_width;
5656 UNBLOCK_INPUT;
5657}
5658
5659
5660/* Delete N glyphs at the nominal cursor position. Not implemented
5661 for X frames. */
5662
e0f712ba 5663static void
1a578e9b
AC
5664x_delete_glyphs (n)
5665 register int n;
5666{
5667 abort ();
5668}
5669
5670
5671/* Erase the current text line from the nominal cursor position
5672 (inclusive) to pixel column TO_X (exclusive). The idea is that
5673 everything from TO_X onward is already erased.
5674
5675 TO_X is a pixel position relative to updated_area of
5676 updated_window. TO_X == -1 means clear to the end of this area. */
5677
e0f712ba 5678static void
1a578e9b
AC
5679x_clear_end_of_line (to_x)
5680 int to_x;
5681{
5682 struct frame *f;
5683 struct window *w = updated_window;
5684 int max_x, min_y, max_y;
5685 int from_x, from_y, to_y;
5686
5687 xassert (updated_window && updated_row);
5688 f = XFRAME (w->frame);
5689
5690 if (updated_row->full_width_p)
5691 {
5692 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5693 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5694 && !w->pseudo_window_p)
5695 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5696 }
5697 else
5698 max_x = window_box_width (w, updated_area);
5699 max_y = window_text_bottom_y (w);
5700
5701 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5702 of window. For TO_X > 0, truncate to end of drawing area. */
5703 if (to_x == 0)
5704 return;
5705 else if (to_x < 0)
5706 to_x = max_x;
5707 else
5708 to_x = min (to_x, max_x);
5709
5710 to_y = min (max_y, output_cursor.y + updated_row->height);
5711
5712 /* Notice if the cursor will be cleared by this operation. */
5713 if (!updated_row->full_width_p)
e0f712ba
AC
5714 notice_overwritten_cursor (w, updated_area,
5715 output_cursor.x, -1,
5716 updated_row->y,
5717 MATRIX_ROW_BOTTOM_Y (updated_row));
1a578e9b
AC
5718
5719 from_x = output_cursor.x;
e0f712ba 5720
1a578e9b
AC
5721 /* Translate to frame coordinates. */
5722 if (updated_row->full_width_p)
5723 {
5724 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5725 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5726 }
5727 else
5728 {
5729 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5730 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5731 }
5732
5733 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5734 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5735 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5736
5737 /* Prevent inadvertently clearing to end of the X window. */
5738 if (to_x > from_x && to_y > from_y)
5739 {
5740 BLOCK_INPUT;
5741 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5742 from_x, from_y, to_x - from_x, to_y - from_y,
5743 0);
5744 UNBLOCK_INPUT;
5745 }
5746}
5747
5748
5749/* Clear entire frame. If updating_frame is non-null, clear that
5750 frame. Otherwise clear the selected frame. */
5751
e0f712ba 5752static void
1a578e9b
AC
5753x_clear_frame ()
5754{
5755 struct frame *f;
5756
5757 if (updating_frame)
5758 f = updating_frame;
5759 else
5760 f = SELECTED_FRAME ();
5761
5762 /* Clearing the frame will erase any cursor, so mark them all as no
5763 longer visible. */
5764 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5765 output_cursor.hpos = output_cursor.vpos = 0;
5766 output_cursor.x = -1;
5767
5768 /* We don't set the output cursor here because there will always
5769 follow an explicit cursor_to. */
5770 BLOCK_INPUT;
5771 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5772
5773#if 0 /* Clearing frame on Mac OS clears scroll bars. */
5774 /* We have to clear the scroll bars, too. If we have changed
5775 colors or something like that, then they should be notified. */
5776 x_scroll_bar_clear (f);
5777#endif
5778
5779 XFlush (FRAME_MAC_DISPLAY (f));
5780 UNBLOCK_INPUT;
5781}
5782
5783
5784\f
5785/* Invert the middle quarter of the frame for .15 sec. */
5786
5787/* We use the select system call to do the waiting, so we have to make
5788 sure it's available. If it isn't, we just won't do visual bells. */
5789
5790#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5791
5792/* Subtract the `struct timeval' values X and Y, storing the result in
5793 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5794
5795static int
5796timeval_subtract (result, x, y)
5797 struct timeval *result, x, y;
5798{
5799 /* Perform the carry for the later subtraction by updating y. This
5800 is safer because on some systems the tv_sec member is unsigned. */
5801 if (x.tv_usec < y.tv_usec)
5802 {
5803 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5804 y.tv_usec -= 1000000 * nsec;
5805 y.tv_sec += nsec;
5806 }
5807
5808 if (x.tv_usec - y.tv_usec > 1000000)
5809 {
5810 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5811 y.tv_usec += 1000000 * nsec;
5812 y.tv_sec -= nsec;
5813 }
5814
5815 /* Compute the time remaining to wait. tv_usec is certainly
5816 positive. */
5817 result->tv_sec = x.tv_sec - y.tv_sec;
5818 result->tv_usec = x.tv_usec - y.tv_usec;
5819
5820 /* Return indication of whether the result should be considered
5821 negative. */
5822 return x.tv_sec < y.tv_sec;
5823}
5824
5825void
5826XTflash (f)
5827 struct frame *f;
5828{
5829 BLOCK_INPUT;
5830
5831 FlashMenuBar (0);
5832
5833 {
5834 struct timeval wakeup;
5835
5836 EMACS_GET_TIME (wakeup);
5837
5838 /* Compute time to wait until, propagating carry from usecs. */
5839 wakeup.tv_usec += 150000;
5840 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5841 wakeup.tv_usec %= 1000000;
5842
5843 /* Keep waiting until past the time wakeup. */
5844 while (1)
5845 {
5846 struct timeval timeout;
5847
5848 EMACS_GET_TIME (timeout);
5849
5850 /* In effect, timeout = wakeup - timeout.
5851 Break if result would be negative. */
5852 if (timeval_subtract (&timeout, wakeup, timeout))
5853 break;
5854
5855 /* Try to wait that long--but we might wake up sooner. */
5856 select (0, NULL, NULL, NULL, &timeout);
5857 }
5858 }
5859
5860 FlashMenuBar (0);
5861
5862 UNBLOCK_INPUT;
5863}
5864
5865#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5866
5867
5868/* Make audible bell. */
5869
5870void
5871XTring_bell ()
5872{
5873 struct frame *f = SELECTED_FRAME ();
5874
5875#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5876 if (visible_bell)
5877 XTflash (f);
5878 else
5879#endif
5880 {
5881 BLOCK_INPUT;
5882 SysBeep (1);
5883 XFlush (FRAME_MAC_DISPLAY (f));
5884 UNBLOCK_INPUT;
5885 }
5886}
5887
5888
5889\f
5890/* Specify how many text lines, from the top of the window,
5891 should be affected by insert-lines and delete-lines operations.
5892 This, and those operations, are used only within an update
5893 that is bounded by calls to x_update_begin and x_update_end. */
5894
5895void
5896XTset_terminal_window (n)
5897 register int n;
5898{
5899 /* This function intentionally left blank. */
5900}
5901
5902
5903\f
5904/***********************************************************************
5905 Line Dance
5906 ***********************************************************************/
5907
5908/* Perform an insert-lines or delete-lines operation, inserting N
5909 lines or deleting -N lines at vertical position VPOS. */
5910
e0f712ba 5911static void
1a578e9b
AC
5912x_ins_del_lines (vpos, n)
5913 int vpos, n;
5914{
5915 abort ();
5916}
5917
5918
5919/* Scroll part of the display as described by RUN. */
5920
e0f712ba 5921static void
1a578e9b
AC
5922x_scroll_run (w, run)
5923 struct window *w;
5924 struct run *run;
5925{
5926 struct frame *f = XFRAME (w->frame);
5927 int x, y, width, height, from_y, to_y, bottom_y;
5928
5929 /* Get frame-relative bounding box of the text display area of W,
3f332ef3
KS
5930 without mode lines. Include in this box the left and right
5931 fringes of W. */
1a578e9b 5932 window_box (w, -1, &x, &y, &width, &height);
3f332ef3
KS
5933 width += FRAME_X_FRINGE_WIDTH (f);
5934 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
1a578e9b
AC
5935
5936 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5937 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5938 bottom_y = y + height;
5939
5940 if (to_y < from_y)
5941 {
5942 /* Scrolling up. Make sure we don't copy part of the mode
5943 line at the bottom. */
5944 if (from_y + run->height > bottom_y)
5945 height = bottom_y - from_y;
5946 else
5947 height = run->height;
5948 }
5949 else
5950 {
5951 /* Scolling down. Make sure we don't copy over the mode line.
5952 at the bottom. */
5953 if (to_y + run->height > bottom_y)
5954 height = bottom_y - to_y;
5955 else
5956 height = run->height;
5957 }
5958
5959 BLOCK_INPUT;
5960
5961 /* Cursor off. Will be switched on again in x_update_window_end. */
5962 updated_window = w;
5963 x_clear_cursor (w);
5964
5965 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5966 f->output_data.mac->normal_gc,
5967 x, from_y,
5968 width, height,
5969 x, to_y);
5970
5971 UNBLOCK_INPUT;
5972}
5973
5974
5975\f
5976/***********************************************************************
5977 Exposure Events
5978 ***********************************************************************/
5979
5980/* Redisplay an exposed area of frame F. X and Y are the upper-left
5981 corner of the exposed rectangle. W and H are width and height of
5982 the exposed area. All are pixel values. W or H zero means redraw
5983 the entire frame. */
5984
5985static void
5986expose_frame (f, x, y, w, h)
5987 struct frame *f;
5988 int x, y, w, h;
5989{
5990 Rect r;
e0f712ba 5991 int mouse_face_overwritten_p = 0;
1a578e9b
AC
5992
5993 TRACE ((stderr, "expose_frame "));
5994
5995 /* No need to redraw if frame will be redrawn soon. */
5996 if (FRAME_GARBAGED_P (f))
5997 {
5998 TRACE ((stderr, " garbaged\n"));
5999 return;
6000 }
6001
6002 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6003 or deactivated here, for unknown reasons, activated scroll bars
6004 are shown in deactivated frames in some instances. */
6005 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6006 activate_scroll_bars (f);
6007 else
6008 deactivate_scroll_bars (f);
6009
6010 /* If basic faces haven't been realized yet, there is no point in
6011 trying to redraw anything. This can happen when we get an expose
6012 event while Emacs is starting, e.g. by moving another window. */
6013 if (FRAME_FACE_CACHE (f) == NULL
6014 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6015 {
6016 TRACE ((stderr, " no faces\n"));
6017 return;
6018 }
6019
6020 if (w == 0 || h == 0)
6021 {
6022 r.left = r.top = 0;
6023 r.right = CANON_X_UNIT (f) * f->width;
6024 r.bottom = CANON_Y_UNIT (f) * f->height;
6025 }
6026 else
6027 {
6028 r.left = x;
6029 r.top = y;
6030 r.right = x + w;
6031 r.bottom = y + h;
6032 }
6033
6034 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
e0f712ba 6035 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
1a578e9b
AC
6036
6037 if (WINDOWP (f->tool_bar_window))
e0f712ba
AC
6038 mouse_face_overwritten_p
6039 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6040
6041 /* Some window managers support a focus-follows-mouse style with
6042 delayed raising of frames. Imagine a partially obscured frame,
6043 and moving the mouse into partially obscured mouse-face on that
6044 frame. The visible part of the mouse-face will be highlighted,
6045 then the WM raises the obscured frame. With at least one WM, KDE
6046 2.1, Emacs is not getting any event for the raising of the frame
6047 (even tried with SubstructureRedirectMask), only Expose events.
6048 These expose events will draw text normally, i.e. not
6049 highlighted. Which means we must redo the highlight here.
6050 Subsume it under ``we love X''. --gerd 2001-08-15 */
6051 /* Included in Windows version because Windows most likely does not
6052 do the right thing if any third party tool offers
6053 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6054 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
1a578e9b 6055 {
e0f712ba
AC
6056 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6057 if (f == dpyinfo->mouse_face_mouse_frame)
6058 {
6059 int x = dpyinfo->mouse_face_mouse_x;
6060 int y = dpyinfo->mouse_face_mouse_y;
6061 clear_mouse_face (dpyinfo);
6062 note_mouse_highlight (f, x, y);
6063 }
1a578e9b 6064 }
1a578e9b
AC
6065}
6066
6067
6068/* Redraw (parts) of all windows in the window tree rooted at W that
6069 intersect R. R contains frame pixel coordinates. */
6070
e0f712ba 6071static int
1a578e9b
AC
6072expose_window_tree (w, r)
6073 struct window *w;
6074 Rect *r;
6075{
e0f712ba
AC
6076 struct frame *f = XFRAME (w->frame);
6077 int mouse_face_overwritten_p = 0;
6078
6079 while (w && !FRAME_GARBAGED_P (f))
1a578e9b
AC
6080 {
6081 if (!NILP (w->hchild))
e0f712ba
AC
6082 mouse_face_overwritten_p
6083 |= expose_window_tree (XWINDOW (w->hchild), r);
1a578e9b 6084 else if (!NILP (w->vchild))
e0f712ba
AC
6085 mouse_face_overwritten_p
6086 |= expose_window_tree (XWINDOW (w->vchild), r);
1a578e9b 6087 else
e0f712ba 6088 mouse_face_overwritten_p |= expose_window (w, r);
1a578e9b 6089
e0f712ba 6090 w = NILP (w->next) ? NULL : XWINDOW (w->next);
1a578e9b 6091 }
e0f712ba
AC
6092
6093 return mouse_face_overwritten_p;
1a578e9b
AC
6094}
6095
6096
6097/* Redraw the part of glyph row area AREA of glyph row ROW on window W
6098 which intersects rectangle R. R is in window-relative coordinates. */
6099
6100static void
6101expose_area (w, row, r, area)
6102 struct window *w;
6103 struct glyph_row *row;
6104 Rect *r;
6105 enum glyph_row_area area;
6106{
1a578e9b
AC
6107 struct glyph *first = row->glyphs[area];
6108 struct glyph *end = row->glyphs[area] + row->used[area];
6109 struct glyph *last;
e0f712ba 6110 int first_x, start_x, x;
1a578e9b
AC
6111
6112 if (area == TEXT_AREA && row->fill_line_p)
6113 /* If row extends face to end of line write the whole line. */
e0f712ba 6114 x_draw_glyphs (w, 0, row, area,
1a578e9b 6115 0, row->used[area],
e0f712ba 6116 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
6117 else
6118 {
e0f712ba
AC
6119 /* Set START_X to the window-relative start position for drawing glyphs of
6120 AREA. The first glyph of the text area can be partially visible.
6121 The first glyphs of other areas cannot. */
6122 if (area == LEFT_MARGIN_AREA)
6123 start_x = 0;
6124 else if (area == TEXT_AREA)
6125 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6126 else
6127 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6128 + window_box_width (w, TEXT_AREA));
6129 x = start_x;
6130
1a578e9b
AC
6131 /* Find the first glyph that must be redrawn. */
6132 while (first < end
6133 && x + first->pixel_width < r->left)
6134 {
6135 x += first->pixel_width;
6136 ++first;
6137 }
6138
6139 /* Find the last one. */
6140 last = first;
6141 first_x = x;
6142 while (last < end
6143 && x < r->right)
6144 {
6145 x += last->pixel_width;
6146 ++last;
6147 }
e0f712ba 6148
1a578e9b
AC
6149 /* Repaint. */
6150 if (last > first)
e0f712ba
AC
6151 x_draw_glyphs (w, first_x - start_x, row, area,
6152 first - row->glyphs[area],
6153 last - row->glyphs[area],
6154 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
6155 }
6156}
e0f712ba 6157
1a578e9b
AC
6158
6159/* Redraw the parts of the glyph row ROW on window W intersecting
e0f712ba
AC
6160 rectangle R. R is in window-relative coordinates. Value is
6161 non-zero if mouse face was overwritten. */
1a578e9b 6162
e0f712ba 6163static int
1a578e9b
AC
6164expose_line (w, row, r)
6165 struct window *w;
6166 struct glyph_row *row;
6167 Rect *r;
6168{
6169 xassert (row->enabled_p);
6170
6171 if (row->mode_line_p || w->pseudo_window_p)
6172 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
e0f712ba 6173 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
6174 else
6175 {
6176 if (row->used[LEFT_MARGIN_AREA])
6177 expose_area (w, row, r, LEFT_MARGIN_AREA);
6178 if (row->used[TEXT_AREA])
6179 expose_area (w, row, r, TEXT_AREA);
6180 if (row->used[RIGHT_MARGIN_AREA])
6181 expose_area (w, row, r, RIGHT_MARGIN_AREA);
3f332ef3 6182 x_draw_row_fringe_bitmaps (w, row);
1a578e9b 6183 }
e0f712ba
AC
6184
6185 return row->mouse_face_p;
1a578e9b
AC
6186}
6187
6188
6189/* Return non-zero if W's cursor intersects rectangle R. */
6190
6191static int
6192x_phys_cursor_in_rect_p (w, r)
6193 struct window *w;
6194 Rect *r;
6195{
6196 Rect cr, result;
6197 struct glyph *cursor_glyph;
6198
6199 cursor_glyph = get_phys_cursor_glyph (w);
6200 if (cursor_glyph)
6201 {
6202 cr.left = w->phys_cursor.x;
6203 cr.top = w->phys_cursor.y;
6204 cr.right = cr.left + cursor_glyph->pixel_width;
6205 cr.bottom = cr.top + w->phys_cursor_height;
6206 return x_intersect_rectangles (&cr, r, &result);
6207 }
6208 else
6209 return 0;
6210}
6211
6212
e0f712ba
AC
6213/* Redraw the part of window W intersection rectagle FR. Pixel
6214 coordinates in FR are frame relative. Call this function with
6215 input blocked. Value is non-zero if the exposure overwrites
6216 mouse-face. */
1a578e9b 6217
e0f712ba
AC
6218static int
6219expose_window (w, fr)
1a578e9b 6220 struct window *w;
e0f712ba 6221 Rect *fr;
1a578e9b 6222{
e0f712ba
AC
6223 struct frame *f = XFRAME (w->frame);
6224 Rect wr, r;
6225 int mouse_face_overwritten_p = 0;
1a578e9b
AC
6226
6227 /* If window is not yet fully initialized, do nothing. This can
6228 happen when toolkit scroll bars are used and a window is split.
6229 Reconfiguring the scroll bar will generate an expose for a newly
6230 created window. */
6231 if (w->current_matrix == NULL)
e0f712ba 6232 return 0;
1a578e9b 6233
e0f712ba
AC
6234 /* When we're currently updating the window, display and current
6235 matrix usually don't agree. Arrange for a thorough display
6236 later. */
6237 if (w == updated_window)
1a578e9b 6238 {
e0f712ba
AC
6239 SET_FRAME_GARBAGED (f);
6240 return 0;
1a578e9b 6241 }
1a578e9b 6242
e0f712ba
AC
6243 /* Frame-relative pixel rectangle of W. */
6244 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6245 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6246 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6247 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6248
6249 if (x_intersect_rectangles (fr, &wr, &r))
1a578e9b 6250 {
e0f712ba
AC
6251 int yb = window_text_bottom_y (w);
6252 struct glyph_row *row;
6253 int cursor_cleared_p;
1a578e9b 6254
e0f712ba
AC
6255 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6256 r.left, r.top, r.right, r.bottom));
1a578e9b 6257
e0f712ba
AC
6258 /* Convert to window coordinates. */
6259 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6260 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6261 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6262 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6263
6264 /* Turn off the cursor. */
6265 if (!w->pseudo_window_p
6266 && x_phys_cursor_in_rect_p (w, &r))
6267 {
6268 x_clear_cursor (w);
6269 cursor_cleared_p = 1;
6270 }
6271 else
6272 cursor_cleared_p = 0;
6273
6274 /* Find the first row intersecting the rectangle R. */
6275 for (row = w->current_matrix->rows;
6276 row->enabled_p;
6277 ++row)
6278 {
6279 int y0 = row->y;
6280 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6281
6282 if ((y0 >= r.top && y0 < r.bottom)
6283 || (y1 > r.top && y1 < r.bottom)
6284 || (r.top >= y0 && r.top < y1)
6285 || (r.bottom > y0 && r.bottom < y1))
6286 {
6287 if (expose_line (w, row, &r))
6288 mouse_face_overwritten_p = 1;
6289 }
6290
6291 if (y1 >= yb)
6292 break;
6293 }
6294
6295 /* Display the mode line if there is one. */
6296 if (WINDOW_WANTS_MODELINE_P (w)
6297 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6298 row->enabled_p)
6299 && row->y < r.bottom)
6300 {
6301 if (expose_line (w, row, &r))
6302 mouse_face_overwritten_p = 1;
6303 }
6304
6305 if (!w->pseudo_window_p)
6306 {
6307 /* Draw border between windows. */
6308 x_draw_vertical_border (w);
6309
6310 /* Turn the cursor on again. */
6311 if (cursor_cleared_p)
6312 x_update_window_cursor (w, 1);
6313 }
1a578e9b 6314 }
e0f712ba 6315
1a578e9b
AC
6316 /* Display scroll bar for this window. */
6317 if (!NILP (w->vertical_scroll_bar))
6318 {
6319 ControlHandle ch
e0f712ba 6320 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
1a578e9b
AC
6321
6322 Draw1Control (ch);
6323 }
1a578e9b 6324
e0f712ba
AC
6325 return mouse_face_overwritten_p;
6326}
1a578e9b
AC
6327
6328static int
6329x_intersect_rectangles (r1, r2, result)
6330 Rect *r1, *r2, *result;
6331{
6332 Rect *left, *right;
6333 Rect *upper, *lower;
6334 int intersection_p = 0;
6335
6336 /* Rerrange so that R1 is the left-most rectangle. */
6337 if (r1->left < r2->left)
6338 left = r1, right = r2;
6339 else
6340 left = r2, right = r1;
6341
6342 /* X0 of the intersection is right.x0, if this is inside R1,
6343 otherwise there is no intersection. */
6344 if (right->left <= left->right)
6345 {
6346 result->left = right->left;
6347
6348 /* The right end of the intersection is the minimum of the
6349 the right ends of left and right. */
6350 result->right = min (left->right, right->right);
6351
6352 /* Same game for Y. */
6353 if (r1->top < r2->top)
6354 upper = r1, lower = r2;
6355 else
6356 upper = r2, lower = r1;
6357
6358 /* The upper end of the intersection is lower.y0, if this is inside
6359 of upper. Otherwise, there is no intersection. */
6360 if (lower->top <= upper->bottom)
6361 {
6362 result->top = lower->top;
6363
6364 /* The lower end of the intersection is the minimum of the lower
6365 ends of upper and lower. */
6366 result->bottom = min (lower->bottom, upper->bottom);
6367 intersection_p = 1;
6368 }
6369 }
6370
6371 return intersection_p;
6372}
6373
6374
6375
6376
6377\f
6378static void
6379frame_highlight (f)
6380 struct frame *f;
6381{
6382 x_update_cursor (f, 1);
6383}
6384
6385static void
6386frame_unhighlight (f)
6387 struct frame *f;
6388{
6389 x_update_cursor (f, 1);
6390}
6391
6392/* The focus has changed. Update the frames as necessary to reflect
6393 the new situation. Note that we can't change the selected frame
6394 here, because the Lisp code we are interrupting might become confused.
6395 Each event gets marked with the frame in which it occurred, so the
6396 Lisp code can tell when the switch took place by examining the events. */
6397
6398static void
6399x_new_focus_frame (dpyinfo, frame)
6400 struct x_display_info *dpyinfo;
6401 struct frame *frame;
6402{
6403 struct frame *old_focus = dpyinfo->x_focus_frame;
6404
6405 if (frame != dpyinfo->x_focus_frame)
6406 {
6407 /* Set this before calling other routines, so that they see
6408 the correct value of x_focus_frame. */
6409 dpyinfo->x_focus_frame = frame;
6410
6411 if (old_focus && old_focus->auto_lower)
6412 x_lower_frame (old_focus);
6413
6414#if 0
6415 selected_frame = frame;
6416 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6417 selected_frame);
6418 Fselect_window (selected_frame->selected_window);
6419 choose_minibuf_frame ();
6420#endif /* ! 0 */
6421
6422 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6423 pending_autoraise_frame = dpyinfo->x_focus_frame;
6424 else
6425 pending_autoraise_frame = 0;
6426 }
6427
6428 x_frame_rehighlight (dpyinfo);
6429}
6430
6431/* Handle an event saying the mouse has moved out of an Emacs frame. */
6432
e0f712ba 6433void
1a578e9b
AC
6434x_mouse_leave (dpyinfo)
6435 struct x_display_info *dpyinfo;
6436{
6437 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6438}
6439
6440/* The focus has changed, or we have redirected a frame's focus to
6441 another frame (this happens when a frame uses a surrogate
6442 mini-buffer frame). Shift the highlight as appropriate.
6443
6444 The FRAME argument doesn't necessarily have anything to do with which
6445 frame is being highlighted or un-highlighted; we only use it to find
6446 the appropriate X display info. */
6447
e0f712ba 6448static void
1a578e9b
AC
6449XTframe_rehighlight (frame)
6450 struct frame *frame;
6451{
6452 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6453}
6454
6455static void
6456x_frame_rehighlight (dpyinfo)
6457 struct x_display_info *dpyinfo;
6458{
6459 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6460
6461 if (dpyinfo->x_focus_frame)
6462 {
6463 dpyinfo->x_highlight_frame
6464 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6465 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6466 : dpyinfo->x_focus_frame);
6467 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6468 {
6469 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6470 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6471 }
6472 }
6473 else
6474 dpyinfo->x_highlight_frame = 0;
6475
6476 if (dpyinfo->x_highlight_frame != old_highlight)
6477 {
6478 if (old_highlight)
6479 frame_unhighlight (old_highlight);
6480 if (dpyinfo->x_highlight_frame)
6481 frame_highlight (dpyinfo->x_highlight_frame);
6482 }
6483}
6484
6485
6486\f
6487/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6488
e0f712ba 6489#if 0 /* MAC_TODO */
1a578e9b
AC
6490/* Initialize mode_switch_bit and modifier_meaning. */
6491static void
6492x_find_modifier_meanings (dpyinfo)
6493 struct x_display_info *dpyinfo;
6494{
6495 int min_code, max_code;
6496 KeySym *syms;
6497 int syms_per_code;
6498 XModifierKeymap *mods;
6499
6500 dpyinfo->meta_mod_mask = 0;
6501 dpyinfo->shift_lock_mask = 0;
6502 dpyinfo->alt_mod_mask = 0;
6503 dpyinfo->super_mod_mask = 0;
6504 dpyinfo->hyper_mod_mask = 0;
6505
6506#ifdef HAVE_X11R4
6507 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6508#else
6509 min_code = dpyinfo->display->min_keycode;
6510 max_code = dpyinfo->display->max_keycode;
6511#endif
6512
6513 syms = XGetKeyboardMapping (dpyinfo->display,
6514 min_code, max_code - min_code + 1,
6515 &syms_per_code);
6516 mods = XGetModifierMapping (dpyinfo->display);
6517
6518 /* Scan the modifier table to see which modifier bits the Meta and
6519 Alt keysyms are on. */
6520 {
6521 int row, col; /* The row and column in the modifier table. */
6522
6523 for (row = 3; row < 8; row++)
6524 for (col = 0; col < mods->max_keypermod; col++)
6525 {
6526 KeyCode code
6527 = mods->modifiermap[(row * mods->max_keypermod) + col];
6528
6529 /* Zeroes are used for filler. Skip them. */
6530 if (code == 0)
6531 continue;
6532
6533 /* Are any of this keycode's keysyms a meta key? */
6534 {
6535 int code_col;
6536
6537 for (code_col = 0; code_col < syms_per_code; code_col++)
6538 {
6539 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6540
6541 switch (sym)
6542 {
6543 case XK_Meta_L:
6544 case XK_Meta_R:
6545 dpyinfo->meta_mod_mask |= (1 << row);
6546 break;
6547
6548 case XK_Alt_L:
6549 case XK_Alt_R:
6550 dpyinfo->alt_mod_mask |= (1 << row);
6551 break;
6552
6553 case XK_Hyper_L:
6554 case XK_Hyper_R:
6555 dpyinfo->hyper_mod_mask |= (1 << row);
6556 break;
6557
6558 case XK_Super_L:
6559 case XK_Super_R:
6560 dpyinfo->super_mod_mask |= (1 << row);
6561 break;
6562
6563 case XK_Shift_Lock:
6564 /* Ignore this if it's not on the lock modifier. */
6565 if ((1 << row) == LockMask)
6566 dpyinfo->shift_lock_mask = LockMask;
6567 break;
6568 }
6569 }
6570 }
6571 }
6572 }
6573
6574 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6575 if (! dpyinfo->meta_mod_mask)
6576 {
6577 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6578 dpyinfo->alt_mod_mask = 0;
6579 }
6580
6581 /* If some keys are both alt and meta,
6582 make them just meta, not alt. */
6583 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6584 {
6585 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6586 }
6587
6588 XFree ((char *) syms);
6589 XFreeModifiermap (mods);
6590}
6591
e0f712ba 6592#endif /* MAC_TODO */
1a578e9b
AC
6593
6594/* Convert between the modifier bits X uses and the modifier bits
6595 Emacs uses. */
6596
6597static unsigned int
6598x_mac_to_emacs_modifiers (dpyinfo, state)
6599 struct x_display_info *dpyinfo;
6600 unsigned short state;
6601{
6602 return (((state & shiftKey) ? shift_modifier : 0)
6603 | ((state & controlKey) ? ctrl_modifier : 0)
6604 | ((state & cmdKey) ? meta_modifier : 0)
6605 | ((state & optionKey) ? alt_modifier : 0));
6606}
6607
e0f712ba 6608#if 0 /* MAC_TODO */
1a578e9b
AC
6609static unsigned short
6610x_emacs_to_x_modifiers (dpyinfo, state)
6611 struct x_display_info *dpyinfo;
6612 unsigned int state;
6613{
6614 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6615 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6616 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6617 | ((state & shift_modifier) ? ShiftMask : 0)
6618 | ((state & ctrl_modifier) ? ControlMask : 0)
6619 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6620}
e0f712ba 6621#endif /* MAC_TODO */
1a578e9b
AC
6622
6623/* Convert a keysym to its name. */
6624
6625char *
6626x_get_keysym_name (keysym)
6627 int keysym;
6628{
6629 char *value;
6630
6631 BLOCK_INPUT;
6632#if 0
6633 value = XKeysymToString (keysym);
6634#else
6635 value = 0;
6636#endif
6637 UNBLOCK_INPUT;
6638
6639 return value;
6640}
6641
6642
6643\f
6644/* Mouse clicks and mouse movement. Rah. */
6645
6646/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6647 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6648 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6649 not force the value into range. */
6650
6651void
6652pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6653 FRAME_PTR f;
6654 register int pix_x, pix_y;
6655 register int *x, *y;
6656 Rect *bounds;
6657 int noclip;
6658{
e0f712ba
AC
6659 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6660 if (NILP (Vwindow_system))
6661 {
6662 *x = pix_x;
6663 *y = pix_y;
6664 return;
6665 }
6666
6667 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1a578e9b
AC
6668 even for negative values. */
6669 if (pix_x < 0)
e0f712ba 6670 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
1a578e9b
AC
6671 if (pix_y < 0)
6672 pix_y -= (f)->output_data.mac->line_height - 1;
6673
6674 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6675 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6676
6677 if (bounds)
6678 {
6679 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6680 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
e0f712ba
AC
6681 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6682 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
1a578e9b
AC
6683 }
6684
6685 if (!noclip)
6686 {
6687 if (pix_x < 0)
6688 pix_x = 0;
6689 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6690 pix_x = FRAME_WINDOW_WIDTH (f);
6691
6692 if (pix_y < 0)
6693 pix_y = 0;
6694 else if (pix_y > f->height)
6695 pix_y = f->height;
6696 }
6697
6698 *x = pix_x;
6699 *y = pix_y;
6700}
6701
6702
6703/* Given HPOS/VPOS in the current matrix of W, return corresponding
6704 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6705 can't tell the positions because W's display is not up to date,
6706 return 0. */
6707
e0f712ba 6708int
1a578e9b
AC
6709glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6710 struct window *w;
6711 int hpos, vpos;
6712 int *frame_x, *frame_y;
6713{
6714 int success_p;
6715
6716 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6717 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6718
6719 if (display_completed)
6720 {
6721 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6722 struct glyph *glyph = row->glyphs[TEXT_AREA];
6723 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6724
6725 *frame_y = row->y;
6726 *frame_x = row->x;
6727 while (glyph < end)
6728 {
6729 *frame_x += glyph->pixel_width;
6730 ++glyph;
6731 }
6732
6733 success_p = 1;
6734 }
6735 else
6736 {
6737 *frame_y = *frame_x = 0;
6738 success_p = 0;
6739 }
6740
6741 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6742 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6743 return success_p;
6744}
6745
6746
6747/* Prepare a mouse-event in *RESULT for placement in the input queue.
6748
6749 If the event is a button press, then note that we have grabbed
6750 the mouse. */
6751
6752static Lisp_Object
6753construct_mouse_click (result, event, f)
6754 struct input_event *result;
6755 EventRecord *event;
6756 struct frame *f;
6757{
6758 Point mouseLoc;
6759
6760 result->kind = mouse_click;
6761 result->code = 0; /* only one mouse button */
6762 result->timestamp = event->when;
6763 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6764
6765 mouseLoc = event->where;
e0f712ba
AC
6766
6767#if TARGET_API_MAC_CARBON
6768 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6769#else
1a578e9b 6770 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
6771#endif
6772
1a578e9b
AC
6773 GlobalToLocal (&mouseLoc);
6774 XSETINT (result->x, mouseLoc.h);
6775 XSETINT (result->y, mouseLoc.v);
6776
6777 XSETFRAME (result->frame_or_window, f);
6778
6779 result->arg = Qnil;
6780 return Qnil;
6781}
6782
6783\f
6784/* Function to report a mouse movement to the mainstream Emacs code.
6785 The input handler calls this.
6786
6787 We have received a mouse movement event, which is given in *event.
6788 If the mouse is over a different glyph than it was last time, tell
6789 the mainstream emacs code by setting mouse_moved. If not, ask for
6790 another motion event, so we can check again the next time it moves. */
6791
6792static Point last_mouse_motion_position;
6793static Lisp_Object last_mouse_motion_frame;
6794
6795static void
6796note_mouse_movement (frame, pos)
6797 FRAME_PTR frame;
6798 Point *pos;
6799{
e0f712ba
AC
6800#if TARGET_API_MAC_CARBON
6801 Rect r;
6802#endif
6803
1a578e9b
AC
6804 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6805 last_mouse_motion_position = *pos;
6806 XSETFRAME (last_mouse_motion_frame, frame);
6807
e0f712ba
AC
6808#if TARGET_API_MAC_CARBON
6809 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6810#else
1a578e9b 6811 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
e0f712ba 6812#endif
1a578e9b
AC
6813 {
6814 frame->mouse_moved = 1;
6815 last_mouse_scroll_bar = Qnil;
6816 note_mouse_highlight (frame, -1, -1);
6817 }
6818 /* Has the mouse moved off the glyph it was on at the last sighting? */
6819 else if (pos->h < last_mouse_glyph.left
6820 || pos->h >= last_mouse_glyph.right
6821 || pos->v < last_mouse_glyph.top
6822 || pos->v >= last_mouse_glyph.bottom)
6823 {
6824 frame->mouse_moved = 1;
6825 last_mouse_scroll_bar = Qnil;
6826 note_mouse_highlight (frame, pos->h, pos->v);
6827 }
6828}
6829
6830/* This is used for debugging, to turn off note_mouse_highlight. */
6831
6832int disable_mouse_highlight;
6833
6834
6835\f
6836/************************************************************************
6837 Mouse Face
6838 ************************************************************************/
6839
6840/* Find the glyph under window-relative coordinates X/Y in window W.
6841 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6842 strings. Return in *HPOS and *VPOS the row and column number of
6843 the glyph found. Return in *AREA the glyph area containing X.
6844 Value is a pointer to the glyph found or null if X/Y is not on
6845 text, or we can't tell because W's current matrix is not up to
6846 date. */
6847
6848static struct glyph *
e0f712ba 6849x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
1a578e9b
AC
6850 struct window *w;
6851 int x, y;
6852 int *hpos, *vpos, *area;
e0f712ba 6853 int buffer_only_p;
1a578e9b
AC
6854{
6855 struct glyph *glyph, *end;
6856 struct glyph_row *row = NULL;
6857 int x0, i, left_area_width;
6858
6859 /* Find row containing Y. Give up if some row is not enabled. */
6860 for (i = 0; i < w->current_matrix->nrows; ++i)
6861 {
6862 row = MATRIX_ROW (w->current_matrix, i);
6863 if (!row->enabled_p)
6864 return NULL;
6865 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6866 break;
6867 }
6868
6869 *vpos = i;
6870 *hpos = 0;
6871
6872 /* Give up if Y is not in the window. */
6873 if (i == w->current_matrix->nrows)
6874 return NULL;
6875
6876 /* Get the glyph area containing X. */
6877 if (w->pseudo_window_p)
6878 {
6879 *area = TEXT_AREA;
6880 x0 = 0;
6881 }
6882 else
6883 {
6884 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6885 if (x < left_area_width)
6886 {
6887 *area = LEFT_MARGIN_AREA;
6888 x0 = 0;
6889 }
6890 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6891 {
6892 *area = TEXT_AREA;
6893 x0 = row->x + left_area_width;
6894 }
6895 else
6896 {
6897 *area = RIGHT_MARGIN_AREA;
6898 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6899 }
6900 }
6901
6902 /* Find glyph containing X. */
6903 glyph = row->glyphs[*area];
6904 end = glyph + row->used[*area];
6905 while (glyph < end)
6906 {
6907 if (x < x0 + glyph->pixel_width)
6908 {
6909 if (w->pseudo_window_p)
6910 break;
e0f712ba 6911 else if (!buffer_only_p || BUFFERP (glyph->object))
1a578e9b
AC
6912 break;
6913 }
6914
6915 x0 += glyph->pixel_width;
6916 ++glyph;
6917 }
6918
6919 if (glyph == end)
6920 return NULL;
6921
6922 *hpos = glyph - row->glyphs[*area];
6923 return glyph;
6924}
6925
6926
6927/* Convert frame-relative x/y to coordinates relative to window W.
6928 Takes pseudo-windows into account. */
6929
6930static void
6931frame_to_window_pixel_xy (w, x, y)
6932 struct window *w;
6933 int *x, *y;
6934{
6935 if (w->pseudo_window_p)
6936 {
6937 /* A pseudo-window is always full-width, and starts at the
6938 left edge of the frame, plus a frame border. */
6939 struct frame *f = XFRAME (w->frame);
6940 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6941 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6942 }
6943 else
6944 {
6945 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6946 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6947 }
6948}
6949
6950
e0f712ba 6951/* Take proper action when mouse has moved to the mode or header line of
1a578e9b
AC
6952 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6953 mode line. X is relative to the start of the text display area of
3f332ef3 6954 W, so the width of fringes and scroll bars must be subtracted
1a578e9b
AC
6955 to get a position relative to the start of the mode line. */
6956
6957static void
6958note_mode_line_highlight (w, x, mode_line_p)
6959 struct window *w;
6960 int x, mode_line_p;
6961{
6962 struct frame *f = XFRAME (w->frame);
6963 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
e0f712ba 6964 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
1a578e9b
AC
6965 struct glyph_row *row;
6966
6967 if (mode_line_p)
6968 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6969 else
6970 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
e0f712ba 6971
1a578e9b
AC
6972 if (row->enabled_p)
6973 {
6974 struct glyph *glyph, *end;
6975 Lisp_Object help, map;
6976 int x0;
6977
6978 /* Find the glyph under X. */
6979 glyph = row->glyphs[TEXT_AREA];
6980 end = glyph + row->used[TEXT_AREA];
6981 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
3f332ef3 6982 + FRAME_X_LEFT_FRINGE_WIDTH (f));
e0f712ba 6983
1a578e9b
AC
6984 while (glyph < end
6985 && x >= x0 + glyph->pixel_width)
6986 {
6987 x0 += glyph->pixel_width;
6988 ++glyph;
6989 }
6990
6991 if (glyph < end
6992 && STRINGP (glyph->object)
6993 && XSTRING (glyph->object)->intervals
6994 && glyph->charpos >= 0
6995 && glyph->charpos < XSTRING (glyph->object)->size)
6996 {
6997 /* If we're on a string with `help-echo' text property,
6998 arrange for the help to be displayed. This is done by
6999 setting the global variable help_echo to the help string. */
7000 help = Fget_text_property (make_number (glyph->charpos),
7001 Qhelp_echo, glyph->object);
7002 if (!NILP (help))
e0f712ba
AC
7003 {
7004 help_echo = help;
7005 XSETWINDOW (help_echo_window, w);
7006 help_echo_object = glyph->object;
7007 help_echo_pos = glyph->charpos;
7008 }
1a578e9b
AC
7009
7010 /* Change the mouse pointer according to what is under X/Y. */
7011 map = Fget_text_property (make_number (glyph->charpos),
7012 Qlocal_map, glyph->object);
e7cbccd1 7013 if (KEYMAPP (map))
1a578e9b
AC
7014 cursor = f->output_data.mac->nontext_cursor;
7015 else
7016 {
7017 map = Fget_text_property (make_number (glyph->charpos),
7018 Qkeymap, glyph->object);
e7cbccd1 7019 if (KEYMAPP (map))
1a578e9b
AC
7020 cursor = f->output_data.mac->nontext_cursor;
7021 }
7022 }
7023 }
7024
7025#if 0 /* MAC_TODO: mouse cursor */
7026 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7027#endif
7028}
7029
7030
7031/* Take proper action when the mouse has moved to position X, Y on
7032 frame F as regards highlighting characters that have mouse-face
7033 properties. Also de-highlighting chars where the mouse was before.
7034 X and Y can be negative or out of range. */
7035
7036static void
7037note_mouse_highlight (f, x, y)
7038 struct frame *f;
7039 int x, y;
7040{
7041 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7042 int portion;
7043 Lisp_Object window;
7044 struct window *w;
e0f712ba 7045 struct buffer *b;
1a578e9b 7046
e0f712ba
AC
7047#if 0
7048 /* When a menu is active, don't highlight because this looks odd. */
1a578e9b
AC
7049 if (popup_activated ())
7050 return;
7051#endif
7052
e0f712ba 7053 if (NILP (Vmouse_highlight)
1a578e9b
AC
7054 || !f->glyphs_initialized_p)
7055 return;
7056
7057 dpyinfo->mouse_face_mouse_x = x;
7058 dpyinfo->mouse_face_mouse_y = y;
7059 dpyinfo->mouse_face_mouse_frame = f;
7060
7061 if (dpyinfo->mouse_face_defer)
7062 return;
7063
7064 if (gc_in_progress)
7065 {
7066 dpyinfo->mouse_face_deferred_gc = 1;
7067 return;
7068 }
7069
7070 /* Which window is that in? */
7071 window = window_from_coordinates (f, x, y, &portion, 1);
7072
7073 /* If we were displaying active text in another window, clear that. */
7074 if (! EQ (window, dpyinfo->mouse_face_window))
7075 clear_mouse_face (dpyinfo);
7076
7077 /* Not on a window -> return. */
7078 if (!WINDOWP (window))
7079 return;
7080
e0f712ba
AC
7081 /* Reset help_echo. It will get recomputed below. */
7082 help_echo = Qnil;
7083
1a578e9b
AC
7084 /* Convert to window-relative pixel coordinates. */
7085 w = XWINDOW (window);
7086 frame_to_window_pixel_xy (w, &x, &y);
7087
7088 /* Handle tool-bar window differently since it doesn't display a
7089 buffer. */
7090 if (EQ (window, f->tool_bar_window))
7091 {
7092 note_tool_bar_highlight (f, x, y);
7093 return;
7094 }
7095
e0f712ba 7096 /* Mouse is on the mode or header line? */
1a578e9b
AC
7097 if (portion == 1 || portion == 3)
7098 {
1a578e9b
AC
7099 note_mode_line_highlight (w, x, portion == 1);
7100 return;
7101 }
e0f712ba
AC
7102#if 0 /* TODO: mouse cursor */
7103 if (portion == 2)
7104 cursor = f->output_data.x->horizontal_drag_cursor;
1a578e9b 7105 else
e0f712ba 7106 cursor = f->output_data.x->text_cursor;
1a578e9b 7107#endif
1a578e9b
AC
7108 /* Are we in a window whose display is up to date?
7109 And verify the buffer's text has not changed. */
e0f712ba 7110 b = XBUFFER (w->buffer);
1a578e9b
AC
7111 if (/* Within text portion of the window. */
7112 portion == 0
7113 && EQ (w->window_end_valid, w->buffer)
e0f712ba
AC
7114 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7115 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
1a578e9b
AC
7116 {
7117 int hpos, vpos, pos, i, area;
7118 struct glyph *glyph;
e0f712ba
AC
7119 Lisp_Object object;
7120 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7121 Lisp_Object *overlay_vec = NULL;
7122 int len, noverlays;
7123 struct buffer *obuf;
7124 int obegv, ozv, same_region;
1a578e9b
AC
7125
7126 /* Find the glyph under X/Y. */
e0f712ba 7127 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
1a578e9b
AC
7128
7129 /* Clear mouse face if X/Y not over text. */
7130 if (glyph == NULL
7131 || area != TEXT_AREA
7132 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7133 {
7134 clear_mouse_face (dpyinfo);
e0f712ba
AC
7135 /* TODO: mouse cursor */
7136 goto set_cursor;
1a578e9b
AC
7137 }
7138
7139 pos = glyph->charpos;
e0f712ba
AC
7140 object = glyph->object;
7141 if (!STRINGP (object) && !BUFFERP (object))
7142 goto set_cursor;
7143
7144 /* If we get an out-of-range value, return now; avoid an error. */
7145 if (BUFFERP (object) && pos > BUF_Z (b))
7146 goto set_cursor;
7147
7148 /* Make the window's buffer temporarily current for
7149 overlays_at and compute_char_face. */
7150 obuf = current_buffer;
7151 current_buffer = b;
7152 obegv = BEGV;
7153 ozv = ZV;
7154 BEGV = BEG;
7155 ZV = Z;
7156
7157 /* Is this char mouse-active or does it have help-echo? */
7158 position = make_number (pos);
7159
7160 if (BUFFERP (object))
7161 {
7162 /* Put all the overlays we want in a vector in overlay_vec.
7163 Store the length in len. If there are more than 10, make
7164 enough space for all, and try again. */
7165 len = 10;
7166 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7167 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7168 if (noverlays > len)
7169 {
7170 len = noverlays;
7171 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7172 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7173 }
1a578e9b 7174
e0f712ba
AC
7175 /* Sort overlays into increasing priority order. */
7176 noverlays = sort_overlays (overlay_vec, noverlays, w);
7177 }
7178 else
7179 noverlays = 0;
7180
7181 same_region = (EQ (window, dpyinfo->mouse_face_window)
7182 && vpos >= dpyinfo->mouse_face_beg_row
7183 && vpos <= dpyinfo->mouse_face_end_row
7184 && (vpos > dpyinfo->mouse_face_beg_row
7185 || hpos >= dpyinfo->mouse_face_beg_col)
7186 && (vpos < dpyinfo->mouse_face_end_row
7187 || hpos < dpyinfo->mouse_face_end_col
7188 || dpyinfo->mouse_face_past_end));
7189
7190 /* TODO: if (same_region)
7191 mouse cursor */
7192
7193 /* Check mouse-face highlighting. */
7194 if (! same_region
7195 /* If there exists an overlay with mouse-face overlapping
7196 the one we are currently highlighting, we have to
7197 check if we enter the overlapping overlay, and then
7198 highlight that. */
7199 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7200 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7201 {
7202 /* Find the highest priority overlay that has a mouse-face
7203 property. */
7204 overlay = Qnil;
7205 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7206 {
7207 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7208 if (!NILP (mouse_face))
7209 overlay = overlay_vec[i];
7210 }
1a578e9b 7211
e0f712ba
AC
7212 /* If we're actually highlighting the same overlay as
7213 before, there's no need to do that again. */
7214 if (!NILP (overlay)
7215 && EQ (overlay, dpyinfo->mouse_face_overlay))
7216 goto check_help_echo;
1a578e9b 7217
e0f712ba 7218 dpyinfo->mouse_face_overlay = overlay;
1a578e9b 7219
e0f712ba
AC
7220 /* Clear the display of the old active region, if any. */
7221 clear_mouse_face (dpyinfo);
7222 /* TODO: mouse cursor changes. */
1a578e9b 7223
e0f712ba
AC
7224 /* If no overlay applies, get a text property. */
7225 if (NILP (overlay))
7226 mouse_face = Fget_text_property (position, Qmouse_face, object);
1a578e9b 7227
e0f712ba
AC
7228 /* Handle the overlay case. */
7229 if (!NILP (overlay))
7230 {
7231 /* Find the range of text around this char that
7232 should be active. */
7233 Lisp_Object before, after;
7234 int ignore;
7235
7236 before = Foverlay_start (overlay);
7237 after = Foverlay_end (overlay);
7238 /* Record this as the current active region. */
7239 fast_find_position (w, XFASTINT (before),
7240 &dpyinfo->mouse_face_beg_col,
7241 &dpyinfo->mouse_face_beg_row,
7242 &dpyinfo->mouse_face_beg_x,
7243 &dpyinfo->mouse_face_beg_y, Qnil);
7244
7245 dpyinfo->mouse_face_past_end
7246 = !fast_find_position (w, XFASTINT (after),
7247 &dpyinfo->mouse_face_end_col,
7248 &dpyinfo->mouse_face_end_row,
7249 &dpyinfo->mouse_face_end_x,
7250 &dpyinfo->mouse_face_end_y, Qnil);
7251 dpyinfo->mouse_face_window = window;
7252
7253 dpyinfo->mouse_face_face_id
7254 = face_at_buffer_position (w, pos, 0, 0,
7255 &ignore, pos + 1, 1);
7256
7257 /* Display it as active. */
7258 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7259 /* TODO: mouse cursor changes. */
7260 }
7261 /* Handle the text property case. */
7262 else if (! NILP (mouse_face) && BUFFERP (object))
7263 {
7264 /* Find the range of text around this char that
7265 should be active. */
7266 Lisp_Object before, after, beginning, end;
7267 int ignore;
7268
7269 beginning = Fmarker_position (w->start);
7270 end = make_number (BUF_Z (XBUFFER (object))
7271 - XFASTINT (w->window_end_pos));
7272 before
7273 = Fprevious_single_property_change (make_number (pos + 1),
7274 Qmouse_face,
7275 object, beginning);
7276 after
7277 = Fnext_single_property_change (position, Qmouse_face,
7278 object, end);
7279
7280 /* Record this as the current active region. */
7281 fast_find_position (w, XFASTINT (before),
7282 &dpyinfo->mouse_face_beg_col,
7283 &dpyinfo->mouse_face_beg_row,
7284 &dpyinfo->mouse_face_beg_x,
7285 &dpyinfo->mouse_face_beg_y, Qnil);
7286 dpyinfo->mouse_face_past_end
7287 = !fast_find_position (w, XFASTINT (after),
7288 &dpyinfo->mouse_face_end_col,
7289 &dpyinfo->mouse_face_end_row,
7290 &dpyinfo->mouse_face_end_x,
7291 &dpyinfo->mouse_face_end_y, Qnil);
7292 dpyinfo->mouse_face_window = window;
7293
7294 if (BUFFERP (object))
1a578e9b
AC
7295 dpyinfo->mouse_face_face_id
7296 = face_at_buffer_position (w, pos, 0, 0,
7297 &ignore, pos + 1, 1);
7298
e0f712ba
AC
7299 /* Display it as active. */
7300 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7301 /* TODO: mouse cursor changes. */
7302 }
7303 else if (!NILP (mouse_face) && STRINGP (object))
7304 {
7305 Lisp_Object b, e;
7306 int ignore;
7307
7308 b = Fprevious_single_property_change (make_number (pos + 1),
7309 Qmouse_face,
7310 object, Qnil);
7311 e = Fnext_single_property_change (position, Qmouse_face,
7312 object, Qnil);
7313 if (NILP (b))
7314 b = make_number (0);
7315 if (NILP (e))
7316 e = make_number (XSTRING (object)->size - 1);
7317 fast_find_string_pos (w, XINT (b), object,
1a578e9b
AC
7318 &dpyinfo->mouse_face_beg_col,
7319 &dpyinfo->mouse_face_beg_row,
7320 &dpyinfo->mouse_face_beg_x,
e0f712ba
AC
7321 &dpyinfo->mouse_face_beg_y, 0);
7322 fast_find_string_pos (w, XINT (e), object,
7323 &dpyinfo->mouse_face_end_col,
7324 &dpyinfo->mouse_face_end_row,
7325 &dpyinfo->mouse_face_end_x,
7326 &dpyinfo->mouse_face_end_y, 1);
7327 dpyinfo->mouse_face_past_end = 0;
7328 dpyinfo->mouse_face_window = window;
7329 dpyinfo->mouse_face_face_id
7330 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7331 glyph->face_id, 1);
7332 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7333 /* TODO: mouse cursor changes. */
1a578e9b 7334 }
e0f712ba 7335 else if (STRINGP (object) && NILP (mouse_face))
1a578e9b 7336 {
e0f712ba
AC
7337 /* A string which doesn't have mouse-face, but
7338 the text ``under'' it might have. */
7339 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7340 int start = MATRIX_ROW_START_CHARPOS (r);
7341
7342 pos = string_buffer_position (w, object, start);
7343 if (pos > 0)
7344 mouse_face = get_char_property_and_overlay (make_number (pos),
7345 Qmouse_face,
7346 w->buffer,
7347 &overlay);
7348 if (!NILP (mouse_face) && !NILP (overlay))
1a578e9b 7349 {
e0f712ba
AC
7350 Lisp_Object before = Foverlay_start (overlay);
7351 Lisp_Object after = Foverlay_end (overlay);
7352 int ignore;
7353
7354 /* Note that we might not be able to find position
7355 BEFORE in the glyph matrix if the overlay is
7356 entirely covered by a `display' property. In
7357 this case, we overshoot. So let's stop in
7358 the glyph matrix before glyphs for OBJECT. */
7359 fast_find_position (w, XFASTINT (before),
7360 &dpyinfo->mouse_face_beg_col,
7361 &dpyinfo->mouse_face_beg_row,
7362 &dpyinfo->mouse_face_beg_x,
7363 &dpyinfo->mouse_face_beg_y,
7364 object);
7365
7366 dpyinfo->mouse_face_past_end
7367 = !fast_find_position (w, XFASTINT (after),
7368 &dpyinfo->mouse_face_end_col,
7369 &dpyinfo->mouse_face_end_row,
7370 &dpyinfo->mouse_face_end_x,
7371 &dpyinfo->mouse_face_end_y,
7372 Qnil);
7373 dpyinfo->mouse_face_window = window;
7374 dpyinfo->mouse_face_face_id
7375 = face_at_buffer_position (w, pos, 0, 0,
7376 &ignore, pos + 1, 1);
7377
7378 /* Display it as active. */
7379 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7380 /* TODO: mouse cursor changes. */
1a578e9b
AC
7381 }
7382 }
7383 }
1a578e9b 7384
e0f712ba
AC
7385 check_help_echo:
7386
7387 /* Look for a `help-echo' property. */
7388 {
7389 Lisp_Object help, overlay;
7390
7391 /* Check overlays first. */
7392 help = overlay = Qnil;
7393 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7394 {
7395 overlay = overlay_vec[i];
7396 help = Foverlay_get (overlay, Qhelp_echo);
7397 }
7398
7399 if (!NILP (help))
7400 {
7401 help_echo = help;
7402 help_echo_window = window;
7403 help_echo_object = overlay;
7404 help_echo_pos = pos;
7405 }
7406 else
7407 {
7408 Lisp_Object object = glyph->object;
7409 int charpos = glyph->charpos;
7410
7411 /* Try text properties. */
7412 if (STRINGP (object)
7413 && charpos >= 0
7414 && charpos < XSTRING (object)->size)
7415 {
7416 help = Fget_text_property (make_number (charpos),
7417 Qhelp_echo, object);
7418 if (NILP (help))
7419 {
7420 /* If the string itself doesn't specify a help-echo,
7421 see if the buffer text ``under'' it does. */
7422 struct glyph_row *r
7423 = MATRIX_ROW (w->current_matrix, vpos);
7424 int start = MATRIX_ROW_START_CHARPOS (r);
7425 int pos = string_buffer_position (w, object, start);
7426 if (pos > 0)
7427 {
7428 help = Fget_char_property (make_number (pos),
7429 Qhelp_echo, w->buffer);
7430 if (!NILP (help))
7431 {
7432 charpos = pos;
7433 object = w->buffer;
7434 }
7435 }
7436 }
7437 }
7438 else if (BUFFERP (object)
7439 && charpos >= BEGV
7440 && charpos < ZV)
7441 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7442 object);
7443
7444 if (!NILP (help))
7445 {
7446 help_echo = help;
7447 help_echo_window = window;
7448 help_echo_object = object;
7449 help_echo_pos = charpos;
7450 }
7451 }
7452 }
7453
7454 BEGV = obegv;
7455 ZV = ozv;
7456 current_buffer = obuf;
7457 }
7458
7459 set_cursor:
7460 /* TODO: mouse cursor changes. */
7461 ;
7462}
7463
7464static void
7465redo_mouse_highlight ()
7466{
7467 if (!NILP (last_mouse_motion_frame)
7468 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
1a578e9b
AC
7469 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7470 last_mouse_motion_position.h,
7471 last_mouse_motion_position.v);
7472}
7473
7474
7475\f
7476/***********************************************************************
7477 Tool-bars
7478 ***********************************************************************/
7479
7480static int x_tool_bar_item P_ ((struct frame *, int, int,
7481 struct glyph **, int *, int *, int *));
7482
7483/* Tool-bar item index of the item on which a mouse button was pressed
7484 or -1. */
7485
7486static int last_tool_bar_item;
7487
7488
7489/* Get information about the tool-bar item at position X/Y on frame F.
7490 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7491 the current matrix of the tool-bar window of F, or NULL if not
7492 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7493 item in F->current_tool_bar_items. Value is
7494
7495 -1 if X/Y is not on a tool-bar item
7496 0 if X/Y is on the same item that was highlighted before.
7497 1 otherwise. */
7498
7499static int
7500x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7501 struct frame *f;
7502 int x, y;
7503 struct glyph **glyph;
7504 int *hpos, *vpos, *prop_idx;
7505{
7506 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7507 struct window *w = XWINDOW (f->tool_bar_window);
7508 int area;
7509
7510 /* Find the glyph under X/Y. */
e0f712ba 7511 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
1a578e9b
AC
7512 if (*glyph == NULL)
7513 return -1;
7514
7515 /* Get the start of this tool-bar item's properties in
7516 f->current_tool_bar_items. */
7517 if (!tool_bar_item_info (f, *glyph, prop_idx))
7518 return -1;
7519
7520 /* Is mouse on the highlighted item? */
7521 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7522 && *vpos >= dpyinfo->mouse_face_beg_row
7523 && *vpos <= dpyinfo->mouse_face_end_row
7524 && (*vpos > dpyinfo->mouse_face_beg_row
7525 || *hpos >= dpyinfo->mouse_face_beg_col)
7526 && (*vpos < dpyinfo->mouse_face_end_row
7527 || *hpos < dpyinfo->mouse_face_end_col
7528 || dpyinfo->mouse_face_past_end))
7529 return 0;
7530
7531 return 1;
7532}
7533
7534
7535/* Handle mouse button event on the tool-bar of frame F, at
7536 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7537 or ButtonRelase. */
7538
7539static void
7540x_handle_tool_bar_click (f, button_event)
7541 struct frame *f;
7542 EventRecord *button_event;
7543{
7544 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7545 struct window *w = XWINDOW (f->tool_bar_window);
7546 int hpos, vpos, prop_idx;
7547 struct glyph *glyph;
7548 Lisp_Object enabled_p;
7549 int x = button_event->where.h;
7550 int y = button_event->where.v;
7551
7552 /* If not on the highlighted tool-bar item, return. */
7553 frame_to_window_pixel_xy (w, &x, &y);
7554 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7555 return;
7556
7557 /* If item is disabled, do nothing. */
2d4bc735 7558 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
1a578e9b
AC
7559 if (NILP (enabled_p))
7560 return;
7561
7562 if (button_event->what == mouseDown)
7563 {
7564 /* Show item in pressed state. */
7565 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7566 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7567 last_tool_bar_item = prop_idx;
7568 }
7569 else
7570 {
7571 Lisp_Object key, frame;
7572 struct input_event event;
7573
7574 /* Show item in released state. */
7575 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7576 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7577
2d4bc735 7578 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
1a578e9b
AC
7579
7580 XSETFRAME (frame, f);
7581 event.kind = TOOL_BAR_EVENT;
7582 event.frame_or_window = frame;
7583 event.arg = frame;
7584 kbd_buffer_store_event (&event);
7585
7586 event.kind = TOOL_BAR_EVENT;
7587 event.frame_or_window = frame;
7588 event.arg = key;
7589 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7590 button_event->modifiers);
7591 kbd_buffer_store_event (&event);
7592 last_tool_bar_item = -1;
7593 }
7594}
7595
7596
7597/* Possibly highlight a tool-bar item on frame F when mouse moves to
7598 tool-bar window-relative coordinates X/Y. Called from
7599 note_mouse_highlight. */
7600
7601static void
7602note_tool_bar_highlight (f, x, y)
7603 struct frame *f;
7604 int x, y;
7605{
7606 Lisp_Object window = f->tool_bar_window;
7607 struct window *w = XWINDOW (window);
7608 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7609 int hpos, vpos;
7610 struct glyph *glyph;
7611 struct glyph_row *row;
7612 int i;
7613 Lisp_Object enabled_p;
7614 int prop_idx;
7615 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7616 int mouse_down_p, rc;
7617
7618 /* Function note_mouse_highlight is called with negative x(y
7619 values when mouse moves outside of the frame. */
7620 if (x <= 0 || y <= 0)
7621 {
7622 clear_mouse_face (dpyinfo);
7623 return;
7624 }
7625
7626 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7627 if (rc < 0)
7628 {
7629 /* Not on tool-bar item. */
7630 clear_mouse_face (dpyinfo);
7631 return;
7632 }
7633 else if (rc == 0)
7634 /* On same tool-bar item as before. */
7635 goto set_help_echo;
7636
7637 clear_mouse_face (dpyinfo);
7638
7639 /* Mouse is down, but on different tool-bar item? */
7640 mouse_down_p = (dpyinfo->grabbed
7641 && f == last_mouse_frame
7642 && FRAME_LIVE_P (f));
7643 if (mouse_down_p
7644 && last_tool_bar_item != prop_idx)
7645 return;
7646
7647 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7648 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7649
7650 /* If tool-bar item is not enabled, don't highlight it. */
2d4bc735 7651 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
1a578e9b
AC
7652 if (!NILP (enabled_p))
7653 {
7654 /* Compute the x-position of the glyph. In front and past the
7655 image is a space. We include this is the highlighted area. */
7656 row = MATRIX_ROW (w->current_matrix, vpos);
7657 for (i = x = 0; i < hpos; ++i)
7658 x += row->glyphs[TEXT_AREA][i].pixel_width;
7659
7660 /* Record this as the current active region. */
7661 dpyinfo->mouse_face_beg_col = hpos;
7662 dpyinfo->mouse_face_beg_row = vpos;
7663 dpyinfo->mouse_face_beg_x = x;
7664 dpyinfo->mouse_face_beg_y = row->y;
7665 dpyinfo->mouse_face_past_end = 0;
7666
7667 dpyinfo->mouse_face_end_col = hpos + 1;
7668 dpyinfo->mouse_face_end_row = vpos;
7669 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7670 dpyinfo->mouse_face_end_y = row->y;
7671 dpyinfo->mouse_face_window = window;
7672 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7673
7674 /* Display it as active. */
7675 show_mouse_face (dpyinfo, draw);
7676 dpyinfo->mouse_face_image_state = draw;
7677 }
7678
7679 set_help_echo:
7680
7681 /* Set help_echo to a help string.to display for this tool-bar item.
7682 XTread_socket does the rest. */
7683 help_echo_object = help_echo_window = Qnil;
7684 help_echo_pos = -1;
2d4bc735 7685 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
1a578e9b 7686 if (NILP (help_echo))
2d4bc735 7687 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
1a578e9b
AC
7688}
7689
7690
7691\f
e0f712ba
AC
7692/* Find the glyph matrix position of buffer position CHARPOS in window
7693 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7694 current glyphs must be up to date. If CHARPOS is above window
7695 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7696 of last line in W. In the row containing CHARPOS, stop before glyphs
7697 having STOP as object. */
7698
7699#if 0 /* This is a version of fast_find_position that's more correct
7700 in the presence of hscrolling, for example. I didn't install
7701 it right away because the problem fixed is minor, it failed
7702 in 20.x as well, and I think it's too risky to install
7703 so near the release of 21.1. 2001-09-25 gerd. */
7704
7705static int
7706fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7707 struct window *w;
7708 int charpos;
7709 int *hpos, *vpos, *x, *y;
7710 Lisp_Object stop;
7711{
7712 struct glyph_row *row, *first;
7713 struct glyph *glyph, *end;
7714 int i, past_end = 0;
7715
7716 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7717 row = row_containing_pos (w, charpos, first, NULL, 0);
7718 if (row == NULL)
7719 {
7720 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7721 {
7722 *x = *y = *hpos = *vpos = 0;
7723 return 0;
7724 }
7725 else
7726 {
7727 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7728 past_end = 1;
7729 }
7730 }
7731
7732 *x = row->x;
7733 *y = row->y;
7734 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7735
7736 glyph = row->glyphs[TEXT_AREA];
7737 end = glyph + row->used[TEXT_AREA];
7738
7739 /* Skip over glyphs not having an object at the start of the row.
7740 These are special glyphs like truncation marks on terminal
7741 frames. */
7742 if (row->displays_text_p)
7743 while (glyph < end
7744 && INTEGERP (glyph->object)
7745 && !EQ (stop, glyph->object)
7746 && glyph->charpos < 0)
7747 {
7748 *x += glyph->pixel_width;
7749 ++glyph;
7750 }
7751
7752 while (glyph < end
7753 && !INTEGERP (glyph->object)
7754 && !EQ (stop, glyph->object)
7755 && (!BUFFERP (glyph->object)
7756 || glyph->charpos < charpos))
7757 {
7758 *x += glyph->pixel_width;
7759 ++glyph;
7760 }
7761
7762 *hpos = glyph - row->glyphs[TEXT_AREA];
7763 return past_end;
7764}
7765
7766#else /* not 0 */
1a578e9b
AC
7767
7768static int
e0f712ba 7769fast_find_position (w, pos, hpos, vpos, x, y, stop)
1a578e9b
AC
7770 struct window *w;
7771 int pos;
7772 int *hpos, *vpos, *x, *y;
e0f712ba 7773 Lisp_Object stop;
1a578e9b
AC
7774{
7775 int i;
7776 int lastcol;
7777 int maybe_next_line_p = 0;
7778 int line_start_position;
7779 int yb = window_text_bottom_y (w);
e0f712ba
AC
7780 struct glyph_row *row, *best_row;
7781 int row_vpos, best_row_vpos;
1a578e9b
AC
7782 int current_x;
7783
e0f712ba
AC
7784 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7785 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7786
1a578e9b
AC
7787 while (row->y < yb)
7788 {
7789 if (row->used[TEXT_AREA])
7790 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7791 else
7792 line_start_position = 0;
7793
7794 if (line_start_position > pos)
7795 break;
7796 /* If the position sought is the end of the buffer,
7797 don't include the blank lines at the bottom of the window. */
7798 else if (line_start_position == pos
e0f712ba 7799 && pos == BUF_ZV (XBUFFER (w->buffer)))
1a578e9b
AC
7800 {
7801 maybe_next_line_p = 1;
7802 break;
7803 }
7804 else if (line_start_position > 0)
e0f712ba
AC
7805 {
7806 best_row = row;
7807 best_row_vpos = row_vpos;
7808 }
1a578e9b
AC
7809
7810 if (row->y + row->height >= yb)
e0f712ba
AC
7811 break;
7812
1a578e9b
AC
7813 ++row;
7814 ++row_vpos;
7815 }
e0f712ba 7816
1a578e9b
AC
7817 /* Find the right column within BEST_ROW. */
7818 lastcol = 0;
7819 current_x = best_row->x;
7820 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7821 {
7822 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
e0f712ba 7823 int charpos = glyph->charpos;
1a578e9b 7824
e0f712ba 7825 if (BUFFERP (glyph->object))
1a578e9b 7826 {
e0f712ba
AC
7827 if (charpos == pos)
7828 {
7829 *hpos = i;
7830 *vpos = best_row_vpos;
7831 *x = current_x;
7832 *y = best_row->y;
7833 return 1;
7834 }
7835 else if (charpos > pos)
7836 break;
1a578e9b 7837 }
e0f712ba 7838 else if (EQ (glyph->object, stop))
1a578e9b 7839 break;
1a578e9b 7840
e0f712ba
AC
7841 if (charpos > 0)
7842 lastcol = i;
1a578e9b
AC
7843 current_x += glyph->pixel_width;
7844 }
7845
7846 /* If we're looking for the end of the buffer,
7847 and we didn't find it in the line we scanned,
7848 use the start of the following line. */
7849 if (maybe_next_line_p)
7850 {
7851 ++best_row;
7852 ++best_row_vpos;
7853 lastcol = 0;
7854 current_x = best_row->x;
7855 }
7856
7857 *vpos = best_row_vpos;
7858 *hpos = lastcol + 1;
7859 *x = current_x;
7860 *y = best_row->y;
7861 return 0;
7862}
7863
e0f712ba
AC
7864#endif /* not 0 */
7865
7866
7867/* Find the position of the glyph for position POS in OBJECT in
7868 window W's current matrix, and return in *X/*Y the pixel
7869 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7870
7871 RIGHT_P non-zero means return the position of the right edge of the
7872 glyph, RIGHT_P zero means return the left edge position.
7873
7874 If no glyph for POS exists in the matrix, return the position of
7875 the glyph with the next smaller position that is in the matrix, if
7876 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7877 exists in the matrix, return the position of the glyph with the
7878 next larger position in OBJECT.
7879
7880 Value is non-zero if a glyph was found. */
7881
7882static int
7883fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7884 struct window *w;
7885 int pos;
7886 Lisp_Object object;
7887 int *hpos, *vpos, *x, *y;
7888 int right_p;
7889{
7890 int yb = window_text_bottom_y (w);
7891 struct glyph_row *r;
7892 struct glyph *best_glyph = NULL;
7893 struct glyph_row *best_row = NULL;
7894 int best_x = 0;
7895
7896 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7897 r->enabled_p && r->y < yb;
7898 ++r)
7899 {
7900 struct glyph *g = r->glyphs[TEXT_AREA];
7901 struct glyph *e = g + r->used[TEXT_AREA];
7902 int gx;
7903
7904 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7905 if (EQ (g->object, object))
7906 {
7907 if (g->charpos == pos)
7908 {
7909 best_glyph = g;
7910 best_x = gx;
7911 best_row = r;
7912 goto found;
7913 }
7914 else if (best_glyph == NULL
7915 || ((abs (g->charpos - pos)
7916 < abs (best_glyph->charpos - pos))
7917 && (right_p
7918 ? g->charpos < pos
7919 : g->charpos > pos)))
7920 {
7921 best_glyph = g;
7922 best_x = gx;
7923 best_row = r;
7924 }
7925 }
7926 }
7927
7928 found:
7929
7930 if (best_glyph)
7931 {
7932 *x = best_x;
7933 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7934
7935 if (right_p)
7936 {
7937 *x += best_glyph->pixel_width;
7938 ++*hpos;
7939 }
7940
7941 *y = best_row->y;
7942 *vpos = best_row - w->current_matrix->rows;
7943 }
7944
7945 return best_glyph != NULL;
7946}
7947
1a578e9b
AC
7948
7949/* Display the active region described by mouse_face_*
7950 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7951
7952static void
7953show_mouse_face (dpyinfo, draw)
7954 struct mac_display_info *dpyinfo;
7955 enum draw_glyphs_face draw;
7956{
7957 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7958 struct frame *f = XFRAME (WINDOW_FRAME (w));
1a578e9b 7959
e0f712ba
AC
7960 if (/* If window is in the process of being destroyed, don't bother
7961 to do anything. */
7962 w->current_matrix != NULL
7963 /* Don't update mouse highlight if hidden */
7964 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7965 /* Recognize when we are called to operate on rows that don't exist
7966 anymore. This can happen when a window is split. */
7967 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
1a578e9b 7968 {
e0f712ba
AC
7969 int phys_cursor_on_p = w->phys_cursor_on_p;
7970 struct glyph_row *row, *first, *last;
1a578e9b 7971
e0f712ba
AC
7972 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7973 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7974
7975 for (row = first; row <= last && row->enabled_p; ++row)
1a578e9b 7976 {
e0f712ba 7977 int start_hpos, end_hpos, start_x;
1a578e9b 7978
e0f712ba
AC
7979 /* For all but the first row, the highlight starts at column 0. */
7980 if (row == first)
7981 {
7982 start_hpos = dpyinfo->mouse_face_beg_col;
7983 start_x = dpyinfo->mouse_face_beg_x;
7984 }
7985 else
7986 {
7987 start_hpos = 0;
7988 start_x = 0;
7989 }
1a578e9b 7990
e0f712ba
AC
7991 if (row == last)
7992 end_hpos = dpyinfo->mouse_face_end_col;
7993 else
7994 end_hpos = row->used[TEXT_AREA];
1a578e9b 7995
e0f712ba
AC
7996 if (end_hpos > start_hpos)
7997 {
7998 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7999 start_hpos, end_hpos, draw, 0);
1a578e9b 8000
e0f712ba
AC
8001 row->mouse_face_p
8002 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8003 }
8004 }
1a578e9b 8005
e0f712ba
AC
8006 /* When we've written over the cursor, arrange for it to
8007 be displayed again. */
8008 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8009 x_display_cursor (w, 1,
8010 w->phys_cursor.hpos, w->phys_cursor.vpos,
8011 w->phys_cursor.x, w->phys_cursor.y);
8012 }
1a578e9b 8013
1a578e9b
AC
8014#if 0 /* MAC_TODO: mouse cursor */
8015 /* Change the mouse cursor. */
8016 if (draw == DRAW_NORMAL_TEXT)
8017 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8018 f->output_data.x->text_cursor);
8019 else if (draw == DRAW_MOUSE_FACE)
8020 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8021 f->output_data.x->cross_cursor);
8022 else
8023 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8024 f->output_data.x->nontext_cursor);
8025#endif
1a578e9b
AC
8026}
8027
8028/* Clear out the mouse-highlighted active region.
8029 Redraw it un-highlighted first. */
8030
e0f712ba 8031static int
1a578e9b
AC
8032clear_mouse_face (dpyinfo)
8033 struct mac_display_info *dpyinfo;
8034{
e0f712ba
AC
8035 int cleared = 0;
8036
1a578e9b 8037 if (! NILP (dpyinfo->mouse_face_window))
e0f712ba
AC
8038 {
8039 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8040 cleared = 1;
8041 }
1a578e9b
AC
8042
8043 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8044 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8045 dpyinfo->mouse_face_window = Qnil;
e0f712ba
AC
8046 dpyinfo->mouse_face_overlay = Qnil;
8047 return cleared;
1a578e9b
AC
8048}
8049
8050
8051/* Clear any mouse-face on window W. This function is part of the
8052 redisplay interface, and is called from try_window_id and similar
8053 functions to ensure the mouse-highlight is off. */
8054
e0f712ba 8055static void
1a578e9b
AC
8056x_clear_mouse_face (w)
8057 struct window *w;
8058{
8059 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8060 Lisp_Object window;
8061
e0f712ba 8062 BLOCK_INPUT;
1a578e9b
AC
8063 XSETWINDOW (window, w);
8064 if (EQ (window, dpyinfo->mouse_face_window))
8065 clear_mouse_face (dpyinfo);
e0f712ba 8066 UNBLOCK_INPUT;
1a578e9b
AC
8067}
8068
8069
8070/* Just discard the mouse face information for frame F, if any.
8071 This is used when the size of F is changed. */
8072
e0f712ba 8073void
1a578e9b
AC
8074cancel_mouse_face (f)
8075 FRAME_PTR f;
8076{
8077 Lisp_Object window;
8078 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8079
8080 window = dpyinfo->mouse_face_window;
8081 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8082 {
8083 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8084 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8085 dpyinfo->mouse_face_window = Qnil;
8086 }
8087}
8088\f
8089static struct scroll_bar *x_window_to_scroll_bar ();
8090static void x_scroll_bar_report_motion ();
e0f712ba
AC
8091static void x_check_fullscreen P_ ((struct frame *));
8092static void x_check_fullscreen_move P_ ((struct frame *));
8093static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8094
8095
8096/* Try to determine frame pixel position and size of the glyph under
8097 frame pixel coordinates X/Y on frame F . Return the position and
8098 size in *RECT. Value is non-zero if we could compute these
8099 values. */
8100
8101static int
8102glyph_rect (f, x, y, rect)
8103 struct frame *f;
8104 int x, y;
8105 Rect *rect;
8106{
8107 Lisp_Object window;
8108 int part;
8109
8110 window = window_from_coordinates (f, x, y, &part, 0);
8111 if (!NILP (window))
8112 {
8113 struct window *w = XWINDOW (window);
8114 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8115 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8116
8117 frame_to_window_pixel_xy (w, &x, &y);
8118
8119 for (; r < end && r->enabled_p; ++r)
8120 if (r->y <= y && r->y + r->height > y)
8121 {
8122 /* Found the row at y. */
8123 struct glyph *g = r->glyphs[TEXT_AREA];
8124 struct glyph *end = g + r->used[TEXT_AREA];
8125 int gx;
8126
8127 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8128 rect->bottom = rect->top + r->height;
8129
8130 if (x < r->x)
8131 {
8132 /* x is to the left of the first glyph in the row. */
8133 rect->left = XINT (w->left);
8134 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8135 return 1;
8136 }
8137
8138 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8139 if (gx <= x && gx + g->pixel_width > x)
8140 {
8141 /* x is on a glyph. */
8142 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8143 rect->right = rect->left + g->pixel_width;
8144 return 1;
8145 }
8146
8147 /* x is to the right of the last glyph in the row. */
8148 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8149 rect->right = XINT (w->left) + XINT (w->width);
8150 return 1;
8151 }
8152 }
8153
8154 /* The y is not on any row. */
8155 return 0;
8156}
8157
8158/* Record the position of the mouse in last_mouse_glyph. */
8159static void
8160remember_mouse_glyph (f1, gx, gy)
8161 struct frame * f1;
8162 int gx, gy;
8163{
8164 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8165 {
8166 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8167 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8168
8169 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8170 round down even for negative values. */
8171 if (gx < 0)
8172 gx -= width - 1;
8173 if (gy < 0)
8174 gy -= height - 1;
8175#if 0
8176 /* This was the original code from XTmouse_position, but it seems
8177 to give the position of the glyph diagonally next to the one
8178 the mouse is over. */
8179 gx = (gx + width - 1) / width * width;
8180 gy = (gy + height - 1) / height * height;
8181#else
8182 gx = gx / width * width;
8183 gy = gy / height * height;
8184#endif
8185
8186 last_mouse_glyph.left = gx;
8187 last_mouse_glyph.top = gy;
8188 last_mouse_glyph.right = gx + width;
8189 last_mouse_glyph.bottom = gy + height;
8190 }
8191}
1a578e9b
AC
8192
8193/* Return the current position of the mouse.
8194 *fp should be a frame which indicates which display to ask about.
8195
8196 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8197 and *part to the frame, window, and scroll bar part that the mouse
8198 is over. Set *x and *y to the portion and whole of the mouse's
8199 position on the scroll bar.
8200
8201 If the mouse movement started elsewhere, set *fp to the frame the
8202 mouse is on, *bar_window to nil, and *x and *y to the character cell
8203 the mouse is over.
8204
8205 Set *time to the server time-stamp for the time at which the mouse
8206 was at this position.
8207
8208 Don't store anything if we don't have a valid set of values to report.
8209
8210 This clears the mouse_moved flag, so we can wait for the next mouse
8211 movement. */
8212
e0f712ba 8213static void
1a578e9b
AC
8214XTmouse_position (fp, insist, bar_window, part, x, y, time)
8215 FRAME_PTR *fp;
8216 int insist;
8217 Lisp_Object *bar_window;
8218 enum scroll_bar_part *part;
8219 Lisp_Object *x, *y;
8220 unsigned long *time;
8221{
8222 Point mouse_pos;
8223 int ignore1, ignore2;
8224 WindowPtr wp = FrontWindow ();
8225 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8226 Lisp_Object frame, tail;
8227
8228 BLOCK_INPUT;
8229
8230 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8231 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8232 else
8233 {
8234 /* Clear the mouse-moved flag for every frame on this display. */
8235 FOR_EACH_FRAME (tail, frame)
8236 XFRAME (frame)->mouse_moved = 0;
8237
8238 last_mouse_scroll_bar = Qnil;
8239
e0f712ba
AC
8240#if TARGET_API_MAC_CARBON
8241 SetPort (GetWindowPort (wp));
8242#else
1a578e9b 8243 SetPort (wp);
e0f712ba
AC
8244#endif
8245
1a578e9b
AC
8246 GetMouse (&mouse_pos);
8247
8248 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8249 &last_mouse_glyph, insist);
8250
8251 *bar_window = Qnil;
8252 *part = scroll_bar_handle;
8253 *fp = f;
8254 XSETINT (*x, mouse_pos.h);
8255 XSETINT (*y, mouse_pos.v);
8256 *time = last_mouse_movement_time;
8257 }
8258
8259 UNBLOCK_INPUT;
8260}
8261
8262\f
8263/************************************************************************
8264 Scroll bars, general
8265 ************************************************************************/
8266
8267/* Create a scroll bar and return the scroll bar vector for it. W is
8268 the Emacs window on which to create the scroll bar. TOP, LEFT,
e0f712ba 8269 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
1a578e9b
AC
8270 scroll bar. */
8271
8272static struct scroll_bar *
8273x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8274 struct window *w;
8275 int top, left, width, height, disp_top, disp_height;
8276{
8277 struct frame *f = XFRAME (w->frame);
8278 struct scroll_bar *bar
8279 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8280 Rect r;
8281 ControlHandle ch;
8282
8283 BLOCK_INPUT;
8284
8285 r.left = left;
8286 r.top = disp_top;
8287 r.right = left + width;
8288 r.bottom = disp_top + disp_height;
8289
e0f712ba
AC
8290#ifdef TARGET_API_MAC_CARBON
8291 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8292 kControlScrollBarProc, 0L);
8293#else
1a578e9b
AC
8294 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8295 0L);
e0f712ba 8296#endif
1a578e9b
AC
8297 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8298 SetControlReference (ch, (long) bar);
8299
8300 XSETWINDOW (bar->window, w);
8301 XSETINT (bar->top, top);
8302 XSETINT (bar->left, left);
8303 XSETINT (bar->width, width);
8304 XSETINT (bar->height, height);
8305 XSETINT (bar->start, 0);
8306 XSETINT (bar->end, 0);
8307 bar->dragging = Qnil;
8308
8309 /* Add bar to its frame's list of scroll bars. */
8310 bar->next = FRAME_SCROLL_BARS (f);
8311 bar->prev = Qnil;
8312 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8313 if (!NILP (bar->next))
8314 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8315
8316 UNBLOCK_INPUT;
8317 return bar;
8318}
8319
8320
8321/* Draw BAR's handle in the proper position.
8322
8323 If the handle is already drawn from START to END, don't bother
8324 redrawing it, unless REBUILD is non-zero; in that case, always
8325 redraw it. (REBUILD is handy for drawing the handle after expose
8326 events.)
8327
8328 Normally, we want to constrain the start and end of the handle to
8329 fit inside its rectangle, but if the user is dragging the scroll
8330 bar handle, we want to let them drag it down all the way, so that
8331 the bar's top is as far down as it goes; otherwise, there's no way
8332 to move to the very end of the buffer. */
8333
8334static void
8335x_scroll_bar_set_handle (bar, start, end, rebuild)
8336 struct scroll_bar *bar;
8337 int start, end;
8338 int rebuild;
8339{
8340 int dragging = ! NILP (bar->dragging);
8341 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8342 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba
AC
8343 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8344 int length = end - start;
1a578e9b
AC
8345
8346 /* If the display is already accurate, do nothing. */
8347 if (! rebuild
8348 && start == XINT (bar->start)
8349 && end == XINT (bar->end))
8350 return;
8351
8352 BLOCK_INPUT;
8353
e0f712ba
AC
8354 /* Make sure the values are reasonable, and try to preserve the
8355 distance between start and end. */
8356 if (start < 0)
8357 start = 0;
8358 else if (start > top_range)
8359 start = top_range;
8360 end = start + length;
8361
8362 if (end < start)
8363 end = start;
8364 else if (end > top_range && ! dragging)
8365 end = top_range;
8366
8367 /* Store the adjusted setting in the scroll bar. */
8368 XSETINT (bar->start, start);
8369 XSETINT (bar->end, end);
8370
8371 /* Clip the end position, just for display. */
8372 if (end > top_range)
8373 end = top_range;
8374
8375 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8376 top positions, to make sure the handle is always at least that
8377 many pixels tall. */
8378 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8379
8380 SetControlMinimum (ch, 0);
8381 /* Don't inadvertently activate deactivated scroll bars */
8382 if (GetControlMaximum (ch) != -1)
8383 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8384 - (end - start));
8385 SetControlValue (ch, start);
8386#if TARGET_API_MAC_CARBON
8387 SetControlViewSize (ch, end - start);
1a578e9b 8388#endif
1a578e9b
AC
8389
8390 UNBLOCK_INPUT;
8391}
8392
8393
8394/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8395 nil. */
8396
8397static void
8398x_scroll_bar_remove (bar)
8399 struct scroll_bar *bar;
8400{
8401 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba 8402
1a578e9b
AC
8403 BLOCK_INPUT;
8404
8405 /* Destroy the Mac scroll bar control */
8406 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8407
8408 /* Disassociate this scroll bar from its window. */
8409 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8410
8411 UNBLOCK_INPUT;
8412}
8413
1a578e9b
AC
8414/* Set the handle of the vertical scroll bar for WINDOW to indicate
8415 that we are displaying PORTION characters out of a total of WHOLE
8416 characters, starting at POSITION. If WINDOW has no scroll bar,
8417 create one. */
1a578e9b
AC
8418static void
8419XTset_vertical_scroll_bar (w, portion, whole, position)
8420 struct window *w;
8421 int portion, whole, position;
8422{
8423 struct frame *f = XFRAME (w->frame);
8424 struct scroll_bar *bar;
8425 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8426 int window_x, window_y, window_width, window_height;
8427
8428 /* Get window dimensions. */
8429 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8430 top = window_y;
e0f712ba
AC
8431#ifdef MAC_OSX
8432 width = 16;
8433#else
1a578e9b 8434 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
e0f712ba 8435#endif
1a578e9b
AC
8436 height = window_height;
8437
8438 /* Compute the left edge of the scroll bar area. */
8439 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8440 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8441 else
8442 left = XFASTINT (w->left);
8443 left *= CANON_X_UNIT (f);
8444 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8445
8446 /* Compute the width of the scroll bar which might be less than
8447 the width of the area reserved for the scroll bar. */
8448 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8449 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8450 else
8451 sb_width = width;
8452
8453 /* Compute the left edge of the scroll bar. */
8454 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8455 sb_left = left + width - sb_width - (width - sb_width) / 2;
8456 else
8457 sb_left = left + (width - sb_width) / 2;
8458
8459 /* Adjustments according to Inside Macintosh to make it look nice */
8460 disp_top = top;
8461 disp_height = height;
8462 if (disp_top == 0)
8463 {
8464 disp_top = -1;
8465 disp_height++;
8466 }
8467 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8468 {
8469 disp_top++;
8470 disp_height--;
8471 }
8472
8473 if (sb_left + sb_width == PIXEL_WIDTH (f))
8474 sb_left++;
8475
8476 /* Does the scroll bar exist yet? */
8477 if (NILP (w->vertical_scroll_bar))
8478 {
8479 BLOCK_INPUT;
8480 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8481 left, top, width, height, 0);
8482 UNBLOCK_INPUT;
8483 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8484 disp_height);
8485 XSETVECTOR (w->vertical_scroll_bar, bar);
8486 }
8487 else
8488 {
8489 /* It may just need to be moved and resized. */
8490 ControlHandle ch;
8491
8492 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8493 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8494
8495 BLOCK_INPUT;
8496
8497 /* If already correctly positioned, do nothing. */
8498 if (XINT (bar->left) == sb_left
8499 && XINT (bar->top) == top
8500 && XINT (bar->width) == sb_width
8501 && XINT (bar->height) == height)
8502 Draw1Control (ch);
8503 else
8504 {
e0f712ba
AC
8505 /* Clear areas not covered by the scroll bar because it's not as
8506 wide as the area reserved for it . This makes sure a
8507 previous mode line display is cleared after C-x 2 C-x 1, for
8508 example. */
8509 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8510 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8511 left, top, area_width, height, 0);
8512
8513#if 0
1a578e9b
AC
8514 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8515 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8516 sb_left - 1, top, 1, height, 0);
e0f712ba 8517#endif
1a578e9b
AC
8518
8519 HideControl (ch);
8520 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8521 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8522 disp_height);
8523 ShowControl (ch);
8524
8525 /* Remember new settings. */
8526 XSETINT (bar->left, sb_left);
8527 XSETINT (bar->top, top);
8528 XSETINT (bar->width, sb_width);
8529 XSETINT (bar->height, height);
8530 }
8531
8532 UNBLOCK_INPUT;
8533 }
8534
8535 /* Set the scroll bar's current state, unless we're currently being
8536 dragged. */
8537 if (NILP (bar->dragging))
8538 {
8539 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8540
8541 if (whole == 0)
8542 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8543 else
8544 {
8545 int start = ((double) position * top_range) / whole;
8546 int end = ((double) (position + portion) * top_range) / whole;
8547 x_scroll_bar_set_handle (bar, start, end, 0);
8548 }
8549 }
8550}
8551
8552
8553/* The following three hooks are used when we're doing a thorough
8554 redisplay of the frame. We don't explicitly know which scroll bars
8555 are going to be deleted, because keeping track of when windows go
8556 away is a real pain - "Can you say set-window-configuration, boys
8557 and girls?" Instead, we just assert at the beginning of redisplay
8558 that *all* scroll bars are to be removed, and then save a scroll bar
8559 from the fiery pit when we actually redisplay its window. */
8560
8561/* Arrange for all scroll bars on FRAME to be removed at the next call
8562 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8563 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8564
8565static void
8566XTcondemn_scroll_bars (frame)
8567 FRAME_PTR frame;
8568{
8569 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8570 while (! NILP (FRAME_SCROLL_BARS (frame)))
8571 {
8572 Lisp_Object bar;
8573 bar = FRAME_SCROLL_BARS (frame);
8574 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8575 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8576 XSCROLL_BAR (bar)->prev = Qnil;
8577 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8578 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8579 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8580 }
8581}
8582
e0f712ba 8583
1a578e9b
AC
8584/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8585 Note that WINDOW isn't necessarily condemned at all. */
e0f712ba 8586
1a578e9b
AC
8587static void
8588XTredeem_scroll_bar (window)
8589 struct window *window;
8590{
8591 struct scroll_bar *bar;
8592
8593 /* We can't redeem this window's scroll bar if it doesn't have one. */
8594 if (NILP (window->vertical_scroll_bar))
8595 abort ();
8596
8597 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8598
8599 /* Unlink it from the condemned list. */
8600 {
8601 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8602
8603 if (NILP (bar->prev))
8604 {
8605 /* If the prev pointer is nil, it must be the first in one of
8606 the lists. */
8607 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8608 /* It's not condemned. Everything's fine. */
8609 return;
8610 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8611 window->vertical_scroll_bar))
8612 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8613 else
8614 /* If its prev pointer is nil, it must be at the front of
8615 one or the other! */
8616 abort ();
8617 }
8618 else
8619 XSCROLL_BAR (bar->prev)->next = bar->next;
8620
8621 if (! NILP (bar->next))
8622 XSCROLL_BAR (bar->next)->prev = bar->prev;
8623
8624 bar->next = FRAME_SCROLL_BARS (f);
8625 bar->prev = Qnil;
8626 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8627 if (! NILP (bar->next))
8628 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8629 }
8630}
8631
8632/* Remove all scroll bars on FRAME that haven't been saved since the
8633 last call to `*condemn_scroll_bars_hook'. */
8634
8635static void
8636XTjudge_scroll_bars (f)
8637 FRAME_PTR f;
8638{
8639 Lisp_Object bar, next;
8640
8641 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8642
8643 /* Clear out the condemned list now so we won't try to process any
8644 more events on the hapless scroll bars. */
8645 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8646
8647 for (; ! NILP (bar); bar = next)
8648 {
8649 struct scroll_bar *b = XSCROLL_BAR (bar);
8650
8651 x_scroll_bar_remove (b);
8652
8653 next = b->next;
8654 b->next = b->prev = Qnil;
8655 }
8656
8657 /* Now there should be no references to the condemned scroll bars,
8658 and they should get garbage-collected. */
8659}
8660
8661
8662static void
8663activate_scroll_bars (frame)
8664 FRAME_PTR frame;
8665{
8666 Lisp_Object bar;
8667 ControlHandle ch;
8668
8669 bar = FRAME_SCROLL_BARS (frame);
8670 while (! NILP (bar))
8671 {
8672 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
e0f712ba
AC
8673#ifdef TARGET_API_MAC_CARBON
8674 ActivateControl (ch);
8675#else
1a578e9b
AC
8676 SetControlMaximum (ch,
8677 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8678 XINT (XSCROLL_BAR (bar)
8679 ->height)) - 1);
e0f712ba 8680#endif
1a578e9b
AC
8681 bar = XSCROLL_BAR (bar)->next;
8682 }
8683}
8684
8685
8686static void
8687deactivate_scroll_bars (frame)
8688 FRAME_PTR frame;
8689{
8690 Lisp_Object bar;
8691 ControlHandle ch;
8692
8693 bar = FRAME_SCROLL_BARS (frame);
8694 while (! NILP (bar))
8695 {
8696 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
e0f712ba
AC
8697#ifdef TARGET_API_MAC_CARBON
8698 DeactivateControl (ch);
8699#else
1a578e9b 8700 SetControlMaximum (ch, XINT (-1));
e0f712ba 8701#endif
1a578e9b
AC
8702 bar = XSCROLL_BAR (bar)->next;
8703 }
8704}
8705
8706/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8707 is set to something other than no_event, it is enqueued.
8708
8709 This may be called from a signal handler, so we have to ignore GC
8710 mark bits. */
8711
8712static void
8713x_scroll_bar_handle_click (bar, part_code, er, bufp)
8714 struct scroll_bar *bar;
8715 int part_code;
8716 EventRecord *er;
8717 struct input_event *bufp;
8718{
8719 if (! GC_WINDOWP (bar->window))
8720 abort ();
8721
8722 bufp->kind = scroll_bar_click;
8723 bufp->frame_or_window = bar->window;
8724 bufp->arg = Qnil;
8725
8726 bar->dragging = Qnil;
8727
8728 switch (part_code)
8729 {
8730 case kControlUpButtonPart:
8731 bufp->part = scroll_bar_up_arrow;
8732 break;
8733 case kControlDownButtonPart:
8734 bufp->part = scroll_bar_down_arrow;
8735 break;
8736 case kControlPageUpPart:
8737 bufp->part = scroll_bar_above_handle;
8738 break;
8739 case kControlPageDownPart:
8740 bufp->part = scroll_bar_below_handle;
8741 break;
e0f712ba
AC
8742#ifdef TARGET_API_MAC_CARBON
8743 default:
8744#else
1a578e9b 8745 case kControlIndicatorPart:
e0f712ba 8746#endif
1a578e9b
AC
8747 if (er->what == mouseDown)
8748 bar->dragging = make_number (0);
8749 XSETVECTOR (last_mouse_scroll_bar, bar);
8750 bufp->part = scroll_bar_handle;
8751 break;
8752 }
8753}
8754
8755
8756/* Handle some mouse motion while someone is dragging the scroll bar.
8757
8758 This may be called from a signal handler, so we have to ignore GC
8759 mark bits. */
8760
8761static void
8762x_scroll_bar_note_movement (bar, y_pos, t)
8763 struct scroll_bar *bar;
8764 int y_pos;
8765 Time t;
8766{
8767 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8768
8769 last_mouse_movement_time = t;
8770
8771 f->mouse_moved = 1;
8772 XSETVECTOR (last_mouse_scroll_bar, bar);
8773
8774 /* If we're dragging the bar, display it. */
8775 if (! GC_NILP (bar->dragging))
8776 {
8777 /* Where should the handle be now? */
8778 int new_start = y_pos - 24;
8779
8780 if (new_start != XINT (bar->start))
8781 {
8782 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8783
8784 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8785 }
8786 }
8787}
8788
8789
8790/* Return information to the user about the current position of the
8791 mouse on the scroll bar. */
8792
8793static void
8794x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8795 FRAME_PTR *fp;
8796 Lisp_Object *bar_window;
8797 enum scroll_bar_part *part;
8798 Lisp_Object *x, *y;
8799 unsigned long *time;
8800{
8801 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8802 WindowPtr wp = FrontWindow ();
8803 Point mouse_pos;
8804 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8805 int win_y, top_range;
8806
e0f712ba
AC
8807#if TARGET_API_MAC_CARBON
8808 SetPort (GetWindowPort (wp));
8809#else
1a578e9b 8810 SetPort (wp);
e0f712ba
AC
8811#endif
8812
1a578e9b
AC
8813 GetMouse (&mouse_pos);
8814
8815 win_y = mouse_pos.v - XINT (bar->top);
8816 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8817
8818 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8819
8820 win_y -= 24;
8821
8822 if (! NILP (bar->dragging))
8823 win_y -= XINT (bar->dragging);
8824
8825 if (win_y < 0)
8826 win_y = 0;
8827 if (win_y > top_range)
8828 win_y = top_range;
8829
8830 *fp = f;
8831 *bar_window = bar->window;
8832
8833 if (! NILP (bar->dragging))
8834 *part = scroll_bar_handle;
8835 else if (win_y < XINT (bar->start))
8836 *part = scroll_bar_above_handle;
8837 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8838 *part = scroll_bar_handle;
8839 else
8840 *part = scroll_bar_below_handle;
8841
8842 XSETINT (*x, win_y);
8843 XSETINT (*y, top_range);
8844
8845 f->mouse_moved = 0;
8846 last_mouse_scroll_bar = Qnil;
8847
8848 *time = last_mouse_movement_time;
8849}
8850\f
8851/***********************************************************************
8852 Text Cursor
8853 ***********************************************************************/
8854
e0f712ba
AC
8855/* Notice if the text cursor of window W has been overwritten by a
8856 drawing operation that outputs glyphs starting at START_X and
8857 ending at END_X in the line given by output_cursor.vpos.
8858 Coordinates are area-relative. END_X < 0 means all the rest
8859 of the line after START_X has been written. */
1a578e9b
AC
8860
8861static void
e0f712ba 8862notice_overwritten_cursor (w, area, x0, x1, y0, y1)
1a578e9b 8863 struct window *w;
e0f712ba
AC
8864 enum glyph_row_area area;
8865 int x0, x1, y0, y1;
8866{
8867 if (area == TEXT_AREA
8868 && w->phys_cursor_on_p
8869 && y0 <= w->phys_cursor.y
8870 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8871 && x0 <= w->phys_cursor.x
8872 && (x1 < 0 || x1 > w->phys_cursor.x))
1a578e9b
AC
8873 w->phys_cursor_on_p = 0;
8874}
8875
8876
8877/* Set clipping for output in glyph row ROW. W is the window in which
8878 we operate. GC is the graphics context to set clipping in.
8879 WHOLE_LINE_P non-zero means include the areas used for truncation
8880 mark display and alike in the clipping rectangle.
8881
8882 ROW may be a text row or, e.g., a mode line. Text rows must be
8883 clipped to the interior of the window dedicated to text display,
8884 mode lines must be clipped to the whole window. */
8885
8886static void
8887x_clip_to_row (w, row, gc, whole_line_p)
8888 struct window *w;
8889 struct glyph_row *row;
8890 GC gc;
8891 int whole_line_p;
8892{
8893 struct frame *f = XFRAME (WINDOW_FRAME (w));
8894 Rect clip_rect;
8895 int window_x, window_y, window_width, window_height;
8896
8897 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8898
8899 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8900 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8901 clip_rect.top = max (clip_rect.top, window_y);
8902 clip_rect.right = clip_rect.left + window_width;
8903 clip_rect.bottom = clip_rect.top + row->visible_height;
8904
8905 /* If clipping to the whole line, including trunc marks, extend
8906 the rectangle to the left and increase its width. */
8907 if (whole_line_p)
8908 {
3f332ef3
KS
8909 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8910 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
1a578e9b
AC
8911 }
8912
8913 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8914}
8915
8916
8917/* Draw a hollow box cursor on window W in glyph row ROW. */
8918
8919static void
8920x_draw_hollow_cursor (w, row)
8921 struct window *w;
8922 struct glyph_row *row;
8923{
8924 struct frame *f = XFRAME (WINDOW_FRAME (w));
8925 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8926 Display *dpy = FRAME_MAC_DISPLAY (f);
8927 int x, y, wd, h;
8928 XGCValues xgcv;
8929 struct glyph *cursor_glyph;
8930 GC gc;
8931
8932 /* Compute frame-relative coordinates from window-relative
8933 coordinates. */
8934 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8935 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8936 + row->ascent - w->phys_cursor_ascent);
8937 h = row->height - 1;
8938
8939 /* Get the glyph the cursor is on. If we can't tell because
8940 the current matrix is invalid or such, give up. */
8941 cursor_glyph = get_phys_cursor_glyph (w);
8942 if (cursor_glyph == NULL)
8943 return;
8944
8945 /* Compute the width of the rectangle to draw. If on a stretch
8946 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8947 rectangle as wide as the glyph, but use a canonical character
8948 width instead. */
8949 wd = cursor_glyph->pixel_width - 1;
8950 if (cursor_glyph->type == STRETCH_GLYPH
8951 && !x_stretch_cursor_p)
8952 wd = min (CANON_X_UNIT (f), wd);
8953
8954 /* The foreground of cursor_gc is typically the same as the normal
8955 background color, which can cause the cursor box to be invisible. */
8956 xgcv.foreground = f->output_data.mac->cursor_pixel;
8957 if (dpyinfo->scratch_cursor_gc)
8958 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8959 else
8960 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8961 GCForeground, &xgcv);
8962 gc = dpyinfo->scratch_cursor_gc;
8963
8964 /* Set clipping, draw the rectangle, and reset clipping again. */
8965 x_clip_to_row (w, row, gc, 0);
8966 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
8967 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8968}
8969
8970
8971/* Draw a bar cursor on window W in glyph row ROW.
8972
8973 Implementation note: One would like to draw a bar cursor with an
8974 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8975 Unfortunately, I didn't find a font yet that has this property set.
8976 --gerd. */
8977
8978static void
8979x_draw_bar_cursor (w, row, width)
8980 struct window *w;
8981 struct glyph_row *row;
8982 int width;
8983{
8984 /* If cursor hpos is out of bounds, don't draw garbage. This can
8985 happen in mini-buffer windows when switching between echo area
8986 glyphs and mini-buffer. */
8987 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8988 {
8989 struct frame *f = XFRAME (w->frame);
8990 struct glyph *cursor_glyph;
8991 GC gc;
8992 int x;
8993 unsigned long mask;
8994 XGCValues xgcv;
8995 Display *dpy;
8996 Window window;
8997
8998 cursor_glyph = get_phys_cursor_glyph (w);
8999 if (cursor_glyph == NULL)
9000 return;
9001
9002 xgcv.background = f->output_data.mac->cursor_pixel;
9003 xgcv.foreground = f->output_data.mac->cursor_pixel;
9004 mask = GCForeground | GCBackground;
9005 dpy = FRAME_MAC_DISPLAY (f);
9006 window = FRAME_MAC_WINDOW (f);
9007 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9008
9009 if (gc)
9010 XChangeGC (dpy, gc, mask, &xgcv);
9011 else
9012 {
9013 gc = XCreateGC (dpy, window, mask, &xgcv);
9014 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9015 }
9016
9017 if (width < 0)
9018 width = f->output_data.mac->cursor_width;
9019
9020 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9021 x_clip_to_row (w, row, gc, 0);
9022 XFillRectangle (dpy, window, gc,
9023 x,
9024 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9025 min (cursor_glyph->pixel_width, width),
9026 row->height);
9027 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9028 }
9029}
9030
9031
9032/* Clear the cursor of window W to background color, and mark the
9033 cursor as not shown. This is used when the text where the cursor
9034 is is about to be rewritten. */
9035
9036static void
9037x_clear_cursor (w)
9038 struct window *w;
9039{
9040 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9041 x_update_window_cursor (w, 0);
9042}
9043
9044
9045/* Draw the cursor glyph of window W in glyph row ROW. See the
9046 comment of x_draw_glyphs for the meaning of HL. */
9047
9048static void
9049x_draw_phys_cursor_glyph (w, row, hl)
9050 struct window *w;
9051 struct glyph_row *row;
9052 enum draw_glyphs_face hl;
9053{
9054 /* If cursor hpos is out of bounds, don't draw garbage. This can
9055 happen in mini-buffer windows when switching between echo area
9056 glyphs and mini-buffer. */
9057 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9058 {
e0f712ba 9059 int on_p = w->phys_cursor_on_p;
1a578e9b 9060 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
e0f712ba
AC
9061 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9062 hl, 0);
9063 w->phys_cursor_on_p = on_p;
1a578e9b
AC
9064
9065 /* When we erase the cursor, and ROW is overlapped by other
9066 rows, make sure that these overlapping parts of other rows
9067 are redrawn. */
9068 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9069 {
9070 if (row > w->current_matrix->rows
9071 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9072 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9073
9074 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9075 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9076 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9077 }
9078 }
9079}
9080
9081
9082/* Erase the image of a cursor of window W from the screen. */
9083
9084static void
9085x_erase_phys_cursor (w)
9086 struct window *w;
9087{
9088 struct frame *f = XFRAME (w->frame);
9089 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9090 int hpos = w->phys_cursor.hpos;
9091 int vpos = w->phys_cursor.vpos;
9092 int mouse_face_here_p = 0;
9093 struct glyph_matrix *active_glyphs = w->current_matrix;
9094 struct glyph_row *cursor_row;
9095 struct glyph *cursor_glyph;
9096 enum draw_glyphs_face hl;
9097
9098 /* No cursor displayed or row invalidated => nothing to do on the
9099 screen. */
9100 if (w->phys_cursor_type == NO_CURSOR)
9101 goto mark_cursor_off;
9102
9103 /* VPOS >= active_glyphs->nrows means that window has been resized.
9104 Don't bother to erase the cursor. */
9105 if (vpos >= active_glyphs->nrows)
9106 goto mark_cursor_off;
9107
9108 /* If row containing cursor is marked invalid, there is nothing we
9109 can do. */
9110 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9111 if (!cursor_row->enabled_p)
9112 goto mark_cursor_off;
9113
796d4ec7 9114 /* If row is completely invisible, don't attempt to delete a cursor which
e0f712ba 9115 isn't there. This may happen if cursor is at top of window, and
796d4ec7
KS
9116 we switch to a buffer with a header line in that window. */
9117 if (cursor_row->visible_height <= 0)
9118 goto mark_cursor_off;
9119
1a578e9b
AC
9120 /* This can happen when the new row is shorter than the old one.
9121 In this case, either x_draw_glyphs or clear_end_of_line
9122 should have cleared the cursor. Note that we wouldn't be
9123 able to erase the cursor in this case because we don't have a
9124 cursor glyph at hand. */
9125 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9126 goto mark_cursor_off;
9127
9128 /* If the cursor is in the mouse face area, redisplay that when
9129 we clear the cursor. */
9130 if (! NILP (dpyinfo->mouse_face_window)
9131 && w == XWINDOW (dpyinfo->mouse_face_window)
9132 && (vpos > dpyinfo->mouse_face_beg_row
9133 || (vpos == dpyinfo->mouse_face_beg_row
9134 && hpos >= dpyinfo->mouse_face_beg_col))
9135 && (vpos < dpyinfo->mouse_face_end_row
9136 || (vpos == dpyinfo->mouse_face_end_row
9137 && hpos < dpyinfo->mouse_face_end_col))
9138 /* Don't redraw the cursor's spot in mouse face if it is at the
9139 end of a line (on a newline). The cursor appears there, but
9140 mouse highlighting does not. */
9141 && cursor_row->used[TEXT_AREA] > hpos)
9142 mouse_face_here_p = 1;
9143
9144 /* Maybe clear the display under the cursor. */
9145 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9146 {
9147 int x;
9148 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9149
9150 cursor_glyph = get_phys_cursor_glyph (w);
9151 if (cursor_glyph == NULL)
9152 goto mark_cursor_off;
9153
9154 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9155
9156 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9157 x,
9158 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9159 cursor_row->y)),
9160 cursor_glyph->pixel_width,
9161 cursor_row->visible_height,
9162 0);
9163 }
9164
9165 /* Erase the cursor by redrawing the character underneath it. */
9166 if (mouse_face_here_p)
9167 hl = DRAW_MOUSE_FACE;
1a578e9b
AC
9168 else
9169 hl = DRAW_NORMAL_TEXT;
9170 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9171
9172 mark_cursor_off:
9173 w->phys_cursor_on_p = 0;
9174 w->phys_cursor_type = NO_CURSOR;
9175}
9176
9177
e0f712ba
AC
9178/* Non-zero if physical cursor of window W is within mouse face. */
9179
9180static int
9181cursor_in_mouse_face_p (w)
9182 struct window *w;
9183{
9184 struct mac_display_info *dpyinfo
9185 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9186 int in_mouse_face = 0;
9187
9188 if (WINDOWP (dpyinfo->mouse_face_window)
9189 && XWINDOW (dpyinfo->mouse_face_window) == w)
9190 {
9191 int hpos = w->phys_cursor.hpos;
9192 int vpos = w->phys_cursor.vpos;
9193
9194 if (vpos >= dpyinfo->mouse_face_beg_row
9195 && vpos <= dpyinfo->mouse_face_end_row
9196 && (vpos > dpyinfo->mouse_face_beg_row
9197 || hpos >= dpyinfo->mouse_face_beg_col)
9198 && (vpos < dpyinfo->mouse_face_end_row
9199 || hpos < dpyinfo->mouse_face_end_col
9200 || dpyinfo->mouse_face_past_end))
9201 in_mouse_face = 1;
9202 }
9203
9204 return in_mouse_face;
9205}
9206
9207
1a578e9b
AC
9208/* Display or clear cursor of window W. If ON is zero, clear the
9209 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9210 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9211
9212void
9213x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9214 struct window *w;
9215 int on, hpos, vpos, x, y;
9216{
9217 struct frame *f = XFRAME (w->frame);
9218 int new_cursor_type;
9219 int new_cursor_width;
9220 struct glyph_matrix *current_glyphs;
9221 struct glyph_row *glyph_row;
9222 struct glyph *glyph;
e0f712ba
AC
9223 int cursor_non_selected;
9224 int active_cursor = 1;
1a578e9b
AC
9225
9226 /* This is pointless on invisible frames, and dangerous on garbaged
9227 windows and frames; in the latter case, the frame or window may
9228 be in the midst of changing its size, and x and y may be off the
9229 window. */
9230 if (! FRAME_VISIBLE_P (f)
9231 || FRAME_GARBAGED_P (f)
9232 || vpos >= w->current_matrix->nrows
9233 || hpos >= w->current_matrix->matrix_w)
9234 return;
9235
9236 /* If cursor is off and we want it off, return quickly. */
9237 if (!on && !w->phys_cursor_on_p)
9238 return;
9239
9240 current_glyphs = w->current_matrix;
9241 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9242 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9243
9244 /* If cursor row is not enabled, we don't really know where to
9245 display the cursor. */
9246 if (!glyph_row->enabled_p)
9247 {
9248 w->phys_cursor_on_p = 0;
9249 return;
9250 }
9251
9252 xassert (interrupt_input_blocked);
9253
9254 /* Set new_cursor_type to the cursor we want to be displayed. In a
9255 mini-buffer window, we want the cursor only to appear if we are
9256 reading input from this window. For the selected window, we want
9257 the cursor type given by the frame parameter. If explicitly
9258 marked off, draw no cursor. In all other cases, we want a hollow
9259 box cursor. */
e0f712ba
AC
9260 cursor_non_selected
9261 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
9262 w->buffer));
1a578e9b
AC
9263 new_cursor_width = -1;
9264 if (cursor_in_echo_area
9265 && FRAME_HAS_MINIBUF_P (f)
9266 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
9267 {
9268 if (w == XWINDOW (echo_area_window))
9269 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9270 else
1a578e9b 9271 {
e0f712ba 9272 if (cursor_non_selected)
1a578e9b 9273 new_cursor_type = HOLLOW_BOX_CURSOR;
e0f712ba
AC
9274 else
9275 new_cursor_type = NO_CURSOR;
9276 active_cursor = 0;
1a578e9b 9277 }
e0f712ba
AC
9278 }
9279 else
9280 {
9281 if (f != FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame
9282 || w != XWINDOW (f->selected_window))
9283 {
9284 active_cursor = 0;
9285
9286 if (MINI_WINDOW_P (w)
9287 || !cursor_non_selected
9288 || NILP (XBUFFER (w->buffer)->cursor_type))
9289 new_cursor_type = NO_CURSOR;
9290 else
9291 new_cursor_type = HOLLOW_BOX_CURSOR;
9292 }
1a578e9b 9293 else
e0f712ba 9294 {
1a578e9b
AC
9295 struct buffer *b = XBUFFER (w->buffer);
9296
9297 if (EQ (b->cursor_type, Qt))
e0f712ba 9298 new_cursor_type = FRAME_DESIRED_CURSOR (f);
1a578e9b
AC
9299 else
9300 new_cursor_type = x_specified_cursor_type (b->cursor_type,
9301 &new_cursor_width);
e0f712ba
AC
9302 if (w->cursor_off_p)
9303 {
9304 if (new_cursor_type == FILLED_BOX_CURSOR)
9305 new_cursor_type = HOLLOW_BOX_CURSOR;
9306 else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
9307 new_cursor_width = 1;
9308 else
9309 new_cursor_type = NO_CURSOR;
9310 }
1a578e9b
AC
9311 }
9312 }
9313
9314 /* If cursor is currently being shown and we don't want it to be or
9315 it is in the wrong place, or the cursor type is not what we want,
9316 erase it. */
9317 if (w->phys_cursor_on_p
9318 && (!on
9319 || w->phys_cursor.x != x
9320 || w->phys_cursor.y != y
e0f712ba
AC
9321 || new_cursor_type != w->phys_cursor_type
9322 || (new_cursor_type == BAR_CURSOR
9323 && new_cursor_width != w->phys_cursor_width)))
1a578e9b
AC
9324 x_erase_phys_cursor (w);
9325
9326 /* If the cursor is now invisible and we want it to be visible,
9327 display it. */
9328 if (on && !w->phys_cursor_on_p)
9329 {
9330 w->phys_cursor_ascent = glyph_row->ascent;
9331 w->phys_cursor_height = glyph_row->height;
9332
9333 /* Set phys_cursor_.* before x_draw_.* is called because some
9334 of them may need the information. */
9335 w->phys_cursor.x = x;
9336 w->phys_cursor.y = glyph_row->y;
9337 w->phys_cursor.hpos = hpos;
9338 w->phys_cursor.vpos = vpos;
9339 w->phys_cursor_type = new_cursor_type;
e0f712ba 9340 w->phys_cursor_width = new_cursor_width;
1a578e9b
AC
9341 w->phys_cursor_on_p = 1;
9342
9343 switch (new_cursor_type)
9344 {
9345 case HOLLOW_BOX_CURSOR:
9346 x_draw_hollow_cursor (w, glyph_row);
9347 break;
9348
9349 case FILLED_BOX_CURSOR:
9350 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9351 break;
9352
9353 case BAR_CURSOR:
9354 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9355 break;
9356
9357 case NO_CURSOR:
9358 break;
9359
9360 default:
9361 abort ();
9362 }
1a578e9b 9363 }
1a578e9b
AC
9364}
9365
9366
9367/* Display the cursor on window W, or clear it. X and Y are window
9368 relative pixel coordinates. HPOS and VPOS are glyph matrix
9369 positions. If W is not the selected window, display a hollow
9370 cursor. ON non-zero means display the cursor at X, Y which
9371 correspond to HPOS, VPOS, otherwise it is cleared. */
9372
9373void
9374x_display_cursor (w, on, hpos, vpos, x, y)
9375 struct window *w;
9376 int on, hpos, vpos, x, y;
9377{
9378 BLOCK_INPUT;
9379 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9380 UNBLOCK_INPUT;
9381}
9382
9383
9384/* Display the cursor on window W, or clear it, according to ON_P.
9385 Don't change the cursor's position. */
9386
9387void
9388x_update_cursor (f, on_p)
9389 struct frame *f;
e0f712ba 9390 int on_p;
1a578e9b
AC
9391{
9392 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9393}
9394
9395
9396/* Call x_update_window_cursor with parameter ON_P on all leaf windows
9397 in the window tree rooted at W. */
9398
9399static void
9400x_update_cursor_in_window_tree (w, on_p)
9401 struct window *w;
9402 int on_p;
9403{
9404 while (w)
9405 {
9406 if (!NILP (w->hchild))
9407 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9408 else if (!NILP (w->vchild))
9409 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9410 else
9411 x_update_window_cursor (w, on_p);
9412
9413 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9414 }
9415}
9416
9417
9418/* Switch the display of W's cursor on or off, according to the value
9419 of ON. */
9420
9421static void
9422x_update_window_cursor (w, on)
9423 struct window *w;
9424 int on;
9425{
9426 /* Don't update cursor in windows whose frame is in the process
9427 of being deleted. */
9428 if (w->current_matrix)
9429 {
9430 BLOCK_INPUT;
e0f712ba
AC
9431 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9432 w->phys_cursor.vpos, w->phys_cursor.x,
9433 w->phys_cursor.y);
1a578e9b
AC
9434 UNBLOCK_INPUT;
9435 }
9436}
9437
1a578e9b 9438
1a578e9b 9439
e0f712ba
AC
9440\f
9441/* Icons. */
1a578e9b 9442
e0f712ba 9443#if 0 /* MAC_TODO: no icon support yet. */
1a578e9b 9444int
e0f712ba 9445x_bitmap_icon (f, icon)
1a578e9b 9446 struct frame *f;
e0f712ba 9447 Lisp_Object icon;
1a578e9b 9448{
e0f712ba 9449 HANDLE hicon;
1a578e9b 9450
e0f712ba 9451 if (FRAME_W32_WINDOW (f) == 0)
1a578e9b
AC
9452 return 1;
9453
e0f712ba
AC
9454 if (NILP (icon))
9455 hicon = LoadIcon (hinst, EMACS_CLASS);
9456 else if (STRINGP (icon))
9457 hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
9458 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9459 else if (SYMBOLP (icon))
9460 {
9461 LPCTSTR name;
9462
9463 if (EQ (icon, intern ("application")))
9464 name = (LPCTSTR) IDI_APPLICATION;
9465 else if (EQ (icon, intern ("hand")))
9466 name = (LPCTSTR) IDI_HAND;
9467 else if (EQ (icon, intern ("question")))
9468 name = (LPCTSTR) IDI_QUESTION;
9469 else if (EQ (icon, intern ("exclamation")))
9470 name = (LPCTSTR) IDI_EXCLAMATION;
9471 else if (EQ (icon, intern ("asterisk")))
9472 name = (LPCTSTR) IDI_ASTERISK;
9473 else if (EQ (icon, intern ("winlogo")))
9474 name = (LPCTSTR) IDI_WINLOGO;
9475 else
9476 return 1;
1a578e9b 9477
e0f712ba 9478 hicon = LoadIcon (NULL, name);
1a578e9b 9479 }
e0f712ba 9480 else
1a578e9b
AC
9481 return 1;
9482
e0f712ba
AC
9483 if (hicon == NULL)
9484 return 1;
1a578e9b 9485
e0f712ba
AC
9486 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9487 (LPARAM) hicon);
1a578e9b
AC
9488
9489 return 0;
9490}
e0f712ba 9491#endif /* MAC_TODO */
1a578e9b 9492\f
e0f712ba
AC
9493/************************************************************************
9494 Handling X errors
9495 ************************************************************************/
1a578e9b 9496
e0f712ba
AC
9497/* Display Error Handling functions not used on W32. Listing them here
9498 helps diff stay in step when comparing w32term.c with xterm.c.
1a578e9b 9499
1a578e9b 9500x_error_catcher (display, error)
1a578e9b 9501x_catch_errors (dpy)
1a578e9b 9502x_catch_errors_unwind (old_val)
1a578e9b 9503x_check_errors (dpy, format)
1a578e9b 9504x_had_errors_p (dpy)
1a578e9b 9505x_clear_errors (dpy)
1a578e9b 9506x_uncatch_errors (dpy, count)
1a578e9b 9507x_trace_wire ()
e0f712ba
AC
9508x_connection_signal (signalnum)
9509x_connection_closed (dpy, error_message)
1a578e9b 9510x_error_quitter (display, error)
1a578e9b 9511x_error_handler (display, error)
1a578e9b 9512x_io_error_quitter (display)
1a578e9b 9513
e0f712ba
AC
9514 */
9515
1a578e9b
AC
9516\f
9517/* Changing the font of the frame. */
9518
9519/* Give frame F the font named FONTNAME as its default font, and
9520 return the full name of that font. FONTNAME may be a wildcard
9521 pattern; in that case, we choose some font that fits the pattern.
9522 The return value shows which font we chose. */
9523
9524Lisp_Object
9525x_new_font (f, fontname)
9526 struct frame *f;
9527 register char *fontname;
9528{
9529 struct font_info *fontp
9530 = FS_LOAD_FONT (f, 0, fontname, -1);
9531
9532 if (!fontp)
9533 return Qnil;
9534
e0f712ba
AC
9535 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9536 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9537 FRAME_FONTSET (f) = -1;
9538
1a578e9b
AC
9539 /* Compute the scroll bar width in character columns. */
9540 if (f->scroll_bar_pixel_width > 0)
9541 {
e0f712ba 9542 int wid = FONT_WIDTH (FRAME_FONT (f));
1a578e9b
AC
9543 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9544 }
9545 else
9546 {
e0f712ba 9547 int wid = FONT_WIDTH (FRAME_FONT (f));
1a578e9b
AC
9548 f->scroll_bar_cols = (14 + wid - 1) / wid;
9549 }
9550
9551 /* Now make the frame display the given font. */
9552 if (FRAME_MAC_WINDOW (f) != 0)
9553 {
1a578e9b 9554 frame_update_line_height (f);
e0f712ba
AC
9555 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9556 x_set_window_size (f, 0, f->width, f->height);
1a578e9b
AC
9557 }
9558 else
e0f712ba
AC
9559 /* If we are setting a new frame's font for the first time,
9560 there are no faces yet, so this font's height is the line height. */
9561 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
1a578e9b
AC
9562
9563 return build_string (fontp->full_name);
9564}
e0f712ba 9565\f
1a578e9b 9566/* Give frame F the fontset named FONTSETNAME as its default font, and
e0f712ba
AC
9567 return the full name of that fontset. FONTSETNAME may be a wildcard
9568 pattern; in that case, we choose some fontset that fits the pattern.
9569 The return value shows which fontset we chose. */
1a578e9b
AC
9570
9571Lisp_Object
9572x_new_fontset (f, fontsetname)
9573 struct frame *f;
9574 char *fontsetname;
9575{
9576 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9577 Lisp_Object result;
9578
9579 if (fontset < 0)
9580 return Qnil;
9581
e0f712ba 9582 if (FRAME_FONTSET (f) == fontset)
1a578e9b
AC
9583 /* This fontset is already set in frame F. There's nothing more
9584 to do. */
9585 return fontset_name (fontset);
9586
9587 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
9588
9589 if (!STRINGP (result))
9590 /* Can't load ASCII font. */
9591 return Qnil;
9592
e0f712ba
AC
9593 /* Since x_new_font doesn't update any fontset information, do it now. */
9594 FRAME_FONTSET(f) = fontset;
1a578e9b 9595
1a578e9b
AC
9596 return build_string (fontsetname);
9597}
9598
d33c49e8
KS
9599/* Compute actual fringe widths */
9600
9601void
9602x_compute_fringe_widths (f, redraw)
9603 struct frame *f;
9604 int redraw;
9605{
9606 int o_left = f->output_data.mac->left_fringe_width;
9607 int o_right = f->output_data.mac->right_fringe_width;
9608 int o_cols = f->output_data.mac->fringe_cols;
9609
9610 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9611 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9612 int left_fringe_width, right_fringe_width;
9613
9614 if (!NILP (left_fringe))
9615 left_fringe = Fcdr (left_fringe);
9616 if (!NILP (right_fringe))
9617 right_fringe = Fcdr (right_fringe);
9618
9619 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9620 XINT (left_fringe));
9621 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9622 XINT (right_fringe));
9623
9624 if (left_fringe_width || right_fringe_width)
9625 {
9626 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9627 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9628 int conf_wid = left_wid + right_wid;
9629 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9630 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9631 int real_wid = cols * font_wid;
9632 if (left_wid && right_wid)
9633 {
9634 if (left_fringe_width < 0)
9635 {
9636 /* Left fringe width is fixed, adjust right fringe if necessary */
9637 f->output_data.mac->left_fringe_width = left_wid;
9638 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9639 }
9640 else if (right_fringe_width < 0)
9641 {
9642 /* Right fringe width is fixed, adjust left fringe if necessary */
9643 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9644 f->output_data.mac->right_fringe_width = right_wid;
9645 }
9646 else
9647 {
9648 /* Adjust both fringes with an equal amount.
9649 Note that we are doing integer arithmetic here, so don't
9650 lose a pixel if the total width is an odd number. */
9651 int fill = real_wid - conf_wid;
9652 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9653 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9654 }
9655 }
9656 else if (left_fringe_width)
9657 {
9658 f->output_data.mac->left_fringe_width = real_wid;
9659 f->output_data.mac->right_fringe_width = 0;
9660 }
9661 else
9662 {
9663 f->output_data.mac->left_fringe_width = 0;
9664 f->output_data.mac->right_fringe_width = real_wid;
9665 }
9666 f->output_data.mac->fringe_cols = cols;
9667 f->output_data.mac->fringes_extra = real_wid;
9668 }
9669 else
9670 {
9671 f->output_data.mac->left_fringe_width = 0;
9672 f->output_data.mac->right_fringe_width = 0;
9673 f->output_data.mac->fringe_cols = 0;
9674 f->output_data.mac->fringes_extra = 0;
9675 }
9676
9677 if (redraw && FRAME_VISIBLE_P (f))
9678 if (o_left != f->output_data.mac->left_fringe_width ||
9679 o_right != f->output_data.mac->right_fringe_width ||
9680 o_cols != f->output_data.mac->fringe_cols)
9681 redraw_frame (f);
9682}
1a578e9b
AC
9683\f
9684/***********************************************************************
e0f712ba 9685 TODO: W32 Input Methods
1a578e9b 9686 ***********************************************************************/
e0f712ba 9687/* Listing missing functions from xterm.c helps diff stay in step.
1a578e9b 9688
1a578e9b 9689xim_destroy_callback (xim, client_data, call_data)
1a578e9b 9690xim_open_dpy (dpyinfo, resource_name)
1a578e9b 9691struct xim_inst_t
1a578e9b 9692xim_instantiate_callback (display, client_data, call_data)
1a578e9b 9693xim_initialize (dpyinfo, resource_name)
1a578e9b 9694xim_close_dpy (dpyinfo)
1a578e9b 9695
e0f712ba 9696 */
1a578e9b 9697
1a578e9b
AC
9698\f
9699/* Calculate the absolute position in frame F
9700 from its current recorded position values and gravity. */
9701
e0f712ba 9702void
1a578e9b
AC
9703x_calc_absolute_position (f)
9704 struct frame *f;
9705{
9706 Point pt;
9707 int flags = f->output_data.mac->size_hint_flags;
9708
9709 pt.h = pt.v = 0;
9710
9711 /* Find the position of the outside upper-left corner of
9712 the inner window, with respect to the outer window. */
9713 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9714 {
9715 GrafPtr savePort;
9716 GetPort (&savePort);
e0f712ba
AC
9717
9718#if TARGET_API_MAC_CARBON
9719 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9720#else
1a578e9b 9721 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
9722#endif
9723
9724#if TARGET_API_MAC_CARBON
9725 {
9726 Rect r;
9727
9728 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9729 SetPt(&pt, r.left, r.top);
9730 }
9731#else /* not TARGET_API_MAC_CARBON */
1a578e9b 9732 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
e0f712ba 9733#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
9734 LocalToGlobal (&pt);
9735 SetPort (savePort);
9736 }
9737
9738 /* Treat negative positions as relative to the leftmost bottommost
9739 position that fits on the screen. */
9740 if (flags & XNegative)
9741 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9742 - 2 * f->output_data.mac->border_width - pt.h
9743 - PIXEL_WIDTH (f)
9744 + f->output_data.mac->left_pos);
9745 /* NTEMACS_TODO: Subtract menubar height? */
9746 if (flags & YNegative)
9747 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9748 - 2 * f->output_data.mac->border_width - pt.v
9749 - PIXEL_HEIGHT (f)
9750 + f->output_data.mac->top_pos);
9751 /* The left_pos and top_pos
9752 are now relative to the top and left screen edges,
9753 so the flags should correspond. */
9754 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9755}
9756
9757/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9758 to really change the position, and 0 when calling from
9759 x_make_frame_visible (in that case, XOFF and YOFF are the current
9760 position values). It is -1 when calling from x_set_frame_parameters,
9761 which means, do adjust for borders but don't change the gravity. */
9762
9763void
9764x_set_offset (f, xoff, yoff, change_gravity)
9765 struct frame *f;
9766 register int xoff, yoff;
9767 int change_gravity;
9768{
e0f712ba
AC
9769 int modified_top, modified_left;
9770
1a578e9b
AC
9771 if (change_gravity > 0)
9772 {
9773 f->output_data.mac->top_pos = yoff;
9774 f->output_data.mac->left_pos = xoff;
9775 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9776 if (xoff < 0)
9777 f->output_data.mac->size_hint_flags |= XNegative;
9778 if (yoff < 0)
9779 f->output_data.mac->size_hint_flags |= YNegative;
9780 f->output_data.mac->win_gravity = NorthWestGravity;
9781 }
9782 x_calc_absolute_position (f);
9783
9784 BLOCK_INPUT;
9785 x_wm_set_size_hint (f, (long) 0, 0);
9786
e0f712ba
AC
9787 modified_left = f->output_data.mac->left_pos;
9788 modified_top = f->output_data.mac->top_pos;
9789
9790 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9791 modified_top + 42, false);
1a578e9b
AC
9792
9793 UNBLOCK_INPUT;
9794}
9795
9796/* Call this to change the size of frame F's x-window.
9797 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9798 for this size change and subsequent size changes.
9799 Otherwise we leave the window gravity unchanged. */
9800
9801void
9802x_set_window_size (f, change_gravity, cols, rows)
9803 struct frame *f;
9804 int change_gravity;
9805 int cols, rows;
9806{
9807 int pixelwidth, pixelheight;
e0f712ba
AC
9808
9809 BLOCK_INPUT;
9810
1a578e9b
AC
9811 check_frame_size (f, &rows, &cols);
9812 f->output_data.mac->vertical_scroll_bar_extra
9813 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9814 ? 0
1a578e9b 9815 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
d33c49e8
KS
9816
9817 x_compute_fringe_widths (f, 0);
9818
1a578e9b
AC
9819 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9820 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9821
9822 f->output_data.mac->win_gravity = NorthWestGravity;
9823 x_wm_set_size_hint (f, (long) 0, 0);
9824
9825 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9826
9827 /* Now, strictly speaking, we can't be sure that this is accurate,
9828 but the window manager will get around to dealing with the size
9829 change request eventually, and we'll hear how it went when the
9830 ConfigureNotify event gets here.
e0f712ba 9831
1a578e9b
AC
9832 We could just not bother storing any of this information here,
9833 and let the ConfigureNotify event set everything up, but that
9834 might be kind of confusing to the Lisp code, since size changes
9835 wouldn't be reported in the frame parameters until some random
9836 point in the future when the ConfigureNotify event arrives.
9837
9838 We pass 1 for DELAY since we can't run Lisp code inside of
9839 a BLOCK_INPUT. */
9840 change_frame_size (f, rows, cols, 0, 1, 0);
9841 PIXEL_WIDTH (f) = pixelwidth;
9842 PIXEL_HEIGHT (f) = pixelheight;
9843
9844 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9845 receive in the ConfigureNotify event; if we get what we asked
9846 for, then the event won't cause the screen to become garbaged, so
9847 we have to make sure to do it here. */
9848 SET_FRAME_GARBAGED (f);
9849
9850 XFlush (FRAME_X_DISPLAY (f));
9851
9852 /* If cursor was outside the new size, mark it as off. */
9853 mark_window_cursors_off (XWINDOW (f->root_window));
9854
9855 /* Clear out any recollection of where the mouse highlighting was,
9856 since it might be in a place that's outside the new frame size.
9857 Actually checking whether it is outside is a pain in the neck,
9858 so don't try--just let the highlighting be done afresh with new size. */
9859 cancel_mouse_face (f);
e0f712ba
AC
9860
9861 UNBLOCK_INPUT;
1a578e9b
AC
9862}
9863\f
9864/* Mouse warping. */
9865
9866void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9867
9868void
9869x_set_mouse_position (f, x, y)
9870 struct frame *f;
9871 int x, y;
9872{
9873 int pix_x, pix_y;
9874
9875 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9876 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9877
9878 if (pix_x < 0) pix_x = 0;
9879 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9880
9881 if (pix_y < 0) pix_y = 0;
9882 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9883
9884 x_set_mouse_pixel_position (f, pix_x, pix_y);
9885}
9886
1a578e9b
AC
9887void
9888x_set_mouse_pixel_position (f, pix_x, pix_y)
9889 struct frame *f;
9890 int pix_x, pix_y;
9891{
9892#if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9893 BLOCK_INPUT;
9894
9895 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9896 0, 0, 0, 0, pix_x, pix_y);
9897 UNBLOCK_INPUT;
9898#endif
9899}
e0f712ba 9900
1a578e9b
AC
9901\f
9902/* focus shifting, raising and lowering. */
9903
e0f712ba 9904void
1a578e9b
AC
9905x_focus_on_frame (f)
9906 struct frame *f;
9907{
9908#if 0 /* This proves to be unpleasant. */
9909 x_raise_frame (f);
9910#endif
9911#if 0
9912 /* I don't think that the ICCCM allows programs to do things like this
9913 without the interaction of the window manager. Whatever you end up
9914 doing with this code, do it to x_unfocus_frame too. */
9915 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9916 RevertToPointerRoot, CurrentTime);
9917#endif /* ! 0 */
9918}
9919
e0f712ba 9920void
1a578e9b
AC
9921x_unfocus_frame (f)
9922 struct frame *f;
9923{
1a578e9b
AC
9924}
9925
9926/* Raise frame F. */
1a578e9b
AC
9927void
9928x_raise_frame (f)
9929 struct frame *f;
9930{
9931 if (f->async_visible)
9932 SelectWindow (FRAME_MAC_WINDOW (f));
9933}
9934
9935/* Lower frame F. */
1a578e9b
AC
9936void
9937x_lower_frame (f)
9938 struct frame *f;
9939{
9940 if (f->async_visible)
9941 SendBehind (FRAME_MAC_WINDOW (f), nil);
9942}
9943
e0f712ba 9944static void
1a578e9b
AC
9945XTframe_raise_lower (f, raise_flag)
9946 FRAME_PTR f;
9947 int raise_flag;
9948{
9949 if (raise_flag)
9950 x_raise_frame (f);
9951 else
9952 x_lower_frame (f);
9953}
9954\f
9955/* Change of visibility. */
9956
9957/* This tries to wait until the frame is really visible.
9958 However, if the window manager asks the user where to position
9959 the frame, this will return before the user finishes doing that.
9960 The frame will not actually be visible at that time,
9961 but it will become visible later when the window manager
9962 finishes with it. */
9963
9964void
9965x_make_frame_visible (f)
9966 struct frame *f;
9967{
9968 Lisp_Object type;
9969 int original_top, original_left;
9970
9971 BLOCK_INPUT;
9972
9973 if (! FRAME_VISIBLE_P (f))
9974 {
9975 /* We test FRAME_GARBAGED_P here to make sure we don't
9976 call x_set_offset a second time
9977 if we get to x_make_frame_visible a second time
9978 before the window gets really visible. */
9979 if (! FRAME_ICONIFIED_P (f)
9980 && ! f->output_data.mac->asked_for_visible)
9981 x_set_offset (f, f->output_data.mac->left_pos,
9982 f->output_data.mac->top_pos, 0);
9983
9984 f->output_data.mac->asked_for_visible = 1;
9985
9986 ShowWindow (FRAME_MAC_WINDOW (f));
9987 }
9988
9989 XFlush (FRAME_MAC_DISPLAY (f));
9990
e0f712ba 9991#if 0 /* MAC_TODO */
1a578e9b
AC
9992 /* Synchronize to ensure Emacs knows the frame is visible
9993 before we do anything else. We do this loop with input not blocked
9994 so that incoming events are handled. */
9995 {
9996 Lisp_Object frame;
9997 int count;
9998
9999 /* This must come after we set COUNT. */
10000 UNBLOCK_INPUT;
10001
10002 XSETFRAME (frame, f);
10003
10004 /* Wait until the frame is visible. Process X events until a
10005 MapNotify event has been seen, or until we think we won't get a
10006 MapNotify at all.. */
10007 for (count = input_signal_count + 10;
10008 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10009 {
10010 /* Force processing of queued events. */
10011 x_sync (f);
10012
10013 /* Machines that do polling rather than SIGIO have been
10014 observed to go into a busy-wait here. So we'll fake an
10015 alarm signal to let the handler know that there's something
10016 to be read. We used to raise a real alarm, but it seems
10017 that the handler isn't always enabled here. This is
10018 probably a bug. */
10019 if (input_polling_used ())
10020 {
10021 /* It could be confusing if a real alarm arrives while
10022 processing the fake one. Turn it off and let the
10023 handler reset it. */
10024 extern void poll_for_input_1 P_ ((void));
10025 int old_poll_suppress_count = poll_suppress_count;
10026 poll_suppress_count = 1;
10027 poll_for_input_1 ();
10028 poll_suppress_count = old_poll_suppress_count;
10029 }
10030
10031 /* See if a MapNotify event has been processed. */
10032 FRAME_SAMPLE_VISIBILITY (f);
10033 }
10034 }
e0f712ba 10035#endif /* MAC_TODO */
1a578e9b
AC
10036}
10037
10038/* Change from mapped state to withdrawn state. */
10039
10040/* Make the frame visible (mapped and not iconified). */
10041
10042void
10043x_make_frame_invisible (f)
10044 struct frame *f;
10045{
10046 /* Don't keep the highlight on an invisible frame. */
10047 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10048 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10049
10050 BLOCK_INPUT;
10051
10052 HideWindow (FRAME_MAC_WINDOW (f));
10053
10054 /* We can't distinguish this from iconification
10055 just by the event that we get from the server.
10056 So we can't win using the usual strategy of letting
10057 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10058 and synchronize with the server to make sure we agree. */
10059 f->visible = 0;
10060 FRAME_ICONIFIED_P (f) = 0;
10061 f->async_visible = 0;
10062 f->async_iconified = 0;
10063
10064 UNBLOCK_INPUT;
10065}
10066
10067/* Change window state from mapped to iconified. */
10068
10069void
10070x_iconify_frame (f)
10071 struct frame *f;
10072{
10073#if 0 /* MAC_TODO: really no iconify on Mac */
10074 int result;
10075 Lisp_Object type;
10076
10077 /* Don't keep the highlight on an invisible frame. */
10078 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
10079 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
10080
10081 if (f->async_iconified)
10082 return;
10083
10084 BLOCK_INPUT;
10085
10086 FRAME_SAMPLE_VISIBILITY (f);
10087
10088 type = x_icon_type (f);
10089 if (!NILP (type))
10090 x_bitmap_icon (f, type);
10091
10092#ifdef USE_X_TOOLKIT
10093
10094 if (! FRAME_VISIBLE_P (f))
10095 {
10096 if (! EQ (Vx_no_window_manager, Qt))
10097 x_wm_set_window_state (f, IconicState);
10098 /* This was XtPopup, but that did nothing for an iconified frame. */
10099 XtMapWidget (f->output_data.x->widget);
10100 /* The server won't give us any event to indicate
10101 that an invisible frame was changed to an icon,
10102 so we have to record it here. */
10103 f->iconified = 1;
10104 f->visible = 1;
10105 f->async_iconified = 1;
10106 f->async_visible = 0;
10107 UNBLOCK_INPUT;
10108 return;
10109 }
10110
10111 result = XIconifyWindow (FRAME_X_DISPLAY (f),
10112 XtWindow (f->output_data.x->widget),
10113 DefaultScreen (FRAME_X_DISPLAY (f)));
10114 UNBLOCK_INPUT;
10115
10116 if (!result)
10117 error ("Can't notify window manager of iconification");
10118
10119 f->async_iconified = 1;
10120 f->async_visible = 0;
10121
10122
10123 BLOCK_INPUT;
10124 XFlush (FRAME_X_DISPLAY (f));
10125 UNBLOCK_INPUT;
10126#else /* not USE_X_TOOLKIT */
10127
10128 /* Make sure the X server knows where the window should be positioned,
10129 in case the user deiconifies with the window manager. */
10130 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
10131 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
10132
10133 /* Since we don't know which revision of X we're running, we'll use both
10134 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
10135
10136 /* X11R4: send a ClientMessage to the window manager using the
10137 WM_CHANGE_STATE type. */
10138 {
10139 XEvent message;
10140
10141 message.xclient.window = FRAME_X_WINDOW (f);
10142 message.xclient.type = ClientMessage;
10143 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
10144 message.xclient.format = 32;
10145 message.xclient.data.l[0] = IconicState;
10146
10147 if (! XSendEvent (FRAME_X_DISPLAY (f),
10148 DefaultRootWindow (FRAME_X_DISPLAY (f)),
10149 False,
10150 SubstructureRedirectMask | SubstructureNotifyMask,
10151 &message))
10152 {
10153 UNBLOCK_INPUT_RESIGNAL;
10154 error ("Can't notify window manager of iconification");
10155 }
10156 }
10157
10158 /* X11R3: set the initial_state field of the window manager hints to
10159 IconicState. */
10160 x_wm_set_window_state (f, IconicState);
10161
10162 if (!FRAME_VISIBLE_P (f))
10163 {
10164 /* If the frame was withdrawn, before, we must map it. */
10165 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10166 }
10167
10168 f->async_iconified = 1;
10169 f->async_visible = 0;
10170
10171 XFlush (FRAME_X_DISPLAY (f));
10172 UNBLOCK_INPUT;
10173#endif /* not USE_X_TOOLKIT */
e0f712ba 10174#endif /* MAC_TODO */
1a578e9b 10175}
e0f712ba 10176
1a578e9b
AC
10177\f
10178/* Destroy the X window of frame F. */
10179
10180void
10181x_destroy_window (f)
10182 struct frame *f;
10183{
10184 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10185
10186 BLOCK_INPUT;
10187
10188 DisposeWindow (FRAME_MAC_WINDOW (f));
10189
10190 free_frame_menubar (f);
10191 free_frame_faces (f);
10192
10193 xfree (f->output_data.mac);
10194 f->output_data.mac = 0;
10195 if (f == dpyinfo->x_focus_frame)
10196 dpyinfo->x_focus_frame = 0;
10197 if (f == dpyinfo->x_focus_event_frame)
10198 dpyinfo->x_focus_event_frame = 0;
10199 if (f == dpyinfo->x_highlight_frame)
10200 dpyinfo->x_highlight_frame = 0;
10201
10202 dpyinfo->reference_count--;
10203
10204 if (f == dpyinfo->mouse_face_mouse_frame)
10205 {
10206 dpyinfo->mouse_face_beg_row
10207 = dpyinfo->mouse_face_beg_col = -1;
10208 dpyinfo->mouse_face_end_row
10209 = dpyinfo->mouse_face_end_col = -1;
10210 dpyinfo->mouse_face_window = Qnil;
10211 dpyinfo->mouse_face_deferred_gc = 0;
10212 dpyinfo->mouse_face_mouse_frame = 0;
10213 }
10214
10215 UNBLOCK_INPUT;
10216}
10217\f
10218/* Setting window manager hints. */
10219
10220/* Set the normal size hints for the window manager, for frame F.
10221 FLAGS is the flags word to use--or 0 meaning preserve the flags
10222 that the window now has.
10223 If USER_POSITION is nonzero, we set the USPosition
10224 flag (this is useful when FLAGS is 0). */
1a578e9b
AC
10225void
10226x_wm_set_size_hint (f, flags, user_position)
10227 struct frame *f;
10228 long flags;
10229 int user_position;
10230{
10231#if 0 /* MAC_TODO: connect this to the Appearance Manager */
10232 XSizeHints size_hints;
10233
10234#ifdef USE_X_TOOLKIT
10235 Arg al[2];
10236 int ac = 0;
10237 Dimension widget_width, widget_height;
10238 Window window = XtWindow (f->output_data.x->widget);
10239#else /* not USE_X_TOOLKIT */
10240 Window window = FRAME_X_WINDOW (f);
10241#endif /* not USE_X_TOOLKIT */
10242
10243 /* Setting PMaxSize caused various problems. */
10244 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10245
10246 size_hints.x = f->output_data.x->left_pos;
10247 size_hints.y = f->output_data.x->top_pos;
10248
10249#ifdef USE_X_TOOLKIT
10250 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10251 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10252 XtGetValues (f->output_data.x->widget, al, ac);
10253 size_hints.height = widget_height;
10254 size_hints.width = widget_width;
10255#else /* not USE_X_TOOLKIT */
10256 size_hints.height = PIXEL_HEIGHT (f);
10257 size_hints.width = PIXEL_WIDTH (f);
10258#endif /* not USE_X_TOOLKIT */
10259
10260 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10261 size_hints.height_inc = f->output_data.x->line_height;
10262 size_hints.max_width
10263 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10264 size_hints.max_height
10265 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10266
10267 /* Calculate the base and minimum sizes.
10268
10269 (When we use the X toolkit, we don't do it here.
10270 Instead we copy the values that the widgets are using, below.) */
10271#ifndef USE_X_TOOLKIT
10272 {
10273 int base_width, base_height;
10274 int min_rows = 0, min_cols = 0;
10275
10276 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10277 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10278
10279 check_frame_size (f, &min_rows, &min_cols);
10280
10281 /* The window manager uses the base width hints to calculate the
10282 current number of rows and columns in the frame while
10283 resizing; min_width and min_height aren't useful for this
10284 purpose, since they might not give the dimensions for a
10285 zero-row, zero-column frame.
10286
10287 We use the base_width and base_height members if we have
10288 them; otherwise, we set the min_width and min_height members
10289 to the size for a zero x zero frame. */
10290
10291#ifdef HAVE_X11R4
10292 size_hints.flags |= PBaseSize;
10293 size_hints.base_width = base_width;
10294 size_hints.base_height = base_height;
10295 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10296 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10297#else
10298 size_hints.min_width = base_width;
10299 size_hints.min_height = base_height;
10300#endif
10301 }
10302
10303 /* If we don't need the old flags, we don't need the old hint at all. */
10304 if (flags)
10305 {
10306 size_hints.flags |= flags;
10307 goto no_read;
10308 }
10309#endif /* not USE_X_TOOLKIT */
10310
10311 {
10312 XSizeHints hints; /* Sometimes I hate X Windows... */
10313 long supplied_return;
10314 int value;
10315
10316#ifdef HAVE_X11R4
10317 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10318 &supplied_return);
10319#else
10320 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10321#endif
10322
10323#ifdef USE_X_TOOLKIT
10324 size_hints.base_height = hints.base_height;
10325 size_hints.base_width = hints.base_width;
10326 size_hints.min_height = hints.min_height;
10327 size_hints.min_width = hints.min_width;
10328#endif
10329
10330 if (flags)
10331 size_hints.flags |= flags;
10332 else
10333 {
10334 if (value == 0)
10335 hints.flags = 0;
10336 if (hints.flags & PSize)
10337 size_hints.flags |= PSize;
10338 if (hints.flags & PPosition)
10339 size_hints.flags |= PPosition;
10340 if (hints.flags & USPosition)
10341 size_hints.flags |= USPosition;
10342 if (hints.flags & USSize)
10343 size_hints.flags |= USSize;
10344 }
10345 }
10346
10347#ifndef USE_X_TOOLKIT
10348 no_read:
10349#endif
10350
10351#ifdef PWinGravity
10352 size_hints.win_gravity = f->output_data.x->win_gravity;
10353 size_hints.flags |= PWinGravity;
10354
10355 if (user_position)
10356 {
10357 size_hints.flags &= ~ PPosition;
10358 size_hints.flags |= USPosition;
10359 }
10360#endif /* PWinGravity */
10361
10362#ifdef HAVE_X11R4
10363 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10364#else
10365 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10366#endif
e0f712ba 10367#endif /* MAC_TODO */
1a578e9b
AC
10368}
10369
e0f712ba 10370#if 0 /* MAC_TODO: hide application instead of iconify? */
1a578e9b
AC
10371/* Used for IconicState or NormalState */
10372
10373void
10374x_wm_set_window_state (f, state)
10375 struct frame *f;
10376 int state;
10377{
10378#ifdef USE_X_TOOLKIT
10379 Arg al[1];
10380
10381 XtSetArg (al[0], XtNinitialState, state);
10382 XtSetValues (f->output_data.x->widget, al, 1);
10383#else /* not USE_X_TOOLKIT */
10384 Window window = FRAME_X_WINDOW (f);
10385
10386 f->output_data.x->wm_hints.flags |= StateHint;
10387 f->output_data.x->wm_hints.initial_state = state;
10388
10389 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10390#endif /* not USE_X_TOOLKIT */
10391}
10392
10393void
10394x_wm_set_icon_pixmap (f, pixmap_id)
10395 struct frame *f;
10396 int pixmap_id;
10397{
10398 Pixmap icon_pixmap;
10399
10400#ifndef USE_X_TOOLKIT
10401 Window window = FRAME_X_WINDOW (f);
10402#endif
10403
10404 if (pixmap_id > 0)
10405 {
10406 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10407 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10408 }
10409 else
10410 {
10411 /* It seems there is no way to turn off use of an icon pixmap.
10412 The following line does it, only if no icon has yet been created,
10413 for some window managers. But with mwm it crashes.
10414 Some people say it should clear the IconPixmapHint bit in this case,
10415 but that doesn't work, and the X consortium said it isn't the
10416 right thing at all. Since there is no way to win,
10417 best to explicitly give up. */
10418#if 0
10419 f->output_data.x->wm_hints.icon_pixmap = None;
10420#else
10421 return;
10422#endif
10423 }
10424
10425#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10426
10427 {
10428 Arg al[1];
10429 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10430 XtSetValues (f->output_data.x->widget, al, 1);
10431 }
10432
10433#else /* not USE_X_TOOLKIT */
10434
10435 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10436 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10437
10438#endif /* not USE_X_TOOLKIT */
10439}
10440
e0f712ba 10441#endif /* MAC_TODO */
1a578e9b
AC
10442
10443void
10444x_wm_set_icon_position (f, icon_x, icon_y)
10445 struct frame *f;
10446 int icon_x, icon_y;
10447{
10448#if 0 /* MAC_TODO: no icons on Mac */
10449#ifdef USE_X_TOOLKIT
10450 Window window = XtWindow (f->output_data.x->widget);
10451#else
10452 Window window = FRAME_X_WINDOW (f);
10453#endif
10454
10455 f->output_data.x->wm_hints.flags |= IconPositionHint;
10456 f->output_data.x->wm_hints.icon_x = icon_x;
10457 f->output_data.x->wm_hints.icon_y = icon_y;
10458
10459 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
e0f712ba 10460#endif /* MAC_TODO */
1a578e9b
AC
10461}
10462
10463\f
10464/***********************************************************************
10465 Fonts
10466 ***********************************************************************/
10467
10468/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10469
10470struct font_info *
10471x_get_font_info (f, font_idx)
10472 FRAME_PTR f;
10473 int font_idx;
10474{
10475 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10476}
10477
10478/* the global font name table */
10479char **font_name_table = NULL;
10480int font_name_table_size = 0;
10481int font_name_count = 0;
10482
10483/* compare two strings ignoring case */
10484static int
10485stricmp (const char *s, const char *t)
10486{
10487 for ( ; tolower (*s) == tolower (*t); s++, t++)
10488 if (*s == '\0')
10489 return 0;
10490 return tolower (*s) - tolower (*t);
10491}
10492
10493/* compare two strings ignoring case and handling wildcard */
10494static int
10495wildstrieq (char *s1, char *s2)
10496{
10497 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10498 return true;
10499
10500 return stricmp (s1, s2) == 0;
10501}
10502
10503/* Assume parameter 1 is fully qualified, no wildcards. */
10504static int
10505mac_font_pattern_match (fontname, pattern)
10506 char * fontname;
10507 char * pattern;
10508{
b179a3a2 10509 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
1a578e9b
AC
10510 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10511 char *ptr;
10512
10513 /* Copy fontname so we can modify it during comparison. */
10514 strcpy (font_name_copy, fontname);
10515
10516 ptr = regex;
10517 *ptr++ = '^';
10518
10519 /* Turn pattern into a regexp and do a regexp match. */
10520 for (; *pattern; pattern++)
10521 {
10522 if (*pattern == '?')
10523 *ptr++ = '.';
10524 else if (*pattern == '*')
10525 {
10526 *ptr++ = '.';
10527 *ptr++ = '*';
10528 }
10529 else
10530 *ptr++ = *pattern;
10531 }
10532 *ptr = '$';
10533 *(ptr + 1) = '\0';
10534
10535 return (fast_c_string_match_ignore_case (build_string (regex),
10536 font_name_copy) >= 0);
10537}
10538
10539/* Two font specs are considered to match if their foundry, family,
10540 weight, slant, and charset match. */
10541static int
10542mac_font_match (char *mf, char *xf)
10543{
10544 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10545 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10546
10547 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10548 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10549 return mac_font_pattern_match (mf, xf);
10550
10551 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10552 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10553 return mac_font_pattern_match (mf, xf);
10554
10555 return (wildstrieq (m_foundry, x_foundry)
10556 && wildstrieq (m_family, x_family)
10557 && wildstrieq (m_weight, x_weight)
10558 && wildstrieq (m_slant, x_slant)
10559 && wildstrieq (m_charset, x_charset))
10560 || mac_font_pattern_match (mf, xf);
10561}
10562
10563
10564static char *
10565mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10566{
10567 char foundry[32], family[32], cs[32];
10568 char xf[255], *result, *p;
10569
10570 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10571 {
10572 strcpy(foundry, "Apple");
10573 strcpy(family, name);
10574
10575 switch (scriptcode)
10576 {
10577 case smTradChinese:
10578 strcpy(cs, "big5-0");
10579 break;
10580 case smSimpChinese:
83a96b4d 10581 strcpy(cs, "gb2312.1980-0");
1a578e9b
AC
10582 break;
10583 case smJapanese:
10584 strcpy(cs, "jisx0208.1983-sjis");
10585 break;
2f64cf3a
AC
10586 case -smJapanese:
10587 /* Each Apple Japanese font is entered into the font table
10588 twice: once as a jisx0208.1983-sjis font and once as a
10589 jisx0201.1976-0 font. The latter can be used to display
10590 the ascii charset and katakana-jisx0201 charset. A
10591 negative script code signals that the name of this latter
10592 font is being built. */
10593 strcpy(cs, "jisx0201.1976-0");
10594 break;
1a578e9b 10595 case smKorean:
83a96b4d 10596 strcpy(cs, "ksc5601.1989-0");
1a578e9b
AC
10597 break;
10598 default:
10599 strcpy(cs, "mac-roman");
10600 break;
10601 }
10602 }
10603
10604 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10605 foundry, family, style & bold ? "bold" : "medium",
10606 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10607
10608 result = (char *) xmalloc (strlen (xf) + 1);
10609 strcpy (result, xf);
10610 for (p = result; *p; p++)
10611 *p = tolower(*p);
10612 return result;
10613}
10614
10615
10616/* Convert an X font spec to the corresponding mac font name, which
10617 can then be passed to GetFNum after conversion to a Pascal string.
10618 For ordinary Mac fonts, this should just be their names, like
10619 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10620 collection contain their charset designation in their names, like
10621 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10622 names are handled accordingly. */
10623static void
10624x_font_name_to_mac_font_name (char *xf, char *mf)
10625{
10626 char foundry[32], family[32], weight[20], slant[2], cs[32];
10627
10628 strcpy (mf, "");
10629
10630 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10631 foundry, family, weight, slant, cs) != 5 &&
10632 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10633 foundry, family, weight, slant, cs) != 5)
10634 return;
10635
83a96b4d 10636 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
1a578e9b 10637 || strcmp (cs, "jisx0208.1983-sjis") == 0
2f64cf3a 10638 || strcmp (cs, "jisx0201.1976-0") == 0
83a96b4d 10639 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
1a578e9b
AC
10640 strcpy(mf, family);
10641 else
10642 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10643}
10644
10645
10646/* Sets up the table font_name_table to contain the list of all
10647 monospace fonts in the system the first time the table is used so
10648 that the Resource Manager need not be accessed every time this
10649 information is needed. */
10650
10651static void
10652init_font_name_table ()
10653{
e0f712ba
AC
10654#if TARGET_API_MAC_CARBON
10655 SInt32 sv;
10656
10657 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10658 {
10659 FMFontFamilyIterator ffi;
10660 FMFontFamilyInstanceIterator ffii;
10661 FMFontFamily ff;
1a578e9b 10662
e0f712ba
AC
10663 /* Create a dummy instance iterator here to avoid creating and
10664 destroying it in the loop. */
10665 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10666 return;
10667 /* Create an iterator to enumerate the font families. */
10668 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10669 != noErr)
10670 {
10671 FMDisposeFontFamilyInstanceIterator (&ffii);
10672 return;
10673 }
1a578e9b 10674
e0f712ba
AC
10675 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10676 {
10677 Str255 name;
10678 FMFont font;
10679 FMFontStyle style;
10680 FMFontSize size;
10681 SInt16 sc;
10682
10683 if (FMGetFontFamilyName (ff, name) != noErr)
10684 break;
10685 p2cstr (name);
10686
10687 sc = FontToScript (ff);
10688
10689 /* Point the instance iterator at the current font family. */
10690 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10691 break;
10692
10693 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10694 == noErr)
10695 {
10696 if (font_name_table_size == 0)
10697 {
10698 font_name_table_size = 16;
10699 font_name_table = (char **)
10700 xmalloc (font_name_table_size * sizeof (char *));
10701 }
10702 else if (font_name_count + 1 >= font_name_table_size)
10703 {
10704 font_name_table_size += 16;
10705 font_name_table = (char **)
10706 xrealloc (font_name_table,
10707 font_name_table_size * sizeof (char *));
10708 }
10709 font_name_table[font_name_count++]
10710 = mac_to_x_fontname (name, size, style, sc);
10711 }
10712 }
10713
10714 /* Dispose of the iterators. */
10715 FMDisposeFontFamilyIterator (&ffi);
10716 FMDisposeFontFamilyInstanceIterator (&ffii);
10717 }
10718 else
1a578e9b 10719 {
e0f712ba
AC
10720#endif /* TARGET_API_MAC_CARBON */
10721 GrafPtr port;
10722 SInt16 fontnum, old_fontnum;
10723 int num_mac_fonts = CountResources('FOND');
10724 int i, j;
10725 Handle font_handle, font_handle_2;
10726 short id, scriptcode;
10727 ResType type;
10728 Str32 name;
10729 struct FontAssoc *fat;
10730 struct AsscEntry *assc_entry;
1a578e9b 10731
e0f712ba
AC
10732 GetPort (&port); /* save the current font number used */
10733#if TARGET_API_MAC_CARBON
10734 old_fontnum = GetPortTextFont (port);
10735#else
10736 old_fontnum = port->txFont;
10737#endif
10738
10739 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10740 {
10741 font_handle = GetIndResource ('FOND', i);
10742 if (!font_handle)
10743 continue;
10744
10745 GetResInfo (font_handle, &id, &type, name);
10746 GetFNum (name, &fontnum);
10747 p2cstr (name);
10748 if (fontnum == 0)
10749 continue;
10750
10751 TextFont (fontnum);
10752 scriptcode = FontToScript (fontnum);
10753 do
10754 {
10755 HLock (font_handle);
10756
10757 if (GetResourceSizeOnDisk (font_handle)
10758 >= sizeof (struct FamRec))
10759 {
10760 fat = (struct FontAssoc *) (*font_handle
10761 + sizeof (struct FamRec));
10762 assc_entry
10763 = (struct AsscEntry *) (*font_handle
10764 + sizeof (struct FamRec)
10765 + sizeof (struct FontAssoc));
10766
10767 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
199f9270 10768 {
e0f712ba
AC
10769 if (font_name_table_size == 0)
10770 {
10771 font_name_table_size = 16;
10772 font_name_table = (char **)
10773 xmalloc (font_name_table_size * sizeof (char *));
10774 }
10775 else if (font_name_count >= font_name_table_size)
10776 {
10777 font_name_table_size += 16;
10778 font_name_table = (char **)
10779 xrealloc (font_name_table,
10780 font_name_table_size * sizeof (char *));
10781 }
199f9270 10782 font_name_table[font_name_count++]
e0f712ba 10783 = mac_to_x_fontname (name,
199f9270
AC
10784 assc_entry->fontSize,
10785 assc_entry->fontStyle,
e0f712ba
AC
10786 scriptcode);
10787 /* Both jisx0208.1983-sjis and
10788 jisx0201.1976-sjis parts are contained in
10789 Apple Japanese (SJIS) font. */
10790 if (smJapanese == scriptcode)
10791 {
10792 font_name_table[font_name_count++]
10793 = mac_to_x_fontname (name,
10794 assc_entry->fontSize,
10795 assc_entry->fontStyle,
10796 smRoman);
10797 }
199f9270 10798 }
e0f712ba
AC
10799 }
10800
10801 HUnlock (font_handle);
10802 font_handle_2 = GetNextFOND (font_handle);
10803 ReleaseResource (font_handle);
10804 font_handle = font_handle_2;
10805 }
10806 while (ResError () == noErr && font_handle);
10807 }
10808
10809 TextFont (old_fontnum);
10810#if TARGET_API_MAC_CARBON
1a578e9b 10811 }
e0f712ba 10812#endif /* TARGET_API_MAC_CARBON */
1a578e9b
AC
10813}
10814
10815
10816/* Return a list of at most MAXNAMES font specs matching the one in
10817 PATTERN. Note that each '*' in the PATTERN matches exactly one
10818 field of the font spec, unlike X in which an '*' in a font spec can
10819 match a number of fields. The result is in the Mac implementation
10820 all fonts must be specified by a font spec with all 13 fields
10821 (although many of these can be "*'s"). */
10822
10823Lisp_Object
10824x_list_fonts (struct frame *f,
10825 Lisp_Object pattern,
10826 int size,
10827 int maxnames)
10828{
10829 char *ptnstr;
10830 Lisp_Object newlist = Qnil;
10831 int n_fonts = 0;
10832 int i;
b179a3a2 10833 struct gcpro gcpro1, gcpro2;
1a578e9b
AC
10834
10835 if (font_name_table == NULL) /* Initialize when first used. */
10836 init_font_name_table ();
10837
10838 ptnstr = XSTRING (pattern)->data;
10839
b179a3a2
AC
10840 GCPRO2 (pattern, newlist);
10841
1a578e9b
AC
10842 /* Scan and matching bitmap fonts. */
10843 for (i = 0; i < font_name_count; i++)
10844 {
10845 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10846 {
10847 newlist = Fcons (build_string (font_name_table[i]), newlist);
10848
10849 n_fonts++;
10850 if (n_fonts >= maxnames)
10851 break;
10852 }
10853 }
10854
10855 /* MAC_TODO: add code for matching outline fonts here */
10856
b179a3a2
AC
10857 UNGCPRO;
10858
1a578e9b
AC
10859 return newlist;
10860}
10861
10862
10863#if GLYPH_DEBUG
10864
e0f712ba
AC
10865/* Check that FONT is valid on frame F. It is if it can be found in F's
10866 font table. */
1a578e9b
AC
10867
10868static void
10869x_check_font (f, font)
10870 struct frame *f;
10871 XFontStruct *font;
10872{
10873 int i;
10874 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10875
10876 xassert (font != NULL);
10877
10878 for (i = 0; i < dpyinfo->n_fonts; i++)
10879 if (dpyinfo->font_table[i].name
10880 && font == dpyinfo->font_table[i].font)
10881 break;
10882
10883 xassert (i < dpyinfo->n_fonts);
10884}
10885
10886#endif /* GLYPH_DEBUG != 0 */
10887
1a578e9b
AC
10888/* Set *W to the minimum width, *H to the minimum font height of FONT.
10889 Note: There are (broken) X fonts out there with invalid XFontStruct
10890 min_bounds contents. For example, handa@etl.go.jp reports that
10891 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10892 have font->min_bounds.width == 0. */
10893
10894static INLINE void
10895x_font_min_bounds (font, w, h)
10896 MacFontStruct *font;
10897 int *w, *h;
10898{
e0f712ba
AC
10899 /*
10900 * TODO: Windows does not appear to offer min bound, only
10901 * average and maximum width, and maximum height.
10902 */
1a578e9b 10903 *h = FONT_HEIGHT (font);
e0f712ba 10904 *w = FONT_WIDTH (font);
1a578e9b
AC
10905}
10906
10907
10908/* Compute the smallest character width and smallest font height over
10909 all fonts available on frame F. Set the members smallest_char_width
10910 and smallest_font_height in F's x_display_info structure to
10911 the values computed. Value is non-zero if smallest_font_height or
10912 smallest_char_width become smaller than they were before. */
10913
e0f712ba 10914int
1a578e9b
AC
10915x_compute_min_glyph_bounds (f)
10916 struct frame *f;
10917{
10918 int i;
10919 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10920 MacFontStruct *font;
10921 int old_width = dpyinfo->smallest_char_width;
10922 int old_height = dpyinfo->smallest_font_height;
10923
10924 dpyinfo->smallest_font_height = 100000;
10925 dpyinfo->smallest_char_width = 100000;
10926
10927 for (i = 0; i < dpyinfo->n_fonts; ++i)
10928 if (dpyinfo->font_table[i].name)
10929 {
10930 struct font_info *fontp = dpyinfo->font_table + i;
10931 int w, h;
10932
10933 font = (MacFontStruct *) fontp->font;
10934 xassert (font != (MacFontStruct *) ~0);
10935 x_font_min_bounds (font, &w, &h);
10936
10937 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10938 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10939 }
10940
10941 xassert (dpyinfo->smallest_char_width > 0
10942 && dpyinfo->smallest_font_height > 0);
10943
10944 return (dpyinfo->n_fonts == 1
10945 || dpyinfo->smallest_char_width < old_width
10946 || dpyinfo->smallest_font_height < old_height);
10947}
10948
10949
10950/* Determine whether given string is a fully-specified XLFD: all 14
10951 fields are present, none is '*'. */
10952
10953static int
10954is_fully_specified_xlfd (char *p)
10955{
10956 int i;
10957 char *q;
10958
10959 if (*p != '-')
10960 return 0;
10961
10962 for (i = 0; i < 13; i++)
10963 {
10964 q = strchr (p + 1, '-');
10965 if (q == NULL)
10966 return 0;
10967 if (q - p == 2 && *(p + 1) == '*')
10968 return 0;
10969 p = q;
10970 }
10971
10972 if (strchr (p + 1, '-') != NULL)
10973 return 0;
10974
10975 if (*(p + 1) == '*' && *(p + 2) == '\0')
10976 return 0;
10977
10978 return 1;
10979}
10980
10981
10982const int kDefaultFontSize = 9;
10983
10984
e0f712ba
AC
10985/* XLoadQueryFont creates and returns an internal representation for a
10986 font in a MacFontStruct struct. There is really no concept
10987 corresponding to "loading" a font on the Mac. But we check its
10988 existence and find the font number and all other information for it
10989 and store them in the returned MacFontStruct. */
1a578e9b
AC
10990
10991static MacFontStruct *
10992XLoadQueryFont (Display *dpy, char *fontname)
10993{
10994 int i, size, is_two_byte_font, char_width;
10995 char *name;
10996 GrafPtr port;
10997 SInt16 old_fontnum, old_fontsize;
10998 Style old_fontface;
10999 Str32 mfontname;
11000 SInt16 fontnum;
11001 Style fontface = normal;
11002 MacFontStruct *font;
11003 FontInfo the_fontinfo;
11004 char s_weight[7], c_slant;
11005
11006 if (is_fully_specified_xlfd (fontname))
11007 name = fontname;
11008 else
11009 {
11010 for (i = 0; i < font_name_count; i++)
11011 if (mac_font_pattern_match (font_name_table[i], fontname))
11012 break;
11013
11014 if (i >= font_name_count)
11015 return NULL;
11016
11017 name = font_name_table[i];
11018 }
11019
11020 GetPort (&port); /* save the current font number used */
e0f712ba
AC
11021#if TARGET_API_MAC_CARBON
11022 old_fontnum = GetPortTextFont (port);
11023 old_fontsize = GetPortTextSize (port);
11024 old_fontface = GetPortTextFace (port);
11025#else
1a578e9b
AC
11026 old_fontnum = port->txFont;
11027 old_fontsize = port->txSize;
11028 old_fontface = port->txFace;
e0f712ba 11029#endif
1a578e9b
AC
11030
11031 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11032 size = kDefaultFontSize;
11033
11034 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11035 if (strcmp (s_weight, "bold") == 0)
11036 fontface |= bold;
11037
11038 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11039 if (c_slant == 'i')
11040 fontface |= italic;
11041
11042 x_font_name_to_mac_font_name (name, mfontname);
11043 c2pstr (mfontname);
11044 GetFNum (mfontname, &fontnum);
11045 if (fontnum == 0)
11046 return NULL;
11047
11048 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
11049
11050 font->fontname = (char *) xmalloc (strlen (name) + 1);
11051 bcopy (name, font->fontname, strlen (name) + 1);
11052
11053 font->mac_fontnum = fontnum;
11054 font->mac_fontsize = size;
11055 font->mac_fontface = fontface;
11056 font->mac_scriptcode = FontToScript (fontnum);
11057
199f9270 11058 /* Apple Japanese (SJIS) font is listed as both
2f64cf3a 11059 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
e0f712ba 11060 (Roman script) in init_font_name_table (). The latter should be
2f64cf3a 11061 treated as a one-byte font. */
199f9270
AC
11062 {
11063 char cs[32];
11064
11065 if (sscanf (name,
11066 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11067 cs) == 1
e0f712ba 11068 && 0 == strcmp (cs, "mac-roman"))
199f9270
AC
11069 font->mac_scriptcode = smRoman;
11070 }
11071
1a578e9b
AC
11072 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11073 font->mac_scriptcode == smTradChinese ||
11074 font->mac_scriptcode == smSimpChinese ||
11075 font->mac_scriptcode == smKorean;
11076
11077 TextFont (fontnum);
11078 TextSize (size);
11079 TextFace (fontface);
11080
11081 GetFontInfo (&the_fontinfo);
11082
11083 font->ascent = the_fontinfo.ascent;
11084 font->descent = the_fontinfo.descent;
11085
11086 font->min_byte1 = 0;
11087 if (is_two_byte_font)
11088 font->max_byte1 = 1;
11089 else
11090 font->max_byte1 = 0;
11091 font->min_char_or_byte2 = 0x20;
11092 font->max_char_or_byte2 = 0xff;
11093
11094 if (is_two_byte_font)
11095 {
11096 /* Use the width of an "ideographic space" of that font because
11097 the_fontinfo.widMax returns the wrong width for some fonts. */
11098 switch (font->mac_scriptcode)
11099 {
11100 case smJapanese:
11101 char_width = StringWidth("\p\x81\x40");
11102 break;
11103 case smTradChinese:
11104 char_width = StringWidth("\p\xa1\x40");
11105 break;
11106 case smSimpChinese:
11107 char_width = StringWidth("\p\xa1\xa1");
11108 break;
11109 case smKorean:
11110 char_width = StringWidth("\p\xa1\xa1");
11111 break;
11112 }
11113 }
11114 else
11115 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11116 returns 15 for 12-point Monaco! */
11117 char_width = CharWidth ('m');
11118
11119 font->max_bounds.rbearing = char_width;
11120 font->max_bounds.lbearing = 0;
11121 font->max_bounds.width = char_width;
11122 font->max_bounds.ascent = the_fontinfo.ascent;
11123 font->max_bounds.descent = the_fontinfo.descent;
11124
11125 font->min_bounds = font->max_bounds;
11126
11127 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11128 font->per_char = NULL;
11129 else
11130 {
11131 font->per_char = (XCharStruct *)
11132 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11133 {
11134 int c;
11135
11136 for (c = 0x20; c <= 0xff; c++)
11137 {
11138 font->per_char[c - 0x20] = font->max_bounds;
11139 font->per_char[c - 0x20].width = CharWidth (c);
11140 }
11141 }
11142 }
11143
11144 TextFont (old_fontnum); /* restore previous font number, size and face */
11145 TextSize (old_fontsize);
11146 TextFace (old_fontface);
11147
11148 return font;
11149}
11150
11151
11152/* Load font named FONTNAME of the size SIZE for frame F, and return a
11153 pointer to the structure font_info while allocating it dynamically.
11154 If SIZE is 0, load any size of font.
11155 If loading is failed, return NULL. */
11156
11157struct font_info *
11158x_load_font (f, fontname, size)
11159 struct frame *f;
11160 register char *fontname;
11161 int size;
11162{
11163 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11164 Lisp_Object font_names;
11165
11166 /* Get a list of all the fonts that match this name. Once we
11167 have a list of matching fonts, we compare them against the fonts
11168 we already have by comparing names. */
11169 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11170
11171 if (!NILP (font_names))
11172 {
11173 Lisp_Object tail;
11174 int i;
11175
11176 for (i = 0; i < dpyinfo->n_fonts; i++)
11177 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11178 if (dpyinfo->font_table[i].name
11179 && (!strcmp (dpyinfo->font_table[i].name,
11180 XSTRING (XCAR (tail))->data)
11181 || !strcmp (dpyinfo->font_table[i].full_name,
11182 XSTRING (XCAR (tail))->data)))
11183 return (dpyinfo->font_table + i);
11184 }
11185
11186 /* Load the font and add it to the table. */
11187 {
11188 char *full_name;
11189 struct MacFontStruct *font;
11190 struct font_info *fontp;
11191 unsigned long value;
11192 int i;
11193
11194 /* If we have found fonts by x_list_font, load one of them. If
11195 not, we still try to load a font by the name given as FONTNAME
11196 because XListFonts (called in x_list_font) of some X server has
11197 a bug of not finding a font even if the font surely exists and
11198 is loadable by XLoadQueryFont. */
11199 if (size > 0 && !NILP (font_names))
11200 fontname = (char *) XSTRING (XCAR (font_names))->data;
11201
11202 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11203 if (!font)
11204 return NULL;
11205
11206 /* Find a free slot in the font table. */
11207 for (i = 0; i < dpyinfo->n_fonts; ++i)
11208 if (dpyinfo->font_table[i].name == NULL)
11209 break;
11210
11211 /* If no free slot found, maybe enlarge the font table. */
11212 if (i == dpyinfo->n_fonts
11213 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11214 {
11215 int sz;
11216 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11217 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11218 dpyinfo->font_table
11219 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11220 }
11221
11222 fontp = dpyinfo->font_table + i;
11223 if (i == dpyinfo->n_fonts)
11224 ++dpyinfo->n_fonts;
11225
11226 /* Now fill in the slots of *FONTP. */
11227 BLOCK_INPUT;
11228 fontp->font = font;
11229 fontp->font_idx = i;
11230 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11231 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11232
11233 fontp->full_name = fontp->name;
11234
11235 fontp->size = font->max_bounds.width;
11236 fontp->height = FONT_HEIGHT (font);
11237 {
11238 /* For some font, ascent and descent in max_bounds field is
11239 larger than the above value. */
11240 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11241 if (max_height > fontp->height)
11242 fontp->height = max_height;
11243 }
11244
11245 /* The slot `encoding' specifies how to map a character
11246 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11247 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11248 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11249 2:0xA020..0xFF7F). For the moment, we don't know which charset
11250 uses this font. So, we set information in fontp->encoding[1]
11251 which is never used by any charset. If mapping can't be
11252 decided, set FONT_ENCODING_NOT_DECIDED. */
11253 if (font->mac_scriptcode == smJapanese)
11254 fontp->encoding[1] = 4;
11255 else
11256 {
11257 fontp->encoding[1]
11258 = (font->max_byte1 == 0
11259 /* 1-byte font */
11260 ? (font->min_char_or_byte2 < 0x80
11261 ? (font->max_char_or_byte2 < 0x80
11262 ? 0 /* 0x20..0x7F */
11263 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11264 : 1) /* 0xA0..0xFF */
11265 /* 2-byte font */
11266 : (font->min_byte1 < 0x80
11267 ? (font->max_byte1 < 0x80
11268 ? (font->min_char_or_byte2 < 0x80
11269 ? (font->max_char_or_byte2 < 0x80
11270 ? 0 /* 0x2020..0x7F7F */
11271 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11272 : 3) /* 0x20A0..0x7FFF */
11273 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11274 : (font->min_char_or_byte2 < 0x80
11275 ? (font->max_char_or_byte2 < 0x80
11276 ? 2 /* 0xA020..0xFF7F */
11277 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11278 : 1))); /* 0xA0A0..0xFFFF */
11279 }
11280
11281#if 0 /* MAC_TODO: fill these out with more reasonably values */
11282 fontp->baseline_offset
11283 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11284 ? (long) value : 0);
11285 fontp->relative_compose
11286 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11287 ? (long) value : 0);
11288 fontp->default_ascent
11289 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11290 ? (long) value : 0);
11291#else
11292 fontp->baseline_offset = 0;
11293 fontp->relative_compose = 0;
11294 fontp->default_ascent = 0;
11295#endif
11296
11297 /* Set global flag fonts_changed_p to non-zero if the font loaded
11298 has a character with a smaller width than any other character
11299 before, or if the font loaded has a smalle>r height than any
11300 other font loaded before. If this happens, it will make a
11301 glyph matrix reallocation necessary. */
11302 fonts_changed_p = x_compute_min_glyph_bounds (f);
11303 UNBLOCK_INPUT;
11304 return fontp;
11305 }
11306}
11307
11308
11309/* Return a pointer to struct font_info of a font named FONTNAME for
11310 frame F. If no such font is loaded, return NULL. */
11311
11312struct font_info *
11313x_query_font (f, fontname)
11314 struct frame *f;
11315 register char *fontname;
11316{
11317 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11318 int i;
11319
11320 for (i = 0; i < dpyinfo->n_fonts; i++)
11321 if (dpyinfo->font_table[i].name
11322 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11323 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11324 return (dpyinfo->font_table + i);
11325 return NULL;
11326}
11327
11328
11329/* Find a CCL program for a font specified by FONTP, and set the member
11330 `encoder' of the structure. */
11331
11332void
11333x_find_ccl_program (fontp)
11334 struct font_info *fontp;
11335{
11336 Lisp_Object list, elt;
11337
11338 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11339 {
11340 elt = XCAR (list);
11341 if (CONSP (elt)
11342 && STRINGP (XCAR (elt))
11343 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11344 >= 0))
11345 break;
11346 }
11347 if (! NILP (list))
11348 {
11349 struct ccl_program *ccl
11350 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11351
11352 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11353 xfree (ccl);
11354 else
11355 fontp->font_encoder = ccl;
11356 }
11357}
11358
11359
11360\f
11361/***********************************************************************
11362 Initialization
11363 ***********************************************************************/
11364
11365#ifdef USE_X_TOOLKIT
11366static XrmOptionDescRec emacs_options[] = {
11367 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11368 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11369
11370 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11371 XrmoptionSepArg, NULL},
11372 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11373
11374 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11375 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11376 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11377 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11378 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11379 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11380 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11381};
11382#endif /* USE_X_TOOLKIT */
11383
11384static int x_initialized;
11385
11386#ifdef MULTI_KBOARD
11387/* Test whether two display-name strings agree up to the dot that separates
11388 the screen number from the server number. */
11389static int
11390same_x_server (name1, name2)
11391 char *name1, *name2;
11392{
11393 int seen_colon = 0;
11394 unsigned char *system_name = XSTRING (Vsystem_name)->data;
11395 int system_name_length = strlen (system_name);
11396 int length_until_period = 0;
11397
11398 while (system_name[length_until_period] != 0
11399 && system_name[length_until_period] != '.')
11400 length_until_period++;
11401
11402 /* Treat `unix' like an empty host name. */
11403 if (! strncmp (name1, "unix:", 5))
11404 name1 += 4;
11405 if (! strncmp (name2, "unix:", 5))
11406 name2 += 4;
11407 /* Treat this host's name like an empty host name. */
11408 if (! strncmp (name1, system_name, system_name_length)
11409 && name1[system_name_length] == ':')
11410 name1 += system_name_length;
11411 if (! strncmp (name2, system_name, system_name_length)
11412 && name2[system_name_length] == ':')
11413 name2 += system_name_length;
11414 /* Treat this host's domainless name like an empty host name. */
11415 if (! strncmp (name1, system_name, length_until_period)
11416 && name1[length_until_period] == ':')
e0f712ba
AC
11417 name1 += length_until_period;
11418 if (! strncmp (name2, system_name, length_until_period)
11419 && name2[length_until_period] == ':')
11420 name2 += length_until_period;
11421
11422 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11423 {
11424 if (*name1 == ':')
11425 seen_colon++;
11426 if (seen_colon && *name1 == '.')
11427 return 1;
11428 }
11429 return (seen_colon
11430 && (*name1 == '.' || *name1 == '\0')
11431 && (*name2 == '.' || *name2 == '\0'));
11432}
11433#endif
1a578e9b
AC
11434
11435
11436/* The Mac Event loop code */
11437
e0f712ba 11438#ifndef MAC_OSX
1a578e9b
AC
11439#include <Events.h>
11440#include <Quickdraw.h>
11441#include <Balloons.h>
11442#include <Devices.h>
11443#include <Fonts.h>
11444#include <Gestalt.h>
11445#include <Menus.h>
11446#include <Processes.h>
11447#include <Sound.h>
11448#include <ToolUtils.h>
11449#include <TextUtils.h>
11450#include <Dialogs.h>
11451#include <Script.h>
1a578e9b
AC
11452#include <Types.h>
11453#include <TextEncodingConverter.h>
11454#include <Resources.h>
11455
11456#if __MWERKS__
11457#include <unix.h>
11458#endif
e0f712ba 11459#endif /* ! MAC_OSX */
1a578e9b
AC
11460
11461#define M_APPLE 128
11462#define I_ABOUT 1
11463
11464#define WINDOW_RESOURCE 128
11465#define TERM_WINDOW_RESOURCE 129
11466
11467#define DEFAULT_NUM_COLS 80
11468
11469#define MIN_DOC_SIZE 64
11470#define MAX_DOC_SIZE 32767
11471
11472/* sleep time for WaitNextEvent */
11473#define WNE_SLEEP_AT_SUSPEND 10
11474#define WNE_SLEEP_AT_RESUME 1
11475
11476/* true when cannot handle any Mac OS events */
11477static int handling_window_update = 0;
11478
11479/* the flag appl_is_suspended is used both for determining the sleep
11480 time to be passed to WaitNextEvent and whether the cursor should be
11481 drawn when updating the display. The cursor is turned off when
11482 Emacs is suspended. Redrawing it is unnecessary and what needs to
11483 be done depends on whether the cursor lies inside or outside the
11484 redraw region. So we might as well skip drawing it when Emacs is
11485 suspended. */
11486static Boolean app_is_suspended = false;
11487static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11488
11489#define EXTRA_STACK_ALLOC (256 * 1024)
11490
11491#define ARGV_STRING_LIST_ID 129
11492#define ABOUT_ALERT_ID 128
2e875e36 11493#define RAM_TOO_LARGE_ALERT_ID 129
1a578e9b
AC
11494
11495Boolean terminate_flag = false;
11496
11497/* true if using command key as meta key */
11498Lisp_Object Vmac_command_key_is_meta;
11499
11500/* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11501 to this text encoding */
11502int mac_keyboard_text_encoding;
11503int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11504
11505/* Set in term/mac-win.el to indicate that event loop can now generate
11506 drag and drop events. */
8f47302e 11507Lisp_Object Qmac_ready_for_drag_n_drop;
1a578e9b
AC
11508
11509Lisp_Object drag_and_drop_file_list;
11510
11511Point saved_menu_event_location;
11512
11513/* Apple Events */
11514static void init_required_apple_events(void);
e0f712ba
AC
11515static pascal OSErr
11516do_ae_open_application(const AppleEvent *, AppleEvent *, long);
11517static pascal OSErr
11518do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
1a578e9b
AC
11519static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
11520static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
11521
11522extern void init_emacs_passwd_dir ();
11523extern int emacs_main (int, char **, char **);
11524extern void check_alarm ();
11525
11526extern void initialize_applescript();
11527extern void terminate_applescript();
11528
11529
11530static void
11531do_get_menus (void)
11532{
11533 Handle menubar_handle;
11534 MenuHandle menu_handle;
11535
11536 menubar_handle = GetNewMBar (128);
11537 if(menubar_handle == NULL)
11538 abort ();
11539 SetMenuBar (menubar_handle);
11540 DrawMenuBar ();
11541
11542 menu_handle = GetMenuHandle (M_APPLE);
11543 if(menu_handle != NULL)
11544 AppendResMenu (menu_handle,'DRVR');
11545 else
11546 abort ();
11547}
11548
11549
11550static void
11551do_init_managers (void)
11552{
e0f712ba 11553#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11554 InitGraf (&qd.thePort);
11555 InitFonts ();
11556 FlushEvents (everyEvent, 0);
11557 InitWindows ();
11558 InitMenus ();
11559 TEInit ();
11560 InitDialogs (NULL);
e0f712ba
AC
11561#endif /* !TARGET_API_MAC_CARBON */
11562 InitCursor ();
1a578e9b 11563
e0f712ba 11564#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11565 /* set up some extra stack space for use by emacs */
11566 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11567
11568 /* MaxApplZone must be called for AppleScript to execute more
11569 complicated scripts */
11570 MaxApplZone ();
11571 MoreMasters ();
e0f712ba 11572#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
11573}
11574
2e875e36
AC
11575static void
11576do_check_ram_size (void)
11577{
11578 SInt32 physical_ram_size, logical_ram_size;
11579
11580 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11581 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11582 || physical_ram_size > 256 * 1024 * 1024
11583 || logical_ram_size > 256 * 1024 * 1024)
11584 {
11585 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11586 exit (1);
11587 }
11588}
11589
1a578e9b
AC
11590static void
11591do_window_update (WindowPtr win)
11592{
11593 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11594 struct frame *f = mwp->mFP;
11595
11596 if (f)
11597 {
11598 if (f->async_visible == 0)
11599 {
11600 f->async_visible = 1;
11601 f->async_iconified = 0;
11602 SET_FRAME_GARBAGED (f);
11603
11604 /* An update event is equivalent to MapNotify on X, so report
11605 visibility changes properly. */
11606 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11607 /* Force a redisplay sooner or later to update the
11608 frame titles in case this is the second frame. */
11609 record_asynch_buffer_change ();
11610 }
11611 else
11612 {
11613 BeginUpdate (win);
11614 handling_window_update = 1;
11615
11616 expose_frame (f, 0, 0, 0, 0);
11617
11618 handling_window_update = 0;
11619 EndUpdate (win);
11620 }
11621 }
11622}
11623
e0f712ba
AC
11624static int
11625is_emacs_window (WindowPtr win)
11626{
11627 Lisp_Object tail, frame;
11628
11629 if (!win)
11630 return 0;
11631
11632 FOR_EACH_FRAME (tail, frame)
11633 if (FRAME_MAC_P (XFRAME (frame)))
11634 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11635 return 1;
11636
11637 return 0;
11638}
11639
1a578e9b
AC
11640static void
11641do_window_activate (WindowPtr win)
11642{
e0f712ba
AC
11643 mac_output *mwp;
11644 struct frame *f;
1a578e9b 11645
e0f712ba 11646 if (is_emacs_window (win))
1a578e9b 11647 {
e0f712ba
AC
11648 mwp = (mac_output *) GetWRefCon (win);
11649 f = mwp->mFP;
11650
11651 if (f)
11652 {
11653 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11654 activate_scroll_bars (f);
11655 }
1a578e9b
AC
11656 }
11657}
11658
11659static void
11660do_window_deactivate (WindowPtr win)
11661{
e0f712ba
AC
11662 mac_output *mwp;
11663 struct frame *f;
1a578e9b 11664
e0f712ba 11665 if (is_emacs_window (win))
1a578e9b 11666 {
e0f712ba
AC
11667 mwp = (mac_output *) GetWRefCon (win);
11668 f = mwp->mFP;
11669
11670 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11671 {
11672 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11673 deactivate_scroll_bars (f);
11674 }
1a578e9b
AC
11675 }
11676}
11677
11678static void
11679do_app_resume ()
11680{
e0f712ba
AC
11681 WindowPtr wp;
11682 mac_output *mwp;
11683 struct frame *f;
fa0b4c14 11684
e0f712ba
AC
11685 wp = FrontWindow();
11686 if (is_emacs_window (wp))
1a578e9b 11687 {
e0f712ba
AC
11688 mwp = (mac_output *) GetWRefCon (wp);
11689 f = mwp->mFP;
11690
11691 if (f)
11692 {
11693 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11694 activate_scroll_bars (f);
11695 }
1a578e9b
AC
11696 }
11697
11698 app_is_suspended = false;
11699 app_sleep_time = WNE_SLEEP_AT_RESUME;
11700}
11701
11702static void
11703do_app_suspend ()
11704{
e0f712ba
AC
11705 WindowPtr wp;
11706 mac_output *mwp;
11707 struct frame *f;
1a578e9b 11708
e0f712ba
AC
11709 wp = FrontWindow();
11710 if (is_emacs_window (wp))
1a578e9b 11711 {
e0f712ba
AC
11712 mwp = (mac_output *) GetWRefCon (wp);
11713 f = mwp->mFP;
11714
11715 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11716 {
11717 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11718 deactivate_scroll_bars (f);
11719 }
1a578e9b
AC
11720 }
11721
11722 app_is_suspended = true;
11723 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11724}
11725
11726
11727static void
11728do_mouse_moved (Point mouse_pos)
11729{
11730 WindowPtr wp = FrontWindow ();
11731 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11732
e0f712ba
AC
11733#if TARGET_API_MAC_CARBON
11734 SetPort (GetWindowPort (wp));
11735#else
11736 SetPort (wp);
11737#endif
11738
1a578e9b
AC
11739 GlobalToLocal (&mouse_pos);
11740
11741 note_mouse_movement (f, &mouse_pos);
11742}
11743
11744
11745static void
11746do_os_event (EventRecord *erp)
11747{
11748 switch((erp->message >> 24) & 0x000000FF)
11749 {
11750 case suspendResumeMessage:
11751 if((erp->message & resumeFlag) == 1)
11752 do_app_resume ();
11753 else
11754 do_app_suspend ();
11755 break;
11756
e0f712ba 11757 case mouseMovedMessage:
1a578e9b
AC
11758 do_mouse_moved (erp->where);
11759 break;
11760 }
11761}
11762
11763static void
11764do_events (EventRecord *erp)
11765{
11766 switch (erp->what)
11767 {
11768 case updateEvt:
11769 do_window_update ((WindowPtr) erp->message);
11770 break;
11771
11772 case osEvt:
11773 do_os_event (erp);
11774 break;
11775
11776 case activateEvt:
11777 if ((erp->modifiers & activeFlag) != 0)
11778 do_window_activate ((WindowPtr) erp->message);
11779 else
11780 do_window_deactivate ((WindowPtr) erp->message);
11781 break;
11782 }
11783}
11784
11785static void
11786do_apple_menu (SInt16 menu_item)
11787{
e0f712ba 11788#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11789 Str255 item_name;
11790 SInt16 da_driver_refnum;
11791
11792 if (menu_item == I_ABOUT)
11793 NoteAlert (ABOUT_ALERT_ID, NULL);
11794 else
11795 {
11796 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11797 da_driver_refnum = OpenDeskAcc (item_name);
11798 }
e0f712ba 11799#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
11800}
11801
11802void
11803do_menu_choice (SInt32 menu_choice)
11804{
11805 SInt16 menu_id, menu_item;
11806
11807 menu_id = HiWord (menu_choice);
11808 menu_item = LoWord (menu_choice);
11809
11810 if (menu_id == 0)
11811 return;
11812
11813 switch (menu_id)
11814 {
11815 case M_APPLE:
11816 do_apple_menu (menu_item);
11817 break;
11818
11819 default:
11820 {
11821 WindowPtr wp = FrontWindow ();
11822 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11823 MenuHandle menu = GetMenuHandle (menu_id);
11824 if (menu)
11825 {
11826 UInt32 refcon;
11827
11828 GetMenuItemRefCon (menu, menu_item, &refcon);
11829 menubar_selection_callback (f, refcon);
11830 }
11831 }
11832 }
11833
11834 HiliteMenu (0);
11835}
11836
11837
11838/* Handle drags in size box. Based on code contributed by Ben
11839 Mesander and IM - Window Manager A. */
11840
11841static void
11842do_grow_window (WindowPtr w, EventRecord *e)
11843{
11844 long grow_size;
11845 Rect limit_rect;
11846 int rows, columns;
11847 mac_output *mwp = (mac_output *) GetWRefCon (w);
11848 struct frame *f = mwp->mFP;
11849
11850 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11851
11852 grow_size = GrowWindow (w, e->where, &limit_rect);
11853
11854 /* see if it really changed size */
11855 if (grow_size != 0)
11856 {
11857 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11858 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11859
11860 x_set_window_size (f, 0, columns, rows);
11861 }
11862}
11863
11864
11865/* Handle clicks in zoom box. Calculation of "standard state" based
11866 on code in IM - Window Manager A and code contributed by Ben
11867 Mesander. The standard state of an Emacs window is 80-characters
11868 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11869
11870static void
11871do_zoom_window (WindowPtr w, int zoom_in_or_out)
11872{
11873 GrafPtr save_port;
11874 Rect zoom_rect, port_rect;
11875 Point top_left;
11876 int w_title_height, columns, rows, width, height, dummy, x, y;
11877 mac_output *mwp = (mac_output *) GetWRefCon (w);
11878 struct frame *f = mwp->mFP;
11879
11880 GetPort (&save_port);
e0f712ba
AC
11881
11882#if TARGET_API_MAC_CARBON
11883 SetPort (GetWindowPort (w));
11884#else
1a578e9b 11885 SetPort (w);
e0f712ba
AC
11886#endif
11887
11888 /* Clear window to avoid flicker. */
11889#if TARGET_API_MAC_CARBON
11890 {
11891 Rect r;
11892 BitMap bm;
11893
11894 GetWindowPortBounds (w, &r);
11895 EraseRect (&r);
11896
11897 if (zoom_in_or_out == inZoomOut)
11898 {
11899 /* calculate height of window's title bar (hard card it for now). */
11900 w_title_height = 20 + GetMBarHeight ();
11901
11902 /* get maximum height of window into zoom_rect.bottom -
11903 zoom_rect.top */
11904 GetQDGlobalsScreenBits (&bm);
11905 zoom_rect = bm.bounds;
11906 zoom_rect.top += w_title_height;
11907 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11908
11909 zoom_rect.right = zoom_rect.left
11910 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11911
11912 SetWindowStandardState (w, &zoom_rect);
11913 }
11914 }
11915#else /* not TARGET_API_MAC_CARBON */
11916 EraseRect (&(w->portRect));
1a578e9b
AC
11917 if (zoom_in_or_out == inZoomOut)
11918 {
e0f712ba 11919 SetPt (&top_left, w->portRect.left, w->portRect.top);
1a578e9b
AC
11920 LocalToGlobal (&top_left);
11921
11922 /* calculate height of window's title bar */
11923 w_title_height = top_left.v - 1
e0f712ba 11924 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
1a578e9b
AC
11925
11926 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
11927 zoom_rect = qd.screenBits.bounds;
11928 zoom_rect.top += w_title_height;
11929 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11930
11931 zoom_rect.right = zoom_rect.left
11932 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11933
e0f712ba
AC
11934 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
11935 = zoom_rect;
1a578e9b 11936 }
e0f712ba 11937#endif /* not TARGET_API_MAC_CARBON */
1a578e9b 11938
e0f712ba 11939 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
1a578e9b
AC
11940
11941 /* retrieve window size and update application values */
e0f712ba
AC
11942#if TARGET_API_MAC_CARBON
11943 GetWindowPortBounds (w, &port_rect);
11944#else
1a578e9b 11945 port_rect = w->portRect;
e0f712ba 11946#endif
1a578e9b
AC
11947 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
11948 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
11949 x_set_window_size (mwp->mFP, 0, columns, rows);
11950
11951 SetPort (save_port);
11952}
11953
11954
11955/* Intialize AppleEvent dispatcher table for the required events. */
11956void
11957init_required_apple_events ()
11958{
11959 OSErr err;
11960 long result;
11961
11962 /* Make sure we have apple events before starting. */
11963 err = Gestalt (gestaltAppleEventsAttr, &result);
11964 if (err != noErr)
11965 abort ();
11966
11967 if (!(result & (1 << gestaltAppleEventsPresent)))
11968 abort ();
11969
e0f712ba 11970#if TARGET_API_MAC_CARBON
1a578e9b 11971 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
e0f712ba
AC
11972 NewAEEventHandlerUPP
11973 ((AEEventHandlerProcPtr) do_ae_open_application),
1a578e9b 11974 0L, false);
e0f712ba
AC
11975#else
11976 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
11977 NewAEEventHandlerProc
11978 ((AEEventHandlerProcPtr) do_ae_open_application),
11979 0L, false);
11980#endif
1a578e9b
AC
11981 if (err != noErr)
11982 abort ();
e0f712ba
AC
11983
11984#if TARGET_API_MAC_CARBON
11985 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
11986 NewAEEventHandlerUPP
11987 ((AEEventHandlerProcPtr) do_ae_open_documents),
11988 0L, false);
11989#else
1a578e9b 11990 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
e0f712ba
AC
11991 NewAEEventHandlerProc
11992 ((AEEventHandlerProcPtr) do_ae_open_documents),
1a578e9b 11993 0L, false);
e0f712ba 11994#endif
1a578e9b
AC
11995 if (err != noErr)
11996 abort ();
11997
e0f712ba
AC
11998#if TARGET_API_MAC_CARBON
11999 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12000 NewAEEventHandlerUPP
12001 ((AEEventHandlerProcPtr) do_ae_print_documents),
12002 0L, false);
12003#else
1a578e9b 12004 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
e0f712ba
AC
12005 NewAEEventHandlerProc
12006 ((AEEventHandlerProcPtr) do_ae_print_documents),
1a578e9b 12007 0L, false);
e0f712ba 12008#endif
1a578e9b
AC
12009 if (err != noErr)
12010 abort ();
12011
e0f712ba
AC
12012#if TARGET_API_MAC_CARBON
12013 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12014 NewAEEventHandlerUPP
12015 ((AEEventHandlerProcPtr) do_ae_quit_application),
12016 0L, false);
12017#else
1a578e9b 12018 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
e0f712ba
AC
12019 NewAEEventHandlerProc
12020 ((AEEventHandlerProcPtr) do_ae_quit_application),
1a578e9b 12021 0L, false);
e0f712ba 12022#endif
1a578e9b
AC
12023 if (err != noErr)
12024 abort ();
12025}
12026
12027
12028/* Open Application Apple Event */
12029static pascal OSErr
12030do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12031{
12032 return noErr;
12033}
12034
12035
12036/* Defined in mac.c. */
12037extern int
12038path_from_vol_dir_name (char *, int, short, long, char *);
12039
12040
12041/* Called when we receive an AppleEvent with an ID of
12042 "kAEOpenDocuments". This routine gets the direct parameter,
12043 extracts the FSSpecs in it, and puts their names on a list. */
12044static pascal OSErr
12045do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12046{
12047 OSErr err, err2;
12048 AEDesc the_desc;
12049 AEKeyword keyword;
12050 DescType actual_type;
12051 Size actual_size;
12052
12053 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12054 if (err != noErr)
12055 goto descriptor_error_exit;
12056
12057 /* Check to see that we got all of the required parameters from the
12058 event descriptor. For an 'odoc' event this should just be the
12059 file list. */
12060 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12061 &actual_type, (Ptr) &keyword,
12062 sizeof (keyword), &actual_size);
12063 /* No error means that we found some unused parameters.
12064 errAEDescNotFound means that there are no more parameters. If we
12065 get an error code other than that, flag it. */
12066 if ((err == noErr) || (err != errAEDescNotFound))
12067 {
12068 err = errAEEventNotHandled;
12069 goto error_exit;
12070 }
12071 err = noErr;
12072
12073 /* Got all the parameters we need. Now, go through the direct
12074 object list and parse it up. */
12075 {
12076 long num_files_to_open;
12077
12078 err = AECountItems (&the_desc, &num_files_to_open);
12079 if (err == noErr)
12080 {
12081 int i;
12082
12083 /* AE file list is one based so just use that for indexing here. */
12084 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++) {
12085 FSSpec fs;
12086 Str255 path_name, unix_path_name;
12087
12088 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12089 (Ptr) &fs, sizeof (fs), &actual_size);
12090 if (err != noErr) break;
12091
12092 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12093 fs.name) &&
60fe1161 12094 mac_to_posix_pathname (path_name, unix_path_name, 255))
1a578e9b
AC
12095 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12096 drag_and_drop_file_list);
12097 }
12098 }
12099 }
12100
12101error_exit:
12102 /* Nuke the coerced file list in any case */
12103 err2 = AEDisposeDesc(&the_desc);
12104
12105descriptor_error_exit:
12106 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12107 return err;
12108}
12109
12110
12111/* Print Document Apple Event */
12112static pascal OSErr
12113do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12114{
12115 return errAEEventNotHandled;
12116}
12117
12118
12119static pascal OSErr
12120do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12121{
12122 /* FixMe: Do we need an unwind-protect or something here? And what
12123 do we do about unsaved files. Currently just forces quit rather
12124 than doing recursive callback to get user input. */
12125
12126 terminate_flag = true;
12127
12128 /* Fkill_emacs doesn't return. We have to return. (TI) */
12129 return noErr;
12130}
12131
12132
12133#if __profile__
12134void
12135profiler_exit_proc ()
12136{
12137 ProfilerDump ("\pEmacs.prof");
12138 ProfilerTerm ();
12139}
12140#endif
12141
12142/* These few functions implement Emacs as a normal Mac application
8c1cc9e8 12143 (almost): set up the heap and the Toolbox, handle necessary
1a578e9b
AC
12144 system events plus a few simple menu events. They also set up
12145 Emacs's access to functions defined in the rest of this file.
12146 Emacs uses function hooks to perform all its terminal I/O. A
12147 complete list of these functions appear in termhooks.h. For what
12148 they do, read the comments there and see also w32term.c and
12149 xterm.c. What's noticeably missing here is the event loop, which
12150 is normally present in most Mac application. After performing the
12151 necessary Mac initializations, main passes off control to
12152 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12153 mac_read_socket (defined further below) to read input. This is
12154 where WaitNextEvent is called to process Mac events. This is also
12155 where check_alarm in sysdep.c is called to simulate alarm signals.
12156 This makes the cursor jump back to its correct position after
12157 briefly jumping to that of the matching parenthesis, print useful
12158 hints and prompts in the minibuffer after the user stops typing for
12159 a wait, etc. */
12160
e0f712ba 12161#if !TARGET_API_MAC_CARBON
1a578e9b
AC
12162#undef main
12163int
12164main (void)
12165{
12166#if __profile__ /* is the profiler on? */
12167 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12168 exit(1);
12169#endif
12170
12171#if __MWERKS__
12172 /* set creator and type for files created by MSL */
12173 _fcreator = 'EMAx';
12174 _ftype = 'TEXT';
12175#endif
12176
12177 do_init_managers ();
12178
12179 do_get_menus ();
12180
2e875e36
AC
12181 do_check_ram_size ();
12182
1a578e9b
AC
12183 init_emacs_passwd_dir ();
12184
12185 init_environ ();
12186
12187 initialize_applescript ();
12188
12189 init_required_apple_events ();
12190
12191 {
12192 char **argv;
12193 int argc = 0;
12194
12195 /* set up argv array from STR# resource */
12196 get_string_list (&argv, ARGV_STRING_LIST_ID);
12197 while (argv[argc])
12198 argc++;
12199
12200 /* free up AppleScript resources on exit */
12201 atexit (terminate_applescript);
12202
12203#if __profile__ /* is the profiler on? */
12204 atexit (profiler_exit_proc);
12205#endif
12206
12207 /* 3rd param "envp" never used in emacs_main */
12208 (void) emacs_main (argc, argv, 0);
12209 }
12210
12211 /* Never reached - real exit in Fkill_emacs */
12212 return 0;
12213}
e0f712ba 12214#endif
1a578e9b
AC
12215
12216/* Table for translating Mac keycode to X keysym values. Contributed
12217 by Sudhir Shenoy. */
12218static unsigned char keycode_to_xkeysym_table[] = {
12219/* 0x00 - 0x3f */
12220 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12224/* 0x40 */
e0f712ba
AC
12225 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12226 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12227 0, 0, 0, '\xaf' /* kp/ */,
12228 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
1a578e9b 12229/* 0x50 */
e0f712ba
AC
12230 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12231 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12232 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12233 '\xb9' /* kp9 */, 0, 0, 0,
1a578e9b 12234/* 0x60 */
e0f712ba
AC
12235 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12236 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12237 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12238 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
1a578e9b 12239/* 0x70 */
e0f712ba
AC
12240 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12241 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12242 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12243 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
1a578e9b
AC
12244};
12245
12246static int
12247keycode_to_xkeysym (int keyCode, int *xKeySym)
12248{
12249 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12250 return *xKeySym != 0;
12251}
12252
12253/* Emacs calls this whenever it wants to read an input event from the
12254 user. */
12255int
12256XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12257{
12258 int count = 0;
12259 EventRecord er;
12260 int the_modifiers;
12261 EventMask event_mask;
12262
e0f712ba 12263#if 0
1a578e9b
AC
12264 if (interrupt_input_blocked)
12265 {
12266 interrupt_input_pending = 1;
12267 return -1;
12268 }
e0f712ba 12269#endif
1a578e9b
AC
12270
12271 interrupt_input_pending = 0;
12272 BLOCK_INPUT;
12273
12274 /* So people can tell when we have read the available input. */
12275 input_signal_count++;
12276
12277 if (numchars <= 0)
12278 abort ();
12279
12280 /* Don't poll for events to process (specifically updateEvt) if
12281 window update currently already in progress. A call to redisplay
12282 (in do_window_update) can be preempted by another call to
12283 redisplay, causing blank regions to be left on the screen and the
12284 cursor to be left at strange places. */
12285 if (handling_window_update)
12286 {
12287 UNBLOCK_INPUT;
12288 return 0;
12289 }
12290
12291 if (terminate_flag)
12292 Fkill_emacs (make_number (1));
12293
12294 /* It is necessary to set this (additional) argument slot of an
12295 event to nil because keyboard.c protects incompletely processed
12296 event from being garbage collected by placing them in the
12297 kbd_buffer_gcpro vector. */
12298 bufp->arg = Qnil;
12299
12300 event_mask = everyEvent;
8f47302e 12301 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
1a578e9b
AC
12302 event_mask -= highLevelEventMask;
12303
1305f1a7 12304 while (WaitNextEvent (event_mask, &er, 0L, NULL) && numchars > 0)
1a578e9b
AC
12305 switch (er.what)
12306 {
12307 case mouseDown:
12308 case mouseUp:
12309 {
12310 WindowPtr window_ptr = FrontWindow ();
12311 SInt16 part_code;
12312
12313 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12314 && er.what == mouseUp)
12315 {
12316 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12317 Point mouse_loc = er.where;
12318
12319 /* Convert to local coordinates of new window. */
e0f712ba
AC
12320#if TARGET_API_MAC_CARBON
12321 SetPort (GetWindowPort (window_ptr));
12322#else
12323 SetPort (window_ptr);
12324#endif
12325
1a578e9b
AC
12326 GlobalToLocal (&mouse_loc);
12327
12328 bufp->code = 0; /* only one mouse button */
12329 bufp->kind = scroll_bar_click;
12330 bufp->frame_or_window = tracked_scroll_bar->window;
12331 bufp->part = scroll_bar_handle;
12332 bufp->modifiers = up_modifier;
12333 bufp->timestamp = er.when * (1000 / 60);
12334 /* ticks to milliseconds */
12335
12336 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12337 XSETINT (bufp->y, mouse_loc.v - 24);
12338 tracked_scroll_bar->dragging = Qnil;
12339 mouse_tracking_in_progress = mouse_tracking_none;
12340 tracked_scroll_bar = NULL;
12341 count++;
1305f1a7
AC
12342 bufp++;
12343 numchars--;
1a578e9b
AC
12344 break;
12345 }
12346
12347 part_code = FindWindow (er.where, &window_ptr);
12348
12349 switch (part_code)
12350 {
12351 case inMenuBar:
12352 {
12353 struct frame *f = ((mac_output *)
12354 GetWRefCon (FrontWindow ()))->mFP;
12355 saved_menu_event_location = er.where;
12356 bufp->kind = menu_bar_activate_event;
12357 XSETFRAME (bufp->frame_or_window, f);
12358 count++;
1305f1a7
AC
12359 bufp++;
12360 numchars--;
1a578e9b
AC
12361 }
12362 break;
12363
12364 case inContent:
12365 if (window_ptr != FrontWindow ())
12366 SelectWindow (window_ptr);
12367 else
12368 {
e0f712ba 12369 SInt16 control_part_code;
1a578e9b
AC
12370 ControlHandle ch;
12371 struct mac_output *mwp = (mac_output *)
12372 GetWRefCon (window_ptr);
12373 Point mouse_loc = er.where;
12374
12375 /* convert to local coordinates of new window */
e0f712ba
AC
12376#if TARGET_API_MAC_CARBON
12377 SetPort (GetWindowPort (window_ptr));
12378#else
12379 SetPort (window_ptr);
12380#endif
12381
1a578e9b 12382 GlobalToLocal (&mouse_loc);
e0f712ba
AC
12383#if TARGET_API_MAC_CARBON
12384 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12385 &control_part_code);
12386#else
1a578e9b 12387 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
e0f712ba 12388#endif
1a578e9b
AC
12389 bufp->code = 0; /* only one mouse button */
12390 XSETINT (bufp->x, mouse_loc.h);
12391 XSETINT (bufp->y, mouse_loc.v);
12392 bufp->timestamp = er.when * (1000 / 60);
12393 /* ticks to milliseconds */
e0f712ba
AC
12394
12395#if TARGET_API_MAC_CARBON
12396 if (ch != 0)
12397#else
1a578e9b 12398 if (control_part_code != 0)
e0f712ba 12399#endif
1a578e9b
AC
12400 {
12401 struct scroll_bar *bar = (struct scroll_bar *)
12402 GetControlReference (ch);
12403 x_scroll_bar_handle_click (bar, control_part_code, &er,
12404 bufp);
12405 if (er.what == mouseDown
12406 && control_part_code == kControlIndicatorPart)
12407 {
e0f712ba
AC
12408 mouse_tracking_in_progress
12409 = mouse_tracking_scroll_bar;
1a578e9b
AC
12410 tracked_scroll_bar = bar;
12411 }
12412 else
12413 {
12414 mouse_tracking_in_progress = mouse_tracking_none;
12415 tracked_scroll_bar = NULL;
12416 }
12417 }
12418 else
12419 {
12420 bufp->kind = mouse_click;
12421 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12422 if (er.what == mouseDown)
e0f712ba
AC
12423 mouse_tracking_in_progress
12424 = mouse_tracking_mouse_movement;
1a578e9b 12425 else
e0f712ba 12426 mouse_tracking_in_progress = mouse_tracking_none;
1a578e9b
AC
12427 }
12428
12429 switch (er.what)
12430 {
12431 case mouseDown:
12432 bufp->modifiers = down_modifier;
12433 break;
12434 case mouseUp:
12435 bufp->modifiers = up_modifier;
12436 break;
12437 }
12438
12439 count++;
1305f1a7
AC
12440 bufp++;
12441 numchars--;
1a578e9b
AC
12442 }
12443 break;
12444
12445 case inDrag:
e0f712ba
AC
12446#if TARGET_API_MAC_CARBON
12447 {
12448 BitMap bm;
12449
12450 GetQDGlobalsScreenBits (&bm);
12451 DragWindow (window_ptr, er.where, &bm.bounds);
12452 }
12453#else /* not TARGET_API_MAC_CARBON */
1a578e9b 12454 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
e0f712ba 12455#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
12456 break;
12457
12458 case inGoAway:
12459 if (TrackGoAway (window_ptr, er.where))
12460 {
12461 bufp->kind = delete_window_event;
12462 XSETFRAME (bufp->frame_or_window,
12463 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12464 count++;
1305f1a7
AC
12465 bufp++;
12466 numchars--;
1a578e9b
AC
12467 }
12468 break;
12469
12470 /* window resize handling added --ben */
12471 case inGrow:
12472 do_grow_window(window_ptr, &er);
12473 break;
12474
12475 /* window zoom handling added --ben */
12476 case inZoomIn:
12477 case inZoomOut:
12478 if (TrackBox (window_ptr, er.where, part_code))
12479 do_zoom_window (window_ptr, part_code);
12480 break;
12481
12482 default:
12483 break;
12484 }
12485 }
12486 break;
12487
12488 case updateEvt:
12489 case osEvt:
12490 case activateEvt:
12491 do_events (&er);
12492 break;
12493
12494 case keyDown:
12495 case autoKey:
12496 {
12497 int keycode = (er.message & keyCodeMask) >> 8;
12498 int xkeysym;
12499
12500 ObscureCursor ();
12501
12502 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12503 {
12504 bufp->code = 0x7f;
12505 bufp->kind = ascii_keystroke;
12506 }
12507 else if (keycode_to_xkeysym (keycode, &xkeysym))
12508 {
12509 bufp->code = 0xff00 | xkeysym;
12510 bufp->kind = non_ascii_keystroke;
12511 }
12512 else
12513 {
12514 if (er.modifiers
12515 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12516 {
12517 /* This code comes from Keyboard Resource, Appendix
12518 C of IM - Text. This is necessary since shift is
12519 ignored in KCHR table translation when option or
12520 command is pressed. */
12521 int new_modifiers = er.modifiers & 0xf600;
12522 /* mask off option and command */
12523 int new_keycode = keycode | new_modifiers;
12524 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12525 unsigned long some_state = 0;
12526 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12527 &some_state) & 0xff;
12528 }
12529 else
12530 bufp->code = er.message & charCodeMask;
12531 bufp->kind = ascii_keystroke;
12532 }
12533 }
12534
12535 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12536 convert non-ASCII characters typed at the Mac keyboard
12537 (presumed to be in the Mac Roman encoding) to iso-latin-1
12538 encoding before they are passed to Emacs. This enables the
12539 Mac keyboard to be used to enter non-ASCII iso-latin-1
12540 characters directly. */
12541 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12542 && bufp->kind == ascii_keystroke && bufp->code >= 128)
12543 {
12544 static TECObjectRef converter = NULL;
12545 OSStatus the_err = noErr;
12546 OSStatus convert_status = noErr;
12547
12548 if (converter == NULL)
12549 {
12550 the_err = TECCreateConverter (&converter,
12551 kTextEncodingMacRoman,
12552 mac_keyboard_text_encoding);
e0f712ba
AC
12553 current_mac_keyboard_text_encoding
12554 = mac_keyboard_text_encoding;
1a578e9b 12555 }
e0f712ba
AC
12556 else if (mac_keyboard_text_encoding
12557 != current_mac_keyboard_text_encoding)
1a578e9b
AC
12558 {
12559 /* Free the converter for the current encoding before
12560 creating a new one. */
12561 TECDisposeConverter (converter);
12562 the_err = TECCreateConverter (&converter,
12563 kTextEncodingMacRoman,
12564 mac_keyboard_text_encoding);
e0f712ba
AC
12565 current_mac_keyboard_text_encoding
12566 = mac_keyboard_text_encoding;
1a578e9b
AC
12567 }
12568
12569 if (the_err == noErr)
12570 {
12571 unsigned char ch = bufp->code;
12572 ByteCount actual_input_length, actual_output_length;
12573 unsigned char outch;
12574
12575 convert_status = TECConvertText (converter, &ch, 1,
12576 &actual_input_length,
12577 &outch, 1,
12578 &actual_output_length);
12579 if (convert_status == noErr
12580 && actual_input_length == 1
12581 && actual_output_length == 1)
12582 bufp->code = outch;
12583 }
12584 }
12585
12586 the_modifiers = 0;
12587 if (er.modifiers & shiftKey)
12588 the_modifiers |= shift_modifier;
12589 if (er.modifiers & controlKey)
12590 the_modifiers |= ctrl_modifier;
12591 /* use option or command key as meta depending on value of
12592 mac-command-key-is-meta */
12593 if (er.modifiers
12594 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12595 the_modifiers |= meta_modifier;
12596 bufp->modifiers = the_modifiers;
12597
12598 {
12599 mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
12600 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12601 }
12602
12603 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
12604
12605 count++;
1305f1a7
AC
12606 bufp++;
12607 numchars--;
1a578e9b
AC
12608 break;
12609
12610 case kHighLevelEvent:
12611 drag_and_drop_file_list = Qnil;
8f47302e 12612
1a578e9b
AC
12613 AEProcessAppleEvent(&er);
12614
12615 /* Build a drag_n_drop type event as is done in
12616 constuct_drag_n_drop in w32term.c. */
12617 if (!NILP (drag_and_drop_file_list))
12618 {
12619 struct frame *f;
12620 WindowPtr wp;
12621 Lisp_Object frame;
12622
12623 wp = FrontWindow ();
12624 if (!wp)
12625 f = NULL;
12626 else
12627 f = ((mac_output *) GetWRefCon (wp))->mFP;
12628
12629 bufp->kind = drag_n_drop;
12630 bufp->code = 0;
12631 bufp->timestamp = er.when * (1000 / 60);
12632 /* ticks to milliseconds */
12633 bufp->modifiers = 0;
12634
12635 XSETINT (bufp->x, 0);
12636 XSETINT (bufp->y, 0);
12637
12638 XSETFRAME (frame, f);
12639 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
12640
12641 /* Regardless of whether Emacs was suspended or in the
12642 foreground, ask it to redraw its entire screen.
12643 Otherwise parts of the screen can be left in an
12644 inconsistent state. */
12645 if (wp)
e0f712ba
AC
12646#if TARGET_API_MAC_CARBON
12647 {
12648 Rect r;
12649
12650 GetWindowPortBounds (wp, &r);
12651 InvalWindowRect (wp, &r);
12652 }
12653#else /* not TARGET_API_MAC_CARBON */
1a578e9b 12654 InvalRect (&(wp->portRect));
e0f712ba 12655#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
12656
12657 count++;
1305f1a7
AC
12658 bufp++;
12659 numchars--;
1a578e9b
AC
12660 }
12661
12662 default:
12663 break;
12664 }
12665
12666 /* If the focus was just given to an autoraising frame,
12667 raise it now. */
12668 /* ??? This ought to be able to handle more than one such frame. */
12669 if (pending_autoraise_frame)
12670 {
12671 x_raise_frame (pending_autoraise_frame);
12672 pending_autoraise_frame = 0;
12673 }
12674
e0f712ba 12675#if !TARGET_API_MAC_CARBON
1a578e9b 12676 check_alarm (); /* simulate the handling of a SIGALRM */
e0f712ba 12677#endif
1a578e9b
AC
12678
12679 {
12680 static Point old_mouse_pos = { -1, -1 };
12681
12682 if (app_is_suspended)
12683 {
12684 old_mouse_pos.h = -1;
12685 old_mouse_pos.v = -1;
12686 }
12687 else
12688 {
12689 Point mouse_pos;
e0f712ba
AC
12690 WindowPtr wp;
12691 struct frame *f;
1a578e9b
AC
12692 Lisp_Object bar;
12693 struct scroll_bar *sb;
12694
e0f712ba
AC
12695 wp = FrontWindow ();
12696 if (is_emacs_window (wp))
12697 {
12698 f = ((mac_output *) GetWRefCon (wp))->mFP;
1a578e9b 12699
e0f712ba
AC
12700#if TARGET_API_MAC_CARBON
12701 SetPort (GetWindowPort (wp));
12702#else
12703 SetPort (wp);
12704#endif
12705
12706 GetMouse (&mouse_pos);
12707
12708 if (!EqualPt (mouse_pos, old_mouse_pos))
12709 {
12710 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12711 && tracked_scroll_bar)
12712 x_scroll_bar_note_movement (tracked_scroll_bar,
12713 mouse_pos.v
12714 - XINT (tracked_scroll_bar->top),
12715 TickCount() * (1000 / 60));
12716 else
12717 note_mouse_movement (f, &mouse_pos);
12718
12719 old_mouse_pos = mouse_pos;
12720 }
12721 }
1a578e9b
AC
12722 }
12723 }
12724
12725 UNBLOCK_INPUT;
12726
12727 return count;
12728}
12729
12730
12731/* Need to override CodeWarrior's input function so no conversion is
12732 done on newlines Otherwise compiled functions in .elc files will be
12733 read incorrectly. Defined in ...:MSL C:MSL
12734 Common:Source:buffer_io.c. */
12735#ifdef __MWERKS__
12736void
12737__convert_to_newlines (unsigned char * p, size_t * n)
12738{
12739#pragma unused(p,n)
12740}
12741
12742void
12743__convert_from_newlines (unsigned char * p, size_t * n)
12744{
12745#pragma unused(p,n)
12746}
12747#endif
12748
12749
12750/* Initialize the struct pointed to by MW to represent a new COLS x
12751 ROWS Macintosh window, using font with name FONTNAME and size
12752 FONTSIZE. */
12753void
12754NewMacWindow (FRAME_PTR fp)
12755{
12756 mac_output *mwp;
e0f712ba
AC
12757#if TARGET_API_MAC_CARBON
12758 static int making_terminal_window = 0;
12759#else
1a578e9b 12760 static int making_terminal_window = 1;
e0f712ba 12761#endif
1a578e9b
AC
12762
12763 mwp = fp->output_data.mac;
12764
12765 if (making_terminal_window)
12766 {
12767 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
12768 (WindowPtr) -1)))
12769 abort ();
12770 making_terminal_window = 0;
12771 }
12772 else
12773 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
12774 abort ();
12775
12776
12777 SetWRefCon (mwp->mWP, (long) mwp);
12778 /* so that update events can find this mac_output struct */
12779 mwp->mFP = fp; /* point back to emacs frame */
12780
e0f712ba
AC
12781#if TARGET_API_MAC_CARBON
12782 SetPort (GetWindowPort (mwp->mWP));
12783#else
1a578e9b 12784 SetPort (mwp->mWP);
e0f712ba 12785#endif
1a578e9b
AC
12786
12787 mwp->fontset = -1;
12788
12789 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
12790 ShowWindow (mwp->mWP);
12791
12792}
12793
12794
12795void make_mac_frame (struct frame *f)
12796{
12797 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12798 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12799
12800 NewMacWindow(f);
e0f712ba
AC
12801 FRAME_BACKGROUND_PIXEL (f) = 0xffffff;
12802 FRAME_FOREGROUND_PIXEL (f) = 0;
1a578e9b
AC
12803
12804 f->output_data.mac->cursor_pixel = 0;
12805 f->output_data.mac->border_pixel = 0x00ff00;
12806 f->output_data.mac->mouse_pixel = 0xff00ff;
12807 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12808
12809 f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
12810
12811 f->output_data.mac->fontset = -1;
12812 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12813 f->output_data.mac->scroll_bar_background_pixel = -1;
12814 f->output_data.mac->left_pos = 4;
12815 f->output_data.mac->top_pos = 4;
12816 f->output_data.mac->border_width = 0;
12817 f->output_data.mac->explicit_parent = 0;
12818
12819 f->output_data.mac->internal_border_width = 0;
12820
12821 f->output_method = output_mac;
12822
12823 f->auto_raise = 1;
12824 f->auto_lower = 1;
12825
12826 f->new_width = 0;
12827 f->new_height = 0;
12828}
12829
12830void make_mac_terminal_frame (struct frame *f)
12831{
12832 Lisp_Object frame;
12833
12834 XSETFRAME (frame, f);
12835
12836 f->output_method = output_mac;
12837 f->output_data.mac = (struct mac_output *)
12838 xmalloc (sizeof (struct mac_output));
12839 bzero (f->output_data.mac, sizeof (struct mac_output));
12840 f->output_data.mac->fontset = -1;
12841 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12842 f->output_data.mac->scroll_bar_background_pixel = -1;
12843
12844 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12845
12846 f->width = 96;
12847 f->height = 4;
12848
12849 make_mac_frame (f);
e0f712ba
AC
12850
12851 x_make_gc (f);
1a578e9b 12852
e0f712ba
AC
12853 /* Need to be initialized for unshow_buffer in window.c. */
12854 selected_window = f->selected_window;
12855
1a578e9b
AC
12856 Fmodify_frame_parameters (frame,
12857 Fcons (Fcons (Qfont,
12858 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12859 Fmodify_frame_parameters (frame,
12860 Fcons (Fcons (Qforeground_color,
12861 build_string ("black")), Qnil));
12862 Fmodify_frame_parameters (frame,
12863 Fcons (Fcons (Qbackground_color,
12864 build_string ("white")), Qnil));
12865}
12866
e0f712ba
AC
12867\f
12868/***********************************************************************
12869 Initialization
12870 ***********************************************************************/
12871
12872#ifdef USE_X_TOOLKIT
12873static XrmOptionDescRec emacs_options[] = {
12874 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12875 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12876
12877 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12878 XrmoptionSepArg, NULL},
12879 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12880
12881 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12882 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12883 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12884 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12885 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12886 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12887 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12888};
12889#endif /* USE_X_TOOLKIT */
12890
12891#ifdef MULTI_KBOARD
12892/* Test whether two display-name strings agree up to the dot that separates
12893 the screen number from the server number. */
12894static int
12895same_x_server (name1, name2)
12896 char *name1, *name2;
12897{
12898 int seen_colon = 0;
12899 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12900 int system_name_length = strlen (system_name);
12901 int length_until_period = 0;
12902
12903 while (system_name[length_until_period] != 0
12904 && system_name[length_until_period] != '.')
12905 length_until_period++;
12906
12907 /* Treat `unix' like an empty host name. */
12908 if (! strncmp (name1, "unix:", 5))
12909 name1 += 4;
12910 if (! strncmp (name2, "unix:", 5))
12911 name2 += 4;
12912 /* Treat this host's name like an empty host name. */
12913 if (! strncmp (name1, system_name, system_name_length)
12914 && name1[system_name_length] == ':')
12915 name1 += system_name_length;
12916 if (! strncmp (name2, system_name, system_name_length)
12917 && name2[system_name_length] == ':')
12918 name2 += system_name_length;
12919 /* Treat this host's domainless name like an empty host name. */
12920 if (! strncmp (name1, system_name, length_until_period)
12921 && name1[length_until_period] == ':')
12922 name1 += length_until_period;
12923 if (! strncmp (name2, system_name, length_until_period)
12924 && name2[length_until_period] == ':')
12925 name2 += length_until_period;
12926
12927 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12928 {
12929 if (*name1 == ':')
12930 seen_colon++;
12931 if (seen_colon && *name1 == '.')
12932 return 1;
12933 }
12934 return (seen_colon
12935 && (*name1 == '.' || *name1 == '\0')
12936 && (*name2 == '.' || *name2 == '\0'));
12937}
12938#endif
12939
12940int mac_initialized = 0;
12941
1a578e9b
AC
12942void
12943mac_initialize_display_info ()
12944{
12945 struct mac_display_info *dpyinfo = &one_mac_display_info;
12946 GDHandle main_device_handle;
12947
12948 bzero (dpyinfo, sizeof (*dpyinfo));
12949
12950 /* Put it on x_display_name_list. */
12951 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
12952 x_display_name_list);
12953 dpyinfo->name_list_element = XCAR (x_display_name_list);
12954
e0f712ba
AC
12955#if 0
12956 dpyinfo->mac_id_name
12957 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
12958 + XSTRING (Vsystem_name)->size
12959 + 2);
12960 sprintf (dpyinfo->mac_id_name, "%s@%s",
12961 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
12962#else
12963 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
12964 strcpy (dpyinfo->mac_id_name, "Mac Display");
12965#endif
12966
1a578e9b
AC
12967 main_device_handle = LMGetMainDevice();
12968
12969 dpyinfo->reference_count = 0;
12970 dpyinfo->resx = 75.0;
12971 dpyinfo->resy = 75.0;
12972 dpyinfo->n_planes = 1;
12973 dpyinfo->n_cbits = 16;
12974 dpyinfo->height = (**main_device_handle).gdRect.bottom;
12975 dpyinfo->width = (**main_device_handle).gdRect.right;
12976 dpyinfo->grabbed = 0;
12977 dpyinfo->root_window = NULL;
12978
12979 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12980 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
12981 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
12982 dpyinfo->mouse_face_window = Qnil;
e0f712ba
AC
12983}
12984
12985struct mac_display_info *
12986mac_term_init (display_name, xrm_option, resource_name)
12987 Lisp_Object display_name;
12988 char *xrm_option;
12989 char *resource_name;
12990{
12991 struct mac_display_info *dpyinfo;
12992 GDHandle main_device_handle;
12993
12994 if (!mac_initialized)
12995 {
12996 mac_initialize ();
12997 mac_initialized = 1;
12998 }
12999
13000 mac_initialize_display_info (display_name);
13001
13002 dpyinfo = &one_mac_display_info;
13003
13004 main_device_handle = LMGetMainDevice();
13005
13006 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13007 dpyinfo->width = (**main_device_handle).gdRect.right;
1a578e9b 13008
e0f712ba 13009 return dpyinfo;
1a578e9b 13010}
e0f712ba
AC
13011\f
13012/* Set up use of X before we make the first connection. */
13013
13014static struct redisplay_interface x_redisplay_interface =
13015{
13016 x_produce_glyphs,
13017 x_write_glyphs,
13018 x_insert_glyphs,
13019 x_clear_end_of_line,
13020 x_scroll_run,
13021 x_after_update_window_line,
13022 x_update_window_begin,
13023 x_update_window_end,
13024 XTcursor_to,
13025 x_flush,
13026 x_clear_mouse_face,
13027 x_get_glyph_overhangs,
13028 x_fix_overlapping_area
13029};
1a578e9b
AC
13030
13031void
e0f712ba 13032mac_initialize ()
1a578e9b
AC
13033{
13034 rif = &x_redisplay_interface;
13035
13036 clear_frame_hook = x_clear_frame;
13037 ins_del_lines_hook = x_ins_del_lines;
1a578e9b
AC
13038 delete_glyphs_hook = x_delete_glyphs;
13039 ring_bell_hook = XTring_bell;
13040 reset_terminal_modes_hook = XTreset_terminal_modes;
13041 set_terminal_modes_hook = XTset_terminal_modes;
13042 update_begin_hook = x_update_begin;
13043 update_end_hook = x_update_end;
13044 set_terminal_window_hook = XTset_terminal_window;
13045 read_socket_hook = XTread_socket;
13046 frame_up_to_date_hook = XTframe_up_to_date;
1a578e9b
AC
13047 mouse_position_hook = XTmouse_position;
13048 frame_rehighlight_hook = XTframe_rehighlight;
13049 frame_raise_lower_hook = XTframe_raise_lower;
13050
13051 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13052 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13053 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13054 judge_scroll_bars_hook = XTjudge_scroll_bars;
13055
13056 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13057
e0f712ba
AC
13058 scroll_region_ok = 1; /* we'll scroll partial frames */
13059 char_ins_del_ok = 1;
13060 line_ins_del_ok = 1; /* we'll just blt 'em */
13061 fast_clear_end_of_line = 1; /* X does this well */
13062 memory_below_frame = 0; /* we don't remember what scrolls
1a578e9b
AC
13063 off the bottom */
13064 baud_rate = 19200;
13065
13066 x_noop_count = 0;
13067 last_tool_bar_item = -1;
13068 any_help_event_p = 0;
13069
13070 /* Try to use interrupt input; if we can't, then start polling. */
13071 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13072
13073#ifdef USE_X_TOOLKIT
13074 XtToolkitInitialize ();
13075 Xt_app_con = XtCreateApplicationContext ();
13076 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13077
13078 /* Install an asynchronous timer that processes Xt timeout events
13079 every 0.1s. This is necessary because some widget sets use
13080 timeouts internally, for example the LessTif menu bar, or the
13081 Xaw3d scroll bar. When Xt timouts aren't processed, these
13082 widgets don't behave normally. */
13083 {
13084 EMACS_TIME interval;
13085 EMACS_SET_SECS_USECS (interval, 0, 100000);
13086 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13087 }
13088#endif
13089
13090#if USE_TOOLKIT_SCROLL_BARS
13091 xaw3d_arrow_scroll = False;
13092 xaw3d_pick_top = True;
13093#endif
13094
13095#if 0
13096 /* Note that there is no real way portable across R3/R4 to get the
13097 original error handler. */
13098 XSetErrorHandler (x_error_handler);
13099 XSetIOErrorHandler (x_io_error_quitter);
13100
13101 /* Disable Window Change signals; they are handled by X events. */
13102#ifdef SIGWINCH
13103 signal (SIGWINCH, SIG_DFL);
13104#endif /* ! defined (SIGWINCH) */
13105
13106 signal (SIGPIPE, x_connection_signal);
13107#endif
13108
13109 mac_initialize_display_info ();
13110}
13111
13112
13113void
13114syms_of_macterm ()
13115{
13116#if 0
13117 staticpro (&x_error_message_string);
13118 x_error_message_string = Qnil;
13119#endif
13120
13121 staticpro (&x_display_name_list);
13122 x_display_name_list = Qnil;
13123
13124 staticpro (&last_mouse_scroll_bar);
13125 last_mouse_scroll_bar = Qnil;
13126
13127 staticpro (&Qvendor_specific_keysyms);
13128 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13129
13130 staticpro (&last_mouse_press_frame);
13131 last_mouse_press_frame = Qnil;
13132
8f47302e
AC
13133 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13134 staticpro (&Qmac_ready_for_drag_n_drop);
13135
1a578e9b
AC
13136 help_echo = Qnil;
13137 staticpro (&help_echo);
13138 help_echo_object = Qnil;
13139 staticpro (&help_echo_object);
13140 help_echo_window = Qnil;
13141 staticpro (&help_echo_window);
13142 previous_help_echo = Qnil;
13143 staticpro (&previous_help_echo);
13144 help_echo_pos = -1;
13145
e0f712ba
AC
13146 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13147 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13148 x_autoselect_window_p = 0;
13149
1a578e9b 13150 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
e0f712ba
AC
13151 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13152For example, if a block cursor is over a tab, it will be drawn as
13153wide as that tab on the display. */);
1a578e9b
AC
13154 x_stretch_cursor_p = 0;
13155
e0f712ba
AC
13156#if 0 /* TODO: Setting underline position from font properties. */
13157 DEFVAR_BOOL ("x-use-underline-position-properties",
13158 &x_use_underline_position_properties,
13159 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13160nil means ignore them. If you encounter fonts with bogus
13161UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13162to 4.1, set this to nil. */);
13163 x_use_underline_position_properties = 1;
1a578e9b
AC
13164#endif
13165
e0f712ba
AC
13166 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13167 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13168 Vx_toolkit_scroll_bars = Qt;
13169
1a578e9b
AC
13170 staticpro (&last_mouse_motion_frame);
13171 last_mouse_motion_frame = Qnil;
13172
13173 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
e0f712ba
AC
13174 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13175Otherwise the option key is used. */);
1a578e9b
AC
13176 Vmac_command_key_is_meta = Qt;
13177
1a578e9b 13178 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
e0f712ba
AC
13179 doc: /* One of the Text Encoding Base constant values defined in the
13180Basic Text Constants section of Inside Macintosh - Text Encoding
13181Conversion Manager. Its value determines the encoding characters
13182typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13183will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13184its default value, no conversion takes place. If it is set to
13185kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13186characters typed on Mac keyboard are first converted into the
13187ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13188passed to Emacs. Together with Emacs's set-keyboard-coding-system
13189command, this enables the Mac keyboard to be used to enter non-ASCII
13190characters directly. */);
1a578e9b
AC
13191 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13192}