(enum fringe_bitmap_type): Define here.
[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
f00691a3 47#undef init_process
e0f712ba
AC
48#include <Carbon/Carbon.h>
49#undef free
50#define free unexec_free
51#undef malloc
52#define malloc unexec_malloc
53#undef realloc
54#define realloc unexec_realloc
55#undef min
56#define min(a, b) ((a) < (b) ? (a) : (b))
57#undef max
58#define max(a, b) ((a) > (b) ? (a) : (b))
f00691a3
AC
59#undef init_process
60#define init_process emacs_init_process
742fbed7
AC
61/* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
62 obtain events from the event queue. If set to 0, WaitNextEvent is
63 used instead. */
64#define USE_CARBON_EVENTS 1
e0f712ba 65#else /* not MAC_OSX */
1a578e9b
AC
66#include <Quickdraw.h>
67#include <ToolUtils.h>
68#include <Sound.h>
69#include <Events.h>
70#include <Script.h>
71#include <Resources.h>
72#include <Fonts.h>
73#include <TextUtils.h>
74#include <LowMem.h>
75#include <Controls.h>
e0f712ba 76#if defined (__MRC__) || (__MSL__ >= 0x6000)
1a578e9b
AC
77#include <ControlDefinitions.h>
78#endif
e0f712ba 79#include <Gestalt.h>
1a578e9b
AC
80
81#if __profile__
82#include <profiler.h>
83#endif
e0f712ba 84#endif /* not MAC_OSX */
1a578e9b
AC
85
86#include "systty.h"
87#include "systime.h"
e0f712ba
AC
88#include "atimer.h"
89#include "keymap.h"
1a578e9b 90
1a578e9b
AC
91#include <ctype.h>
92#include <errno.h>
93#include <setjmp.h>
94#include <sys/stat.h>
95
e0f712ba 96#include "keyboard.h"
1a578e9b
AC
97#include "frame.h"
98#include "dispextern.h"
99#include "fontset.h"
100#include "termhooks.h"
101#include "termopts.h"
102#include "termchar.h"
103#include "gnu.h"
104#include "disptab.h"
105#include "buffer.h"
106#include "window.h"
1a578e9b 107#include "intervals.h"
e0f712ba 108#include "composite.h"
1a578e9b
AC
109#include "coding.h"
110
1a578e9b
AC
111#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
112
742fbed7
AC
113/* Set of macros that handle mapping of Mac modifier keys to emacs. */
114#define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
115 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
116#define macShiftKey (shiftKey)
117#define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
118 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
119 : controlKey)
120#define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
121
1a578e9b 122\f
3f332ef3 123/* Fringe bitmaps. */
1a578e9b 124
3f332ef3 125enum fringe_bitmap_type
1a578e9b 126{
3f332ef3 127 NO_FRINGE_BITMAP,
1a578e9b
AC
128 LEFT_TRUNCATION_BITMAP,
129 RIGHT_TRUNCATION_BITMAP,
130 OVERLAY_ARROW_BITMAP,
131 CONTINUED_LINE_BITMAP,
132 CONTINUATION_LINE_BITMAP,
133 ZV_LINE_BITMAP
134};
135
136/* Bitmap drawn to indicate lines not displaying text if
137 `indicate-empty-lines' is non-nil. */
138
139#define zv_width 8
d33c49e8
KS
140#define zv_height 72
141#define zv_period 3
1a578e9b 142static unsigned char zv_bits[] = {
d33c49e8
KS
143 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
144 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
145 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
146 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
147 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
148 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
149 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
150 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
1a578e9b
AC
151
152/* An arrow like this: `<-'. */
153
154#define left_width 8
155#define left_height 8
156static unsigned char left_bits[] = {
157 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
158
159/* Right truncation arrow bitmap `->'. */
160
161#define right_width 8
162#define right_height 8
163static unsigned char right_bits[] = {
164 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
165
166/* Marker for continued lines. */
167
168#define continued_width 8
169#define continued_height 8
170static unsigned char continued_bits[] = {
171 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
172
173/* Marker for continuation lines. */
174
175#define continuation_width 8
176#define continuation_height 8
177static unsigned char continuation_bits[] = {
178 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
179
180/* Overlay arrow bitmap. */
181
182#if 0
183/* A bomb. */
184#define ov_width 8
185#define ov_height 8
186static unsigned char ov_bits[] = {
187 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
188#else
189/* A triangular arrow. */
190#define ov_width 8
191#define ov_height 8
192static unsigned char ov_bits[] = {
193 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
194#endif
195
196extern Lisp_Object Qhelp_echo;
197
198\f
e0f712ba 199/* Non-nil means Emacs uses toolkit scroll bars. */
1a578e9b 200
e0f712ba 201Lisp_Object Vx_toolkit_scroll_bars;
1a578e9b
AC
202
203/* If a string, XTread_socket generates an event to display that string.
204 (The display is done in read_char.) */
177c0ea7 205
1a578e9b
AC
206static Lisp_Object help_echo;
207static Lisp_Object help_echo_window;
208static Lisp_Object help_echo_object;
209static int help_echo_pos;
210
211/* Temporary variable for XTread_socket. */
212
213static Lisp_Object previous_help_echo;
214
215/* Non-zero means that a HELP_EVENT has been generated since Emacs
216 start. */
217
218static int any_help_event_p;
219
e0f712ba
AC
220/* Non-zero means autoselect window with the mouse cursor. */
221
222int x_autoselect_window_p;
223
1a578e9b
AC
224/* Non-zero means draw block and hollow cursor as wide as the glyph
225 under it. For example, if a block cursor is over a tab, it will be
226 drawn as wide as that tab on the display. */
227
228int x_stretch_cursor_p;
229
e0f712ba
AC
230/* Non-zero means make use of UNDERLINE_POSITION font properties. */
231
232int x_use_underline_position_properties;
233
1a578e9b
AC
234/* This is a chain of structures for all the X displays currently in
235 use. */
236
237struct x_display_info *x_display_list;
238
239/* This is a list of cons cells, each of the form (NAME
240 . FONT-LIST-CACHE), one for each element of x_display_list and in
241 the same order. NAME is the name of the frame. FONT-LIST-CACHE
242 records previous values returned by x-list-fonts. */
243
244Lisp_Object x_display_name_list;
245
246/* This is display since Mac does not support multiple ones. */
247struct mac_display_info one_mac_display_info;
248
249/* Frame being updated by update_frame. This is declared in term.c.
250 This is set by update_begin and looked at by all the XT functions.
251 It is zero while not inside an update. In that case, the XT
252 functions assume that `selected_frame' is the frame to apply to. */
253
254extern struct frame *updating_frame;
255
e0f712ba
AC
256extern int waiting_for_input;
257
1a578e9b
AC
258/* This is a frame waiting to be auto-raised, within XTread_socket. */
259
260struct frame *pending_autoraise_frame;
261
177c0ea7 262/* Nominal cursor position -- where to draw output.
1a578e9b
AC
263 HPOS and VPOS are window relative glyph matrix coordinates.
264 X and Y are window relative pixel coordinates. */
265
266struct cursor_pos output_cursor;
267
268/* Non-zero means user is interacting with a toolkit scroll bar. */
269
270static int toolkit_scroll_bar_interaction;
271
272/* Mouse movement.
273
274 Formerly, we used PointerMotionHintMask (in standard_event_mask)
275 so that we would have to call XQueryPointer after each MotionNotify
276 event to ask for another such event. However, this made mouse tracking
277 slow, and there was a bug that made it eventually stop.
278
279 Simply asking for MotionNotify all the time seems to work better.
280
281 In order to avoid asking for motion events and then throwing most
282 of them away or busy-polling the server for mouse positions, we ask
283 the server for pointer motion hints. This means that we get only
284 one event per group of mouse movements. "Groups" are delimited by
285 other kinds of events (focus changes and button clicks, for
286 example), or by XQueryPointer calls; when one of these happens, we
287 get another MotionNotify event the next time the mouse moves. This
288 is at least as efficient as getting motion events when mouse
289 tracking is on, and I suspect only negligibly worse when tracking
290 is off. */
291
292/* Where the mouse was last time we reported a mouse event. */
293
294FRAME_PTR last_mouse_frame;
295static Rect last_mouse_glyph;
296static Lisp_Object last_mouse_press_frame;
297
298/* The scroll bar in which the last X motion event occurred.
299
300 If the last X motion event occurred in a scroll bar, we set this so
301 XTmouse_position can know whether to report a scroll bar motion or
302 an ordinary motion.
303
304 If the last X motion event didn't occur in a scroll bar, we set
305 this to Qnil, to tell XTmouse_position to return an ordinary motion
306 event. */
307
308static Lisp_Object last_mouse_scroll_bar;
309
310/* This is a hack. We would really prefer that XTmouse_position would
311 return the time associated with the position it returns, but there
312 doesn't seem to be any way to wrest the time-stamp from the server
313 along with the position query. So, we just keep track of the time
314 of the last movement we received, and return that in hopes that
315 it's somewhat accurate. */
316
317static Time last_mouse_movement_time;
318
319enum mouse_tracking_type {
320 mouse_tracking_none,
321 mouse_tracking_mouse_movement,
322 mouse_tracking_scroll_bar
323};
324
325enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
326
327struct scroll_bar *tracked_scroll_bar = NULL;
328
329/* Incremented by XTread_socket whenever it really tries to read
330 events. */
331
332#ifdef __STDC__
333static int volatile input_signal_count;
334#else
335static int input_signal_count;
336#endif
337
338/* Used locally within XTread_socket. */
339
340static int x_noop_count;
341
342/* Initial values of argv and argc. */
343
344extern char **initial_argv;
345extern int initial_argc;
346
347extern Lisp_Object Vcommand_line_args, Vsystem_name;
348
349/* Tells if a window manager is present or not. */
350
351extern Lisp_Object Vx_no_window_manager;
352
353extern Lisp_Object Qface, Qmouse_face;
354
355extern int errno;
356
357/* A mask of extra modifier bits to put into every keyboard char. */
358
359extern int extra_keyboard_modifiers;
360
361static Lisp_Object Qvendor_specific_keysyms;
362
363#if 0
364extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
365#endif
366
367extern Lisp_Object x_icon_type P_ ((struct frame *));
368
8030369c 369extern int inhibit_window_system;
1a578e9b
AC
370
371#if __MRC__
372QDGlobals qd; /* QuickDraw global information structure. */
373#endif
374
375
376/* Enumeration for overriding/changing the face to use for drawing
377 glyphs in x_draw_glyphs. */
378
379enum draw_glyphs_face
380{
381 DRAW_NORMAL_TEXT,
382 DRAW_INVERSE_VIDEO,
383 DRAW_CURSOR,
384 DRAW_MOUSE_FACE,
385 DRAW_IMAGE_RAISED,
386 DRAW_IMAGE_SUNKEN
387};
388
389struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
390struct mac_display_info *mac_display_info_for_display (Display *);
391static void x_update_window_end P_ ((struct window *, int, int));
392static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
1a578e9b 393static int fast_find_position P_ ((struct window *, int, int *, int *,
e0f712ba
AC
394 int *, int *, Lisp_Object));
395static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
396 int *, int *, int *, int *, int));
1a578e9b
AC
397static void set_output_cursor P_ ((struct cursor_pos *));
398static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
e0f712ba 399 int *, int *, int *, int));
1a578e9b
AC
400static void note_mode_line_highlight P_ ((struct window *, int, int));
401static void note_mouse_highlight P_ ((struct frame *, int, int));
402static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
e0f712ba 403static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
1a578e9b
AC
404static void show_mouse_face P_ ((struct x_display_info *,
405 enum draw_glyphs_face));
e0f712ba
AC
406static int cursor_in_mouse_face_p P_ ((struct window *));
407static int clear_mouse_face P_ ((struct mac_display_info *));
1a578e9b
AC
408static int x_io_error_quitter P_ ((Display *));
409int x_catch_errors P_ ((Display *));
410void x_uncatch_errors P_ ((Display *, int));
411void x_lower_frame P_ ((struct frame *));
412void x_scroll_bar_clear P_ ((struct frame *));
413int x_had_errors_p P_ ((Display *));
414void x_wm_set_size_hint P_ ((struct frame *, long, int));
415void x_raise_frame P_ ((struct frame *));
416void x_set_window_size P_ ((struct frame *, int, int, int));
417void x_wm_set_window_state P_ ((struct frame *, int));
418void x_wm_set_icon_pixmap P_ ((struct frame *, int));
e0f712ba 419void mac_initialize P_ ((void));
1a578e9b
AC
420static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
421static int x_compute_min_glyph_bounds P_ ((struct frame *));
1a578e9b
AC
422static void x_draw_phys_cursor_glyph P_ ((struct window *,
423 struct glyph_row *,
424 enum draw_glyphs_face));
425static void x_update_end P_ ((struct frame *));
426static void XTframe_up_to_date P_ ((struct frame *));
427static void XTreassert_line_highlight P_ ((int, int));
428static void x_change_line_highlight P_ ((int, int, int, int));
429static void XTset_terminal_modes P_ ((void));
430static void XTreset_terminal_modes P_ ((void));
431static void XTcursor_to P_ ((int, int, int, int));
432static void x_write_glyphs P_ ((struct glyph *, int));
433static void x_clear_end_of_line P_ ((int));
434static void x_clear_frame P_ ((void));
435static void x_clear_cursor P_ ((struct window *));
436static void frame_highlight P_ ((struct frame *));
437static void frame_unhighlight P_ ((struct frame *));
438static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
439static void XTframe_rehighlight P_ ((struct frame *));
440static void x_frame_rehighlight P_ ((struct x_display_info *));
441static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
442static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
443static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
444static void expose_frame P_ ((struct frame *, int, int, int, int));
e0f712ba 445static int expose_window_tree P_ ((struct window *, Rect *));
ca45961d
AC
446static void expose_overlaps P_ ((struct window *, struct glyph_row *,
447 struct glyph_row *));
e0f712ba 448static int expose_window P_ ((struct window *, Rect *));
1a578e9b 449static void expose_area P_ ((struct window *, struct glyph_row *,
e0f712ba
AC
450 Rect *, enum glyph_row_area));
451static int expose_line P_ ((struct window *, struct glyph_row *,
452 Rect *));
1a578e9b
AC
453void x_display_cursor (struct window *, int, int, int, int, int);
454void x_update_cursor P_ ((struct frame *, int));
455static void x_update_cursor_in_window_tree P_ ((struct window *, int));
456static void x_update_window_cursor P_ ((struct window *, int));
457static void x_erase_phys_cursor P_ ((struct window *));
458void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
177c0ea7 459static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
d33c49e8 460 enum fringe_bitmap_type, int left_p));
1a578e9b
AC
461static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
462 GC, int));
463static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
3f332ef3 464static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
e0f712ba
AC
465static void notice_overwritten_cursor P_ ((struct window *,
466 enum glyph_row_area,
467 int, int, int, int));
1a578e9b
AC
468static void x_flush P_ ((struct frame *f));
469static void x_update_begin P_ ((struct frame *));
470static void x_update_window_begin P_ ((struct window *));
471static void x_draw_vertical_border P_ ((struct window *));
472static void x_after_update_window_line P_ ((struct glyph_row *));
473static INLINE void take_vertical_position_into_account P_ ((struct it *));
474static void x_produce_stretch_glyph P_ ((struct it *));
475
476static void activate_scroll_bars (FRAME_PTR);
477static void deactivate_scroll_bars (FRAME_PTR);
478
5883787c
AC
479static int is_emacs_window (WindowPtr);
480
1a578e9b
AC
481extern int image_ascent (struct image *, struct face *);
482void x_set_offset (struct frame *, int, int, int);
483int x_bitmap_icon (struct frame *, Lisp_Object);
484void x_make_frame_visible (struct frame *);
485
486extern void window_scroll (Lisp_Object, int, int, int);
487
488/* Defined in macmenu.h. */
489extern void menubar_selection_callback (FRAME_PTR, int);
490extern void set_frame_menubar (FRAME_PTR, int, int);
491
492/* X display function emulation */
493
494/* Structure borrowed from Xlib.h to represent two-byte characters in
495 dumpglyphs. */
496
497typedef struct {
498 unsigned char byte1;
499 unsigned char byte2;
500} XChar2b;
501
502static void
503XFreePixmap (display, pixmap)
504 Display *display;
505 Pixmap pixmap;
506{
507 PixMap *p = (PixMap *) pixmap;
177c0ea7 508
1a578e9b
AC
509 xfree (p->baseAddr);
510 xfree (p);
511}
512
513
514/* Set foreground color for subsequent QuickDraw commands. Assume
515 graphic port has already been set. */
516
517static void
518mac_set_forecolor (unsigned long color)
519{
520 RGBColor fg_color;
177c0ea7 521
1a578e9b
AC
522 fg_color.red = RED_FROM_ULONG (color) * 256;
523 fg_color.green = GREEN_FROM_ULONG (color) * 256;
524 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
177c0ea7
JB
525
526 RGBForeColor (&fg_color);
1a578e9b
AC
527}
528
529
530/* Set background color for subsequent QuickDraw commands. Assume
531 graphic port has already been set. */
532
533static void
534mac_set_backcolor (unsigned long color)
535{
536 RGBColor bg_color;
177c0ea7 537
1a578e9b
AC
538 bg_color.red = RED_FROM_ULONG (color) * 256;
539 bg_color.green = GREEN_FROM_ULONG (color) * 256;
540 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
177c0ea7
JB
541
542 RGBBackColor (&bg_color);
1a578e9b
AC
543}
544
545/* Set foreground and background color for subsequent QuickDraw
546 commands. Assume that the graphic port has already been set. */
547
548static void
549mac_set_colors (GC gc)
550{
551 mac_set_forecolor (gc->foreground);
552 mac_set_backcolor (gc->background);
553}
554
555/* Mac version of XDrawLine. */
556
557static void
558XDrawLine (display, w, gc, x1, y1, x2, y2)
559 Display *display;
560 WindowPtr w;
561 GC gc;
562 int x1, y1, x2, y2;
563{
e0f712ba
AC
564#if TARGET_API_MAC_CARBON
565 SetPort (GetWindowPort (w));
566#else
1a578e9b 567 SetPort (w);
e0f712ba
AC
568#endif
569
1a578e9b
AC
570 mac_set_colors (gc);
571
572 MoveTo (x1, y1);
573 LineTo (x2, y2);
574}
575
576/* Mac version of XClearArea. */
577
2e875e36 578void
1a578e9b
AC
579XClearArea (display, w, x, y, width, height, exposures)
580 Display *display;
581 WindowPtr w;
582 int x, y;
583 unsigned int width, height;
584 int exposures;
585{
586 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
587 Rect r;
588 XGCValues xgc;
589
e0f712ba
AC
590 xgc.foreground = mwp->x_compatible.foreground_pixel;
591 xgc.background = mwp->x_compatible.background_pixel;
1a578e9b 592
e0f712ba
AC
593#if TARGET_API_MAC_CARBON
594 SetPort (GetWindowPort (w));
595#else
1a578e9b 596 SetPort (w);
e0f712ba
AC
597#endif
598
1a578e9b
AC
599 mac_set_colors (&xgc);
600 SetRect (&r, x, y, x + width, y + height);
601
602 EraseRect (&r);
603}
604
605/* Mac version of XClearWindow. */
606
607static void
608XClearWindow (display, w)
609 Display *display;
610 WindowPtr w;
611{
612 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
613 XGCValues xgc;
614
e0f712ba
AC
615 xgc.foreground = mwp->x_compatible.foreground_pixel;
616 xgc.background = mwp->x_compatible.background_pixel;
1a578e9b 617
e0f712ba
AC
618#if TARGET_API_MAC_CARBON
619 SetPort (GetWindowPort (w));
620#else
1a578e9b 621 SetPort (w);
e0f712ba
AC
622#endif
623
1a578e9b
AC
624 mac_set_colors (&xgc);
625
e0f712ba
AC
626#if TARGET_API_MAC_CARBON
627 {
628 Rect r;
177c0ea7 629
e0f712ba
AC
630 GetWindowPortBounds (w, &r);
631 EraseRect (&r);
632 }
633#else /* not TARGET_API_MAC_CARBON */
634 EraseRect (&(w->portRect));
635#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
636}
637
638
639/* Mac replacement for XCopyArea. */
640
641static void
642mac_draw_bitmap (display, w, gc, x, y, bitmap)
643 Display *display;
644 WindowPtr w;
645 GC gc;
646 int x, y;
647 BitMap *bitmap;
648{
649 Rect r;
650
e0f712ba
AC
651#if TARGET_API_MAC_CARBON
652 SetPort (GetWindowPort (w));
653#else
1a578e9b 654 SetPort (w);
e0f712ba
AC
655#endif
656
1a578e9b
AC
657 mac_set_colors (gc);
658 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
659
e0f712ba
AC
660#if TARGET_API_MAC_CARBON
661 {
662 PixMapHandle pmh;
663
664 LockPortBits (GetWindowPort (w));
665 pmh = GetPortPixMap (GetWindowPort (w));
666 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
667 UnlockPortBits (GetWindowPort (w));
668 }
669#else /* not TARGET_API_MAC_CARBON */
177c0ea7 670 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
e0f712ba 671#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
672}
673
674
675/* Mac replacement for XSetClipRectangles. */
676
677static void
678mac_set_clip_rectangle (display, w, r)
679 Display *display;
680 WindowPtr w;
681 Rect *r;
682{
e0f712ba
AC
683#if TARGET_API_MAC_CARBON
684 SetPort (GetWindowPort (w));
685#else
1a578e9b 686 SetPort (w);
e0f712ba 687#endif
1a578e9b
AC
688
689 ClipRect (r);
690}
691
692
693/* Mac replacement for XSetClipMask. */
694
695static void
696mac_reset_clipping (display, w)
697 Display *display;
698 WindowPtr w;
699{
700 Rect r;
177c0ea7 701
e0f712ba
AC
702#if TARGET_API_MAC_CARBON
703 SetPort (GetWindowPort (w));
704#else
1a578e9b 705 SetPort (w);
e0f712ba 706#endif
1a578e9b
AC
707
708 SetRect (&r, -32767, -32767, 32767, 32767);
709 ClipRect (&r);
710}
711
712
713/* Mac replacement for XCreateBitmapFromBitmapData. */
714
715static void
716mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
717 BitMap *bitmap;
718 char *bits;
719 int w, h;
720{
721 int bytes_per_row, i, j;
722
723 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
724 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
725 if (!bitmap->baseAddr)
726 abort ();
727
728 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
729 for (i = 0; i < h; i++)
730 for (j = 0; j < w; j++)
731 if (BitTst (bits, i * w + j))
732 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
733
734 SetRect (&(bitmap->bounds), 0, 0, w, h);
735}
736
737
738static void
739mac_free_bitmap (bitmap)
740 BitMap *bitmap;
741{
742 xfree (bitmap->baseAddr);
743}
744
745/* Mac replacement for XFillRectangle. */
746
747static void
748XFillRectangle (display, w, gc, x, y, width, height)
749 Display *display;
750 WindowPtr w;
751 GC gc;
752 int x, y;
753 unsigned int width, height;
754{
755 Rect r;
756
e0f712ba
AC
757#if TARGET_API_MAC_CARBON
758 SetPort (GetWindowPort (w));
759#else
1a578e9b 760 SetPort (w);
e0f712ba
AC
761#endif
762
1a578e9b
AC
763 mac_set_colors (gc);
764 SetRect (&r, x, y, x + width, y + height);
765
766 PaintRect (&r); /* using foreground color of gc */
767}
768
769
770/* Mac replacement for XDrawRectangle: dest is a window. */
771
772static void
773mac_draw_rectangle (display, w, gc, x, y, width, height)
774 Display *display;
775 WindowPtr w;
776 GC gc;
777 int x, y;
778 unsigned int width, height;
779{
780 Rect r;
781
e0f712ba
AC
782#if TARGET_API_MAC_CARBON
783 SetPort (GetWindowPort (w));
784#else
1a578e9b 785 SetPort (w);
e0f712ba
AC
786#endif
787
1a578e9b
AC
788 mac_set_colors (gc);
789 SetRect (&r, x, y, x + width + 1, y + height + 1);
790
791 FrameRect (&r); /* using foreground color of gc */
792}
793
794
795/* Mac replacement for XDrawRectangle: dest is a Pixmap. */
796
797static void
798mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
799 Display *display;
800 Pixmap p;
801 GC gc;
802 int x, y;
803 unsigned int width, height;
804{
805#if 0 /* MAC_TODO: draw a rectangle in a PixMap */
806 Rect r;
807
e0f712ba
AC
808#if TARGET_API_MAC_CARBON
809 SetPort (GetWindowPort (w));
810#else
1a578e9b 811 SetPort (w);
e0f712ba
AC
812#endif
813
1a578e9b
AC
814 mac_set_colors (gc);
815 SetRect (&r, x, y, x + width, y + height);
816
817 FrameRect (&r); /* using foreground color of gc */
e0f712ba 818#endif /* 0 */
1a578e9b
AC
819}
820
821
822static void
823mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
824 bytes_per_char)
825 Display *display;
826 WindowPtr w;
827 GC gc;
828 int x, y;
829 char *buf;
830 int nchars, mode, bytes_per_char;
831{
e0f712ba
AC
832#if TARGET_API_MAC_CARBON
833 SetPort (GetWindowPort (w));
834#else
1a578e9b 835 SetPort (w);
e0f712ba
AC
836#endif
837
1a578e9b
AC
838 mac_set_colors (gc);
839
840 TextFont (gc->font->mac_fontnum);
841 TextSize (gc->font->mac_fontsize);
842 TextFace (gc->font->mac_fontface);
843 TextMode (mode);
844
845 MoveTo (x, y);
846 DrawText (buf, 0, nchars * bytes_per_char);
847}
848
849
850/* Mac replacement for XDrawString. */
851
852static void
853XDrawString (display, w, gc, x, y, buf, nchars)
854 Display *display;
855 WindowPtr w;
856 GC gc;
857 int x, y;
858 char *buf;
859 int nchars;
860{
861 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
862}
863
864
865/* Mac replacement for XDrawString16. */
866
867static void
868XDrawString16 (display, w, gc, x, y, buf, nchars)
869 Display *display;
870 WindowPtr w;
871 GC gc;
872 int x, y;
873 XChar2b *buf;
874 int nchars;
875{
876 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
877 2);
878}
879
880
881/* Mac replacement for XDrawImageString. */
882
883static void
884XDrawImageString (display, w, gc, x, y, buf, nchars)
885 Display *display;
886 WindowPtr w;
887 GC gc;
888 int x, y;
889 char *buf;
890 int nchars;
891{
892 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
893}
894
895
896/* Mac replacement for XDrawString16. */
897
898static void
899XDrawImageString16 (display, w, gc, x, y, buf, nchars)
900 Display *display;
901 WindowPtr w;
902 GC gc;
903 int x, y;
904 XChar2b *buf;
905 int nchars;
906{
907 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
908 2);
909}
910
911
912/* Mac replacement for XCopyArea: dest must be window. */
913
914static void
915mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
916 dest_y)
917 Display *display;
918 Pixmap src;
919 WindowPtr dest;
920 GC gc;
921 int src_x, src_y;
922 unsigned int width, height;
923 int dest_x, dest_y;
924{
925 Rect src_r, dest_r;
926
e0f712ba
AC
927#if TARGET_API_MAC_CARBON
928 SetPort (GetWindowPort (dest));
929#else
1a578e9b 930 SetPort (dest);
e0f712ba
AC
931#endif
932
1a578e9b
AC
933 mac_set_colors (gc);
934
935 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
936 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
937
e0f712ba
AC
938#if TARGET_API_MAC_CARBON
939 {
940 PixMapHandle pmh;
941
942 LockPortBits (GetWindowPort (dest));
943 pmh = GetPortPixMap (GetWindowPort (dest));
944 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
945 UnlockPortBits (GetWindowPort (dest));
946 }
947#else /* not TARGET_API_MAC_CARBON */
948 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
949#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
950}
951
952
f9e25d0c 953#if 0
1a578e9b
AC
954/* Convert a pair of local coordinates to global (screen) coordinates.
955 Assume graphic port has been properly set. */
956static void
957local_to_global_coord (short *h, short *v)
958{
959 Point p;
177c0ea7 960
1a578e9b
AC
961 p.h = *h;
962 p.v = *v;
177c0ea7 963
1a578e9b 964 LocalToGlobal (&p);
177c0ea7 965
1a578e9b
AC
966 *h = p.h;
967 *v = p.v;
968}
f9e25d0c 969#endif
1a578e9b
AC
970
971/* Mac replacement for XCopyArea: used only for scrolling. */
972
973static void
974mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
975 Display *display;
976 WindowPtr w;
977 GC gc;
978 int src_x, src_y;
979 unsigned int width, height;
980 int dest_x, dest_y;
981{
e0f712ba
AC
982#if TARGET_API_MAC_CARBON
983 Rect gw_r, src_r, dest_r;
984 PixMapHandle pmh;
985
986 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
987 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
988
989 SetPort (GetWindowPort (w));
2d97ff8c
AC
990
991 ForeColor (blackColor);
992 BackColor (whiteColor);
e0f712ba
AC
993
994 LockPortBits (GetWindowPort (w));
995 pmh = GetPortPixMap (GetWindowPort (w));
996 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
997 UnlockPortBits (GetWindowPort (w));
2d97ff8c
AC
998
999 mac_set_colors (gc);
e0f712ba 1000#else /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
1001 Rect src_r, dest_r;
1002
1003 SetPort (w);
f9e25d0c 1004#if 0
1a578e9b 1005 mac_set_colors (gc);
f9e25d0c 1006#endif
1a578e9b
AC
1007
1008 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1009 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1010
f9e25d0c 1011#if 0
1a578e9b
AC
1012 /* Need to use global coordinates and screenBits since src and dest
1013 areas overlap in general. */
1014 local_to_global_coord (&src_r.left, &src_r.top);
1015 local_to_global_coord (&src_r.right, &src_r.bottom);
1016 local_to_global_coord (&dest_r.left, &dest_r.top);
1017 local_to_global_coord (&dest_r.right, &dest_r.bottom);
1018
1019 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
f9e25d0c
AC
1020#else
1021 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1022 color mapping in CopyBits. Otherwise, it will be slow. */
1023 ForeColor (blackColor);
1024 BackColor (whiteColor);
1025 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
177c0ea7 1026
f9e25d0c
AC
1027 mac_set_colors (gc);
1028#endif
e0f712ba 1029#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
1030}
1031
1032
1033/* Mac replacement for XCopyArea: dest must be Pixmap. */
1034
1035static void
177c0ea7 1036mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1a578e9b
AC
1037 dest_x, dest_y)
1038 Display *display;
1039 Pixmap src;
1040 Pixmap dest;
1041 GC gc;
1042 int src_x, src_y;
1043 unsigned int width, height;
1044 int dest_x, dest_y;
1045{
1046 Rect src_r, dest_r;
1047 int src_right = ((PixMap *) src)->bounds.right;
1048 int src_bottom = ((PixMap *) src)->bounds.bottom;
1049 int w = src_right - src_x;
1050 int h = src_bottom - src_y;
1051
1052 mac_set_colors (gc);
177c0ea7 1053
1a578e9b
AC
1054 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1055 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1056
e0f712ba 1057 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1a578e9b
AC
1058}
1059
1060
1061/* Mac replacement for XChangeGC. */
1062
1063static void
1064XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1065 XGCValues *xgcv)
1066{
1067 if (mask & GCForeground)
1068 gc->foreground = xgcv->foreground;
1069 if (mask & GCBackground)
1070 gc->background = xgcv->background;
1071 if (mask & GCFont)
1072 gc->font = xgcv->font;
1073}
1074
1075
1076/* Mac replacement for XCreateGC. */
1077
1078XGCValues *
1079XCreateGC (void * ignore, Window window, unsigned long mask,
1080 XGCValues *xgcv)
1081{
1082 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1083 bzero (gc, sizeof (XGCValues));
1084
1085 XChangeGC (ignore, gc, mask, xgcv);
1086
1087 return gc;
1088}
1089
1090
1091/* Used in xfaces.c. */
1092
1093void
1094XFreeGC (display, gc)
1095 Display *display;
1096 GC gc;
1097{
1098 xfree (gc);
1099}
1100
1101
1102/* Mac replacement for XGetGCValues. */
1103
1104static void
1105XGetGCValues (void* ignore, XGCValues *gc,
1106 unsigned long mask, XGCValues *xgcv)
1107{
1108 XChangeGC (ignore, xgcv, mask, gc);
1109}
1110
1111
1112/* Mac replacement for XSetForeground. */
1113
1114static void
1115XSetForeground (display, gc, color)
1116 Display *display;
1117 GC gc;
1118 unsigned long color;
1119{
1120 gc->foreground = color;
1121}
1122
1123
1124/* Mac replacement for XSetFont. */
1125
1126static void
1127XSetFont (display, gc, font)
1128 Display *display;
1129 GC gc;
1130 XFontStruct *font;
1131{
1132 gc->font = font;
1133}
1134
1135
1136static void
1137XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1138 int *direction,int *font_ascent,
1139 int *font_descent, XCharStruct *cs)
1140{
1141 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1142}
1143
1144
1145/* x_sync is a no-op on Mac. */
1146void
1147x_sync (f)
1148 void *f;
1149{
1150}
1151
1152
e0f712ba
AC
1153/* Remove calls to XFlush by defining XFlush to an empty replacement.
1154 Calls to XFlush should be unnecessary because the X output buffer
1155 is flushed automatically as needed by calls to XPending,
1156 XNextEvent, or XWindowEvent according to the XFlush man page.
1157 XTread_socket calls XPending. Removing XFlush improves
1158 performance. */
1159
1160#if TARGET_API_MAC_CARBON
1161#define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1162#else
177c0ea7 1163#define XFlush(DISPLAY) (void) 0
e0f712ba
AC
1164#endif
1165
1a578e9b
AC
1166/* Flush display of frame F, or of all frames if F is null. */
1167
1168void
1169x_flush (f)
1170 struct frame *f;
1171{
e0f712ba 1172#if TARGET_API_MAC_CARBON
1a578e9b
AC
1173 BLOCK_INPUT;
1174 if (f == NULL)
1175 {
1176 Lisp_Object rest, frame;
1177 FOR_EACH_FRAME (rest, frame)
1178 x_flush (XFRAME (frame));
1179 }
1180 else if (FRAME_X_P (f))
1181 XFlush (FRAME_MAC_DISPLAY (f));
1182 UNBLOCK_INPUT;
e0f712ba 1183#endif /* TARGET_API_MAC_CARBON */
1a578e9b
AC
1184}
1185
1186
1a578e9b
AC
1187\f
1188/* Return the struct mac_display_info corresponding to DPY. There's
1189 only one. */
1190
1191struct mac_display_info *
1192mac_display_info_for_display (dpy)
1193 Display *dpy;
1194{
1195 return &one_mac_display_info;
1196}
1197
1198
1199\f
1200/***********************************************************************
1201 Starting and ending an update
1202 ***********************************************************************/
177c0ea7 1203
1a578e9b
AC
1204/* Start an update of frame F. This function is installed as a hook
1205 for update_begin, i.e. it is called when update_begin is called.
1206 This function is called prior to calls to x_update_window_begin for
e0f712ba 1207 each window being updated. */
1a578e9b 1208
e0f712ba 1209static void
1a578e9b
AC
1210x_update_begin (f)
1211 struct frame *f;
1212{
1213 /* Nothing to do. */
1214}
1215
1216
1217/* Start update of window W. Set the global variable updated_window
1218 to the window being updated and set output_cursor to the cursor
1219 position of W. */
1220
e0f712ba 1221static void
1a578e9b
AC
1222x_update_window_begin (w)
1223 struct window *w;
1224{
1225 struct frame *f = XFRAME (WINDOW_FRAME (w));
1226 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
177c0ea7 1227
1a578e9b
AC
1228 updated_window = w;
1229 set_output_cursor (&w->cursor);
1230
1231 BLOCK_INPUT;
1232
1233 if (f == display_info->mouse_face_mouse_frame)
1234 {
1235 /* Don't do highlighting for mouse motion during the update. */
1236 display_info->mouse_face_defer = 1;
1237
1238 /* If F needs to be redrawn, simply forget about any prior mouse
1239 highlighting. */
1240 if (FRAME_GARBAGED_P (f))
1241 display_info->mouse_face_window = Qnil;
1242
1243#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1244 their mouse_face_p flag set, which means that they are always
1245 unequal to rows in a desired matrix which never have that
1246 flag set. So, rows containing mouse-face glyphs are never
1247 scrolled, and we don't have to switch the mouse highlight off
1248 here to prevent it from being scrolled. */
177c0ea7 1249
1a578e9b
AC
1250 /* Can we tell that this update does not affect the window
1251 where the mouse highlight is? If so, no need to turn off.
1252 Likewise, don't do anything if the frame is garbaged;
1253 in that case, the frame's current matrix that we would use
1254 is all wrong, and we will redisplay that line anyway. */
1255 if (!NILP (display_info->mouse_face_window)
1256 && w == XWINDOW (display_info->mouse_face_window))
1257 {
1258 int i;
1259
e0f712ba 1260 for (i = 0; i < w->desired_matrix->nrows; ++i)
1a578e9b
AC
1261 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1262 break;
1263
1264 if (i < w->desired_matrix->nrows)
1265 clear_mouse_face (display_info);
1266 }
1267#endif /* 0 */
1268 }
1269
1270 UNBLOCK_INPUT;
1271}
1272
1273
1274/* Draw a vertical window border to the right of window W if W doesn't
1275 have vertical scroll bars. */
1276
1277static void
1278x_draw_vertical_border (w)
1279 struct window *w;
1280{
1281 struct frame *f = XFRAME (WINDOW_FRAME (w));
177c0ea7 1282
1a578e9b
AC
1283 /* Redraw borders between horizontally adjacent windows. Don't
1284 do it for frames with vertical scroll bars because either the
1285 right scroll bar of a window, or the left scroll bar of its
1286 neighbor will suffice as a border. */
1287 if (!WINDOW_RIGHTMOST_P (w)
1288 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1289 {
1290 int x0, x1, y0, y1;
1291
1292 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
3f332ef3 1293 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1a578e9b 1294 y1 -= 1;
177c0ea7
JB
1295
1296 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1a578e9b
AC
1297 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1298 }
1299}
e0f712ba 1300
177c0ea7 1301
1a578e9b
AC
1302/* End update of window W (which is equal to updated_window).
1303
1304 Draw vertical borders between horizontally adjacent windows, and
1305 display W's cursor if CURSOR_ON_P is non-zero.
1306
1307 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1308 glyphs in mouse-face were overwritten. In that case we have to
1309 make sure that the mouse-highlight is properly redrawn.
1310
1311 W may be a menu bar pseudo-window in case we don't have X toolkit
e0f712ba
AC
1312 support. Such windows don't have a cursor, so don't display it
1313 here. */
1a578e9b 1314
e0f712ba 1315static void
1a578e9b
AC
1316x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1317 struct window *w;
1318 int cursor_on_p, mouse_face_overwritten_p;
1319{
e0f712ba
AC
1320 struct mac_display_info *dpyinfo
1321 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1322
1a578e9b
AC
1323 if (!w->pseudo_window_p)
1324 {
1a578e9b
AC
1325 BLOCK_INPUT;
1326
1a578e9b
AC
1327 if (cursor_on_p)
1328 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1329 output_cursor.vpos,
1330 output_cursor.x, output_cursor.y);
177c0ea7 1331
1a578e9b
AC
1332 x_draw_vertical_border (w);
1333 UNBLOCK_INPUT;
1334 }
e0f712ba
AC
1335
1336 /* If a row with mouse-face was overwritten, arrange for
1337 XTframe_up_to_date to redisplay the mouse highlight. */
1338 if (mouse_face_overwritten_p)
1339 {
1340 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1341 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1342 dpyinfo->mouse_face_window = Qnil;
1343 }
1344
1345#if 0
1346 /* Unhide the caret. This won't actually show the cursor, unless it
1347 was visible before the corresponding call to HideCaret in
1348 x_update_window_begin. */
1349 if (w32_use_visible_system_caret)
1350 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1351#endif
1352
1a578e9b
AC
1353 updated_window = NULL;
1354}
1355
1356
1357/* End update of frame F. This function is installed as a hook in
1358 update_end. */
1359
e0f712ba 1360static void
1a578e9b
AC
1361x_update_end (f)
1362 struct frame *f;
1363{
1364 /* Reset the background color of Mac OS Window to that of the frame after
1365 update so that it is used by Mac Toolbox to clear the update region before
1366 an update event is generated. */
e0f712ba
AC
1367#if TARGET_API_MAC_CARBON
1368 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1369#else
1a578e9b 1370 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
1371#endif
1372
1a578e9b 1373 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
177c0ea7 1374
1a578e9b
AC
1375 /* Mouse highlight may be displayed again. */
1376 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1377
1378 BLOCK_INPUT;
1379 XFlush (FRAME_MAC_DISPLAY (f));
1380 UNBLOCK_INPUT;
1381}
1382
1383
1384/* This function is called from various places in xdisp.c whenever a
1385 complete update has been performed. The global variable
1386 updated_window is not available here. */
1387
e0f712ba 1388static void
1a578e9b
AC
1389XTframe_up_to_date (f)
1390 struct frame *f;
1391{
1392 if (FRAME_X_P (f))
1393 {
1394 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1395
1396 if (dpyinfo->mouse_face_deferred_gc
1397 || f == dpyinfo->mouse_face_mouse_frame)
1398 {
1399 BLOCK_INPUT;
1400 if (dpyinfo->mouse_face_mouse_frame)
1401 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1402 dpyinfo->mouse_face_mouse_x,
1403 dpyinfo->mouse_face_mouse_y);
1404 dpyinfo->mouse_face_deferred_gc = 0;
1405 UNBLOCK_INPUT;
1406 }
1407 }
1408}
1409
1410
1411/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
3f332ef3 1412 arrow bitmaps, or clear the fringes if no bitmaps are required
1a578e9b 1413 before DESIRED_ROW is made current. The window being updated is
e0f712ba 1414 found in updated_window. This function is called from
1a578e9b
AC
1415 update_window_line only if it is known that there are differences
1416 between bitmaps to be drawn between current row and DESIRED_ROW. */
1417
e0f712ba 1418static void
1a578e9b
AC
1419x_after_update_window_line (desired_row)
1420 struct glyph_row *desired_row;
1421{
1422 struct window *w = updated_window;
e0f712ba
AC
1423 struct frame *f;
1424 int width, height;
1425
1a578e9b 1426 xassert (w);
177c0ea7 1427
1a578e9b
AC
1428 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1429 {
1430 BLOCK_INPUT;
3f332ef3 1431 x_draw_row_fringe_bitmaps (w, desired_row);
e0f712ba
AC
1432 UNBLOCK_INPUT;
1433 }
1a578e9b 1434
e0f712ba
AC
1435 /* When a window has disappeared, make sure that no rest of
1436 full-width rows stays visible in the internal border. Could
1437 check here if updated_window is the leftmost/rightmost window,
1438 but I guess it's not worth doing since vertically split windows
1439 are almost never used, internal border is rarely set, and the
1440 overhead is very small. */
1441 if (windows_or_buffers_changed
1442 && desired_row->full_width_p
1443 && (f = XFRAME (w->frame),
1444 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1445 width != 0)
1446 && (height = desired_row->visible_height,
1447 height > 0))
1448 {
1449 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1450 /* Internal border is drawn below the tool bar. */
1451 if (WINDOWP (f->tool_bar_window)
1452 && w == XWINDOW (f->tool_bar_window))
1453 y -= width;
1a578e9b 1454
e0f712ba
AC
1455 BLOCK_INPUT;
1456
1457 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1458 0, y, width, height, 0);
1459 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1460 f->output_data.mac->pixel_width - width, y,
1461 width, height, 0);
177c0ea7 1462
1a578e9b
AC
1463 UNBLOCK_INPUT;
1464 }
1465}
1466
1467
3f332ef3 1468/* Draw the bitmap WHICH in one of the left or right fringes of
1a578e9b
AC
1469 window W. ROW is the glyph row for which to display the bitmap; it
1470 determines the vertical position at which the bitmap has to be
1471 drawn. */
1472
1473static void
d33c49e8 1474x_draw_fringe_bitmap (w, row, which, left_p)
1a578e9b
AC
1475 struct window *w;
1476 struct glyph_row *row;
3f332ef3 1477 enum fringe_bitmap_type which;
d33c49e8 1478 int left_p;
1a578e9b
AC
1479{
1480 struct frame *f = XFRAME (WINDOW_FRAME (w));
1481 Display *display = FRAME_MAC_DISPLAY (f);
1482 WindowPtr window = FRAME_MAC_WINDOW (f);
1483 int x, y, wd, h, dy;
d33c49e8 1484 int b1, b2;
1a578e9b
AC
1485 unsigned char *bits;
1486 BitMap bitmap;
1487 XGCValues gcv;
e0f712ba 1488 GC gc = f->output_data.mac->normal_gc;
1a578e9b
AC
1489 struct face *face;
1490
1491 /* Must clip because of partially visible lines. */
e0f712ba 1492 x_clip_to_row (w, row, gc, 1);
1a578e9b 1493
d33c49e8
KS
1494 /* Convert row to frame coordinates. */
1495 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1496
1a578e9b
AC
1497 switch (which)
1498 {
d33c49e8
KS
1499 case NO_FRINGE_BITMAP:
1500 wd = 0;
1501 h = 0;
1502 break;
1503
1a578e9b
AC
1504 case LEFT_TRUNCATION_BITMAP:
1505 wd = left_width;
1506 h = left_height;
1507 bits = left_bits;
1a578e9b 1508 break;
177c0ea7 1509
1a578e9b 1510 case OVERLAY_ARROW_BITMAP:
d33c49e8
KS
1511 wd = ov_width;
1512 h = ov_height;
1a578e9b 1513 bits = ov_bits;
1a578e9b 1514 break;
177c0ea7 1515
1a578e9b
AC
1516 case RIGHT_TRUNCATION_BITMAP:
1517 wd = right_width;
1518 h = right_height;
1519 bits = right_bits;
1a578e9b
AC
1520 break;
1521
1522 case CONTINUED_LINE_BITMAP:
d33c49e8
KS
1523 wd = continued_width;
1524 h = continued_height;
1a578e9b 1525 bits = continued_bits;
1a578e9b 1526 break;
177c0ea7 1527
1a578e9b
AC
1528 case CONTINUATION_LINE_BITMAP:
1529 wd = continuation_width;
1530 h = continuation_height;
1531 bits = continuation_bits;
1a578e9b
AC
1532 break;
1533
1534 case ZV_LINE_BITMAP:
1535 wd = zv_width;
d33c49e8
KS
1536 h = zv_height - (y % zv_period);
1537 bits = zv_bits + (y % zv_period);
1a578e9b
AC
1538 break;
1539
1540 default:
1541 abort ();
1542 }
1543
d33c49e8
KS
1544 /* Clip bitmap if too high. */
1545 if (h > row->height)
1546 h = row->height;
1547
1548 /* Set dy to the offset in the row to start drawing the bitmap. */
1a578e9b
AC
1549 dy = (row->height - h) / 2;
1550
e0f712ba 1551 /* Draw the bitmap. */
3f332ef3 1552 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
d33c49e8
KS
1553 PREPARE_FACE_FOR_DISPLAY (f, face);
1554
1555 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1556 the fringe. */
1557 b1 = -1;
1558 if (left_p)
1559 {
1560 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1561 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1562 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1563 - wd
1564 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1565 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1566 {
1567 /* If W has a vertical border to its left, don't draw over it. */
1568 int border = ((XFASTINT (w->left) > 0
1569 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1570 ? 1 : 0);
1571 b1 = (window_box_left (w, -1)
1572 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1573 + border);
1574 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1575 }
1576 }
1577 else
1578 {
1579 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1580 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1581 x = (window_box_right (w, -1)
1582 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1583 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1584 the fringe. */
1585 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1586 {
1587 b1 = window_box_right (w, -1);
1588 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1589 }
1590 }
1591
1592 if (b1 >= 0)
1593 {
1594 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1595 XGCValues gcv;
1596 gcv.foreground = face->background;
1597
1598#if 0 /* MAC_TODO: stipple */
1599 /* In case the same realized face is used for fringes and
1600 for something displayed in the text (e.g. face `region' on
1601 mono-displays, the fill style may have been changed to
1602 FillSolid in x_draw_glyph_string_background. */
1603 if (face->stipple)
1604 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1605 else
1606 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1607#endif
1608
1609 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1610 &gcv,
1611 b1,
1612 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1613 row->y)),
1614 b2,
1615 row->visible_height);
1616
1617#if 0 /* MAC_TODO: stipple */
1618 if (!face->stipple)
1619 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1620#endif
1621 }
1622
1623 if (which == NO_FRINGE_BITMAP)
e0f712ba
AC
1624 {
1625 mac_reset_clipping (display, window);
1626 return;
1627 }
1a578e9b
AC
1628
1629 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1630 gcv.foreground = face->foreground;
1631 gcv.background = face->background;
1632
1633 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1634
1635 mac_free_bitmap (&bitmap);
1636 mac_reset_clipping (display, window);
1637}
1638
1639
3f332ef3 1640/* Draw fringe bitmaps for glyph row ROW on window W. Call this
1a578e9b
AC
1641 function with input blocked. */
1642
1643static void
3f332ef3 1644x_draw_row_fringe_bitmaps (w, row)
1a578e9b
AC
1645 struct window *w;
1646 struct glyph_row *row;
1647{
1648 struct frame *f = XFRAME (w->frame);
3f332ef3 1649 enum fringe_bitmap_type bitmap;
1a578e9b
AC
1650
1651 xassert (interrupt_input_blocked);
1652
1653 /* If row is completely invisible, because of vscrolling, we
1654 don't have to draw anything. */
1655 if (row->visible_height <= 0)
1656 return;
1657
d33c49e8
KS
1658 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1659 {
1660 /* Decide which bitmap to draw in the left fringe. */
1661 if (row->overlay_arrow_p)
1662 bitmap = OVERLAY_ARROW_BITMAP;
1663 else if (row->truncated_on_left_p)
1664 bitmap = LEFT_TRUNCATION_BITMAP;
1665 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1666 bitmap = CONTINUATION_LINE_BITMAP;
1667 else if (row->indicate_empty_line_p)
1668 bitmap = ZV_LINE_BITMAP;
1a578e9b 1669 else
d33c49e8 1670 bitmap = NO_FRINGE_BITMAP;
1a578e9b 1671
d33c49e8
KS
1672 x_draw_fringe_bitmap (w, row, bitmap, 1);
1673 }
1a578e9b 1674
d33c49e8 1675 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1a578e9b 1676 {
d33c49e8
KS
1677 /* Decide which bitmap to draw in the right fringe. */
1678 if (row->truncated_on_right_p)
1679 bitmap = RIGHT_TRUNCATION_BITMAP;
1680 else if (row->continued_p)
1681 bitmap = CONTINUED_LINE_BITMAP;
1682 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1683 bitmap = ZV_LINE_BITMAP;
1a578e9b 1684 else
d33c49e8 1685 bitmap = NO_FRINGE_BITMAP;
1a578e9b 1686
d33c49e8 1687 x_draw_fringe_bitmap (w, row, bitmap, 0);
1a578e9b 1688 }
1a578e9b
AC
1689}
1690
1691\f
1a578e9b 1692/* This is called when starting Emacs and when restarting after
e0f712ba 1693 suspend. When starting Emacs, no window is mapped. And nothing
1a578e9b
AC
1694 must be done to Emacs's own window if it is suspended (though that
1695 rarely happens). */
1696
e0f712ba 1697static void
1a578e9b
AC
1698XTset_terminal_modes ()
1699{
1700}
1701
1702/* This is called when exiting or suspending Emacs. Exiting will make
e0f712ba 1703 the windows go away, and suspending requires no action. */
1a578e9b 1704
e0f712ba 1705static void
1a578e9b
AC
1706XTreset_terminal_modes ()
1707{
1708}
1709
1710
1711\f
1712/***********************************************************************
1713 Output Cursor
1714 ***********************************************************************/
1715
1716/* Set the global variable output_cursor to CURSOR. All cursor
1717 positions are relative to updated_window. */
1718
1719static void
1720set_output_cursor (cursor)
1721 struct cursor_pos *cursor;
1722{
1723 output_cursor.hpos = cursor->hpos;
1724 output_cursor.vpos = cursor->vpos;
1725 output_cursor.x = cursor->x;
1726 output_cursor.y = cursor->y;
1727}
1728
1729
1730/* Set a nominal cursor position.
1731
1732 HPOS and VPOS are column/row positions in a window glyph matrix. X
1733 and Y are window text area relative pixel positions.
177c0ea7 1734
1a578e9b
AC
1735 If this is done during an update, updated_window will contain the
1736 window that is being updated and the position is the future output
1737 cursor position for that window. If updated_window is null, use
1738 selected_window and display the cursor at the given position. */
1739
e0f712ba 1740static void
1a578e9b
AC
1741XTcursor_to (vpos, hpos, y, x)
1742 int vpos, hpos, y, x;
1743{
1744 struct window *w;
1745
1746 /* If updated_window is not set, work on selected_window. */
1747 if (updated_window)
1748 w = updated_window;
1749 else
1750 w = XWINDOW (selected_window);
1751
1752 /* Set the output cursor. */
1753 output_cursor.hpos = hpos;
1754 output_cursor.vpos = vpos;
1755 output_cursor.x = x;
1756 output_cursor.y = y;
1757
1758 /* If not called as part of an update, really display the cursor.
1759 This will also set the cursor position of W. */
1760 if (updated_window == NULL)
1761 {
1762 BLOCK_INPUT;
1763 x_display_cursor (w, 1, hpos, vpos, x, y);
1764 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1765 UNBLOCK_INPUT;
1766 }
1767}
1768
1769
1770\f
1771/***********************************************************************
1772 Display Iterator
1773 ***********************************************************************/
1774
1775/* Function prototypes of this page. */
1776
1777static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1778 struct glyph *,
1779 XChar2b *,
1780 int *));
1781static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1782 int, XChar2b *, int));
1783static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1784static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1785static void x_append_glyph P_ ((struct it *));
1786static void x_append_composite_glyph P_ ((struct it *));
1787static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1788 int, int, double));
1789static void x_produce_glyphs P_ ((struct it *));
1790static void x_produce_image_glyph P_ ((struct it *it));
1791
1792
1793/* Return a pointer to per-char metric information in FONT of a
1794 character pointed by B which is a pointer to an XChar2b. */
1795
1796#define PER_CHAR_METRIC(font, b) \
1797 ((font)->per_char \
1798 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1799 + (((font)->min_byte1 || (font)->max_byte1) \
1800 ? (((b)->byte1 - (font)->min_byte1) \
1801 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1802 : 0)) \
1803 : &((font)->max_bounds))
1804
1805
1806/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1807 is not contained in the font. */
1808
1809static INLINE XCharStruct *
1810x_per_char_metric (font, char2b)
1811 XFontStruct *font;
1812 XChar2b *char2b;
1813{
1814 /* The result metric information. */
1815 XCharStruct *pcm = NULL;
1816
1817 xassert (font && char2b);
1818
1819 if (font->per_char != NULL)
1820 {
1821 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1822 {
1823 /* min_char_or_byte2 specifies the linear character index
1824 corresponding to the first element of the per_char array,
1825 max_char_or_byte2 is the index of the last character. A
1826 character with non-zero CHAR2B->byte1 is not in the font.
1827 A character with byte2 less than min_char_or_byte2 or
1828 greater max_char_or_byte2 is not in the font. */
1829 if (char2b->byte1 == 0
1830 && char2b->byte2 >= font->min_char_or_byte2
1831 && char2b->byte2 <= font->max_char_or_byte2)
1832 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1833 }
1834 else
1835 {
1836 /* If either min_byte1 or max_byte1 are nonzero, both
1837 min_char_or_byte2 and max_char_or_byte2 are less than
1838 256, and the 2-byte character index values corresponding
1839 to the per_char array element N (counting from 0) are:
1840
1841 byte1 = N/D + min_byte1
1842 byte2 = N\D + min_char_or_byte2
1843
1844 where:
1845
1846 D = max_char_or_byte2 - min_char_or_byte2 + 1
1847 / = integer division
1848 \ = integer modulus */
1849 if (char2b->byte1 >= font->min_byte1
1850 && char2b->byte1 <= font->max_byte1
1851 && char2b->byte2 >= font->min_char_or_byte2
1852 && char2b->byte2 <= font->max_char_or_byte2)
1853 {
1854 pcm = (font->per_char
1855 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1856 * (char2b->byte1 - font->min_byte1))
1857 + (char2b->byte2 - font->min_char_or_byte2));
1858 }
1859 }
1860 }
1861 else
1862 {
1863 /* If the per_char pointer is null, all glyphs between the first
1864 and last character indexes inclusive have the same
1865 information, as given by both min_bounds and max_bounds. */
1866 if (char2b->byte2 >= font->min_char_or_byte2
1867 && char2b->byte2 <= font->max_char_or_byte2)
1868 pcm = &font->max_bounds;
1869 }
1870
1871 return ((pcm == NULL
1872 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1873 ? NULL : pcm);
1874}
1875
1876
1877/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1878 the two-byte form of C. Encoding is returned in *CHAR2B. */
1879
1880static INLINE void
1881x_encode_char (c, char2b, font_info)
1882 int c;
1883 XChar2b *char2b;
1884 struct font_info *font_info;
1885{
1886 int charset = CHAR_CHARSET (c);
1887 XFontStruct *font = font_info->font;
1888
1889 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1890 This may be either a program in a special encoder language or a
1891 fixed encoding. */
1892 if (font_info->font_encoder)
1893 {
1894 /* It's a program. */
1895 struct ccl_program *ccl = font_info->font_encoder;
1896
1897 if (CHARSET_DIMENSION (charset) == 1)
1898 {
1899 ccl->reg[0] = charset;
1900 ccl->reg[1] = char2b->byte2;
1901 }
1902 else
1903 {
1904 ccl->reg[0] = charset;
1905 ccl->reg[1] = char2b->byte1;
1906 ccl->reg[2] = char2b->byte2;
1907 }
177c0ea7 1908
1a578e9b 1909 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
177c0ea7 1910
1a578e9b
AC
1911 /* We assume that MSBs are appropriately set/reset by CCL
1912 program. */
1913 if (font->max_byte1 == 0) /* 1-byte font */
1914 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1915 else
1916 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1917 }
1918 else if (font_info->encoding[charset])
1919 {
1920 /* Fixed encoding scheme. See fontset.h for the meaning of the
1921 encoding numbers. */
1922 int enc = font_info->encoding[charset];
177c0ea7 1923
1a578e9b
AC
1924 if ((enc == 1 || enc == 2)
1925 && CHARSET_DIMENSION (charset) == 2)
1926 char2b->byte1 |= 0x80;
177c0ea7 1927
1a578e9b
AC
1928 if (enc == 1 || enc == 3)
1929 char2b->byte2 |= 0x80;
1930
1931 if (enc == 4)
1932 {
1933 int sjis1, sjis2;
1934
1935 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1936 char2b->byte1 = sjis1;
1937 char2b->byte2 = sjis2;
1938 }
1939 }
1940}
1941
1942
1943/* Get face and two-byte form of character C in face FACE_ID on frame
1944 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1945 means we want to display multibyte text. Value is a pointer to a
1946 realized face that is ready for display. */
1947
1948static INLINE struct face *
1949x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1950 struct frame *f;
1951 int c, face_id;
1952 XChar2b *char2b;
1953 int multibyte_p;
1954{
1955 struct face *face = FACE_FROM_ID (f, face_id);
1956
1957 if (!multibyte_p)
1958 {
1959 /* Unibyte case. We don't have to encode, but we have to make
1960 sure to use a face suitable for unibyte. */
1961 char2b->byte1 = 0;
1962 char2b->byte2 = c;
1963 face_id = FACE_FOR_CHAR (f, face, c);
1964 face = FACE_FROM_ID (f, face_id);
1965 }
1966 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1967 {
1968 /* Case of ASCII in a face known to fit ASCII. */
1969 char2b->byte1 = 0;
1970 char2b->byte2 = c;
1971 }
1972 else
1973 {
1974 int c1, c2, charset;
177c0ea7 1975
1a578e9b
AC
1976 /* Split characters into bytes. If c2 is -1 afterwards, C is
1977 really a one-byte character so that byte1 is zero. */
1978 SPLIT_CHAR (c, charset, c1, c2);
1979 if (c2 > 0)
1980 char2b->byte1 = c1, char2b->byte2 = c2;
1981 else
1982 char2b->byte1 = 0, char2b->byte2 = c1;
1983
1984 /* Maybe encode the character in *CHAR2B. */
1985 if (face->font != NULL)
1986 {
1987 struct font_info *font_info
1988 = FONT_INFO_FROM_ID (f, face->font_info_id);
1989 if (font_info)
1990 x_encode_char (c, char2b, font_info);
1991 }
1992 }
1993
1994 /* Make sure X resources of the face are allocated. */
1995 xassert (face != NULL);
1996 PREPARE_FACE_FOR_DISPLAY (f, face);
177c0ea7 1997
1a578e9b
AC
1998 return face;
1999}
2000
2001
2002/* Get face and two-byte form of character glyph GLYPH on frame F.
2003 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
2004 a pointer to a realized face that is ready for display. */
2005
2006static INLINE struct face *
2007x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
2008 struct frame *f;
2009 struct glyph *glyph;
2010 XChar2b *char2b;
2011 int *two_byte_p;
2012{
2013 struct face *face;
2014
2015 xassert (glyph->type == CHAR_GLYPH);
2016 face = FACE_FROM_ID (f, glyph->face_id);
2017
2018 if (two_byte_p)
2019 *two_byte_p = 0;
2020
2021 if (!glyph->multibyte_p)
2022 {
2023 /* Unibyte case. We don't have to encode, but we have to make
2024 sure to use a face suitable for unibyte. */
2025 char2b->byte1 = 0;
2026 char2b->byte2 = glyph->u.ch;
2027 }
2028 else if (glyph->u.ch < 128
2029 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2030 {
2031 /* Case of ASCII in a face known to fit ASCII. */
2032 char2b->byte1 = 0;
2033 char2b->byte2 = glyph->u.ch;
2034 }
2035 else
2036 {
2037 int c1, c2, charset;
177c0ea7 2038
1a578e9b
AC
2039 /* Split characters into bytes. If c2 is -1 afterwards, C is
2040 really a one-byte character so that byte1 is zero. */
2041 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2042 if (c2 > 0)
2043 char2b->byte1 = c1, char2b->byte2 = c2;
2044 else
2045 char2b->byte1 = 0, char2b->byte2 = c1;
2046
2047 /* Maybe encode the character in *CHAR2B. */
2048 if (charset != CHARSET_ASCII)
2049 {
2050 struct font_info *font_info
2051 = FONT_INFO_FROM_ID (f, face->font_info_id);
2052 if (font_info)
2053 {
2054 x_encode_char (glyph->u.ch, char2b, font_info);
2055 if (two_byte_p)
2056 *two_byte_p
2057 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2058 }
2059 }
2060 }
2061
2062 /* Make sure X resources of the face are allocated. */
2063 xassert (face != NULL);
2064 PREPARE_FACE_FOR_DISPLAY (f, face);
2065 return face;
2066}
2067
2068
177c0ea7 2069/* Store one glyph for IT->char_to_display in IT->glyph_row.
1a578e9b
AC
2070 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2071
2072static INLINE void
2073x_append_glyph (it)
2074 struct it *it;
2075{
2076 struct glyph *glyph;
2077 enum glyph_row_area area = it->area;
177c0ea7 2078
1a578e9b
AC
2079 xassert (it->glyph_row);
2080 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
177c0ea7 2081
1a578e9b
AC
2082 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2083 if (glyph < it->glyph_row->glyphs[area + 1])
2084 {
2085 glyph->charpos = CHARPOS (it->position);
2086 glyph->object = it->object;
2087 glyph->pixel_width = it->pixel_width;
2088 glyph->voffset = it->voffset;
2089 glyph->type = CHAR_GLYPH;
2090 glyph->multibyte_p = it->multibyte_p;
2091 glyph->left_box_line_p = it->start_of_box_run_p;
2092 glyph->right_box_line_p = it->end_of_box_run_p;
2093 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2094 || it->phys_descent > it->descent);
2095 glyph->padding_p = 0;
2096 glyph->glyph_not_available_p = it->glyph_not_available_p;
2097 glyph->face_id = it->face_id;
2098 glyph->u.ch = it->char_to_display;
2099 ++it->glyph_row->used[area];
2100 }
2101}
2102
177c0ea7 2103/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1a578e9b
AC
2104 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2105
2106static INLINE void
2107x_append_composite_glyph (it)
2108 struct it *it;
2109{
2110 struct glyph *glyph;
2111 enum glyph_row_area area = it->area;
177c0ea7 2112
1a578e9b 2113 xassert (it->glyph_row);
177c0ea7 2114
1a578e9b
AC
2115 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2116 if (glyph < it->glyph_row->glyphs[area + 1])
2117 {
2118 glyph->charpos = CHARPOS (it->position);
2119 glyph->object = it->object;
2120 glyph->pixel_width = it->pixel_width;
2121 glyph->voffset = it->voffset;
2122 glyph->type = COMPOSITE_GLYPH;
2123 glyph->multibyte_p = it->multibyte_p;
2124 glyph->left_box_line_p = it->start_of_box_run_p;
2125 glyph->right_box_line_p = it->end_of_box_run_p;
2126 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2127 || it->phys_descent > it->descent);
2128 glyph->padding_p = 0;
2129 glyph->glyph_not_available_p = 0;
2130 glyph->face_id = it->face_id;
2131 glyph->u.cmp_id = it->cmp_id;
2132 ++it->glyph_row->used[area];
2133 }
2134}
2135
2136
2137/* Change IT->ascent and IT->height according to the setting of
2138 IT->voffset. */
2139
2140static INLINE void
2141take_vertical_position_into_account (it)
2142 struct it *it;
2143{
2144 if (it->voffset)
2145 {
2146 if (it->voffset < 0)
2147 /* Increase the ascent so that we can display the text higher
2148 in the line. */
2149 it->ascent += abs (it->voffset);
2150 else
2151 /* Increase the descent so that we can display the text lower
2152 in the line. */
2153 it->descent += it->voffset;
2154 }
2155}
2156
2157
2158/* Produce glyphs/get display metrics for the image IT is loaded with.
2159 See the description of struct display_iterator in dispextern.h for
2160 an overview of struct display_iterator. */
2161
2162static void
2163x_produce_image_glyph (it)
2164 struct it *it;
2165{
2166 struct image *img;
2167 struct face *face;
2168
2169 xassert (it->what == IT_IMAGE);
2170
2171 face = FACE_FROM_ID (it->f, it->face_id);
2172 img = IMAGE_FROM_ID (it->f, it->image_id);
2173 xassert (img);
2174
2175 /* Make sure X resources of the face and image are loaded. */
2176 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2177 prepare_image_for_display (it->f, img);
2178
2179 it->ascent = it->phys_ascent = image_ascent (img, face);
83a96b4d
AC
2180 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2181 it->pixel_width = img->width + 2 * img->hmargin;
1a578e9b
AC
2182
2183 it->nglyphs = 1;
177c0ea7 2184
1a578e9b
AC
2185 if (face->box != FACE_NO_BOX)
2186 {
e0f712ba
AC
2187 if (face->box_line_width > 0)
2188 {
2189 it->ascent += face->box_line_width;
2190 it->descent += face->box_line_width;
2191 }
177c0ea7 2192
1a578e9b 2193 if (it->start_of_box_run_p)
e0f712ba 2194 it->pixel_width += abs (face->box_line_width);
1a578e9b 2195 if (it->end_of_box_run_p)
e0f712ba 2196 it->pixel_width += abs (face->box_line_width);
1a578e9b
AC
2197 }
2198
2199 take_vertical_position_into_account (it);
177c0ea7 2200
1a578e9b
AC
2201 if (it->glyph_row)
2202 {
2203 struct glyph *glyph;
2204 enum glyph_row_area area = it->area;
177c0ea7 2205
1a578e9b
AC
2206 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2207 if (glyph < it->glyph_row->glyphs[area + 1])
2208 {
2209 glyph->charpos = CHARPOS (it->position);
2210 glyph->object = it->object;
2211 glyph->pixel_width = it->pixel_width;
2212 glyph->voffset = it->voffset;
2213 glyph->type = IMAGE_GLYPH;
2214 glyph->multibyte_p = it->multibyte_p;
2215 glyph->left_box_line_p = it->start_of_box_run_p;
2216 glyph->right_box_line_p = it->end_of_box_run_p;
2217 glyph->overlaps_vertically_p = 0;
2218 glyph->padding_p = 0;
2219 glyph->glyph_not_available_p = 0;
2220 glyph->face_id = it->face_id;
2221 glyph->u.img_id = img->id;
2222 ++it->glyph_row->used[area];
2223 }
2224 }
2225}
2226
2227
2228/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
177c0ea7
JB
2229 of the glyph, WIDTH and HEIGHT are the width and height of the
2230 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1a578e9b 2231 ascent of the glyph (0 <= ASCENT <= 1). */
177c0ea7 2232
1a578e9b
AC
2233static void
2234x_append_stretch_glyph (it, object, width, height, ascent)
2235 struct it *it;
2236 Lisp_Object object;
2237 int width, height;
2238 double ascent;
2239{
2240 struct glyph *glyph;
2241 enum glyph_row_area area = it->area;
2242
2243 xassert (ascent >= 0 && ascent <= 1);
177c0ea7 2244
1a578e9b
AC
2245 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2246 if (glyph < it->glyph_row->glyphs[area + 1])
2247 {
2248 glyph->charpos = CHARPOS (it->position);
2249 glyph->object = object;
2250 glyph->pixel_width = width;
2251 glyph->voffset = it->voffset;
2252 glyph->type = STRETCH_GLYPH;
2253 glyph->multibyte_p = it->multibyte_p;
2254 glyph->left_box_line_p = it->start_of_box_run_p;
2255 glyph->right_box_line_p = it->end_of_box_run_p;
2256 glyph->overlaps_vertically_p = 0;
2257 glyph->padding_p = 0;
2258 glyph->glyph_not_available_p = 0;
2259 glyph->face_id = it->face_id;
2260 glyph->u.stretch.ascent = height * ascent;
2261 glyph->u.stretch.height = height;
2262 ++it->glyph_row->used[area];
2263 }
2264}
2265
2266
2267/* Produce a stretch glyph for iterator IT. IT->object is the value
2268 of the glyph property displayed. The value must be a list
2269 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2270 being recognized:
2271
2272 1. `:width WIDTH' specifies that the space should be WIDTH *
177c0ea7 2273 canonical char width wide. WIDTH may be an integer or floating
1a578e9b
AC
2274 point number.
2275
2276 2. `:relative-width FACTOR' specifies that the width of the stretch
2277 should be computed from the width of the first character having the
2278 `glyph' property, and should be FACTOR times that width.
2279
2280 3. `:align-to HPOS' specifies that the space should be wide enough
2281 to reach HPOS, a value in canonical character units.
2282
177c0ea7 2283 Exactly one of the above pairs must be present.
1a578e9b
AC
2284
2285 4. `:height HEIGHT' specifies that the height of the stretch produced
2286 should be HEIGHT, measured in canonical character units.
2287
e0f712ba
AC
2288 5. `:relative-height FACTOR' specifies that the height of the
2289 stretch should be FACTOR times the height of the characters having
2290 the glyph property.
1a578e9b
AC
2291
2292 Either none or exactly one of 4 or 5 must be present.
2293
2294 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2295 of the stretch should be used for the ascent of the stretch.
2296 ASCENT must be in the range 0 <= ASCENT <= 100. */
2297
2298#define NUMVAL(X) \
2299 ((INTEGERP (X) || FLOATP (X)) \
2300 ? XFLOATINT (X) \
2301 : - 1)
2302
2303
2304static void
2305x_produce_stretch_glyph (it)
2306 struct it *it;
2307{
2308 /* (space :width WIDTH :height HEIGHT. */
2309#if GLYPH_DEBUG
2310 extern Lisp_Object Qspace;
2311#endif
2312 extern Lisp_Object QCwidth, QCheight, QCascent;
2313 extern Lisp_Object QCrelative_width, QCrelative_height;
2314 extern Lisp_Object QCalign_to;
2315 Lisp_Object prop, plist;
2316 double width = 0, height = 0, ascent = 0;
2317 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2318 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2319
2320 PREPARE_FACE_FOR_DISPLAY (it->f, face);
177c0ea7 2321
1a578e9b
AC
2322 /* List should start with `space'. */
2323 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2324 plist = XCDR (it->object);
2325
2326 /* Compute the width of the stretch. */
2327 if (prop = Fplist_get (plist, QCwidth),
2328 NUMVAL (prop) > 0)
2329 /* Absolute width `:width WIDTH' specified and valid. */
2330 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2331 else if (prop = Fplist_get (plist, QCrelative_width),
2332 NUMVAL (prop) > 0)
2333 {
2334 /* Relative width `:relative-width FACTOR' specified and valid.
2335 Compute the width of the characters having the `glyph'
2336 property. */
2337 struct it it2;
2338 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
177c0ea7 2339
1a578e9b
AC
2340 it2 = *it;
2341 if (it->multibyte_p)
2342 {
2343 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2344 - IT_BYTEPOS (*it));
2345 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2346 }
2347 else
2348 it2.c = *p, it2.len = 1;
2349
2350 it2.glyph_row = NULL;
2351 it2.what = IT_CHARACTER;
2352 x_produce_glyphs (&it2);
2353 width = NUMVAL (prop) * it2.pixel_width;
2354 }
2355 else if (prop = Fplist_get (plist, QCalign_to),
2356 NUMVAL (prop) > 0)
2357 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2358 else
2359 /* Nothing specified -> width defaults to canonical char width. */
2360 width = CANON_X_UNIT (it->f);
177c0ea7 2361
1a578e9b
AC
2362 /* Compute height. */
2363 if (prop = Fplist_get (plist, QCheight),
2364 NUMVAL (prop) > 0)
2365 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2366 else if (prop = Fplist_get (plist, QCrelative_height),
2367 NUMVAL (prop) > 0)
2368 height = FONT_HEIGHT (font) * NUMVAL (prop);
2369 else
2370 height = FONT_HEIGHT (font);
2371
177c0ea7 2372 /* Compute percentage of height used for ascent. If
1a578e9b
AC
2373 `:ascent ASCENT' is present and valid, use that. Otherwise,
2374 derive the ascent from the font in use. */
2375 if (prop = Fplist_get (plist, QCascent),
2376 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2377 ascent = NUMVAL (prop) / 100.0;
2378 else
e0f712ba 2379 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
1a578e9b
AC
2380
2381 if (width <= 0)
2382 width = 1;
2383 if (height <= 0)
2384 height = 1;
2385
2386 if (it->glyph_row)
2387 {
2388 Lisp_Object object = it->stack[it->sp - 1].string;
2389 if (!STRINGP (object))
2390 object = it->w->buffer;
2391 x_append_stretch_glyph (it, object, width, height, ascent);
2392 }
2393
2394 it->pixel_width = width;
2395 it->ascent = it->phys_ascent = height * ascent;
2396 it->descent = it->phys_descent = height - it->ascent;
2397 it->nglyphs = 1;
2398
2399 if (face->box != FACE_NO_BOX)
2400 {
e0f712ba
AC
2401 if (face->box_line_width > 0)
2402 {
2403 it->ascent += face->box_line_width;
2404 it->descent += face->box_line_width;
2405 }
177c0ea7 2406
1a578e9b 2407 if (it->start_of_box_run_p)
e0f712ba 2408 it->pixel_width += abs (face->box_line_width);
1a578e9b 2409 if (it->end_of_box_run_p)
e0f712ba 2410 it->pixel_width += abs (face->box_line_width);
1a578e9b 2411 }
177c0ea7 2412
1a578e9b
AC
2413 take_vertical_position_into_account (it);
2414}
2415
2416/* Return proper value to be used as baseline offset of font that has
2417 ASCENT and DESCENT to draw characters by the font at the vertical
2418 center of the line of frame F.
2419
2420 Here, out task is to find the value of BOFF in the following figure;
2421
2422 -------------------------+-----------+-
2423 -+-+---------+-+ | |
2424 | | | | | |
2425 | | | | F_ASCENT F_HEIGHT
2426 | | | ASCENT | |
2427 HEIGHT | | | | |
2428 | | |-|-+------+-----------|------- baseline
2429 | | | | BOFF | |
2430 | |---------|-+-+ | |
2431 | | | DESCENT | |
2432 -+-+---------+-+ F_DESCENT |
2433 -------------------------+-----------+-
2434
2435 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2436 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2437 DESCENT = FONT->descent
2438 HEIGHT = FONT_HEIGHT (FONT)
2439 F_DESCENT = (F->output_data.x->font->descent
2440 - F->output_data.x->baseline_offset)
2441 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2442*/
2443
e0f712ba
AC
2444#define VCENTER_BASELINE_OFFSET(FONT, F) \
2445 (FONT_DESCENT (FONT) \
2446 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2447 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2448 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
1a578e9b
AC
2449
2450/* Produce glyphs/get display metrics for the display element IT is
2451 loaded with. See the description of struct display_iterator in
2452 dispextern.h for an overview of struct display_iterator. */
2453
e0f712ba 2454static void
1a578e9b
AC
2455x_produce_glyphs (it)
2456 struct it *it;
2457{
2458 it->glyph_not_available_p = 0;
2459
2460 if (it->what == IT_CHARACTER)
2461 {
2462 XChar2b char2b;
2463 XFontStruct *font;
2464 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2465 XCharStruct *pcm;
2466 int font_not_found_p;
2467 struct font_info *font_info;
e0f712ba
AC
2468 int boff; /* baseline offset */
2469 /* We may change it->multibyte_p upon unibyte<->multibyte
2470 conversion. So, save the current value now and restore it
2471 later.
2472
2473 Note: It seems that we don't have to record multibyte_p in
2474 struct glyph because the character code itself tells if or
2475 not the character is multibyte. Thus, in the future, we must
2476 consider eliminating the field `multibyte_p' in the struct
2477 glyph.
2478 */
2479 int saved_multibyte_p = it->multibyte_p;
1a578e9b
AC
2480
2481 /* Maybe translate single-byte characters to multibyte, or the
e0f712ba 2482 other way. */
1a578e9b
AC
2483 it->char_to_display = it->c;
2484 if (!ASCII_BYTE_P (it->c))
e0f712ba
AC
2485 {
2486 if (unibyte_display_via_language_environment
2487 && SINGLE_BYTE_CHAR_P (it->c)
2488 && (it->c >= 0240
2489 || !NILP (Vnonascii_translation_table)))
2490 {
2491 it->char_to_display = unibyte_char_to_multibyte (it->c);
2492 it->multibyte_p = 1;
1a578e9b
AC
2493 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2494 face = FACE_FROM_ID (it->f, it->face_id);
2495 }
2496 else if (!SINGLE_BYTE_CHAR_P (it->c)
2497 && !it->multibyte_p)
2498 {
e0f712ba 2499 it->multibyte_p = 1;
1a578e9b
AC
2500 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2501 face = FACE_FROM_ID (it->f, it->face_id);
2502 }
e0f712ba 2503 }
177c0ea7 2504
1a578e9b
AC
2505 /* Get font to use. Encode IT->char_to_display. */
2506 x_get_char_face_and_encoding (it->f, it->char_to_display,
e0f712ba
AC
2507 it->face_id, &char2b,
2508 it->multibyte_p);
1a578e9b
AC
2509 font = face->font;
2510
2511 /* When no suitable font found, use the default font. */
2512 font_not_found_p = font == NULL;
2513 if (font_not_found_p)
2514 {
2515 font = FRAME_FONT (it->f);
2516 boff = it->f->output_data.mac->baseline_offset;
2517 font_info = NULL;
2518 }
2519 else
2520 {
2521 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2522 boff = font_info->baseline_offset;
2523 if (font_info->vertical_centering)
2524 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2525 }
2526
2527 if (it->char_to_display >= ' '
2528 && (!it->multibyte_p || it->char_to_display < 128))
2529 {
2530 /* Either unibyte or ASCII. */
2531 int stretched_p;
2532
2533 it->nglyphs = 1;
2534
e0f712ba
AC
2535 pcm = x_per_char_metric (font, &char2b);
2536 it->ascent = FONT_BASE (font) + boff;
2537 it->descent = FONT_DESCENT (font) - boff;
1a578e9b 2538
e0f712ba
AC
2539 if (pcm)
2540 {
2541 it->phys_ascent = pcm->ascent + boff;
2542 it->phys_descent = pcm->descent - boff;
2543 it->pixel_width = pcm->width;
2544 }
2545 else
2546 {
2547 it->glyph_not_available_p = 1;
2548 it->phys_ascent = FONT_BASE (font) + boff;
2549 it->phys_descent = FONT_DESCENT (font) - boff;
2550 it->pixel_width = FONT_WIDTH (font);
2551 }
177c0ea7 2552
1a578e9b
AC
2553 /* If this is a space inside a region of text with
2554 `space-width' property, change its width. */
2555 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2556 if (stretched_p)
2557 it->pixel_width *= XFLOATINT (it->space_width);
2558
2559 /* If face has a box, add the box thickness to the character
2560 height. If character has a box line to the left and/or
2561 right, add the box line width to the character's width. */
2562 if (face->box != FACE_NO_BOX)
2563 {
2564 int thick = face->box_line_width;
177c0ea7 2565
e0f712ba
AC
2566 if (thick > 0)
2567 {
2568 it->ascent += thick;
2569 it->descent += thick;
2570 }
2571 else
2572 thick = -thick;
177c0ea7 2573
1a578e9b
AC
2574 if (it->start_of_box_run_p)
2575 it->pixel_width += thick;
2576 if (it->end_of_box_run_p)
2577 it->pixel_width += thick;
2578 }
2579
2580 /* If face has an overline, add the height of the overline
2581 (1 pixel) and a 1 pixel margin to the character height. */
2582 if (face->overline_p)
2583 it->ascent += 2;
2584
2585 take_vertical_position_into_account (it);
177c0ea7 2586
1a578e9b
AC
2587 /* If we have to actually produce glyphs, do it. */
2588 if (it->glyph_row)
2589 {
2590 if (stretched_p)
2591 {
2592 /* Translate a space with a `space-width' property
2593 into a stretch glyph. */
e0f712ba
AC
2594 double ascent = (double) FONT_BASE (font)
2595 / FONT_HEIGHT (font);
177c0ea7 2596 x_append_stretch_glyph (it, it->object, it->pixel_width,
1a578e9b
AC
2597 it->ascent + it->descent, ascent);
2598 }
2599 else
2600 x_append_glyph (it);
2601
2602 /* If characters with lbearing or rbearing are displayed
2603 in this line, record that fact in a flag of the
2604 glyph row. This is used to optimize X output code. */
2605 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2606 it->glyph_row->contains_overlapping_glyphs_p = 1;
2607 }
2608 }
2609 else if (it->char_to_display == '\n')
2610 {
2611 /* A newline has no width but we need the height of the line. */
2612 it->pixel_width = 0;
2613 it->nglyphs = 0;
e0f712ba
AC
2614 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2615 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
177c0ea7 2616
e0f712ba
AC
2617 if (face->box != FACE_NO_BOX
2618 && face->box_line_width > 0)
1a578e9b 2619 {
e0f712ba
AC
2620 it->ascent += face->box_line_width;
2621 it->descent += face->box_line_width;
1a578e9b
AC
2622 }
2623 }
2624 else if (it->char_to_display == '\t')
2625 {
2626 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2627 int x = it->current_x + it->continuation_lines_width;
2628 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
177c0ea7 2629
e0f712ba
AC
2630 /* If the distance from the current position to the next tab
2631 stop is less than a canonical character width, use the
2632 tab stop after that. */
2633 if (next_tab_x - x < CANON_X_UNIT (it->f))
2634 next_tab_x += tab_width;
2635
1a578e9b
AC
2636 it->pixel_width = next_tab_x - x;
2637 it->nglyphs = 1;
e0f712ba
AC
2638 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2639 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
177c0ea7 2640
1a578e9b
AC
2641 if (it->glyph_row)
2642 {
2643 double ascent = (double) it->ascent / (it->ascent + it->descent);
177c0ea7 2644 x_append_stretch_glyph (it, it->object, it->pixel_width,
1a578e9b
AC
2645 it->ascent + it->descent, ascent);
2646 }
2647 }
177c0ea7 2648 else
1a578e9b
AC
2649 {
2650 /* A multi-byte character. Assume that the display width of the
2651 character is the width of the character multiplied by the
2652 width of the font. */
2653
2654 /* If we found a font, this font should give us the right
2655 metrics. If we didn't find a font, use the frame's
2656 default font and calculate the width of the character
2657 from the charset width; this is what old redisplay code
2658 did. */
2659 pcm = x_per_char_metric (font, &char2b);
2660 if (font_not_found_p || !pcm)
2661 {
2662 int charset = CHAR_CHARSET (it->char_to_display);
2663
2664 it->glyph_not_available_p = 1;
2665 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2666 * CHARSET_WIDTH (charset));
e0f712ba
AC
2667 it->phys_ascent = FONT_BASE (font) + boff;
2668 it->phys_descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2669 }
2670 else
2671 {
2672 it->pixel_width = pcm->width;
e0f712ba
AC
2673 it->phys_ascent = pcm->ascent + boff;
2674 it->phys_descent = pcm->descent - boff;
2675 if (it->glyph_row
2676 && (pcm->lbearing < 0
2677 || pcm->rbearing > pcm->width))
2678 it->glyph_row->contains_overlapping_glyphs_p = 1;
2679 }
2680 it->nglyphs = 1;
2681 it->ascent = FONT_BASE (font) + boff;
2682 it->descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2683 if (face->box != FACE_NO_BOX)
2684 {
2685 int thick = face->box_line_width;
e0f712ba
AC
2686
2687 if (thick > 0)
2688 {
2689 it->ascent += thick;
2690 it->descent += thick;
2691 }
2692 else
2693 thick = - thick;
177c0ea7 2694
1a578e9b
AC
2695 if (it->start_of_box_run_p)
2696 it->pixel_width += thick;
2697 if (it->end_of_box_run_p)
2698 it->pixel_width += thick;
2699 }
177c0ea7 2700
1a578e9b
AC
2701 /* If face has an overline, add the height of the overline
2702 (1 pixel) and a 1 pixel margin to the character height. */
2703 if (face->overline_p)
2704 it->ascent += 2;
2705
2706 take_vertical_position_into_account (it);
177c0ea7 2707
1a578e9b
AC
2708 if (it->glyph_row)
2709 x_append_glyph (it);
2710 }
e0f712ba 2711 it->multibyte_p = saved_multibyte_p;
1a578e9b
AC
2712 }
2713 else if (it->what == IT_COMPOSITION)
2714 {
2715 /* Note: A composition is represented as one glyph in the
2716 glyph matrix. There are no padding glyphs. */
2717 XChar2b char2b;
2718 XFontStruct *font;
2719 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2720 XCharStruct *pcm;
2721 int font_not_found_p;
2722 struct font_info *font_info;
2723 int boff; /* baseline offset */
2724 struct composition *cmp = composition_table[it->cmp_id];
2725
2726 /* Maybe translate single-byte characters to multibyte. */
2727 it->char_to_display = it->c;
2728 if (unibyte_display_via_language_environment
2729 && SINGLE_BYTE_CHAR_P (it->c)
2730 && (it->c >= 0240
2731 || (it->c >= 0200
2732 && !NILP (Vnonascii_translation_table))))
2733 {
2734 it->char_to_display = unibyte_char_to_multibyte (it->c);
2735 }
e0f712ba 2736
1a578e9b
AC
2737 /* Get face and font to use. Encode IT->char_to_display. */
2738 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2739 face = FACE_FROM_ID (it->f, it->face_id);
2740 x_get_char_face_and_encoding (it->f, it->char_to_display,
2741 it->face_id, &char2b, it->multibyte_p);
2742 font = face->font;
2743
2744 /* When no suitable font found, use the default font. */
2745 font_not_found_p = font == NULL;
2746 if (font_not_found_p)
2747 {
2748 font = FRAME_FONT (it->f);
2749 boff = it->f->output_data.mac->baseline_offset;
2750 font_info = NULL;
2751 }
2752 else
2753 {
2754 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2755 boff = font_info->baseline_offset;
2756 if (font_info->vertical_centering)
2757 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2758 }
2759
2760 /* There are no padding glyphs, so there is only one glyph to
2761 produce for the composition. Important is that pixel_width,
2762 ascent and descent are the values of what is drawn by
2763 draw_glyphs (i.e. the values of the overall glyphs composed). */
2764 it->nglyphs = 1;
2765
2766 /* If we have not yet calculated pixel size data of glyphs of
2767 the composition for the current face font, calculate them
2768 now. Theoretically, we have to check all fonts for the
2769 glyphs, but that requires much time and memory space. So,
2770 here we check only the font of the first glyph. This leads
2771 to incorrect display very rarely, and C-l (recenter) can
2772 correct the display anyway. */
2773 if (cmp->font != (void *) font)
2774 {
2775 /* Ascent and descent of the font of the first character of
2776 this composition (adjusted by baseline offset). Ascent
2777 and descent of overall glyphs should not be less than
2778 them respectively. */
e0f712ba
AC
2779 int font_ascent = FONT_BASE (font) + boff;
2780 int font_descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2781 /* Bounding box of the overall glyphs. */
2782 int leftmost, rightmost, lowest, highest;
2783 int i, width, ascent, descent;
2784
2785 cmp->font = (void *) font;
2786
2787 /* Initialize the bounding box. */
2788 pcm = x_per_char_metric (font, &char2b);
2789 if (pcm)
2790 {
2791 width = pcm->width;
2792 ascent = pcm->ascent;
2793 descent = pcm->descent;
2794 }
2795 else
2796 {
2797 width = FONT_WIDTH (font);
e0f712ba
AC
2798 ascent = FONT_BASE (font);
2799 descent = FONT_DESCENT (font);
1a578e9b 2800 }
177c0ea7 2801
1a578e9b
AC
2802 rightmost = width;
2803 lowest = - descent + boff;
2804 highest = ascent + boff;
2805 leftmost = 0;
177c0ea7 2806
1a578e9b
AC
2807 if (font_info
2808 && font_info->default_ascent
2809 && CHAR_TABLE_P (Vuse_default_ascent)
2810 && !NILP (Faref (Vuse_default_ascent,
2811 make_number (it->char_to_display))))
2812 highest = font_info->default_ascent + boff;
2813
2814 /* Draw the first glyph at the normal position. It may be
2815 shifted to right later if some other glyphs are drawn at
2816 the left. */
2817 cmp->offsets[0] = 0;
2818 cmp->offsets[1] = boff;
2819
2820 /* Set cmp->offsets for the remaining glyphs. */
2821 for (i = 1; i < cmp->glyph_len; i++)
2822 {
2823 int left, right, btm, top;
2824 int ch = COMPOSITION_GLYPH (cmp, i);
2825 int face_id = FACE_FOR_CHAR (it->f, face, ch);
e0f712ba 2826
1a578e9b
AC
2827 face = FACE_FROM_ID (it->f, face_id);
2828 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2829 it->multibyte_p);
2830 font = face->font;
2831 if (font == NULL)
2832 {
2833 font = FRAME_FONT (it->f);
2834 boff = it->f->output_data.mac->baseline_offset;
2835 font_info = NULL;
2836 }
2837 else
2838 {
2839 font_info
2840 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2841 boff = font_info->baseline_offset;
2842 if (font_info->vertical_centering)
2843 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2844 }
2845
2846 pcm = x_per_char_metric (font, &char2b);
2847 if (pcm)
2848 {
2849 width = pcm->width;
2850 ascent = pcm->ascent;
2851 descent = pcm->descent;
2852 }
2853 else
2854 {
2855 width = FONT_WIDTH (font);
e0f712ba
AC
2856 ascent = 1;
2857 descent = 0;
1a578e9b
AC
2858 }
2859
2860 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2861 {
2862 /* Relative composition with or without
2863 alternate chars. */
2864 left = (leftmost + rightmost - width) / 2;
2865 btm = - descent + boff;
2866 if (font_info && font_info->relative_compose
2867 && (! CHAR_TABLE_P (Vignore_relative_composition)
2868 || NILP (Faref (Vignore_relative_composition,
2869 make_number (ch)))))
2870 {
2871
2872 if (- descent >= font_info->relative_compose)
2873 /* One extra pixel between two glyphs. */
2874 btm = highest + 1;
2875 else if (ascent <= 0)
2876 /* One extra pixel between two glyphs. */
2877 btm = lowest - 1 - ascent - descent;
2878 }
2879 }
2880 else
2881 {
2882 /* A composition rule is specified by an integer
2883 value that encodes global and new reference
2884 points (GREF and NREF). GREF and NREF are
2885 specified by numbers as below:
2886
2887 0---1---2 -- ascent
2888 | |
2889 | |
2890 | |
2891 9--10--11 -- center
2892 | |
2893 ---3---4---5--- baseline
2894 | |
2895 6---7---8 -- descent
2896 */
2897 int rule = COMPOSITION_RULE (cmp, i);
2898 int gref, nref, grefx, grefy, nrefx, nrefy;
2899
2900 COMPOSITION_DECODE_RULE (rule, gref, nref);
2901 grefx = gref % 3, nrefx = nref % 3;
2902 grefy = gref / 3, nrefy = nref / 3;
2903
2904 left = (leftmost
2905 + grefx * (rightmost - leftmost) / 2
2906 - nrefx * width / 2);
2907 btm = ((grefy == 0 ? highest
2908 : grefy == 1 ? 0
2909 : grefy == 2 ? lowest
2910 : (highest + lowest) / 2)
2911 - (nrefy == 0 ? ascent + descent
2912 : nrefy == 1 ? descent - boff
2913 : nrefy == 2 ? 0
2914 : (ascent + descent) / 2));
2915 }
2916
2917 cmp->offsets[i * 2] = left;
2918 cmp->offsets[i * 2 + 1] = btm + descent;
2919
2920 /* Update the bounding box of the overall glyphs. */
2921 right = left + width;
2922 top = btm + descent + ascent;
2923 if (left < leftmost)
2924 leftmost = left;
2925 if (right > rightmost)
2926 rightmost = right;
2927 if (top > highest)
2928 highest = top;
2929 if (btm < lowest)
2930 lowest = btm;
2931 }
2932
2933 /* If there are glyphs whose x-offsets are negative,
2934 shift all glyphs to the right and make all x-offsets
2935 non-negative. */
2936 if (leftmost < 0)
2937 {
2938 for (i = 0; i < cmp->glyph_len; i++)
2939 cmp->offsets[i * 2] -= leftmost;
2940 rightmost -= leftmost;
2941 }
2942
2943 cmp->pixel_width = rightmost;
2944 cmp->ascent = highest;
2945 cmp->descent = - lowest;
2946 if (cmp->ascent < font_ascent)
2947 cmp->ascent = font_ascent;
2948 if (cmp->descent < font_descent)
2949 cmp->descent = font_descent;
2950 }
2951
2952 it->pixel_width = cmp->pixel_width;
2953 it->ascent = it->phys_ascent = cmp->ascent;
2954 it->descent = it->phys_descent = cmp->descent;
2955
2956 if (face->box != FACE_NO_BOX)
2957 {
2958 int thick = face->box_line_width;
e0f712ba
AC
2959
2960 if (thick > 0)
2961 {
2962 it->ascent += thick;
2963 it->descent += thick;
2964 }
2965 else
2966 thick = - thick;
177c0ea7 2967
1a578e9b
AC
2968 if (it->start_of_box_run_p)
2969 it->pixel_width += thick;
2970 if (it->end_of_box_run_p)
2971 it->pixel_width += thick;
2972 }
177c0ea7 2973
1a578e9b
AC
2974 /* If face has an overline, add the height of the overline
2975 (1 pixel) and a 1 pixel margin to the character height. */
2976 if (face->overline_p)
2977 it->ascent += 2;
2978
2979 take_vertical_position_into_account (it);
177c0ea7 2980
1a578e9b
AC
2981 if (it->glyph_row)
2982 x_append_composite_glyph (it);
2983 }
2984 else if (it->what == IT_IMAGE)
2985 x_produce_image_glyph (it);
2986 else if (it->what == IT_STRETCH)
2987 x_produce_stretch_glyph (it);
2988
2989 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2990 because this isn't true for images with `:ascent 100'. */
2991 xassert (it->ascent >= 0 && it->descent >= 0);
2992 if (it->area == TEXT_AREA)
2993 it->current_x += it->pixel_width;
e0f712ba 2994
1a578e9b 2995 it->descent += it->extra_line_spacing;
e0f712ba 2996
1a578e9b
AC
2997 it->max_ascent = max (it->max_ascent, it->ascent);
2998 it->max_descent = max (it->max_descent, it->descent);
2999 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
3000 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
3001}
3002
3003
3004/* Estimate the pixel height of the mode or top line on frame F.
3005 FACE_ID specifies what line's height to estimate. */
3006
3007int
3008x_estimate_mode_line_height (f, face_id)
3009 struct frame *f;
3010 enum face_id face_id;
3011{
e0f712ba 3012 int height = FONT_HEIGHT (FRAME_FONT (f));
1a578e9b
AC
3013
3014 /* This function is called so early when Emacs starts that the face
3015 cache and mode line face are not yet initialized. */
3016 if (FRAME_FACE_CACHE (f))
3017 {
3018 struct face *face = FACE_FROM_ID (f, face_id);
3019 if (face)
e0f712ba
AC
3020 {
3021 if (face->font)
3022 height = FONT_HEIGHT (face->font);
3023 if (face->box_line_width > 0)
3024 height += 2 * face->box_line_width;
3025 }
1a578e9b 3026 }
177c0ea7 3027
1a578e9b
AC
3028 return height;
3029}
3030
3031\f
3032/***********************************************************************
3033 Glyph display
3034 ***********************************************************************/
3035
3036/* A sequence of glyphs to be drawn in the same face.
3037
3038 This data structure is not really completely X specific, so it
3039 could possibly, at least partially, be useful for other systems. It
3040 is currently not part of the external redisplay interface because
3041 it's not clear what other systems will need. */
3042
3043struct glyph_string
3044{
3045 /* X-origin of the string. */
3046 int x;
3047
3048 /* Y-origin and y-position of the base line of this string. */
3049 int y, ybase;
3050
3051 /* The width of the string, not including a face extension. */
3052 int width;
3053
3054 /* The width of the string, including a face extension. */
3055 int background_width;
3056
3057 /* The height of this string. This is the height of the line this
3058 string is drawn in, and can be different from the height of the
3059 font the string is drawn in. */
3060 int height;
3061
3062 /* Number of pixels this string overwrites in front of its x-origin.
3063 This number is zero if the string has an lbearing >= 0; it is
3064 -lbearing, if the string has an lbearing < 0. */
3065 int left_overhang;
3066
3067 /* Number of pixels this string overwrites past its right-most
3068 nominal x-position, i.e. x + width. Zero if the string's
3069 rbearing is <= its nominal width, rbearing - width otherwise. */
3070 int right_overhang;
3071
3072 /* The frame on which the glyph string is drawn. */
3073 struct frame *f;
3074
3075 /* The window on which the glyph string is drawn. */
3076 struct window *w;
3077
3078 /* X display and window for convenience. */
3079 Display *display;
3080 Window window;
3081
3082 /* The glyph row for which this string was built. It determines the
3083 y-origin and height of the string. */
3084 struct glyph_row *row;
3085
3086 /* The area within row. */
3087 enum glyph_row_area area;
3088
3089 /* Characters to be drawn, and number of characters. */
3090 XChar2b *char2b;
3091 int nchars;
3092
3093 /* A face-override for drawing cursors, mouse face and similar. */
3094 enum draw_glyphs_face hl;
3095
3096 /* Face in which this string is to be drawn. */
3097 struct face *face;
3098
3099 /* Font in which this string is to be drawn. */
3100 XFontStruct *font;
3101
3102 /* Font info for this string. */
3103 struct font_info *font_info;
3104
3105 /* Non-null means this string describes (part of) a composition.
3106 All characters from char2b are drawn composed. */
3107 struct composition *cmp;
3108
3109 /* Index of this glyph string's first character in the glyph
3110 definition of CMP. If this is zero, this glyph string describes
3111 the first character of a composition. */
3112 int gidx;
3113
3114 /* 1 means this glyph strings face has to be drawn to the right end
3115 of the window's drawing area. */
3116 unsigned extends_to_end_of_line_p : 1;
3117
3118 /* 1 means the background of this string has been drawn. */
3119 unsigned background_filled_p : 1;
3120
3121 /* 1 means glyph string must be drawn with 16-bit functions. */
3122 unsigned two_byte_p : 1;
3123
3124 /* 1 means that the original font determined for drawing this glyph
3125 string could not be loaded. The member `font' has been set to
3126 the frame's default font in this case. */
3127 unsigned font_not_found_p : 1;
3128
3129 /* 1 means that the face in which this glyph string is drawn has a
3130 stipple pattern. */
3131 unsigned stippled_p : 1;
3132
3133 /* 1 means only the foreground of this glyph string must be drawn,
3134 and we should use the physical height of the line this glyph
3135 string appears in as clip rect. */
3136 unsigned for_overlaps_p : 1;
3137
3138 /* The GC to use for drawing this glyph string. */
3139 GC gc;
3140
3141 /* A pointer to the first glyph in the string. This glyph
3142 corresponds to char2b[0]. Needed to draw rectangles if
3143 font_not_found_p is 1. */
3144 struct glyph *first_glyph;
3145
3146 /* Image, if any. */
3147 struct image *img;
3148
3149 struct glyph_string *next, *prev;
3150};
3151
3152
3153#if 0
3154
3155static void
3156x_dump_glyph_string (s)
3157 struct glyph_string *s;
3158{
3159 fprintf (stderr, "glyph string\n");
3160 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3161 s->x, s->y, s->width, s->height);
3162 fprintf (stderr, " ybase = %d\n", s->ybase);
3163 fprintf (stderr, " hl = %d\n", s->hl);
3164 fprintf (stderr, " left overhang = %d, right = %d\n",
3165 s->left_overhang, s->right_overhang);
3166 fprintf (stderr, " nchars = %d\n", s->nchars);
3167 fprintf (stderr, " extends to end of line = %d\n",
3168 s->extends_to_end_of_line_p);
3169 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3170 fprintf (stderr, " bg width = %d\n", s->background_width);
3171}
3172
3173#endif /* GLYPH_DEBUG */
3174
3175
3176
3177static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3178 struct glyph_string **,
3179 struct glyph_string *,
3180 struct glyph_string *));
3181static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3182 struct glyph_string **,
3183 struct glyph_string *,
3184 struct glyph_string *));
3185static void x_append_glyph_string P_ ((struct glyph_string **,
3186 struct glyph_string **,
3187 struct glyph_string *));
3188static int x_left_overwritten P_ ((struct glyph_string *));
3189static int x_left_overwriting P_ ((struct glyph_string *));
3190static int x_right_overwritten P_ ((struct glyph_string *));
3191static int x_right_overwriting P_ ((struct glyph_string *));
3192static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3193 int));
3194static void x_init_glyph_string P_ ((struct glyph_string *,
3195 XChar2b *, struct window *,
3196 struct glyph_row *,
177c0ea7 3197 enum glyph_row_area, int,
1a578e9b
AC
3198 enum draw_glyphs_face));
3199static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3200 enum glyph_row_area, int, int,
e0f712ba 3201 enum draw_glyphs_face, int));
1a578e9b
AC
3202static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3203static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3204static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3205 int));
3206static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3207static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3208static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3209static void x_draw_glyph_string P_ ((struct glyph_string *));
3210static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3211static void x_set_cursor_gc P_ ((struct glyph_string *));
3212static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3213static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3214static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3215 int *, int *));
3216static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
e0f712ba
AC
3217/*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3218 unsigned long *, double, int));*/
1a578e9b
AC
3219static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3220 double, int, unsigned long));
3221static void x_setup_relief_colors P_ ((struct glyph_string *));
3222static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3223static void x_draw_image_relief P_ ((struct glyph_string *));
3224static void x_draw_image_foreground P_ ((struct glyph_string *));
3225static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3226static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3227static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3228 int, int, int));
3229static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
e0f712ba 3230 int, int, int, int, Rect *));
1a578e9b 3231static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
e0f712ba 3232 int, int, int, Rect *));
1a578e9b
AC
3233static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3234 enum glyph_row_area));
3235static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3236 struct glyph_row *,
3237 enum glyph_row_area, int, int));
3238
3239#if GLYPH_DEBUG
3240static void x_check_font P_ ((struct frame *, XFontStruct *));
3241#endif
3242
177c0ea7 3243
1a578e9b
AC
3244/* Append the list of glyph strings with head H and tail T to the list
3245 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3246
3247static INLINE void
3248x_append_glyph_string_lists (head, tail, h, t)
3249 struct glyph_string **head, **tail;
3250 struct glyph_string *h, *t;
3251{
3252 if (h)
3253 {
3254 if (*head)
3255 (*tail)->next = h;
3256 else
3257 *head = h;
3258 h->prev = *tail;
3259 *tail = t;
3260 }
3261}
3262
3263
3264/* Prepend the list of glyph strings with head H and tail T to the
3265 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3266 result. */
3267
3268static INLINE void
3269x_prepend_glyph_string_lists (head, tail, h, t)
3270 struct glyph_string **head, **tail;
3271 struct glyph_string *h, *t;
3272{
3273 if (h)
3274 {
3275 if (*head)
3276 (*head)->prev = t;
3277 else
3278 *tail = t;
3279 t->next = *head;
3280 *head = h;
3281 }
3282}
3283
3284
3285/* Append glyph string S to the list with head *HEAD and tail *TAIL.
3286 Set *HEAD and *TAIL to the resulting list. */
3287
3288static INLINE void
3289x_append_glyph_string (head, tail, s)
3290 struct glyph_string **head, **tail;
3291 struct glyph_string *s;
3292{
3293 s->next = s->prev = NULL;
3294 x_append_glyph_string_lists (head, tail, s, s);
3295}
3296
3297
3298/* Set S->gc to a suitable GC for drawing glyph string S in cursor
3299 face. */
3300
3301static void
3302x_set_cursor_gc (s)
3303 struct glyph_string *s;
3304{
3305 if (s->font == FRAME_FONT (s->f)
3306 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3307 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3308 && !s->cmp)
3309 s->gc = s->f->output_data.mac->cursor_gc;
3310 else
3311 {
3312 /* Cursor on non-default face: must merge. */
3313 XGCValues xgcv;
3314 unsigned long mask;
3315
3316 xgcv.background = s->f->output_data.mac->cursor_pixel;
3317 xgcv.foreground = s->face->background;
3318
3319 /* If the glyph would be invisible, try a different foreground. */
3320 if (xgcv.foreground == xgcv.background)
3321 xgcv.foreground = s->face->foreground;
3322 if (xgcv.foreground == xgcv.background)
3323 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3324 if (xgcv.foreground == xgcv.background)
3325 xgcv.foreground = s->face->foreground;
3326
3327 /* Make sure the cursor is distinct from text in this face. */
3328 if (xgcv.background == s->face->background
3329 && xgcv.foreground == s->face->foreground)
3330 {
3331 xgcv.background = s->face->foreground;
3332 xgcv.foreground = s->face->background;
3333 }
3334
3335 IF_DEBUG (x_check_font (s->f, s->font));
3336 xgcv.font = s->font;
3337 mask = GCForeground | GCBackground | GCFont;
3338
3339 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3340 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3341 mask, &xgcv);
3342 else
3343 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3344 = XCreateGC (s->display, s->window, mask, &xgcv);
3345
3346 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3347 }
3348}
3349
3350
3351/* Set up S->gc of glyph string S for drawing text in mouse face. */
177c0ea7 3352
1a578e9b
AC
3353static void
3354x_set_mouse_face_gc (s)
3355 struct glyph_string *s;
177c0ea7 3356{
1a578e9b
AC
3357 int face_id;
3358 struct face *face;
3359
e0f712ba 3360 /* What face has to be used last for the mouse face? */
1a578e9b
AC
3361 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3362 face = FACE_FROM_ID (s->f, face_id);
e0f712ba
AC
3363 if (face == NULL)
3364 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
177c0ea7 3365
1a578e9b
AC
3366 if (s->first_glyph->type == CHAR_GLYPH)
3367 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3368 else
3369 face_id = FACE_FOR_CHAR (s->f, face, 0);
3370 s->face = FACE_FROM_ID (s->f, face_id);
3371 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3372
3373 /* If font in this face is same as S->font, use it. */
3374 if (s->font == s->face->font)
3375 s->gc = s->face->gc;
3376 else
3377 {
3378 /* Otherwise construct scratch_cursor_gc with values from FACE
3379 but font FONT. */
3380 XGCValues xgcv;
3381 unsigned long mask;
177c0ea7 3382
1a578e9b
AC
3383 xgcv.background = s->face->background;
3384 xgcv.foreground = s->face->foreground;
3385 IF_DEBUG (x_check_font (s->f, s->font));
3386 xgcv.font = s->font;
3387 mask = GCForeground | GCBackground | GCFont;
177c0ea7 3388
1a578e9b
AC
3389 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3390 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3391 mask, &xgcv);
3392 else
3393 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3394 = XCreateGC (s->display, s->window, mask, &xgcv);
177c0ea7 3395
1a578e9b
AC
3396 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3397 }
3398
3399 xassert (s->gc != 0);
3400}
3401
3402
3403/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3404 Faces to use in the mode line have already been computed when the
3405 matrix was built, so there isn't much to do, here. */
3406
3407static INLINE void
3408x_set_mode_line_face_gc (s)
3409 struct glyph_string *s;
177c0ea7 3410{
1a578e9b
AC
3411 s->gc = s->face->gc;
3412}
3413
3414
3415/* Set S->gc of glyph string S for drawing that glyph string. Set
3416 S->stippled_p to a non-zero value if the face of S has a stipple
3417 pattern. */
3418
3419static INLINE void
3420x_set_glyph_string_gc (s)
3421 struct glyph_string *s;
3422{
3423 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
177c0ea7 3424
1a578e9b
AC
3425 if (s->hl == DRAW_NORMAL_TEXT)
3426 {
3427 s->gc = s->face->gc;
3428 s->stippled_p = s->face->stipple != 0;
3429 }
3430 else if (s->hl == DRAW_INVERSE_VIDEO)
3431 {
3432 x_set_mode_line_face_gc (s);
3433 s->stippled_p = s->face->stipple != 0;
3434 }
3435 else if (s->hl == DRAW_CURSOR)
3436 {
3437 x_set_cursor_gc (s);
3438 s->stippled_p = 0;
3439 }
3440 else if (s->hl == DRAW_MOUSE_FACE)
3441 {
3442 x_set_mouse_face_gc (s);
3443 s->stippled_p = s->face->stipple != 0;
3444 }
3445 else if (s->hl == DRAW_IMAGE_RAISED
3446 || s->hl == DRAW_IMAGE_SUNKEN)
3447 {
3448 s->gc = s->face->gc;
3449 s->stippled_p = s->face->stipple != 0;
3450 }
3451 else
3452 {
3453 s->gc = s->face->gc;
3454 s->stippled_p = s->face->stipple != 0;
3455 }
3456
3457 /* GC must have been set. */
3458 xassert (s->gc != 0);
3459}
3460
3461
3462/* Return in *R the clipping rectangle for glyph string S. */
3463
3464static void
3465x_get_glyph_string_clip_rect (s, r)
3466 struct glyph_string *s;
3467 Rect *r;
3468{
3469 int r_height, r_width;
3470
3471 if (s->row->full_width_p)
3472 {
3473 /* Draw full-width. X coordinates are relative to S->w->left. */
3474 int canon_x = CANON_X_UNIT (s->f);
177c0ea7 3475
1a578e9b
AC
3476 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3477 r_width = XFASTINT (s->w->width) * canon_x;
3478
3479 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3480 {
3481 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3482 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3483 r->left -= width;
3484 }
177c0ea7 3485
1a578e9b
AC
3486 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3487
3488 /* Unless displaying a mode or menu bar line, which are always
3489 fully visible, clip to the visible part of the row. */
3490 if (s->w->pseudo_window_p)
3491 r_height = s->row->visible_height;
3492 else
3493 r_height = s->height;
3494 }
3495 else
3496 {
3497 /* This is a text line that may be partially visible. */
3498 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3499 r_width = window_box_width (s->w, s->area);
3500 r_height = s->row->visible_height;
3501 }
3502
1a578e9b
AC
3503 /* If S draws overlapping rows, it's sufficient to use the top and
3504 bottom of the window for clipping because this glyph string
3505 intentionally draws over other lines. */
3506 if (s->for_overlaps_p)
3507 {
3508 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3509 r_height = window_text_bottom_y (s->w) - r->top;
3510 }
e0f712ba
AC
3511 else
3512 {
3513 /* Don't use S->y for clipping because it doesn't take partially
3514 visible lines into account. For example, it can be negative for
3515 partially visible lines at the top of a window. */
3516 if (!s->row->full_width_p
3517 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3518 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3519 else
3520 r->top = max (0, s->row->y);
3521
3522 /* If drawing a tool-bar window, draw it over the internal border
3523 at the top of the window. */
3524 if (s->w == XWINDOW (s->f->tool_bar_window))
3525 r->top -= s->f->output_data.mac->internal_border_width;
3526 }
3527
1a578e9b
AC
3528 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3529
3530 r->bottom = r->top + r_height;
3531 r->right = r->left + r_width;
3532}
3533
3534
3535/* Set clipping for output of glyph string S. S may be part of a mode
3536 line or menu if we don't have X toolkit support. */
3537
3538static INLINE void
3539x_set_glyph_string_clipping (s)
3540 struct glyph_string *s;
3541{
3542 Rect r;
3543 x_get_glyph_string_clip_rect (s, &r);
3544 mac_set_clip_rectangle (s->display, s->window, &r);
3545}
3546
3547
3548/* Compute left and right overhang of glyph string S. If S is a glyph
3549 string for a composition, assume overhangs don't exist. */
3550
3551static INLINE void
3552x_compute_glyph_string_overhangs (s)
3553 struct glyph_string *s;
3554{
3555 if (s->cmp == NULL
3556 && s->first_glyph->type == CHAR_GLYPH)
3557 {
3558 XCharStruct cs;
3559 int direction, font_ascent, font_descent;
3560 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3561 &font_ascent, &font_descent, &cs);
3562 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3563 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3564 }
3565}
3566
3567
3568/* Compute overhangs and x-positions for glyph string S and its
3569 predecessors, or successors. X is the starting x-position for S.
3570 BACKWARD_P non-zero means process predecessors. */
177c0ea7 3571
1a578e9b
AC
3572static void
3573x_compute_overhangs_and_x (s, x, backward_p)
3574 struct glyph_string *s;
3575 int x;
3576 int backward_p;
3577{
3578 if (backward_p)
3579 {
3580 while (s)
3581 {
3582 x_compute_glyph_string_overhangs (s);
3583 x -= s->width;
3584 s->x = x;
3585 s = s->prev;
3586 }
3587 }
3588 else
3589 {
3590 while (s)
3591 {
3592 x_compute_glyph_string_overhangs (s);
3593 s->x = x;
3594 x += s->width;
3595 s = s->next;
3596 }
3597 }
3598}
3599
3600
3601/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3602 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3603 assumed to be zero. */
3604
3605void
3606x_get_glyph_overhangs (glyph, f, left, right)
3607 struct glyph *glyph;
3608 struct frame *f;
3609 int *left, *right;
3610{
3611 *left = *right = 0;
177c0ea7 3612
1a578e9b
AC
3613 if (glyph->type == CHAR_GLYPH)
3614 {
3615 XFontStruct *font;
3616 struct face *face;
3617 struct font_info *font_info;
3618 XChar2b char2b;
3619 XCharStruct *pcm;
3620
3621 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3622 font = face->font;
3623 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3624 if (font
3625 && (pcm = x_per_char_metric (font, &char2b)))
3626 {
3627 if (pcm->rbearing > pcm->width)
3628 *right = pcm->rbearing - pcm->width;
3629 if (pcm->lbearing < 0)
3630 *left = -pcm->lbearing;
3631 }
3632 }
3633}
3634
3635
3636/* Return the index of the first glyph preceding glyph string S that
3637 is overwritten by S because of S's left overhang. Value is -1
3638 if no glyphs are overwritten. */
3639
3640static int
3641x_left_overwritten (s)
3642 struct glyph_string *s;
3643{
3644 int k;
177c0ea7 3645
1a578e9b
AC
3646 if (s->left_overhang)
3647 {
3648 int x = 0, i;
3649 struct glyph *glyphs = s->row->glyphs[s->area];
3650 int first = s->first_glyph - glyphs;
3651
3652 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3653 x -= glyphs[i].pixel_width;
3654
3655 k = i + 1;
3656 }
3657 else
3658 k = -1;
3659
3660 return k;
3661}
3662
3663
3664/* Return the index of the first glyph preceding glyph string S that
3665 is overwriting S because of its right overhang. Value is -1 if no
3666 glyph in front of S overwrites S. */
3667
3668static int
3669x_left_overwriting (s)
3670 struct glyph_string *s;
3671{
3672 int i, k, x;
3673 struct glyph *glyphs = s->row->glyphs[s->area];
3674 int first = s->first_glyph - glyphs;
3675
3676 k = -1;
3677 x = 0;
3678 for (i = first - 1; i >= 0; --i)
3679 {
3680 int left, right;
3681 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3682 if (x + right > 0)
3683 k = i;
3684 x -= glyphs[i].pixel_width;
3685 }
3686
3687 return k;
3688}
3689
3690
3691/* Return the index of the last glyph following glyph string S that is
3692 not overwritten by S because of S's right overhang. Value is -1 if
3693 no such glyph is found. */
3694
3695static int
3696x_right_overwritten (s)
3697 struct glyph_string *s;
3698{
3699 int k = -1;
3700
3701 if (s->right_overhang)
3702 {
3703 int x = 0, i;
3704 struct glyph *glyphs = s->row->glyphs[s->area];
3705 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3706 int end = s->row->used[s->area];
177c0ea7 3707
1a578e9b
AC
3708 for (i = first; i < end && s->right_overhang > x; ++i)
3709 x += glyphs[i].pixel_width;
3710
3711 k = i;
3712 }
3713
3714 return k;
3715}
3716
3717
3718/* Return the index of the last glyph following glyph string S that
3719 overwrites S because of its left overhang. Value is negative
3720 if no such glyph is found. */
3721
3722static int
3723x_right_overwriting (s)
3724 struct glyph_string *s;
3725{
3726 int i, k, x;
3727 int end = s->row->used[s->area];
3728 struct glyph *glyphs = s->row->glyphs[s->area];
3729 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3730
3731 k = -1;
3732 x = 0;
3733 for (i = first; i < end; ++i)
3734 {
3735 int left, right;
3736 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3737 if (x - left < 0)
3738 k = i;
3739 x += glyphs[i].pixel_width;
3740 }
3741
3742 return k;
3743}
3744
3745
3746/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3747
3748static INLINE void
3749x_clear_glyph_string_rect (s, x, y, w, h)
3750 struct glyph_string *s;
3751 int x, y, w, h;
3752{
3753 XGCValues xgcv;
3754
3755 xgcv.foreground = s->gc->background;
3756 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3757}
3758
3759
3760/* Draw the background of glyph_string S. If S->background_filled_p
3761 is non-zero don't draw it. FORCE_P non-zero means draw the
3762 background even if it wouldn't be drawn normally. This is used
3763 when a string preceding S draws into the background of S, or S
3764 contains the first component of a composition. */
3765
3766static void
3767x_draw_glyph_string_background (s, force_p)
3768 struct glyph_string *s;
3769 int force_p;
3770{
3771 /* Nothing to do if background has already been drawn or if it
3772 shouldn't be drawn in the first place. */
3773 if (!s->background_filled_p)
3774 {
e0f712ba
AC
3775 int box_line_width = max (s->face->box_line_width, 0);
3776
1a578e9b
AC
3777#if 0 /* MAC_TODO: stipple */
3778 if (s->stippled_p)
3779 {
3780 /* Fill background with a stipple pattern. */
3781 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3782 XFillRectangle (s->display, s->window, s->gc, s->x,
e0f712ba 3783 s->y + box_line_width,
1a578e9b 3784 s->background_width,
e0f712ba 3785 s->height - 2 * box_line_width);
1a578e9b
AC
3786 XSetFillStyle (s->display, s->gc, FillSolid);
3787 s->background_filled_p = 1;
3788 }
3789 else
3790#endif
e0f712ba 3791 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1a578e9b
AC
3792 || s->font_not_found_p
3793 || s->extends_to_end_of_line_p
3794 || force_p)
3795 {
e0f712ba 3796 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1a578e9b 3797 s->background_width,
e0f712ba 3798 s->height - 2 * box_line_width);
1a578e9b
AC
3799 s->background_filled_p = 1;
3800 }
3801 }
3802}
3803
3804
3805/* Draw the foreground of glyph string S. */
3806
3807static void
3808x_draw_glyph_string_foreground (s)
3809 struct glyph_string *s;
3810{
3811 int i, x;
3812
3813 /* If first glyph of S has a left box line, start drawing the text
3814 of S to the right of that box line. */
3815 if (s->face->box != FACE_NO_BOX
3816 && s->first_glyph->left_box_line_p)
e0f712ba 3817 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
3818 else
3819 x = s->x;
3820
3821 /* Draw characters of S as rectangles if S's font could not be
3822 loaded. */
3823 if (s->font_not_found_p)
3824 {
3825 for (i = 0; i < s->nchars; ++i)
3826 {
3827 struct glyph *g = s->first_glyph + i;
3828 mac_draw_rectangle (s->display, s->window,
3829 s->gc, x, s->y, g->pixel_width - 1,
3830 s->height - 1);
3831 x += g->pixel_width;
3832 }
3833 }
3834 else
3835 {
3836 char *char1b = (char *) s->char2b;
3837 int boff = s->font_info->baseline_offset;
3838
3839 if (s->font_info->vertical_centering)
3840 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3841
3842 /* If we can use 8-bit functions, condense S->char2b. */
3843 if (!s->two_byte_p)
3844 for (i = 0; i < s->nchars; ++i)
3845 char1b[i] = s->char2b[i].byte2;
3846
3847 /* Draw text with XDrawString if background has already been
3848 filled. Otherwise, use XDrawImageString. (Note that
3849 XDrawImageString is usually faster than XDrawString.) Always
3850 use XDrawImageString when drawing the cursor so that there is
3851 no chance that characters under a box cursor are invisible. */
3852 if (s->for_overlaps_p
3853 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3854 {
3855 /* Draw characters with 16-bit or 8-bit functions. */
3856 if (s->two_byte_p)
3857 XDrawString16 (s->display, s->window, s->gc, x,
3858 s->ybase - boff, s->char2b, s->nchars);
3859 else
3860 XDrawString (s->display, s->window, s->gc, x,
3861 s->ybase - boff, char1b, s->nchars);
3862 }
3863 else
3864 {
3865 if (s->two_byte_p)
3866 XDrawImageString16 (s->display, s->window, s->gc, x,
3867 s->ybase - boff, s->char2b, s->nchars);
3868 else
3869 XDrawImageString (s->display, s->window, s->gc, x,
3870 s->ybase - boff, char1b, s->nchars);
3871 }
3872 }
3873}
3874
3875/* Draw the foreground of composite glyph string S. */
3876
3877static void
3878x_draw_composite_glyph_string_foreground (s)
3879 struct glyph_string *s;
3880{
3881 int i, x;
3882
3883 /* If first glyph of S has a left box line, start drawing the text
3884 of S to the right of that box line. */
3885 if (s->face->box != FACE_NO_BOX
3886 && s->first_glyph->left_box_line_p)
e0f712ba 3887 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
3888 else
3889 x = s->x;
3890
3891 /* S is a glyph string for a composition. S->gidx is the index of
3892 the first character drawn for glyphs of this composition.
3893 S->gidx == 0 means we are drawing the very first character of
3894 this composition. */
3895
3896 /* Draw a rectangle for the composition if the font for the very
3897 first character of the composition could not be loaded. */
3898 if (s->font_not_found_p)
3899 {
3900 if (s->gidx == 0)
3901 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3902 s->width - 1, s->height - 1);
3903 }
3904 else
3905 {
3906 for (i = 0; i < s->nchars; i++, ++s->gidx)
3907 XDrawString16 (s->display, s->window, s->gc,
3908 x + s->cmp->offsets[s->gidx * 2],
3909 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3910 s->char2b + i, 1);
3911 }
3912}
3913
3914
3915#ifdef USE_X_TOOLKIT
3916
3917static struct frame *x_frame_of_widget P_ ((Widget));
3918
3919
3920/* Return the frame on which widget WIDGET is used.. Abort if frame
3921 cannot be determined. */
3922
3923static struct frame *
3924x_frame_of_widget (widget)
3925 Widget widget;
3926{
3927 struct x_display_info *dpyinfo;
3928 Lisp_Object tail;
3929 struct frame *f;
177c0ea7 3930
1a578e9b 3931 dpyinfo = x_display_info_for_display (XtDisplay (widget));
177c0ea7 3932
1a578e9b
AC
3933 /* Find the top-level shell of the widget. Note that this function
3934 can be called when the widget is not yet realized, so XtWindow
3935 (widget) == 0. That's the reason we can't simply use
3936 x_any_window_to_frame. */
3937 while (!XtIsTopLevelShell (widget))
3938 widget = XtParent (widget);
3939
3940 /* Look for a frame with that top-level widget. Allocate the color
3941 on that frame to get the right gamma correction value. */
3942 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3943 if (GC_FRAMEP (XCAR (tail))
3944 && (f = XFRAME (XCAR (tail)),
3945 (f->output_data.nothing != 1
3946 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3947 && f->output_data.x->widget == widget)
3948 return f;
3949
3950 abort ();
3951}
3952
3953
3954/* Allocate the color COLOR->pixel on the screen and display of
3955 widget WIDGET in colormap CMAP. If an exact match cannot be
3956 allocated, try the nearest color available. Value is non-zero
3957 if successful. This is called from lwlib. */
3958
3959int
3960x_alloc_nearest_color_for_widget (widget, cmap, color)
3961 Widget widget;
3962 Colormap cmap;
3963 XColor *color;
3964{
3965 struct frame *f = x_frame_of_widget (widget);
3966 return x_alloc_nearest_color (f, cmap, color);
3967}
3968
3969
3970#endif /* USE_X_TOOLKIT */
3971
e0f712ba 3972#if 0 /* MAC_TODO */
1a578e9b
AC
3973
3974/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3975 CMAP. If an exact match can't be allocated, try the nearest color
3976 available. Value is non-zero if successful. Set *COLOR to the
3977 color allocated. */
3978
3979int
3980x_alloc_nearest_color (f, cmap, color)
3981 struct frame *f;
3982 Colormap cmap;
3983 XColor *color;
3984{
3985 Display *display = FRAME_X_DISPLAY (f);
3986 Screen *screen = FRAME_X_SCREEN (f);
3987 int rc;
3988
3989 gamma_correct (f, color);
3990 rc = XAllocColor (display, cmap, color);
3991 if (rc == 0)
3992 {
3993 /* If we got to this point, the colormap is full, so we're going
3994 to try to get the next closest color. The algorithm used is
3995 a least-squares matching, which is what X uses for closest
3996 color matching with StaticColor visuals. */
3997 int nearest, i;
3998 unsigned long nearest_delta = ~0;
3999 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
4000 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
4001
4002 for (i = 0; i < ncells; ++i)
4003 cells[i].pixel = i;
4004 XQueryColors (display, cmap, cells, ncells);
4005
4006 for (nearest = i = 0; i < ncells; ++i)
4007 {
4008 long dred = (color->red >> 8) - (cells[i].red >> 8);
4009 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
4010 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
4011 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
4012
4013 if (delta < nearest_delta)
4014 {
4015 nearest = i;
4016 nearest_delta = delta;
4017 }
4018 }
177c0ea7 4019
1a578e9b
AC
4020 color->red = cells[nearest].red;
4021 color->green = cells[nearest].green;
4022 color->blue = cells[nearest].blue;
4023 rc = XAllocColor (display, cmap, color);
4024 }
4025
4026#ifdef DEBUG_X_COLORS
4027 if (rc)
4028 register_color (color->pixel);
4029#endif /* DEBUG_X_COLORS */
177c0ea7 4030
1a578e9b
AC
4031 return rc;
4032}
4033
4034
4035/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4036 It's necessary to do this instead of just using PIXEL directly to
4037 get color reference counts right. */
4038
4039unsigned long
4040x_copy_color (f, pixel)
4041 struct frame *f;
4042 unsigned long pixel;
4043{
4044 XColor color;
4045
4046 color.pixel = pixel;
4047 BLOCK_INPUT;
4048 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4049 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4050 UNBLOCK_INPUT;
4051#ifdef DEBUG_X_COLORS
4052 register_color (pixel);
4053#endif
4054 return color.pixel;
4055}
4056
4057
4058/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4059 It's necessary to do this instead of just using PIXEL directly to
4060 get color reference counts right. */
4061
4062unsigned long
4063x_copy_dpy_color (dpy, cmap, pixel)
4064 Display *dpy;
4065 Colormap cmap;
4066 unsigned long pixel;
4067{
4068 XColor color;
4069
4070 color.pixel = pixel;
4071 BLOCK_INPUT;
4072 XQueryColor (dpy, cmap, &color);
4073 XAllocColor (dpy, cmap, &color);
4074 UNBLOCK_INPUT;
4075#ifdef DEBUG_X_COLORS
4076 register_color (pixel);
4077#endif
4078 return color.pixel;
4079}
4080
e0f712ba 4081#endif /* MAC_TODO */
1a578e9b
AC
4082
4083/* Allocate a color which is lighter or darker than *COLOR by FACTOR
4084 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4085 If this produces the same color as COLOR, try a color where all RGB
4086 values have DELTA added. Return the allocated color in *COLOR.
4087 DISPLAY is the X display, CMAP is the colormap to operate on.
4088 Value is non-zero if successful. */
4089
4090static int
4091mac_alloc_lighter_color (f, color, factor, delta)
4092 struct frame *f;
4093 unsigned long *color;
4094 double factor;
4095 int delta;
4096{
4097 unsigned long new;
4098
4099 /* Change RGB values by specified FACTOR. Avoid overflow! */
4100 xassert (factor >= 0);
4101 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4102 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4103 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4104 if (new == *color)
4105 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4106 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4107 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4108
4109 /* MAC_TODO: Map to palette and retry with delta if same? */
4110 /* MAC_TODO: Free colors (if using palette)? */
4111
4112 if (new == *color)
4113 return 0;
4114
4115 *color = new;
4116
4117 return 1;
4118}
4119
4120
4121/* Set up the foreground color for drawing relief lines of glyph
4122 string S. RELIEF is a pointer to a struct relief containing the GC
4123 with which lines will be drawn. Use a color that is FACTOR or
4124 DELTA lighter or darker than the relief's background which is found
4125 in S->f->output_data.x->relief_background. If such a color cannot
4126 be allocated, use DEFAULT_PIXEL, instead. */
177c0ea7 4127
1a578e9b
AC
4128static void
4129x_setup_relief_color (f, relief, factor, delta, default_pixel)
4130 struct frame *f;
4131 struct relief *relief;
4132 double factor;
4133 int delta;
4134 unsigned long default_pixel;
4135{
4136 XGCValues xgcv;
4137 struct mac_output *di = f->output_data.mac;
4138 unsigned long mask = GCForeground;
4139 unsigned long pixel;
4140 unsigned long background = di->relief_background;
4141 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4142
4143 /* MAC_TODO: Free colors (if using palette)? */
4144
4145 /* Allocate new color. */
4146 xgcv.foreground = default_pixel;
4147 pixel = background;
4148 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4149 {
4150 relief->allocated_p = 1;
4151 xgcv.foreground = relief->pixel = pixel;
4152 }
177c0ea7 4153
1a578e9b
AC
4154 if (relief->gc == 0)
4155 {
4156#if 0 /* MAC_TODO: stipple */
4157 xgcv.stipple = dpyinfo->gray;
4158 mask |= GCStipple;
4159#endif
4160 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4161 }
4162 else
4163 XChangeGC (NULL, relief->gc, mask, &xgcv);
4164}
4165
4166
4167/* Set up colors for the relief lines around glyph string S. */
4168
4169static void
4170x_setup_relief_colors (s)
4171 struct glyph_string *s;
4172{
4173 struct mac_output *di = s->f->output_data.mac;
4174 unsigned long color;
4175
4176 if (s->face->use_box_color_for_shadows_p)
4177 color = s->face->box_color;
4178 else
4179 {
4180 XGCValues xgcv;
177c0ea7 4181
1a578e9b
AC
4182 /* Get the background color of the face. */
4183 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4184 color = xgcv.background;
4185 }
4186
4187 if (di->white_relief.gc == 0
4188 || color != di->relief_background)
4189 {
4190 di->relief_background = color;
4191 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4192 WHITE_PIX_DEFAULT (s->f));
4193 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4194 BLACK_PIX_DEFAULT (s->f));
4195 }
4196}
4197
4198
4199/* Draw a relief on frame F inside the rectangle given by LEFT_X,
4200 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4201 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4202 relief. LEFT_P non-zero means draw a relief on the left side of
4203 the rectangle. RIGHT_P non-zero means draw a relief on the right
4204 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4205 when drawing. */
4206
4207static void
4208x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4209 raised_p, left_p, right_p, clip_rect)
4210 struct frame *f;
4211 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4212 Rect *clip_rect;
4213{
4214 int i;
4215 GC gc;
177c0ea7 4216
1a578e9b
AC
4217 if (raised_p)
4218 gc = f->output_data.mac->white_relief.gc;
4219 else
4220 gc = f->output_data.mac->black_relief.gc;
4221 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4222
4223 /* Top. */
4224 for (i = 0; i < width; ++i)
4225 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4226 left_x + i * left_p, top_y + i,
4227 right_x + 1 - i * right_p, top_y + i);
4228
4229 /* Left. */
4230 if (left_p)
4231 for (i = 0; i < width; ++i)
4232 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4233 left_x + i, top_y + i, left_x + i, bottom_y - i);
4234
4235 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4236 if (raised_p)
4237 gc = f->output_data.mac->black_relief.gc;
4238 else
4239 gc = f->output_data.mac->white_relief.gc;
e0f712ba
AC
4240 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4241 clip_rect);
177c0ea7 4242
1a578e9b
AC
4243 /* Bottom. */
4244 for (i = 0; i < width; ++i)
4245 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4246 left_x + i * left_p, bottom_y - i,
4247 right_x + 1 - i * right_p, bottom_y - i);
177c0ea7 4248
1a578e9b
AC
4249 /* Right. */
4250 if (right_p)
4251 for (i = 0; i < width; ++i)
4252 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4253 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4254
4255 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4256}
4257
4258
4259/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4260 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4261 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4262 left side of the rectangle. RIGHT_P non-zero means draw a line
4263 on the right side of the rectangle. CLIP_RECT is the clipping
4264 rectangle to use when drawing. */
4265
4266static void
4267x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4268 left_p, right_p, clip_rect)
4269 struct glyph_string *s;
4270 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4271 Rect *clip_rect;
4272{
4273 XGCValues xgcv;
177c0ea7 4274
1a578e9b
AC
4275 xgcv.foreground = s->face->box_color;
4276 mac_set_clip_rectangle (s->display, s->window, clip_rect);
177c0ea7 4277
1a578e9b
AC
4278 /* Top. */
4279 XFillRectangle (s->display, s->window, &xgcv,
4280 left_x, top_y, right_x - left_x, width);
4281
4282 /* Left. */
4283 if (left_p)
4284 XFillRectangle (s->display, s->window, &xgcv,
4285 left_x, top_y, width, bottom_y - top_y);
4286
4287 /* Bottom. */
4288 XFillRectangle (s->display, s->window, &xgcv,
4289 left_x, bottom_y - width, right_x - left_x, width);
177c0ea7 4290
1a578e9b
AC
4291 /* Right. */
4292 if (right_p)
4293 XFillRectangle (s->display, s->window, &xgcv,
4294 right_x - width, top_y, width, bottom_y - top_y);
4295
4296 mac_reset_clipping (s->display, s->window);
4297}
4298
4299
4300/* Draw a box around glyph string S. */
4301
4302static void
4303x_draw_glyph_string_box (s)
4304 struct glyph_string *s;
4305{
4306 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4307 int left_p, right_p;
4308 struct glyph *last_glyph;
4309 Rect clip_rect;
4310
4311 last_x = window_box_right (s->w, s->area);
4312 if (s->row->full_width_p
4313 && !s->w->pseudo_window_p)
4314 {
3f332ef3 4315 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
1a578e9b
AC
4316 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4317 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4318 }
177c0ea7 4319
1a578e9b
AC
4320 /* The glyph that may have a right box line. */
4321 last_glyph = (s->cmp || s->img
4322 ? s->first_glyph
4323 : s->first_glyph + s->nchars - 1);
4324
e0f712ba 4325 width = abs (s->face->box_line_width);
1a578e9b
AC
4326 raised_p = s->face->box == FACE_RAISED_BOX;
4327 left_x = s->x;
e0f712ba 4328 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
1a578e9b
AC
4329 ? last_x - 1
4330 : min (last_x, s->x + s->background_width) - 1));
4331 top_y = s->y;
4332 bottom_y = top_y + s->height - 1;
4333
4334 left_p = (s->first_glyph->left_box_line_p
4335 || (s->hl == DRAW_MOUSE_FACE
4336 && (s->prev == NULL
4337 || s->prev->hl != s->hl)));
4338 right_p = (last_glyph->right_box_line_p
4339 || (s->hl == DRAW_MOUSE_FACE
4340 && (s->next == NULL
4341 || s->next->hl != s->hl)));
177c0ea7 4342
1a578e9b
AC
4343 x_get_glyph_string_clip_rect (s, &clip_rect);
4344
4345 if (s->face->box == FACE_SIMPLE_BOX)
4346 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4347 left_p, right_p, &clip_rect);
4348 else
4349 {
4350 x_setup_relief_colors (s);
4351 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4352 width, raised_p, left_p, right_p, &clip_rect);
4353 }
4354}
4355
4356
4357/* Draw foreground of image glyph string S. */
4358
4359static void
4360x_draw_image_foreground (s)
4361 struct glyph_string *s;
4362{
4363 int x;
4364 int y = s->ybase - image_ascent (s->img, s->face);
4365
4366 /* If first glyph of S has a left box line, start drawing it to the
4367 right of that line. */
4368 if (s->face->box != FACE_NO_BOX
4369 && s->first_glyph->left_box_line_p)
e0f712ba 4370 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
4371 else
4372 x = s->x;
4373
4374 /* If there is a margin around the image, adjust x- and y-position
4375 by that margin. */
83a96b4d
AC
4376 x += s->img->hmargin;
4377 y += s->img->vmargin;
1a578e9b
AC
4378
4379 if (s->img->pixmap)
4380 {
4381#if 0 /* MAC_TODO: image mask */
4382 if (s->img->mask)
4383 {
4384 /* We can't set both a clip mask and use XSetClipRectangles
4385 because the latter also sets a clip mask. We also can't
4386 trust on the shape extension to be available
4387 (XShapeCombineRegion). So, compute the rectangle to draw
4388 manually. */
4389 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4390 | GCFunction);
4391 XGCValues xgcv;
4392 XRectangle clip_rect, image_rect, r;
4393
4394 xgcv.clip_mask = s->img->mask;
4395 xgcv.clip_x_origin = x;
4396 xgcv.clip_y_origin = y;
4397 xgcv.function = GXcopy;
4398 XChangeGC (s->display, s->gc, mask, &xgcv);
177c0ea7 4399
1a578e9b
AC
4400 x_get_glyph_string_clip_rect (s, &clip_rect);
4401 image_rect.x = x;
4402 image_rect.y = y;
4403 image_rect.width = s->img->width;
4404 image_rect.height = s->img->height;
4405 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4406 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4407 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4408 }
4409 else
e0f712ba 4410#endif /* MAC_TODO */
1a578e9b
AC
4411 {
4412 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4413 0, 0, s->img->width, s->img->height, x, y);
177c0ea7 4414
1a578e9b
AC
4415 /* When the image has a mask, we can expect that at
4416 least part of a mouse highlight or a block cursor will
4417 be visible. If the image doesn't have a mask, make
4418 a block cursor visible by drawing a rectangle around
4419 the image. I believe it's looking better if we do
4420 nothing here for mouse-face. */
4421 if (s->hl == DRAW_CURSOR)
534c20b2
KS
4422 {
4423 int r = s->img->relief;
4424 if (r < 0) r = -r;
4425 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4426 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4427 }
1a578e9b
AC
4428 }
4429 }
4430 else
4431 /* Draw a rectangle if image could not be loaded. */
4432 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4433 s->img->width - 1, s->img->height - 1);
4434}
4435
4436
e0f712ba 4437
1a578e9b
AC
4438/* Draw a relief around the image glyph string S. */
4439
4440static void
4441x_draw_image_relief (s)
4442 struct glyph_string *s;
4443{
4444 int x0, y0, x1, y1, thick, raised_p;
4445 Rect r;
4446 int x;
4447 int y = s->ybase - image_ascent (s->img, s->face);
177c0ea7 4448
1a578e9b
AC
4449 /* If first glyph of S has a left box line, start drawing it to the
4450 right of that line. */
4451 if (s->face->box != FACE_NO_BOX
4452 && s->first_glyph->left_box_line_p)
e0f712ba 4453 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
4454 else
4455 x = s->x;
177c0ea7 4456
1a578e9b
AC
4457 /* If there is a margin around the image, adjust x- and y-position
4458 by that margin. */
83a96b4d
AC
4459 x += s->img->hmargin;
4460 y += s->img->vmargin;
177c0ea7 4461
1a578e9b
AC
4462 if (s->hl == DRAW_IMAGE_SUNKEN
4463 || s->hl == DRAW_IMAGE_RAISED)
4464 {
e0f712ba 4465 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1a578e9b
AC
4466 raised_p = s->hl == DRAW_IMAGE_RAISED;
4467 }
4468 else
4469 {
4470 thick = abs (s->img->relief);
4471 raised_p = s->img->relief > 0;
4472 }
177c0ea7 4473
1a578e9b
AC
4474 x0 = x - thick;
4475 y0 = y - thick;
4476 x1 = x + s->img->width + thick - 1;
4477 y1 = y + s->img->height + thick - 1;
177c0ea7 4478
1a578e9b
AC
4479 x_setup_relief_colors (s);
4480 x_get_glyph_string_clip_rect (s, &r);
4481 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4482}
4483
4484
4485/* Draw the foreground of image glyph string S to PIXMAP. */
4486
4487static void
4488x_draw_image_foreground_1 (s, pixmap)
4489 struct glyph_string *s;
4490 Pixmap pixmap;
4491{
4492 int x;
4493 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4494
4495 /* If first glyph of S has a left box line, start drawing it to the
4496 right of that line. */
4497 if (s->face->box != FACE_NO_BOX
4498 && s->first_glyph->left_box_line_p)
e0f712ba 4499 x = abs (s->face->box_line_width);
1a578e9b
AC
4500 else
4501 x = 0;
4502
4503 /* If there is a margin around the image, adjust x- and y-position
4504 by that margin. */
83a96b4d
AC
4505 x += s->img->hmargin;
4506 y += s->img->vmargin;
1a578e9b
AC
4507
4508 if (s->img->pixmap)
4509 {
4510#if 0 /* MAC_TODO: image mask */
4511 if (s->img->mask)
4512 {
4513 /* We can't set both a clip mask and use XSetClipRectangles
4514 because the latter also sets a clip mask. We also can't
4515 trust on the shape extension to be available
4516 (XShapeCombineRegion). So, compute the rectangle to draw
4517 manually. */
4518 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4519 | GCFunction);
4520 XGCValues xgcv;
4521
4522 xgcv.clip_mask = s->img->mask;
4523 xgcv.clip_x_origin = x;
4524 xgcv.clip_y_origin = y;
4525 xgcv.function = GXcopy;
4526 XChangeGC (s->display, s->gc, mask, &xgcv);
4527
4528 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4529 0, 0, s->img->width, s->img->height, x, y);
4530 XSetClipMask (s->display, s->gc, None);
4531 }
4532 else
e0f712ba 4533#endif /* MAC_TODO */
1a578e9b
AC
4534 {
4535 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4536 0, 0, s->img->width, s->img->height, x, y);
177c0ea7 4537
1a578e9b
AC
4538 /* When the image has a mask, we can expect that at
4539 least part of a mouse highlight or a block cursor will
4540 be visible. If the image doesn't have a mask, make
4541 a block cursor visible by drawing a rectangle around
4542 the image. I believe it's looking better if we do
4543 nothing here for mouse-face. */
4544 if (s->hl == DRAW_CURSOR)
534c20b2
KS
4545 {
4546 int r = s->img->relief;
4547 if (r < 0) r = -r;
4548 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4549 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4550 }
1a578e9b
AC
4551 }
4552 }
4553 else
4554 /* Draw a rectangle if image could not be loaded. */
4555 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4556 s->img->width - 1, s->img->height - 1);
4557}
4558
4559
4560/* Draw part of the background of glyph string S. X, Y, W, and H
4561 give the rectangle to draw. */
4562
4563static void
4564x_draw_glyph_string_bg_rect (s, x, y, w, h)
4565 struct glyph_string *s;
4566 int x, y, w, h;
4567{
4568#if 0 /* MAC_TODO: stipple */
4569 if (s->stippled_p)
4570 {
4571 /* Fill background with a stipple pattern. */
4572 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4573 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4574 XSetFillStyle (s->display, s->gc, FillSolid);
4575 }
4576 else
e0f712ba 4577#endif /* MAC_TODO */
1a578e9b
AC
4578 x_clear_glyph_string_rect (s, x, y, w, h);
4579}
4580
4581
177c0ea7 4582/* Draw image glyph string S.
1a578e9b
AC
4583
4584 s->y
4585 s->x +-------------------------
4586 | s->face->box
4587 |
4588 | +-------------------------
83a96b4d 4589 | | s->img->vmargin
1a578e9b
AC
4590 | |
4591 | | +-------------------
4592 | | | the image
4593
4594 */
4595
4596static void
4597x_draw_image_glyph_string (s)
4598 struct glyph_string *s;
4599{
4600 int x, y;
e0f712ba
AC
4601 int box_line_hwidth = abs (s->face->box_line_width);
4602 int box_line_vwidth = max (s->face->box_line_width, 0);
1a578e9b
AC
4603 int height;
4604 Pixmap pixmap = 0;
4605
e0f712ba 4606 height = s->height - 2 * box_line_vwidth;
1a578e9b
AC
4607
4608 /* Fill background with face under the image. Do it only if row is
4609 taller than image or if image has a clip mask to reduce
4610 flickering. */
4611 s->stippled_p = s->face->stipple != 0;
4612 if (height > s->img->height
83a96b4d 4613 || s->img->hmargin
e0f712ba
AC
4614 || s->img->vmargin
4615#if 0 /* TODO: image mask */
1a578e9b
AC
4616 || s->img->mask
4617#endif
4618 || s->img->pixmap == 0
4619 || s->width != s->background_width)
4620 {
e0f712ba
AC
4621 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4622 x = s->x + box_line_hwidth;
1a578e9b
AC
4623 else
4624 x = s->x;
177c0ea7 4625
e0f712ba
AC
4626 y = s->y + box_line_vwidth;
4627#if 0 /* TODO: image mask */
1a578e9b
AC
4628 if (s->img->mask)
4629 {
e0f712ba
AC
4630 /* Create a pixmap as large as the glyph string. Fill it
4631 with the background color. Copy the image to it, using
4632 its mask. Copy the temporary pixmap to the display. */
1a578e9b
AC
4633 Screen *screen = FRAME_X_SCREEN (s->f);
4634 int depth = DefaultDepthOfScreen (screen);
4635
4636 /* Create a pixmap as large as the glyph string. */
4637 pixmap = XCreatePixmap (s->display, s->window,
4638 s->background_width,
4639 s->height, depth);
177c0ea7 4640
1a578e9b
AC
4641 /* Don't clip in the following because we're working on the
4642 pixmap. */
4643 XSetClipMask (s->display, s->gc, None);
4644
4645 /* Fill the pixmap with the background color/stipple. */
4646 if (s->stippled_p)
4647 {
4648 /* Fill background with a stipple pattern. */
4649 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4650 XFillRectangle (s->display, pixmap, s->gc,
4651 0, 0, s->background_width, s->height);
4652 XSetFillStyle (s->display, s->gc, FillSolid);
4653 }
4654 else
4655 {
4656 XGCValues xgcv;
4657 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4658 &xgcv);
4659 XSetForeground (s->display, s->gc, xgcv.background);
4660 XFillRectangle (s->display, pixmap, s->gc,
4661 0, 0, s->background_width, s->height);
4662 XSetForeground (s->display, s->gc, xgcv.foreground);
4663 }
4664 }
4665 else
4666#endif
1a578e9b 4667 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
177c0ea7 4668
1a578e9b
AC
4669 s->background_filled_p = 1;
4670 }
4671
4672 /* Draw the foreground. */
4673 if (pixmap != 0)
4674 {
4675 x_draw_image_foreground_1 (s, pixmap);
4676 x_set_glyph_string_clipping (s);
4677 mac_copy_area (s->display, pixmap, s->window, s->gc,
4678 0, 0, s->background_width, s->height, s->x, s->y);
e0f712ba 4679 mac_reset_clipping (s->display, s->window);
1a578e9b
AC
4680 XFreePixmap (s->display, pixmap);
4681 }
4682 else
4683 x_draw_image_foreground (s);
4684
4685 /* If we must draw a relief around the image, do it. */
4686 if (s->img->relief
4687 || s->hl == DRAW_IMAGE_RAISED
4688 || s->hl == DRAW_IMAGE_SUNKEN)
4689 x_draw_image_relief (s);
4690}
4691
4692
4693/* Draw stretch glyph string S. */
4694
4695static void
4696x_draw_stretch_glyph_string (s)
4697 struct glyph_string *s;
4698{
4699 xassert (s->first_glyph->type == STRETCH_GLYPH);
4700 s->stippled_p = s->face->stipple != 0;
4701
4702 if (s->hl == DRAW_CURSOR
4703 && !x_stretch_cursor_p)
4704 {
4705 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4706 as wide as the stretch glyph. */
4707 int width = min (CANON_X_UNIT (s->f), s->background_width);
4708
4709 /* Draw cursor. */
4710 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4711
4712 /* Clear rest using the GC of the original non-cursor face. */
4713 if (width < s->background_width)
4714 {
4715 GC gc = s->face->gc;
4716 int x = s->x + width, y = s->y;
4717 int w = s->background_width - width, h = s->height;
4718 Rect r;
4719
e0f712ba
AC
4720 if (s->row->mouse_face_p
4721 && cursor_in_mouse_face_p (s->w))
4722 {
4723 x_set_mouse_face_gc (s);
4724 gc = s->gc;
4725 }
4726 else
4727 gc = s->face->gc;
177c0ea7 4728
1a578e9b
AC
4729 x_get_glyph_string_clip_rect (s, &r);
4730 mac_set_clip_rectangle (s->display, s->window, &r);
4731
4732#if 0 /* MAC_TODO: stipple */
4733 if (s->face->stipple)
4734 {
4735 /* Fill background with a stipple pattern. */
4736 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4737 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4738 XSetFillStyle (s->display, gc, FillSolid);
4739 }
4740 else
e0f712ba 4741#endif /* MAC_TODO */
1a578e9b
AC
4742 {
4743 XGCValues xgcv;
4744 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4745 XSetForeground (s->display, gc, xgcv.background);
4746 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4747 XSetForeground (s->display, gc, xgcv.foreground);
4748 }
e0f712ba
AC
4749
4750 mac_reset_clipping (s->display, s->window);
1a578e9b
AC
4751 }
4752 }
e0f712ba 4753 else if (!s->background_filled_p)
1a578e9b
AC
4754 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4755 s->height);
177c0ea7 4756
1a578e9b
AC
4757 s->background_filled_p = 1;
4758}
4759
4760
4761/* Draw glyph string S. */
4762
4763static void
4764x_draw_glyph_string (s)
4765 struct glyph_string *s;
4766{
e0f712ba
AC
4767 int relief_drawn_p = 0;
4768
1a578e9b
AC
4769 /* If S draws into the background of its successor, draw the
4770 background of the successor first so that S can draw into it.
4771 This makes S->next use XDrawString instead of XDrawImageString. */
4772 if (s->next && s->right_overhang && !s->for_overlaps_p)
4773 {
4774 xassert (s->next->img == NULL);
4775 x_set_glyph_string_gc (s->next);
4776 x_set_glyph_string_clipping (s->next);
4777 x_draw_glyph_string_background (s->next, 1);
e0f712ba 4778
1a578e9b
AC
4779 }
4780
4781 /* Set up S->gc, set clipping and draw S. */
4782 x_set_glyph_string_gc (s);
e0f712ba
AC
4783
4784 /* Draw relief (if any) in advance for char/composition so that the
4785 glyph string can be drawn over it. */
4786 if (!s->for_overlaps_p
4787 && s->face->box != FACE_NO_BOX
4788 && (s->first_glyph->type == CHAR_GLYPH
4789 || s->first_glyph->type == COMPOSITE_GLYPH))
4790
4791 {
4792 x_set_glyph_string_clipping (s);
4793 x_draw_glyph_string_background (s, 1);
4794 x_draw_glyph_string_box (s);
4795 x_set_glyph_string_clipping (s);
4796 relief_drawn_p = 1;
4797 }
4798 else
4799 x_set_glyph_string_clipping (s);
1a578e9b
AC
4800
4801 switch (s->first_glyph->type)
4802 {
4803 case IMAGE_GLYPH:
4804 x_draw_image_glyph_string (s);
4805 break;
4806
4807 case STRETCH_GLYPH:
4808 x_draw_stretch_glyph_string (s);
4809 break;
4810
4811 case CHAR_GLYPH:
4812 if (s->for_overlaps_p)
4813 s->background_filled_p = 1;
4814 else
e0f712ba 4815 x_draw_glyph_string_background (s, 0);
1a578e9b
AC
4816 x_draw_glyph_string_foreground (s);
4817 break;
4818
4819 case COMPOSITE_GLYPH:
4820 if (s->for_overlaps_p || s->gidx > 0)
4821 s->background_filled_p = 1;
4822 else
4823 x_draw_glyph_string_background (s, 1);
4824 x_draw_composite_glyph_string_foreground (s);
4825 break;
4826
4827 default:
4828 abort ();
4829 }
4830
4831 if (!s->for_overlaps_p)
4832 {
4833 /* Draw underline. */
4834 if (s->face->underline_p)
4835 {
4836 unsigned long h = 1;
4837 unsigned long dy = s->height - h;
177c0ea7 4838
1a578e9b
AC
4839 if (s->face->underline_defaulted_p)
4840 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4841 s->width, h);
4842 else
4843 {
4844 XGCValues xgcv;
4845 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4846 XSetForeground (s->display, s->gc, s->face->underline_color);
4847 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4848 s->width, h);
4849 XSetForeground (s->display, s->gc, xgcv.foreground);
4850 }
4851 }
4852
4853 /* Draw overline. */
4854 if (s->face->overline_p)
4855 {
4856 unsigned long dy = 0, h = 1;
4857
4858 if (s->face->overline_color_defaulted_p)
4859 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4860 s->width, h);
4861 else
4862 {
4863 XGCValues xgcv;
4864 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4865 XSetForeground (s->display, s->gc, s->face->overline_color);
4866 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4867 s->width, h);
4868 XSetForeground (s->display, s->gc, xgcv.foreground);
4869 }
4870 }
177c0ea7 4871
1a578e9b
AC
4872 /* Draw strike-through. */
4873 if (s->face->strike_through_p)
4874 {
4875 unsigned long h = 1;
4876 unsigned long dy = (s->height - h) / 2;
4877
4878 if (s->face->strike_through_color_defaulted_p)
4879 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4880 s->width, h);
4881 else
4882 {
4883 XGCValues xgcv;
4884 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4885 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4886 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4887 s->width, h);
4888 XSetForeground (s->display, s->gc, xgcv.foreground);
4889 }
4890 }
177c0ea7 4891
1a578e9b 4892 /* Draw relief. */
e0f712ba
AC
4893 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4894 x_draw_glyph_string_box (s);
1a578e9b 4895 }
e0f712ba 4896
1a578e9b
AC
4897 /* Reset clipping. */
4898 mac_reset_clipping (s->display, s->window);
4899}
4900
4901
4902static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4903 struct face **, int));
4904
4905
4906/* Fill glyph string S with composition components specified by S->cmp.
177c0ea7 4907
1a578e9b
AC
4908 FACES is an array of faces for all components of this composition.
4909 S->gidx is the index of the first component for S.
4910 OVERLAPS_P non-zero means S should draw the foreground only, and
4911 use its physical height for clipping.
4912
4913 Value is the index of a component not in S. */
4914
4915static int
4916x_fill_composite_glyph_string (s, faces, overlaps_p)
4917 struct glyph_string *s;
4918 struct face **faces;
4919 int overlaps_p;
4920{
4921 int i;
4922
4923 xassert (s);
4924
4925 s->for_overlaps_p = overlaps_p;
e0f712ba 4926
1a578e9b
AC
4927 s->face = faces[s->gidx];
4928 s->font = s->face->font;
4929 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4930
4931 /* For all glyphs of this composition, starting at the offset
4932 S->gidx, until we reach the end of the definition or encounter a
4933 glyph that requires the different face, add it to S. */
4934 ++s->nchars;
4935 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4936 ++s->nchars;
4937
4938 /* All glyph strings for the same composition has the same width,
4939 i.e. the width set for the first component of the composition. */
4940
4941 s->width = s->first_glyph->pixel_width;
4942
4943 /* If the specified font could not be loaded, use the frame's
4944 default font, but record the fact that we couldn't load it in
4945 the glyph string so that we can draw rectangles for the
4946 characters of the glyph string. */
4947 if (s->font == NULL)
4948 {
4949 s->font_not_found_p = 1;
4950 s->font = FRAME_FONT (s->f);
4951 }
4952
4953 /* Adjust base line for subscript/superscript text. */
4954 s->ybase += s->first_glyph->voffset;
177c0ea7 4955
1a578e9b
AC
4956 xassert (s->face && s->face->gc);
4957
4958 /* This glyph string must always be drawn with 16-bit functions. */
4959 s->two_byte_p = 1;
4960
4961 return s->gidx + s->nchars;
4962}
4963
4964
4965/* Fill glyph string S from a sequence of character glyphs.
177c0ea7 4966
1a578e9b
AC
4967 FACE_ID is the face id of the string. START is the index of the
4968 first glyph to consider, END is the index of the last + 1.
4969 OVERLAPS_P non-zero means S should draw the foreground only, and
4970 use its physical height for clipping.
4971
4972 Value is the index of the first glyph not in S. */
4973
4974static int
4975x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4976 struct glyph_string *s;
4977 int face_id;
4978 int start, end, overlaps_p;
4979{
4980 struct glyph *glyph, *last;
4981 int voffset;
4982 int glyph_not_available_p;
e0f712ba 4983
1a578e9b
AC
4984 xassert (s->f == XFRAME (s->w->frame));
4985 xassert (s->nchars == 0);
4986 xassert (start >= 0 && end > start);
4987
e0f712ba 4988 s->for_overlaps_p = overlaps_p;
1a578e9b
AC
4989 glyph = s->row->glyphs[s->area] + start;
4990 last = s->row->glyphs[s->area] + end;
4991 voffset = glyph->voffset;
e0f712ba 4992
1a578e9b
AC
4993 glyph_not_available_p = glyph->glyph_not_available_p;
4994
4995 while (glyph < last
4996 && glyph->type == CHAR_GLYPH
4997 && glyph->voffset == voffset
4998 /* Same face id implies same font, nowadays. */
4999 && glyph->face_id == face_id
e0f712ba 5000 && glyph->glyph_not_available_p == glyph_not_available_p)
1a578e9b
AC
5001 {
5002 int two_byte_p;
5003
5004 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
5005 s->char2b + s->nchars,
e0f712ba 5006 &two_byte_p);
1a578e9b
AC
5007 s->two_byte_p = two_byte_p;
5008 ++s->nchars;
5009 xassert (s->nchars <= end - start);
5010 s->width += glyph->pixel_width;
5011 ++glyph;
5012 }
5013
5014 s->font = s->face->font;
5015 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
177c0ea7 5016
1a578e9b
AC
5017 /* If the specified font could not be loaded, use the frame's font,
5018 but record the fact that we couldn't load it in
5019 S->font_not_found_p so that we can draw rectangles for the
5020 characters of the glyph string. */
5021 if (s->font == NULL || glyph_not_available_p)
5022 {
5023 s->font_not_found_p = 1;
5024 s->font = FRAME_FONT (s->f);
5025 }
5026
5027 /* Adjust base line for subscript/superscript text. */
5028 s->ybase += voffset;
177c0ea7 5029
1a578e9b
AC
5030 xassert (s->face && s->face->gc);
5031 return glyph - s->row->glyphs[s->area];
5032}
5033
5034
5035/* Fill glyph string S from image glyph S->first_glyph. */
5036
5037static void
5038x_fill_image_glyph_string (s)
5039 struct glyph_string *s;
5040{
5041 xassert (s->first_glyph->type == IMAGE_GLYPH);
5042 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5043 xassert (s->img);
5044 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5045 s->font = s->face->font;
5046 s->width = s->first_glyph->pixel_width;
177c0ea7 5047
1a578e9b
AC
5048 /* Adjust base line for subscript/superscript text. */
5049 s->ybase += s->first_glyph->voffset;
5050}
5051
5052
5053/* Fill glyph string S from a sequence of stretch glyphs.
5054
5055 ROW is the glyph row in which the glyphs are found, AREA is the
5056 area within the row. START is the index of the first glyph to
5057 consider, END is the index of the last + 1.
5058
5059 Value is the index of the first glyph not in S. */
5060
5061static int
5062x_fill_stretch_glyph_string (s, row, area, start, end)
5063 struct glyph_string *s;
5064 struct glyph_row *row;
5065 enum glyph_row_area area;
5066 int start, end;
5067{
5068 struct glyph *glyph, *last;
5069 int voffset, face_id;
177c0ea7 5070
1a578e9b 5071 xassert (s->first_glyph->type == STRETCH_GLYPH);
177c0ea7 5072
1a578e9b
AC
5073 glyph = s->row->glyphs[s->area] + start;
5074 last = s->row->glyphs[s->area] + end;
5075 face_id = glyph->face_id;
5076 s->face = FACE_FROM_ID (s->f, face_id);
5077 s->font = s->face->font;
5078 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5079 s->width = glyph->pixel_width;
5080 voffset = glyph->voffset;
5081
5082 for (++glyph;
5083 (glyph < last
5084 && glyph->type == STRETCH_GLYPH
5085 && glyph->voffset == voffset
5086 && glyph->face_id == face_id);
5087 ++glyph)
5088 s->width += glyph->pixel_width;
177c0ea7 5089
1a578e9b
AC
5090 /* Adjust base line for subscript/superscript text. */
5091 s->ybase += voffset;
5092
e0f712ba 5093 xassert (s->face);
1a578e9b
AC
5094 return glyph - s->row->glyphs[s->area];
5095}
5096
5097
5098/* Initialize glyph string S. CHAR2B is a suitably allocated vector
5099 of XChar2b structures for S; it can't be allocated in
5100 x_init_glyph_string because it must be allocated via `alloca'. W
5101 is the window on which S is drawn. ROW and AREA are the glyph row
5102 and area within the row from which S is constructed. START is the
5103 index of the first glyph structure covered by S. HL is a
5104 face-override for drawing S. */
177c0ea7 5105
1a578e9b
AC
5106static void
5107x_init_glyph_string (s, char2b, w, row, area, start, hl)
5108 struct glyph_string *s;
5109 XChar2b *char2b;
5110 struct window *w;
5111 struct glyph_row *row;
5112 enum glyph_row_area area;
5113 int start;
5114 enum draw_glyphs_face hl;
5115{
5116 bzero (s, sizeof *s);
5117 s->w = w;
5118 s->f = XFRAME (w->frame);
5119 s->display = FRAME_MAC_DISPLAY (s->f);
5120 s->window = FRAME_MAC_WINDOW (s->f);
5121 s->char2b = char2b;
5122 s->hl = hl;
5123 s->row = row;
5124 s->area = area;
5125 s->first_glyph = row->glyphs[area] + start;
5126 s->height = row->height;
5127 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5128
5129 /* Display the internal border below the tool-bar window. */
5130 if (s->w == XWINDOW (s->f->tool_bar_window))
5131 s->y -= s->f->output_data.mac->internal_border_width;
177c0ea7 5132
1a578e9b
AC
5133 s->ybase = s->y + row->ascent;
5134}
5135
5136
5137/* Set background width of glyph string S. START is the index of the
5138 first glyph following S. LAST_X is the right-most x-position + 1
5139 in the drawing area. */
5140
5141static INLINE void
5142x_set_glyph_string_background_width (s, start, last_x)
5143 struct glyph_string *s;
5144 int start;
5145 int last_x;
5146{
5147 /* If the face of this glyph string has to be drawn to the end of
5148 the drawing area, set S->extends_to_end_of_line_p. */
5149 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
177c0ea7 5150
1a578e9b 5151 if (start == s->row->used[s->area]
e0f712ba
AC
5152 && s->area == TEXT_AREA
5153 && ((s->hl == DRAW_NORMAL_TEXT
5154 && (s->row->fill_line_p
5155 || s->face->background != default_face->background
5156 || s->face->stipple != default_face->stipple
5157 || s->row->mouse_face_p))
5158 || s->hl == DRAW_MOUSE_FACE
5159 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5160 && s->row->fill_line_p)))
1a578e9b 5161 s->extends_to_end_of_line_p = 1;
177c0ea7 5162
1a578e9b
AC
5163 /* If S extends its face to the end of the line, set its
5164 background_width to the distance to the right edge of the drawing
5165 area. */
5166 if (s->extends_to_end_of_line_p)
5167 s->background_width = last_x - s->x + 1;
5168 else
5169 s->background_width = s->width;
5170}
5171
5172
5173/* Add a glyph string for a stretch glyph to the list of strings
5174 between HEAD and TAIL. START is the index of the stretch glyph in
5175 row area AREA of glyph row ROW. END is the index of the last glyph
5176 in that glyph row area. X is the current output position assigned
5177 to the new glyph string constructed. HL overrides that face of the
5178 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5179 is the right-most x-position of the drawing area. */
5180
5181/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5182 and below -- keep them on one line. */
5183#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5184 do \
5185 { \
5186 s = (struct glyph_string *) alloca (sizeof *s); \
5187 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5188 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5189 x_append_glyph_string (&HEAD, &TAIL, s); \
5190 s->x = (X); \
5191 } \
5192 while (0)
5193
5194
5195/* Add a glyph string for an image glyph to the list of strings
5196 between HEAD and TAIL. START is the index of the image glyph in
5197 row area AREA of glyph row ROW. END is the index of the last glyph
5198 in that glyph row area. X is the current output position assigned
5199 to the new glyph string constructed. HL overrides that face of the
5200 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5201 is the right-most x-position of the drawing area. */
5202
5203#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5204 do \
5205 { \
5206 s = (struct glyph_string *) alloca (sizeof *s); \
5207 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5208 x_fill_image_glyph_string (s); \
5209 x_append_glyph_string (&HEAD, &TAIL, s); \
5210 ++START; \
5211 s->x = (X); \
5212 } \
5213 while (0)
5214
5215
5216/* Add a glyph string for a sequence of character glyphs to the list
5217 of strings between HEAD and TAIL. START is the index of the first
5218 glyph in row area AREA of glyph row ROW that is part of the new
5219 glyph string. END is the index of the last glyph in that glyph row
5220 area. X is the current output position assigned to the new glyph
5221 string constructed. HL overrides that face of the glyph; e.g. it
5222 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5223 right-most x-position of the drawing area. */
5224
5225#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5226 do \
5227 { \
5228 int c, face_id; \
5229 XChar2b *char2b; \
5230 \
5231 c = (ROW)->glyphs[AREA][START].u.ch; \
5232 face_id = (ROW)->glyphs[AREA][START].face_id; \
5233 \
5234 s = (struct glyph_string *) alloca (sizeof *s); \
5235 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5236 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5237 x_append_glyph_string (&HEAD, &TAIL, s); \
5238 s->x = (X); \
5239 START = x_fill_glyph_string (s, face_id, START, END, \
5240 OVERLAPS_P); \
5241 } \
5242 while (0)
177c0ea7 5243
1a578e9b
AC
5244
5245/* Add a glyph string for a composite sequence to the list of strings
5246 between HEAD and TAIL. START is the index of the first glyph in
5247 row area AREA of glyph row ROW that is part of the new glyph
5248 string. END is the index of the last glyph in that glyph row area.
5249 X is the current output position assigned to the new glyph string
5250 constructed. HL overrides that face of the glyph; e.g. it is
5251 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5252 x-position of the drawing area. */
5253
5254#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5255 do { \
5256 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5257 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5258 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5259 struct composition *cmp = composition_table[cmp_id]; \
5260 int glyph_len = cmp->glyph_len; \
5261 XChar2b *char2b; \
5262 struct face **faces; \
5263 struct glyph_string *first_s = NULL; \
5264 int n; \
5265 \
5266 base_face = base_face->ascii_face; \
5267 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5268 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5269 /* At first, fill in `char2b' and `faces'. */ \
5270 for (n = 0; n < glyph_len; n++) \
5271 { \
5272 int c = COMPOSITION_GLYPH (cmp, n); \
5273 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5274 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5275 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5276 this_face_id, char2b + n, 1); \
5277 } \
5278 \
5279 /* Make glyph_strings for each glyph sequence that is drawable by \
5280 the same face, and append them to HEAD/TAIL. */ \
5281 for (n = 0; n < cmp->glyph_len;) \
5282 { \
5283 s = (struct glyph_string *) alloca (sizeof *s); \
5284 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5285 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5286 s->cmp = cmp; \
5287 s->gidx = n; \
5288 s->x = (X); \
5289 \
5290 if (n == 0) \
5291 first_s = s; \
5292 \
5293 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5294 } \
5295 \
5296 ++START; \
5297 s = first_s; \
5298 } while (0)
177c0ea7 5299
1a578e9b
AC
5300
5301/* Build a list of glyph strings between HEAD and TAIL for the glyphs
5302 of AREA of glyph row ROW on window W between indices START and END.
5303 HL overrides the face for drawing glyph strings, e.g. it is
5304 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5305 x-positions of the drawing area.
5306
5307 This is an ugly monster macro construct because we must use alloca
5308 to allocate glyph strings (because x_draw_glyphs can be called
5309 asynchronously). */
5310
5311#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5312 do \
5313 { \
5314 HEAD = TAIL = NULL; \
5315 while (START < END) \
5316 { \
5317 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5318 switch (first_glyph->type) \
5319 { \
5320 case CHAR_GLYPH: \
5321 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5322 TAIL, HL, X, LAST_X, \
5323 OVERLAPS_P); \
5324 break; \
5325 \
5326 case COMPOSITE_GLYPH: \
5327 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5328 HEAD, TAIL, HL, X, LAST_X,\
5329 OVERLAPS_P); \
5330 break; \
5331 \
5332 case STRETCH_GLYPH: \
5333 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5334 HEAD, TAIL, HL, X, LAST_X); \
5335 break; \
5336 \
5337 case IMAGE_GLYPH: \
5338 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5339 TAIL, HL, X, LAST_X); \
5340 break; \
5341 \
5342 default: \
5343 abort (); \
5344 } \
5345 \
5346 x_set_glyph_string_background_width (s, START, LAST_X); \
5347 (X) += s->width; \
5348 } \
5349 } \
5350 while (0)
5351
5352
5353/* Draw glyphs between START and END in AREA of ROW on window W,
5354 starting at x-position X. X is relative to AREA in W. HL is a
5355 face-override with the following meaning:
5356
5357 DRAW_NORMAL_TEXT draw normally
5358 DRAW_CURSOR draw in cursor face
5359 DRAW_MOUSE_FACE draw in mouse face.
5360 DRAW_INVERSE_VIDEO draw in mode line face
5361 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5362 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5363
1a578e9b
AC
5364 If OVERLAPS_P is non-zero, draw only the foreground of characters
5365 and clip to the physical height of ROW.
5366
5367 Value is the x-position reached, relative to AREA of W. */
177c0ea7 5368
1a578e9b 5369static int
e0f712ba 5370x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
1a578e9b
AC
5371 struct window *w;
5372 int x;
5373 struct glyph_row *row;
5374 enum glyph_row_area area;
5375 int start, end;
5376 enum draw_glyphs_face hl;
1a578e9b
AC
5377 int overlaps_p;
5378{
5379 struct glyph_string *head, *tail;
5380 struct glyph_string *s;
5381 int last_x, area_width;
5382 int x_reached;
5383 int i, j;
5384
5385 /* Let's rather be paranoid than getting a SEGV. */
1a578e9b 5386 end = min (end, row->used[area]);
e0f712ba
AC
5387 start = max (0, start);
5388 start = min (end, start);
1a578e9b
AC
5389
5390 /* Translate X to frame coordinates. Set last_x to the right
5391 end of the drawing area. */
5392 if (row->full_width_p)
5393 {
5394 /* X is relative to the left edge of W, without scroll bars
3f332ef3 5395 or fringes. */
e0f712ba 5396 struct frame *f = XFRAME (WINDOW_FRAME (w));
1a578e9b
AC
5397 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5398
5399 x += window_left_x;
5400 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5401 last_x = window_left_x + area_width;
5402
5403 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5404 {
5405 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5406 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5407 last_x += width;
5408 else
5409 x -= width;
5410 }
5411
5412 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5413 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5414 }
5415 else
5416 {
5417 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5418 area_width = window_box_width (w, area);
5419 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5420 }
5421
5422 /* Build a doubly-linked list of glyph_string structures between
5423 head and tail from what we have to draw. Note that the macro
5424 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5425 the reason we use a separate variable `i'. */
5426 i = start;
5427 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
e0f712ba 5428 overlaps_p);
1a578e9b
AC
5429 if (tail)
5430 x_reached = tail->x + tail->background_width;
5431 else
5432 x_reached = x;
5433
5434 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5435 the row, redraw some glyphs in front or following the glyph
5436 strings built above. */
e0f712ba 5437 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
1a578e9b
AC
5438 {
5439 int dummy_x = 0;
5440 struct glyph_string *h, *t;
5441
5442 /* Compute overhangs for all glyph strings. */
5443 for (s = head; s; s = s->next)
5444 x_compute_glyph_string_overhangs (s);
5445
5446 /* Prepend glyph strings for glyphs in front of the first glyph
5447 string that are overwritten because of the first glyph
5448 string's left overhang. The background of all strings
177c0ea7 5449 prepended must be drawn because the first glyph string
1a578e9b
AC
5450 draws over it. */
5451 i = x_left_overwritten (head);
5452 if (i >= 0)
5453 {
5454 j = i;
5455 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5456 DRAW_NORMAL_TEXT, dummy_x, last_x,
e0f712ba 5457 overlaps_p);
1a578e9b 5458 start = i;
1a578e9b
AC
5459 x_compute_overhangs_and_x (t, head->x, 1);
5460 x_prepend_glyph_string_lists (&head, &tail, h, t);
5461 }
5462
5463 /* Prepend glyph strings for glyphs in front of the first glyph
5464 string that overwrite that glyph string because of their
5465 right overhang. For these strings, only the foreground must
5466 be drawn, because it draws over the glyph string at `head'.
5467 The background must not be drawn because this would overwrite
5468 right overhangs of preceding glyphs for which no glyph
5469 strings exist. */
5470 i = x_left_overwriting (head);
5471 if (i >= 0)
5472 {
5473 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5474 DRAW_NORMAL_TEXT, dummy_x, last_x,
e0f712ba 5475 overlaps_p);
1a578e9b
AC
5476 for (s = h; s; s = s->next)
5477 s->background_filled_p = 1;
1a578e9b
AC
5478 x_compute_overhangs_and_x (t, head->x, 1);
5479 x_prepend_glyph_string_lists (&head, &tail, h, t);
5480 }
5481
5482 /* Append glyphs strings for glyphs following the last glyph
5483 string tail that are overwritten by tail. The background of
5484 these strings has to be drawn because tail's foreground draws
5485 over it. */
5486 i = x_right_overwritten (tail);
5487 if (i >= 0)
5488 {
5489 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5490 DRAW_NORMAL_TEXT, x, last_x,
e0f712ba 5491 overlaps_p);
1a578e9b
AC
5492 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5493 x_append_glyph_string_lists (&head, &tail, h, t);
1a578e9b
AC
5494 }
5495
5496 /* Append glyph strings for glyphs following the last glyph
5497 string tail that overwrite tail. The foreground of such
5498 glyphs has to be drawn because it writes into the background
5499 of tail. The background must not be drawn because it could
5500 paint over the foreground of following glyphs. */
5501 i = x_right_overwriting (tail);
5502 if (i >= 0)
5503 {
5504 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5505 DRAW_NORMAL_TEXT, x, last_x,
e0f712ba 5506 overlaps_p);
1a578e9b
AC
5507 for (s = h; s; s = s->next)
5508 s->background_filled_p = 1;
5509 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5510 x_append_glyph_string_lists (&head, &tail, h, t);
1a578e9b
AC
5511 }
5512 }
5513
5514 /* Draw all strings. */
5515 for (s = head; s; s = s->next)
5516 x_draw_glyph_string (s);
5517
e0f712ba
AC
5518 if (area == TEXT_AREA
5519 && !row->full_width_p
5520 /* When drawing overlapping rows, only the glyph strings'
5521 foreground is drawn, which doesn't erase a cursor
5522 completely. */
5523 && !overlaps_p)
5524 {
5525 int x0 = head ? head->x : x;
5526 int x1 = tail ? tail->x + tail->background_width : x;
177c0ea7 5527
e0f712ba
AC
5528 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5529 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
177c0ea7 5530
e0f712ba
AC
5531 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5532 {
5533 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5534 x0 -= left_area_width;
5535 x1 -= left_area_width;
5536 }
5537
5538 notice_overwritten_cursor (w, area, x0, x1,
5539 row->y, MATRIX_ROW_BOTTOM_Y (row));
5540 }
5541
1a578e9b
AC
5542 /* Value is the x-position up to which drawn, relative to AREA of W.
5543 This doesn't include parts drawn because of overhangs. */
5544 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5545 if (!row->full_width_p)
5546 {
5547 if (area > LEFT_MARGIN_AREA)
5548 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5549 if (area > TEXT_AREA)
5550 x_reached -= window_box_width (w, TEXT_AREA);
5551 }
e0f712ba 5552
1a578e9b
AC
5553 return x_reached;
5554}
5555
5556
5557/* Fix the display of area AREA of overlapping row ROW in window W. */
5558
e0f712ba 5559static void
1a578e9b
AC
5560x_fix_overlapping_area (w, row, area)
5561 struct window *w;
5562 struct glyph_row *row;
5563 enum glyph_row_area area;
5564{
5565 int i, x;
177c0ea7 5566
1a578e9b 5567 BLOCK_INPUT;
177c0ea7 5568
1a578e9b
AC
5569 if (area == LEFT_MARGIN_AREA)
5570 x = 0;
5571 else if (area == TEXT_AREA)
5572 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5573 else
5574 x = (window_box_width (w, LEFT_MARGIN_AREA)
5575 + window_box_width (w, TEXT_AREA));
5576
5577 for (i = 0; i < row->used[area];)
5578 {
5579 if (row->glyphs[area][i].overlaps_vertically_p)
5580 {
5581 int start = i, start_x = x;
5582
5583 do
5584 {
5585 x += row->glyphs[area][i].pixel_width;
5586 ++i;
5587 }
5588 while (i < row->used[area]
5589 && row->glyphs[area][i].overlaps_vertically_p);
5590
5591 x_draw_glyphs (w, start_x, row, area, start, i,
e0f712ba 5592 DRAW_NORMAL_TEXT, 1);
1a578e9b
AC
5593 }
5594 else
5595 {
5596 x += row->glyphs[area][i].pixel_width;
5597 ++i;
5598 }
5599 }
177c0ea7 5600
1a578e9b
AC
5601 UNBLOCK_INPUT;
5602}
5603
5604
5605/* Output LEN glyphs starting at START at the nominal cursor position.
5606 Advance the nominal cursor over the text. The global variable
5607 updated_window contains the window being updated, updated_row is
5608 the glyph row being updated, and updated_area is the area of that
5609 row being updated. */
5610
e0f712ba 5611static void
1a578e9b
AC
5612x_write_glyphs (start, len)
5613 struct glyph *start;
5614 int len;
5615{
e0f712ba 5616 int x, hpos;
1a578e9b
AC
5617
5618 xassert (updated_window && updated_row);
5619 BLOCK_INPUT;
177c0ea7 5620
1a578e9b
AC
5621 /* Write glyphs. */
5622
5623 hpos = start - updated_row->glyphs[updated_area];
5624 x = x_draw_glyphs (updated_window, output_cursor.x,
5625 updated_row, updated_area,
5626 hpos, hpos + len,
e0f712ba 5627 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
5628
5629 UNBLOCK_INPUT;
177c0ea7 5630
1a578e9b
AC
5631 /* Advance the output cursor. */
5632 output_cursor.hpos += len;
5633 output_cursor.x = x;
5634}
5635
5636
5637/* Insert LEN glyphs from START at the nominal cursor position. */
5638
e0f712ba 5639static void
1a578e9b
AC
5640x_insert_glyphs (start, len)
5641 struct glyph *start;
5642 register int len;
5643{
5644 struct frame *f;
5645 struct window *w;
5646 int line_height, shift_by_width, shifted_region_width;
5647 struct glyph_row *row;
5648 struct glyph *glyph;
e0f712ba 5649 int frame_x, frame_y, hpos;
1a578e9b
AC
5650
5651 xassert (updated_window && updated_row);
5652 BLOCK_INPUT;
5653 w = updated_window;
5654 f = XFRAME (WINDOW_FRAME (w));
5655
5656 /* Get the height of the line we are in. */
5657 row = updated_row;
5658 line_height = row->height;
5659
5660 /* Get the width of the glyphs to insert. */
5661 shift_by_width = 0;
5662 for (glyph = start; glyph < start + len; ++glyph)
5663 shift_by_width += glyph->pixel_width;
5664
5665 /* Get the width of the region to shift right. */
5666 shifted_region_width = (window_box_width (w, updated_area)
5667 - output_cursor.x
5668 - shift_by_width);
5669
5670 /* Shift right. */
e0f712ba 5671 frame_x = window_box_left (w, updated_area) + output_cursor.x;
1a578e9b
AC
5672 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5673
5674 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5675 f->output_data.mac->normal_gc,
5676 frame_x, frame_y,
5677 shifted_region_width, line_height,
5678 frame_x + shift_by_width, frame_y);
5679
5680 /* Write the glyphs. */
5681 hpos = start - row->glyphs[updated_area];
5682 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
e0f712ba
AC
5683 DRAW_NORMAL_TEXT, 0);
5684
1a578e9b
AC
5685 /* Advance the output cursor. */
5686 output_cursor.hpos += len;
5687 output_cursor.x += shift_by_width;
5688 UNBLOCK_INPUT;
5689}
5690
5691
5692/* Delete N glyphs at the nominal cursor position. Not implemented
5693 for X frames. */
5694
e0f712ba 5695static void
1a578e9b
AC
5696x_delete_glyphs (n)
5697 register int n;
5698{
5699 abort ();
5700}
5701
5702
5703/* Erase the current text line from the nominal cursor position
5704 (inclusive) to pixel column TO_X (exclusive). The idea is that
5705 everything from TO_X onward is already erased.
5706
5707 TO_X is a pixel position relative to updated_area of
5708 updated_window. TO_X == -1 means clear to the end of this area. */
5709
e0f712ba 5710static void
1a578e9b
AC
5711x_clear_end_of_line (to_x)
5712 int to_x;
5713{
5714 struct frame *f;
5715 struct window *w = updated_window;
5716 int max_x, min_y, max_y;
5717 int from_x, from_y, to_y;
177c0ea7 5718
1a578e9b
AC
5719 xassert (updated_window && updated_row);
5720 f = XFRAME (w->frame);
177c0ea7 5721
1a578e9b
AC
5722 if (updated_row->full_width_p)
5723 {
5724 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5725 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5726 && !w->pseudo_window_p)
5727 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5728 }
5729 else
5730 max_x = window_box_width (w, updated_area);
5731 max_y = window_text_bottom_y (w);
5732
5733 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5734 of window. For TO_X > 0, truncate to end of drawing area. */
5735 if (to_x == 0)
5736 return;
5737 else if (to_x < 0)
5738 to_x = max_x;
5739 else
5740 to_x = min (to_x, max_x);
5741
5742 to_y = min (max_y, output_cursor.y + updated_row->height);
177c0ea7 5743
1a578e9b
AC
5744 /* Notice if the cursor will be cleared by this operation. */
5745 if (!updated_row->full_width_p)
e0f712ba
AC
5746 notice_overwritten_cursor (w, updated_area,
5747 output_cursor.x, -1,
5748 updated_row->y,
5749 MATRIX_ROW_BOTTOM_Y (updated_row));
1a578e9b
AC
5750
5751 from_x = output_cursor.x;
e0f712ba 5752
1a578e9b
AC
5753 /* Translate to frame coordinates. */
5754 if (updated_row->full_width_p)
5755 {
5756 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5757 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5758 }
5759 else
5760 {
5761 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5762 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5763 }
177c0ea7 5764
1a578e9b
AC
5765 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5766 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5767 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
177c0ea7 5768
1a578e9b
AC
5769 /* Prevent inadvertently clearing to end of the X window. */
5770 if (to_x > from_x && to_y > from_y)
5771 {
5772 BLOCK_INPUT;
5773 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5774 from_x, from_y, to_x - from_x, to_y - from_y,
5775 0);
5776 UNBLOCK_INPUT;
5777 }
5778}
5779
5780
5781/* Clear entire frame. If updating_frame is non-null, clear that
5782 frame. Otherwise clear the selected frame. */
5783
e0f712ba 5784static void
1a578e9b
AC
5785x_clear_frame ()
5786{
5787 struct frame *f;
5788
5789 if (updating_frame)
5790 f = updating_frame;
5791 else
5792 f = SELECTED_FRAME ();
5793
5794 /* Clearing the frame will erase any cursor, so mark them all as no
5795 longer visible. */
5796 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5797 output_cursor.hpos = output_cursor.vpos = 0;
5798 output_cursor.x = -1;
5799
5800 /* We don't set the output cursor here because there will always
5801 follow an explicit cursor_to. */
5802 BLOCK_INPUT;
5803 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5804
5805#if 0 /* Clearing frame on Mac OS clears scroll bars. */
5806 /* We have to clear the scroll bars, too. If we have changed
5807 colors or something like that, then they should be notified. */
5808 x_scroll_bar_clear (f);
5809#endif
5810
5811 XFlush (FRAME_MAC_DISPLAY (f));
5812 UNBLOCK_INPUT;
5813}
5814
5815
5816\f
5817/* Invert the middle quarter of the frame for .15 sec. */
5818
5819/* We use the select system call to do the waiting, so we have to make
5820 sure it's available. If it isn't, we just won't do visual bells. */
5821
5822#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5823
5824/* Subtract the `struct timeval' values X and Y, storing the result in
5825 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5826
5827static int
5828timeval_subtract (result, x, y)
5829 struct timeval *result, x, y;
5830{
5831 /* Perform the carry for the later subtraction by updating y. This
5832 is safer because on some systems the tv_sec member is unsigned. */
5833 if (x.tv_usec < y.tv_usec)
5834 {
5835 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5836 y.tv_usec -= 1000000 * nsec;
5837 y.tv_sec += nsec;
5838 }
177c0ea7 5839
1a578e9b
AC
5840 if (x.tv_usec - y.tv_usec > 1000000)
5841 {
5842 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5843 y.tv_usec += 1000000 * nsec;
5844 y.tv_sec -= nsec;
5845 }
5846
5847 /* Compute the time remaining to wait. tv_usec is certainly
5848 positive. */
5849 result->tv_sec = x.tv_sec - y.tv_sec;
5850 result->tv_usec = x.tv_usec - y.tv_usec;
5851
5852 /* Return indication of whether the result should be considered
5853 negative. */
5854 return x.tv_sec < y.tv_sec;
5855}
5856
5857void
5858XTflash (f)
5859 struct frame *f;
5860{
5861 BLOCK_INPUT;
5862
5863 FlashMenuBar (0);
5864
5865 {
5866 struct timeval wakeup;
5867
5868 EMACS_GET_TIME (wakeup);
5869
5870 /* Compute time to wait until, propagating carry from usecs. */
5871 wakeup.tv_usec += 150000;
5872 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5873 wakeup.tv_usec %= 1000000;
5874
5875 /* Keep waiting until past the time wakeup. */
5876 while (1)
5877 {
5878 struct timeval timeout;
5879
5880 EMACS_GET_TIME (timeout);
5881
5882 /* In effect, timeout = wakeup - timeout.
5883 Break if result would be negative. */
5884 if (timeval_subtract (&timeout, wakeup, timeout))
5885 break;
5886
5887 /* Try to wait that long--but we might wake up sooner. */
5888 select (0, NULL, NULL, NULL, &timeout);
5889 }
5890 }
177c0ea7 5891
1a578e9b
AC
5892 FlashMenuBar (0);
5893
5894 UNBLOCK_INPUT;
5895}
5896
5897#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5898
5899
5900/* Make audible bell. */
5901
5902void
5903XTring_bell ()
5904{
5905 struct frame *f = SELECTED_FRAME ();
177c0ea7 5906
1a578e9b
AC
5907#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5908 if (visible_bell)
5909 XTflash (f);
5910 else
5911#endif
5912 {
5913 BLOCK_INPUT;
5914 SysBeep (1);
5915 XFlush (FRAME_MAC_DISPLAY (f));
5916 UNBLOCK_INPUT;
5917 }
5918}
5919
5920
5921\f
5922/* Specify how many text lines, from the top of the window,
5923 should be affected by insert-lines and delete-lines operations.
5924 This, and those operations, are used only within an update
5925 that is bounded by calls to x_update_begin and x_update_end. */
5926
5927void
5928XTset_terminal_window (n)
5929 register int n;
5930{
5931 /* This function intentionally left blank. */
5932}
5933
5934
5935\f
5936/***********************************************************************
5937 Line Dance
5938 ***********************************************************************/
5939
5940/* Perform an insert-lines or delete-lines operation, inserting N
5941 lines or deleting -N lines at vertical position VPOS. */
5942
e0f712ba 5943static void
1a578e9b
AC
5944x_ins_del_lines (vpos, n)
5945 int vpos, n;
5946{
5947 abort ();
5948}
5949
5950
5951/* Scroll part of the display as described by RUN. */
5952
e0f712ba 5953static void
1a578e9b
AC
5954x_scroll_run (w, run)
5955 struct window *w;
5956 struct run *run;
5957{
5958 struct frame *f = XFRAME (w->frame);
5959 int x, y, width, height, from_y, to_y, bottom_y;
5960
5961 /* Get frame-relative bounding box of the text display area of W,
3f332ef3
KS
5962 without mode lines. Include in this box the left and right
5963 fringes of W. */
1a578e9b 5964 window_box (w, -1, &x, &y, &width, &height);
3f332ef3
KS
5965 width += FRAME_X_FRINGE_WIDTH (f);
5966 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
1a578e9b
AC
5967
5968 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5969 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5970 bottom_y = y + height;
5971
5972 if (to_y < from_y)
5973 {
5974 /* Scrolling up. Make sure we don't copy part of the mode
5975 line at the bottom. */
5976 if (from_y + run->height > bottom_y)
5977 height = bottom_y - from_y;
5978 else
5979 height = run->height;
5980 }
5981 else
5982 {
5983 /* Scolling down. Make sure we don't copy over the mode line.
5984 at the bottom. */
5985 if (to_y + run->height > bottom_y)
5986 height = bottom_y - to_y;
5987 else
5988 height = run->height;
5989 }
5990
5991 BLOCK_INPUT;
177c0ea7 5992
1a578e9b
AC
5993 /* Cursor off. Will be switched on again in x_update_window_end. */
5994 updated_window = w;
5995 x_clear_cursor (w);
5996
5997 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5998 f->output_data.mac->normal_gc,
5999 x, from_y,
6000 width, height,
6001 x, to_y);
177c0ea7 6002
1a578e9b
AC
6003 UNBLOCK_INPUT;
6004}
6005
6006
6007\f
6008/***********************************************************************
6009 Exposure Events
6010 ***********************************************************************/
177c0ea7 6011
1a578e9b
AC
6012/* Redisplay an exposed area of frame F. X and Y are the upper-left
6013 corner of the exposed rectangle. W and H are width and height of
6014 the exposed area. All are pixel values. W or H zero means redraw
6015 the entire frame. */
6016
6017static void
6018expose_frame (f, x, y, w, h)
6019 struct frame *f;
6020 int x, y, w, h;
6021{
6022 Rect r;
e0f712ba 6023 int mouse_face_overwritten_p = 0;
1a578e9b
AC
6024
6025 TRACE ((stderr, "expose_frame "));
6026
6027 /* No need to redraw if frame will be redrawn soon. */
6028 if (FRAME_GARBAGED_P (f))
6029 {
6030 TRACE ((stderr, " garbaged\n"));
6031 return;
6032 }
6033
6034 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6035 or deactivated here, for unknown reasons, activated scroll bars
6036 are shown in deactivated frames in some instances. */
6037 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6038 activate_scroll_bars (f);
6039 else
6040 deactivate_scroll_bars (f);
6041
6042 /* If basic faces haven't been realized yet, there is no point in
6043 trying to redraw anything. This can happen when we get an expose
6044 event while Emacs is starting, e.g. by moving another window. */
6045 if (FRAME_FACE_CACHE (f) == NULL
6046 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6047 {
6048 TRACE ((stderr, " no faces\n"));
6049 return;
6050 }
6051
6052 if (w == 0 || h == 0)
6053 {
6054 r.left = r.top = 0;
6055 r.right = CANON_X_UNIT (f) * f->width;
6056 r.bottom = CANON_Y_UNIT (f) * f->height;
6057 }
6058 else
6059 {
6060 r.left = x;
6061 r.top = y;
6062 r.right = x + w;
6063 r.bottom = y + h;
6064 }
6065
6066 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
e0f712ba 6067 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
1a578e9b
AC
6068
6069 if (WINDOWP (f->tool_bar_window))
e0f712ba
AC
6070 mouse_face_overwritten_p
6071 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6072
6073 /* Some window managers support a focus-follows-mouse style with
6074 delayed raising of frames. Imagine a partially obscured frame,
6075 and moving the mouse into partially obscured mouse-face on that
6076 frame. The visible part of the mouse-face will be highlighted,
6077 then the WM raises the obscured frame. With at least one WM, KDE
6078 2.1, Emacs is not getting any event for the raising of the frame
6079 (even tried with SubstructureRedirectMask), only Expose events.
6080 These expose events will draw text normally, i.e. not
6081 highlighted. Which means we must redo the highlight here.
6082 Subsume it under ``we love X''. --gerd 2001-08-15 */
6083 /* Included in Windows version because Windows most likely does not
6084 do the right thing if any third party tool offers
6085 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6086 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
1a578e9b 6087 {
e0f712ba
AC
6088 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6089 if (f == dpyinfo->mouse_face_mouse_frame)
6090 {
6091 int x = dpyinfo->mouse_face_mouse_x;
6092 int y = dpyinfo->mouse_face_mouse_y;
6093 clear_mouse_face (dpyinfo);
6094 note_mouse_highlight (f, x, y);
6095 }
1a578e9b 6096 }
1a578e9b
AC
6097}
6098
6099
6100/* Redraw (parts) of all windows in the window tree rooted at W that
6101 intersect R. R contains frame pixel coordinates. */
6102
e0f712ba 6103static int
1a578e9b
AC
6104expose_window_tree (w, r)
6105 struct window *w;
6106 Rect *r;
6107{
e0f712ba
AC
6108 struct frame *f = XFRAME (w->frame);
6109 int mouse_face_overwritten_p = 0;
6110
6111 while (w && !FRAME_GARBAGED_P (f))
1a578e9b
AC
6112 {
6113 if (!NILP (w->hchild))
e0f712ba
AC
6114 mouse_face_overwritten_p
6115 |= expose_window_tree (XWINDOW (w->hchild), r);
1a578e9b 6116 else if (!NILP (w->vchild))
e0f712ba
AC
6117 mouse_face_overwritten_p
6118 |= expose_window_tree (XWINDOW (w->vchild), r);
1a578e9b 6119 else
e0f712ba 6120 mouse_face_overwritten_p |= expose_window (w, r);
1a578e9b 6121
e0f712ba 6122 w = NILP (w->next) ? NULL : XWINDOW (w->next);
1a578e9b 6123 }
e0f712ba
AC
6124
6125 return mouse_face_overwritten_p;
1a578e9b
AC
6126}
6127
6128
6129/* Redraw the part of glyph row area AREA of glyph row ROW on window W
6130 which intersects rectangle R. R is in window-relative coordinates. */
6131
6132static void
6133expose_area (w, row, r, area)
6134 struct window *w;
6135 struct glyph_row *row;
6136 Rect *r;
6137 enum glyph_row_area area;
6138{
1a578e9b
AC
6139 struct glyph *first = row->glyphs[area];
6140 struct glyph *end = row->glyphs[area] + row->used[area];
6141 struct glyph *last;
e0f712ba 6142 int first_x, start_x, x;
1a578e9b
AC
6143
6144 if (area == TEXT_AREA && row->fill_line_p)
6145 /* If row extends face to end of line write the whole line. */
e0f712ba 6146 x_draw_glyphs (w, 0, row, area,
1a578e9b 6147 0, row->used[area],
e0f712ba 6148 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
6149 else
6150 {
e0f712ba
AC
6151 /* Set START_X to the window-relative start position for drawing glyphs of
6152 AREA. The first glyph of the text area can be partially visible.
6153 The first glyphs of other areas cannot. */
6154 if (area == LEFT_MARGIN_AREA)
6155 start_x = 0;
6156 else if (area == TEXT_AREA)
6157 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6158 else
6159 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6160 + window_box_width (w, TEXT_AREA));
6161 x = start_x;
6162
1a578e9b
AC
6163 /* Find the first glyph that must be redrawn. */
6164 while (first < end
6165 && x + first->pixel_width < r->left)
6166 {
6167 x += first->pixel_width;
6168 ++first;
6169 }
177c0ea7 6170
1a578e9b
AC
6171 /* Find the last one. */
6172 last = first;
6173 first_x = x;
6174 while (last < end
6175 && x < r->right)
6176 {
6177 x += last->pixel_width;
6178 ++last;
6179 }
e0f712ba 6180
1a578e9b
AC
6181 /* Repaint. */
6182 if (last > first)
e0f712ba
AC
6183 x_draw_glyphs (w, first_x - start_x, row, area,
6184 first - row->glyphs[area],
6185 last - row->glyphs[area],
6186 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
6187 }
6188}
e0f712ba 6189
1a578e9b
AC
6190
6191/* Redraw the parts of the glyph row ROW on window W intersecting
e0f712ba
AC
6192 rectangle R. R is in window-relative coordinates. Value is
6193 non-zero if mouse face was overwritten. */
1a578e9b 6194
e0f712ba 6195static int
1a578e9b
AC
6196expose_line (w, row, r)
6197 struct window *w;
6198 struct glyph_row *row;
6199 Rect *r;
6200{
6201 xassert (row->enabled_p);
177c0ea7 6202
1a578e9b
AC
6203 if (row->mode_line_p || w->pseudo_window_p)
6204 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
e0f712ba 6205 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
6206 else
6207 {
6208 if (row->used[LEFT_MARGIN_AREA])
6209 expose_area (w, row, r, LEFT_MARGIN_AREA);
6210 if (row->used[TEXT_AREA])
6211 expose_area (w, row, r, TEXT_AREA);
6212 if (row->used[RIGHT_MARGIN_AREA])
6213 expose_area (w, row, r, RIGHT_MARGIN_AREA);
3f332ef3 6214 x_draw_row_fringe_bitmaps (w, row);
1a578e9b 6215 }
e0f712ba
AC
6216
6217 return row->mouse_face_p;
1a578e9b
AC
6218}
6219
6220
6221/* Return non-zero if W's cursor intersects rectangle R. */
6222
6223static int
6224x_phys_cursor_in_rect_p (w, r)
6225 struct window *w;
6226 Rect *r;
6227{
6228 Rect cr, result;
6229 struct glyph *cursor_glyph;
6230
6231 cursor_glyph = get_phys_cursor_glyph (w);
6232 if (cursor_glyph)
6233 {
6234 cr.left = w->phys_cursor.x;
6235 cr.top = w->phys_cursor.y;
6236 cr.right = cr.left + cursor_glyph->pixel_width;
6237 cr.bottom = cr.top + w->phys_cursor_height;
6238 return x_intersect_rectangles (&cr, r, &result);
6239 }
6240 else
6241 return 0;
6242}
6243
6244
ca45961d
AC
6245/* Redraw those parts of glyphs rows during expose event handling that
6246 overlap other rows. Redrawing of an exposed line writes over parts
6247 of lines overlapping that exposed line; this function fixes that.
6248
6249 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
6250 row in W's current matrix that is exposed and overlaps other rows.
6251 LAST_OVERLAPPING_ROW is the last such row. */
6252
6253static void
6254expose_overlaps (w, first_overlapping_row, last_overlapping_row)
6255 struct window *w;
6256 struct glyph_row *first_overlapping_row;
6257 struct glyph_row *last_overlapping_row;
6258{
6259 struct glyph_row *row;
177c0ea7 6260
ca45961d
AC
6261 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
6262 if (row->overlapping_p)
6263 {
6264 xassert (row->enabled_p && !row->mode_line_p);
177c0ea7 6265
ca45961d
AC
6266 if (row->used[LEFT_MARGIN_AREA])
6267 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
177c0ea7 6268
ca45961d
AC
6269 if (row->used[TEXT_AREA])
6270 x_fix_overlapping_area (w, row, TEXT_AREA);
177c0ea7 6271
ca45961d
AC
6272 if (row->used[RIGHT_MARGIN_AREA])
6273 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
6274 }
6275}
6276
6277
6278/* Redraw the part of window W intersection rectangle FR. Pixel
6279 coordinates in FR are frame-relative. Call this function with
e0f712ba
AC
6280 input blocked. Value is non-zero if the exposure overwrites
6281 mouse-face. */
1a578e9b 6282
e0f712ba
AC
6283static int
6284expose_window (w, fr)
1a578e9b 6285 struct window *w;
e0f712ba 6286 Rect *fr;
1a578e9b 6287{
e0f712ba
AC
6288 struct frame *f = XFRAME (w->frame);
6289 Rect wr, r;
6290 int mouse_face_overwritten_p = 0;
1a578e9b
AC
6291
6292 /* If window is not yet fully initialized, do nothing. This can
6293 happen when toolkit scroll bars are used and a window is split.
6294 Reconfiguring the scroll bar will generate an expose for a newly
6295 created window. */
6296 if (w->current_matrix == NULL)
e0f712ba 6297 return 0;
1a578e9b 6298
e0f712ba
AC
6299 /* When we're currently updating the window, display and current
6300 matrix usually don't agree. Arrange for a thorough display
6301 later. */
6302 if (w == updated_window)
1a578e9b 6303 {
e0f712ba
AC
6304 SET_FRAME_GARBAGED (f);
6305 return 0;
1a578e9b 6306 }
1a578e9b 6307
e0f712ba
AC
6308 /* Frame-relative pixel rectangle of W. */
6309 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6310 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6311 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6312 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6313
6314 if (x_intersect_rectangles (fr, &wr, &r))
1a578e9b 6315 {
e0f712ba
AC
6316 int yb = window_text_bottom_y (w);
6317 struct glyph_row *row;
6318 int cursor_cleared_p;
ca45961d 6319 struct glyph_row *first_overlapping_row, *last_overlapping_row;
177c0ea7 6320
e0f712ba
AC
6321 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6322 r.left, r.top, r.right, r.bottom));
1a578e9b 6323
e0f712ba
AC
6324 /* Convert to window coordinates. */
6325 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6326 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6327 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6328 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6329
6330 /* Turn off the cursor. */
6331 if (!w->pseudo_window_p
6332 && x_phys_cursor_in_rect_p (w, &r))
6333 {
6334 x_clear_cursor (w);
6335 cursor_cleared_p = 1;
6336 }
6337 else
6338 cursor_cleared_p = 0;
6339
ca45961d
AC
6340 /* Update lines intersecting rectangle R. */
6341 first_overlapping_row = last_overlapping_row = NULL;
e0f712ba
AC
6342 for (row = w->current_matrix->rows;
6343 row->enabled_p;
6344 ++row)
6345 {
6346 int y0 = row->y;
6347 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6348
6349 if ((y0 >= r.top && y0 < r.bottom)
6350 || (y1 > r.top && y1 < r.bottom)
6351 || (r.top >= y0 && r.top < y1)
6352 || (r.bottom > y0 && r.bottom < y1))
6353 {
ca45961d
AC
6354 if (row->overlapping_p)
6355 {
6356 if (first_overlapping_row == NULL)
6357 first_overlapping_row = row;
6358 last_overlapping_row = row;
6359 }
177c0ea7 6360
e0f712ba
AC
6361 if (expose_line (w, row, &r))
6362 mouse_face_overwritten_p = 1;
6363 }
177c0ea7 6364
e0f712ba
AC
6365 if (y1 >= yb)
6366 break;
6367 }
6368
6369 /* Display the mode line if there is one. */
6370 if (WINDOW_WANTS_MODELINE_P (w)
6371 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6372 row->enabled_p)
6373 && row->y < r.bottom)
6374 {
6375 if (expose_line (w, row, &r))
6376 mouse_face_overwritten_p = 1;
6377 }
6378
6379 if (!w->pseudo_window_p)
6380 {
ca45961d
AC
6381 /* Fix the display of overlapping rows. */
6382 if (first_overlapping_row)
6383 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
177c0ea7 6384
e0f712ba
AC
6385 /* Draw border between windows. */
6386 x_draw_vertical_border (w);
177c0ea7 6387
e0f712ba
AC
6388 /* Turn the cursor on again. */
6389 if (cursor_cleared_p)
6390 x_update_window_cursor (w, 1);
6391 }
1a578e9b 6392 }
e0f712ba 6393
1a578e9b
AC
6394 /* Display scroll bar for this window. */
6395 if (!NILP (w->vertical_scroll_bar))
6396 {
6397 ControlHandle ch
e0f712ba 6398 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
1a578e9b
AC
6399
6400 Draw1Control (ch);
6401 }
1a578e9b 6402
e0f712ba
AC
6403 return mouse_face_overwritten_p;
6404}
1a578e9b
AC
6405
6406static int
6407x_intersect_rectangles (r1, r2, result)
6408 Rect *r1, *r2, *result;
6409{
6410 Rect *left, *right;
6411 Rect *upper, *lower;
6412 int intersection_p = 0;
177c0ea7 6413
1a578e9b
AC
6414 /* Rerrange so that R1 is the left-most rectangle. */
6415 if (r1->left < r2->left)
6416 left = r1, right = r2;
6417 else
6418 left = r2, right = r1;
6419
6420 /* X0 of the intersection is right.x0, if this is inside R1,
6421 otherwise there is no intersection. */
6422 if (right->left <= left->right)
6423 {
6424 result->left = right->left;
177c0ea7 6425
1a578e9b
AC
6426 /* The right end of the intersection is the minimum of the
6427 the right ends of left and right. */
6428 result->right = min (left->right, right->right);
6429
6430 /* Same game for Y. */
6431 if (r1->top < r2->top)
6432 upper = r1, lower = r2;
6433 else
6434 upper = r2, lower = r1;
6435
6436 /* The upper end of the intersection is lower.y0, if this is inside
6437 of upper. Otherwise, there is no intersection. */
6438 if (lower->top <= upper->bottom)
6439 {
6440 result->top = lower->top;
177c0ea7 6441
1a578e9b
AC
6442 /* The lower end of the intersection is the minimum of the lower
6443 ends of upper and lower. */
6444 result->bottom = min (lower->bottom, upper->bottom);
6445 intersection_p = 1;
6446 }
6447 }
6448
6449 return intersection_p;
6450}
6451
6452
6453
6454
6455\f
6456static void
6457frame_highlight (f)
6458 struct frame *f;
6459{
6460 x_update_cursor (f, 1);
6461}
6462
6463static void
6464frame_unhighlight (f)
6465 struct frame *f;
6466{
6467 x_update_cursor (f, 1);
6468}
6469
6470/* The focus has changed. Update the frames as necessary to reflect
6471 the new situation. Note that we can't change the selected frame
6472 here, because the Lisp code we are interrupting might become confused.
6473 Each event gets marked with the frame in which it occurred, so the
6474 Lisp code can tell when the switch took place by examining the events. */
6475
6476static void
6477x_new_focus_frame (dpyinfo, frame)
6478 struct x_display_info *dpyinfo;
6479 struct frame *frame;
6480{
6481 struct frame *old_focus = dpyinfo->x_focus_frame;
6482
6483 if (frame != dpyinfo->x_focus_frame)
6484 {
6485 /* Set this before calling other routines, so that they see
6486 the correct value of x_focus_frame. */
6487 dpyinfo->x_focus_frame = frame;
6488
6489 if (old_focus && old_focus->auto_lower)
6490 x_lower_frame (old_focus);
6491
6492#if 0
6493 selected_frame = frame;
6494 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6495 selected_frame);
6496 Fselect_window (selected_frame->selected_window);
6497 choose_minibuf_frame ();
6498#endif /* ! 0 */
6499
6500 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6501 pending_autoraise_frame = dpyinfo->x_focus_frame;
6502 else
6503 pending_autoraise_frame = 0;
6504 }
6505
6506 x_frame_rehighlight (dpyinfo);
6507}
6508
6509/* Handle an event saying the mouse has moved out of an Emacs frame. */
6510
e0f712ba 6511void
1a578e9b
AC
6512x_mouse_leave (dpyinfo)
6513 struct x_display_info *dpyinfo;
6514{
6515 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6516}
6517
6518/* The focus has changed, or we have redirected a frame's focus to
6519 another frame (this happens when a frame uses a surrogate
6520 mini-buffer frame). Shift the highlight as appropriate.
6521
6522 The FRAME argument doesn't necessarily have anything to do with which
6523 frame is being highlighted or un-highlighted; we only use it to find
6524 the appropriate X display info. */
6525
e0f712ba 6526static void
1a578e9b
AC
6527XTframe_rehighlight (frame)
6528 struct frame *frame;
6529{
6530 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6531}
6532
6533static void
6534x_frame_rehighlight (dpyinfo)
6535 struct x_display_info *dpyinfo;
6536{
6537 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6538
6539 if (dpyinfo->x_focus_frame)
6540 {
6541 dpyinfo->x_highlight_frame
6542 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6543 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6544 : dpyinfo->x_focus_frame);
6545 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6546 {
6547 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6548 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6549 }
6550 }
6551 else
6552 dpyinfo->x_highlight_frame = 0;
6553
6554 if (dpyinfo->x_highlight_frame != old_highlight)
6555 {
6556 if (old_highlight)
6557 frame_unhighlight (old_highlight);
6558 if (dpyinfo->x_highlight_frame)
6559 frame_highlight (dpyinfo->x_highlight_frame);
6560 }
6561}
6562
6563
6564\f
6565/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6566
e0f712ba 6567#if 0 /* MAC_TODO */
1a578e9b
AC
6568/* Initialize mode_switch_bit and modifier_meaning. */
6569static void
6570x_find_modifier_meanings (dpyinfo)
6571 struct x_display_info *dpyinfo;
6572{
6573 int min_code, max_code;
6574 KeySym *syms;
6575 int syms_per_code;
6576 XModifierKeymap *mods;
6577
6578 dpyinfo->meta_mod_mask = 0;
6579 dpyinfo->shift_lock_mask = 0;
6580 dpyinfo->alt_mod_mask = 0;
6581 dpyinfo->super_mod_mask = 0;
6582 dpyinfo->hyper_mod_mask = 0;
6583
6584#ifdef HAVE_X11R4
6585 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6586#else
6587 min_code = dpyinfo->display->min_keycode;
6588 max_code = dpyinfo->display->max_keycode;
6589#endif
6590
6591 syms = XGetKeyboardMapping (dpyinfo->display,
6592 min_code, max_code - min_code + 1,
6593 &syms_per_code);
6594 mods = XGetModifierMapping (dpyinfo->display);
6595
6596 /* Scan the modifier table to see which modifier bits the Meta and
6597 Alt keysyms are on. */
6598 {
6599 int row, col; /* The row and column in the modifier table. */
6600
6601 for (row = 3; row < 8; row++)
6602 for (col = 0; col < mods->max_keypermod; col++)
6603 {
6604 KeyCode code
6605 = mods->modifiermap[(row * mods->max_keypermod) + col];
6606
6607 /* Zeroes are used for filler. Skip them. */
6608 if (code == 0)
6609 continue;
6610
6611 /* Are any of this keycode's keysyms a meta key? */
6612 {
6613 int code_col;
6614
6615 for (code_col = 0; code_col < syms_per_code; code_col++)
6616 {
6617 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6618
6619 switch (sym)
6620 {
6621 case XK_Meta_L:
6622 case XK_Meta_R:
6623 dpyinfo->meta_mod_mask |= (1 << row);
6624 break;
6625
6626 case XK_Alt_L:
6627 case XK_Alt_R:
6628 dpyinfo->alt_mod_mask |= (1 << row);
6629 break;
6630
6631 case XK_Hyper_L:
6632 case XK_Hyper_R:
6633 dpyinfo->hyper_mod_mask |= (1 << row);
6634 break;
6635
6636 case XK_Super_L:
6637 case XK_Super_R:
6638 dpyinfo->super_mod_mask |= (1 << row);
6639 break;
6640
6641 case XK_Shift_Lock:
6642 /* Ignore this if it's not on the lock modifier. */
6643 if ((1 << row) == LockMask)
6644 dpyinfo->shift_lock_mask = LockMask;
6645 break;
6646 }
6647 }
6648 }
6649 }
6650 }
6651
6652 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6653 if (! dpyinfo->meta_mod_mask)
6654 {
6655 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6656 dpyinfo->alt_mod_mask = 0;
6657 }
6658
6659 /* If some keys are both alt and meta,
6660 make them just meta, not alt. */
6661 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6662 {
6663 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6664 }
6665
6666 XFree ((char *) syms);
6667 XFreeModifiermap (mods);
6668}
6669
e0f712ba 6670#endif /* MAC_TODO */
1a578e9b
AC
6671
6672/* Convert between the modifier bits X uses and the modifier bits
6673 Emacs uses. */
6674
6675static unsigned int
6676x_mac_to_emacs_modifiers (dpyinfo, state)
6677 struct x_display_info *dpyinfo;
6678 unsigned short state;
6679{
6680 return (((state & shiftKey) ? shift_modifier : 0)
6681 | ((state & controlKey) ? ctrl_modifier : 0)
6682 | ((state & cmdKey) ? meta_modifier : 0)
6683 | ((state & optionKey) ? alt_modifier : 0));
6684}
6685
e0f712ba 6686#if 0 /* MAC_TODO */
1a578e9b
AC
6687static unsigned short
6688x_emacs_to_x_modifiers (dpyinfo, state)
6689 struct x_display_info *dpyinfo;
6690 unsigned int state;
6691{
6692 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6693 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6694 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6695 | ((state & shift_modifier) ? ShiftMask : 0)
6696 | ((state & ctrl_modifier) ? ControlMask : 0)
6697 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6698}
e0f712ba 6699#endif /* MAC_TODO */
1a578e9b
AC
6700
6701/* Convert a keysym to its name. */
6702
6703char *
6704x_get_keysym_name (keysym)
6705 int keysym;
6706{
6707 char *value;
6708
6709 BLOCK_INPUT;
6710#if 0
6711 value = XKeysymToString (keysym);
6712#else
6713 value = 0;
6714#endif
6715 UNBLOCK_INPUT;
6716
6717 return value;
6718}
6719
6720
6721\f
6722/* Mouse clicks and mouse movement. Rah. */
6723
6724/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6725 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6726 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6727 not force the value into range. */
6728
6729void
6730pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6731 FRAME_PTR f;
6732 register int pix_x, pix_y;
6733 register int *x, *y;
6734 Rect *bounds;
6735 int noclip;
6736{
e0f712ba
AC
6737 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6738 if (NILP (Vwindow_system))
6739 {
6740 *x = pix_x;
6741 *y = pix_y;
6742 return;
6743 }
6744
6745 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1a578e9b
AC
6746 even for negative values. */
6747 if (pix_x < 0)
e0f712ba 6748 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
1a578e9b
AC
6749 if (pix_y < 0)
6750 pix_y -= (f)->output_data.mac->line_height - 1;
6751
6752 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6753 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6754
6755 if (bounds)
6756 {
6757 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6758 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
e0f712ba
AC
6759 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6760 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
1a578e9b
AC
6761 }
6762
6763 if (!noclip)
6764 {
6765 if (pix_x < 0)
6766 pix_x = 0;
6767 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6768 pix_x = FRAME_WINDOW_WIDTH (f);
6769
6770 if (pix_y < 0)
6771 pix_y = 0;
6772 else if (pix_y > f->height)
6773 pix_y = f->height;
6774 }
6775
6776 *x = pix_x;
6777 *y = pix_y;
6778}
6779
6780
6781/* Given HPOS/VPOS in the current matrix of W, return corresponding
6782 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6783 can't tell the positions because W's display is not up to date,
6784 return 0. */
6785
e0f712ba 6786int
1a578e9b
AC
6787glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6788 struct window *w;
6789 int hpos, vpos;
6790 int *frame_x, *frame_y;
6791{
6792 int success_p;
6793
6794 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6795 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6796
6797 if (display_completed)
6798 {
6799 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6800 struct glyph *glyph = row->glyphs[TEXT_AREA];
6801 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6802
6803 *frame_y = row->y;
6804 *frame_x = row->x;
6805 while (glyph < end)
6806 {
6807 *frame_x += glyph->pixel_width;
6808 ++glyph;
6809 }
6810
6811 success_p = 1;
6812 }
6813 else
6814 {
6815 *frame_y = *frame_x = 0;
6816 success_p = 0;
6817 }
6818
6819 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6820 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6821 return success_p;
6822}
6823
6824
6825/* Prepare a mouse-event in *RESULT for placement in the input queue.
6826
6827 If the event is a button press, then note that we have grabbed
6828 the mouse. */
6829
6830static Lisp_Object
6831construct_mouse_click (result, event, f)
6832 struct input_event *result;
6833 EventRecord *event;
6834 struct frame *f;
6835{
6836 Point mouseLoc;
6837
3b8f9651 6838 result->kind = MOUSE_CLICK_EVENT;
1a578e9b
AC
6839 result->code = 0; /* only one mouse button */
6840 result->timestamp = event->when;
6841 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6842
6843 mouseLoc = event->where;
e0f712ba
AC
6844
6845#if TARGET_API_MAC_CARBON
6846 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6847#else
1a578e9b 6848 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
6849#endif
6850
1a578e9b
AC
6851 GlobalToLocal (&mouseLoc);
6852 XSETINT (result->x, mouseLoc.h);
6853 XSETINT (result->y, mouseLoc.v);
6854
6855 XSETFRAME (result->frame_or_window, f);
6856
6857 result->arg = Qnil;
6858 return Qnil;
6859}
6860
6861\f
6862/* Function to report a mouse movement to the mainstream Emacs code.
6863 The input handler calls this.
6864
6865 We have received a mouse movement event, which is given in *event.
6866 If the mouse is over a different glyph than it was last time, tell
6867 the mainstream emacs code by setting mouse_moved. If not, ask for
6868 another motion event, so we can check again the next time it moves. */
6869
6870static Point last_mouse_motion_position;
6871static Lisp_Object last_mouse_motion_frame;
6872
6873static void
6874note_mouse_movement (frame, pos)
6875 FRAME_PTR frame;
6876 Point *pos;
6877{
e0f712ba
AC
6878#if TARGET_API_MAC_CARBON
6879 Rect r;
6880#endif
6881
1a578e9b
AC
6882 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6883 last_mouse_motion_position = *pos;
6884 XSETFRAME (last_mouse_motion_frame, frame);
6885
e0f712ba
AC
6886#if TARGET_API_MAC_CARBON
6887 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6888#else
1a578e9b 6889 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
e0f712ba 6890#endif
1a578e9b
AC
6891 {
6892 frame->mouse_moved = 1;
6893 last_mouse_scroll_bar = Qnil;
6894 note_mouse_highlight (frame, -1, -1);
6895 }
6896 /* Has the mouse moved off the glyph it was on at the last sighting? */
6897 else if (pos->h < last_mouse_glyph.left
6898 || pos->h >= last_mouse_glyph.right
6899 || pos->v < last_mouse_glyph.top
6900 || pos->v >= last_mouse_glyph.bottom)
6901 {
6902 frame->mouse_moved = 1;
6903 last_mouse_scroll_bar = Qnil;
6904 note_mouse_highlight (frame, pos->h, pos->v);
6905 }
6906}
6907
6908/* This is used for debugging, to turn off note_mouse_highlight. */
6909
6910int disable_mouse_highlight;
6911
6912
6913\f
6914/************************************************************************
6915 Mouse Face
6916 ************************************************************************/
6917
6918/* Find the glyph under window-relative coordinates X/Y in window W.
6919 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6920 strings. Return in *HPOS and *VPOS the row and column number of
6921 the glyph found. Return in *AREA the glyph area containing X.
6922 Value is a pointer to the glyph found or null if X/Y is not on
6923 text, or we can't tell because W's current matrix is not up to
6924 date. */
6925
6926static struct glyph *
e0f712ba 6927x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
1a578e9b
AC
6928 struct window *w;
6929 int x, y;
6930 int *hpos, *vpos, *area;
e0f712ba 6931 int buffer_only_p;
1a578e9b
AC
6932{
6933 struct glyph *glyph, *end;
6934 struct glyph_row *row = NULL;
6935 int x0, i, left_area_width;
6936
6937 /* Find row containing Y. Give up if some row is not enabled. */
6938 for (i = 0; i < w->current_matrix->nrows; ++i)
6939 {
6940 row = MATRIX_ROW (w->current_matrix, i);
6941 if (!row->enabled_p)
6942 return NULL;
6943 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6944 break;
6945 }
6946
6947 *vpos = i;
6948 *hpos = 0;
6949
6950 /* Give up if Y is not in the window. */
6951 if (i == w->current_matrix->nrows)
6952 return NULL;
6953
6954 /* Get the glyph area containing X. */
6955 if (w->pseudo_window_p)
6956 {
6957 *area = TEXT_AREA;
6958 x0 = 0;
6959 }
6960 else
6961 {
6962 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6963 if (x < left_area_width)
6964 {
6965 *area = LEFT_MARGIN_AREA;
6966 x0 = 0;
6967 }
6968 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6969 {
6970 *area = TEXT_AREA;
6971 x0 = row->x + left_area_width;
6972 }
6973 else
6974 {
6975 *area = RIGHT_MARGIN_AREA;
6976 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6977 }
6978 }
6979
6980 /* Find glyph containing X. */
6981 glyph = row->glyphs[*area];
6982 end = glyph + row->used[*area];
6983 while (glyph < end)
6984 {
6985 if (x < x0 + glyph->pixel_width)
6986 {
6987 if (w->pseudo_window_p)
6988 break;
e0f712ba 6989 else if (!buffer_only_p || BUFFERP (glyph->object))
1a578e9b
AC
6990 break;
6991 }
177c0ea7 6992
1a578e9b
AC
6993 x0 += glyph->pixel_width;
6994 ++glyph;
6995 }
6996
6997 if (glyph == end)
6998 return NULL;
6999
7000 *hpos = glyph - row->glyphs[*area];
7001 return glyph;
7002}
7003
7004
7005/* Convert frame-relative x/y to coordinates relative to window W.
7006 Takes pseudo-windows into account. */
7007
7008static void
7009frame_to_window_pixel_xy (w, x, y)
7010 struct window *w;
7011 int *x, *y;
7012{
7013 if (w->pseudo_window_p)
7014 {
7015 /* A pseudo-window is always full-width, and starts at the
7016 left edge of the frame, plus a frame border. */
7017 struct frame *f = XFRAME (w->frame);
7018 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
7019 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
7020 }
7021 else
7022 {
7023 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
7024 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
7025 }
7026}
7027
7028
e0f712ba 7029/* Take proper action when mouse has moved to the mode or header line of
1a578e9b
AC
7030 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
7031 mode line. X is relative to the start of the text display area of
3f332ef3 7032 W, so the width of fringes and scroll bars must be subtracted
1a578e9b
AC
7033 to get a position relative to the start of the mode line. */
7034
7035static void
7036note_mode_line_highlight (w, x, mode_line_p)
7037 struct window *w;
7038 int x, mode_line_p;
7039{
7040 struct frame *f = XFRAME (w->frame);
7041 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
e0f712ba 7042 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
1a578e9b
AC
7043 struct glyph_row *row;
7044
7045 if (mode_line_p)
7046 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
7047 else
7048 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
e0f712ba 7049
1a578e9b
AC
7050 if (row->enabled_p)
7051 {
7052 struct glyph *glyph, *end;
7053 Lisp_Object help, map;
7054 int x0;
177c0ea7 7055
1a578e9b
AC
7056 /* Find the glyph under X. */
7057 glyph = row->glyphs[TEXT_AREA];
7058 end = glyph + row->used[TEXT_AREA];
7059 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
3f332ef3 7060 + FRAME_X_LEFT_FRINGE_WIDTH (f));
177c0ea7 7061
1a578e9b
AC
7062 while (glyph < end
7063 && x >= x0 + glyph->pixel_width)
7064 {
7065 x0 += glyph->pixel_width;
7066 ++glyph;
7067 }
7068
7069 if (glyph < end
7070 && STRINGP (glyph->object)
d5db4077 7071 && STRING_INTERVALS (glyph->object)
1a578e9b 7072 && glyph->charpos >= 0
d5db4077 7073 && glyph->charpos < SCHARS (glyph->object))
1a578e9b
AC
7074 {
7075 /* If we're on a string with `help-echo' text property,
7076 arrange for the help to be displayed. This is done by
7077 setting the global variable help_echo to the help string. */
7078 help = Fget_text_property (make_number (glyph->charpos),
7079 Qhelp_echo, glyph->object);
7080 if (!NILP (help))
e0f712ba
AC
7081 {
7082 help_echo = help;
7083 XSETWINDOW (help_echo_window, w);
7084 help_echo_object = glyph->object;
7085 help_echo_pos = glyph->charpos;
7086 }
1a578e9b
AC
7087
7088 /* Change the mouse pointer according to what is under X/Y. */
7089 map = Fget_text_property (make_number (glyph->charpos),
7090 Qlocal_map, glyph->object);
e7cbccd1 7091 if (KEYMAPP (map))
1a578e9b
AC
7092 cursor = f->output_data.mac->nontext_cursor;
7093 else
7094 {
7095 map = Fget_text_property (make_number (glyph->charpos),
7096 Qkeymap, glyph->object);
e7cbccd1 7097 if (KEYMAPP (map))
1a578e9b
AC
7098 cursor = f->output_data.mac->nontext_cursor;
7099 }
7100 }
7101 }
7102
7103#if 0 /* MAC_TODO: mouse cursor */
7104 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7105#endif
7106}
7107
7108
7109/* Take proper action when the mouse has moved to position X, Y on
7110 frame F as regards highlighting characters that have mouse-face
7111 properties. Also de-highlighting chars where the mouse was before.
7112 X and Y can be negative or out of range. */
7113
7114static void
7115note_mouse_highlight (f, x, y)
7116 struct frame *f;
7117 int x, y;
7118{
7119 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7120 int portion;
7121 Lisp_Object window;
7122 struct window *w;
e0f712ba 7123 struct buffer *b;
1a578e9b 7124
e0f712ba
AC
7125#if 0
7126 /* When a menu is active, don't highlight because this looks odd. */
1a578e9b
AC
7127 if (popup_activated ())
7128 return;
7129#endif
7130
e0f712ba 7131 if (NILP (Vmouse_highlight)
1a578e9b
AC
7132 || !f->glyphs_initialized_p)
7133 return;
7134
7135 dpyinfo->mouse_face_mouse_x = x;
7136 dpyinfo->mouse_face_mouse_y = y;
7137 dpyinfo->mouse_face_mouse_frame = f;
7138
7139 if (dpyinfo->mouse_face_defer)
7140 return;
7141
7142 if (gc_in_progress)
7143 {
7144 dpyinfo->mouse_face_deferred_gc = 1;
7145 return;
7146 }
7147
7148 /* Which window is that in? */
7149 window = window_from_coordinates (f, x, y, &portion, 1);
7150
7151 /* If we were displaying active text in another window, clear that. */
7152 if (! EQ (window, dpyinfo->mouse_face_window))
7153 clear_mouse_face (dpyinfo);
7154
7155 /* Not on a window -> return. */
7156 if (!WINDOWP (window))
7157 return;
7158
e0f712ba
AC
7159 /* Reset help_echo. It will get recomputed below. */
7160 help_echo = Qnil;
7161
1a578e9b
AC
7162 /* Convert to window-relative pixel coordinates. */
7163 w = XWINDOW (window);
7164 frame_to_window_pixel_xy (w, &x, &y);
7165
7166 /* Handle tool-bar window differently since it doesn't display a
7167 buffer. */
7168 if (EQ (window, f->tool_bar_window))
7169 {
7170 note_tool_bar_highlight (f, x, y);
7171 return;
7172 }
7173
e0f712ba 7174 /* Mouse is on the mode or header line? */
1a578e9b
AC
7175 if (portion == 1 || portion == 3)
7176 {
1a578e9b
AC
7177 note_mode_line_highlight (w, x, portion == 1);
7178 return;
7179 }
e0f712ba
AC
7180#if 0 /* TODO: mouse cursor */
7181 if (portion == 2)
7182 cursor = f->output_data.x->horizontal_drag_cursor;
1a578e9b 7183 else
e0f712ba 7184 cursor = f->output_data.x->text_cursor;
1a578e9b 7185#endif
1a578e9b
AC
7186 /* Are we in a window whose display is up to date?
7187 And verify the buffer's text has not changed. */
e0f712ba 7188 b = XBUFFER (w->buffer);
1a578e9b
AC
7189 if (/* Within text portion of the window. */
7190 portion == 0
7191 && EQ (w->window_end_valid, w->buffer)
e0f712ba
AC
7192 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7193 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
1a578e9b
AC
7194 {
7195 int hpos, vpos, pos, i, area;
7196 struct glyph *glyph;
e0f712ba
AC
7197 Lisp_Object object;
7198 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7199 Lisp_Object *overlay_vec = NULL;
7200 int len, noverlays;
7201 struct buffer *obuf;
7202 int obegv, ozv, same_region;
1a578e9b
AC
7203
7204 /* Find the glyph under X/Y. */
e0f712ba 7205 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
1a578e9b
AC
7206
7207 /* Clear mouse face if X/Y not over text. */
7208 if (glyph == NULL
7209 || area != TEXT_AREA
7210 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7211 {
7212 clear_mouse_face (dpyinfo);
e0f712ba
AC
7213 /* TODO: mouse cursor */
7214 goto set_cursor;
1a578e9b
AC
7215 }
7216
7217 pos = glyph->charpos;
e0f712ba
AC
7218 object = glyph->object;
7219 if (!STRINGP (object) && !BUFFERP (object))
7220 goto set_cursor;
7221
7222 /* If we get an out-of-range value, return now; avoid an error. */
7223 if (BUFFERP (object) && pos > BUF_Z (b))
7224 goto set_cursor;
7225
7226 /* Make the window's buffer temporarily current for
7227 overlays_at and compute_char_face. */
7228 obuf = current_buffer;
7229 current_buffer = b;
7230 obegv = BEGV;
7231 ozv = ZV;
7232 BEGV = BEG;
7233 ZV = Z;
7234
7235 /* Is this char mouse-active or does it have help-echo? */
7236 position = make_number (pos);
7237
7238 if (BUFFERP (object))
7239 {
7240 /* Put all the overlays we want in a vector in overlay_vec.
7241 Store the length in len. If there are more than 10, make
7242 enough space for all, and try again. */
7243 len = 10;
7244 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7245 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7246 if (noverlays > len)
7247 {
7248 len = noverlays;
7249 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7250 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7251 }
1a578e9b 7252
e0f712ba
AC
7253 /* Sort overlays into increasing priority order. */
7254 noverlays = sort_overlays (overlay_vec, noverlays, w);
7255 }
7256 else
7257 noverlays = 0;
7258
7259 same_region = (EQ (window, dpyinfo->mouse_face_window)
7260 && vpos >= dpyinfo->mouse_face_beg_row
7261 && vpos <= dpyinfo->mouse_face_end_row
7262 && (vpos > dpyinfo->mouse_face_beg_row
7263 || hpos >= dpyinfo->mouse_face_beg_col)
7264 && (vpos < dpyinfo->mouse_face_end_row
7265 || hpos < dpyinfo->mouse_face_end_col
7266 || dpyinfo->mouse_face_past_end));
7267
7268 /* TODO: if (same_region)
7269 mouse cursor */
7270
7271 /* Check mouse-face highlighting. */
7272 if (! same_region
7273 /* If there exists an overlay with mouse-face overlapping
7274 the one we are currently highlighting, we have to
7275 check if we enter the overlapping overlay, and then
7276 highlight that. */
7277 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7278 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7279 {
7280 /* Find the highest priority overlay that has a mouse-face
7281 property. */
7282 overlay = Qnil;
7283 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7284 {
7285 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7286 if (!NILP (mouse_face))
7287 overlay = overlay_vec[i];
7288 }
1a578e9b 7289
e0f712ba
AC
7290 /* If we're actually highlighting the same overlay as
7291 before, there's no need to do that again. */
7292 if (!NILP (overlay)
7293 && EQ (overlay, dpyinfo->mouse_face_overlay))
7294 goto check_help_echo;
1a578e9b 7295
e0f712ba 7296 dpyinfo->mouse_face_overlay = overlay;
1a578e9b 7297
e0f712ba
AC
7298 /* Clear the display of the old active region, if any. */
7299 clear_mouse_face (dpyinfo);
7300 /* TODO: mouse cursor changes. */
1a578e9b 7301
e0f712ba
AC
7302 /* If no overlay applies, get a text property. */
7303 if (NILP (overlay))
7304 mouse_face = Fget_text_property (position, Qmouse_face, object);
1a578e9b 7305
e0f712ba
AC
7306 /* Handle the overlay case. */
7307 if (!NILP (overlay))
7308 {
7309 /* Find the range of text around this char that
7310 should be active. */
7311 Lisp_Object before, after;
7312 int ignore;
7313
7314 before = Foverlay_start (overlay);
7315 after = Foverlay_end (overlay);
7316 /* Record this as the current active region. */
7317 fast_find_position (w, XFASTINT (before),
7318 &dpyinfo->mouse_face_beg_col,
7319 &dpyinfo->mouse_face_beg_row,
7320 &dpyinfo->mouse_face_beg_x,
7321 &dpyinfo->mouse_face_beg_y, Qnil);
7322
7323 dpyinfo->mouse_face_past_end
7324 = !fast_find_position (w, XFASTINT (after),
7325 &dpyinfo->mouse_face_end_col,
7326 &dpyinfo->mouse_face_end_row,
7327 &dpyinfo->mouse_face_end_x,
7328 &dpyinfo->mouse_face_end_y, Qnil);
7329 dpyinfo->mouse_face_window = window;
7330
7331 dpyinfo->mouse_face_face_id
7332 = face_at_buffer_position (w, pos, 0, 0,
1b7334a4
KS
7333 &ignore, pos + 1,
7334 !dpyinfo->mouse_face_hidden);
e0f712ba
AC
7335
7336 /* Display it as active. */
7337 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7338 /* TODO: mouse cursor changes. */
7339 }
7340 /* Handle the text property case. */
7341 else if (! NILP (mouse_face) && BUFFERP (object))
7342 {
7343 /* Find the range of text around this char that
7344 should be active. */
7345 Lisp_Object before, after, beginning, end;
7346 int ignore;
7347
7348 beginning = Fmarker_position (w->start);
7349 end = make_number (BUF_Z (XBUFFER (object))
7350 - XFASTINT (w->window_end_pos));
7351 before
7352 = Fprevious_single_property_change (make_number (pos + 1),
7353 Qmouse_face,
7354 object, beginning);
7355 after
7356 = Fnext_single_property_change (position, Qmouse_face,
7357 object, end);
7358
7359 /* Record this as the current active region. */
7360 fast_find_position (w, XFASTINT (before),
7361 &dpyinfo->mouse_face_beg_col,
7362 &dpyinfo->mouse_face_beg_row,
7363 &dpyinfo->mouse_face_beg_x,
7364 &dpyinfo->mouse_face_beg_y, Qnil);
7365 dpyinfo->mouse_face_past_end
7366 = !fast_find_position (w, XFASTINT (after),
7367 &dpyinfo->mouse_face_end_col,
7368 &dpyinfo->mouse_face_end_row,
7369 &dpyinfo->mouse_face_end_x,
7370 &dpyinfo->mouse_face_end_y, Qnil);
7371 dpyinfo->mouse_face_window = window;
7372
7373 if (BUFFERP (object))
1a578e9b
AC
7374 dpyinfo->mouse_face_face_id
7375 = face_at_buffer_position (w, pos, 0, 0,
1b7334a4
KS
7376 &ignore, pos + 1,
7377 !dpyinfo->mouse_face_hidden);
1a578e9b 7378
e0f712ba
AC
7379 /* Display it as active. */
7380 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7381 /* TODO: mouse cursor changes. */
7382 }
7383 else if (!NILP (mouse_face) && STRINGP (object))
7384 {
7385 Lisp_Object b, e;
7386 int ignore;
7387
7388 b = Fprevious_single_property_change (make_number (pos + 1),
7389 Qmouse_face,
7390 object, Qnil);
7391 e = Fnext_single_property_change (position, Qmouse_face,
7392 object, Qnil);
7393 if (NILP (b))
7394 b = make_number (0);
7395 if (NILP (e))
d5db4077 7396 e = make_number (SCHARS (object) - 1);
e0f712ba 7397 fast_find_string_pos (w, XINT (b), object,
1a578e9b
AC
7398 &dpyinfo->mouse_face_beg_col,
7399 &dpyinfo->mouse_face_beg_row,
7400 &dpyinfo->mouse_face_beg_x,
e0f712ba
AC
7401 &dpyinfo->mouse_face_beg_y, 0);
7402 fast_find_string_pos (w, XINT (e), object,
7403 &dpyinfo->mouse_face_end_col,
7404 &dpyinfo->mouse_face_end_row,
7405 &dpyinfo->mouse_face_end_x,
7406 &dpyinfo->mouse_face_end_y, 1);
7407 dpyinfo->mouse_face_past_end = 0;
7408 dpyinfo->mouse_face_window = window;
7409 dpyinfo->mouse_face_face_id
7410 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7411 glyph->face_id, 1);
7412 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7413 /* TODO: mouse cursor changes. */
1a578e9b 7414 }
e0f712ba 7415 else if (STRINGP (object) && NILP (mouse_face))
1a578e9b 7416 {
e0f712ba
AC
7417 /* A string which doesn't have mouse-face, but
7418 the text ``under'' it might have. */
7419 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7420 int start = MATRIX_ROW_START_CHARPOS (r);
177c0ea7 7421
e0f712ba
AC
7422 pos = string_buffer_position (w, object, start);
7423 if (pos > 0)
7424 mouse_face = get_char_property_and_overlay (make_number (pos),
7425 Qmouse_face,
7426 w->buffer,
7427 &overlay);
7428 if (!NILP (mouse_face) && !NILP (overlay))
1a578e9b 7429 {
e0f712ba
AC
7430 Lisp_Object before = Foverlay_start (overlay);
7431 Lisp_Object after = Foverlay_end (overlay);
7432 int ignore;
7433
7434 /* Note that we might not be able to find position
7435 BEFORE in the glyph matrix if the overlay is
7436 entirely covered by a `display' property. In
7437 this case, we overshoot. So let's stop in
7438 the glyph matrix before glyphs for OBJECT. */
7439 fast_find_position (w, XFASTINT (before),
7440 &dpyinfo->mouse_face_beg_col,
7441 &dpyinfo->mouse_face_beg_row,
7442 &dpyinfo->mouse_face_beg_x,
7443 &dpyinfo->mouse_face_beg_y,
7444 object);
177c0ea7 7445
e0f712ba
AC
7446 dpyinfo->mouse_face_past_end
7447 = !fast_find_position (w, XFASTINT (after),
7448 &dpyinfo->mouse_face_end_col,
7449 &dpyinfo->mouse_face_end_row,
7450 &dpyinfo->mouse_face_end_x,
7451 &dpyinfo->mouse_face_end_y,
7452 Qnil);
7453 dpyinfo->mouse_face_window = window;
7454 dpyinfo->mouse_face_face_id
7455 = face_at_buffer_position (w, pos, 0, 0,
1b7334a4
KS
7456 &ignore, pos + 1,
7457 !dpyinfo->mouse_face_hidden);
e0f712ba
AC
7458
7459 /* Display it as active. */
7460 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7461 /* TODO: mouse cursor changes. */
1a578e9b
AC
7462 }
7463 }
7464 }
1a578e9b 7465
e0f712ba
AC
7466 check_help_echo:
7467
7468 /* Look for a `help-echo' property. */
7469 {
7470 Lisp_Object help, overlay;
7471
7472 /* Check overlays first. */
7473 help = overlay = Qnil;
7474 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7475 {
7476 overlay = overlay_vec[i];
177c0ea7 7477 help = Foverlay_get (overlay, Qhelp_echo);
e0f712ba
AC
7478 }
7479
7480 if (!NILP (help))
7481 {
7482 help_echo = help;
7483 help_echo_window = window;
7484 help_echo_object = overlay;
7485 help_echo_pos = pos;
7486 }
7487 else
7488 {
7489 Lisp_Object object = glyph->object;
7490 int charpos = glyph->charpos;
7491
7492 /* Try text properties. */
7493 if (STRINGP (object)
7494 && charpos >= 0
d5db4077 7495 && charpos < SCHARS (object))
e0f712ba
AC
7496 {
7497 help = Fget_text_property (make_number (charpos),
7498 Qhelp_echo, object);
7499 if (NILP (help))
7500 {
7501 /* If the string itself doesn't specify a help-echo,
7502 see if the buffer text ``under'' it does. */
7503 struct glyph_row *r
7504 = MATRIX_ROW (w->current_matrix, vpos);
7505 int start = MATRIX_ROW_START_CHARPOS (r);
7506 int pos = string_buffer_position (w, object, start);
7507 if (pos > 0)
7508 {
7509 help = Fget_char_property (make_number (pos),
7510 Qhelp_echo, w->buffer);
7511 if (!NILP (help))
7512 {
7513 charpos = pos;
7514 object = w->buffer;
7515 }
7516 }
7517 }
7518 }
7519 else if (BUFFERP (object)
7520 && charpos >= BEGV
7521 && charpos < ZV)
7522 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7523 object);
177c0ea7 7524
e0f712ba
AC
7525 if (!NILP (help))
7526 {
7527 help_echo = help;
7528 help_echo_window = window;
7529 help_echo_object = object;
7530 help_echo_pos = charpos;
7531 }
7532 }
7533 }
7534
7535 BEGV = obegv;
7536 ZV = ozv;
7537 current_buffer = obuf;
7538 }
7539
7540 set_cursor:
7541 /* TODO: mouse cursor changes. */
7542 ;
7543}
7544
7545static void
7546redo_mouse_highlight ()
7547{
7548 if (!NILP (last_mouse_motion_frame)
7549 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
1a578e9b
AC
7550 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7551 last_mouse_motion_position.h,
7552 last_mouse_motion_position.v);
7553}
7554
7555
7556\f
7557/***********************************************************************
7558 Tool-bars
7559 ***********************************************************************/
7560
7561static int x_tool_bar_item P_ ((struct frame *, int, int,
7562 struct glyph **, int *, int *, int *));
7563
7564/* Tool-bar item index of the item on which a mouse button was pressed
7565 or -1. */
7566
7567static int last_tool_bar_item;
7568
7569
7570/* Get information about the tool-bar item at position X/Y on frame F.
7571 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7572 the current matrix of the tool-bar window of F, or NULL if not
7573 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7574 item in F->current_tool_bar_items. Value is
7575
7576 -1 if X/Y is not on a tool-bar item
7577 0 if X/Y is on the same item that was highlighted before.
7578 1 otherwise. */
7579
7580static int
7581x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7582 struct frame *f;
7583 int x, y;
7584 struct glyph **glyph;
7585 int *hpos, *vpos, *prop_idx;
7586{
7587 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7588 struct window *w = XWINDOW (f->tool_bar_window);
7589 int area;
7590
7591 /* Find the glyph under X/Y. */
e0f712ba 7592 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
1a578e9b
AC
7593 if (*glyph == NULL)
7594 return -1;
7595
7596 /* Get the start of this tool-bar item's properties in
7597 f->current_tool_bar_items. */
7598 if (!tool_bar_item_info (f, *glyph, prop_idx))
7599 return -1;
7600
7601 /* Is mouse on the highlighted item? */
7602 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7603 && *vpos >= dpyinfo->mouse_face_beg_row
7604 && *vpos <= dpyinfo->mouse_face_end_row
7605 && (*vpos > dpyinfo->mouse_face_beg_row
7606 || *hpos >= dpyinfo->mouse_face_beg_col)
7607 && (*vpos < dpyinfo->mouse_face_end_row
7608 || *hpos < dpyinfo->mouse_face_end_col
7609 || dpyinfo->mouse_face_past_end))
7610 return 0;
177c0ea7 7611
1a578e9b
AC
7612 return 1;
7613}
7614
7615
7616/* Handle mouse button event on the tool-bar of frame F, at
7617 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7618 or ButtonRelase. */
7619
7620static void
7621x_handle_tool_bar_click (f, button_event)
7622 struct frame *f;
7623 EventRecord *button_event;
7624{
7625 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7626 struct window *w = XWINDOW (f->tool_bar_window);
7627 int hpos, vpos, prop_idx;
7628 struct glyph *glyph;
7629 Lisp_Object enabled_p;
7630 int x = button_event->where.h;
7631 int y = button_event->where.v;
177c0ea7 7632
1a578e9b
AC
7633 /* If not on the highlighted tool-bar item, return. */
7634 frame_to_window_pixel_xy (w, &x, &y);
7635 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7636 return;
7637
7638 /* If item is disabled, do nothing. */
2d4bc735 7639 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
1a578e9b
AC
7640 if (NILP (enabled_p))
7641 return;
177c0ea7 7642
1a578e9b
AC
7643 if (button_event->what == mouseDown)
7644 {
7645 /* Show item in pressed state. */
7646 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7647 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7648 last_tool_bar_item = prop_idx;
7649 }
7650 else
7651 {
7652 Lisp_Object key, frame;
7653 struct input_event event;
7654
7655 /* Show item in released state. */
7656 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7657 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7658
2d4bc735 7659 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
1a578e9b
AC
7660
7661 XSETFRAME (frame, f);
7662 event.kind = TOOL_BAR_EVENT;
7663 event.frame_or_window = frame;
7664 event.arg = frame;
7665 kbd_buffer_store_event (&event);
7666
7667 event.kind = TOOL_BAR_EVENT;
7668 event.frame_or_window = frame;
7669 event.arg = key;
7670 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7671 button_event->modifiers);
7672 kbd_buffer_store_event (&event);
7673 last_tool_bar_item = -1;
7674 }
7675}
7676
7677
7678/* Possibly highlight a tool-bar item on frame F when mouse moves to
7679 tool-bar window-relative coordinates X/Y. Called from
7680 note_mouse_highlight. */
7681
7682static void
7683note_tool_bar_highlight (f, x, y)
7684 struct frame *f;
7685 int x, y;
7686{
7687 Lisp_Object window = f->tool_bar_window;
7688 struct window *w = XWINDOW (window);
7689 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7690 int hpos, vpos;
7691 struct glyph *glyph;
7692 struct glyph_row *row;
7693 int i;
7694 Lisp_Object enabled_p;
7695 int prop_idx;
7696 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7697 int mouse_down_p, rc;
7698
7699 /* Function note_mouse_highlight is called with negative x(y
7700 values when mouse moves outside of the frame. */
7701 if (x <= 0 || y <= 0)
7702 {
7703 clear_mouse_face (dpyinfo);
7704 return;
7705 }
7706
7707 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7708 if (rc < 0)
7709 {
7710 /* Not on tool-bar item. */
7711 clear_mouse_face (dpyinfo);
7712 return;
7713 }
7714 else if (rc == 0)
7715 /* On same tool-bar item as before. */
7716 goto set_help_echo;
7717
7718 clear_mouse_face (dpyinfo);
177c0ea7 7719
1a578e9b
AC
7720 /* Mouse is down, but on different tool-bar item? */
7721 mouse_down_p = (dpyinfo->grabbed
7722 && f == last_mouse_frame
7723 && FRAME_LIVE_P (f));
7724 if (mouse_down_p
7725 && last_tool_bar_item != prop_idx)
7726 return;
7727
7728 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7729 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
177c0ea7 7730
1a578e9b 7731 /* If tool-bar item is not enabled, don't highlight it. */
2d4bc735 7732 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
1a578e9b
AC
7733 if (!NILP (enabled_p))
7734 {
7735 /* Compute the x-position of the glyph. In front and past the
7736 image is a space. We include this is the highlighted area. */
7737 row = MATRIX_ROW (w->current_matrix, vpos);
7738 for (i = x = 0; i < hpos; ++i)
7739 x += row->glyphs[TEXT_AREA][i].pixel_width;
177c0ea7 7740
1a578e9b
AC
7741 /* Record this as the current active region. */
7742 dpyinfo->mouse_face_beg_col = hpos;
7743 dpyinfo->mouse_face_beg_row = vpos;
7744 dpyinfo->mouse_face_beg_x = x;
7745 dpyinfo->mouse_face_beg_y = row->y;
7746 dpyinfo->mouse_face_past_end = 0;
177c0ea7 7747
1a578e9b
AC
7748 dpyinfo->mouse_face_end_col = hpos + 1;
7749 dpyinfo->mouse_face_end_row = vpos;
7750 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7751 dpyinfo->mouse_face_end_y = row->y;
7752 dpyinfo->mouse_face_window = window;
7753 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
177c0ea7 7754
1a578e9b
AC
7755 /* Display it as active. */
7756 show_mouse_face (dpyinfo, draw);
7757 dpyinfo->mouse_face_image_state = draw;
7758 }
177c0ea7 7759
1a578e9b 7760 set_help_echo:
177c0ea7 7761
1a578e9b
AC
7762 /* Set help_echo to a help string.to display for this tool-bar item.
7763 XTread_socket does the rest. */
7764 help_echo_object = help_echo_window = Qnil;
7765 help_echo_pos = -1;
2d4bc735 7766 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
1a578e9b 7767 if (NILP (help_echo))
2d4bc735 7768 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
1a578e9b
AC
7769}
7770
7771
7772\f
e0f712ba
AC
7773/* Find the glyph matrix position of buffer position CHARPOS in window
7774 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7775 current glyphs must be up to date. If CHARPOS is above window
7776 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7777 of last line in W. In the row containing CHARPOS, stop before glyphs
7778 having STOP as object. */
7779
7780#if 0 /* This is a version of fast_find_position that's more correct
7781 in the presence of hscrolling, for example. I didn't install
7782 it right away because the problem fixed is minor, it failed
177c0ea7 7783 in 20.x as well, and I think it's too risky to install
e0f712ba
AC
7784 so near the release of 21.1. 2001-09-25 gerd. */
7785
7786static int
7787fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7788 struct window *w;
7789 int charpos;
7790 int *hpos, *vpos, *x, *y;
7791 Lisp_Object stop;
7792{
7793 struct glyph_row *row, *first;
7794 struct glyph *glyph, *end;
7795 int i, past_end = 0;
7796
7797 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7798 row = row_containing_pos (w, charpos, first, NULL, 0);
7799 if (row == NULL)
7800 {
7801 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7802 {
7803 *x = *y = *hpos = *vpos = 0;
7804 return 0;
7805 }
7806 else
7807 {
7808 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7809 past_end = 1;
7810 }
7811 }
7812
7813 *x = row->x;
7814 *y = row->y;
7815 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
177c0ea7 7816
e0f712ba
AC
7817 glyph = row->glyphs[TEXT_AREA];
7818 end = glyph + row->used[TEXT_AREA];
177c0ea7 7819
e0f712ba
AC
7820 /* Skip over glyphs not having an object at the start of the row.
7821 These are special glyphs like truncation marks on terminal
7822 frames. */
7823 if (row->displays_text_p)
7824 while (glyph < end
7825 && INTEGERP (glyph->object)
7826 && !EQ (stop, glyph->object)
7827 && glyph->charpos < 0)
7828 {
7829 *x += glyph->pixel_width;
7830 ++glyph;
7831 }
7832
7833 while (glyph < end
7834 && !INTEGERP (glyph->object)
7835 && !EQ (stop, glyph->object)
7836 && (!BUFFERP (glyph->object)
7837 || glyph->charpos < charpos))
7838 {
7839 *x += glyph->pixel_width;
7840 ++glyph;
7841 }
7842
7843 *hpos = glyph - row->glyphs[TEXT_AREA];
7844 return past_end;
7845}
7846
7847#else /* not 0 */
1a578e9b
AC
7848
7849static int
e0f712ba 7850fast_find_position (w, pos, hpos, vpos, x, y, stop)
1a578e9b
AC
7851 struct window *w;
7852 int pos;
7853 int *hpos, *vpos, *x, *y;
e0f712ba 7854 Lisp_Object stop;
1a578e9b
AC
7855{
7856 int i;
7857 int lastcol;
7858 int maybe_next_line_p = 0;
7859 int line_start_position;
7860 int yb = window_text_bottom_y (w);
e0f712ba
AC
7861 struct glyph_row *row, *best_row;
7862 int row_vpos, best_row_vpos;
1a578e9b
AC
7863 int current_x;
7864
e0f712ba
AC
7865 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7866 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7867
1a578e9b
AC
7868 while (row->y < yb)
7869 {
7870 if (row->used[TEXT_AREA])
7871 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7872 else
7873 line_start_position = 0;
7874
7875 if (line_start_position > pos)
7876 break;
7877 /* If the position sought is the end of the buffer,
7878 don't include the blank lines at the bottom of the window. */
7879 else if (line_start_position == pos
e0f712ba 7880 && pos == BUF_ZV (XBUFFER (w->buffer)))
1a578e9b
AC
7881 {
7882 maybe_next_line_p = 1;
7883 break;
7884 }
7885 else if (line_start_position > 0)
e0f712ba
AC
7886 {
7887 best_row = row;
7888 best_row_vpos = row_vpos;
7889 }
1a578e9b
AC
7890
7891 if (row->y + row->height >= yb)
e0f712ba
AC
7892 break;
7893
1a578e9b
AC
7894 ++row;
7895 ++row_vpos;
7896 }
e0f712ba 7897
1a578e9b
AC
7898 /* Find the right column within BEST_ROW. */
7899 lastcol = 0;
7900 current_x = best_row->x;
7901 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7902 {
7903 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
e0f712ba 7904 int charpos = glyph->charpos;
1a578e9b 7905
e0f712ba 7906 if (BUFFERP (glyph->object))
1a578e9b 7907 {
e0f712ba
AC
7908 if (charpos == pos)
7909 {
7910 *hpos = i;
7911 *vpos = best_row_vpos;
7912 *x = current_x;
7913 *y = best_row->y;
7914 return 1;
7915 }
7916 else if (charpos > pos)
7917 break;
1a578e9b 7918 }
e0f712ba 7919 else if (EQ (glyph->object, stop))
1a578e9b 7920 break;
1a578e9b 7921
e0f712ba
AC
7922 if (charpos > 0)
7923 lastcol = i;
1a578e9b
AC
7924 current_x += glyph->pixel_width;
7925 }
7926
7927 /* If we're looking for the end of the buffer,
7928 and we didn't find it in the line we scanned,
7929 use the start of the following line. */
7930 if (maybe_next_line_p)
7931 {
7932 ++best_row;
7933 ++best_row_vpos;
7934 lastcol = 0;
7935 current_x = best_row->x;
7936 }
7937
7938 *vpos = best_row_vpos;
7939 *hpos = lastcol + 1;
7940 *x = current_x;
7941 *y = best_row->y;
7942 return 0;
7943}
7944
e0f712ba
AC
7945#endif /* not 0 */
7946
7947
7948/* Find the position of the glyph for position POS in OBJECT in
7949 window W's current matrix, and return in *X/*Y the pixel
7950 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7951
7952 RIGHT_P non-zero means return the position of the right edge of the
7953 glyph, RIGHT_P zero means return the left edge position.
7954
7955 If no glyph for POS exists in the matrix, return the position of
7956 the glyph with the next smaller position that is in the matrix, if
7957 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7958 exists in the matrix, return the position of the glyph with the
7959 next larger position in OBJECT.
7960
7961 Value is non-zero if a glyph was found. */
7962
7963static int
7964fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7965 struct window *w;
7966 int pos;
7967 Lisp_Object object;
7968 int *hpos, *vpos, *x, *y;
7969 int right_p;
7970{
7971 int yb = window_text_bottom_y (w);
7972 struct glyph_row *r;
7973 struct glyph *best_glyph = NULL;
7974 struct glyph_row *best_row = NULL;
7975 int best_x = 0;
7976
7977 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7978 r->enabled_p && r->y < yb;
7979 ++r)
7980 {
7981 struct glyph *g = r->glyphs[TEXT_AREA];
7982 struct glyph *e = g + r->used[TEXT_AREA];
7983 int gx;
7984
7985 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7986 if (EQ (g->object, object))
7987 {
7988 if (g->charpos == pos)
7989 {
7990 best_glyph = g;
7991 best_x = gx;
7992 best_row = r;
7993 goto found;
7994 }
7995 else if (best_glyph == NULL
7996 || ((abs (g->charpos - pos)
7997 < abs (best_glyph->charpos - pos))
7998 && (right_p
7999 ? g->charpos < pos
8000 : g->charpos > pos)))
8001 {
8002 best_glyph = g;
8003 best_x = gx;
8004 best_row = r;
8005 }
8006 }
8007 }
8008
8009 found:
8010
8011 if (best_glyph)
8012 {
8013 *x = best_x;
8014 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
8015
8016 if (right_p)
8017 {
8018 *x += best_glyph->pixel_width;
8019 ++*hpos;
8020 }
177c0ea7 8021
e0f712ba
AC
8022 *y = best_row->y;
8023 *vpos = best_row - w->current_matrix->rows;
8024 }
8025
8026 return best_glyph != NULL;
8027}
8028
1a578e9b
AC
8029
8030/* Display the active region described by mouse_face_*
8031 in its mouse-face if HL > 0, in its normal face if HL = 0. */
8032
8033static void
8034show_mouse_face (dpyinfo, draw)
8035 struct mac_display_info *dpyinfo;
8036 enum draw_glyphs_face draw;
8037{
8038 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
8039 struct frame *f = XFRAME (WINDOW_FRAME (w));
177c0ea7 8040
e0f712ba
AC
8041 if (/* If window is in the process of being destroyed, don't bother
8042 to do anything. */
8043 w->current_matrix != NULL
8044 /* Don't update mouse highlight if hidden */
8045 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
8046 /* Recognize when we are called to operate on rows that don't exist
8047 anymore. This can happen when a window is split. */
8048 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
1a578e9b 8049 {
e0f712ba
AC
8050 int phys_cursor_on_p = w->phys_cursor_on_p;
8051 struct glyph_row *row, *first, *last;
1a578e9b 8052
e0f712ba
AC
8053 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
8054 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
177c0ea7 8055
e0f712ba 8056 for (row = first; row <= last && row->enabled_p; ++row)
1a578e9b 8057 {
e0f712ba 8058 int start_hpos, end_hpos, start_x;
1a578e9b 8059
e0f712ba
AC
8060 /* For all but the first row, the highlight starts at column 0. */
8061 if (row == first)
8062 {
8063 start_hpos = dpyinfo->mouse_face_beg_col;
8064 start_x = dpyinfo->mouse_face_beg_x;
8065 }
8066 else
8067 {
8068 start_hpos = 0;
8069 start_x = 0;
8070 }
1a578e9b 8071
e0f712ba
AC
8072 if (row == last)
8073 end_hpos = dpyinfo->mouse_face_end_col;
8074 else
8075 end_hpos = row->used[TEXT_AREA];
1a578e9b 8076
e0f712ba
AC
8077 if (end_hpos > start_hpos)
8078 {
177c0ea7 8079 x_draw_glyphs (w, start_x, row, TEXT_AREA,
e0f712ba 8080 start_hpos, end_hpos, draw, 0);
1a578e9b 8081
e0f712ba
AC
8082 row->mouse_face_p
8083 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8084 }
8085 }
1a578e9b 8086
e0f712ba
AC
8087 /* When we've written over the cursor, arrange for it to
8088 be displayed again. */
8089 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8090 x_display_cursor (w, 1,
8091 w->phys_cursor.hpos, w->phys_cursor.vpos,
8092 w->phys_cursor.x, w->phys_cursor.y);
8093 }
1a578e9b 8094
1a578e9b
AC
8095#if 0 /* MAC_TODO: mouse cursor */
8096 /* Change the mouse cursor. */
8097 if (draw == DRAW_NORMAL_TEXT)
8098 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8099 f->output_data.x->text_cursor);
8100 else if (draw == DRAW_MOUSE_FACE)
8101 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8102 f->output_data.x->cross_cursor);
8103 else
8104 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8105 f->output_data.x->nontext_cursor);
8106#endif
1a578e9b
AC
8107}
8108
8109/* Clear out the mouse-highlighted active region.
8110 Redraw it un-highlighted first. */
8111
e0f712ba 8112static int
1a578e9b
AC
8113clear_mouse_face (dpyinfo)
8114 struct mac_display_info *dpyinfo;
8115{
e0f712ba
AC
8116 int cleared = 0;
8117
1a578e9b 8118 if (! NILP (dpyinfo->mouse_face_window))
e0f712ba
AC
8119 {
8120 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8121 cleared = 1;
8122 }
1a578e9b
AC
8123
8124 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8125 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8126 dpyinfo->mouse_face_window = Qnil;
e0f712ba
AC
8127 dpyinfo->mouse_face_overlay = Qnil;
8128 return cleared;
1a578e9b
AC
8129}
8130
8131
8132/* Clear any mouse-face on window W. This function is part of the
8133 redisplay interface, and is called from try_window_id and similar
8134 functions to ensure the mouse-highlight is off. */
8135
e0f712ba 8136static void
1a578e9b
AC
8137x_clear_mouse_face (w)
8138 struct window *w;
8139{
8140 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8141 Lisp_Object window;
8142
e0f712ba 8143 BLOCK_INPUT;
1a578e9b
AC
8144 XSETWINDOW (window, w);
8145 if (EQ (window, dpyinfo->mouse_face_window))
8146 clear_mouse_face (dpyinfo);
e0f712ba 8147 UNBLOCK_INPUT;
1a578e9b
AC
8148}
8149
8150
8151/* Just discard the mouse face information for frame F, if any.
8152 This is used when the size of F is changed. */
8153
e0f712ba 8154void
1a578e9b
AC
8155cancel_mouse_face (f)
8156 FRAME_PTR f;
8157{
8158 Lisp_Object window;
8159 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8160
8161 window = dpyinfo->mouse_face_window;
8162 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8163 {
8164 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8165 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8166 dpyinfo->mouse_face_window = Qnil;
8167 }
8168}
8169\f
8170static struct scroll_bar *x_window_to_scroll_bar ();
8171static void x_scroll_bar_report_motion ();
e0f712ba
AC
8172static void x_check_fullscreen P_ ((struct frame *));
8173static void x_check_fullscreen_move P_ ((struct frame *));
8174static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8175
8176
8177/* Try to determine frame pixel position and size of the glyph under
8178 frame pixel coordinates X/Y on frame F . Return the position and
8179 size in *RECT. Value is non-zero if we could compute these
8180 values. */
8181
8182static int
8183glyph_rect (f, x, y, rect)
8184 struct frame *f;
8185 int x, y;
8186 Rect *rect;
8187{
8188 Lisp_Object window;
8189 int part;
8190
8191 window = window_from_coordinates (f, x, y, &part, 0);
8192 if (!NILP (window))
8193 {
8194 struct window *w = XWINDOW (window);
8195 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8196 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8197
8198 frame_to_window_pixel_xy (w, &x, &y);
8199
8200 for (; r < end && r->enabled_p; ++r)
8201 if (r->y <= y && r->y + r->height > y)
8202 {
8203 /* Found the row at y. */
8204 struct glyph *g = r->glyphs[TEXT_AREA];
8205 struct glyph *end = g + r->used[TEXT_AREA];
8206 int gx;
8207
8208 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8209 rect->bottom = rect->top + r->height;
8210
8211 if (x < r->x)
8212 {
8213 /* x is to the left of the first glyph in the row. */
8214 rect->left = XINT (w->left);
8215 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8216 return 1;
8217 }
8218
8219 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8220 if (gx <= x && gx + g->pixel_width > x)
8221 {
8222 /* x is on a glyph. */
8223 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8224 rect->right = rect->left + g->pixel_width;
8225 return 1;
8226 }
8227
8228 /* x is to the right of the last glyph in the row. */
8229 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8230 rect->right = XINT (w->left) + XINT (w->width);
8231 return 1;
8232 }
8233 }
8234
8235 /* The y is not on any row. */
8236 return 0;
8237}
8238
8239/* Record the position of the mouse in last_mouse_glyph. */
8240static void
8241remember_mouse_glyph (f1, gx, gy)
8242 struct frame * f1;
8243 int gx, gy;
8244{
8245 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8246 {
8247 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8248 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8249
8250 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8251 round down even for negative values. */
8252 if (gx < 0)
8253 gx -= width - 1;
8254 if (gy < 0)
8255 gy -= height - 1;
8256#if 0
8257 /* This was the original code from XTmouse_position, but it seems
8258 to give the position of the glyph diagonally next to the one
8259 the mouse is over. */
8260 gx = (gx + width - 1) / width * width;
8261 gy = (gy + height - 1) / height * height;
8262#else
8263 gx = gx / width * width;
8264 gy = gy / height * height;
8265#endif
8266
8267 last_mouse_glyph.left = gx;
8268 last_mouse_glyph.top = gy;
8269 last_mouse_glyph.right = gx + width;
8270 last_mouse_glyph.bottom = gy + height;
8271 }
8272}
1a578e9b
AC
8273
8274/* Return the current position of the mouse.
8275 *fp should be a frame which indicates which display to ask about.
8276
8277 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8278 and *part to the frame, window, and scroll bar part that the mouse
8279 is over. Set *x and *y to the portion and whole of the mouse's
8280 position on the scroll bar.
8281
8282 If the mouse movement started elsewhere, set *fp to the frame the
8283 mouse is on, *bar_window to nil, and *x and *y to the character cell
8284 the mouse is over.
8285
8286 Set *time to the server time-stamp for the time at which the mouse
8287 was at this position.
8288
8289 Don't store anything if we don't have a valid set of values to report.
8290
8291 This clears the mouse_moved flag, so we can wait for the next mouse
8292 movement. */
8293
e0f712ba 8294static void
1a578e9b
AC
8295XTmouse_position (fp, insist, bar_window, part, x, y, time)
8296 FRAME_PTR *fp;
8297 int insist;
8298 Lisp_Object *bar_window;
8299 enum scroll_bar_part *part;
8300 Lisp_Object *x, *y;
8301 unsigned long *time;
8302{
8303 Point mouse_pos;
8304 int ignore1, ignore2;
8305 WindowPtr wp = FrontWindow ();
5883787c 8306 struct frame *f;
1a578e9b
AC
8307 Lisp_Object frame, tail;
8308
5883787c 8309 if (is_emacs_window(wp))
177c0ea7 8310 f = ((mac_output *) GetWRefCon (wp))->mFP;
5883787c 8311
1a578e9b
AC
8312 BLOCK_INPUT;
8313
8314 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8315 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8316 else
8317 {
8318 /* Clear the mouse-moved flag for every frame on this display. */
8319 FOR_EACH_FRAME (tail, frame)
8320 XFRAME (frame)->mouse_moved = 0;
8321
8322 last_mouse_scroll_bar = Qnil;
8323
e0f712ba
AC
8324#if TARGET_API_MAC_CARBON
8325 SetPort (GetWindowPort (wp));
8326#else
1a578e9b 8327 SetPort (wp);
e0f712ba
AC
8328#endif
8329
1a578e9b
AC
8330 GetMouse (&mouse_pos);
8331
8332 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8333 &last_mouse_glyph, insist);
8334
8335 *bar_window = Qnil;
8336 *part = scroll_bar_handle;
8337 *fp = f;
8338 XSETINT (*x, mouse_pos.h);
8339 XSETINT (*y, mouse_pos.v);
8340 *time = last_mouse_movement_time;
8341 }
177c0ea7 8342
1a578e9b
AC
8343 UNBLOCK_INPUT;
8344}
8345
8346\f
8347/************************************************************************
8348 Scroll bars, general
8349 ************************************************************************/
177c0ea7 8350
1a578e9b
AC
8351/* Create a scroll bar and return the scroll bar vector for it. W is
8352 the Emacs window on which to create the scroll bar. TOP, LEFT,
e0f712ba 8353 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
1a578e9b
AC
8354 scroll bar. */
8355
8356static struct scroll_bar *
8357x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8358 struct window *w;
8359 int top, left, width, height, disp_top, disp_height;
8360{
8361 struct frame *f = XFRAME (w->frame);
8362 struct scroll_bar *bar
8363 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8364 Rect r;
8365 ControlHandle ch;
8366
8367 BLOCK_INPUT;
8368
8369 r.left = left;
8370 r.top = disp_top;
8371 r.right = left + width;
8372 r.bottom = disp_top + disp_height;
177c0ea7 8373
e0f712ba
AC
8374#ifdef TARGET_API_MAC_CARBON
8375 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8376 kControlScrollBarProc, 0L);
8377#else
1a578e9b
AC
8378 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8379 0L);
e0f712ba 8380#endif
1a578e9b
AC
8381 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8382 SetControlReference (ch, (long) bar);
8383
8384 XSETWINDOW (bar->window, w);
8385 XSETINT (bar->top, top);
8386 XSETINT (bar->left, left);
8387 XSETINT (bar->width, width);
8388 XSETINT (bar->height, height);
8389 XSETINT (bar->start, 0);
8390 XSETINT (bar->end, 0);
8391 bar->dragging = Qnil;
8392
8393 /* Add bar to its frame's list of scroll bars. */
8394 bar->next = FRAME_SCROLL_BARS (f);
8395 bar->prev = Qnil;
8396 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8397 if (!NILP (bar->next))
8398 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8399
8400 UNBLOCK_INPUT;
8401 return bar;
8402}
8403
8404
8405/* Draw BAR's handle in the proper position.
177c0ea7 8406
1a578e9b
AC
8407 If the handle is already drawn from START to END, don't bother
8408 redrawing it, unless REBUILD is non-zero; in that case, always
8409 redraw it. (REBUILD is handy for drawing the handle after expose
8410 events.)
8411
8412 Normally, we want to constrain the start and end of the handle to
8413 fit inside its rectangle, but if the user is dragging the scroll
8414 bar handle, we want to let them drag it down all the way, so that
8415 the bar's top is as far down as it goes; otherwise, there's no way
8416 to move to the very end of the buffer. */
8417
8418static void
8419x_scroll_bar_set_handle (bar, start, end, rebuild)
8420 struct scroll_bar *bar;
8421 int start, end;
8422 int rebuild;
8423{
8424 int dragging = ! NILP (bar->dragging);
8425 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8426 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba
AC
8427 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8428 int length = end - start;
1a578e9b
AC
8429
8430 /* If the display is already accurate, do nothing. */
8431 if (! rebuild
8432 && start == XINT (bar->start)
8433 && end == XINT (bar->end))
8434 return;
8435
8436 BLOCK_INPUT;
8437
e0f712ba
AC
8438 /* Make sure the values are reasonable, and try to preserve the
8439 distance between start and end. */
8440 if (start < 0)
8441 start = 0;
8442 else if (start > top_range)
8443 start = top_range;
8444 end = start + length;
177c0ea7 8445
e0f712ba
AC
8446 if (end < start)
8447 end = start;
8448 else if (end > top_range && ! dragging)
8449 end = top_range;
8450
8451 /* Store the adjusted setting in the scroll bar. */
8452 XSETINT (bar->start, start);
8453 XSETINT (bar->end, end);
8454
8455 /* Clip the end position, just for display. */
8456 if (end > top_range)
8457 end = top_range;
8458
8459 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8460 top positions, to make sure the handle is always at least that
8461 many pixels tall. */
8462 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8463
8464 SetControlMinimum (ch, 0);
8465 /* Don't inadvertently activate deactivated scroll bars */
8466 if (GetControlMaximum (ch) != -1)
8467 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8468 - (end - start));
8469 SetControlValue (ch, start);
8470#if TARGET_API_MAC_CARBON
8471 SetControlViewSize (ch, end - start);
1a578e9b 8472#endif
1a578e9b
AC
8473
8474 UNBLOCK_INPUT;
8475}
8476
8477
8478/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8479 nil. */
8480
8481static void
8482x_scroll_bar_remove (bar)
8483 struct scroll_bar *bar;
8484{
8485 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba 8486
1a578e9b
AC
8487 BLOCK_INPUT;
8488
8489 /* Destroy the Mac scroll bar control */
8490 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8491
8492 /* Disassociate this scroll bar from its window. */
8493 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8494
8495 UNBLOCK_INPUT;
8496}
8497
1a578e9b
AC
8498/* Set the handle of the vertical scroll bar for WINDOW to indicate
8499 that we are displaying PORTION characters out of a total of WHOLE
8500 characters, starting at POSITION. If WINDOW has no scroll bar,
8501 create one. */
1a578e9b
AC
8502static void
8503XTset_vertical_scroll_bar (w, portion, whole, position)
8504 struct window *w;
8505 int portion, whole, position;
8506{
8507 struct frame *f = XFRAME (w->frame);
8508 struct scroll_bar *bar;
8509 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8510 int window_x, window_y, window_width, window_height;
8511
8512 /* Get window dimensions. */
8513 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8514 top = window_y;
e0f712ba
AC
8515#ifdef MAC_OSX
8516 width = 16;
8517#else
1a578e9b 8518 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
e0f712ba 8519#endif
1a578e9b
AC
8520 height = window_height;
8521
8522 /* Compute the left edge of the scroll bar area. */
8523 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8524 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8525 else
8526 left = XFASTINT (w->left);
8527 left *= CANON_X_UNIT (f);
8528 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8529
8530 /* Compute the width of the scroll bar which might be less than
8531 the width of the area reserved for the scroll bar. */
8532 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8533 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8534 else
8535 sb_width = width;
8536
8537 /* Compute the left edge of the scroll bar. */
8538 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
177c0ea7 8539 sb_left = left + width - sb_width - (width - sb_width) / 2;
1a578e9b
AC
8540 else
8541 sb_left = left + (width - sb_width) / 2;
177c0ea7 8542
1a578e9b
AC
8543 /* Adjustments according to Inside Macintosh to make it look nice */
8544 disp_top = top;
8545 disp_height = height;
8546 if (disp_top == 0)
8547 {
8548 disp_top = -1;
8549 disp_height++;
8550 }
8551 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8552 {
8553 disp_top++;
8554 disp_height--;
8555 }
177c0ea7 8556
1a578e9b
AC
8557 if (sb_left + sb_width == PIXEL_WIDTH (f))
8558 sb_left++;
177c0ea7 8559
1a578e9b
AC
8560 /* Does the scroll bar exist yet? */
8561 if (NILP (w->vertical_scroll_bar))
8562 {
8563 BLOCK_INPUT;
8564 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8565 left, top, width, height, 0);
8566 UNBLOCK_INPUT;
8567 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8568 disp_height);
8569 XSETVECTOR (w->vertical_scroll_bar, bar);
8570 }
8571 else
8572 {
8573 /* It may just need to be moved and resized. */
8574 ControlHandle ch;
177c0ea7 8575
1a578e9b
AC
8576 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8577 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8578
8579 BLOCK_INPUT;
8580
8581 /* If already correctly positioned, do nothing. */
8582 if (XINT (bar->left) == sb_left
8583 && XINT (bar->top) == top
8584 && XINT (bar->width) == sb_width
8585 && XINT (bar->height) == height)
8586 Draw1Control (ch);
8587 else
8588 {
e0f712ba
AC
8589 /* Clear areas not covered by the scroll bar because it's not as
8590 wide as the area reserved for it . This makes sure a
8591 previous mode line display is cleared after C-x 2 C-x 1, for
8592 example. */
8593 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8594 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8595 left, top, area_width, height, 0);
8596
8597#if 0
1a578e9b
AC
8598 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8599 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8600 sb_left - 1, top, 1, height, 0);
e0f712ba 8601#endif
1a578e9b
AC
8602
8603 HideControl (ch);
8604 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8605 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8606 disp_height);
8607 ShowControl (ch);
177c0ea7 8608
1a578e9b
AC
8609 /* Remember new settings. */
8610 XSETINT (bar->left, sb_left);
8611 XSETINT (bar->top, top);
8612 XSETINT (bar->width, sb_width);
8613 XSETINT (bar->height, height);
8614 }
8615
8616 UNBLOCK_INPUT;
8617 }
8618
8619 /* Set the scroll bar's current state, unless we're currently being
8620 dragged. */
8621 if (NILP (bar->dragging))
8622 {
8623 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8624
8625 if (whole == 0)
8626 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8627 else
8628 {
8629 int start = ((double) position * top_range) / whole;
8630 int end = ((double) (position + portion) * top_range) / whole;
8631 x_scroll_bar_set_handle (bar, start, end, 0);
8632 }
8633 }
8634}
8635
8636
8637/* The following three hooks are used when we're doing a thorough
8638 redisplay of the frame. We don't explicitly know which scroll bars
8639 are going to be deleted, because keeping track of when windows go
8640 away is a real pain - "Can you say set-window-configuration, boys
8641 and girls?" Instead, we just assert at the beginning of redisplay
8642 that *all* scroll bars are to be removed, and then save a scroll bar
8643 from the fiery pit when we actually redisplay its window. */
8644
8645/* Arrange for all scroll bars on FRAME to be removed at the next call
8646 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8647 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8648
8649static void
8650XTcondemn_scroll_bars (frame)
8651 FRAME_PTR frame;
8652{
8653 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8654 while (! NILP (FRAME_SCROLL_BARS (frame)))
8655 {
8656 Lisp_Object bar;
8657 bar = FRAME_SCROLL_BARS (frame);
8658 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8659 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8660 XSCROLL_BAR (bar)->prev = Qnil;
8661 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8662 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8663 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8664 }
8665}
8666
e0f712ba 8667
1a578e9b
AC
8668/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8669 Note that WINDOW isn't necessarily condemned at all. */
e0f712ba 8670
1a578e9b
AC
8671static void
8672XTredeem_scroll_bar (window)
8673 struct window *window;
8674{
8675 struct scroll_bar *bar;
8676
8677 /* We can't redeem this window's scroll bar if it doesn't have one. */
8678 if (NILP (window->vertical_scroll_bar))
8679 abort ();
8680
8681 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8682
8683 /* Unlink it from the condemned list. */
8684 {
8685 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8686
8687 if (NILP (bar->prev))
8688 {
8689 /* If the prev pointer is nil, it must be the first in one of
8690 the lists. */
8691 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8692 /* It's not condemned. Everything's fine. */
8693 return;
8694 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8695 window->vertical_scroll_bar))
8696 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8697 else
8698 /* If its prev pointer is nil, it must be at the front of
8699 one or the other! */
8700 abort ();
8701 }
8702 else
8703 XSCROLL_BAR (bar->prev)->next = bar->next;
8704
8705 if (! NILP (bar->next))
8706 XSCROLL_BAR (bar->next)->prev = bar->prev;
8707
8708 bar->next = FRAME_SCROLL_BARS (f);
8709 bar->prev = Qnil;
8710 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8711 if (! NILP (bar->next))
8712 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8713 }
8714}
8715
8716/* Remove all scroll bars on FRAME that haven't been saved since the
8717 last call to `*condemn_scroll_bars_hook'. */
8718
8719static void
8720XTjudge_scroll_bars (f)
8721 FRAME_PTR f;
8722{
8723 Lisp_Object bar, next;
8724
8725 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8726
8727 /* Clear out the condemned list now so we won't try to process any
8728 more events on the hapless scroll bars. */
8729 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8730
8731 for (; ! NILP (bar); bar = next)
8732 {
8733 struct scroll_bar *b = XSCROLL_BAR (bar);
8734
8735 x_scroll_bar_remove (b);
8736
8737 next = b->next;
8738 b->next = b->prev = Qnil;
8739 }
8740
8741 /* Now there should be no references to the condemned scroll bars,
8742 and they should get garbage-collected. */
8743}
8744
8745
8746static void
8747activate_scroll_bars (frame)
8748 FRAME_PTR frame;
8749{
8750 Lisp_Object bar;
8751 ControlHandle ch;
177c0ea7 8752
1a578e9b
AC
8753 bar = FRAME_SCROLL_BARS (frame);
8754 while (! NILP (bar))
8755 {
8756 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
e0f712ba
AC
8757#ifdef TARGET_API_MAC_CARBON
8758 ActivateControl (ch);
8759#else
1a578e9b
AC
8760 SetControlMaximum (ch,
8761 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8762 XINT (XSCROLL_BAR (bar)
8763 ->height)) - 1);
e0f712ba 8764#endif
1a578e9b
AC
8765 bar = XSCROLL_BAR (bar)->next;
8766 }
8767}
8768
8769
8770static void
8771deactivate_scroll_bars (frame)
8772 FRAME_PTR frame;
8773{
8774 Lisp_Object bar;
8775 ControlHandle ch;
177c0ea7 8776
1a578e9b
AC
8777 bar = FRAME_SCROLL_BARS (frame);
8778 while (! NILP (bar))
8779 {
8780 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
e0f712ba
AC
8781#ifdef TARGET_API_MAC_CARBON
8782 DeactivateControl (ch);
8783#else
1a578e9b 8784 SetControlMaximum (ch, XINT (-1));
177c0ea7 8785#endif
1a578e9b
AC
8786 bar = XSCROLL_BAR (bar)->next;
8787 }
8788}
8789
8790/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3b8f9651 8791 is set to something other than NO_EVENT, it is enqueued.
1a578e9b
AC
8792
8793 This may be called from a signal handler, so we have to ignore GC
8794 mark bits. */
8795
8796static void
8797x_scroll_bar_handle_click (bar, part_code, er, bufp)
8798 struct scroll_bar *bar;
8799 int part_code;
8800 EventRecord *er;
8801 struct input_event *bufp;
8802{
8803 if (! GC_WINDOWP (bar->window))
8804 abort ();
8805
3b8f9651 8806 bufp->kind = SCROLL_BAR_CLICK_EVENT;
1a578e9b
AC
8807 bufp->frame_or_window = bar->window;
8808 bufp->arg = Qnil;
8809
8810 bar->dragging = Qnil;
177c0ea7 8811
1a578e9b
AC
8812 switch (part_code)
8813 {
8814 case kControlUpButtonPart:
8815 bufp->part = scroll_bar_up_arrow;
8816 break;
8817 case kControlDownButtonPart:
8818 bufp->part = scroll_bar_down_arrow;
8819 break;
8820 case kControlPageUpPart:
8821 bufp->part = scroll_bar_above_handle;
8822 break;
8823 case kControlPageDownPart:
8824 bufp->part = scroll_bar_below_handle;
8825 break;
e0f712ba
AC
8826#ifdef TARGET_API_MAC_CARBON
8827 default:
8828#else
1a578e9b 8829 case kControlIndicatorPart:
e0f712ba 8830#endif
1a578e9b
AC
8831 if (er->what == mouseDown)
8832 bar->dragging = make_number (0);
8833 XSETVECTOR (last_mouse_scroll_bar, bar);
8834 bufp->part = scroll_bar_handle;
8835 break;
8836 }
8837}
8838
8839
8840/* Handle some mouse motion while someone is dragging the scroll bar.
8841
8842 This may be called from a signal handler, so we have to ignore GC
8843 mark bits. */
8844
8845static void
8846x_scroll_bar_note_movement (bar, y_pos, t)
8847 struct scroll_bar *bar;
8848 int y_pos;
8849 Time t;
8850{
8851 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8852
8853 last_mouse_movement_time = t;
8854
8855 f->mouse_moved = 1;
8856 XSETVECTOR (last_mouse_scroll_bar, bar);
8857
8858 /* If we're dragging the bar, display it. */
8859 if (! GC_NILP (bar->dragging))
8860 {
8861 /* Where should the handle be now? */
8862 int new_start = y_pos - 24;
8863
8864 if (new_start != XINT (bar->start))
8865 {
8866 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8867
8868 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8869 }
8870 }
8871}
8872
8873
8874/* Return information to the user about the current position of the
8875 mouse on the scroll bar. */
8876
8877static void
8878x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8879 FRAME_PTR *fp;
8880 Lisp_Object *bar_window;
8881 enum scroll_bar_part *part;
8882 Lisp_Object *x, *y;
8883 unsigned long *time;
8884{
8885 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8886 WindowPtr wp = FrontWindow ();
8887 Point mouse_pos;
8888 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8889 int win_y, top_range;
8890
e0f712ba
AC
8891#if TARGET_API_MAC_CARBON
8892 SetPort (GetWindowPort (wp));
8893#else
1a578e9b 8894 SetPort (wp);
e0f712ba
AC
8895#endif
8896
1a578e9b
AC
8897 GetMouse (&mouse_pos);
8898
8899 win_y = mouse_pos.v - XINT (bar->top);
8900 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8901
8902 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8903
8904 win_y -= 24;
8905
8906 if (! NILP (bar->dragging))
8907 win_y -= XINT (bar->dragging);
8908
8909 if (win_y < 0)
8910 win_y = 0;
8911 if (win_y > top_range)
8912 win_y = top_range;
8913
8914 *fp = f;
8915 *bar_window = bar->window;
8916
8917 if (! NILP (bar->dragging))
8918 *part = scroll_bar_handle;
8919 else if (win_y < XINT (bar->start))
8920 *part = scroll_bar_above_handle;
8921 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8922 *part = scroll_bar_handle;
8923 else
8924 *part = scroll_bar_below_handle;
8925
8926 XSETINT (*x, win_y);
8927 XSETINT (*y, top_range);
8928
8929 f->mouse_moved = 0;
8930 last_mouse_scroll_bar = Qnil;
8931
8932 *time = last_mouse_movement_time;
8933}
8934\f
8935/***********************************************************************
8936 Text Cursor
8937 ***********************************************************************/
8938
e0f712ba
AC
8939/* Notice if the text cursor of window W has been overwritten by a
8940 drawing operation that outputs glyphs starting at START_X and
8941 ending at END_X in the line given by output_cursor.vpos.
8942 Coordinates are area-relative. END_X < 0 means all the rest
8943 of the line after START_X has been written. */
1a578e9b
AC
8944
8945static void
e0f712ba 8946notice_overwritten_cursor (w, area, x0, x1, y0, y1)
1a578e9b 8947 struct window *w;
e0f712ba
AC
8948 enum glyph_row_area area;
8949 int x0, x1, y0, y1;
8950{
8951 if (area == TEXT_AREA
8952 && w->phys_cursor_on_p
8953 && y0 <= w->phys_cursor.y
8954 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8955 && x0 <= w->phys_cursor.x
8956 && (x1 < 0 || x1 > w->phys_cursor.x))
1a578e9b
AC
8957 w->phys_cursor_on_p = 0;
8958}
8959
8960
8961/* Set clipping for output in glyph row ROW. W is the window in which
8962 we operate. GC is the graphics context to set clipping in.
8963 WHOLE_LINE_P non-zero means include the areas used for truncation
8964 mark display and alike in the clipping rectangle.
8965
8966 ROW may be a text row or, e.g., a mode line. Text rows must be
8967 clipped to the interior of the window dedicated to text display,
8968 mode lines must be clipped to the whole window. */
8969
8970static void
8971x_clip_to_row (w, row, gc, whole_line_p)
8972 struct window *w;
8973 struct glyph_row *row;
8974 GC gc;
8975 int whole_line_p;
8976{
8977 struct frame *f = XFRAME (WINDOW_FRAME (w));
8978 Rect clip_rect;
8979 int window_x, window_y, window_width, window_height;
8980
8981 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8982
8983 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8984 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8985 clip_rect.top = max (clip_rect.top, window_y);
8986 clip_rect.right = clip_rect.left + window_width;
8987 clip_rect.bottom = clip_rect.top + row->visible_height;
8988
8989 /* If clipping to the whole line, including trunc marks, extend
8990 the rectangle to the left and increase its width. */
8991 if (whole_line_p)
8992 {
3f332ef3
KS
8993 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8994 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
1a578e9b
AC
8995 }
8996
8997 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8998}
8999
9000
9001/* Draw a hollow box cursor on window W in glyph row ROW. */
9002
9003static void
9004x_draw_hollow_cursor (w, row)
9005 struct window *w;
9006 struct glyph_row *row;
9007{
9008 struct frame *f = XFRAME (WINDOW_FRAME (w));
9009 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9010 Display *dpy = FRAME_MAC_DISPLAY (f);
9011 int x, y, wd, h;
9012 XGCValues xgcv;
9013 struct glyph *cursor_glyph;
9014 GC gc;
9015
9016 /* Compute frame-relative coordinates from window-relative
9017 coordinates. */
9018 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9019 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9020 + row->ascent - w->phys_cursor_ascent);
9021 h = row->height - 1;
9022
9023 /* Get the glyph the cursor is on. If we can't tell because
9024 the current matrix is invalid or such, give up. */
9025 cursor_glyph = get_phys_cursor_glyph (w);
9026 if (cursor_glyph == NULL)
9027 return;
9028
9029 /* Compute the width of the rectangle to draw. If on a stretch
9030 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9031 rectangle as wide as the glyph, but use a canonical character
9032 width instead. */
9033 wd = cursor_glyph->pixel_width - 1;
9034 if (cursor_glyph->type == STRETCH_GLYPH
9035 && !x_stretch_cursor_p)
9036 wd = min (CANON_X_UNIT (f), wd);
177c0ea7 9037
1a578e9b
AC
9038 /* The foreground of cursor_gc is typically the same as the normal
9039 background color, which can cause the cursor box to be invisible. */
9040 xgcv.foreground = f->output_data.mac->cursor_pixel;
9041 if (dpyinfo->scratch_cursor_gc)
9042 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
9043 else
9044 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
9045 GCForeground, &xgcv);
9046 gc = dpyinfo->scratch_cursor_gc;
9047
9048 /* Set clipping, draw the rectangle, and reset clipping again. */
9049 x_clip_to_row (w, row, gc, 0);
9050 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
9051 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9052}
9053
9054
9055/* Draw a bar cursor on window W in glyph row ROW.
9056
9057 Implementation note: One would like to draw a bar cursor with an
9058 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9059 Unfortunately, I didn't find a font yet that has this property set.
9060 --gerd. */
9061
9062static void
9063x_draw_bar_cursor (w, row, width)
9064 struct window *w;
9065 struct glyph_row *row;
9066 int width;
9067{
9068 /* If cursor hpos is out of bounds, don't draw garbage. This can
9069 happen in mini-buffer windows when switching between echo area
9070 glyphs and mini-buffer. */
9071 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9072 {
9073 struct frame *f = XFRAME (w->frame);
9074 struct glyph *cursor_glyph;
9075 GC gc;
9076 int x;
9077 unsigned long mask;
9078 XGCValues xgcv;
9079 Display *dpy;
9080 Window window;
177c0ea7 9081
1a578e9b
AC
9082 cursor_glyph = get_phys_cursor_glyph (w);
9083 if (cursor_glyph == NULL)
9084 return;
9085
9086 xgcv.background = f->output_data.mac->cursor_pixel;
9087 xgcv.foreground = f->output_data.mac->cursor_pixel;
9088 mask = GCForeground | GCBackground;
9089 dpy = FRAME_MAC_DISPLAY (f);
9090 window = FRAME_MAC_WINDOW (f);
9091 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
177c0ea7 9092
1a578e9b
AC
9093 if (gc)
9094 XChangeGC (dpy, gc, mask, &xgcv);
9095 else
9096 {
9097 gc = XCreateGC (dpy, window, mask, &xgcv);
9098 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9099 }
9100
9101 if (width < 0)
668e2d32 9102 width = FRAME_CURSOR_WIDTH (f);
1a578e9b
AC
9103
9104 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9105 x_clip_to_row (w, row, gc, 0);
9106 XFillRectangle (dpy, window, gc,
9107 x,
9108 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9109 min (cursor_glyph->pixel_width, width),
9110 row->height);
9111 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9112 }
9113}
9114
9115
9116/* Clear the cursor of window W to background color, and mark the
9117 cursor as not shown. This is used when the text where the cursor
9118 is is about to be rewritten. */
9119
9120static void
9121x_clear_cursor (w)
9122 struct window *w;
9123{
9124 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9125 x_update_window_cursor (w, 0);
9126}
9127
9128
9129/* Draw the cursor glyph of window W in glyph row ROW. See the
9130 comment of x_draw_glyphs for the meaning of HL. */
9131
9132static void
9133x_draw_phys_cursor_glyph (w, row, hl)
9134 struct window *w;
9135 struct glyph_row *row;
9136 enum draw_glyphs_face hl;
9137{
9138 /* If cursor hpos is out of bounds, don't draw garbage. This can
9139 happen in mini-buffer windows when switching between echo area
9140 glyphs and mini-buffer. */
9141 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9142 {
e0f712ba 9143 int on_p = w->phys_cursor_on_p;
1a578e9b 9144 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
e0f712ba
AC
9145 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9146 hl, 0);
9147 w->phys_cursor_on_p = on_p;
1a578e9b
AC
9148
9149 /* When we erase the cursor, and ROW is overlapped by other
9150 rows, make sure that these overlapping parts of other rows
9151 are redrawn. */
9152 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9153 {
9154 if (row > w->current_matrix->rows
9155 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9156 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9157
9158 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9159 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9160 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9161 }
9162 }
9163}
9164
9165
9166/* Erase the image of a cursor of window W from the screen. */
9167
9168static void
9169x_erase_phys_cursor (w)
9170 struct window *w;
9171{
9172 struct frame *f = XFRAME (w->frame);
9173 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9174 int hpos = w->phys_cursor.hpos;
9175 int vpos = w->phys_cursor.vpos;
9176 int mouse_face_here_p = 0;
9177 struct glyph_matrix *active_glyphs = w->current_matrix;
9178 struct glyph_row *cursor_row;
9179 struct glyph *cursor_glyph;
9180 enum draw_glyphs_face hl;
9181
9182 /* No cursor displayed or row invalidated => nothing to do on the
9183 screen. */
9184 if (w->phys_cursor_type == NO_CURSOR)
9185 goto mark_cursor_off;
177c0ea7 9186
1a578e9b
AC
9187 /* VPOS >= active_glyphs->nrows means that window has been resized.
9188 Don't bother to erase the cursor. */
9189 if (vpos >= active_glyphs->nrows)
9190 goto mark_cursor_off;
9191
9192 /* If row containing cursor is marked invalid, there is nothing we
9193 can do. */
9194 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9195 if (!cursor_row->enabled_p)
9196 goto mark_cursor_off;
177c0ea7 9197
796d4ec7 9198 /* If row is completely invisible, don't attempt to delete a cursor which
e0f712ba 9199 isn't there. This may happen if cursor is at top of window, and
796d4ec7
KS
9200 we switch to a buffer with a header line in that window. */
9201 if (cursor_row->visible_height <= 0)
9202 goto mark_cursor_off;
177c0ea7 9203
1a578e9b
AC
9204 /* This can happen when the new row is shorter than the old one.
9205 In this case, either x_draw_glyphs or clear_end_of_line
9206 should have cleared the cursor. Note that we wouldn't be
9207 able to erase the cursor in this case because we don't have a
9208 cursor glyph at hand. */
9209 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9210 goto mark_cursor_off;
177c0ea7 9211
1a578e9b
AC
9212 /* If the cursor is in the mouse face area, redisplay that when
9213 we clear the cursor. */
9214 if (! NILP (dpyinfo->mouse_face_window)
9215 && w == XWINDOW (dpyinfo->mouse_face_window)
9216 && (vpos > dpyinfo->mouse_face_beg_row
9217 || (vpos == dpyinfo->mouse_face_beg_row
9218 && hpos >= dpyinfo->mouse_face_beg_col))
9219 && (vpos < dpyinfo->mouse_face_end_row
9220 || (vpos == dpyinfo->mouse_face_end_row
9221 && hpos < dpyinfo->mouse_face_end_col))
9222 /* Don't redraw the cursor's spot in mouse face if it is at the
9223 end of a line (on a newline). The cursor appears there, but
9224 mouse highlighting does not. */
9225 && cursor_row->used[TEXT_AREA] > hpos)
9226 mouse_face_here_p = 1;
9227
9228 /* Maybe clear the display under the cursor. */
9229 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9230 {
9231 int x;
9232 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9233
9234 cursor_glyph = get_phys_cursor_glyph (w);
9235 if (cursor_glyph == NULL)
9236 goto mark_cursor_off;
9237
9238 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
177c0ea7 9239
1a578e9b
AC
9240 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9241 x,
9242 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9243 cursor_row->y)),
9244 cursor_glyph->pixel_width,
9245 cursor_row->visible_height,
9246 0);
9247 }
177c0ea7 9248
1a578e9b
AC
9249 /* Erase the cursor by redrawing the character underneath it. */
9250 if (mouse_face_here_p)
9251 hl = DRAW_MOUSE_FACE;
1a578e9b
AC
9252 else
9253 hl = DRAW_NORMAL_TEXT;
9254 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9255
9256 mark_cursor_off:
9257 w->phys_cursor_on_p = 0;
9258 w->phys_cursor_type = NO_CURSOR;
9259}
9260
9261
e0f712ba
AC
9262/* Non-zero if physical cursor of window W is within mouse face. */
9263
9264static int
9265cursor_in_mouse_face_p (w)
9266 struct window *w;
9267{
9268 struct mac_display_info *dpyinfo
9269 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9270 int in_mouse_face = 0;
177c0ea7 9271
e0f712ba
AC
9272 if (WINDOWP (dpyinfo->mouse_face_window)
9273 && XWINDOW (dpyinfo->mouse_face_window) == w)
9274 {
9275 int hpos = w->phys_cursor.hpos;
9276 int vpos = w->phys_cursor.vpos;
9277
9278 if (vpos >= dpyinfo->mouse_face_beg_row
9279 && vpos <= dpyinfo->mouse_face_end_row
9280 && (vpos > dpyinfo->mouse_face_beg_row
9281 || hpos >= dpyinfo->mouse_face_beg_col)
9282 && (vpos < dpyinfo->mouse_face_end_row
9283 || hpos < dpyinfo->mouse_face_end_col
9284 || dpyinfo->mouse_face_past_end))
9285 in_mouse_face = 1;
9286 }
9287
9288 return in_mouse_face;
9289}
9290
9291
1a578e9b
AC
9292/* Display or clear cursor of window W. If ON is zero, clear the
9293 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9294 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9295
9296void
9297x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9298 struct window *w;
9299 int on, hpos, vpos, x, y;
9300{
9301 struct frame *f = XFRAME (w->frame);
9302 int new_cursor_type;
9303 int new_cursor_width;
e9c99027 9304 int active_cursor;
1a578e9b
AC
9305 struct glyph_matrix *current_glyphs;
9306 struct glyph_row *glyph_row;
9307 struct glyph *glyph;
9308
9309 /* This is pointless on invisible frames, and dangerous on garbaged
9310 windows and frames; in the latter case, the frame or window may
9311 be in the midst of changing its size, and x and y may be off the
9312 window. */
9313 if (! FRAME_VISIBLE_P (f)
9314 || FRAME_GARBAGED_P (f)
9315 || vpos >= w->current_matrix->nrows
9316 || hpos >= w->current_matrix->matrix_w)
9317 return;
9318
9319 /* If cursor is off and we want it off, return quickly. */
9320 if (!on && !w->phys_cursor_on_p)
9321 return;
9322
9323 current_glyphs = w->current_matrix;
9324 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9325 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
177c0ea7
JB
9326
9327 /* If cursor row is not enabled, we don't really know where to
1a578e9b
AC
9328 display the cursor. */
9329 if (!glyph_row->enabled_p)
9330 {
9331 w->phys_cursor_on_p = 0;
9332 return;
9333 }
9334
9335 xassert (interrupt_input_blocked);
9336
668e2d32 9337 /* Set new_cursor_type to the cursor we want to be displayed. */
e9c99027 9338 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
e0f712ba 9339
1a578e9b
AC
9340
9341 /* If cursor is currently being shown and we don't want it to be or
9342 it is in the wrong place, or the cursor type is not what we want,
9343 erase it. */
9344 if (w->phys_cursor_on_p
9345 && (!on
9346 || w->phys_cursor.x != x
9347 || w->phys_cursor.y != y
e0f712ba 9348 || new_cursor_type != w->phys_cursor_type
668e2d32 9349 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
e0f712ba 9350 && new_cursor_width != w->phys_cursor_width)))
1a578e9b
AC
9351 x_erase_phys_cursor (w);
9352
9353 /* If the cursor is now invisible and we want it to be visible,
9354 display it. */
9355 if (on && !w->phys_cursor_on_p)
9356 {
9357 w->phys_cursor_ascent = glyph_row->ascent;
9358 w->phys_cursor_height = glyph_row->height;
177c0ea7 9359
1a578e9b
AC
9360 /* Set phys_cursor_.* before x_draw_.* is called because some
9361 of them may need the information. */
9362 w->phys_cursor.x = x;
9363 w->phys_cursor.y = glyph_row->y;
9364 w->phys_cursor.hpos = hpos;
9365 w->phys_cursor.vpos = vpos;
9366 w->phys_cursor_type = new_cursor_type;
e0f712ba 9367 w->phys_cursor_width = new_cursor_width;
1a578e9b
AC
9368 w->phys_cursor_on_p = 1;
9369
9370 switch (new_cursor_type)
9371 {
9372 case HOLLOW_BOX_CURSOR:
9373 x_draw_hollow_cursor (w, glyph_row);
9374 break;
9375
9376 case FILLED_BOX_CURSOR:
9377 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9378 break;
9379
668e2d32
KS
9380 case HBAR_CURSOR:
9381 /* TODO. For now, just draw bar cursor. */
1a578e9b
AC
9382 case BAR_CURSOR:
9383 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9384 break;
9385
9386 case NO_CURSOR:
9387 break;
9388
9389 default:
9390 abort ();
9391 }
1a578e9b 9392 }
1a578e9b
AC
9393}
9394
9395
9396/* Display the cursor on window W, or clear it. X and Y are window
9397 relative pixel coordinates. HPOS and VPOS are glyph matrix
9398 positions. If W is not the selected window, display a hollow
9399 cursor. ON non-zero means display the cursor at X, Y which
9400 correspond to HPOS, VPOS, otherwise it is cleared. */
9401
9402void
9403x_display_cursor (w, on, hpos, vpos, x, y)
9404 struct window *w;
9405 int on, hpos, vpos, x, y;
9406{
9407 BLOCK_INPUT;
9408 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9409 UNBLOCK_INPUT;
9410}
9411
9412
9413/* Display the cursor on window W, or clear it, according to ON_P.
9414 Don't change the cursor's position. */
9415
9416void
9417x_update_cursor (f, on_p)
9418 struct frame *f;
e0f712ba 9419 int on_p;
1a578e9b
AC
9420{
9421 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9422}
9423
9424
9425/* Call x_update_window_cursor with parameter ON_P on all leaf windows
9426 in the window tree rooted at W. */
9427
9428static void
9429x_update_cursor_in_window_tree (w, on_p)
9430 struct window *w;
9431 int on_p;
9432{
9433 while (w)
9434 {
9435 if (!NILP (w->hchild))
9436 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9437 else if (!NILP (w->vchild))
9438 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9439 else
9440 x_update_window_cursor (w, on_p);
9441
9442 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9443 }
9444}
9445
9446
9447/* Switch the display of W's cursor on or off, according to the value
9448 of ON. */
9449
9450static void
9451x_update_window_cursor (w, on)
9452 struct window *w;
9453 int on;
9454{
9455 /* Don't update cursor in windows whose frame is in the process
9456 of being deleted. */
9457 if (w->current_matrix)
9458 {
9459 BLOCK_INPUT;
e0f712ba
AC
9460 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9461 w->phys_cursor.vpos, w->phys_cursor.x,
9462 w->phys_cursor.y);
1a578e9b
AC
9463 UNBLOCK_INPUT;
9464 }
9465}
9466
1a578e9b 9467
1a578e9b 9468
e0f712ba
AC
9469\f
9470/* Icons. */
1a578e9b 9471
e0f712ba 9472#if 0 /* MAC_TODO: no icon support yet. */
1a578e9b 9473int
e0f712ba 9474x_bitmap_icon (f, icon)
1a578e9b 9475 struct frame *f;
e0f712ba 9476 Lisp_Object icon;
1a578e9b 9477{
e0f712ba 9478 HANDLE hicon;
1a578e9b 9479
e0f712ba 9480 if (FRAME_W32_WINDOW (f) == 0)
1a578e9b
AC
9481 return 1;
9482
e0f712ba
AC
9483 if (NILP (icon))
9484 hicon = LoadIcon (hinst, EMACS_CLASS);
9485 else if (STRINGP (icon))
d5db4077 9486 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
e0f712ba
AC
9487 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9488 else if (SYMBOLP (icon))
9489 {
9490 LPCTSTR name;
9491
9492 if (EQ (icon, intern ("application")))
9493 name = (LPCTSTR) IDI_APPLICATION;
9494 else if (EQ (icon, intern ("hand")))
9495 name = (LPCTSTR) IDI_HAND;
9496 else if (EQ (icon, intern ("question")))
9497 name = (LPCTSTR) IDI_QUESTION;
9498 else if (EQ (icon, intern ("exclamation")))
9499 name = (LPCTSTR) IDI_EXCLAMATION;
9500 else if (EQ (icon, intern ("asterisk")))
9501 name = (LPCTSTR) IDI_ASTERISK;
9502 else if (EQ (icon, intern ("winlogo")))
9503 name = (LPCTSTR) IDI_WINLOGO;
9504 else
9505 return 1;
1a578e9b 9506
e0f712ba 9507 hicon = LoadIcon (NULL, name);
1a578e9b 9508 }
e0f712ba 9509 else
1a578e9b
AC
9510 return 1;
9511
e0f712ba
AC
9512 if (hicon == NULL)
9513 return 1;
1a578e9b 9514
e0f712ba
AC
9515 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9516 (LPARAM) hicon);
1a578e9b
AC
9517
9518 return 0;
9519}
e0f712ba 9520#endif /* MAC_TODO */
1a578e9b 9521\f
e0f712ba
AC
9522/************************************************************************
9523 Handling X errors
9524 ************************************************************************/
1a578e9b 9525
e0f712ba
AC
9526/* Display Error Handling functions not used on W32. Listing them here
9527 helps diff stay in step when comparing w32term.c with xterm.c.
1a578e9b 9528
1a578e9b 9529x_error_catcher (display, error)
1a578e9b 9530x_catch_errors (dpy)
1a578e9b 9531x_catch_errors_unwind (old_val)
1a578e9b 9532x_check_errors (dpy, format)
1a578e9b 9533x_had_errors_p (dpy)
1a578e9b 9534x_clear_errors (dpy)
1a578e9b 9535x_uncatch_errors (dpy, count)
1a578e9b 9536x_trace_wire ()
e0f712ba
AC
9537x_connection_signal (signalnum)
9538x_connection_closed (dpy, error_message)
1a578e9b 9539x_error_quitter (display, error)
1a578e9b 9540x_error_handler (display, error)
1a578e9b 9541x_io_error_quitter (display)
1a578e9b 9542
e0f712ba
AC
9543 */
9544
1a578e9b
AC
9545\f
9546/* Changing the font of the frame. */
9547
9548/* Give frame F the font named FONTNAME as its default font, and
9549 return the full name of that font. FONTNAME may be a wildcard
9550 pattern; in that case, we choose some font that fits the pattern.
9551 The return value shows which font we chose. */
9552
9553Lisp_Object
9554x_new_font (f, fontname)
9555 struct frame *f;
9556 register char *fontname;
9557{
9558 struct font_info *fontp
9559 = FS_LOAD_FONT (f, 0, fontname, -1);
9560
9561 if (!fontp)
9562 return Qnil;
9563
e0f712ba
AC
9564 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9565 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9566 FRAME_FONTSET (f) = -1;
9567
1a578e9b
AC
9568 /* Compute the scroll bar width in character columns. */
9569 if (f->scroll_bar_pixel_width > 0)
9570 {
e0f712ba 9571 int wid = FONT_WIDTH (FRAME_FONT (f));
1a578e9b
AC
9572 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9573 }
9574 else
9575 {
e0f712ba 9576 int wid = FONT_WIDTH (FRAME_FONT (f));
1a578e9b
AC
9577 f->scroll_bar_cols = (14 + wid - 1) / wid;
9578 }
9579
9580 /* Now make the frame display the given font. */
9581 if (FRAME_MAC_WINDOW (f) != 0)
9582 {
f00691a3
AC
9583 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9584 f->output_data.mac->font);
9585 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9586 f->output_data.mac->font);
9587 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9588 f->output_data.mac->font);
9589
1a578e9b 9590 frame_update_line_height (f);
e0f712ba
AC
9591 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9592 x_set_window_size (f, 0, f->width, f->height);
1a578e9b
AC
9593 }
9594 else
e0f712ba
AC
9595 /* If we are setting a new frame's font for the first time,
9596 there are no faces yet, so this font's height is the line height. */
9597 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
1a578e9b
AC
9598
9599 return build_string (fontp->full_name);
9600}
e0f712ba 9601\f
1a578e9b 9602/* Give frame F the fontset named FONTSETNAME as its default font, and
e0f712ba
AC
9603 return the full name of that fontset. FONTSETNAME may be a wildcard
9604 pattern; in that case, we choose some fontset that fits the pattern.
9605 The return value shows which fontset we chose. */
1a578e9b
AC
9606
9607Lisp_Object
9608x_new_fontset (f, fontsetname)
9609 struct frame *f;
9610 char *fontsetname;
9611{
9612 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9613 Lisp_Object result;
9614
9615 if (fontset < 0)
9616 return Qnil;
9617
e0f712ba 9618 if (FRAME_FONTSET (f) == fontset)
1a578e9b
AC
9619 /* This fontset is already set in frame F. There's nothing more
9620 to do. */
9621 return fontset_name (fontset);
9622
d5db4077 9623 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
1a578e9b
AC
9624
9625 if (!STRINGP (result))
9626 /* Can't load ASCII font. */
9627 return Qnil;
9628
e0f712ba
AC
9629 /* Since x_new_font doesn't update any fontset information, do it now. */
9630 FRAME_FONTSET(f) = fontset;
1a578e9b 9631
1a578e9b
AC
9632 return build_string (fontsetname);
9633}
9634
d33c49e8
KS
9635/* Compute actual fringe widths */
9636
9637void
9638x_compute_fringe_widths (f, redraw)
9639 struct frame *f;
9640 int redraw;
9641{
9642 int o_left = f->output_data.mac->left_fringe_width;
9643 int o_right = f->output_data.mac->right_fringe_width;
9644 int o_cols = f->output_data.mac->fringe_cols;
9645
9646 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9647 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9648 int left_fringe_width, right_fringe_width;
9649
9650 if (!NILP (left_fringe))
9651 left_fringe = Fcdr (left_fringe);
9652 if (!NILP (right_fringe))
9653 right_fringe = Fcdr (right_fringe);
9654
9655 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9656 XINT (left_fringe));
9657 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9658 XINT (right_fringe));
9659
9660 if (left_fringe_width || right_fringe_width)
9661 {
9662 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9663 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9664 int conf_wid = left_wid + right_wid;
9665 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9666 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9667 int real_wid = cols * font_wid;
9668 if (left_wid && right_wid)
9669 {
9670 if (left_fringe_width < 0)
9671 {
9672 /* Left fringe width is fixed, adjust right fringe if necessary */
9673 f->output_data.mac->left_fringe_width = left_wid;
9674 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9675 }
9676 else if (right_fringe_width < 0)
9677 {
9678 /* Right fringe width is fixed, adjust left fringe if necessary */
9679 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9680 f->output_data.mac->right_fringe_width = right_wid;
9681 }
9682 else
9683 {
9684 /* Adjust both fringes with an equal amount.
9685 Note that we are doing integer arithmetic here, so don't
9686 lose a pixel if the total width is an odd number. */
9687 int fill = real_wid - conf_wid;
9688 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9689 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9690 }
9691 }
9692 else if (left_fringe_width)
9693 {
9694 f->output_data.mac->left_fringe_width = real_wid;
9695 f->output_data.mac->right_fringe_width = 0;
9696 }
9697 else
9698 {
9699 f->output_data.mac->left_fringe_width = 0;
9700 f->output_data.mac->right_fringe_width = real_wid;
9701 }
9702 f->output_data.mac->fringe_cols = cols;
9703 f->output_data.mac->fringes_extra = real_wid;
9704 }
9705 else
9706 {
9707 f->output_data.mac->left_fringe_width = 0;
9708 f->output_data.mac->right_fringe_width = 0;
9709 f->output_data.mac->fringe_cols = 0;
9710 f->output_data.mac->fringes_extra = 0;
9711 }
9712
9713 if (redraw && FRAME_VISIBLE_P (f))
9714 if (o_left != f->output_data.mac->left_fringe_width ||
9715 o_right != f->output_data.mac->right_fringe_width ||
9716 o_cols != f->output_data.mac->fringe_cols)
9717 redraw_frame (f);
9718}
1a578e9b
AC
9719\f
9720/***********************************************************************
e0f712ba 9721 TODO: W32 Input Methods
1a578e9b 9722 ***********************************************************************/
e0f712ba 9723/* Listing missing functions from xterm.c helps diff stay in step.
1a578e9b 9724
1a578e9b 9725xim_destroy_callback (xim, client_data, call_data)
1a578e9b 9726xim_open_dpy (dpyinfo, resource_name)
1a578e9b 9727struct xim_inst_t
1a578e9b 9728xim_instantiate_callback (display, client_data, call_data)
1a578e9b 9729xim_initialize (dpyinfo, resource_name)
1a578e9b 9730xim_close_dpy (dpyinfo)
1a578e9b 9731
e0f712ba 9732 */
1a578e9b 9733
1a578e9b
AC
9734\f
9735/* Calculate the absolute position in frame F
9736 from its current recorded position values and gravity. */
9737
e0f712ba 9738void
1a578e9b
AC
9739x_calc_absolute_position (f)
9740 struct frame *f;
9741{
9742 Point pt;
9743 int flags = f->output_data.mac->size_hint_flags;
9744
9745 pt.h = pt.v = 0;
9746
9747 /* Find the position of the outside upper-left corner of
9748 the inner window, with respect to the outer window. */
9749 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9750 {
9751 GrafPtr savePort;
9752 GetPort (&savePort);
e0f712ba
AC
9753
9754#if TARGET_API_MAC_CARBON
9755 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9756#else
1a578e9b 9757 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
9758#endif
9759
9760#if TARGET_API_MAC_CARBON
9761 {
9762 Rect r;
177c0ea7 9763
e0f712ba
AC
9764 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9765 SetPt(&pt, r.left, r.top);
9766 }
9767#else /* not TARGET_API_MAC_CARBON */
1a578e9b 9768 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
e0f712ba 9769#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
9770 LocalToGlobal (&pt);
9771 SetPort (savePort);
9772 }
9773
9774 /* Treat negative positions as relative to the leftmost bottommost
9775 position that fits on the screen. */
9776 if (flags & XNegative)
9777 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9778 - 2 * f->output_data.mac->border_width - pt.h
9779 - PIXEL_WIDTH (f)
9780 + f->output_data.mac->left_pos);
9781 /* NTEMACS_TODO: Subtract menubar height? */
9782 if (flags & YNegative)
9783 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9784 - 2 * f->output_data.mac->border_width - pt.v
9785 - PIXEL_HEIGHT (f)
9786 + f->output_data.mac->top_pos);
9787 /* The left_pos and top_pos
9788 are now relative to the top and left screen edges,
9789 so the flags should correspond. */
9790 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9791}
9792
9793/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9794 to really change the position, and 0 when calling from
9795 x_make_frame_visible (in that case, XOFF and YOFF are the current
9796 position values). It is -1 when calling from x_set_frame_parameters,
9797 which means, do adjust for borders but don't change the gravity. */
9798
9799void
9800x_set_offset (f, xoff, yoff, change_gravity)
9801 struct frame *f;
9802 register int xoff, yoff;
9803 int change_gravity;
9804{
e0f712ba
AC
9805 int modified_top, modified_left;
9806
1a578e9b
AC
9807 if (change_gravity > 0)
9808 {
9809 f->output_data.mac->top_pos = yoff;
9810 f->output_data.mac->left_pos = xoff;
9811 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9812 if (xoff < 0)
9813 f->output_data.mac->size_hint_flags |= XNegative;
9814 if (yoff < 0)
9815 f->output_data.mac->size_hint_flags |= YNegative;
9816 f->output_data.mac->win_gravity = NorthWestGravity;
9817 }
9818 x_calc_absolute_position (f);
9819
9820 BLOCK_INPUT;
9821 x_wm_set_size_hint (f, (long) 0, 0);
9822
e0f712ba
AC
9823 modified_left = f->output_data.mac->left_pos;
9824 modified_top = f->output_data.mac->top_pos;
9825
9826 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9827 modified_top + 42, false);
1a578e9b
AC
9828
9829 UNBLOCK_INPUT;
9830}
9831
9832/* Call this to change the size of frame F's x-window.
9833 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9834 for this size change and subsequent size changes.
9835 Otherwise we leave the window gravity unchanged. */
9836
9837void
9838x_set_window_size (f, change_gravity, cols, rows)
9839 struct frame *f;
9840 int change_gravity;
9841 int cols, rows;
9842{
9843 int pixelwidth, pixelheight;
177c0ea7 9844
e0f712ba 9845 BLOCK_INPUT;
177c0ea7 9846
1a578e9b
AC
9847 check_frame_size (f, &rows, &cols);
9848 f->output_data.mac->vertical_scroll_bar_extra
9849 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9850 ? 0
1a578e9b 9851 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
d33c49e8
KS
9852
9853 x_compute_fringe_widths (f, 0);
9854
1a578e9b
AC
9855 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9856 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9857
9858 f->output_data.mac->win_gravity = NorthWestGravity;
9859 x_wm_set_size_hint (f, (long) 0, 0);
9860
9861 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9862
9863 /* Now, strictly speaking, we can't be sure that this is accurate,
9864 but the window manager will get around to dealing with the size
9865 change request eventually, and we'll hear how it went when the
9866 ConfigureNotify event gets here.
177c0ea7 9867
1a578e9b
AC
9868 We could just not bother storing any of this information here,
9869 and let the ConfigureNotify event set everything up, but that
9870 might be kind of confusing to the Lisp code, since size changes
9871 wouldn't be reported in the frame parameters until some random
9872 point in the future when the ConfigureNotify event arrives.
9873
9874 We pass 1 for DELAY since we can't run Lisp code inside of
9875 a BLOCK_INPUT. */
9876 change_frame_size (f, rows, cols, 0, 1, 0);
9877 PIXEL_WIDTH (f) = pixelwidth;
9878 PIXEL_HEIGHT (f) = pixelheight;
9879
9880 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9881 receive in the ConfigureNotify event; if we get what we asked
9882 for, then the event won't cause the screen to become garbaged, so
9883 we have to make sure to do it here. */
9884 SET_FRAME_GARBAGED (f);
9885
9886 XFlush (FRAME_X_DISPLAY (f));
9887
9888 /* If cursor was outside the new size, mark it as off. */
9889 mark_window_cursors_off (XWINDOW (f->root_window));
9890
9891 /* Clear out any recollection of where the mouse highlighting was,
177c0ea7 9892 since it might be in a place that's outside the new frame size.
1a578e9b
AC
9893 Actually checking whether it is outside is a pain in the neck,
9894 so don't try--just let the highlighting be done afresh with new size. */
9895 cancel_mouse_face (f);
e0f712ba
AC
9896
9897 UNBLOCK_INPUT;
1a578e9b
AC
9898}
9899\f
9900/* Mouse warping. */
9901
9902void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9903
9904void
9905x_set_mouse_position (f, x, y)
9906 struct frame *f;
9907 int x, y;
9908{
9909 int pix_x, pix_y;
9910
9911 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9912 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9913
9914 if (pix_x < 0) pix_x = 0;
9915 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9916
9917 if (pix_y < 0) pix_y = 0;
9918 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9919
9920 x_set_mouse_pixel_position (f, pix_x, pix_y);
9921}
9922
1a578e9b
AC
9923void
9924x_set_mouse_pixel_position (f, pix_x, pix_y)
9925 struct frame *f;
9926 int pix_x, pix_y;
9927{
9928#if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9929 BLOCK_INPUT;
9930
9931 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9932 0, 0, 0, 0, pix_x, pix_y);
9933 UNBLOCK_INPUT;
9934#endif
9935}
e0f712ba 9936
1a578e9b
AC
9937\f
9938/* focus shifting, raising and lowering. */
9939
e0f712ba 9940void
1a578e9b
AC
9941x_focus_on_frame (f)
9942 struct frame *f;
9943{
9944#if 0 /* This proves to be unpleasant. */
9945 x_raise_frame (f);
9946#endif
9947#if 0
9948 /* I don't think that the ICCCM allows programs to do things like this
9949 without the interaction of the window manager. Whatever you end up
9950 doing with this code, do it to x_unfocus_frame too. */
9951 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9952 RevertToPointerRoot, CurrentTime);
9953#endif /* ! 0 */
9954}
9955
e0f712ba 9956void
1a578e9b
AC
9957x_unfocus_frame (f)
9958 struct frame *f;
9959{
1a578e9b
AC
9960}
9961
9962/* Raise frame F. */
1a578e9b
AC
9963void
9964x_raise_frame (f)
9965 struct frame *f;
9966{
9967 if (f->async_visible)
9968 SelectWindow (FRAME_MAC_WINDOW (f));
9969}
9970
9971/* Lower frame F. */
1a578e9b
AC
9972void
9973x_lower_frame (f)
9974 struct frame *f;
9975{
9976 if (f->async_visible)
9977 SendBehind (FRAME_MAC_WINDOW (f), nil);
9978}
9979
e0f712ba 9980static void
1a578e9b
AC
9981XTframe_raise_lower (f, raise_flag)
9982 FRAME_PTR f;
9983 int raise_flag;
9984{
9985 if (raise_flag)
9986 x_raise_frame (f);
9987 else
9988 x_lower_frame (f);
9989}
9990\f
9991/* Change of visibility. */
9992
9993/* This tries to wait until the frame is really visible.
9994 However, if the window manager asks the user where to position
9995 the frame, this will return before the user finishes doing that.
9996 The frame will not actually be visible at that time,
9997 but it will become visible later when the window manager
9998 finishes with it. */
9999
10000void
10001x_make_frame_visible (f)
10002 struct frame *f;
10003{
10004 Lisp_Object type;
10005 int original_top, original_left;
10006
10007 BLOCK_INPUT;
10008
10009 if (! FRAME_VISIBLE_P (f))
10010 {
10011 /* We test FRAME_GARBAGED_P here to make sure we don't
10012 call x_set_offset a second time
10013 if we get to x_make_frame_visible a second time
10014 before the window gets really visible. */
10015 if (! FRAME_ICONIFIED_P (f)
10016 && ! f->output_data.mac->asked_for_visible)
10017 x_set_offset (f, f->output_data.mac->left_pos,
10018 f->output_data.mac->top_pos, 0);
10019
10020 f->output_data.mac->asked_for_visible = 1;
177c0ea7 10021
1a578e9b
AC
10022 ShowWindow (FRAME_MAC_WINDOW (f));
10023 }
10024
10025 XFlush (FRAME_MAC_DISPLAY (f));
10026
e0f712ba 10027#if 0 /* MAC_TODO */
1a578e9b
AC
10028 /* Synchronize to ensure Emacs knows the frame is visible
10029 before we do anything else. We do this loop with input not blocked
10030 so that incoming events are handled. */
10031 {
10032 Lisp_Object frame;
10033 int count;
10034
10035 /* This must come after we set COUNT. */
10036 UNBLOCK_INPUT;
10037
10038 XSETFRAME (frame, f);
10039
10040 /* Wait until the frame is visible. Process X events until a
10041 MapNotify event has been seen, or until we think we won't get a
10042 MapNotify at all.. */
10043 for (count = input_signal_count + 10;
10044 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10045 {
10046 /* Force processing of queued events. */
10047 x_sync (f);
10048
10049 /* Machines that do polling rather than SIGIO have been
10050 observed to go into a busy-wait here. So we'll fake an
10051 alarm signal to let the handler know that there's something
10052 to be read. We used to raise a real alarm, but it seems
10053 that the handler isn't always enabled here. This is
10054 probably a bug. */
10055 if (input_polling_used ())
10056 {
10057 /* It could be confusing if a real alarm arrives while
10058 processing the fake one. Turn it off and let the
10059 handler reset it. */
10060 extern void poll_for_input_1 P_ ((void));
10061 int old_poll_suppress_count = poll_suppress_count;
10062 poll_suppress_count = 1;
10063 poll_for_input_1 ();
10064 poll_suppress_count = old_poll_suppress_count;
10065 }
10066
10067 /* See if a MapNotify event has been processed. */
10068 FRAME_SAMPLE_VISIBILITY (f);
10069 }
10070 }
e0f712ba 10071#endif /* MAC_TODO */
1a578e9b
AC
10072}
10073
10074/* Change from mapped state to withdrawn state. */
10075
10076/* Make the frame visible (mapped and not iconified). */
10077
10078void
10079x_make_frame_invisible (f)
10080 struct frame *f;
10081{
10082 /* Don't keep the highlight on an invisible frame. */
10083 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10084 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
177c0ea7 10085
1a578e9b 10086 BLOCK_INPUT;
177c0ea7 10087
1a578e9b 10088 HideWindow (FRAME_MAC_WINDOW (f));
177c0ea7 10089
1a578e9b
AC
10090 /* We can't distinguish this from iconification
10091 just by the event that we get from the server.
10092 So we can't win using the usual strategy of letting
10093 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10094 and synchronize with the server to make sure we agree. */
10095 f->visible = 0;
10096 FRAME_ICONIFIED_P (f) = 0;
10097 f->async_visible = 0;
10098 f->async_iconified = 0;
177c0ea7 10099
1a578e9b
AC
10100 UNBLOCK_INPUT;
10101}
10102
10103/* Change window state from mapped to iconified. */
10104
10105void
10106x_iconify_frame (f)
10107 struct frame *f;
10108{
1a578e9b 10109 /* Don't keep the highlight on an invisible frame. */
742fbed7
AC
10110 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10111 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
1a578e9b 10112
742fbed7
AC
10113#if 0
10114 /* Review: Since window is still visible in dock, still allow updates? */
1a578e9b
AC
10115 if (f->async_iconified)
10116 return;
742fbed7 10117#endif
1a578e9b
AC
10118
10119 BLOCK_INPUT;
10120
742fbed7 10121 CollapseWindow (FRAME_MAC_WINDOW (f), true);
177c0ea7 10122
1a578e9b 10123 UNBLOCK_INPUT;
1a578e9b 10124}
e0f712ba 10125
1a578e9b
AC
10126\f
10127/* Destroy the X window of frame F. */
10128
10129void
10130x_destroy_window (f)
10131 struct frame *f;
10132{
10133 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10134
10135 BLOCK_INPUT;
10136
10137 DisposeWindow (FRAME_MAC_WINDOW (f));
10138
10139 free_frame_menubar (f);
10140 free_frame_faces (f);
10141
10142 xfree (f->output_data.mac);
10143 f->output_data.mac = 0;
10144 if (f == dpyinfo->x_focus_frame)
10145 dpyinfo->x_focus_frame = 0;
10146 if (f == dpyinfo->x_focus_event_frame)
10147 dpyinfo->x_focus_event_frame = 0;
10148 if (f == dpyinfo->x_highlight_frame)
10149 dpyinfo->x_highlight_frame = 0;
10150
10151 dpyinfo->reference_count--;
10152
10153 if (f == dpyinfo->mouse_face_mouse_frame)
10154 {
10155 dpyinfo->mouse_face_beg_row
10156 = dpyinfo->mouse_face_beg_col = -1;
10157 dpyinfo->mouse_face_end_row
10158 = dpyinfo->mouse_face_end_col = -1;
10159 dpyinfo->mouse_face_window = Qnil;
10160 dpyinfo->mouse_face_deferred_gc = 0;
10161 dpyinfo->mouse_face_mouse_frame = 0;
10162 }
10163
10164 UNBLOCK_INPUT;
10165}
10166\f
10167/* Setting window manager hints. */
10168
10169/* Set the normal size hints for the window manager, for frame F.
10170 FLAGS is the flags word to use--or 0 meaning preserve the flags
10171 that the window now has.
10172 If USER_POSITION is nonzero, we set the USPosition
10173 flag (this is useful when FLAGS is 0). */
1a578e9b
AC
10174void
10175x_wm_set_size_hint (f, flags, user_position)
10176 struct frame *f;
10177 long flags;
10178 int user_position;
10179{
10180#if 0 /* MAC_TODO: connect this to the Appearance Manager */
10181 XSizeHints size_hints;
10182
10183#ifdef USE_X_TOOLKIT
10184 Arg al[2];
10185 int ac = 0;
10186 Dimension widget_width, widget_height;
10187 Window window = XtWindow (f->output_data.x->widget);
10188#else /* not USE_X_TOOLKIT */
10189 Window window = FRAME_X_WINDOW (f);
10190#endif /* not USE_X_TOOLKIT */
10191
10192 /* Setting PMaxSize caused various problems. */
10193 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10194
10195 size_hints.x = f->output_data.x->left_pos;
10196 size_hints.y = f->output_data.x->top_pos;
10197
10198#ifdef USE_X_TOOLKIT
10199 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10200 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10201 XtGetValues (f->output_data.x->widget, al, ac);
10202 size_hints.height = widget_height;
10203 size_hints.width = widget_width;
10204#else /* not USE_X_TOOLKIT */
10205 size_hints.height = PIXEL_HEIGHT (f);
10206 size_hints.width = PIXEL_WIDTH (f);
10207#endif /* not USE_X_TOOLKIT */
10208
10209 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10210 size_hints.height_inc = f->output_data.x->line_height;
10211 size_hints.max_width
10212 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10213 size_hints.max_height
10214 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10215
10216 /* Calculate the base and minimum sizes.
10217
10218 (When we use the X toolkit, we don't do it here.
10219 Instead we copy the values that the widgets are using, below.) */
10220#ifndef USE_X_TOOLKIT
10221 {
10222 int base_width, base_height;
10223 int min_rows = 0, min_cols = 0;
10224
10225 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10226 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10227
10228 check_frame_size (f, &min_rows, &min_cols);
10229
10230 /* The window manager uses the base width hints to calculate the
10231 current number of rows and columns in the frame while
10232 resizing; min_width and min_height aren't useful for this
10233 purpose, since they might not give the dimensions for a
10234 zero-row, zero-column frame.
10235
10236 We use the base_width and base_height members if we have
10237 them; otherwise, we set the min_width and min_height members
10238 to the size for a zero x zero frame. */
10239
10240#ifdef HAVE_X11R4
10241 size_hints.flags |= PBaseSize;
10242 size_hints.base_width = base_width;
10243 size_hints.base_height = base_height;
10244 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10245 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10246#else
10247 size_hints.min_width = base_width;
10248 size_hints.min_height = base_height;
10249#endif
10250 }
10251
10252 /* If we don't need the old flags, we don't need the old hint at all. */
10253 if (flags)
10254 {
10255 size_hints.flags |= flags;
10256 goto no_read;
10257 }
10258#endif /* not USE_X_TOOLKIT */
10259
10260 {
10261 XSizeHints hints; /* Sometimes I hate X Windows... */
10262 long supplied_return;
10263 int value;
10264
10265#ifdef HAVE_X11R4
10266 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10267 &supplied_return);
10268#else
10269 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10270#endif
10271
10272#ifdef USE_X_TOOLKIT
10273 size_hints.base_height = hints.base_height;
10274 size_hints.base_width = hints.base_width;
10275 size_hints.min_height = hints.min_height;
10276 size_hints.min_width = hints.min_width;
10277#endif
10278
10279 if (flags)
10280 size_hints.flags |= flags;
10281 else
10282 {
10283 if (value == 0)
10284 hints.flags = 0;
10285 if (hints.flags & PSize)
10286 size_hints.flags |= PSize;
10287 if (hints.flags & PPosition)
10288 size_hints.flags |= PPosition;
10289 if (hints.flags & USPosition)
10290 size_hints.flags |= USPosition;
10291 if (hints.flags & USSize)
10292 size_hints.flags |= USSize;
10293 }
10294 }
10295
10296#ifndef USE_X_TOOLKIT
10297 no_read:
10298#endif
10299
10300#ifdef PWinGravity
10301 size_hints.win_gravity = f->output_data.x->win_gravity;
10302 size_hints.flags |= PWinGravity;
10303
10304 if (user_position)
10305 {
10306 size_hints.flags &= ~ PPosition;
10307 size_hints.flags |= USPosition;
10308 }
10309#endif /* PWinGravity */
10310
10311#ifdef HAVE_X11R4
10312 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10313#else
10314 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10315#endif
e0f712ba 10316#endif /* MAC_TODO */
1a578e9b
AC
10317}
10318
e0f712ba 10319#if 0 /* MAC_TODO: hide application instead of iconify? */
1a578e9b
AC
10320/* Used for IconicState or NormalState */
10321
10322void
10323x_wm_set_window_state (f, state)
10324 struct frame *f;
10325 int state;
10326{
10327#ifdef USE_X_TOOLKIT
10328 Arg al[1];
10329
10330 XtSetArg (al[0], XtNinitialState, state);
10331 XtSetValues (f->output_data.x->widget, al, 1);
10332#else /* not USE_X_TOOLKIT */
10333 Window window = FRAME_X_WINDOW (f);
10334
10335 f->output_data.x->wm_hints.flags |= StateHint;
10336 f->output_data.x->wm_hints.initial_state = state;
10337
10338 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10339#endif /* not USE_X_TOOLKIT */
10340}
10341
10342void
10343x_wm_set_icon_pixmap (f, pixmap_id)
10344 struct frame *f;
10345 int pixmap_id;
10346{
10347 Pixmap icon_pixmap;
10348
10349#ifndef USE_X_TOOLKIT
10350 Window window = FRAME_X_WINDOW (f);
10351#endif
10352
10353 if (pixmap_id > 0)
10354 {
10355 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10356 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10357 }
10358 else
10359 {
10360 /* It seems there is no way to turn off use of an icon pixmap.
10361 The following line does it, only if no icon has yet been created,
10362 for some window managers. But with mwm it crashes.
10363 Some people say it should clear the IconPixmapHint bit in this case,
10364 but that doesn't work, and the X consortium said it isn't the
10365 right thing at all. Since there is no way to win,
10366 best to explicitly give up. */
10367#if 0
10368 f->output_data.x->wm_hints.icon_pixmap = None;
10369#else
10370 return;
10371#endif
10372 }
10373
10374#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10375
10376 {
10377 Arg al[1];
10378 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10379 XtSetValues (f->output_data.x->widget, al, 1);
10380 }
10381
10382#else /* not USE_X_TOOLKIT */
177c0ea7 10383
1a578e9b
AC
10384 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10385 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10386
10387#endif /* not USE_X_TOOLKIT */
10388}
10389
e0f712ba 10390#endif /* MAC_TODO */
1a578e9b
AC
10391
10392void
10393x_wm_set_icon_position (f, icon_x, icon_y)
10394 struct frame *f;
10395 int icon_x, icon_y;
10396{
10397#if 0 /* MAC_TODO: no icons on Mac */
10398#ifdef USE_X_TOOLKIT
10399 Window window = XtWindow (f->output_data.x->widget);
10400#else
10401 Window window = FRAME_X_WINDOW (f);
10402#endif
10403
10404 f->output_data.x->wm_hints.flags |= IconPositionHint;
10405 f->output_data.x->wm_hints.icon_x = icon_x;
10406 f->output_data.x->wm_hints.icon_y = icon_y;
10407
10408 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
e0f712ba 10409#endif /* MAC_TODO */
1a578e9b
AC
10410}
10411
10412\f
10413/***********************************************************************
10414 Fonts
10415 ***********************************************************************/
10416
10417/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10418
10419struct font_info *
10420x_get_font_info (f, font_idx)
10421 FRAME_PTR f;
10422 int font_idx;
10423{
10424 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10425}
10426
10427/* the global font name table */
10428char **font_name_table = NULL;
10429int font_name_table_size = 0;
10430int font_name_count = 0;
10431
10432/* compare two strings ignoring case */
10433static int
10434stricmp (const char *s, const char *t)
10435{
10436 for ( ; tolower (*s) == tolower (*t); s++, t++)
10437 if (*s == '\0')
10438 return 0;
10439 return tolower (*s) - tolower (*t);
10440}
10441
10442/* compare two strings ignoring case and handling wildcard */
10443static int
10444wildstrieq (char *s1, char *s2)
10445{
10446 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10447 return true;
10448
10449 return stricmp (s1, s2) == 0;
10450}
10451
10452/* Assume parameter 1 is fully qualified, no wildcards. */
177c0ea7 10453static int
1a578e9b
AC
10454mac_font_pattern_match (fontname, pattern)
10455 char * fontname;
10456 char * pattern;
10457{
b179a3a2 10458 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
1a578e9b
AC
10459 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10460 char *ptr;
10461
10462 /* Copy fontname so we can modify it during comparison. */
10463 strcpy (font_name_copy, fontname);
10464
10465 ptr = regex;
10466 *ptr++ = '^';
10467
10468 /* Turn pattern into a regexp and do a regexp match. */
10469 for (; *pattern; pattern++)
10470 {
10471 if (*pattern == '?')
10472 *ptr++ = '.';
10473 else if (*pattern == '*')
10474 {
10475 *ptr++ = '.';
10476 *ptr++ = '*';
10477 }
10478 else
10479 *ptr++ = *pattern;
10480 }
10481 *ptr = '$';
10482 *(ptr + 1) = '\0';
10483
10484 return (fast_c_string_match_ignore_case (build_string (regex),
10485 font_name_copy) >= 0);
10486}
10487
10488/* Two font specs are considered to match if their foundry, family,
10489 weight, slant, and charset match. */
177c0ea7 10490static int
1a578e9b
AC
10491mac_font_match (char *mf, char *xf)
10492{
10493 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10494 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10495
10496 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10497 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10498 return mac_font_pattern_match (mf, xf);
10499
10500 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10501 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10502 return mac_font_pattern_match (mf, xf);
10503
10504 return (wildstrieq (m_foundry, x_foundry)
10505 && wildstrieq (m_family, x_family)
10506 && wildstrieq (m_weight, x_weight)
10507 && wildstrieq (m_slant, x_slant)
10508 && wildstrieq (m_charset, x_charset))
10509 || mac_font_pattern_match (mf, xf);
10510}
10511
10512
10513static char *
10514mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10515{
10516 char foundry[32], family[32], cs[32];
10517 char xf[255], *result, *p;
10518
10519 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10520 {
10521 strcpy(foundry, "Apple");
10522 strcpy(family, name);
10523
10524 switch (scriptcode)
10525 {
10526 case smTradChinese:
10527 strcpy(cs, "big5-0");
10528 break;
10529 case smSimpChinese:
83a96b4d 10530 strcpy(cs, "gb2312.1980-0");
1a578e9b
AC
10531 break;
10532 case smJapanese:
10533 strcpy(cs, "jisx0208.1983-sjis");
10534 break;
2f64cf3a
AC
10535 case -smJapanese:
10536 /* Each Apple Japanese font is entered into the font table
10537 twice: once as a jisx0208.1983-sjis font and once as a
10538 jisx0201.1976-0 font. The latter can be used to display
10539 the ascii charset and katakana-jisx0201 charset. A
10540 negative script code signals that the name of this latter
10541 font is being built. */
10542 strcpy(cs, "jisx0201.1976-0");
10543 break;
1a578e9b 10544 case smKorean:
83a96b4d 10545 strcpy(cs, "ksc5601.1989-0");
177c0ea7 10546 break;
1a578e9b
AC
10547 default:
10548 strcpy(cs, "mac-roman");
10549 break;
10550 }
10551 }
10552
10553 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10554 foundry, family, style & bold ? "bold" : "medium",
10555 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
177c0ea7 10556
1a578e9b
AC
10557 result = (char *) xmalloc (strlen (xf) + 1);
10558 strcpy (result, xf);
10559 for (p = result; *p; p++)
10560 *p = tolower(*p);
10561 return result;
10562}
177c0ea7 10563
1a578e9b
AC
10564
10565/* Convert an X font spec to the corresponding mac font name, which
10566 can then be passed to GetFNum after conversion to a Pascal string.
10567 For ordinary Mac fonts, this should just be their names, like
10568 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10569 collection contain their charset designation in their names, like
10570 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10571 names are handled accordingly. */
10572static void
10573x_font_name_to_mac_font_name (char *xf, char *mf)
10574{
10575 char foundry[32], family[32], weight[20], slant[2], cs[32];
10576
10577 strcpy (mf, "");
10578
10579 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10580 foundry, family, weight, slant, cs) != 5 &&
10581 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10582 foundry, family, weight, slant, cs) != 5)
10583 return;
10584
83a96b4d 10585 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
1a578e9b 10586 || strcmp (cs, "jisx0208.1983-sjis") == 0
2f64cf3a 10587 || strcmp (cs, "jisx0201.1976-0") == 0
83a96b4d 10588 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
1a578e9b
AC
10589 strcpy(mf, family);
10590 else
10591 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10592}
10593
10594
f00691a3
AC
10595static void
10596add_font_name_table_entry (char *font_name)
10597{
10598 if (font_name_table_size == 0)
10599 {
10600 font_name_table_size = 16;
10601 font_name_table = (char **)
10602 xmalloc (font_name_table_size * sizeof (char *));
10603 }
10604 else if (font_name_count + 1 >= font_name_table_size)
10605 {
10606 font_name_table_size += 16;
10607 font_name_table = (char **)
10608 xrealloc (font_name_table,
10609 font_name_table_size * sizeof (char *));
10610 }
10611
10612 font_name_table[font_name_count++] = font_name;
10613}
10614
10615/* Sets up the table font_name_table to contain the list of all fonts
10616 in the system the first time the table is used so that the Resource
10617 Manager need not be accessed every time this information is
10618 needed. */
1a578e9b
AC
10619
10620static void
10621init_font_name_table ()
10622{
e0f712ba
AC
10623#if TARGET_API_MAC_CARBON
10624 SInt32 sv;
177c0ea7 10625
e0f712ba
AC
10626 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10627 {
10628 FMFontFamilyIterator ffi;
10629 FMFontFamilyInstanceIterator ffii;
10630 FMFontFamily ff;
1a578e9b 10631
e0f712ba
AC
10632 /* Create a dummy instance iterator here to avoid creating and
10633 destroying it in the loop. */
10634 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10635 return;
10636 /* Create an iterator to enumerate the font families. */
10637 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10638 != noErr)
10639 {
10640 FMDisposeFontFamilyInstanceIterator (&ffii);
10641 return;
10642 }
1a578e9b 10643
e0f712ba
AC
10644 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10645 {
10646 Str255 name;
10647 FMFont font;
10648 FMFontStyle style;
10649 FMFontSize size;
10650 SInt16 sc;
177c0ea7 10651
e0f712ba
AC
10652 if (FMGetFontFamilyName (ff, name) != noErr)
10653 break;
10654 p2cstr (name);
177c0ea7 10655
e0f712ba 10656 sc = FontToScript (ff);
177c0ea7 10657
e0f712ba
AC
10658 /* Point the instance iterator at the current font family. */
10659 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10660 break;
177c0ea7 10661
e0f712ba
AC
10662 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10663 == noErr)
f00691a3
AC
10664 if (size == 0)
10665 {
10666 add_font_name_table_entry (mac_to_x_fontname (name, size,
10667 style, sc));
10668 add_font_name_table_entry (mac_to_x_fontname (name, size,
10669 italic, sc));
10670 add_font_name_table_entry (mac_to_x_fontname (name, size,
10671 bold, sc));
10672 add_font_name_table_entry (mac_to_x_fontname (name, size,
10673 italic | bold,
10674 sc));
10675 }
10676 else
a0f593ff
AC
10677 {
10678 add_font_name_table_entry (mac_to_x_fontname (name, size,
10679 style, sc));
10680 if (smJapanese == sc)
10681 add_font_name_table_entry (mac_to_x_fontname (name, size,
10682 style,
10683 -smJapanese));
10684 }
e0f712ba 10685 }
177c0ea7 10686
e0f712ba
AC
10687 /* Dispose of the iterators. */
10688 FMDisposeFontFamilyIterator (&ffi);
10689 FMDisposeFontFamilyInstanceIterator (&ffii);
10690 }
10691 else
1a578e9b 10692 {
e0f712ba
AC
10693#endif /* TARGET_API_MAC_CARBON */
10694 GrafPtr port;
10695 SInt16 fontnum, old_fontnum;
10696 int num_mac_fonts = CountResources('FOND');
10697 int i, j;
10698 Handle font_handle, font_handle_2;
10699 short id, scriptcode;
10700 ResType type;
10701 Str32 name;
10702 struct FontAssoc *fat;
10703 struct AsscEntry *assc_entry;
177c0ea7 10704
e0f712ba
AC
10705 GetPort (&port); /* save the current font number used */
10706#if TARGET_API_MAC_CARBON
10707 old_fontnum = GetPortTextFont (port);
10708#else
10709 old_fontnum = port->txFont;
10710#endif
10711
10712 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10713 {
10714 font_handle = GetIndResource ('FOND', i);
10715 if (!font_handle)
10716 continue;
177c0ea7 10717
e0f712ba
AC
10718 GetResInfo (font_handle, &id, &type, name);
10719 GetFNum (name, &fontnum);
10720 p2cstr (name);
10721 if (fontnum == 0)
10722 continue;
177c0ea7 10723
e0f712ba
AC
10724 TextFont (fontnum);
10725 scriptcode = FontToScript (fontnum);
10726 do
10727 {
10728 HLock (font_handle);
177c0ea7 10729
e0f712ba
AC
10730 if (GetResourceSizeOnDisk (font_handle)
10731 >= sizeof (struct FamRec))
10732 {
10733 fat = (struct FontAssoc *) (*font_handle
10734 + sizeof (struct FamRec));
10735 assc_entry
10736 = (struct AsscEntry *) (*font_handle
10737 + sizeof (struct FamRec)
10738 + sizeof (struct FontAssoc));
177c0ea7 10739
e0f712ba 10740 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
199f9270 10741 {
e0f712ba
AC
10742 if (font_name_table_size == 0)
10743 {
10744 font_name_table_size = 16;
10745 font_name_table = (char **)
10746 xmalloc (font_name_table_size * sizeof (char *));
10747 }
10748 else if (font_name_count >= font_name_table_size)
10749 {
10750 font_name_table_size += 16;
10751 font_name_table = (char **)
10752 xrealloc (font_name_table,
10753 font_name_table_size * sizeof (char *));
10754 }
199f9270 10755 font_name_table[font_name_count++]
e0f712ba 10756 = mac_to_x_fontname (name,
199f9270
AC
10757 assc_entry->fontSize,
10758 assc_entry->fontStyle,
e0f712ba
AC
10759 scriptcode);
10760 /* Both jisx0208.1983-sjis and
10761 jisx0201.1976-sjis parts are contained in
10762 Apple Japanese (SJIS) font. */
10763 if (smJapanese == scriptcode)
10764 {
10765 font_name_table[font_name_count++]
10766 = mac_to_x_fontname (name,
10767 assc_entry->fontSize,
10768 assc_entry->fontStyle,
a0f593ff 10769 -smJapanese);
e0f712ba 10770 }
199f9270 10771 }
e0f712ba 10772 }
177c0ea7 10773
e0f712ba
AC
10774 HUnlock (font_handle);
10775 font_handle_2 = GetNextFOND (font_handle);
10776 ReleaseResource (font_handle);
10777 font_handle = font_handle_2;
10778 }
10779 while (ResError () == noErr && font_handle);
10780 }
177c0ea7 10781
e0f712ba
AC
10782 TextFont (old_fontnum);
10783#if TARGET_API_MAC_CARBON
1a578e9b 10784 }
e0f712ba 10785#endif /* TARGET_API_MAC_CARBON */
1a578e9b
AC
10786}
10787
10788
10789/* Return a list of at most MAXNAMES font specs matching the one in
10ba2aec
AC
10790 PATTERN. Cache matching fonts for patterns in
10791 dpyinfo->name_list_element to avoid looking them up again by
10792 calling mac_font_pattern_match (slow). */
1a578e9b
AC
10793
10794Lisp_Object
10795x_list_fonts (struct frame *f,
10796 Lisp_Object pattern,
10797 int size,
10798 int maxnames)
10799{
10800 char *ptnstr;
10ba2aec 10801 Lisp_Object newlist = Qnil, tem, key;
1a578e9b
AC
10802 int n_fonts = 0;
10803 int i;
b179a3a2 10804 struct gcpro gcpro1, gcpro2;
10ba2aec 10805 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
1a578e9b
AC
10806
10807 if (font_name_table == NULL) /* Initialize when first used. */
10808 init_font_name_table ();
10809
10ba2aec
AC
10810 if (dpyinfo)
10811 {
10812 tem = XCDR (dpyinfo->name_list_element);
10813 key = Fcons (pattern, make_number (maxnames));
10814
10815 newlist = Fassoc (key, tem);
10816 if (!NILP (newlist))
10817 {
10818 newlist = Fcdr_safe (newlist);
10819 goto label_cached;
10820 }
10821 }
10822
d5db4077 10823 ptnstr = SDATA (pattern);
1a578e9b 10824
b179a3a2
AC
10825 GCPRO2 (pattern, newlist);
10826
1a578e9b
AC
10827 /* Scan and matching bitmap fonts. */
10828 for (i = 0; i < font_name_count; i++)
10829 {
10830 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10831 {
10832 newlist = Fcons (build_string (font_name_table[i]), newlist);
10833
10834 n_fonts++;
10835 if (n_fonts >= maxnames)
10836 break;
10837 }
10838 }
177c0ea7 10839
1a578e9b
AC
10840 /* MAC_TODO: add code for matching outline fonts here */
10841
b179a3a2
AC
10842 UNGCPRO;
10843
10ba2aec
AC
10844 if (dpyinfo)
10845 {
10846 XSETCDR (dpyinfo->name_list_element,
10847 Fcons (Fcons (key, newlist),
10848 XCDR (dpyinfo->name_list_element)));
10849 }
10850 label_cached:
177c0ea7 10851
1a578e9b
AC
10852 return newlist;
10853}
10854
10855
10856#if GLYPH_DEBUG
10857
e0f712ba
AC
10858/* Check that FONT is valid on frame F. It is if it can be found in F's
10859 font table. */
1a578e9b
AC
10860
10861static void
10862x_check_font (f, font)
10863 struct frame *f;
10864 XFontStruct *font;
10865{
10866 int i;
10867 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10868
10869 xassert (font != NULL);
10870
10871 for (i = 0; i < dpyinfo->n_fonts; i++)
177c0ea7 10872 if (dpyinfo->font_table[i].name
1a578e9b
AC
10873 && font == dpyinfo->font_table[i].font)
10874 break;
10875
10876 xassert (i < dpyinfo->n_fonts);
10877}
10878
10879#endif /* GLYPH_DEBUG != 0 */
10880
1a578e9b
AC
10881/* Set *W to the minimum width, *H to the minimum font height of FONT.
10882 Note: There are (broken) X fonts out there with invalid XFontStruct
10883 min_bounds contents. For example, handa@etl.go.jp reports that
10884 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10885 have font->min_bounds.width == 0. */
10886
10887static INLINE void
10888x_font_min_bounds (font, w, h)
10889 MacFontStruct *font;
10890 int *w, *h;
10891{
e0f712ba
AC
10892 /*
10893 * TODO: Windows does not appear to offer min bound, only
10894 * average and maximum width, and maximum height.
10895 */
1a578e9b 10896 *h = FONT_HEIGHT (font);
e0f712ba 10897 *w = FONT_WIDTH (font);
1a578e9b
AC
10898}
10899
10900
10901/* Compute the smallest character width and smallest font height over
10902 all fonts available on frame F. Set the members smallest_char_width
10903 and smallest_font_height in F's x_display_info structure to
10904 the values computed. Value is non-zero if smallest_font_height or
10905 smallest_char_width become smaller than they were before. */
10906
e0f712ba 10907int
1a578e9b
AC
10908x_compute_min_glyph_bounds (f)
10909 struct frame *f;
10910{
10911 int i;
10912 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10913 MacFontStruct *font;
10914 int old_width = dpyinfo->smallest_char_width;
10915 int old_height = dpyinfo->smallest_font_height;
177c0ea7 10916
1a578e9b
AC
10917 dpyinfo->smallest_font_height = 100000;
10918 dpyinfo->smallest_char_width = 100000;
177c0ea7 10919
1a578e9b
AC
10920 for (i = 0; i < dpyinfo->n_fonts; ++i)
10921 if (dpyinfo->font_table[i].name)
10922 {
10923 struct font_info *fontp = dpyinfo->font_table + i;
10924 int w, h;
177c0ea7 10925
1a578e9b
AC
10926 font = (MacFontStruct *) fontp->font;
10927 xassert (font != (MacFontStruct *) ~0);
10928 x_font_min_bounds (font, &w, &h);
177c0ea7 10929
1a578e9b
AC
10930 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10931 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10932 }
10933
10934 xassert (dpyinfo->smallest_char_width > 0
10935 && dpyinfo->smallest_font_height > 0);
10936
10937 return (dpyinfo->n_fonts == 1
10938 || dpyinfo->smallest_char_width < old_width
10939 || dpyinfo->smallest_font_height < old_height);
10940}
10941
10942
10943/* Determine whether given string is a fully-specified XLFD: all 14
10944 fields are present, none is '*'. */
10945
10946static int
10947is_fully_specified_xlfd (char *p)
10948{
10949 int i;
10950 char *q;
10951
10952 if (*p != '-')
10953 return 0;
177c0ea7 10954
1a578e9b
AC
10955 for (i = 0; i < 13; i++)
10956 {
10957 q = strchr (p + 1, '-');
10958 if (q == NULL)
10959 return 0;
10960 if (q - p == 2 && *(p + 1) == '*')
10961 return 0;
10962 p = q;
10963 }
10964
10965 if (strchr (p + 1, '-') != NULL)
10966 return 0;
177c0ea7 10967
1a578e9b
AC
10968 if (*(p + 1) == '*' && *(p + 2) == '\0')
10969 return 0;
10970
10971 return 1;
10972}
10973
10974
10975const int kDefaultFontSize = 9;
10976
10977
e0f712ba
AC
10978/* XLoadQueryFont creates and returns an internal representation for a
10979 font in a MacFontStruct struct. There is really no concept
10980 corresponding to "loading" a font on the Mac. But we check its
10981 existence and find the font number and all other information for it
10982 and store them in the returned MacFontStruct. */
1a578e9b
AC
10983
10984static MacFontStruct *
10985XLoadQueryFont (Display *dpy, char *fontname)
10986{
10987 int i, size, is_two_byte_font, char_width;
10988 char *name;
10989 GrafPtr port;
10990 SInt16 old_fontnum, old_fontsize;
10991 Style old_fontface;
10992 Str32 mfontname;
10993 SInt16 fontnum;
10994 Style fontface = normal;
10995 MacFontStruct *font;
10996 FontInfo the_fontinfo;
10997 char s_weight[7], c_slant;
10998
10999 if (is_fully_specified_xlfd (fontname))
11000 name = fontname;
11001 else
11002 {
11003 for (i = 0; i < font_name_count; i++)
11004 if (mac_font_pattern_match (font_name_table[i], fontname))
11005 break;
11006
11007 if (i >= font_name_count)
11008 return NULL;
177c0ea7 11009
1a578e9b
AC
11010 name = font_name_table[i];
11011 }
11012
11013 GetPort (&port); /* save the current font number used */
e0f712ba
AC
11014#if TARGET_API_MAC_CARBON
11015 old_fontnum = GetPortTextFont (port);
11016 old_fontsize = GetPortTextSize (port);
11017 old_fontface = GetPortTextFace (port);
11018#else
1a578e9b
AC
11019 old_fontnum = port->txFont;
11020 old_fontsize = port->txSize;
11021 old_fontface = port->txFace;
e0f712ba 11022#endif
1a578e9b
AC
11023
11024 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11025 size = kDefaultFontSize;
11026
11027 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11028 if (strcmp (s_weight, "bold") == 0)
11029 fontface |= bold;
11030
11031 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11032 if (c_slant == 'i')
11033 fontface |= italic;
11034
11035 x_font_name_to_mac_font_name (name, mfontname);
11036 c2pstr (mfontname);
11037 GetFNum (mfontname, &fontnum);
11038 if (fontnum == 0)
11039 return NULL;
177c0ea7 11040
1a578e9b 11041 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
177c0ea7 11042
1a578e9b
AC
11043 font->fontname = (char *) xmalloc (strlen (name) + 1);
11044 bcopy (name, font->fontname, strlen (name) + 1);
11045
11046 font->mac_fontnum = fontnum;
11047 font->mac_fontsize = size;
11048 font->mac_fontface = fontface;
11049 font->mac_scriptcode = FontToScript (fontnum);
11050
199f9270 11051 /* Apple Japanese (SJIS) font is listed as both
2f64cf3a 11052 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
e0f712ba 11053 (Roman script) in init_font_name_table (). The latter should be
2f64cf3a 11054 treated as a one-byte font. */
199f9270
AC
11055 {
11056 char cs[32];
11057
177c0ea7 11058 if (sscanf (name,
199f9270
AC
11059 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11060 cs) == 1
177c0ea7 11061 && 0 == strcmp (cs, "jisx0201.1976-0"))
199f9270
AC
11062 font->mac_scriptcode = smRoman;
11063 }
177c0ea7 11064
1a578e9b
AC
11065 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11066 font->mac_scriptcode == smTradChinese ||
11067 font->mac_scriptcode == smSimpChinese ||
11068 font->mac_scriptcode == smKorean;
11069
11070 TextFont (fontnum);
11071 TextSize (size);
11072 TextFace (fontface);
177c0ea7 11073
1a578e9b
AC
11074 GetFontInfo (&the_fontinfo);
11075
11076 font->ascent = the_fontinfo.ascent;
11077 font->descent = the_fontinfo.descent;
11078
11079 font->min_byte1 = 0;
11080 if (is_two_byte_font)
11081 font->max_byte1 = 1;
11082 else
11083 font->max_byte1 = 0;
11084 font->min_char_or_byte2 = 0x20;
11085 font->max_char_or_byte2 = 0xff;
177c0ea7 11086
1a578e9b
AC
11087 if (is_two_byte_font)
11088 {
11089 /* Use the width of an "ideographic space" of that font because
11090 the_fontinfo.widMax returns the wrong width for some fonts. */
11091 switch (font->mac_scriptcode)
11092 {
11093 case smJapanese:
11094 char_width = StringWidth("\p\x81\x40");
11095 break;
11096 case smTradChinese:
11097 char_width = StringWidth("\p\xa1\x40");
11098 break;
11099 case smSimpChinese:
11100 char_width = StringWidth("\p\xa1\xa1");
11101 break;
11102 case smKorean:
11103 char_width = StringWidth("\p\xa1\xa1");
11104 break;
11105 }
11106 }
11107 else
11108 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11109 returns 15 for 12-point Monaco! */
11110 char_width = CharWidth ('m');
11111
11112 font->max_bounds.rbearing = char_width;
11113 font->max_bounds.lbearing = 0;
11114 font->max_bounds.width = char_width;
11115 font->max_bounds.ascent = the_fontinfo.ascent;
11116 font->max_bounds.descent = the_fontinfo.descent;
11117
11118 font->min_bounds = font->max_bounds;
11119
11120 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11121 font->per_char = NULL;
11122 else
11123 {
11124 font->per_char = (XCharStruct *)
11125 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11126 {
11127 int c;
177c0ea7 11128
1a578e9b
AC
11129 for (c = 0x20; c <= 0xff; c++)
11130 {
11131 font->per_char[c - 0x20] = font->max_bounds;
11132 font->per_char[c - 0x20].width = CharWidth (c);
11133 }
11134 }
11135 }
177c0ea7 11136
1a578e9b
AC
11137 TextFont (old_fontnum); /* restore previous font number, size and face */
11138 TextSize (old_fontsize);
11139 TextFace (old_fontface);
177c0ea7 11140
1a578e9b
AC
11141 return font;
11142}
11143
11144
11145/* Load font named FONTNAME of the size SIZE for frame F, and return a
11146 pointer to the structure font_info while allocating it dynamically.
11147 If SIZE is 0, load any size of font.
11148 If loading is failed, return NULL. */
11149
11150struct font_info *
11151x_load_font (f, fontname, size)
11152 struct frame *f;
11153 register char *fontname;
11154 int size;
11155{
11156 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11157 Lisp_Object font_names;
11158
11159 /* Get a list of all the fonts that match this name. Once we
11160 have a list of matching fonts, we compare them against the fonts
11161 we already have by comparing names. */
11162 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11163
11164 if (!NILP (font_names))
11165 {
11166 Lisp_Object tail;
11167 int i;
11168
11169 for (i = 0; i < dpyinfo->n_fonts; i++)
11170 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11171 if (dpyinfo->font_table[i].name
11172 && (!strcmp (dpyinfo->font_table[i].name,
d5db4077 11173 SDATA (XCAR (tail)))
1a578e9b 11174 || !strcmp (dpyinfo->font_table[i].full_name,
d5db4077 11175 SDATA (XCAR (tail)))))
1a578e9b
AC
11176 return (dpyinfo->font_table + i);
11177 }
11178
11179 /* Load the font and add it to the table. */
11180 {
11181 char *full_name;
11182 struct MacFontStruct *font;
11183 struct font_info *fontp;
11184 unsigned long value;
11185 int i;
11186
11187 /* If we have found fonts by x_list_font, load one of them. If
11188 not, we still try to load a font by the name given as FONTNAME
11189 because XListFonts (called in x_list_font) of some X server has
11190 a bug of not finding a font even if the font surely exists and
11191 is loadable by XLoadQueryFont. */
11192 if (size > 0 && !NILP (font_names))
d5db4077 11193 fontname = (char *) SDATA (XCAR (font_names));
1a578e9b
AC
11194
11195 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11196 if (!font)
11197 return NULL;
11198
11199 /* Find a free slot in the font table. */
11200 for (i = 0; i < dpyinfo->n_fonts; ++i)
11201 if (dpyinfo->font_table[i].name == NULL)
11202 break;
11203
11204 /* If no free slot found, maybe enlarge the font table. */
11205 if (i == dpyinfo->n_fonts
11206 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11207 {
11208 int sz;
11209 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11210 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11211 dpyinfo->font_table
11212 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11213 }
11214
11215 fontp = dpyinfo->font_table + i;
11216 if (i == dpyinfo->n_fonts)
11217 ++dpyinfo->n_fonts;
11218
11219 /* Now fill in the slots of *FONTP. */
11220 BLOCK_INPUT;
11221 fontp->font = font;
11222 fontp->font_idx = i;
11223 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11224 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11225
11226 fontp->full_name = fontp->name;
11227
11228 fontp->size = font->max_bounds.width;
11229 fontp->height = FONT_HEIGHT (font);
11230 {
11231 /* For some font, ascent and descent in max_bounds field is
11232 larger than the above value. */
11233 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11234 if (max_height > fontp->height)
11235 fontp->height = max_height;
11236 }
11237
11238 /* The slot `encoding' specifies how to map a character
11239 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11240 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11241 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11242 2:0xA020..0xFF7F). For the moment, we don't know which charset
11243 uses this font. So, we set information in fontp->encoding[1]
11244 which is never used by any charset. If mapping can't be
11245 decided, set FONT_ENCODING_NOT_DECIDED. */
11246 if (font->mac_scriptcode == smJapanese)
11247 fontp->encoding[1] = 4;
11248 else
11249 {
11250 fontp->encoding[1]
11251 = (font->max_byte1 == 0
11252 /* 1-byte font */
11253 ? (font->min_char_or_byte2 < 0x80
11254 ? (font->max_char_or_byte2 < 0x80
11255 ? 0 /* 0x20..0x7F */
11256 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11257 : 1) /* 0xA0..0xFF */
11258 /* 2-byte font */
11259 : (font->min_byte1 < 0x80
11260 ? (font->max_byte1 < 0x80
11261 ? (font->min_char_or_byte2 < 0x80
11262 ? (font->max_char_or_byte2 < 0x80
11263 ? 0 /* 0x2020..0x7F7F */
11264 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11265 : 3) /* 0x20A0..0x7FFF */
11266 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11267 : (font->min_char_or_byte2 < 0x80
11268 ? (font->max_char_or_byte2 < 0x80
11269 ? 2 /* 0xA020..0xFF7F */
11270 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11271 : 1))); /* 0xA0A0..0xFFFF */
11272 }
11273
11274#if 0 /* MAC_TODO: fill these out with more reasonably values */
11275 fontp->baseline_offset
11276 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11277 ? (long) value : 0);
11278 fontp->relative_compose
11279 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11280 ? (long) value : 0);
11281 fontp->default_ascent
11282 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11283 ? (long) value : 0);
11284#else
11285 fontp->baseline_offset = 0;
11286 fontp->relative_compose = 0;
11287 fontp->default_ascent = 0;
11288#endif
11289
11290 /* Set global flag fonts_changed_p to non-zero if the font loaded
11291 has a character with a smaller width than any other character
11292 before, or if the font loaded has a smalle>r height than any
11293 other font loaded before. If this happens, it will make a
11294 glyph matrix reallocation necessary. */
11295 fonts_changed_p = x_compute_min_glyph_bounds (f);
11296 UNBLOCK_INPUT;
11297 return fontp;
11298 }
11299}
11300
11301
11302/* Return a pointer to struct font_info of a font named FONTNAME for
11303 frame F. If no such font is loaded, return NULL. */
11304
11305struct font_info *
11306x_query_font (f, fontname)
11307 struct frame *f;
11308 register char *fontname;
11309{
11310 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11311 int i;
11312
11313 for (i = 0; i < dpyinfo->n_fonts; i++)
11314 if (dpyinfo->font_table[i].name
11315 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11316 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11317 return (dpyinfo->font_table + i);
11318 return NULL;
11319}
11320
11321
11322/* Find a CCL program for a font specified by FONTP, and set the member
11323 `encoder' of the structure. */
11324
11325void
11326x_find_ccl_program (fontp)
11327 struct font_info *fontp;
11328{
11329 Lisp_Object list, elt;
11330
11331 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11332 {
11333 elt = XCAR (list);
11334 if (CONSP (elt)
11335 && STRINGP (XCAR (elt))
11336 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11337 >= 0))
11338 break;
11339 }
11340 if (! NILP (list))
11341 {
11342 struct ccl_program *ccl
11343 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11344
11345 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11346 xfree (ccl);
11347 else
11348 fontp->font_encoder = ccl;
11349 }
11350}
11351
11352
11353\f
11354/***********************************************************************
11355 Initialization
11356 ***********************************************************************/
11357
11358#ifdef USE_X_TOOLKIT
11359static XrmOptionDescRec emacs_options[] = {
11360 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11361 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11362
11363 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11364 XrmoptionSepArg, NULL},
11365 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11366
11367 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11368 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11369 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11370 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11371 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11372 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11373 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11374};
11375#endif /* USE_X_TOOLKIT */
11376
11377static int x_initialized;
11378
11379#ifdef MULTI_KBOARD
11380/* Test whether two display-name strings agree up to the dot that separates
11381 the screen number from the server number. */
11382static int
11383same_x_server (name1, name2)
11384 char *name1, *name2;
11385{
11386 int seen_colon = 0;
d5db4077 11387 unsigned char *system_name = SDATA (Vsystem_name);
1a578e9b
AC
11388 int system_name_length = strlen (system_name);
11389 int length_until_period = 0;
11390
11391 while (system_name[length_until_period] != 0
11392 && system_name[length_until_period] != '.')
11393 length_until_period++;
11394
11395 /* Treat `unix' like an empty host name. */
11396 if (! strncmp (name1, "unix:", 5))
11397 name1 += 4;
11398 if (! strncmp (name2, "unix:", 5))
11399 name2 += 4;
11400 /* Treat this host's name like an empty host name. */
11401 if (! strncmp (name1, system_name, system_name_length)
11402 && name1[system_name_length] == ':')
11403 name1 += system_name_length;
11404 if (! strncmp (name2, system_name, system_name_length)
11405 && name2[system_name_length] == ':')
11406 name2 += system_name_length;
11407 /* Treat this host's domainless name like an empty host name. */
11408 if (! strncmp (name1, system_name, length_until_period)
11409 && name1[length_until_period] == ':')
e0f712ba
AC
11410 name1 += length_until_period;
11411 if (! strncmp (name2, system_name, length_until_period)
11412 && name2[length_until_period] == ':')
11413 name2 += length_until_period;
11414
11415 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11416 {
11417 if (*name1 == ':')
11418 seen_colon++;
11419 if (seen_colon && *name1 == '.')
11420 return 1;
11421 }
11422 return (seen_colon
11423 && (*name1 == '.' || *name1 == '\0')
11424 && (*name2 == '.' || *name2 == '\0'));
11425}
11426#endif
1a578e9b
AC
11427
11428
11429/* The Mac Event loop code */
11430
e0f712ba 11431#ifndef MAC_OSX
1a578e9b
AC
11432#include <Events.h>
11433#include <Quickdraw.h>
11434#include <Balloons.h>
11435#include <Devices.h>
11436#include <Fonts.h>
11437#include <Gestalt.h>
11438#include <Menus.h>
11439#include <Processes.h>
11440#include <Sound.h>
11441#include <ToolUtils.h>
11442#include <TextUtils.h>
11443#include <Dialogs.h>
11444#include <Script.h>
1a578e9b
AC
11445#include <Types.h>
11446#include <TextEncodingConverter.h>
11447#include <Resources.h>
11448
11449#if __MWERKS__
11450#include <unix.h>
11451#endif
e0f712ba 11452#endif /* ! MAC_OSX */
1a578e9b
AC
11453
11454#define M_APPLE 128
11455#define I_ABOUT 1
11456
11457#define WINDOW_RESOURCE 128
11458#define TERM_WINDOW_RESOURCE 129
11459
11460#define DEFAULT_NUM_COLS 80
11461
11462#define MIN_DOC_SIZE 64
11463#define MAX_DOC_SIZE 32767
11464
11465/* sleep time for WaitNextEvent */
11466#define WNE_SLEEP_AT_SUSPEND 10
11467#define WNE_SLEEP_AT_RESUME 1
11468
11469/* true when cannot handle any Mac OS events */
11470static int handling_window_update = 0;
11471
11472/* the flag appl_is_suspended is used both for determining the sleep
11473 time to be passed to WaitNextEvent and whether the cursor should be
11474 drawn when updating the display. The cursor is turned off when
11475 Emacs is suspended. Redrawing it is unnecessary and what needs to
11476 be done depends on whether the cursor lies inside or outside the
11477 redraw region. So we might as well skip drawing it when Emacs is
11478 suspended. */
11479static Boolean app_is_suspended = false;
11480static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11481
11482#define EXTRA_STACK_ALLOC (256 * 1024)
11483
11484#define ARGV_STRING_LIST_ID 129
11485#define ABOUT_ALERT_ID 128
2e875e36 11486#define RAM_TOO_LARGE_ALERT_ID 129
1a578e9b
AC
11487
11488Boolean terminate_flag = false;
11489
742fbed7 11490/* True if using command key as meta key. */
1a578e9b
AC
11491Lisp_Object Vmac_command_key_is_meta;
11492
742fbed7
AC
11493/* True if the ctrl and meta keys should be reversed. */
11494Lisp_Object Vmac_reverse_ctrl_meta;
11495
11496#if USE_CARBON_EVENTS
11497/* True if the mouse wheel button (i.e. button 4) should map to
11498 mouse-2, instead of mouse-3. */
11499Lisp_Object Vmac_wheel_button_is_mouse_2;
5883787c
AC
11500
11501/* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
11502 for processing before Emacs sees it. */
11503Lisp_Object Vmac_pass_command_to_system;
11504
11505/* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
11506 for processing before Emacs sees it. */
11507Lisp_Object Vmac_pass_control_to_system;
742fbed7
AC
11508#endif
11509
1a578e9b
AC
11510/* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11511 to this text encoding */
11512int mac_keyboard_text_encoding;
11513int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11514
11515/* Set in term/mac-win.el to indicate that event loop can now generate
11516 drag and drop events. */
8f47302e 11517Lisp_Object Qmac_ready_for_drag_n_drop;
1a578e9b
AC
11518
11519Lisp_Object drag_and_drop_file_list;
11520
11521Point saved_menu_event_location;
11522
11523/* Apple Events */
742fbed7 11524static void init_required_apple_events (void);
e0f712ba 11525static pascal OSErr
742fbed7 11526do_ae_open_application (const AppleEvent *, AppleEvent *, long);
e0f712ba 11527static pascal OSErr
742fbed7
AC
11528do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
11529static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
11530static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
11531
11532/* Drag and Drop */
11533static OSErr init_mac_drag_n_drop ();
177c0ea7 11534static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
742fbed7
AC
11535
11536#if USE_CARBON_EVENTS
11537/* Preliminary Support for the OSX Services Menu */
11538static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
11539static void init_service_handler ();
11540#endif
1a578e9b
AC
11541
11542extern void init_emacs_passwd_dir ();
11543extern int emacs_main (int, char **, char **);
11544extern void check_alarm ();
11545
11546extern void initialize_applescript();
11547extern void terminate_applescript();
11548
177c0ea7 11549static unsigned int
742fbed7
AC
11550#if USE_CARBON_EVENTS
11551mac_to_emacs_modifiers (UInt32 mods)
11552#else
11553mac_to_emacs_modifiers (EventModifiers mods)
11554#endif
11555{
11556 unsigned int result = 0;
11557 if (mods & macShiftKey)
11558 result |= shift_modifier;
11559 if (mods & macCtrlKey)
11560 result |= ctrl_modifier;
11561 if (mods & macMetaKey)
11562 result |= meta_modifier;
11563 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
11564 result |= alt_modifier;
11565 return result;
11566}
11567
11568#if USE_CARBON_EVENTS
11569/* Obtains the event modifiers from the event ref and then calls
11570 mac_to_emacs_modifiers. */
177c0ea7
JB
11571static int
11572mac_event_to_emacs_modifiers (EventRef eventRef)
742fbed7
AC
11573{
11574 UInt32 mods = 0;
11575 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
11576 sizeof (UInt32), NULL, &mods);
11577 return mac_to_emacs_modifiers (mods);
11578}
11579
11580/* Given an event ref, return the code to use for the mouse button
11581 code in the emacs input_event. */
11582static int
177c0ea7 11583mac_get_mouse_btn (EventRef ref)
742fbed7
AC
11584{
11585 EventMouseButton result = kEventMouseButtonPrimary;
11586 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
11587 sizeof (EventMouseButton), NULL, &result);
177c0ea7 11588 switch (result)
742fbed7
AC
11589 {
11590 case kEventMouseButtonPrimary:
11591 return 0;
11592 case kEventMouseButtonSecondary:
177c0ea7 11593 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
742fbed7
AC
11594 case kEventMouseButtonTertiary:
11595 case 4: /* 4 is the number for the mouse wheel button */
177c0ea7 11596 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
742fbed7
AC
11597 default:
11598 return 0;
11599 }
11600}
11601
11602/* Normally, ConvertEventRefToEventRecord will correctly handle all
11603 events. However the click of the mouse wheel is not converted to a
11604 mouseDown or mouseUp event. This calls ConvertEventRef, but then
11605 checks to see if it is a mouse up or down carbon event that has not
11606 been converted, and if so, converts it by hand (to be picked up in
11607 the XTread_socket loop). */
177c0ea7 11608static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
742fbed7
AC
11609{
11610 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
11611 /* Do special case for mouse wheel button. */
177c0ea7
JB
11612 if (!result && GetEventClass (eventRef) == kEventClassMouse)
11613 {
742fbed7 11614 UInt32 kind = GetEventKind (eventRef);
177c0ea7 11615 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
742fbed7
AC
11616 {
11617 eventRec->what = mouseDown;
11618 result=1;
11619 }
177c0ea7 11620 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
742fbed7
AC
11621 {
11622 eventRec->what = mouseUp;
11623 result=1;
11624 }
177c0ea7 11625 if (result)
742fbed7
AC
11626 {
11627 /* Need where and when. */
11628 UInt32 mods;
11629 GetEventParameter (eventRef, kEventParamMouseLocation,
11630 typeQDPoint, NULL, sizeof (Point),
11631 NULL, &eventRec->where);
11632 /* Use two step process because new event modifiers are
11633 32-bit and old are 16-bit. Currently, only loss is
11634 NumLock & Fn. */
11635 GetEventParameter (eventRef, kEventParamKeyModifiers,
11636 typeUInt32, NULL, sizeof (UInt32),
11637 NULL, &mods);
11638 eventRec->modifiers = mods;
177c0ea7 11639
742fbed7
AC
11640 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
11641 }
11642 }
11643 return result;
11644}
11645
11646#endif
1a578e9b
AC
11647
11648static void
11649do_get_menus (void)
11650{
11651 Handle menubar_handle;
11652 MenuHandle menu_handle;
177c0ea7 11653
1a578e9b
AC
11654 menubar_handle = GetNewMBar (128);
11655 if(menubar_handle == NULL)
11656 abort ();
11657 SetMenuBar (menubar_handle);
11658 DrawMenuBar ();
11659
11660 menu_handle = GetMenuHandle (M_APPLE);
11661 if(menu_handle != NULL)
11662 AppendResMenu (menu_handle,'DRVR');
11663 else
11664 abort ();
11665}
11666
11667
11668static void
11669do_init_managers (void)
11670{
e0f712ba 11671#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11672 InitGraf (&qd.thePort);
11673 InitFonts ();
11674 FlushEvents (everyEvent, 0);
11675 InitWindows ();
11676 InitMenus ();
11677 TEInit ();
11678 InitDialogs (NULL);
e0f712ba
AC
11679#endif /* !TARGET_API_MAC_CARBON */
11680 InitCursor ();
177c0ea7 11681
e0f712ba 11682#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11683 /* set up some extra stack space for use by emacs */
11684 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11685
11686 /* MaxApplZone must be called for AppleScript to execute more
11687 complicated scripts */
11688 MaxApplZone ();
11689 MoreMasters ();
e0f712ba 11690#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
11691}
11692
2e875e36
AC
11693static void
11694do_check_ram_size (void)
11695{
11696 SInt32 physical_ram_size, logical_ram_size;
177c0ea7 11697
2e875e36
AC
11698 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11699 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11700 || physical_ram_size > 256 * 1024 * 1024
11701 || logical_ram_size > 256 * 1024 * 1024)
11702 {
11703 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11704 exit (1);
11705 }
11706}
11707
1a578e9b
AC
11708static void
11709do_window_update (WindowPtr win)
11710{
11711 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11712 struct frame *f = mwp->mFP;
11713
11714 if (f)
11715 {
11716 if (f->async_visible == 0)
11717 {
11718 f->async_visible = 1;
11719 f->async_iconified = 0;
11720 SET_FRAME_GARBAGED (f);
177c0ea7 11721
1a578e9b
AC
11722 /* An update event is equivalent to MapNotify on X, so report
11723 visibility changes properly. */
11724 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11725 /* Force a redisplay sooner or later to update the
11726 frame titles in case this is the second frame. */
11727 record_asynch_buffer_change ();
11728 }
11729 else
11730 {
11731 BeginUpdate (win);
11732 handling_window_update = 1;
11733
2d97ff8c
AC
11734 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
11735
1a578e9b
AC
11736 expose_frame (f, 0, 0, 0, 0);
11737
11738 handling_window_update = 0;
11739 EndUpdate (win);
11740 }
11741 }
11742}
11743
e0f712ba
AC
11744static int
11745is_emacs_window (WindowPtr win)
11746{
11747 Lisp_Object tail, frame;
11748
11749 if (!win)
11750 return 0;
11751
11752 FOR_EACH_FRAME (tail, frame)
11753 if (FRAME_MAC_P (XFRAME (frame)))
11754 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11755 return 1;
11756
11757 return 0;
11758}
11759
1a578e9b
AC
11760static void
11761do_window_activate (WindowPtr win)
11762{
e0f712ba
AC
11763 mac_output *mwp;
11764 struct frame *f;
1a578e9b 11765
e0f712ba 11766 if (is_emacs_window (win))
1a578e9b 11767 {
e0f712ba
AC
11768 mwp = (mac_output *) GetWRefCon (win);
11769 f = mwp->mFP;
177c0ea7 11770
e0f712ba
AC
11771 if (f)
11772 {
11773 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11774 activate_scroll_bars (f);
11775 }
1a578e9b
AC
11776 }
11777}
11778
11779static void
11780do_window_deactivate (WindowPtr win)
11781{
e0f712ba
AC
11782 mac_output *mwp;
11783 struct frame *f;
1a578e9b 11784
e0f712ba 11785 if (is_emacs_window (win))
1a578e9b 11786 {
e0f712ba
AC
11787 mwp = (mac_output *) GetWRefCon (win);
11788 f = mwp->mFP;
177c0ea7 11789
e0f712ba
AC
11790 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11791 {
11792 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11793 deactivate_scroll_bars (f);
11794 }
1a578e9b
AC
11795 }
11796}
11797
11798static void
11799do_app_resume ()
11800{
e0f712ba
AC
11801 WindowPtr wp;
11802 mac_output *mwp;
11803 struct frame *f;
fa0b4c14 11804
e0f712ba
AC
11805 wp = FrontWindow();
11806 if (is_emacs_window (wp))
1a578e9b 11807 {
e0f712ba
AC
11808 mwp = (mac_output *) GetWRefCon (wp);
11809 f = mwp->mFP;
11810
11811 if (f)
11812 {
11813 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11814 activate_scroll_bars (f);
11815 }
1a578e9b
AC
11816 }
11817
11818 app_is_suspended = false;
11819 app_sleep_time = WNE_SLEEP_AT_RESUME;
11820}
11821
11822static void
11823do_app_suspend ()
11824{
e0f712ba
AC
11825 WindowPtr wp;
11826 mac_output *mwp;
11827 struct frame *f;
1a578e9b 11828
e0f712ba
AC
11829 wp = FrontWindow();
11830 if (is_emacs_window (wp))
1a578e9b 11831 {
e0f712ba
AC
11832 mwp = (mac_output *) GetWRefCon (wp);
11833 f = mwp->mFP;
11834
11835 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11836 {
11837 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11838 deactivate_scroll_bars (f);
11839 }
1a578e9b
AC
11840 }
11841
11842 app_is_suspended = true;
11843 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11844}
11845
11846
11847static void
11848do_mouse_moved (Point mouse_pos)
11849{
11850 WindowPtr wp = FrontWindow ();
5883787c 11851 struct frame *f;
1a578e9b 11852
177c0ea7 11853 if (is_emacs_window (wp))
5883787c 11854 {
177c0ea7
JB
11855 f = ((mac_output *) GetWRefCon (wp))->mFP;
11856
e0f712ba
AC
11857#if TARGET_API_MAC_CARBON
11858 SetPort (GetWindowPort (wp));
11859#else
11860 SetPort (wp);
11861#endif
11862
5883787c 11863 GlobalToLocal (&mouse_pos);
177c0ea7 11864
5883787c
AC
11865 note_mouse_movement (f, &mouse_pos);
11866 }
1a578e9b
AC
11867}
11868
11869
11870static void
11871do_os_event (EventRecord *erp)
11872{
11873 switch((erp->message >> 24) & 0x000000FF)
11874 {
11875 case suspendResumeMessage:
11876 if((erp->message & resumeFlag) == 1)
11877 do_app_resume ();
11878 else
11879 do_app_suspend ();
11880 break;
177c0ea7 11881
e0f712ba 11882 case mouseMovedMessage:
1a578e9b
AC
11883 do_mouse_moved (erp->where);
11884 break;
11885 }
11886}
11887
11888static void
11889do_events (EventRecord *erp)
11890{
11891 switch (erp->what)
11892 {
11893 case updateEvt:
11894 do_window_update ((WindowPtr) erp->message);
11895 break;
11896
11897 case osEvt:
11898 do_os_event (erp);
11899 break;
11900
11901 case activateEvt:
11902 if ((erp->modifiers & activeFlag) != 0)
11903 do_window_activate ((WindowPtr) erp->message);
11904 else
11905 do_window_deactivate ((WindowPtr) erp->message);
11906 break;
11907 }
11908}
11909
11910static void
11911do_apple_menu (SInt16 menu_item)
11912{
e0f712ba 11913#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11914 Str255 item_name;
11915 SInt16 da_driver_refnum;
177c0ea7 11916
1a578e9b
AC
11917 if (menu_item == I_ABOUT)
11918 NoteAlert (ABOUT_ALERT_ID, NULL);
11919 else
11920 {
11921 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11922 da_driver_refnum = OpenDeskAcc (item_name);
11923 }
e0f712ba 11924#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
11925}
11926
11927void
11928do_menu_choice (SInt32 menu_choice)
11929{
11930 SInt16 menu_id, menu_item;
177c0ea7 11931
1a578e9b
AC
11932 menu_id = HiWord (menu_choice);
11933 menu_item = LoWord (menu_choice);
177c0ea7 11934
1a578e9b
AC
11935 if (menu_id == 0)
11936 return;
177c0ea7 11937
1a578e9b
AC
11938 switch (menu_id)
11939 {
11940 case M_APPLE:
11941 do_apple_menu (menu_item);
11942 break;
11943
11944 default:
11945 {
11946 WindowPtr wp = FrontWindow ();
177c0ea7 11947 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
1a578e9b
AC
11948 MenuHandle menu = GetMenuHandle (menu_id);
11949 if (menu)
11950 {
11951 UInt32 refcon;
177c0ea7 11952
1a578e9b
AC
11953 GetMenuItemRefCon (menu, menu_item, &refcon);
11954 menubar_selection_callback (f, refcon);
11955 }
11956 }
11957 }
177c0ea7 11958
1a578e9b
AC
11959 HiliteMenu (0);
11960}
11961
11962
11963/* Handle drags in size box. Based on code contributed by Ben
11964 Mesander and IM - Window Manager A. */
11965
11966static void
11967do_grow_window (WindowPtr w, EventRecord *e)
11968{
11969 long grow_size;
11970 Rect limit_rect;
11971 int rows, columns;
11972 mac_output *mwp = (mac_output *) GetWRefCon (w);
11973 struct frame *f = mwp->mFP;
177c0ea7 11974
1a578e9b 11975 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
177c0ea7 11976
1a578e9b 11977 grow_size = GrowWindow (w, e->where, &limit_rect);
177c0ea7 11978
1a578e9b
AC
11979 /* see if it really changed size */
11980 if (grow_size != 0)
11981 {
11982 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11983 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
177c0ea7 11984
1a578e9b
AC
11985 x_set_window_size (f, 0, columns, rows);
11986 }
11987}
11988
11989
11990/* Handle clicks in zoom box. Calculation of "standard state" based
11991 on code in IM - Window Manager A and code contributed by Ben
11992 Mesander. The standard state of an Emacs window is 80-characters
11993 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11994
11995static void
11996do_zoom_window (WindowPtr w, int zoom_in_or_out)
11997{
11998 GrafPtr save_port;
11999 Rect zoom_rect, port_rect;
12000 Point top_left;
12001 int w_title_height, columns, rows, width, height, dummy, x, y;
12002 mac_output *mwp = (mac_output *) GetWRefCon (w);
12003 struct frame *f = mwp->mFP;
177c0ea7 12004
1a578e9b 12005 GetPort (&save_port);
e0f712ba
AC
12006
12007#if TARGET_API_MAC_CARBON
12008 SetPort (GetWindowPort (w));
12009#else
1a578e9b 12010 SetPort (w);
e0f712ba
AC
12011#endif
12012
12013 /* Clear window to avoid flicker. */
12014#if TARGET_API_MAC_CARBON
12015 {
12016 Rect r;
12017 BitMap bm;
177c0ea7 12018
e0f712ba
AC
12019 GetWindowPortBounds (w, &r);
12020 EraseRect (&r);
12021
12022 if (zoom_in_or_out == inZoomOut)
12023 {
12024 /* calculate height of window's title bar (hard card it for now). */
12025 w_title_height = 20 + GetMBarHeight ();
12026
12027 /* get maximum height of window into zoom_rect.bottom -
12028 zoom_rect.top */
12029 GetQDGlobalsScreenBits (&bm);
12030 zoom_rect = bm.bounds;
12031 zoom_rect.top += w_title_height;
12032 InsetRect (&zoom_rect, 8, 4); /* not too tight */
177c0ea7 12033
e0f712ba
AC
12034 zoom_rect.right = zoom_rect.left
12035 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12036
12037 SetWindowStandardState (w, &zoom_rect);
12038 }
12039 }
12040#else /* not TARGET_API_MAC_CARBON */
12041 EraseRect (&(w->portRect));
1a578e9b
AC
12042 if (zoom_in_or_out == inZoomOut)
12043 {
e0f712ba 12044 SetPt (&top_left, w->portRect.left, w->portRect.top);
1a578e9b
AC
12045 LocalToGlobal (&top_left);
12046
12047 /* calculate height of window's title bar */
12048 w_title_height = top_left.v - 1
e0f712ba 12049 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
1a578e9b
AC
12050
12051 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
12052 zoom_rect = qd.screenBits.bounds;
12053 zoom_rect.top += w_title_height;
12054 InsetRect (&zoom_rect, 8, 4); /* not too tight */
177c0ea7 12055
1a578e9b
AC
12056 zoom_rect.right = zoom_rect.left
12057 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12058
e0f712ba
AC
12059 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
12060 = zoom_rect;
1a578e9b 12061 }
e0f712ba 12062#endif /* not TARGET_API_MAC_CARBON */
1a578e9b 12063
e0f712ba 12064 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
1a578e9b
AC
12065
12066 /* retrieve window size and update application values */
e0f712ba
AC
12067#if TARGET_API_MAC_CARBON
12068 GetWindowPortBounds (w, &port_rect);
12069#else
1a578e9b 12070 port_rect = w->portRect;
e0f712ba 12071#endif
1a578e9b
AC
12072 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
12073 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
12074 x_set_window_size (mwp->mFP, 0, columns, rows);
12075
12076 SetPort (save_port);
12077}
12078
742fbed7
AC
12079/* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
12080static OSErr
12081init_mac_drag_n_drop ()
12082{
12083 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
12084 return result;
12085}
1a578e9b
AC
12086
12087/* Intialize AppleEvent dispatcher table for the required events. */
12088void
12089init_required_apple_events ()
12090{
12091 OSErr err;
12092 long result;
12093
12094 /* Make sure we have apple events before starting. */
12095 err = Gestalt (gestaltAppleEventsAttr, &result);
12096 if (err != noErr)
12097 abort ();
12098
12099 if (!(result & (1 << gestaltAppleEventsPresent)))
12100 abort ();
177c0ea7 12101
e0f712ba 12102#if TARGET_API_MAC_CARBON
1a578e9b 12103 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
e0f712ba
AC
12104 NewAEEventHandlerUPP
12105 ((AEEventHandlerProcPtr) do_ae_open_application),
1a578e9b 12106 0L, false);
e0f712ba
AC
12107#else
12108 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12109 NewAEEventHandlerProc
12110 ((AEEventHandlerProcPtr) do_ae_open_application),
12111 0L, false);
12112#endif
1a578e9b
AC
12113 if (err != noErr)
12114 abort ();
e0f712ba
AC
12115
12116#if TARGET_API_MAC_CARBON
12117 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12118 NewAEEventHandlerUPP
12119 ((AEEventHandlerProcPtr) do_ae_open_documents),
12120 0L, false);
12121#else
1a578e9b 12122 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
e0f712ba
AC
12123 NewAEEventHandlerProc
12124 ((AEEventHandlerProcPtr) do_ae_open_documents),
1a578e9b 12125 0L, false);
e0f712ba 12126#endif
1a578e9b
AC
12127 if (err != noErr)
12128 abort ();
12129
e0f712ba
AC
12130#if TARGET_API_MAC_CARBON
12131 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12132 NewAEEventHandlerUPP
12133 ((AEEventHandlerProcPtr) do_ae_print_documents),
12134 0L, false);
12135#else
1a578e9b 12136 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
e0f712ba
AC
12137 NewAEEventHandlerProc
12138 ((AEEventHandlerProcPtr) do_ae_print_documents),
1a578e9b 12139 0L, false);
e0f712ba 12140#endif
1a578e9b
AC
12141 if (err != noErr)
12142 abort ();
12143
e0f712ba
AC
12144#if TARGET_API_MAC_CARBON
12145 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12146 NewAEEventHandlerUPP
12147 ((AEEventHandlerProcPtr) do_ae_quit_application),
12148 0L, false);
12149#else
1a578e9b 12150 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
e0f712ba
AC
12151 NewAEEventHandlerProc
12152 ((AEEventHandlerProcPtr) do_ae_quit_application),
1a578e9b 12153 0L, false);
e0f712ba 12154#endif
1a578e9b
AC
12155 if (err != noErr)
12156 abort ();
12157}
12158
742fbed7
AC
12159#if USE_CARBON_EVENTS
12160
770136ad
RS
12161void
12162init_service_handler ()
742fbed7
AC
12163{
12164 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
12165 {kEventClassService, kEventServiceCopy},
12166 {kEventClassService, kEventServicePaste}};
12167 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
12168 3, specs, NULL, NULL);
12169}
12170
12171/*
12172 MAC_TODO: Check to see if this is called by AEProcessDesc...
12173 */
770136ad
RS
12174OSStatus
12175mac_handle_service_event (EventHandlerCallRef callRef,
12176 EventRef event, void *data)
742fbed7 12177{
177c0ea7 12178 OSStatus err = noErr;
742fbed7
AC
12179 switch (GetEventKind (event))
12180 {
177c0ea7 12181 case kEventServiceGetTypes:
742fbed7
AC
12182 {
12183 CFMutableArrayRef copyTypes, pasteTypes;
12184 CFStringRef type;
12185 Boolean selection = true;
12186 /*
12187 GetEventParameter(event, kEventParamServicePasteTypes,
12188 typeCFMutableArrayRef, NULL,
12189 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
12190 */
12191 GetEventParameter(event, kEventParamServiceCopyTypes,
12192 typeCFMutableArrayRef, NULL,
12193 sizeof (CFMutableArrayRef), NULL, &copyTypes);
12194 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
12195 if (type) {
12196 CFArrayAppendValue (copyTypes, type);
12197 //CFArrayAppendValue (pasteTypes, type);
12198 CFRelease (type);
12199 }
12200 }
12201 case kEventServiceCopy:
12202 {
12203 ScrapRef currentScrap, specificScrap;
12204 char * buf = "";
12205 Size byteCount = 0;
12206
12207 GetCurrentScrap (&currentScrap);
12208
12209 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
12210 if (err == noErr)
12211 {
12212 void *buffer = xmalloc (byteCount);
12213 if (buffer != NULL)
12214 {
12215 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
12216 sizeof (ScrapRef), NULL, &specificScrap);
177c0ea7 12217
742fbed7
AC
12218 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
12219 &byteCount, buffer);
12220 if (err == noErr)
12221 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
12222 kScrapFlavorMaskNone, byteCount, buffer);
12223 xfree (buffer);
177c0ea7 12224 }
742fbed7
AC
12225 }
12226 err = noErr;
12227 }
12228 case kEventServicePaste:
12229 {
12230 /*
12231 // Get the current location
12232 Size byteCount;
12233 ScrapRef specificScrap;
12234 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
12235 sizeof(ScrapRef), NULL, &specificScrap);
12236 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
12237 if (err == noErr) {
12238 void * buffer = xmalloc(byteCount);
12239 if (buffer != NULL ) {
177c0ea7 12240 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
742fbed7
AC
12241 &byteCount, buffer);
12242 if (err == noErr) {
12243 // Actually place in the buffer
12244 BLOCK_INPUT;
12245 // Get the current "selection" string here
12246 UNBLOCK_INPUT;
12247 }
12248 }
12249 xfree(buffer);
12250 }
12251 */
177c0ea7 12252 }
742fbed7
AC
12253 }
12254 return err;
12255}
12256#endif
1a578e9b
AC
12257
12258/* Open Application Apple Event */
12259static pascal OSErr
12260do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12261{
12262 return noErr;
12263}
12264
12265
12266/* Defined in mac.c. */
12267extern int
12268path_from_vol_dir_name (char *, int, short, long, char *);
12269
12270
12271/* Called when we receive an AppleEvent with an ID of
12272 "kAEOpenDocuments". This routine gets the direct parameter,
12273 extracts the FSSpecs in it, and puts their names on a list. */
177c0ea7 12274static pascal OSErr
1a578e9b
AC
12275do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12276{
12277 OSErr err, err2;
12278 AEDesc the_desc;
12279 AEKeyword keyword;
12280 DescType actual_type;
12281 Size actual_size;
12282
12283 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12284 if (err != noErr)
12285 goto descriptor_error_exit;
12286
12287 /* Check to see that we got all of the required parameters from the
12288 event descriptor. For an 'odoc' event this should just be the
12289 file list. */
177c0ea7 12290 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
1a578e9b
AC
12291 &actual_type, (Ptr) &keyword,
12292 sizeof (keyword), &actual_size);
12293 /* No error means that we found some unused parameters.
12294 errAEDescNotFound means that there are no more parameters. If we
12295 get an error code other than that, flag it. */
12296 if ((err == noErr) || (err != errAEDescNotFound))
12297 {
12298 err = errAEEventNotHandled;
12299 goto error_exit;
12300 }
12301 err = noErr;
12302
12303 /* Got all the parameters we need. Now, go through the direct
12304 object list and parse it up. */
12305 {
12306 long num_files_to_open;
12307
12308 err = AECountItems (&the_desc, &num_files_to_open);
12309 if (err == noErr)
12310 {
12311 int i;
177c0ea7 12312
1a578e9b 12313 /* AE file list is one based so just use that for indexing here. */
bc21bf11
AC
12314 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
12315 {
12316 FSSpec fs;
12317 Str255 path_name, unix_path_name;
12318#ifdef MAC_OSX
12319 FSRef fref;
12320#endif
12321
12322 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12323 (Ptr) &fs, sizeof (fs), &actual_size);
12324 if (err != noErr) break;
12325
12326#ifdef MAC_OSX
12327 err = FSpMakeFSRef (&fs, &fref);
12328 if (err != noErr) break;
12329
12330 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12331#else
12332 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12333 fs.name) &&
12334 mac_to_posix_pathname (path_name, unix_path_name, 255))
12335#endif
12336 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12337 drag_and_drop_file_list);
12338 }
1a578e9b
AC
12339 }
12340 }
12341
12342error_exit:
12343 /* Nuke the coerced file list in any case */
12344 err2 = AEDisposeDesc(&the_desc);
12345
12346descriptor_error_exit:
12347 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12348 return err;
12349}
12350
12351
770136ad
RS
12352static pascal OSErr
12353mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
12354 DragReference theDrag)
742fbed7
AC
12355{
12356 short items;
12357 short index;
12358 FlavorFlags theFlags;
12359 Point mouse;
12360 OSErr result;
12361 ItemReference theItem;
12362 HFSFlavor data;
12363 FSRef fref;
12364 Size size = sizeof (HFSFlavor);
12365
12366 drag_and_drop_file_list = Qnil;
12367 GetDragMouse (theDrag, &mouse, 0L);
12368 CountDragItems (theDrag, &items);
177c0ea7 12369 for (index = 1; index <= items; index++)
742fbed7
AC
12370 {
12371 /* Only handle file references. */
12372 GetDragItemReferenceNumber (theDrag, index, &theItem);
12373 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
12374 if (result == noErr)
12375 {
12376#ifdef MAC_OSX
12377 FSRef frref;
12378#else
12379 Str255 path_name;
12380#endif
12381 Str255 unix_path_name;
12382 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
12383#ifdef MAC_OSX
12384 /* Use Carbon routines, otherwise it converts the file name
12385 to /Macintosh HD/..., which is not correct. */
12386 FSpMakeFSRef (&data.fileSpec, &fref);
12387 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
12388#else
12389 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
12390 data.fileSpec.parID, data.fileSpec.name) &&
12391 mac_to_posix_pathname (path_name, unix_path_name, 255))
12392#endif
12393 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12394 drag_and_drop_file_list);
12395 }
12396 else
12397 return;
12398 }
12399 /* If there are items in the list, construct an event and post it to
12400 the queue like an interrupt using kbd_buffer_store_event. */
177c0ea7 12401 if (!NILP (drag_and_drop_file_list))
742fbed7
AC
12402 {
12403 struct input_event event;
12404 Lisp_Object frame;
12405 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
12406 SetPort (GetWindowPort (window));
12407 GlobalToLocal (&mouse);
12408
12409 event.kind = DRAG_N_DROP_EVENT;
12410 event.code = 0;
12411 event.modifiers = 0;
12412 event.timestamp = TickCount () * (1000 / 60);
12413 XSETINT (event.x, mouse.h);
12414 XSETINT (event.y, mouse.v);
12415 XSETFRAME (frame, f);
12416 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
12417 event.arg = Qnil;
12418 /* Post to the interrupt queue */
12419 kbd_buffer_store_event (&event);
12420 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
12421 {
12422 ProcessSerialNumber psn;
12423 GetCurrentProcess (&psn);
12424 SetFrontProcess (&psn);
12425 }
12426 }
12427}
12428
12429
1a578e9b
AC
12430/* Print Document Apple Event */
12431static pascal OSErr
12432do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12433{
12434 return errAEEventNotHandled;
12435}
12436
12437
12438static pascal OSErr
12439do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12440{
12441 /* FixMe: Do we need an unwind-protect or something here? And what
12442 do we do about unsaved files. Currently just forces quit rather
12443 than doing recursive callback to get user input. */
12444
12445 terminate_flag = true;
12446
12447 /* Fkill_emacs doesn't return. We have to return. (TI) */
12448 return noErr;
12449}
12450
12451
12452#if __profile__
12453void
12454profiler_exit_proc ()
12455{
12456 ProfilerDump ("\pEmacs.prof");
12457 ProfilerTerm ();
12458}
12459#endif
12460
12461/* These few functions implement Emacs as a normal Mac application
8c1cc9e8 12462 (almost): set up the heap and the Toolbox, handle necessary
1a578e9b
AC
12463 system events plus a few simple menu events. They also set up
12464 Emacs's access to functions defined in the rest of this file.
12465 Emacs uses function hooks to perform all its terminal I/O. A
12466 complete list of these functions appear in termhooks.h. For what
12467 they do, read the comments there and see also w32term.c and
12468 xterm.c. What's noticeably missing here is the event loop, which
12469 is normally present in most Mac application. After performing the
12470 necessary Mac initializations, main passes off control to
12471 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12472 mac_read_socket (defined further below) to read input. This is
12473 where WaitNextEvent is called to process Mac events. This is also
12474 where check_alarm in sysdep.c is called to simulate alarm signals.
12475 This makes the cursor jump back to its correct position after
12476 briefly jumping to that of the matching parenthesis, print useful
12477 hints and prompts in the minibuffer after the user stops typing for
12478 a wait, etc. */
12479
e0f712ba 12480#if !TARGET_API_MAC_CARBON
1a578e9b 12481#undef main
177c0ea7 12482int
1a578e9b
AC
12483main (void)
12484{
12485#if __profile__ /* is the profiler on? */
12486 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12487 exit(1);
12488#endif
12489
12490#if __MWERKS__
12491 /* set creator and type for files created by MSL */
12492 _fcreator = 'EMAx';
12493 _ftype = 'TEXT';
12494#endif
12495
12496 do_init_managers ();
177c0ea7 12497
1a578e9b 12498 do_get_menus ();
177c0ea7 12499
2e875e36
AC
12500 do_check_ram_size ();
12501
1a578e9b
AC
12502 init_emacs_passwd_dir ();
12503
12504 init_environ ();
12505
12506 initialize_applescript ();
12507
12508 init_required_apple_events ();
177c0ea7 12509
1a578e9b
AC
12510 {
12511 char **argv;
12512 int argc = 0;
12513
12514 /* set up argv array from STR# resource */
12515 get_string_list (&argv, ARGV_STRING_LIST_ID);
12516 while (argv[argc])
12517 argc++;
12518
12519 /* free up AppleScript resources on exit */
12520 atexit (terminate_applescript);
12521
12522#if __profile__ /* is the profiler on? */
12523 atexit (profiler_exit_proc);
12524#endif
12525
12526 /* 3rd param "envp" never used in emacs_main */
12527 (void) emacs_main (argc, argv, 0);
12528 }
12529
12530 /* Never reached - real exit in Fkill_emacs */
12531 return 0;
12532}
e0f712ba 12533#endif
1a578e9b
AC
12534
12535/* Table for translating Mac keycode to X keysym values. Contributed
12536 by Sudhir Shenoy. */
12537static unsigned char keycode_to_xkeysym_table[] = {
058c18c7
AC
12538 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12539 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12540 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12541
12542 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
12543 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
12544 /*0x38*/ 0, 0, 0, 0,
12545 /*0x3C*/ 0, 0, 0, 0,
12546
177c0ea7 12547 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
058c18c7
AC
12548 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
12549 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
12550 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
12551
12552 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
12553 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
12554 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
12555 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
12556
12557 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
177c0ea7
JB
12558 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
12559 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
058c18c7
AC
12560 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
12561
12562 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
12563 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
12564 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
12565 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
1a578e9b
AC
12566};
12567
12568static int
12569keycode_to_xkeysym (int keyCode, int *xKeySym)
12570{
12571 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12572 return *xKeySym != 0;
12573}
12574
12575/* Emacs calls this whenever it wants to read an input event from the
12576 user. */
12577int
12578XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12579{
177c0ea7 12580 int count = 0;
742fbed7
AC
12581#if USE_CARBON_EVENTS
12582 OSStatus rneResult;
12583 EventRef eventRef;
12584 EventMouseButton mouseBtn;
12585#endif
1a578e9b
AC
12586 EventRecord er;
12587 int the_modifiers;
12588 EventMask event_mask;
12589
e0f712ba 12590#if 0
1a578e9b
AC
12591 if (interrupt_input_blocked)
12592 {
12593 interrupt_input_pending = 1;
12594 return -1;
12595 }
e0f712ba 12596#endif
1a578e9b
AC
12597
12598 interrupt_input_pending = 0;
12599 BLOCK_INPUT;
12600
12601 /* So people can tell when we have read the available input. */
12602 input_signal_count++;
12603
12604 if (numchars <= 0)
12605 abort ();
12606
12607 /* Don't poll for events to process (specifically updateEvt) if
12608 window update currently already in progress. A call to redisplay
12609 (in do_window_update) can be preempted by another call to
12610 redisplay, causing blank regions to be left on the screen and the
12611 cursor to be left at strange places. */
12612 if (handling_window_update)
12613 {
12614 UNBLOCK_INPUT;
12615 return 0;
12616 }
12617
12618 if (terminate_flag)
12619 Fkill_emacs (make_number (1));
12620
12621 /* It is necessary to set this (additional) argument slot of an
12622 event to nil because keyboard.c protects incompletely processed
12623 event from being garbage collected by placing them in the
12624 kbd_buffer_gcpro vector. */
12625 bufp->arg = Qnil;
12626
12627 event_mask = everyEvent;
8f47302e 12628 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
1a578e9b
AC
12629 event_mask -= highLevelEventMask;
12630
742fbed7 12631#if USE_CARBON_EVENTS
177c0ea7 12632 rneResult = ReceiveNextEvent (0, NULL,
44fab9c1
AC
12633 expected
12634 ? TicksToEventTime (app_sleep_time)
12635 : 0,
6ef0a87e 12636 kEventRemoveFromQueue, &eventRef);
742fbed7
AC
12637 if (!rneResult)
12638 {
12639 /* Handle new events */
177c0ea7
JB
12640 if (!mac_convert_event_ref (eventRef, &er))
12641 switch (GetEventClass (eventRef))
742fbed7
AC
12642 {
12643 case kEventClassMouse:
177c0ea7 12644 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
742fbed7
AC
12645 {
12646 SInt32 delta;
12647 Point point;
5883787c 12648 WindowPtr window_ptr = FrontNonFloatingWindow ();
742fbed7 12649 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
539e69a9
ST
12650 if (!IsValidWindowPtr (window_ptr))
12651 {
12652 SysBeep(1);
12653 UNBLOCK_INPUT;
12654 return 0;
12655 }
12656
742fbed7
AC
12657 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
12658 typeSInt32, NULL, sizeof (SInt32),
12659 NULL, &delta);
12660 GetEventParameter(eventRef, kEventParamMouseLocation,
12661 typeQDPoint, NULL, sizeof (Point),
12662 NULL, &point);
12663 bufp->kind = MOUSE_WHEEL_EVENT;
12664 bufp->code = delta;
12665 bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
12666 SetPort (GetWindowPort (window_ptr));
12667 GlobalToLocal (&point);
12668 XSETINT (bufp->x, point.h);
12669 XSETINT (bufp->y, point.v);
12670 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12671 bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
12672 count++;
12673 }
177c0ea7 12674 else
742fbed7
AC
12675 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12676
12677 break;
12678 default:
12679 /* Send the event to the appropriate receiver. */
12680 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12681 }
12682 else
12683#else
c7764932 12684 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
742fbed7 12685#endif /* USE_CARBON_EVENTS */
1a578e9b
AC
12686 switch (er.what)
12687 {
12688 case mouseDown:
12689 case mouseUp:
12690 {
12691 WindowPtr window_ptr = FrontWindow ();
12692 SInt16 part_code;
12693
742fbed7 12694#if USE_CARBON_EVENTS
5883787c
AC
12695 /* This is needed to send mouse events like aqua window buttons
12696 to the correct handler. */
12697 if (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
12698 break;
12699 }
12700
12701 if (!is_emacs_window(window_ptr))
12702 break;
742fbed7
AC
12703#endif
12704
1a578e9b
AC
12705 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12706 && er.what == mouseUp)
12707 {
12708 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12709 Point mouse_loc = er.where;
177c0ea7 12710
1a578e9b 12711 /* Convert to local coordinates of new window. */
e0f712ba
AC
12712#if TARGET_API_MAC_CARBON
12713 SetPort (GetWindowPort (window_ptr));
12714#else
12715 SetPort (window_ptr);
12716#endif
12717
1a578e9b 12718 GlobalToLocal (&mouse_loc);
177c0ea7 12719
742fbed7
AC
12720#if USE_CARBON_EVENTS
12721 bufp->code = mac_get_mouse_btn (eventRef);
12722#else
1a578e9b 12723 bufp->code = 0; /* only one mouse button */
742fbed7 12724#endif
3b8f9651 12725 bufp->kind = SCROLL_BAR_CLICK_EVENT;
1a578e9b
AC
12726 bufp->frame_or_window = tracked_scroll_bar->window;
12727 bufp->part = scroll_bar_handle;
742fbed7
AC
12728#if USE_CARBON_EVENTS
12729 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12730#else
12731 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12732#endif
12733 bufp->modifiers |= up_modifier;
1a578e9b
AC
12734 bufp->timestamp = er.when * (1000 / 60);
12735 /* ticks to milliseconds */
12736
12737 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12738 XSETINT (bufp->y, mouse_loc.v - 24);
177c0ea7 12739 tracked_scroll_bar->dragging = Qnil;
1a578e9b
AC
12740 mouse_tracking_in_progress = mouse_tracking_none;
12741 tracked_scroll_bar = NULL;
12742 count++;
12743 break;
12744 }
12745
12746 part_code = FindWindow (er.where, &window_ptr);
177c0ea7 12747
1a578e9b
AC
12748 switch (part_code)
12749 {
12750 case inMenuBar:
12751 {
12752 struct frame *f = ((mac_output *)
12753 GetWRefCon (FrontWindow ()))->mFP;
12754 saved_menu_event_location = er.where;
3b8f9651 12755 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
1a578e9b
AC
12756 XSETFRAME (bufp->frame_or_window, f);
12757 count++;
12758 }
12759 break;
12760
12761 case inContent:
12762 if (window_ptr != FrontWindow ())
12763 SelectWindow (window_ptr);
12764 else
12765 {
e0f712ba 12766 SInt16 control_part_code;
1a578e9b
AC
12767 ControlHandle ch;
12768 struct mac_output *mwp = (mac_output *)
12769 GetWRefCon (window_ptr);
12770 Point mouse_loc = er.where;
177c0ea7 12771
1a578e9b 12772 /* convert to local coordinates of new window */
e0f712ba
AC
12773#if TARGET_API_MAC_CARBON
12774 SetPort (GetWindowPort (window_ptr));
12775#else
12776 SetPort (window_ptr);
12777#endif
12778
1a578e9b 12779 GlobalToLocal (&mouse_loc);
e0f712ba
AC
12780#if TARGET_API_MAC_CARBON
12781 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12782 &control_part_code);
12783#else
1a578e9b 12784 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
177c0ea7 12785#endif
742fbed7
AC
12786
12787#if USE_CARBON_EVENTS
12788 bufp->code = mac_get_mouse_btn (eventRef);
177c0ea7 12789#else
1a578e9b 12790 bufp->code = 0; /* only one mouse button */
742fbed7 12791#endif
1a578e9b
AC
12792 XSETINT (bufp->x, mouse_loc.h);
12793 XSETINT (bufp->y, mouse_loc.v);
12794 bufp->timestamp = er.when * (1000 / 60);
12795 /* ticks to milliseconds */
e0f712ba 12796
177c0ea7 12797#if TARGET_API_MAC_CARBON
e0f712ba
AC
12798 if (ch != 0)
12799#else
1a578e9b 12800 if (control_part_code != 0)
e0f712ba 12801#endif
1a578e9b
AC
12802 {
12803 struct scroll_bar *bar = (struct scroll_bar *)
12804 GetControlReference (ch);
12805 x_scroll_bar_handle_click (bar, control_part_code, &er,
12806 bufp);
12807 if (er.what == mouseDown
12808 && control_part_code == kControlIndicatorPart)
12809 {
e0f712ba
AC
12810 mouse_tracking_in_progress
12811 = mouse_tracking_scroll_bar;
1a578e9b
AC
12812 tracked_scroll_bar = bar;
12813 }
12814 else
12815 {
12816 mouse_tracking_in_progress = mouse_tracking_none;
12817 tracked_scroll_bar = NULL;
12818 }
12819 }
12820 else
12821 {
3b8f9651 12822 bufp->kind = MOUSE_CLICK_EVENT;
1a578e9b
AC
12823 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12824 if (er.what == mouseDown)
e0f712ba
AC
12825 mouse_tracking_in_progress
12826 = mouse_tracking_mouse_movement;
1a578e9b 12827 else
e0f712ba 12828 mouse_tracking_in_progress = mouse_tracking_none;
1a578e9b 12829 }
177c0ea7 12830
742fbed7
AC
12831#if USE_CARBON_EVENTS
12832 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12833#else
12834 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12835#endif
12836
1a578e9b
AC
12837 switch (er.what)
12838 {
12839 case mouseDown:
742fbed7 12840 bufp->modifiers |= down_modifier;
1a578e9b
AC
12841 break;
12842 case mouseUp:
742fbed7 12843 bufp->modifiers |= up_modifier;
1a578e9b
AC
12844 break;
12845 }
177c0ea7 12846
1a578e9b
AC
12847 count++;
12848 }
12849 break;
12850
12851 case inDrag:
e0f712ba
AC
12852#if TARGET_API_MAC_CARBON
12853 {
12854 BitMap bm;
177c0ea7 12855
e0f712ba
AC
12856 GetQDGlobalsScreenBits (&bm);
12857 DragWindow (window_ptr, er.where, &bm.bounds);
12858 }
12859#else /* not TARGET_API_MAC_CARBON */
1a578e9b 12860 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
e0f712ba 12861#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
12862 break;
12863
12864 case inGoAway:
12865 if (TrackGoAway (window_ptr, er.where))
12866 {
3b8f9651 12867 bufp->kind = DELETE_WINDOW_EVENT;
1a578e9b
AC
12868 XSETFRAME (bufp->frame_or_window,
12869 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12870 count++;
12871 }
12872 break;
12873
12874 /* window resize handling added --ben */
12875 case inGrow:
12876 do_grow_window(window_ptr, &er);
12877 break;
177c0ea7 12878
1a578e9b
AC
12879 /* window zoom handling added --ben */
12880 case inZoomIn:
12881 case inZoomOut:
12882 if (TrackBox (window_ptr, er.where, part_code))
12883 do_zoom_window (window_ptr, part_code);
12884 break;
12885
12886 default:
12887 break;
12888 }
12889 }
12890 break;
177c0ea7 12891
1a578e9b
AC
12892 case updateEvt:
12893 case osEvt:
12894 case activateEvt:
742fbed7 12895#if USE_CARBON_EVENTS
5883787c 12896 if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
177c0ea7 12897#endif
1a578e9b
AC
12898 do_events (&er);
12899 break;
177c0ea7 12900
1a578e9b
AC
12901 case keyDown:
12902 case autoKey:
12903 {
12904 int keycode = (er.message & keyCodeMask) >> 8;
12905 int xkeysym;
177c0ea7 12906
5883787c
AC
12907#if USE_CARBON_EVENTS
12908 /* When using Carbon Events, we need to pass raw keyboard events
12909 to the TSM ourselves. If TSM handles it, it will pass back
12910 noErr, otherwise it will pass back "eventNotHandledErr" and
12911 we can process it normally. */
12912 if ((!NILP (Vmac_pass_command_to_system)
12913 || !(er.modifiers & cmdKey))
12914 && (!NILP (Vmac_pass_control_to_system)
12915 || !(er.modifiers & controlKey)))
12916 {
12917 OSStatus err;
12918 err = SendEventToEventTarget (eventRef,
12919 GetEventDispatcherTarget ());
12920 if (err != eventNotHandledErr)
12921 break;
12922 }
12923#endif
177c0ea7 12924
44fab9c1
AC
12925 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
12926 {
12927 SysBeep (1);
12928 UNBLOCK_INPUT;
12929 return 0;
12930 }
177c0ea7 12931
1a578e9b 12932 ObscureCursor ();
177c0ea7 12933
058c18c7 12934 if (keycode_to_xkeysym (keycode, &xkeysym))
1a578e9b
AC
12935 {
12936 bufp->code = 0xff00 | xkeysym;
3b8f9651 12937 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
177c0ea7 12938 }
1a578e9b
AC
12939 else
12940 {
177c0ea7
JB
12941 if (er.modifiers & (controlKey |
12942 (NILP (Vmac_command_key_is_meta) ? optionKey
402e4f8b 12943 : cmdKey)))
6ef0a87e
ST
12944 {
12945 /* This code comes from Keyboard Resource, Appendix
1a578e9b
AC
12946 C of IM - Text. This is necessary since shift is
12947 ignored in KCHR table translation when option or
177c0ea7 12948 command is pressed. It also does not translate
402e4f8b
ST
12949 correctly control-shift chars like C-% so mask off
12950 shift here also */
12951 int new_modifiers = er.modifiers & 0xe600;
6ef0a87e
ST
12952 /* mask off option and command */
12953 int new_keycode = keycode | new_modifiers;
12954 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12955 unsigned long some_state = 0;
12956 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
1a578e9b 12957 &some_state) & 0xff;
6ef0a87e 12958 }
1a578e9b 12959 else
6ef0a87e 12960 bufp->code = er.message & charCodeMask;
3b8f9651 12961 bufp->kind = ASCII_KEYSTROKE_EVENT;
1a578e9b
AC
12962 }
12963 }
177c0ea7 12964
6ef0a87e
ST
12965 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12966 convert non-ASCII characters typed at the Mac keyboard
12967 (presumed to be in the Mac Roman encoding) to iso-latin-1
12968 encoding before they are passed to Emacs. This enables the
12969 Mac keyboard to be used to enter non-ASCII iso-latin-1
12970 characters directly. */
12971 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
3b8f9651 12972 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
1a578e9b 12973 {
6ef0a87e
ST
12974 static TECObjectRef converter = NULL;
12975 OSStatus the_err = noErr;
12976 OSStatus convert_status = noErr;
177c0ea7 12977
6ef0a87e
ST
12978 if (converter == NULL)
12979 {
12980 the_err = TECCreateConverter (&converter,
1a578e9b
AC
12981 kTextEncodingMacRoman,
12982 mac_keyboard_text_encoding);
6ef0a87e 12983 current_mac_keyboard_text_encoding
e0f712ba 12984 = mac_keyboard_text_encoding;
6ef0a87e
ST
12985 }
12986 else if (mac_keyboard_text_encoding
e0f712ba 12987 != current_mac_keyboard_text_encoding)
6ef0a87e
ST
12988 {
12989 /* Free the converter for the current encoding before
12990 creating a new one. */
12991 TECDisposeConverter (converter);
12992 the_err = TECCreateConverter (&converter,
1a578e9b
AC
12993 kTextEncodingMacRoman,
12994 mac_keyboard_text_encoding);
6ef0a87e 12995 current_mac_keyboard_text_encoding
e0f712ba 12996 = mac_keyboard_text_encoding;
177c0ea7
JB
12997 }
12998
6ef0a87e
ST
12999 if (the_err == noErr)
13000 {
13001 unsigned char ch = bufp->code;
13002 ByteCount actual_input_length, actual_output_length;
13003 unsigned char outch;
177c0ea7 13004
6ef0a87e 13005 convert_status = TECConvertText (converter, &ch, 1,
1a578e9b 13006 &actual_input_length,
6ef0a87e 13007 &outch, 1,
1a578e9b 13008 &actual_output_length);
6ef0a87e 13009 if (convert_status == noErr
1a578e9b
AC
13010 && actual_input_length == 1
13011 && actual_output_length == 1)
6ef0a87e
ST
13012 bufp->code = outch;
13013 }
1a578e9b 13014 }
177c0ea7 13015
742fbed7
AC
13016#if USE_CARBON_EVENTS
13017 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13018#else
13019 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13020#endif
177c0ea7 13021
1a578e9b 13022 {
b6cce0b7
AC
13023 mac_output *mwp
13024 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
1a578e9b
AC
13025 XSETFRAME (bufp->frame_or_window, mwp->mFP);
13026 }
177c0ea7 13027
1a578e9b
AC
13028 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
13029
13030 count++;
13031 break;
13032
13033 case kHighLevelEvent:
13034 drag_and_drop_file_list = Qnil;
8f47302e 13035
1a578e9b 13036 AEProcessAppleEvent(&er);
177c0ea7 13037
3b8f9651 13038 /* Build a DRAG_N_DROP_EVENT type event as is done in
1a578e9b
AC
13039 constuct_drag_n_drop in w32term.c. */
13040 if (!NILP (drag_and_drop_file_list))
13041 {
5883787c 13042 struct frame *f = NULL;
1a578e9b
AC
13043 WindowPtr wp;
13044 Lisp_Object frame;
13045
5883787c 13046 wp = FrontNonFloatingWindow ();
177c0ea7 13047
72742a99
AC
13048 if (!wp)
13049 {
13050 struct frame *f = XFRAME (XCAR (Vframe_list));
13051 CollapseWindow (FRAME_MAC_WINDOW (f), false);
13052 wp = FrontNonFloatingWindow ();
13053 }
13054
5883787c 13055 if (wp && is_emacs_window(wp))
177c0ea7 13056 f = ((mac_output *) GetWRefCon (wp))->mFP;
5883787c 13057
3b8f9651 13058 bufp->kind = DRAG_N_DROP_EVENT;
1a578e9b
AC
13059 bufp->code = 0;
13060 bufp->timestamp = er.when * (1000 / 60);
13061 /* ticks to milliseconds */
742fbed7
AC
13062#if USE_CARBON_EVENTS
13063 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13064#else
13065 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13066#endif
1a578e9b
AC
13067
13068 XSETINT (bufp->x, 0);
13069 XSETINT (bufp->y, 0);
13070
13071 XSETFRAME (frame, f);
13072 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
13073
13074 /* Regardless of whether Emacs was suspended or in the
13075 foreground, ask it to redraw its entire screen.
13076 Otherwise parts of the screen can be left in an
13077 inconsistent state. */
13078 if (wp)
e0f712ba
AC
13079#if TARGET_API_MAC_CARBON
13080 {
13081 Rect r;
177c0ea7 13082
e0f712ba
AC
13083 GetWindowPortBounds (wp, &r);
13084 InvalWindowRect (wp, &r);
13085 }
13086#else /* not TARGET_API_MAC_CARBON */
1a578e9b 13087 InvalRect (&(wp->portRect));
e0f712ba 13088#endif /* not TARGET_API_MAC_CARBON */
177c0ea7 13089
1a578e9b
AC
13090 count++;
13091 }
1a578e9b
AC
13092 default:
13093 break;
13094 }
742fbed7
AC
13095#if USE_CARBON_EVENTS
13096 ReleaseEvent (eventRef);
13097 }
13098#endif
1a578e9b
AC
13099
13100 /* If the focus was just given to an autoraising frame,
13101 raise it now. */
13102 /* ??? This ought to be able to handle more than one such frame. */
13103 if (pending_autoraise_frame)
13104 {
13105 x_raise_frame (pending_autoraise_frame);
13106 pending_autoraise_frame = 0;
13107 }
13108
e0f712ba 13109#if !TARGET_API_MAC_CARBON
1a578e9b 13110 check_alarm (); /* simulate the handling of a SIGALRM */
e0f712ba 13111#endif
1a578e9b
AC
13112
13113 {
13114 static Point old_mouse_pos = { -1, -1 };
177c0ea7 13115
1a578e9b
AC
13116 if (app_is_suspended)
13117 {
13118 old_mouse_pos.h = -1;
13119 old_mouse_pos.v = -1;
13120 }
13121 else
13122 {
13123 Point mouse_pos;
e0f712ba
AC
13124 WindowPtr wp;
13125 struct frame *f;
1a578e9b 13126 Lisp_Object bar;
177c0ea7 13127 struct scroll_bar *sb;
1a578e9b 13128
e0f712ba
AC
13129 wp = FrontWindow ();
13130 if (is_emacs_window (wp))
13131 {
13132 f = ((mac_output *) GetWRefCon (wp))->mFP;
1a578e9b 13133
e0f712ba
AC
13134#if TARGET_API_MAC_CARBON
13135 SetPort (GetWindowPort (wp));
13136#else
13137 SetPort (wp);
13138#endif
13139
13140 GetMouse (&mouse_pos);
13141
13142 if (!EqualPt (mouse_pos, old_mouse_pos))
13143 {
13144 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
13145 && tracked_scroll_bar)
13146 x_scroll_bar_note_movement (tracked_scroll_bar,
13147 mouse_pos.v
13148 - XINT (tracked_scroll_bar->top),
13149 TickCount() * (1000 / 60));
13150 else
13151 note_mouse_movement (f, &mouse_pos);
177c0ea7
JB
13152
13153 old_mouse_pos = mouse_pos;
e0f712ba
AC
13154 }
13155 }
1a578e9b
AC
13156 }
13157 }
177c0ea7 13158
1a578e9b 13159 UNBLOCK_INPUT;
177c0ea7 13160
1a578e9b
AC
13161 return count;
13162}
13163
13164
13165/* Need to override CodeWarrior's input function so no conversion is
13166 done on newlines Otherwise compiled functions in .elc files will be
13167 read incorrectly. Defined in ...:MSL C:MSL
13168 Common:Source:buffer_io.c. */
13169#ifdef __MWERKS__
13170void
13171__convert_to_newlines (unsigned char * p, size_t * n)
13172{
13173#pragma unused(p,n)
13174}
13175
13176void
13177__convert_from_newlines (unsigned char * p, size_t * n)
13178{
13179#pragma unused(p,n)
13180}
13181#endif
13182
13183
13184/* Initialize the struct pointed to by MW to represent a new COLS x
13185 ROWS Macintosh window, using font with name FONTNAME and size
13186 FONTSIZE. */
13187void
13188NewMacWindow (FRAME_PTR fp)
13189{
13190 mac_output *mwp;
e0f712ba
AC
13191#if TARGET_API_MAC_CARBON
13192 static int making_terminal_window = 0;
13193#else
1a578e9b 13194 static int making_terminal_window = 1;
e0f712ba 13195#endif
1a578e9b
AC
13196
13197 mwp = fp->output_data.mac;
13198
13199 if (making_terminal_window)
13200 {
13201 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
13202 (WindowPtr) -1)))
13203 abort ();
13204 making_terminal_window = 0;
13205 }
13206 else
13207 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
13208 abort ();
177c0ea7 13209
1a578e9b
AC
13210 SetWRefCon (mwp->mWP, (long) mwp);
13211 /* so that update events can find this mac_output struct */
13212 mwp->mFP = fp; /* point back to emacs frame */
13213
e0f712ba
AC
13214#if TARGET_API_MAC_CARBON
13215 SetPort (GetWindowPort (mwp->mWP));
13216#else
1a578e9b 13217 SetPort (mwp->mWP);
e0f712ba 13218#endif
1a578e9b
AC
13219
13220 mwp->fontset = -1;
177c0ea7 13221
1a578e9b
AC
13222 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
13223 ShowWindow (mwp->mWP);
177c0ea7 13224
1a578e9b
AC
13225}
13226
13227
770136ad
RS
13228void
13229make_mac_frame (struct frame *f)
1a578e9b
AC
13230{
13231 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
13232 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
668e2d32
KS
13233
13234 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
177c0ea7 13235
1a578e9b 13236 NewMacWindow(f);
1a578e9b
AC
13237
13238 f->output_data.mac->cursor_pixel = 0;
13239 f->output_data.mac->border_pixel = 0x00ff00;
13240 f->output_data.mac->mouse_pixel = 0xff00ff;
13241 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
13242
1a578e9b
AC
13243 f->output_data.mac->fontset = -1;
13244 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13245 f->output_data.mac->scroll_bar_background_pixel = -1;
13246 f->output_data.mac->left_pos = 4;
13247 f->output_data.mac->top_pos = 4;
13248 f->output_data.mac->border_width = 0;
13249 f->output_data.mac->explicit_parent = 0;
177c0ea7 13250
1a578e9b
AC
13251 f->output_data.mac->internal_border_width = 0;
13252
13253 f->output_method = output_mac;
13254
13255 f->auto_raise = 1;
13256 f->auto_lower = 1;
177c0ea7 13257
1a578e9b
AC
13258 f->new_width = 0;
13259 f->new_height = 0;
13260}
13261
770136ad
RS
13262void
13263make_mac_terminal_frame (struct frame *f)
1a578e9b
AC
13264{
13265 Lisp_Object frame;
13266
13267 XSETFRAME (frame, f);
13268
13269 f->output_method = output_mac;
13270 f->output_data.mac = (struct mac_output *)
13271 xmalloc (sizeof (struct mac_output));
13272 bzero (f->output_data.mac, sizeof (struct mac_output));
13273 f->output_data.mac->fontset = -1;
13274 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13275 f->output_data.mac->scroll_bar_background_pixel = -1;
177c0ea7 13276
1a578e9b
AC
13277 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
13278
13279 f->width = 96;
13280 f->height = 4;
13281
13282 make_mac_frame (f);
e0f712ba
AC
13283
13284 x_make_gc (f);
177c0ea7 13285
e0f712ba
AC
13286 /* Need to be initialized for unshow_buffer in window.c. */
13287 selected_window = f->selected_window;
13288
1a578e9b
AC
13289 Fmodify_frame_parameters (frame,
13290 Fcons (Fcons (Qfont,
13291 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
13292 Fmodify_frame_parameters (frame,
13293 Fcons (Fcons (Qforeground_color,
13294 build_string ("black")), Qnil));
13295 Fmodify_frame_parameters (frame,
13296 Fcons (Fcons (Qbackground_color,
13297 build_string ("white")), Qnil));
13298}
13299
e0f712ba
AC
13300\f
13301/***********************************************************************
13302 Initialization
13303 ***********************************************************************/
13304
13305#ifdef USE_X_TOOLKIT
13306static XrmOptionDescRec emacs_options[] = {
13307 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13308 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13309
13310 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13311 XrmoptionSepArg, NULL},
13312 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13313
13314 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13315 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13316 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13317 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13318 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13319 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13320 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13321};
13322#endif /* USE_X_TOOLKIT */
13323
13324#ifdef MULTI_KBOARD
13325/* Test whether two display-name strings agree up to the dot that separates
13326 the screen number from the server number. */
13327static int
13328same_x_server (name1, name2)
13329 char *name1, *name2;
13330{
13331 int seen_colon = 0;
d5db4077 13332 unsigned char *system_name = SDATA (Vsystem_name);
e0f712ba
AC
13333 int system_name_length = strlen (system_name);
13334 int length_until_period = 0;
13335
13336 while (system_name[length_until_period] != 0
13337 && system_name[length_until_period] != '.')
13338 length_until_period++;
13339
13340 /* Treat `unix' like an empty host name. */
13341 if (! strncmp (name1, "unix:", 5))
13342 name1 += 4;
13343 if (! strncmp (name2, "unix:", 5))
13344 name2 += 4;
13345 /* Treat this host's name like an empty host name. */
13346 if (! strncmp (name1, system_name, system_name_length)
13347 && name1[system_name_length] == ':')
13348 name1 += system_name_length;
13349 if (! strncmp (name2, system_name, system_name_length)
13350 && name2[system_name_length] == ':')
13351 name2 += system_name_length;
13352 /* Treat this host's domainless name like an empty host name. */
13353 if (! strncmp (name1, system_name, length_until_period)
13354 && name1[length_until_period] == ':')
13355 name1 += length_until_period;
13356 if (! strncmp (name2, system_name, length_until_period)
13357 && name2[length_until_period] == ':')
13358 name2 += length_until_period;
13359
13360 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13361 {
13362 if (*name1 == ':')
13363 seen_colon++;
13364 if (seen_colon && *name1 == '.')
13365 return 1;
13366 }
13367 return (seen_colon
13368 && (*name1 == '.' || *name1 == '\0')
13369 && (*name2 == '.' || *name2 == '\0'));
13370}
13371#endif
13372
13373int mac_initialized = 0;
13374
1a578e9b
AC
13375void
13376mac_initialize_display_info ()
13377{
13378 struct mac_display_info *dpyinfo = &one_mac_display_info;
13379 GDHandle main_device_handle;
13380
13381 bzero (dpyinfo, sizeof (*dpyinfo));
13382
13383 /* Put it on x_display_name_list. */
13384 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13385 x_display_name_list);
13386 dpyinfo->name_list_element = XCAR (x_display_name_list);
177c0ea7 13387
e0f712ba
AC
13388#if 0
13389 dpyinfo->mac_id_name
d5db4077
KR
13390 = (char *) xmalloc (SCHARS (Vinvocation_name)
13391 + SCHARS (Vsystem_name)
e0f712ba
AC
13392 + 2);
13393 sprintf (dpyinfo->mac_id_name, "%s@%s",
d5db4077 13394 SDATA (Vinvocation_name), SDATA (Vsystem_name));
e0f712ba
AC
13395#else
13396 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13397 strcpy (dpyinfo->mac_id_name, "Mac Display");
13398#endif
13399
1a578e9b
AC
13400 main_device_handle = LMGetMainDevice();
13401
13402 dpyinfo->reference_count = 0;
13403 dpyinfo->resx = 75.0;
13404 dpyinfo->resy = 75.0;
13405 dpyinfo->n_planes = 1;
13406 dpyinfo->n_cbits = 16;
13407 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13408 dpyinfo->width = (**main_device_handle).gdRect.right;
13409 dpyinfo->grabbed = 0;
13410 dpyinfo->root_window = NULL;
13411
13412 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13413 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13414 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13415 dpyinfo->mouse_face_window = Qnil;
e0f712ba
AC
13416}
13417
13418struct mac_display_info *
13419mac_term_init (display_name, xrm_option, resource_name)
13420 Lisp_Object display_name;
13421 char *xrm_option;
13422 char *resource_name;
13423{
13424 struct mac_display_info *dpyinfo;
13425 GDHandle main_device_handle;
13426
13427 if (!mac_initialized)
13428 {
13429 mac_initialize ();
13430 mac_initialized = 1;
13431 }
13432
13433 mac_initialize_display_info (display_name);
13434
13435 dpyinfo = &one_mac_display_info;
13436
13437 main_device_handle = LMGetMainDevice();
13438
13439 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13440 dpyinfo->width = (**main_device_handle).gdRect.right;
1a578e9b 13441
e0f712ba 13442 return dpyinfo;
1a578e9b 13443}
e0f712ba 13444\f
8030369c 13445#ifdef MAC_OSX
6ef0a87e
ST
13446void
13447mac_check_bundle()
13448{
13449 extern int inhibit_window_system;
13450 extern int noninteractive;
13451 CFBundleRef appsBundle;
13452 pid_t child;
13453
13454 /* No need to test if already -nw*/
13455 if (inhibit_window_system || noninteractive)
13456 return;
13457
13458 appsBundle = CFBundleGetMainBundle();
13459 if (appsBundle != NULL)
13460 {
13461 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
13462 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
13463 /* We found the bundle identifier, now we know we are valid. */
13464 if (res != NULL)
13465 {
13466 CFRelease(res);
13467 return;
13468 }
13469 }
13470 /* MAC_TODO: Have this start the bundled executable */
13471
13472 /* For now, prevent the fatal error by bringing it up in the terminal */
13473 inhibit_window_system = 1;
13474}
13475
770136ad
RS
13476void
13477MakeMeTheFrontProcess ()
8030369c
AC
13478{
13479 ProcessSerialNumber psn;
13480 OSErr err;
177c0ea7 13481
8030369c
AC
13482 err = GetCurrentProcess (&psn);
13483 if (err == noErr)
13484 (void) SetFrontProcess (&psn);
13485}
6ef0a87e
ST
13486
13487/***** Code to handle C-g testing *****/
13488
13489/* Contains the Mac modifier formed from quit_char */
13490static mac_quit_char_modifiers = 0;
13491static mac_quit_char_keycode;
13492extern int quit_char;
13493
13494static void
13495mac_determine_quit_char_modifiers()
13496{
13497 /* Todo: Determine modifiers from quit_char. */
13498 UInt32 qc_modifiers = ctrl_modifier;
13499
13500 /* Map modifiers */
13501 mac_quit_char_modifiers = 0;
13502 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
13503 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
13504 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
13505 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
13506}
13507
13508static void
13509init_quit_char_handler ()
13510{
13511 /* TODO: Let this support keys other the 'g' */
13512 mac_quit_char_keycode = 5;
13513 /* Look at <architecture/adb_kb_map.h> for details */
13514 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
177c0ea7 13515
6ef0a87e
ST
13516 mac_determine_quit_char_modifiers();
13517}
13518
13519static Boolean
13520quit_char_comp (EventRef inEvent, void *inCompData)
13521{
13522 if (GetEventClass(inEvent) != kEventClassKeyboard)
13523 return false;
13524 if (GetEventKind(inEvent) != kEventRawKeyDown)
13525 return false;
13526 {
13527 UInt32 keyCode;
13528 UInt32 keyModifiers;
177c0ea7 13529 GetEventParameter(inEvent, kEventParamKeyCode,
6ef0a87e
ST
13530 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
13531 if (keyCode != mac_quit_char_keycode)
13532 return false;
177c0ea7 13533 GetEventParameter(inEvent, kEventParamKeyModifiers,
6ef0a87e
ST
13534 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
13535 if (keyModifiers != mac_quit_char_modifiers)
13536 return false;
13537 }
13538 return true;
13539}
13540
13541void
13542mac_check_for_quit_char()
13543{
13544 EventRef event;
13545 /* If windows are not initialized, return immediately (keep it bouncin')*/
13546 if (!mac_quit_char_modifiers)
13547 return;
13548
13549 /* Redetermine modifiers because they are based on lisp variables */
13550 mac_determine_quit_char_modifiers();
13551
13552 /* Fill the queue with events */
13553 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
13554 event = FindSpecificEventInQueue (GetMainEventQueue(), quit_char_comp, NULL);
177c0ea7 13555 if (event)
6ef0a87e
ST
13556 {
13557 struct input_event e;
13558 struct mac_output *mwp = (mac_output*) GetWRefCon (FrontNonFloatingWindow ());
13559 /* Use an input_event to emulate what the interrupt handler does. */
13560 e.kind = ASCII_KEYSTROKE_EVENT;
13561 e.code = quit_char;
96720f09
ST
13562 e.arg = NULL;
13563 e.modifiers = NULL;
6ef0a87e
ST
13564 e.timestamp = EventTimeToTicks(GetEventTime(event))*(1000/60);
13565 XSETFRAME(e.frame_or_window, mwp->mFP);
13566 /* Remove event from queue to prevent looping. */
13567 RemoveEventFromQueue(GetMainEventQueue(), event);
13568 ReleaseEvent(event);
13569 kbd_buffer_store_event(&e);
13570 }
13571}
13572
8030369c
AC
13573#endif /* MAC_OSX */
13574
e0f712ba
AC
13575/* Set up use of X before we make the first connection. */
13576
13577static struct redisplay_interface x_redisplay_interface =
13578{
13579 x_produce_glyphs,
13580 x_write_glyphs,
13581 x_insert_glyphs,
13582 x_clear_end_of_line,
13583 x_scroll_run,
13584 x_after_update_window_line,
13585 x_update_window_begin,
13586 x_update_window_end,
13587 XTcursor_to,
13588 x_flush,
13589 x_clear_mouse_face,
13590 x_get_glyph_overhangs,
13591 x_fix_overlapping_area
13592};
1a578e9b
AC
13593
13594void
e0f712ba 13595mac_initialize ()
1a578e9b
AC
13596{
13597 rif = &x_redisplay_interface;
13598
13599 clear_frame_hook = x_clear_frame;
13600 ins_del_lines_hook = x_ins_del_lines;
1a578e9b
AC
13601 delete_glyphs_hook = x_delete_glyphs;
13602 ring_bell_hook = XTring_bell;
13603 reset_terminal_modes_hook = XTreset_terminal_modes;
13604 set_terminal_modes_hook = XTset_terminal_modes;
13605 update_begin_hook = x_update_begin;
13606 update_end_hook = x_update_end;
13607 set_terminal_window_hook = XTset_terminal_window;
13608 read_socket_hook = XTread_socket;
13609 frame_up_to_date_hook = XTframe_up_to_date;
1a578e9b
AC
13610 mouse_position_hook = XTmouse_position;
13611 frame_rehighlight_hook = XTframe_rehighlight;
13612 frame_raise_lower_hook = XTframe_raise_lower;
13613
13614 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13615 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13616 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13617 judge_scroll_bars_hook = XTjudge_scroll_bars;
13618
13619 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13620
e0f712ba
AC
13621 scroll_region_ok = 1; /* we'll scroll partial frames */
13622 char_ins_del_ok = 1;
13623 line_ins_del_ok = 1; /* we'll just blt 'em */
13624 fast_clear_end_of_line = 1; /* X does this well */
13625 memory_below_frame = 0; /* we don't remember what scrolls
1a578e9b
AC
13626 off the bottom */
13627 baud_rate = 19200;
13628
13629 x_noop_count = 0;
13630 last_tool_bar_item = -1;
13631 any_help_event_p = 0;
177c0ea7 13632
1a578e9b
AC
13633 /* Try to use interrupt input; if we can't, then start polling. */
13634 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13635
13636#ifdef USE_X_TOOLKIT
13637 XtToolkitInitialize ();
13638 Xt_app_con = XtCreateApplicationContext ();
13639 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13640
13641 /* Install an asynchronous timer that processes Xt timeout events
13642 every 0.1s. This is necessary because some widget sets use
13643 timeouts internally, for example the LessTif menu bar, or the
13644 Xaw3d scroll bar. When Xt timouts aren't processed, these
13645 widgets don't behave normally. */
13646 {
13647 EMACS_TIME interval;
13648 EMACS_SET_SECS_USECS (interval, 0, 100000);
13649 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13650 }
13651#endif
177c0ea7 13652
1a578e9b
AC
13653#if USE_TOOLKIT_SCROLL_BARS
13654 xaw3d_arrow_scroll = False;
13655 xaw3d_pick_top = True;
13656#endif
13657
13658#if 0
13659 /* Note that there is no real way portable across R3/R4 to get the
13660 original error handler. */
13661 XSetErrorHandler (x_error_handler);
13662 XSetIOErrorHandler (x_io_error_quitter);
13663
13664 /* Disable Window Change signals; they are handled by X events. */
13665#ifdef SIGWINCH
13666 signal (SIGWINCH, SIG_DFL);
13667#endif /* ! defined (SIGWINCH) */
13668
13669 signal (SIGPIPE, x_connection_signal);
13670#endif
13671
13672 mac_initialize_display_info ();
bc21bf11
AC
13673
13674#if TARGET_API_MAC_CARBON
13675 init_required_apple_events ();
13676
742fbed7
AC
13677 init_mac_drag_n_drop ();
13678
13679#if USE_CARBON_EVENTS
13680 init_service_handler ();
6ef0a87e
ST
13681
13682 init_quit_char_handler ();
742fbed7
AC
13683#endif
13684
bc21bf11 13685 DisableMenuCommand (NULL, kHICommandQuit);
8030369c
AC
13686
13687 if (!inhibit_window_system)
13688 MakeMeTheFrontProcess ();
bc21bf11 13689#endif
1a578e9b
AC
13690}
13691
13692
13693void
13694syms_of_macterm ()
13695{
13696#if 0
13697 staticpro (&x_error_message_string);
13698 x_error_message_string = Qnil;
13699#endif
13700
8c609cff
ST
13701 Fprovide (intern ("mac-carbon"), Qnil);
13702
1a578e9b
AC
13703 staticpro (&x_display_name_list);
13704 x_display_name_list = Qnil;
13705
13706 staticpro (&last_mouse_scroll_bar);
13707 last_mouse_scroll_bar = Qnil;
13708
13709 staticpro (&Qvendor_specific_keysyms);
13710 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13711
13712 staticpro (&last_mouse_press_frame);
13713 last_mouse_press_frame = Qnil;
13714
8f47302e
AC
13715 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13716 staticpro (&Qmac_ready_for_drag_n_drop);
13717
1a578e9b
AC
13718 help_echo = Qnil;
13719 staticpro (&help_echo);
13720 help_echo_object = Qnil;
13721 staticpro (&help_echo_object);
13722 help_echo_window = Qnil;
13723 staticpro (&help_echo_window);
13724 previous_help_echo = Qnil;
13725 staticpro (&previous_help_echo);
13726 help_echo_pos = -1;
13727
e0f712ba
AC
13728 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13729 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13730 x_autoselect_window_p = 0;
13731
1a578e9b 13732 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
e0f712ba
AC
13733 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13734For example, if a block cursor is over a tab, it will be drawn as
13735wide as that tab on the display. */);
1a578e9b
AC
13736 x_stretch_cursor_p = 0;
13737
e0f712ba
AC
13738#if 0 /* TODO: Setting underline position from font properties. */
13739 DEFVAR_BOOL ("x-use-underline-position-properties",
13740 &x_use_underline_position_properties,
13741 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13742nil means ignore them. If you encounter fonts with bogus
13743UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13744to 4.1, set this to nil. */);
13745 x_use_underline_position_properties = 1;
1a578e9b
AC
13746#endif
13747
e0f712ba
AC
13748 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13749 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13750 Vx_toolkit_scroll_bars = Qt;
13751
1a578e9b
AC
13752 staticpro (&last_mouse_motion_frame);
13753 last_mouse_motion_frame = Qnil;
177c0ea7 13754
1a578e9b 13755 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
e0f712ba
AC
13756 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13757Otherwise the option key is used. */);
1a578e9b
AC
13758 Vmac_command_key_is_meta = Qt;
13759
742fbed7
AC
13760 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
13761 doc: /* Non-nil means that the control and meta keys are reversed. This is
13762 useful for non-standard keyboard layouts. */);
13763 Vmac_reverse_ctrl_meta = Qnil;
13764
13765#if USE_CARBON_EVENTS
13766 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
13767 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
13768the right click will be mouse-3.
13769Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
b37113a1 13770 Vmac_wheel_button_is_mouse_2 = Qt;
5883787c
AC
13771
13772 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
13773 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
13774Toolbox for processing before Emacs sees it. */);
13775 Vmac_pass_command_to_system = Qt;
13776
13777 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
13778 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
13779Toolbox for processing before Emacs sees it. */);
13780 Vmac_pass_control_to_system = Qt;
742fbed7
AC
13781#endif
13782
1a578e9b 13783 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
e0f712ba
AC
13784 doc: /* One of the Text Encoding Base constant values defined in the
13785Basic Text Constants section of Inside Macintosh - Text Encoding
13786Conversion Manager. Its value determines the encoding characters
13787typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13788will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13789its default value, no conversion takes place. If it is set to
13790kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13791characters typed on Mac keyboard are first converted into the
13792ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13793passed to Emacs. Together with Emacs's set-keyboard-coding-system
13794command, this enables the Mac keyboard to be used to enter non-ASCII
13795characters directly. */);
1a578e9b
AC
13796 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13797}