Upgraded to mh-e version 6.1.1.
[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.) */
205
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
262/* Nominal cursor position -- where to draw output.
263 HPOS and VPOS are window relative glyph matrix coordinates.
264 X and Y are window relative pixel coordinates. */
265
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));
3f332ef3 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;
508
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;
521
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;
525
526 RGBForeColor (&fg_color);
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;
537
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;
541
542 RGBBackColor (&bg_color);
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;
629
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 */
1a578e9b 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;
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;
960
961 p.h = *h;
962 p.v = *v;
963
964 LocalToGlobal (&p);
965
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);
1026
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
1036mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
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);
1053
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
1163#define XFlush(DISPLAY) (void) 0
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 ***********************************************************************/
1203
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);
1227
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. */
1249
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));
1282
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
AC
1294 y1 -= 1;
1295
1296 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1297 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1298 }
1299}
e0f712ba 1300
1a578e9b
AC
1301
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);
1331
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
AC
1373 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1374
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
AC
1426 xassert (w);
1427
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);
1a578e9b
AC
1462
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
AC
1508 break;
1509
1510 case OVERLAY_ARROW_BITMAP:
d33c49e8
KS
1511 wd = ov_width;
1512 h = ov_height;
1a578e9b 1513 bits = ov_bits;
1a578e9b
AC
1514 break;
1515
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
AC
1526 break;
1527
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.
1734
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 }
1908
1909 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1910
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];
1923
1924 if ((enc == 1 || enc == 2)
1925 && CHARSET_DIMENSION (charset) == 2)
1926 char2b->byte1 |= 0x80;
1927
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;
1975
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);
1997
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;
2038
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
2069/* Store one glyph for IT->char_to_display in IT->glyph_row.
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;
2078
2079 xassert (it->glyph_row);
2080 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2081
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
2103/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
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;
2112
2113 xassert (it->glyph_row);
2114
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;
2184
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 }
1a578e9b
AC
2192
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);
2200
2201 if (it->glyph_row)
2202 {
2203 struct glyph *glyph;
2204 enum glyph_row_area area = it->area;
2205
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
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
2231 ascent of the glyph (0 <= ASCENT <= 1). */
2232
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);
2244
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 *
2273 canonical char width wide. WIDTH may be an integer or floating
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
2283 Exactly one of the above pairs must be present.
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);
2321
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));
2339
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);
2361
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
2372 /* Compute percentage of height used for ascent. If
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 }
1a578e9b
AC
2406
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
AC
2411 }
2412
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 }
1a578e9b
AC
2504
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 }
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;
2565
e0f712ba
AC
2566 if (thick > 0)
2567 {
2568 it->ascent += thick;
2569 it->descent += thick;
2570 }
2571 else
2572 thick = -thick;
1a578e9b
AC
2573
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);
2586
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);
1a578e9b
AC
2596 x_append_stretch_glyph (it, it->object, it->pixel_width,
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;
1a578e9b 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;
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;
1a578e9b
AC
2640
2641 if (it->glyph_row)
2642 {
2643 double ascent = (double) it->ascent / (it->ascent + it->descent);
2644 x_append_stretch_glyph (it, it->object, it->pixel_width,
2645 it->ascent + it->descent, ascent);
2646 }
2647 }
2648 else
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;
1a578e9b
AC
2694
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 }
2700
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);
2707
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
AC
2800 }
2801
2802 rightmost = width;
2803 lowest = - descent + boff;
2804 highest = ascent + boff;
2805 leftmost = 0;
2806
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;
1a578e9b
AC
2967
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 }
2973
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);
2980
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
AC
3026 }
3027
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 *,
3197 enum glyph_row_area, int,
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
e0f712ba 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. */
3352
3353static void
3354x_set_mouse_face_gc (s)
3355 struct glyph_string *s;
3356{
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);
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;
3382
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;
3388
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);
3395
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;
3410{
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);
3424
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);
3475
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 }
3485
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. */
3571
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;
3612
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;
3645
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];
3707
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;
3930
3931 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3932
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 }
4019
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 */
4030
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. */
4127
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 }
4153
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;
4181
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;
4216
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);
1a578e9b
AC
4242
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);
4248
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;
4274
4275 xgcv.foreground = s->face->box_color;
4276 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4277
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);
4290
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 }
4319
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)));
4342
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);
4399
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);
4414
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);
e0f712ba 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;
4456
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;
1a578e9b
AC
4461
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 }
4473
4474 x0 = x - thick;
4475 y0 = y - thick;
4476 x1 = x + s->img->width + thick - 1;
4477 y1 = y + s->img->height + thick - 1;
4478
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);
4537
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
4582/* Draw image glyph string S.
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;
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);
4640
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
AC
4667 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4668
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;
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);
4756
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;
4838
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 }
4871
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 }
4891
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.
4907
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;
4955
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.
4966
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);
5016
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;
e0f712ba 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;
5047
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;
5070
5071 xassert (s->first_glyph->type == STRETCH_GLYPH);
5072
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;
5089
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. */
5105
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;
5132
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);
5150
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
AC
5161 s->extends_to_end_of_line_p = 1;
5162
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)
5243
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)
5299
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. */
5368
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
5449 prepended must be drawn because the first glyph string
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;
5527
5528 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5529 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5530
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;
5566
5567 BLOCK_INPUT;
5568
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 }
5600
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;
5620
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;
5630
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;
5718
5719 xassert (updated_window && updated_row);
5720 f = XFRAME (w->frame);
5721
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);
5743
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 }
5764
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);
5768
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 }
5839
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 }
5891
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 ();
5906
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;
5992
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);
6002
6003 UNBLOCK_INPUT;
6004}
6005
6006
6007\f
6008/***********************************************************************
6009 Exposure Events
6010 ***********************************************************************/
6011
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 }
6170
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);
6202
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;
6260
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);
6265
6266 if (row->used[LEFT_MARGIN_AREA])
6267 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
6268
6269 if (row->used[TEXT_AREA])
6270 x_fix_overlapping_area (w, row, TEXT_AREA);
6271
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
AC
6319 struct glyph_row *first_overlapping_row, *last_overlapping_row;
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 }
6360
e0f712ba
AC
6361 if (expose_line (w, row, &r))
6362 mouse_face_overwritten_p = 1;
6363 }
ca45961d 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);
6384
e0f712ba
AC
6385 /* Draw border between windows. */
6386 x_draw_vertical_border (w);
ca45961d 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;
6413
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;
6425
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;
6441
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 }
6992
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;
7055
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));
e0f712ba 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,
7333 &ignore, pos + 1, 1);
7334
7335 /* Display it as active. */
7336 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7337 /* TODO: mouse cursor changes. */
7338 }
7339 /* Handle the text property case. */
7340 else if (! NILP (mouse_face) && BUFFERP (object))
7341 {
7342 /* Find the range of text around this char that
7343 should be active. */
7344 Lisp_Object before, after, beginning, end;
7345 int ignore;
7346
7347 beginning = Fmarker_position (w->start);
7348 end = make_number (BUF_Z (XBUFFER (object))
7349 - XFASTINT (w->window_end_pos));
7350 before
7351 = Fprevious_single_property_change (make_number (pos + 1),
7352 Qmouse_face,
7353 object, beginning);
7354 after
7355 = Fnext_single_property_change (position, Qmouse_face,
7356 object, end);
7357
7358 /* Record this as the current active region. */
7359 fast_find_position (w, XFASTINT (before),
7360 &dpyinfo->mouse_face_beg_col,
7361 &dpyinfo->mouse_face_beg_row,
7362 &dpyinfo->mouse_face_beg_x,
7363 &dpyinfo->mouse_face_beg_y, Qnil);
7364 dpyinfo->mouse_face_past_end
7365 = !fast_find_position (w, XFASTINT (after),
7366 &dpyinfo->mouse_face_end_col,
7367 &dpyinfo->mouse_face_end_row,
7368 &dpyinfo->mouse_face_end_x,
7369 &dpyinfo->mouse_face_end_y, Qnil);
7370 dpyinfo->mouse_face_window = window;
7371
7372 if (BUFFERP (object))
1a578e9b
AC
7373 dpyinfo->mouse_face_face_id
7374 = face_at_buffer_position (w, pos, 0, 0,
7375 &ignore, pos + 1, 1);
7376
e0f712ba
AC
7377 /* Display it as active. */
7378 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7379 /* TODO: mouse cursor changes. */
7380 }
7381 else if (!NILP (mouse_face) && STRINGP (object))
7382 {
7383 Lisp_Object b, e;
7384 int ignore;
7385
7386 b = Fprevious_single_property_change (make_number (pos + 1),
7387 Qmouse_face,
7388 object, Qnil);
7389 e = Fnext_single_property_change (position, Qmouse_face,
7390 object, Qnil);
7391 if (NILP (b))
7392 b = make_number (0);
7393 if (NILP (e))
d5db4077 7394 e = make_number (SCHARS (object) - 1);
e0f712ba 7395 fast_find_string_pos (w, XINT (b), object,
1a578e9b
AC
7396 &dpyinfo->mouse_face_beg_col,
7397 &dpyinfo->mouse_face_beg_row,
7398 &dpyinfo->mouse_face_beg_x,
e0f712ba
AC
7399 &dpyinfo->mouse_face_beg_y, 0);
7400 fast_find_string_pos (w, XINT (e), object,
7401 &dpyinfo->mouse_face_end_col,
7402 &dpyinfo->mouse_face_end_row,
7403 &dpyinfo->mouse_face_end_x,
7404 &dpyinfo->mouse_face_end_y, 1);
7405 dpyinfo->mouse_face_past_end = 0;
7406 dpyinfo->mouse_face_window = window;
7407 dpyinfo->mouse_face_face_id
7408 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7409 glyph->face_id, 1);
7410 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7411 /* TODO: mouse cursor changes. */
1a578e9b 7412 }
e0f712ba 7413 else if (STRINGP (object) && NILP (mouse_face))
1a578e9b 7414 {
e0f712ba
AC
7415 /* A string which doesn't have mouse-face, but
7416 the text ``under'' it might have. */
7417 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7418 int start = MATRIX_ROW_START_CHARPOS (r);
7419
7420 pos = string_buffer_position (w, object, start);
7421 if (pos > 0)
7422 mouse_face = get_char_property_and_overlay (make_number (pos),
7423 Qmouse_face,
7424 w->buffer,
7425 &overlay);
7426 if (!NILP (mouse_face) && !NILP (overlay))
1a578e9b 7427 {
e0f712ba
AC
7428 Lisp_Object before = Foverlay_start (overlay);
7429 Lisp_Object after = Foverlay_end (overlay);
7430 int ignore;
7431
7432 /* Note that we might not be able to find position
7433 BEFORE in the glyph matrix if the overlay is
7434 entirely covered by a `display' property. In
7435 this case, we overshoot. So let's stop in
7436 the glyph matrix before glyphs for OBJECT. */
7437 fast_find_position (w, XFASTINT (before),
7438 &dpyinfo->mouse_face_beg_col,
7439 &dpyinfo->mouse_face_beg_row,
7440 &dpyinfo->mouse_face_beg_x,
7441 &dpyinfo->mouse_face_beg_y,
7442 object);
7443
7444 dpyinfo->mouse_face_past_end
7445 = !fast_find_position (w, XFASTINT (after),
7446 &dpyinfo->mouse_face_end_col,
7447 &dpyinfo->mouse_face_end_row,
7448 &dpyinfo->mouse_face_end_x,
7449 &dpyinfo->mouse_face_end_y,
7450 Qnil);
7451 dpyinfo->mouse_face_window = window;
7452 dpyinfo->mouse_face_face_id
7453 = face_at_buffer_position (w, pos, 0, 0,
7454 &ignore, pos + 1, 1);
7455
7456 /* Display it as active. */
7457 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7458 /* TODO: mouse cursor changes. */
1a578e9b
AC
7459 }
7460 }
7461 }
1a578e9b 7462
e0f712ba
AC
7463 check_help_echo:
7464
7465 /* Look for a `help-echo' property. */
7466 {
7467 Lisp_Object help, overlay;
7468
7469 /* Check overlays first. */
7470 help = overlay = Qnil;
7471 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7472 {
7473 overlay = overlay_vec[i];
7474 help = Foverlay_get (overlay, Qhelp_echo);
7475 }
7476
7477 if (!NILP (help))
7478 {
7479 help_echo = help;
7480 help_echo_window = window;
7481 help_echo_object = overlay;
7482 help_echo_pos = pos;
7483 }
7484 else
7485 {
7486 Lisp_Object object = glyph->object;
7487 int charpos = glyph->charpos;
7488
7489 /* Try text properties. */
7490 if (STRINGP (object)
7491 && charpos >= 0
d5db4077 7492 && charpos < SCHARS (object))
e0f712ba
AC
7493 {
7494 help = Fget_text_property (make_number (charpos),
7495 Qhelp_echo, object);
7496 if (NILP (help))
7497 {
7498 /* If the string itself doesn't specify a help-echo,
7499 see if the buffer text ``under'' it does. */
7500 struct glyph_row *r
7501 = MATRIX_ROW (w->current_matrix, vpos);
7502 int start = MATRIX_ROW_START_CHARPOS (r);
7503 int pos = string_buffer_position (w, object, start);
7504 if (pos > 0)
7505 {
7506 help = Fget_char_property (make_number (pos),
7507 Qhelp_echo, w->buffer);
7508 if (!NILP (help))
7509 {
7510 charpos = pos;
7511 object = w->buffer;
7512 }
7513 }
7514 }
7515 }
7516 else if (BUFFERP (object)
7517 && charpos >= BEGV
7518 && charpos < ZV)
7519 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7520 object);
7521
7522 if (!NILP (help))
7523 {
7524 help_echo = help;
7525 help_echo_window = window;
7526 help_echo_object = object;
7527 help_echo_pos = charpos;
7528 }
7529 }
7530 }
7531
7532 BEGV = obegv;
7533 ZV = ozv;
7534 current_buffer = obuf;
7535 }
7536
7537 set_cursor:
7538 /* TODO: mouse cursor changes. */
7539 ;
7540}
7541
7542static void
7543redo_mouse_highlight ()
7544{
7545 if (!NILP (last_mouse_motion_frame)
7546 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
1a578e9b
AC
7547 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7548 last_mouse_motion_position.h,
7549 last_mouse_motion_position.v);
7550}
7551
7552
7553\f
7554/***********************************************************************
7555 Tool-bars
7556 ***********************************************************************/
7557
7558static int x_tool_bar_item P_ ((struct frame *, int, int,
7559 struct glyph **, int *, int *, int *));
7560
7561/* Tool-bar item index of the item on which a mouse button was pressed
7562 or -1. */
7563
7564static int last_tool_bar_item;
7565
7566
7567/* Get information about the tool-bar item at position X/Y on frame F.
7568 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7569 the current matrix of the tool-bar window of F, or NULL if not
7570 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7571 item in F->current_tool_bar_items. Value is
7572
7573 -1 if X/Y is not on a tool-bar item
7574 0 if X/Y is on the same item that was highlighted before.
7575 1 otherwise. */
7576
7577static int
7578x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7579 struct frame *f;
7580 int x, y;
7581 struct glyph **glyph;
7582 int *hpos, *vpos, *prop_idx;
7583{
7584 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7585 struct window *w = XWINDOW (f->tool_bar_window);
7586 int area;
7587
7588 /* Find the glyph under X/Y. */
e0f712ba 7589 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
1a578e9b
AC
7590 if (*glyph == NULL)
7591 return -1;
7592
7593 /* Get the start of this tool-bar item's properties in
7594 f->current_tool_bar_items. */
7595 if (!tool_bar_item_info (f, *glyph, prop_idx))
7596 return -1;
7597
7598 /* Is mouse on the highlighted item? */
7599 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7600 && *vpos >= dpyinfo->mouse_face_beg_row
7601 && *vpos <= dpyinfo->mouse_face_end_row
7602 && (*vpos > dpyinfo->mouse_face_beg_row
7603 || *hpos >= dpyinfo->mouse_face_beg_col)
7604 && (*vpos < dpyinfo->mouse_face_end_row
7605 || *hpos < dpyinfo->mouse_face_end_col
7606 || dpyinfo->mouse_face_past_end))
7607 return 0;
7608
7609 return 1;
7610}
7611
7612
7613/* Handle mouse button event on the tool-bar of frame F, at
7614 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7615 or ButtonRelase. */
7616
7617static void
7618x_handle_tool_bar_click (f, button_event)
7619 struct frame *f;
7620 EventRecord *button_event;
7621{
7622 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7623 struct window *w = XWINDOW (f->tool_bar_window);
7624 int hpos, vpos, prop_idx;
7625 struct glyph *glyph;
7626 Lisp_Object enabled_p;
7627 int x = button_event->where.h;
7628 int y = button_event->where.v;
7629
7630 /* If not on the highlighted tool-bar item, return. */
7631 frame_to_window_pixel_xy (w, &x, &y);
7632 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7633 return;
7634
7635 /* If item is disabled, do nothing. */
2d4bc735 7636 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
1a578e9b
AC
7637 if (NILP (enabled_p))
7638 return;
7639
7640 if (button_event->what == mouseDown)
7641 {
7642 /* Show item in pressed state. */
7643 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7644 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7645 last_tool_bar_item = prop_idx;
7646 }
7647 else
7648 {
7649 Lisp_Object key, frame;
7650 struct input_event event;
7651
7652 /* Show item in released state. */
7653 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7654 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7655
2d4bc735 7656 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
1a578e9b
AC
7657
7658 XSETFRAME (frame, f);
7659 event.kind = TOOL_BAR_EVENT;
7660 event.frame_or_window = frame;
7661 event.arg = frame;
7662 kbd_buffer_store_event (&event);
7663
7664 event.kind = TOOL_BAR_EVENT;
7665 event.frame_or_window = frame;
7666 event.arg = key;
7667 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7668 button_event->modifiers);
7669 kbd_buffer_store_event (&event);
7670 last_tool_bar_item = -1;
7671 }
7672}
7673
7674
7675/* Possibly highlight a tool-bar item on frame F when mouse moves to
7676 tool-bar window-relative coordinates X/Y. Called from
7677 note_mouse_highlight. */
7678
7679static void
7680note_tool_bar_highlight (f, x, y)
7681 struct frame *f;
7682 int x, y;
7683{
7684 Lisp_Object window = f->tool_bar_window;
7685 struct window *w = XWINDOW (window);
7686 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7687 int hpos, vpos;
7688 struct glyph *glyph;
7689 struct glyph_row *row;
7690 int i;
7691 Lisp_Object enabled_p;
7692 int prop_idx;
7693 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7694 int mouse_down_p, rc;
7695
7696 /* Function note_mouse_highlight is called with negative x(y
7697 values when mouse moves outside of the frame. */
7698 if (x <= 0 || y <= 0)
7699 {
7700 clear_mouse_face (dpyinfo);
7701 return;
7702 }
7703
7704 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7705 if (rc < 0)
7706 {
7707 /* Not on tool-bar item. */
7708 clear_mouse_face (dpyinfo);
7709 return;
7710 }
7711 else if (rc == 0)
7712 /* On same tool-bar item as before. */
7713 goto set_help_echo;
7714
7715 clear_mouse_face (dpyinfo);
7716
7717 /* Mouse is down, but on different tool-bar item? */
7718 mouse_down_p = (dpyinfo->grabbed
7719 && f == last_mouse_frame
7720 && FRAME_LIVE_P (f));
7721 if (mouse_down_p
7722 && last_tool_bar_item != prop_idx)
7723 return;
7724
7725 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7726 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7727
7728 /* If tool-bar item is not enabled, don't highlight it. */
2d4bc735 7729 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
1a578e9b
AC
7730 if (!NILP (enabled_p))
7731 {
7732 /* Compute the x-position of the glyph. In front and past the
7733 image is a space. We include this is the highlighted area. */
7734 row = MATRIX_ROW (w->current_matrix, vpos);
7735 for (i = x = 0; i < hpos; ++i)
7736 x += row->glyphs[TEXT_AREA][i].pixel_width;
7737
7738 /* Record this as the current active region. */
7739 dpyinfo->mouse_face_beg_col = hpos;
7740 dpyinfo->mouse_face_beg_row = vpos;
7741 dpyinfo->mouse_face_beg_x = x;
7742 dpyinfo->mouse_face_beg_y = row->y;
7743 dpyinfo->mouse_face_past_end = 0;
7744
7745 dpyinfo->mouse_face_end_col = hpos + 1;
7746 dpyinfo->mouse_face_end_row = vpos;
7747 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7748 dpyinfo->mouse_face_end_y = row->y;
7749 dpyinfo->mouse_face_window = window;
7750 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7751
7752 /* Display it as active. */
7753 show_mouse_face (dpyinfo, draw);
7754 dpyinfo->mouse_face_image_state = draw;
7755 }
7756
7757 set_help_echo:
7758
7759 /* Set help_echo to a help string.to display for this tool-bar item.
7760 XTread_socket does the rest. */
7761 help_echo_object = help_echo_window = Qnil;
7762 help_echo_pos = -1;
2d4bc735 7763 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
1a578e9b 7764 if (NILP (help_echo))
2d4bc735 7765 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
1a578e9b
AC
7766}
7767
7768
7769\f
e0f712ba
AC
7770/* Find the glyph matrix position of buffer position CHARPOS in window
7771 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7772 current glyphs must be up to date. If CHARPOS is above window
7773 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7774 of last line in W. In the row containing CHARPOS, stop before glyphs
7775 having STOP as object. */
7776
7777#if 0 /* This is a version of fast_find_position that's more correct
7778 in the presence of hscrolling, for example. I didn't install
7779 it right away because the problem fixed is minor, it failed
7780 in 20.x as well, and I think it's too risky to install
7781 so near the release of 21.1. 2001-09-25 gerd. */
7782
7783static int
7784fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7785 struct window *w;
7786 int charpos;
7787 int *hpos, *vpos, *x, *y;
7788 Lisp_Object stop;
7789{
7790 struct glyph_row *row, *first;
7791 struct glyph *glyph, *end;
7792 int i, past_end = 0;
7793
7794 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7795 row = row_containing_pos (w, charpos, first, NULL, 0);
7796 if (row == NULL)
7797 {
7798 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7799 {
7800 *x = *y = *hpos = *vpos = 0;
7801 return 0;
7802 }
7803 else
7804 {
7805 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7806 past_end = 1;
7807 }
7808 }
7809
7810 *x = row->x;
7811 *y = row->y;
7812 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7813
7814 glyph = row->glyphs[TEXT_AREA];
7815 end = glyph + row->used[TEXT_AREA];
7816
7817 /* Skip over glyphs not having an object at the start of the row.
7818 These are special glyphs like truncation marks on terminal
7819 frames. */
7820 if (row->displays_text_p)
7821 while (glyph < end
7822 && INTEGERP (glyph->object)
7823 && !EQ (stop, glyph->object)
7824 && glyph->charpos < 0)
7825 {
7826 *x += glyph->pixel_width;
7827 ++glyph;
7828 }
7829
7830 while (glyph < end
7831 && !INTEGERP (glyph->object)
7832 && !EQ (stop, glyph->object)
7833 && (!BUFFERP (glyph->object)
7834 || glyph->charpos < charpos))
7835 {
7836 *x += glyph->pixel_width;
7837 ++glyph;
7838 }
7839
7840 *hpos = glyph - row->glyphs[TEXT_AREA];
7841 return past_end;
7842}
7843
7844#else /* not 0 */
1a578e9b
AC
7845
7846static int
e0f712ba 7847fast_find_position (w, pos, hpos, vpos, x, y, stop)
1a578e9b
AC
7848 struct window *w;
7849 int pos;
7850 int *hpos, *vpos, *x, *y;
e0f712ba 7851 Lisp_Object stop;
1a578e9b
AC
7852{
7853 int i;
7854 int lastcol;
7855 int maybe_next_line_p = 0;
7856 int line_start_position;
7857 int yb = window_text_bottom_y (w);
e0f712ba
AC
7858 struct glyph_row *row, *best_row;
7859 int row_vpos, best_row_vpos;
1a578e9b
AC
7860 int current_x;
7861
e0f712ba
AC
7862 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7863 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7864
1a578e9b
AC
7865 while (row->y < yb)
7866 {
7867 if (row->used[TEXT_AREA])
7868 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7869 else
7870 line_start_position = 0;
7871
7872 if (line_start_position > pos)
7873 break;
7874 /* If the position sought is the end of the buffer,
7875 don't include the blank lines at the bottom of the window. */
7876 else if (line_start_position == pos
e0f712ba 7877 && pos == BUF_ZV (XBUFFER (w->buffer)))
1a578e9b
AC
7878 {
7879 maybe_next_line_p = 1;
7880 break;
7881 }
7882 else if (line_start_position > 0)
e0f712ba
AC
7883 {
7884 best_row = row;
7885 best_row_vpos = row_vpos;
7886 }
1a578e9b
AC
7887
7888 if (row->y + row->height >= yb)
e0f712ba
AC
7889 break;
7890
1a578e9b
AC
7891 ++row;
7892 ++row_vpos;
7893 }
e0f712ba 7894
1a578e9b
AC
7895 /* Find the right column within BEST_ROW. */
7896 lastcol = 0;
7897 current_x = best_row->x;
7898 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7899 {
7900 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
e0f712ba 7901 int charpos = glyph->charpos;
1a578e9b 7902
e0f712ba 7903 if (BUFFERP (glyph->object))
1a578e9b 7904 {
e0f712ba
AC
7905 if (charpos == pos)
7906 {
7907 *hpos = i;
7908 *vpos = best_row_vpos;
7909 *x = current_x;
7910 *y = best_row->y;
7911 return 1;
7912 }
7913 else if (charpos > pos)
7914 break;
1a578e9b 7915 }
e0f712ba 7916 else if (EQ (glyph->object, stop))
1a578e9b 7917 break;
1a578e9b 7918
e0f712ba
AC
7919 if (charpos > 0)
7920 lastcol = i;
1a578e9b
AC
7921 current_x += glyph->pixel_width;
7922 }
7923
7924 /* If we're looking for the end of the buffer,
7925 and we didn't find it in the line we scanned,
7926 use the start of the following line. */
7927 if (maybe_next_line_p)
7928 {
7929 ++best_row;
7930 ++best_row_vpos;
7931 lastcol = 0;
7932 current_x = best_row->x;
7933 }
7934
7935 *vpos = best_row_vpos;
7936 *hpos = lastcol + 1;
7937 *x = current_x;
7938 *y = best_row->y;
7939 return 0;
7940}
7941
e0f712ba
AC
7942#endif /* not 0 */
7943
7944
7945/* Find the position of the glyph for position POS in OBJECT in
7946 window W's current matrix, and return in *X/*Y the pixel
7947 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7948
7949 RIGHT_P non-zero means return the position of the right edge of the
7950 glyph, RIGHT_P zero means return the left edge position.
7951
7952 If no glyph for POS exists in the matrix, return the position of
7953 the glyph with the next smaller position that is in the matrix, if
7954 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7955 exists in the matrix, return the position of the glyph with the
7956 next larger position in OBJECT.
7957
7958 Value is non-zero if a glyph was found. */
7959
7960static int
7961fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7962 struct window *w;
7963 int pos;
7964 Lisp_Object object;
7965 int *hpos, *vpos, *x, *y;
7966 int right_p;
7967{
7968 int yb = window_text_bottom_y (w);
7969 struct glyph_row *r;
7970 struct glyph *best_glyph = NULL;
7971 struct glyph_row *best_row = NULL;
7972 int best_x = 0;
7973
7974 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7975 r->enabled_p && r->y < yb;
7976 ++r)
7977 {
7978 struct glyph *g = r->glyphs[TEXT_AREA];
7979 struct glyph *e = g + r->used[TEXT_AREA];
7980 int gx;
7981
7982 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7983 if (EQ (g->object, object))
7984 {
7985 if (g->charpos == pos)
7986 {
7987 best_glyph = g;
7988 best_x = gx;
7989 best_row = r;
7990 goto found;
7991 }
7992 else if (best_glyph == NULL
7993 || ((abs (g->charpos - pos)
7994 < abs (best_glyph->charpos - pos))
7995 && (right_p
7996 ? g->charpos < pos
7997 : g->charpos > pos)))
7998 {
7999 best_glyph = g;
8000 best_x = gx;
8001 best_row = r;
8002 }
8003 }
8004 }
8005
8006 found:
8007
8008 if (best_glyph)
8009 {
8010 *x = best_x;
8011 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
8012
8013 if (right_p)
8014 {
8015 *x += best_glyph->pixel_width;
8016 ++*hpos;
8017 }
8018
8019 *y = best_row->y;
8020 *vpos = best_row - w->current_matrix->rows;
8021 }
8022
8023 return best_glyph != NULL;
8024}
8025
1a578e9b
AC
8026
8027/* Display the active region described by mouse_face_*
8028 in its mouse-face if HL > 0, in its normal face if HL = 0. */
8029
8030static void
8031show_mouse_face (dpyinfo, draw)
8032 struct mac_display_info *dpyinfo;
8033 enum draw_glyphs_face draw;
8034{
8035 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
8036 struct frame *f = XFRAME (WINDOW_FRAME (w));
1a578e9b 8037
e0f712ba
AC
8038 if (/* If window is in the process of being destroyed, don't bother
8039 to do anything. */
8040 w->current_matrix != NULL
8041 /* Don't update mouse highlight if hidden */
8042 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
8043 /* Recognize when we are called to operate on rows that don't exist
8044 anymore. This can happen when a window is split. */
8045 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
1a578e9b 8046 {
e0f712ba
AC
8047 int phys_cursor_on_p = w->phys_cursor_on_p;
8048 struct glyph_row *row, *first, *last;
1a578e9b 8049
e0f712ba
AC
8050 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
8051 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
8052
8053 for (row = first; row <= last && row->enabled_p; ++row)
1a578e9b 8054 {
e0f712ba 8055 int start_hpos, end_hpos, start_x;
1a578e9b 8056
e0f712ba
AC
8057 /* For all but the first row, the highlight starts at column 0. */
8058 if (row == first)
8059 {
8060 start_hpos = dpyinfo->mouse_face_beg_col;
8061 start_x = dpyinfo->mouse_face_beg_x;
8062 }
8063 else
8064 {
8065 start_hpos = 0;
8066 start_x = 0;
8067 }
1a578e9b 8068
e0f712ba
AC
8069 if (row == last)
8070 end_hpos = dpyinfo->mouse_face_end_col;
8071 else
8072 end_hpos = row->used[TEXT_AREA];
1a578e9b 8073
e0f712ba
AC
8074 if (end_hpos > start_hpos)
8075 {
8076 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8077 start_hpos, end_hpos, draw, 0);
1a578e9b 8078
e0f712ba
AC
8079 row->mouse_face_p
8080 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8081 }
8082 }
1a578e9b 8083
e0f712ba
AC
8084 /* When we've written over the cursor, arrange for it to
8085 be displayed again. */
8086 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8087 x_display_cursor (w, 1,
8088 w->phys_cursor.hpos, w->phys_cursor.vpos,
8089 w->phys_cursor.x, w->phys_cursor.y);
8090 }
1a578e9b 8091
1a578e9b
AC
8092#if 0 /* MAC_TODO: mouse cursor */
8093 /* Change the mouse cursor. */
8094 if (draw == DRAW_NORMAL_TEXT)
8095 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8096 f->output_data.x->text_cursor);
8097 else if (draw == DRAW_MOUSE_FACE)
8098 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8099 f->output_data.x->cross_cursor);
8100 else
8101 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8102 f->output_data.x->nontext_cursor);
8103#endif
1a578e9b
AC
8104}
8105
8106/* Clear out the mouse-highlighted active region.
8107 Redraw it un-highlighted first. */
8108
e0f712ba 8109static int
1a578e9b
AC
8110clear_mouse_face (dpyinfo)
8111 struct mac_display_info *dpyinfo;
8112{
e0f712ba
AC
8113 int cleared = 0;
8114
1a578e9b 8115 if (! NILP (dpyinfo->mouse_face_window))
e0f712ba
AC
8116 {
8117 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8118 cleared = 1;
8119 }
1a578e9b
AC
8120
8121 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8122 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8123 dpyinfo->mouse_face_window = Qnil;
e0f712ba
AC
8124 dpyinfo->mouse_face_overlay = Qnil;
8125 return cleared;
1a578e9b
AC
8126}
8127
8128
8129/* Clear any mouse-face on window W. This function is part of the
8130 redisplay interface, and is called from try_window_id and similar
8131 functions to ensure the mouse-highlight is off. */
8132
e0f712ba 8133static void
1a578e9b
AC
8134x_clear_mouse_face (w)
8135 struct window *w;
8136{
8137 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8138 Lisp_Object window;
8139
e0f712ba 8140 BLOCK_INPUT;
1a578e9b
AC
8141 XSETWINDOW (window, w);
8142 if (EQ (window, dpyinfo->mouse_face_window))
8143 clear_mouse_face (dpyinfo);
e0f712ba 8144 UNBLOCK_INPUT;
1a578e9b
AC
8145}
8146
8147
8148/* Just discard the mouse face information for frame F, if any.
8149 This is used when the size of F is changed. */
8150
e0f712ba 8151void
1a578e9b
AC
8152cancel_mouse_face (f)
8153 FRAME_PTR f;
8154{
8155 Lisp_Object window;
8156 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8157
8158 window = dpyinfo->mouse_face_window;
8159 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8160 {
8161 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8162 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8163 dpyinfo->mouse_face_window = Qnil;
8164 }
8165}
8166\f
8167static struct scroll_bar *x_window_to_scroll_bar ();
8168static void x_scroll_bar_report_motion ();
e0f712ba
AC
8169static void x_check_fullscreen P_ ((struct frame *));
8170static void x_check_fullscreen_move P_ ((struct frame *));
8171static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8172
8173
8174/* Try to determine frame pixel position and size of the glyph under
8175 frame pixel coordinates X/Y on frame F . Return the position and
8176 size in *RECT. Value is non-zero if we could compute these
8177 values. */
8178
8179static int
8180glyph_rect (f, x, y, rect)
8181 struct frame *f;
8182 int x, y;
8183 Rect *rect;
8184{
8185 Lisp_Object window;
8186 int part;
8187
8188 window = window_from_coordinates (f, x, y, &part, 0);
8189 if (!NILP (window))
8190 {
8191 struct window *w = XWINDOW (window);
8192 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8193 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8194
8195 frame_to_window_pixel_xy (w, &x, &y);
8196
8197 for (; r < end && r->enabled_p; ++r)
8198 if (r->y <= y && r->y + r->height > y)
8199 {
8200 /* Found the row at y. */
8201 struct glyph *g = r->glyphs[TEXT_AREA];
8202 struct glyph *end = g + r->used[TEXT_AREA];
8203 int gx;
8204
8205 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8206 rect->bottom = rect->top + r->height;
8207
8208 if (x < r->x)
8209 {
8210 /* x is to the left of the first glyph in the row. */
8211 rect->left = XINT (w->left);
8212 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8213 return 1;
8214 }
8215
8216 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8217 if (gx <= x && gx + g->pixel_width > x)
8218 {
8219 /* x is on a glyph. */
8220 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8221 rect->right = rect->left + g->pixel_width;
8222 return 1;
8223 }
8224
8225 /* x is to the right of the last glyph in the row. */
8226 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8227 rect->right = XINT (w->left) + XINT (w->width);
8228 return 1;
8229 }
8230 }
8231
8232 /* The y is not on any row. */
8233 return 0;
8234}
8235
8236/* Record the position of the mouse in last_mouse_glyph. */
8237static void
8238remember_mouse_glyph (f1, gx, gy)
8239 struct frame * f1;
8240 int gx, gy;
8241{
8242 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8243 {
8244 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8245 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8246
8247 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8248 round down even for negative values. */
8249 if (gx < 0)
8250 gx -= width - 1;
8251 if (gy < 0)
8252 gy -= height - 1;
8253#if 0
8254 /* This was the original code from XTmouse_position, but it seems
8255 to give the position of the glyph diagonally next to the one
8256 the mouse is over. */
8257 gx = (gx + width - 1) / width * width;
8258 gy = (gy + height - 1) / height * height;
8259#else
8260 gx = gx / width * width;
8261 gy = gy / height * height;
8262#endif
8263
8264 last_mouse_glyph.left = gx;
8265 last_mouse_glyph.top = gy;
8266 last_mouse_glyph.right = gx + width;
8267 last_mouse_glyph.bottom = gy + height;
8268 }
8269}
1a578e9b
AC
8270
8271/* Return the current position of the mouse.
8272 *fp should be a frame which indicates which display to ask about.
8273
8274 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8275 and *part to the frame, window, and scroll bar part that the mouse
8276 is over. Set *x and *y to the portion and whole of the mouse's
8277 position on the scroll bar.
8278
8279 If the mouse movement started elsewhere, set *fp to the frame the
8280 mouse is on, *bar_window to nil, and *x and *y to the character cell
8281 the mouse is over.
8282
8283 Set *time to the server time-stamp for the time at which the mouse
8284 was at this position.
8285
8286 Don't store anything if we don't have a valid set of values to report.
8287
8288 This clears the mouse_moved flag, so we can wait for the next mouse
8289 movement. */
8290
e0f712ba 8291static void
1a578e9b
AC
8292XTmouse_position (fp, insist, bar_window, part, x, y, time)
8293 FRAME_PTR *fp;
8294 int insist;
8295 Lisp_Object *bar_window;
8296 enum scroll_bar_part *part;
8297 Lisp_Object *x, *y;
8298 unsigned long *time;
8299{
8300 Point mouse_pos;
8301 int ignore1, ignore2;
8302 WindowPtr wp = FrontWindow ();
5883787c 8303 struct frame *f;
1a578e9b
AC
8304 Lisp_Object frame, tail;
8305
5883787c
AC
8306 if (is_emacs_window(wp))
8307 f = ((mac_output *) GetWRefCon (wp))->mFP;
8308
1a578e9b
AC
8309 BLOCK_INPUT;
8310
8311 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8312 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8313 else
8314 {
8315 /* Clear the mouse-moved flag for every frame on this display. */
8316 FOR_EACH_FRAME (tail, frame)
8317 XFRAME (frame)->mouse_moved = 0;
8318
8319 last_mouse_scroll_bar = Qnil;
8320
e0f712ba
AC
8321#if TARGET_API_MAC_CARBON
8322 SetPort (GetWindowPort (wp));
8323#else
1a578e9b 8324 SetPort (wp);
e0f712ba
AC
8325#endif
8326
1a578e9b
AC
8327 GetMouse (&mouse_pos);
8328
8329 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8330 &last_mouse_glyph, insist);
8331
8332 *bar_window = Qnil;
8333 *part = scroll_bar_handle;
8334 *fp = f;
8335 XSETINT (*x, mouse_pos.h);
8336 XSETINT (*y, mouse_pos.v);
8337 *time = last_mouse_movement_time;
8338 }
8339
8340 UNBLOCK_INPUT;
8341}
8342
8343\f
8344/************************************************************************
8345 Scroll bars, general
8346 ************************************************************************/
8347
8348/* Create a scroll bar and return the scroll bar vector for it. W is
8349 the Emacs window on which to create the scroll bar. TOP, LEFT,
e0f712ba 8350 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
1a578e9b
AC
8351 scroll bar. */
8352
8353static struct scroll_bar *
8354x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8355 struct window *w;
8356 int top, left, width, height, disp_top, disp_height;
8357{
8358 struct frame *f = XFRAME (w->frame);
8359 struct scroll_bar *bar
8360 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8361 Rect r;
8362 ControlHandle ch;
8363
8364 BLOCK_INPUT;
8365
8366 r.left = left;
8367 r.top = disp_top;
8368 r.right = left + width;
8369 r.bottom = disp_top + disp_height;
8370
e0f712ba
AC
8371#ifdef TARGET_API_MAC_CARBON
8372 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8373 kControlScrollBarProc, 0L);
8374#else
1a578e9b
AC
8375 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8376 0L);
e0f712ba 8377#endif
1a578e9b
AC
8378 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8379 SetControlReference (ch, (long) bar);
8380
8381 XSETWINDOW (bar->window, w);
8382 XSETINT (bar->top, top);
8383 XSETINT (bar->left, left);
8384 XSETINT (bar->width, width);
8385 XSETINT (bar->height, height);
8386 XSETINT (bar->start, 0);
8387 XSETINT (bar->end, 0);
8388 bar->dragging = Qnil;
8389
8390 /* Add bar to its frame's list of scroll bars. */
8391 bar->next = FRAME_SCROLL_BARS (f);
8392 bar->prev = Qnil;
8393 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8394 if (!NILP (bar->next))
8395 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8396
8397 UNBLOCK_INPUT;
8398 return bar;
8399}
8400
8401
8402/* Draw BAR's handle in the proper position.
8403
8404 If the handle is already drawn from START to END, don't bother
8405 redrawing it, unless REBUILD is non-zero; in that case, always
8406 redraw it. (REBUILD is handy for drawing the handle after expose
8407 events.)
8408
8409 Normally, we want to constrain the start and end of the handle to
8410 fit inside its rectangle, but if the user is dragging the scroll
8411 bar handle, we want to let them drag it down all the way, so that
8412 the bar's top is as far down as it goes; otherwise, there's no way
8413 to move to the very end of the buffer. */
8414
8415static void
8416x_scroll_bar_set_handle (bar, start, end, rebuild)
8417 struct scroll_bar *bar;
8418 int start, end;
8419 int rebuild;
8420{
8421 int dragging = ! NILP (bar->dragging);
8422 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8423 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba
AC
8424 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8425 int length = end - start;
1a578e9b
AC
8426
8427 /* If the display is already accurate, do nothing. */
8428 if (! rebuild
8429 && start == XINT (bar->start)
8430 && end == XINT (bar->end))
8431 return;
8432
8433 BLOCK_INPUT;
8434
e0f712ba
AC
8435 /* Make sure the values are reasonable, and try to preserve the
8436 distance between start and end. */
8437 if (start < 0)
8438 start = 0;
8439 else if (start > top_range)
8440 start = top_range;
8441 end = start + length;
8442
8443 if (end < start)
8444 end = start;
8445 else if (end > top_range && ! dragging)
8446 end = top_range;
8447
8448 /* Store the adjusted setting in the scroll bar. */
8449 XSETINT (bar->start, start);
8450 XSETINT (bar->end, end);
8451
8452 /* Clip the end position, just for display. */
8453 if (end > top_range)
8454 end = top_range;
8455
8456 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8457 top positions, to make sure the handle is always at least that
8458 many pixels tall. */
8459 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8460
8461 SetControlMinimum (ch, 0);
8462 /* Don't inadvertently activate deactivated scroll bars */
8463 if (GetControlMaximum (ch) != -1)
8464 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8465 - (end - start));
8466 SetControlValue (ch, start);
8467#if TARGET_API_MAC_CARBON
8468 SetControlViewSize (ch, end - start);
1a578e9b 8469#endif
1a578e9b
AC
8470
8471 UNBLOCK_INPUT;
8472}
8473
8474
8475/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8476 nil. */
8477
8478static void
8479x_scroll_bar_remove (bar)
8480 struct scroll_bar *bar;
8481{
8482 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba 8483
1a578e9b
AC
8484 BLOCK_INPUT;
8485
8486 /* Destroy the Mac scroll bar control */
8487 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8488
8489 /* Disassociate this scroll bar from its window. */
8490 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8491
8492 UNBLOCK_INPUT;
8493}
8494
1a578e9b
AC
8495/* Set the handle of the vertical scroll bar for WINDOW to indicate
8496 that we are displaying PORTION characters out of a total of WHOLE
8497 characters, starting at POSITION. If WINDOW has no scroll bar,
8498 create one. */
1a578e9b
AC
8499static void
8500XTset_vertical_scroll_bar (w, portion, whole, position)
8501 struct window *w;
8502 int portion, whole, position;
8503{
8504 struct frame *f = XFRAME (w->frame);
8505 struct scroll_bar *bar;
8506 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8507 int window_x, window_y, window_width, window_height;
8508
8509 /* Get window dimensions. */
8510 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8511 top = window_y;
e0f712ba
AC
8512#ifdef MAC_OSX
8513 width = 16;
8514#else
1a578e9b 8515 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
e0f712ba 8516#endif
1a578e9b
AC
8517 height = window_height;
8518
8519 /* Compute the left edge of the scroll bar area. */
8520 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8521 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8522 else
8523 left = XFASTINT (w->left);
8524 left *= CANON_X_UNIT (f);
8525 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8526
8527 /* Compute the width of the scroll bar which might be less than
8528 the width of the area reserved for the scroll bar. */
8529 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8530 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8531 else
8532 sb_width = width;
8533
8534 /* Compute the left edge of the scroll bar. */
8535 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8536 sb_left = left + width - sb_width - (width - sb_width) / 2;
8537 else
8538 sb_left = left + (width - sb_width) / 2;
8539
8540 /* Adjustments according to Inside Macintosh to make it look nice */
8541 disp_top = top;
8542 disp_height = height;
8543 if (disp_top == 0)
8544 {
8545 disp_top = -1;
8546 disp_height++;
8547 }
8548 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8549 {
8550 disp_top++;
8551 disp_height--;
8552 }
8553
8554 if (sb_left + sb_width == PIXEL_WIDTH (f))
8555 sb_left++;
8556
8557 /* Does the scroll bar exist yet? */
8558 if (NILP (w->vertical_scroll_bar))
8559 {
8560 BLOCK_INPUT;
8561 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8562 left, top, width, height, 0);
8563 UNBLOCK_INPUT;
8564 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8565 disp_height);
8566 XSETVECTOR (w->vertical_scroll_bar, bar);
8567 }
8568 else
8569 {
8570 /* It may just need to be moved and resized. */
8571 ControlHandle ch;
8572
8573 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8574 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8575
8576 BLOCK_INPUT;
8577
8578 /* If already correctly positioned, do nothing. */
8579 if (XINT (bar->left) == sb_left
8580 && XINT (bar->top) == top
8581 && XINT (bar->width) == sb_width
8582 && XINT (bar->height) == height)
8583 Draw1Control (ch);
8584 else
8585 {
e0f712ba
AC
8586 /* Clear areas not covered by the scroll bar because it's not as
8587 wide as the area reserved for it . This makes sure a
8588 previous mode line display is cleared after C-x 2 C-x 1, for
8589 example. */
8590 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8591 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8592 left, top, area_width, height, 0);
8593
8594#if 0
1a578e9b
AC
8595 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8596 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8597 sb_left - 1, top, 1, height, 0);
e0f712ba 8598#endif
1a578e9b
AC
8599
8600 HideControl (ch);
8601 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8602 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8603 disp_height);
8604 ShowControl (ch);
8605
8606 /* Remember new settings. */
8607 XSETINT (bar->left, sb_left);
8608 XSETINT (bar->top, top);
8609 XSETINT (bar->width, sb_width);
8610 XSETINT (bar->height, height);
8611 }
8612
8613 UNBLOCK_INPUT;
8614 }
8615
8616 /* Set the scroll bar's current state, unless we're currently being
8617 dragged. */
8618 if (NILP (bar->dragging))
8619 {
8620 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8621
8622 if (whole == 0)
8623 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8624 else
8625 {
8626 int start = ((double) position * top_range) / whole;
8627 int end = ((double) (position + portion) * top_range) / whole;
8628 x_scroll_bar_set_handle (bar, start, end, 0);
8629 }
8630 }
8631}
8632
8633
8634/* The following three hooks are used when we're doing a thorough
8635 redisplay of the frame. We don't explicitly know which scroll bars
8636 are going to be deleted, because keeping track of when windows go
8637 away is a real pain - "Can you say set-window-configuration, boys
8638 and girls?" Instead, we just assert at the beginning of redisplay
8639 that *all* scroll bars are to be removed, and then save a scroll bar
8640 from the fiery pit when we actually redisplay its window. */
8641
8642/* Arrange for all scroll bars on FRAME to be removed at the next call
8643 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8644 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8645
8646static void
8647XTcondemn_scroll_bars (frame)
8648 FRAME_PTR frame;
8649{
8650 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8651 while (! NILP (FRAME_SCROLL_BARS (frame)))
8652 {
8653 Lisp_Object bar;
8654 bar = FRAME_SCROLL_BARS (frame);
8655 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8656 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8657 XSCROLL_BAR (bar)->prev = Qnil;
8658 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8659 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8660 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8661 }
8662}
8663
e0f712ba 8664
1a578e9b
AC
8665/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8666 Note that WINDOW isn't necessarily condemned at all. */
e0f712ba 8667
1a578e9b
AC
8668static void
8669XTredeem_scroll_bar (window)
8670 struct window *window;
8671{
8672 struct scroll_bar *bar;
8673
8674 /* We can't redeem this window's scroll bar if it doesn't have one. */
8675 if (NILP (window->vertical_scroll_bar))
8676 abort ();
8677
8678 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8679
8680 /* Unlink it from the condemned list. */
8681 {
8682 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8683
8684 if (NILP (bar->prev))
8685 {
8686 /* If the prev pointer is nil, it must be the first in one of
8687 the lists. */
8688 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8689 /* It's not condemned. Everything's fine. */
8690 return;
8691 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8692 window->vertical_scroll_bar))
8693 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8694 else
8695 /* If its prev pointer is nil, it must be at the front of
8696 one or the other! */
8697 abort ();
8698 }
8699 else
8700 XSCROLL_BAR (bar->prev)->next = bar->next;
8701
8702 if (! NILP (bar->next))
8703 XSCROLL_BAR (bar->next)->prev = bar->prev;
8704
8705 bar->next = FRAME_SCROLL_BARS (f);
8706 bar->prev = Qnil;
8707 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8708 if (! NILP (bar->next))
8709 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8710 }
8711}
8712
8713/* Remove all scroll bars on FRAME that haven't been saved since the
8714 last call to `*condemn_scroll_bars_hook'. */
8715
8716static void
8717XTjudge_scroll_bars (f)
8718 FRAME_PTR f;
8719{
8720 Lisp_Object bar, next;
8721
8722 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8723
8724 /* Clear out the condemned list now so we won't try to process any
8725 more events on the hapless scroll bars. */
8726 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8727
8728 for (; ! NILP (bar); bar = next)
8729 {
8730 struct scroll_bar *b = XSCROLL_BAR (bar);
8731
8732 x_scroll_bar_remove (b);
8733
8734 next = b->next;
8735 b->next = b->prev = Qnil;
8736 }
8737
8738 /* Now there should be no references to the condemned scroll bars,
8739 and they should get garbage-collected. */
8740}
8741
8742
8743static void
8744activate_scroll_bars (frame)
8745 FRAME_PTR frame;
8746{
8747 Lisp_Object bar;
8748 ControlHandle ch;
8749
8750 bar = FRAME_SCROLL_BARS (frame);
8751 while (! NILP (bar))
8752 {
8753 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
e0f712ba
AC
8754#ifdef TARGET_API_MAC_CARBON
8755 ActivateControl (ch);
8756#else
1a578e9b
AC
8757 SetControlMaximum (ch,
8758 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8759 XINT (XSCROLL_BAR (bar)
8760 ->height)) - 1);
e0f712ba 8761#endif
1a578e9b
AC
8762 bar = XSCROLL_BAR (bar)->next;
8763 }
8764}
8765
8766
8767static void
8768deactivate_scroll_bars (frame)
8769 FRAME_PTR frame;
8770{
8771 Lisp_Object bar;
8772 ControlHandle ch;
8773
8774 bar = FRAME_SCROLL_BARS (frame);
8775 while (! NILP (bar))
8776 {
8777 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
e0f712ba
AC
8778#ifdef TARGET_API_MAC_CARBON
8779 DeactivateControl (ch);
8780#else
1a578e9b 8781 SetControlMaximum (ch, XINT (-1));
e0f712ba 8782#endif
1a578e9b
AC
8783 bar = XSCROLL_BAR (bar)->next;
8784 }
8785}
8786
8787/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3b8f9651 8788 is set to something other than NO_EVENT, it is enqueued.
1a578e9b
AC
8789
8790 This may be called from a signal handler, so we have to ignore GC
8791 mark bits. */
8792
8793static void
8794x_scroll_bar_handle_click (bar, part_code, er, bufp)
8795 struct scroll_bar *bar;
8796 int part_code;
8797 EventRecord *er;
8798 struct input_event *bufp;
8799{
8800 if (! GC_WINDOWP (bar->window))
8801 abort ();
8802
3b8f9651 8803 bufp->kind = SCROLL_BAR_CLICK_EVENT;
1a578e9b
AC
8804 bufp->frame_or_window = bar->window;
8805 bufp->arg = Qnil;
8806
8807 bar->dragging = Qnil;
8808
8809 switch (part_code)
8810 {
8811 case kControlUpButtonPart:
8812 bufp->part = scroll_bar_up_arrow;
8813 break;
8814 case kControlDownButtonPart:
8815 bufp->part = scroll_bar_down_arrow;
8816 break;
8817 case kControlPageUpPart:
8818 bufp->part = scroll_bar_above_handle;
8819 break;
8820 case kControlPageDownPart:
8821 bufp->part = scroll_bar_below_handle;
8822 break;
e0f712ba
AC
8823#ifdef TARGET_API_MAC_CARBON
8824 default:
8825#else
1a578e9b 8826 case kControlIndicatorPart:
e0f712ba 8827#endif
1a578e9b
AC
8828 if (er->what == mouseDown)
8829 bar->dragging = make_number (0);
8830 XSETVECTOR (last_mouse_scroll_bar, bar);
8831 bufp->part = scroll_bar_handle;
8832 break;
8833 }
8834}
8835
8836
8837/* Handle some mouse motion while someone is dragging the scroll bar.
8838
8839 This may be called from a signal handler, so we have to ignore GC
8840 mark bits. */
8841
8842static void
8843x_scroll_bar_note_movement (bar, y_pos, t)
8844 struct scroll_bar *bar;
8845 int y_pos;
8846 Time t;
8847{
8848 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8849
8850 last_mouse_movement_time = t;
8851
8852 f->mouse_moved = 1;
8853 XSETVECTOR (last_mouse_scroll_bar, bar);
8854
8855 /* If we're dragging the bar, display it. */
8856 if (! GC_NILP (bar->dragging))
8857 {
8858 /* Where should the handle be now? */
8859 int new_start = y_pos - 24;
8860
8861 if (new_start != XINT (bar->start))
8862 {
8863 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8864
8865 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8866 }
8867 }
8868}
8869
8870
8871/* Return information to the user about the current position of the
8872 mouse on the scroll bar. */
8873
8874static void
8875x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8876 FRAME_PTR *fp;
8877 Lisp_Object *bar_window;
8878 enum scroll_bar_part *part;
8879 Lisp_Object *x, *y;
8880 unsigned long *time;
8881{
8882 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8883 WindowPtr wp = FrontWindow ();
8884 Point mouse_pos;
8885 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8886 int win_y, top_range;
8887
e0f712ba
AC
8888#if TARGET_API_MAC_CARBON
8889 SetPort (GetWindowPort (wp));
8890#else
1a578e9b 8891 SetPort (wp);
e0f712ba
AC
8892#endif
8893
1a578e9b
AC
8894 GetMouse (&mouse_pos);
8895
8896 win_y = mouse_pos.v - XINT (bar->top);
8897 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8898
8899 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8900
8901 win_y -= 24;
8902
8903 if (! NILP (bar->dragging))
8904 win_y -= XINT (bar->dragging);
8905
8906 if (win_y < 0)
8907 win_y = 0;
8908 if (win_y > top_range)
8909 win_y = top_range;
8910
8911 *fp = f;
8912 *bar_window = bar->window;
8913
8914 if (! NILP (bar->dragging))
8915 *part = scroll_bar_handle;
8916 else if (win_y < XINT (bar->start))
8917 *part = scroll_bar_above_handle;
8918 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8919 *part = scroll_bar_handle;
8920 else
8921 *part = scroll_bar_below_handle;
8922
8923 XSETINT (*x, win_y);
8924 XSETINT (*y, top_range);
8925
8926 f->mouse_moved = 0;
8927 last_mouse_scroll_bar = Qnil;
8928
8929 *time = last_mouse_movement_time;
8930}
8931\f
8932/***********************************************************************
8933 Text Cursor
8934 ***********************************************************************/
8935
e0f712ba
AC
8936/* Notice if the text cursor of window W has been overwritten by a
8937 drawing operation that outputs glyphs starting at START_X and
8938 ending at END_X in the line given by output_cursor.vpos.
8939 Coordinates are area-relative. END_X < 0 means all the rest
8940 of the line after START_X has been written. */
1a578e9b
AC
8941
8942static void
e0f712ba 8943notice_overwritten_cursor (w, area, x0, x1, y0, y1)
1a578e9b 8944 struct window *w;
e0f712ba
AC
8945 enum glyph_row_area area;
8946 int x0, x1, y0, y1;
8947{
8948 if (area == TEXT_AREA
8949 && w->phys_cursor_on_p
8950 && y0 <= w->phys_cursor.y
8951 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8952 && x0 <= w->phys_cursor.x
8953 && (x1 < 0 || x1 > w->phys_cursor.x))
1a578e9b
AC
8954 w->phys_cursor_on_p = 0;
8955}
8956
8957
8958/* Set clipping for output in glyph row ROW. W is the window in which
8959 we operate. GC is the graphics context to set clipping in.
8960 WHOLE_LINE_P non-zero means include the areas used for truncation
8961 mark display and alike in the clipping rectangle.
8962
8963 ROW may be a text row or, e.g., a mode line. Text rows must be
8964 clipped to the interior of the window dedicated to text display,
8965 mode lines must be clipped to the whole window. */
8966
8967static void
8968x_clip_to_row (w, row, gc, whole_line_p)
8969 struct window *w;
8970 struct glyph_row *row;
8971 GC gc;
8972 int whole_line_p;
8973{
8974 struct frame *f = XFRAME (WINDOW_FRAME (w));
8975 Rect clip_rect;
8976 int window_x, window_y, window_width, window_height;
8977
8978 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8979
8980 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8981 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8982 clip_rect.top = max (clip_rect.top, window_y);
8983 clip_rect.right = clip_rect.left + window_width;
8984 clip_rect.bottom = clip_rect.top + row->visible_height;
8985
8986 /* If clipping to the whole line, including trunc marks, extend
8987 the rectangle to the left and increase its width. */
8988 if (whole_line_p)
8989 {
3f332ef3
KS
8990 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8991 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
1a578e9b
AC
8992 }
8993
8994 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8995}
8996
8997
8998/* Draw a hollow box cursor on window W in glyph row ROW. */
8999
9000static void
9001x_draw_hollow_cursor (w, row)
9002 struct window *w;
9003 struct glyph_row *row;
9004{
9005 struct frame *f = XFRAME (WINDOW_FRAME (w));
9006 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9007 Display *dpy = FRAME_MAC_DISPLAY (f);
9008 int x, y, wd, h;
9009 XGCValues xgcv;
9010 struct glyph *cursor_glyph;
9011 GC gc;
9012
9013 /* Compute frame-relative coordinates from window-relative
9014 coordinates. */
9015 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9016 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9017 + row->ascent - w->phys_cursor_ascent);
9018 h = row->height - 1;
9019
9020 /* Get the glyph the cursor is on. If we can't tell because
9021 the current matrix is invalid or such, give up. */
9022 cursor_glyph = get_phys_cursor_glyph (w);
9023 if (cursor_glyph == NULL)
9024 return;
9025
9026 /* Compute the width of the rectangle to draw. If on a stretch
9027 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9028 rectangle as wide as the glyph, but use a canonical character
9029 width instead. */
9030 wd = cursor_glyph->pixel_width - 1;
9031 if (cursor_glyph->type == STRETCH_GLYPH
9032 && !x_stretch_cursor_p)
9033 wd = min (CANON_X_UNIT (f), wd);
9034
9035 /* The foreground of cursor_gc is typically the same as the normal
9036 background color, which can cause the cursor box to be invisible. */
9037 xgcv.foreground = f->output_data.mac->cursor_pixel;
9038 if (dpyinfo->scratch_cursor_gc)
9039 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
9040 else
9041 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
9042 GCForeground, &xgcv);
9043 gc = dpyinfo->scratch_cursor_gc;
9044
9045 /* Set clipping, draw the rectangle, and reset clipping again. */
9046 x_clip_to_row (w, row, gc, 0);
9047 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
9048 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9049}
9050
9051
9052/* Draw a bar cursor on window W in glyph row ROW.
9053
9054 Implementation note: One would like to draw a bar cursor with an
9055 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9056 Unfortunately, I didn't find a font yet that has this property set.
9057 --gerd. */
9058
9059static void
9060x_draw_bar_cursor (w, row, width)
9061 struct window *w;
9062 struct glyph_row *row;
9063 int width;
9064{
9065 /* If cursor hpos is out of bounds, don't draw garbage. This can
9066 happen in mini-buffer windows when switching between echo area
9067 glyphs and mini-buffer. */
9068 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9069 {
9070 struct frame *f = XFRAME (w->frame);
9071 struct glyph *cursor_glyph;
9072 GC gc;
9073 int x;
9074 unsigned long mask;
9075 XGCValues xgcv;
9076 Display *dpy;
9077 Window window;
9078
9079 cursor_glyph = get_phys_cursor_glyph (w);
9080 if (cursor_glyph == NULL)
9081 return;
9082
9083 xgcv.background = f->output_data.mac->cursor_pixel;
9084 xgcv.foreground = f->output_data.mac->cursor_pixel;
9085 mask = GCForeground | GCBackground;
9086 dpy = FRAME_MAC_DISPLAY (f);
9087 window = FRAME_MAC_WINDOW (f);
9088 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9089
9090 if (gc)
9091 XChangeGC (dpy, gc, mask, &xgcv);
9092 else
9093 {
9094 gc = XCreateGC (dpy, window, mask, &xgcv);
9095 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9096 }
9097
9098 if (width < 0)
668e2d32 9099 width = FRAME_CURSOR_WIDTH (f);
1a578e9b
AC
9100
9101 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9102 x_clip_to_row (w, row, gc, 0);
9103 XFillRectangle (dpy, window, gc,
9104 x,
9105 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9106 min (cursor_glyph->pixel_width, width),
9107 row->height);
9108 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9109 }
9110}
9111
9112
9113/* Clear the cursor of window W to background color, and mark the
9114 cursor as not shown. This is used when the text where the cursor
9115 is is about to be rewritten. */
9116
9117static void
9118x_clear_cursor (w)
9119 struct window *w;
9120{
9121 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9122 x_update_window_cursor (w, 0);
9123}
9124
9125
9126/* Draw the cursor glyph of window W in glyph row ROW. See the
9127 comment of x_draw_glyphs for the meaning of HL. */
9128
9129static void
9130x_draw_phys_cursor_glyph (w, row, hl)
9131 struct window *w;
9132 struct glyph_row *row;
9133 enum draw_glyphs_face hl;
9134{
9135 /* If cursor hpos is out of bounds, don't draw garbage. This can
9136 happen in mini-buffer windows when switching between echo area
9137 glyphs and mini-buffer. */
9138 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9139 {
e0f712ba 9140 int on_p = w->phys_cursor_on_p;
1a578e9b 9141 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
e0f712ba
AC
9142 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9143 hl, 0);
9144 w->phys_cursor_on_p = on_p;
1a578e9b
AC
9145
9146 /* When we erase the cursor, and ROW is overlapped by other
9147 rows, make sure that these overlapping parts of other rows
9148 are redrawn. */
9149 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9150 {
9151 if (row > w->current_matrix->rows
9152 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9153 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9154
9155 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9156 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9157 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9158 }
9159 }
9160}
9161
9162
9163/* Erase the image of a cursor of window W from the screen. */
9164
9165static void
9166x_erase_phys_cursor (w)
9167 struct window *w;
9168{
9169 struct frame *f = XFRAME (w->frame);
9170 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9171 int hpos = w->phys_cursor.hpos;
9172 int vpos = w->phys_cursor.vpos;
9173 int mouse_face_here_p = 0;
9174 struct glyph_matrix *active_glyphs = w->current_matrix;
9175 struct glyph_row *cursor_row;
9176 struct glyph *cursor_glyph;
9177 enum draw_glyphs_face hl;
9178
9179 /* No cursor displayed or row invalidated => nothing to do on the
9180 screen. */
9181 if (w->phys_cursor_type == NO_CURSOR)
9182 goto mark_cursor_off;
9183
9184 /* VPOS >= active_glyphs->nrows means that window has been resized.
9185 Don't bother to erase the cursor. */
9186 if (vpos >= active_glyphs->nrows)
9187 goto mark_cursor_off;
9188
9189 /* If row containing cursor is marked invalid, there is nothing we
9190 can do. */
9191 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9192 if (!cursor_row->enabled_p)
9193 goto mark_cursor_off;
9194
796d4ec7 9195 /* If row is completely invisible, don't attempt to delete a cursor which
e0f712ba 9196 isn't there. This may happen if cursor is at top of window, and
796d4ec7
KS
9197 we switch to a buffer with a header line in that window. */
9198 if (cursor_row->visible_height <= 0)
9199 goto mark_cursor_off;
9200
1a578e9b
AC
9201 /* This can happen when the new row is shorter than the old one.
9202 In this case, either x_draw_glyphs or clear_end_of_line
9203 should have cleared the cursor. Note that we wouldn't be
9204 able to erase the cursor in this case because we don't have a
9205 cursor glyph at hand. */
9206 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9207 goto mark_cursor_off;
9208
9209 /* If the cursor is in the mouse face area, redisplay that when
9210 we clear the cursor. */
9211 if (! NILP (dpyinfo->mouse_face_window)
9212 && w == XWINDOW (dpyinfo->mouse_face_window)
9213 && (vpos > dpyinfo->mouse_face_beg_row
9214 || (vpos == dpyinfo->mouse_face_beg_row
9215 && hpos >= dpyinfo->mouse_face_beg_col))
9216 && (vpos < dpyinfo->mouse_face_end_row
9217 || (vpos == dpyinfo->mouse_face_end_row
9218 && hpos < dpyinfo->mouse_face_end_col))
9219 /* Don't redraw the cursor's spot in mouse face if it is at the
9220 end of a line (on a newline). The cursor appears there, but
9221 mouse highlighting does not. */
9222 && cursor_row->used[TEXT_AREA] > hpos)
9223 mouse_face_here_p = 1;
9224
9225 /* Maybe clear the display under the cursor. */
9226 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9227 {
9228 int x;
9229 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9230
9231 cursor_glyph = get_phys_cursor_glyph (w);
9232 if (cursor_glyph == NULL)
9233 goto mark_cursor_off;
9234
9235 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9236
9237 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9238 x,
9239 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9240 cursor_row->y)),
9241 cursor_glyph->pixel_width,
9242 cursor_row->visible_height,
9243 0);
9244 }
9245
9246 /* Erase the cursor by redrawing the character underneath it. */
9247 if (mouse_face_here_p)
9248 hl = DRAW_MOUSE_FACE;
1a578e9b
AC
9249 else
9250 hl = DRAW_NORMAL_TEXT;
9251 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9252
9253 mark_cursor_off:
9254 w->phys_cursor_on_p = 0;
9255 w->phys_cursor_type = NO_CURSOR;
9256}
9257
9258
e0f712ba
AC
9259/* Non-zero if physical cursor of window W is within mouse face. */
9260
9261static int
9262cursor_in_mouse_face_p (w)
9263 struct window *w;
9264{
9265 struct mac_display_info *dpyinfo
9266 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9267 int in_mouse_face = 0;
9268
9269 if (WINDOWP (dpyinfo->mouse_face_window)
9270 && XWINDOW (dpyinfo->mouse_face_window) == w)
9271 {
9272 int hpos = w->phys_cursor.hpos;
9273 int vpos = w->phys_cursor.vpos;
9274
9275 if (vpos >= dpyinfo->mouse_face_beg_row
9276 && vpos <= dpyinfo->mouse_face_end_row
9277 && (vpos > dpyinfo->mouse_face_beg_row
9278 || hpos >= dpyinfo->mouse_face_beg_col)
9279 && (vpos < dpyinfo->mouse_face_end_row
9280 || hpos < dpyinfo->mouse_face_end_col
9281 || dpyinfo->mouse_face_past_end))
9282 in_mouse_face = 1;
9283 }
9284
9285 return in_mouse_face;
9286}
9287
9288
1a578e9b
AC
9289/* Display or clear cursor of window W. If ON is zero, clear the
9290 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9291 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9292
9293void
9294x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9295 struct window *w;
9296 int on, hpos, vpos, x, y;
9297{
9298 struct frame *f = XFRAME (w->frame);
9299 int new_cursor_type;
9300 int new_cursor_width;
9301 struct glyph_matrix *current_glyphs;
9302 struct glyph_row *glyph_row;
9303 struct glyph *glyph;
9304
9305 /* This is pointless on invisible frames, and dangerous on garbaged
9306 windows and frames; in the latter case, the frame or window may
9307 be in the midst of changing its size, and x and y may be off the
9308 window. */
9309 if (! FRAME_VISIBLE_P (f)
9310 || FRAME_GARBAGED_P (f)
9311 || vpos >= w->current_matrix->nrows
9312 || hpos >= w->current_matrix->matrix_w)
9313 return;
9314
9315 /* If cursor is off and we want it off, return quickly. */
9316 if (!on && !w->phys_cursor_on_p)
9317 return;
9318
9319 current_glyphs = w->current_matrix;
9320 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9321 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9322
9323 /* If cursor row is not enabled, we don't really know where to
9324 display the cursor. */
9325 if (!glyph_row->enabled_p)
9326 {
9327 w->phys_cursor_on_p = 0;
9328 return;
9329 }
9330
9331 xassert (interrupt_input_blocked);
9332
668e2d32
KS
9333 /* Set new_cursor_type to the cursor we want to be displayed. */
9334 new_cursor_type = get_window_cursor_type (w, &new_cursor_width);
e0f712ba 9335
1a578e9b
AC
9336
9337 /* If cursor is currently being shown and we don't want it to be or
9338 it is in the wrong place, or the cursor type is not what we want,
9339 erase it. */
9340 if (w->phys_cursor_on_p
9341 && (!on
9342 || w->phys_cursor.x != x
9343 || w->phys_cursor.y != y
e0f712ba 9344 || new_cursor_type != w->phys_cursor_type
668e2d32 9345 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
e0f712ba 9346 && new_cursor_width != w->phys_cursor_width)))
1a578e9b
AC
9347 x_erase_phys_cursor (w);
9348
9349 /* If the cursor is now invisible and we want it to be visible,
9350 display it. */
9351 if (on && !w->phys_cursor_on_p)
9352 {
9353 w->phys_cursor_ascent = glyph_row->ascent;
9354 w->phys_cursor_height = glyph_row->height;
9355
9356 /* Set phys_cursor_.* before x_draw_.* is called because some
9357 of them may need the information. */
9358 w->phys_cursor.x = x;
9359 w->phys_cursor.y = glyph_row->y;
9360 w->phys_cursor.hpos = hpos;
9361 w->phys_cursor.vpos = vpos;
9362 w->phys_cursor_type = new_cursor_type;
e0f712ba 9363 w->phys_cursor_width = new_cursor_width;
1a578e9b
AC
9364 w->phys_cursor_on_p = 1;
9365
9366 switch (new_cursor_type)
9367 {
9368 case HOLLOW_BOX_CURSOR:
9369 x_draw_hollow_cursor (w, glyph_row);
9370 break;
9371
9372 case FILLED_BOX_CURSOR:
9373 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9374 break;
9375
668e2d32
KS
9376 case HBAR_CURSOR:
9377 /* TODO. For now, just draw bar cursor. */
1a578e9b
AC
9378 case BAR_CURSOR:
9379 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9380 break;
9381
9382 case NO_CURSOR:
9383 break;
9384
9385 default:
9386 abort ();
9387 }
1a578e9b 9388 }
1a578e9b
AC
9389}
9390
9391
9392/* Display the cursor on window W, or clear it. X and Y are window
9393 relative pixel coordinates. HPOS and VPOS are glyph matrix
9394 positions. If W is not the selected window, display a hollow
9395 cursor. ON non-zero means display the cursor at X, Y which
9396 correspond to HPOS, VPOS, otherwise it is cleared. */
9397
9398void
9399x_display_cursor (w, on, hpos, vpos, x, y)
9400 struct window *w;
9401 int on, hpos, vpos, x, y;
9402{
9403 BLOCK_INPUT;
9404 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9405 UNBLOCK_INPUT;
9406}
9407
9408
9409/* Display the cursor on window W, or clear it, according to ON_P.
9410 Don't change the cursor's position. */
9411
9412void
9413x_update_cursor (f, on_p)
9414 struct frame *f;
e0f712ba 9415 int on_p;
1a578e9b
AC
9416{
9417 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9418}
9419
9420
9421/* Call x_update_window_cursor with parameter ON_P on all leaf windows
9422 in the window tree rooted at W. */
9423
9424static void
9425x_update_cursor_in_window_tree (w, on_p)
9426 struct window *w;
9427 int on_p;
9428{
9429 while (w)
9430 {
9431 if (!NILP (w->hchild))
9432 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9433 else if (!NILP (w->vchild))
9434 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9435 else
9436 x_update_window_cursor (w, on_p);
9437
9438 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9439 }
9440}
9441
9442
9443/* Switch the display of W's cursor on or off, according to the value
9444 of ON. */
9445
9446static void
9447x_update_window_cursor (w, on)
9448 struct window *w;
9449 int on;
9450{
9451 /* Don't update cursor in windows whose frame is in the process
9452 of being deleted. */
9453 if (w->current_matrix)
9454 {
9455 BLOCK_INPUT;
e0f712ba
AC
9456 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9457 w->phys_cursor.vpos, w->phys_cursor.x,
9458 w->phys_cursor.y);
1a578e9b
AC
9459 UNBLOCK_INPUT;
9460 }
9461}
9462
1a578e9b 9463
1a578e9b 9464
e0f712ba
AC
9465\f
9466/* Icons. */
1a578e9b 9467
e0f712ba 9468#if 0 /* MAC_TODO: no icon support yet. */
1a578e9b 9469int
e0f712ba 9470x_bitmap_icon (f, icon)
1a578e9b 9471 struct frame *f;
e0f712ba 9472 Lisp_Object icon;
1a578e9b 9473{
e0f712ba 9474 HANDLE hicon;
1a578e9b 9475
e0f712ba 9476 if (FRAME_W32_WINDOW (f) == 0)
1a578e9b
AC
9477 return 1;
9478
e0f712ba
AC
9479 if (NILP (icon))
9480 hicon = LoadIcon (hinst, EMACS_CLASS);
9481 else if (STRINGP (icon))
d5db4077 9482 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
e0f712ba
AC
9483 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9484 else if (SYMBOLP (icon))
9485 {
9486 LPCTSTR name;
9487
9488 if (EQ (icon, intern ("application")))
9489 name = (LPCTSTR) IDI_APPLICATION;
9490 else if (EQ (icon, intern ("hand")))
9491 name = (LPCTSTR) IDI_HAND;
9492 else if (EQ (icon, intern ("question")))
9493 name = (LPCTSTR) IDI_QUESTION;
9494 else if (EQ (icon, intern ("exclamation")))
9495 name = (LPCTSTR) IDI_EXCLAMATION;
9496 else if (EQ (icon, intern ("asterisk")))
9497 name = (LPCTSTR) IDI_ASTERISK;
9498 else if (EQ (icon, intern ("winlogo")))
9499 name = (LPCTSTR) IDI_WINLOGO;
9500 else
9501 return 1;
1a578e9b 9502
e0f712ba 9503 hicon = LoadIcon (NULL, name);
1a578e9b 9504 }
e0f712ba 9505 else
1a578e9b
AC
9506 return 1;
9507
e0f712ba
AC
9508 if (hicon == NULL)
9509 return 1;
1a578e9b 9510
e0f712ba
AC
9511 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9512 (LPARAM) hicon);
1a578e9b
AC
9513
9514 return 0;
9515}
e0f712ba 9516#endif /* MAC_TODO */
1a578e9b 9517\f
e0f712ba
AC
9518/************************************************************************
9519 Handling X errors
9520 ************************************************************************/
1a578e9b 9521
e0f712ba
AC
9522/* Display Error Handling functions not used on W32. Listing them here
9523 helps diff stay in step when comparing w32term.c with xterm.c.
1a578e9b 9524
1a578e9b 9525x_error_catcher (display, error)
1a578e9b 9526x_catch_errors (dpy)
1a578e9b 9527x_catch_errors_unwind (old_val)
1a578e9b 9528x_check_errors (dpy, format)
1a578e9b 9529x_had_errors_p (dpy)
1a578e9b 9530x_clear_errors (dpy)
1a578e9b 9531x_uncatch_errors (dpy, count)
1a578e9b 9532x_trace_wire ()
e0f712ba
AC
9533x_connection_signal (signalnum)
9534x_connection_closed (dpy, error_message)
1a578e9b 9535x_error_quitter (display, error)
1a578e9b 9536x_error_handler (display, error)
1a578e9b 9537x_io_error_quitter (display)
1a578e9b 9538
e0f712ba
AC
9539 */
9540
1a578e9b
AC
9541\f
9542/* Changing the font of the frame. */
9543
9544/* Give frame F the font named FONTNAME as its default font, and
9545 return the full name of that font. FONTNAME may be a wildcard
9546 pattern; in that case, we choose some font that fits the pattern.
9547 The return value shows which font we chose. */
9548
9549Lisp_Object
9550x_new_font (f, fontname)
9551 struct frame *f;
9552 register char *fontname;
9553{
9554 struct font_info *fontp
9555 = FS_LOAD_FONT (f, 0, fontname, -1);
9556
9557 if (!fontp)
9558 return Qnil;
9559
e0f712ba
AC
9560 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9561 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9562 FRAME_FONTSET (f) = -1;
9563
1a578e9b
AC
9564 /* Compute the scroll bar width in character columns. */
9565 if (f->scroll_bar_pixel_width > 0)
9566 {
e0f712ba 9567 int wid = FONT_WIDTH (FRAME_FONT (f));
1a578e9b
AC
9568 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9569 }
9570 else
9571 {
e0f712ba 9572 int wid = FONT_WIDTH (FRAME_FONT (f));
1a578e9b
AC
9573 f->scroll_bar_cols = (14 + wid - 1) / wid;
9574 }
9575
9576 /* Now make the frame display the given font. */
9577 if (FRAME_MAC_WINDOW (f) != 0)
9578 {
f00691a3
AC
9579 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9580 f->output_data.mac->font);
9581 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9582 f->output_data.mac->font);
9583 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9584 f->output_data.mac->font);
9585
1a578e9b 9586 frame_update_line_height (f);
e0f712ba
AC
9587 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9588 x_set_window_size (f, 0, f->width, f->height);
1a578e9b
AC
9589 }
9590 else
e0f712ba
AC
9591 /* If we are setting a new frame's font for the first time,
9592 there are no faces yet, so this font's height is the line height. */
9593 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
1a578e9b
AC
9594
9595 return build_string (fontp->full_name);
9596}
e0f712ba 9597\f
1a578e9b 9598/* Give frame F the fontset named FONTSETNAME as its default font, and
e0f712ba
AC
9599 return the full name of that fontset. FONTSETNAME may be a wildcard
9600 pattern; in that case, we choose some fontset that fits the pattern.
9601 The return value shows which fontset we chose. */
1a578e9b
AC
9602
9603Lisp_Object
9604x_new_fontset (f, fontsetname)
9605 struct frame *f;
9606 char *fontsetname;
9607{
9608 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9609 Lisp_Object result;
9610
9611 if (fontset < 0)
9612 return Qnil;
9613
e0f712ba 9614 if (FRAME_FONTSET (f) == fontset)
1a578e9b
AC
9615 /* This fontset is already set in frame F. There's nothing more
9616 to do. */
9617 return fontset_name (fontset);
9618
d5db4077 9619 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
1a578e9b
AC
9620
9621 if (!STRINGP (result))
9622 /* Can't load ASCII font. */
9623 return Qnil;
9624
e0f712ba
AC
9625 /* Since x_new_font doesn't update any fontset information, do it now. */
9626 FRAME_FONTSET(f) = fontset;
1a578e9b 9627
1a578e9b
AC
9628 return build_string (fontsetname);
9629}
9630
d33c49e8
KS
9631/* Compute actual fringe widths */
9632
9633void
9634x_compute_fringe_widths (f, redraw)
9635 struct frame *f;
9636 int redraw;
9637{
9638 int o_left = f->output_data.mac->left_fringe_width;
9639 int o_right = f->output_data.mac->right_fringe_width;
9640 int o_cols = f->output_data.mac->fringe_cols;
9641
9642 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9643 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9644 int left_fringe_width, right_fringe_width;
9645
9646 if (!NILP (left_fringe))
9647 left_fringe = Fcdr (left_fringe);
9648 if (!NILP (right_fringe))
9649 right_fringe = Fcdr (right_fringe);
9650
9651 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9652 XINT (left_fringe));
9653 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9654 XINT (right_fringe));
9655
9656 if (left_fringe_width || right_fringe_width)
9657 {
9658 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9659 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9660 int conf_wid = left_wid + right_wid;
9661 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9662 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9663 int real_wid = cols * font_wid;
9664 if (left_wid && right_wid)
9665 {
9666 if (left_fringe_width < 0)
9667 {
9668 /* Left fringe width is fixed, adjust right fringe if necessary */
9669 f->output_data.mac->left_fringe_width = left_wid;
9670 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9671 }
9672 else if (right_fringe_width < 0)
9673 {
9674 /* Right fringe width is fixed, adjust left fringe if necessary */
9675 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9676 f->output_data.mac->right_fringe_width = right_wid;
9677 }
9678 else
9679 {
9680 /* Adjust both fringes with an equal amount.
9681 Note that we are doing integer arithmetic here, so don't
9682 lose a pixel if the total width is an odd number. */
9683 int fill = real_wid - conf_wid;
9684 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9685 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9686 }
9687 }
9688 else if (left_fringe_width)
9689 {
9690 f->output_data.mac->left_fringe_width = real_wid;
9691 f->output_data.mac->right_fringe_width = 0;
9692 }
9693 else
9694 {
9695 f->output_data.mac->left_fringe_width = 0;
9696 f->output_data.mac->right_fringe_width = real_wid;
9697 }
9698 f->output_data.mac->fringe_cols = cols;
9699 f->output_data.mac->fringes_extra = real_wid;
9700 }
9701 else
9702 {
9703 f->output_data.mac->left_fringe_width = 0;
9704 f->output_data.mac->right_fringe_width = 0;
9705 f->output_data.mac->fringe_cols = 0;
9706 f->output_data.mac->fringes_extra = 0;
9707 }
9708
9709 if (redraw && FRAME_VISIBLE_P (f))
9710 if (o_left != f->output_data.mac->left_fringe_width ||
9711 o_right != f->output_data.mac->right_fringe_width ||
9712 o_cols != f->output_data.mac->fringe_cols)
9713 redraw_frame (f);
9714}
1a578e9b
AC
9715\f
9716/***********************************************************************
e0f712ba 9717 TODO: W32 Input Methods
1a578e9b 9718 ***********************************************************************/
e0f712ba 9719/* Listing missing functions from xterm.c helps diff stay in step.
1a578e9b 9720
1a578e9b 9721xim_destroy_callback (xim, client_data, call_data)
1a578e9b 9722xim_open_dpy (dpyinfo, resource_name)
1a578e9b 9723struct xim_inst_t
1a578e9b 9724xim_instantiate_callback (display, client_data, call_data)
1a578e9b 9725xim_initialize (dpyinfo, resource_name)
1a578e9b 9726xim_close_dpy (dpyinfo)
1a578e9b 9727
e0f712ba 9728 */
1a578e9b 9729
1a578e9b
AC
9730\f
9731/* Calculate the absolute position in frame F
9732 from its current recorded position values and gravity. */
9733
e0f712ba 9734void
1a578e9b
AC
9735x_calc_absolute_position (f)
9736 struct frame *f;
9737{
9738 Point pt;
9739 int flags = f->output_data.mac->size_hint_flags;
9740
9741 pt.h = pt.v = 0;
9742
9743 /* Find the position of the outside upper-left corner of
9744 the inner window, with respect to the outer window. */
9745 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9746 {
9747 GrafPtr savePort;
9748 GetPort (&savePort);
e0f712ba
AC
9749
9750#if TARGET_API_MAC_CARBON
9751 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9752#else
1a578e9b 9753 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
9754#endif
9755
9756#if TARGET_API_MAC_CARBON
9757 {
9758 Rect r;
9759
9760 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9761 SetPt(&pt, r.left, r.top);
9762 }
9763#else /* not TARGET_API_MAC_CARBON */
1a578e9b 9764 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
e0f712ba 9765#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
9766 LocalToGlobal (&pt);
9767 SetPort (savePort);
9768 }
9769
9770 /* Treat negative positions as relative to the leftmost bottommost
9771 position that fits on the screen. */
9772 if (flags & XNegative)
9773 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9774 - 2 * f->output_data.mac->border_width - pt.h
9775 - PIXEL_WIDTH (f)
9776 + f->output_data.mac->left_pos);
9777 /* NTEMACS_TODO: Subtract menubar height? */
9778 if (flags & YNegative)
9779 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9780 - 2 * f->output_data.mac->border_width - pt.v
9781 - PIXEL_HEIGHT (f)
9782 + f->output_data.mac->top_pos);
9783 /* The left_pos and top_pos
9784 are now relative to the top and left screen edges,
9785 so the flags should correspond. */
9786 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9787}
9788
9789/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9790 to really change the position, and 0 when calling from
9791 x_make_frame_visible (in that case, XOFF and YOFF are the current
9792 position values). It is -1 when calling from x_set_frame_parameters,
9793 which means, do adjust for borders but don't change the gravity. */
9794
9795void
9796x_set_offset (f, xoff, yoff, change_gravity)
9797 struct frame *f;
9798 register int xoff, yoff;
9799 int change_gravity;
9800{
e0f712ba
AC
9801 int modified_top, modified_left;
9802
1a578e9b
AC
9803 if (change_gravity > 0)
9804 {
9805 f->output_data.mac->top_pos = yoff;
9806 f->output_data.mac->left_pos = xoff;
9807 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9808 if (xoff < 0)
9809 f->output_data.mac->size_hint_flags |= XNegative;
9810 if (yoff < 0)
9811 f->output_data.mac->size_hint_flags |= YNegative;
9812 f->output_data.mac->win_gravity = NorthWestGravity;
9813 }
9814 x_calc_absolute_position (f);
9815
9816 BLOCK_INPUT;
9817 x_wm_set_size_hint (f, (long) 0, 0);
9818
e0f712ba
AC
9819 modified_left = f->output_data.mac->left_pos;
9820 modified_top = f->output_data.mac->top_pos;
9821
9822 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9823 modified_top + 42, false);
1a578e9b
AC
9824
9825 UNBLOCK_INPUT;
9826}
9827
9828/* Call this to change the size of frame F's x-window.
9829 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9830 for this size change and subsequent size changes.
9831 Otherwise we leave the window gravity unchanged. */
9832
9833void
9834x_set_window_size (f, change_gravity, cols, rows)
9835 struct frame *f;
9836 int change_gravity;
9837 int cols, rows;
9838{
9839 int pixelwidth, pixelheight;
e0f712ba
AC
9840
9841 BLOCK_INPUT;
9842
1a578e9b
AC
9843 check_frame_size (f, &rows, &cols);
9844 f->output_data.mac->vertical_scroll_bar_extra
9845 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9846 ? 0
1a578e9b 9847 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
d33c49e8
KS
9848
9849 x_compute_fringe_widths (f, 0);
9850
1a578e9b
AC
9851 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9852 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9853
9854 f->output_data.mac->win_gravity = NorthWestGravity;
9855 x_wm_set_size_hint (f, (long) 0, 0);
9856
9857 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9858
9859 /* Now, strictly speaking, we can't be sure that this is accurate,
9860 but the window manager will get around to dealing with the size
9861 change request eventually, and we'll hear how it went when the
9862 ConfigureNotify event gets here.
e0f712ba 9863
1a578e9b
AC
9864 We could just not bother storing any of this information here,
9865 and let the ConfigureNotify event set everything up, but that
9866 might be kind of confusing to the Lisp code, since size changes
9867 wouldn't be reported in the frame parameters until some random
9868 point in the future when the ConfigureNotify event arrives.
9869
9870 We pass 1 for DELAY since we can't run Lisp code inside of
9871 a BLOCK_INPUT. */
9872 change_frame_size (f, rows, cols, 0, 1, 0);
9873 PIXEL_WIDTH (f) = pixelwidth;
9874 PIXEL_HEIGHT (f) = pixelheight;
9875
9876 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9877 receive in the ConfigureNotify event; if we get what we asked
9878 for, then the event won't cause the screen to become garbaged, so
9879 we have to make sure to do it here. */
9880 SET_FRAME_GARBAGED (f);
9881
9882 XFlush (FRAME_X_DISPLAY (f));
9883
9884 /* If cursor was outside the new size, mark it as off. */
9885 mark_window_cursors_off (XWINDOW (f->root_window));
9886
9887 /* Clear out any recollection of where the mouse highlighting was,
9888 since it might be in a place that's outside the new frame size.
9889 Actually checking whether it is outside is a pain in the neck,
9890 so don't try--just let the highlighting be done afresh with new size. */
9891 cancel_mouse_face (f);
e0f712ba
AC
9892
9893 UNBLOCK_INPUT;
1a578e9b
AC
9894}
9895\f
9896/* Mouse warping. */
9897
9898void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9899
9900void
9901x_set_mouse_position (f, x, y)
9902 struct frame *f;
9903 int x, y;
9904{
9905 int pix_x, pix_y;
9906
9907 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9908 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9909
9910 if (pix_x < 0) pix_x = 0;
9911 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9912
9913 if (pix_y < 0) pix_y = 0;
9914 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9915
9916 x_set_mouse_pixel_position (f, pix_x, pix_y);
9917}
9918
1a578e9b
AC
9919void
9920x_set_mouse_pixel_position (f, pix_x, pix_y)
9921 struct frame *f;
9922 int pix_x, pix_y;
9923{
9924#if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9925 BLOCK_INPUT;
9926
9927 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9928 0, 0, 0, 0, pix_x, pix_y);
9929 UNBLOCK_INPUT;
9930#endif
9931}
e0f712ba 9932
1a578e9b
AC
9933\f
9934/* focus shifting, raising and lowering. */
9935
e0f712ba 9936void
1a578e9b
AC
9937x_focus_on_frame (f)
9938 struct frame *f;
9939{
9940#if 0 /* This proves to be unpleasant. */
9941 x_raise_frame (f);
9942#endif
9943#if 0
9944 /* I don't think that the ICCCM allows programs to do things like this
9945 without the interaction of the window manager. Whatever you end up
9946 doing with this code, do it to x_unfocus_frame too. */
9947 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9948 RevertToPointerRoot, CurrentTime);
9949#endif /* ! 0 */
9950}
9951
e0f712ba 9952void
1a578e9b
AC
9953x_unfocus_frame (f)
9954 struct frame *f;
9955{
1a578e9b
AC
9956}
9957
9958/* Raise frame F. */
1a578e9b
AC
9959void
9960x_raise_frame (f)
9961 struct frame *f;
9962{
9963 if (f->async_visible)
9964 SelectWindow (FRAME_MAC_WINDOW (f));
9965}
9966
9967/* Lower frame F. */
1a578e9b
AC
9968void
9969x_lower_frame (f)
9970 struct frame *f;
9971{
9972 if (f->async_visible)
9973 SendBehind (FRAME_MAC_WINDOW (f), nil);
9974}
9975
e0f712ba 9976static void
1a578e9b
AC
9977XTframe_raise_lower (f, raise_flag)
9978 FRAME_PTR f;
9979 int raise_flag;
9980{
9981 if (raise_flag)
9982 x_raise_frame (f);
9983 else
9984 x_lower_frame (f);
9985}
9986\f
9987/* Change of visibility. */
9988
9989/* This tries to wait until the frame is really visible.
9990 However, if the window manager asks the user where to position
9991 the frame, this will return before the user finishes doing that.
9992 The frame will not actually be visible at that time,
9993 but it will become visible later when the window manager
9994 finishes with it. */
9995
9996void
9997x_make_frame_visible (f)
9998 struct frame *f;
9999{
10000 Lisp_Object type;
10001 int original_top, original_left;
10002
10003 BLOCK_INPUT;
10004
10005 if (! FRAME_VISIBLE_P (f))
10006 {
10007 /* We test FRAME_GARBAGED_P here to make sure we don't
10008 call x_set_offset a second time
10009 if we get to x_make_frame_visible a second time
10010 before the window gets really visible. */
10011 if (! FRAME_ICONIFIED_P (f)
10012 && ! f->output_data.mac->asked_for_visible)
10013 x_set_offset (f, f->output_data.mac->left_pos,
10014 f->output_data.mac->top_pos, 0);
10015
10016 f->output_data.mac->asked_for_visible = 1;
10017
10018 ShowWindow (FRAME_MAC_WINDOW (f));
10019 }
10020
10021 XFlush (FRAME_MAC_DISPLAY (f));
10022
e0f712ba 10023#if 0 /* MAC_TODO */
1a578e9b
AC
10024 /* Synchronize to ensure Emacs knows the frame is visible
10025 before we do anything else. We do this loop with input not blocked
10026 so that incoming events are handled. */
10027 {
10028 Lisp_Object frame;
10029 int count;
10030
10031 /* This must come after we set COUNT. */
10032 UNBLOCK_INPUT;
10033
10034 XSETFRAME (frame, f);
10035
10036 /* Wait until the frame is visible. Process X events until a
10037 MapNotify event has been seen, or until we think we won't get a
10038 MapNotify at all.. */
10039 for (count = input_signal_count + 10;
10040 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10041 {
10042 /* Force processing of queued events. */
10043 x_sync (f);
10044
10045 /* Machines that do polling rather than SIGIO have been
10046 observed to go into a busy-wait here. So we'll fake an
10047 alarm signal to let the handler know that there's something
10048 to be read. We used to raise a real alarm, but it seems
10049 that the handler isn't always enabled here. This is
10050 probably a bug. */
10051 if (input_polling_used ())
10052 {
10053 /* It could be confusing if a real alarm arrives while
10054 processing the fake one. Turn it off and let the
10055 handler reset it. */
10056 extern void poll_for_input_1 P_ ((void));
10057 int old_poll_suppress_count = poll_suppress_count;
10058 poll_suppress_count = 1;
10059 poll_for_input_1 ();
10060 poll_suppress_count = old_poll_suppress_count;
10061 }
10062
10063 /* See if a MapNotify event has been processed. */
10064 FRAME_SAMPLE_VISIBILITY (f);
10065 }
10066 }
e0f712ba 10067#endif /* MAC_TODO */
1a578e9b
AC
10068}
10069
10070/* Change from mapped state to withdrawn state. */
10071
10072/* Make the frame visible (mapped and not iconified). */
10073
10074void
10075x_make_frame_invisible (f)
10076 struct frame *f;
10077{
10078 /* Don't keep the highlight on an invisible frame. */
10079 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10080 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10081
10082 BLOCK_INPUT;
10083
10084 HideWindow (FRAME_MAC_WINDOW (f));
10085
10086 /* We can't distinguish this from iconification
10087 just by the event that we get from the server.
10088 So we can't win using the usual strategy of letting
10089 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10090 and synchronize with the server to make sure we agree. */
10091 f->visible = 0;
10092 FRAME_ICONIFIED_P (f) = 0;
10093 f->async_visible = 0;
10094 f->async_iconified = 0;
10095
10096 UNBLOCK_INPUT;
10097}
10098
10099/* Change window state from mapped to iconified. */
10100
10101void
10102x_iconify_frame (f)
10103 struct frame *f;
10104{
1a578e9b 10105 /* Don't keep the highlight on an invisible frame. */
742fbed7
AC
10106 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10107 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
1a578e9b 10108
742fbed7
AC
10109#if 0
10110 /* Review: Since window is still visible in dock, still allow updates? */
1a578e9b
AC
10111 if (f->async_iconified)
10112 return;
742fbed7 10113#endif
1a578e9b
AC
10114
10115 BLOCK_INPUT;
10116
742fbed7
AC
10117 CollapseWindow (FRAME_MAC_WINDOW (f), true);
10118
1a578e9b 10119 UNBLOCK_INPUT;
1a578e9b 10120}
e0f712ba 10121
1a578e9b
AC
10122\f
10123/* Destroy the X window of frame F. */
10124
10125void
10126x_destroy_window (f)
10127 struct frame *f;
10128{
10129 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10130
10131 BLOCK_INPUT;
10132
10133 DisposeWindow (FRAME_MAC_WINDOW (f));
10134
10135 free_frame_menubar (f);
10136 free_frame_faces (f);
10137
10138 xfree (f->output_data.mac);
10139 f->output_data.mac = 0;
10140 if (f == dpyinfo->x_focus_frame)
10141 dpyinfo->x_focus_frame = 0;
10142 if (f == dpyinfo->x_focus_event_frame)
10143 dpyinfo->x_focus_event_frame = 0;
10144 if (f == dpyinfo->x_highlight_frame)
10145 dpyinfo->x_highlight_frame = 0;
10146
10147 dpyinfo->reference_count--;
10148
10149 if (f == dpyinfo->mouse_face_mouse_frame)
10150 {
10151 dpyinfo->mouse_face_beg_row
10152 = dpyinfo->mouse_face_beg_col = -1;
10153 dpyinfo->mouse_face_end_row
10154 = dpyinfo->mouse_face_end_col = -1;
10155 dpyinfo->mouse_face_window = Qnil;
10156 dpyinfo->mouse_face_deferred_gc = 0;
10157 dpyinfo->mouse_face_mouse_frame = 0;
10158 }
10159
10160 UNBLOCK_INPUT;
10161}
10162\f
10163/* Setting window manager hints. */
10164
10165/* Set the normal size hints for the window manager, for frame F.
10166 FLAGS is the flags word to use--or 0 meaning preserve the flags
10167 that the window now has.
10168 If USER_POSITION is nonzero, we set the USPosition
10169 flag (this is useful when FLAGS is 0). */
1a578e9b
AC
10170void
10171x_wm_set_size_hint (f, flags, user_position)
10172 struct frame *f;
10173 long flags;
10174 int user_position;
10175{
10176#if 0 /* MAC_TODO: connect this to the Appearance Manager */
10177 XSizeHints size_hints;
10178
10179#ifdef USE_X_TOOLKIT
10180 Arg al[2];
10181 int ac = 0;
10182 Dimension widget_width, widget_height;
10183 Window window = XtWindow (f->output_data.x->widget);
10184#else /* not USE_X_TOOLKIT */
10185 Window window = FRAME_X_WINDOW (f);
10186#endif /* not USE_X_TOOLKIT */
10187
10188 /* Setting PMaxSize caused various problems. */
10189 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10190
10191 size_hints.x = f->output_data.x->left_pos;
10192 size_hints.y = f->output_data.x->top_pos;
10193
10194#ifdef USE_X_TOOLKIT
10195 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10196 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10197 XtGetValues (f->output_data.x->widget, al, ac);
10198 size_hints.height = widget_height;
10199 size_hints.width = widget_width;
10200#else /* not USE_X_TOOLKIT */
10201 size_hints.height = PIXEL_HEIGHT (f);
10202 size_hints.width = PIXEL_WIDTH (f);
10203#endif /* not USE_X_TOOLKIT */
10204
10205 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10206 size_hints.height_inc = f->output_data.x->line_height;
10207 size_hints.max_width
10208 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10209 size_hints.max_height
10210 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10211
10212 /* Calculate the base and minimum sizes.
10213
10214 (When we use the X toolkit, we don't do it here.
10215 Instead we copy the values that the widgets are using, below.) */
10216#ifndef USE_X_TOOLKIT
10217 {
10218 int base_width, base_height;
10219 int min_rows = 0, min_cols = 0;
10220
10221 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10222 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10223
10224 check_frame_size (f, &min_rows, &min_cols);
10225
10226 /* The window manager uses the base width hints to calculate the
10227 current number of rows and columns in the frame while
10228 resizing; min_width and min_height aren't useful for this
10229 purpose, since they might not give the dimensions for a
10230 zero-row, zero-column frame.
10231
10232 We use the base_width and base_height members if we have
10233 them; otherwise, we set the min_width and min_height members
10234 to the size for a zero x zero frame. */
10235
10236#ifdef HAVE_X11R4
10237 size_hints.flags |= PBaseSize;
10238 size_hints.base_width = base_width;
10239 size_hints.base_height = base_height;
10240 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10241 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10242#else
10243 size_hints.min_width = base_width;
10244 size_hints.min_height = base_height;
10245#endif
10246 }
10247
10248 /* If we don't need the old flags, we don't need the old hint at all. */
10249 if (flags)
10250 {
10251 size_hints.flags |= flags;
10252 goto no_read;
10253 }
10254#endif /* not USE_X_TOOLKIT */
10255
10256 {
10257 XSizeHints hints; /* Sometimes I hate X Windows... */
10258 long supplied_return;
10259 int value;
10260
10261#ifdef HAVE_X11R4
10262 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10263 &supplied_return);
10264#else
10265 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10266#endif
10267
10268#ifdef USE_X_TOOLKIT
10269 size_hints.base_height = hints.base_height;
10270 size_hints.base_width = hints.base_width;
10271 size_hints.min_height = hints.min_height;
10272 size_hints.min_width = hints.min_width;
10273#endif
10274
10275 if (flags)
10276 size_hints.flags |= flags;
10277 else
10278 {
10279 if (value == 0)
10280 hints.flags = 0;
10281 if (hints.flags & PSize)
10282 size_hints.flags |= PSize;
10283 if (hints.flags & PPosition)
10284 size_hints.flags |= PPosition;
10285 if (hints.flags & USPosition)
10286 size_hints.flags |= USPosition;
10287 if (hints.flags & USSize)
10288 size_hints.flags |= USSize;
10289 }
10290 }
10291
10292#ifndef USE_X_TOOLKIT
10293 no_read:
10294#endif
10295
10296#ifdef PWinGravity
10297 size_hints.win_gravity = f->output_data.x->win_gravity;
10298 size_hints.flags |= PWinGravity;
10299
10300 if (user_position)
10301 {
10302 size_hints.flags &= ~ PPosition;
10303 size_hints.flags |= USPosition;
10304 }
10305#endif /* PWinGravity */
10306
10307#ifdef HAVE_X11R4
10308 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10309#else
10310 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10311#endif
e0f712ba 10312#endif /* MAC_TODO */
1a578e9b
AC
10313}
10314
e0f712ba 10315#if 0 /* MAC_TODO: hide application instead of iconify? */
1a578e9b
AC
10316/* Used for IconicState or NormalState */
10317
10318void
10319x_wm_set_window_state (f, state)
10320 struct frame *f;
10321 int state;
10322{
10323#ifdef USE_X_TOOLKIT
10324 Arg al[1];
10325
10326 XtSetArg (al[0], XtNinitialState, state);
10327 XtSetValues (f->output_data.x->widget, al, 1);
10328#else /* not USE_X_TOOLKIT */
10329 Window window = FRAME_X_WINDOW (f);
10330
10331 f->output_data.x->wm_hints.flags |= StateHint;
10332 f->output_data.x->wm_hints.initial_state = state;
10333
10334 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10335#endif /* not USE_X_TOOLKIT */
10336}
10337
10338void
10339x_wm_set_icon_pixmap (f, pixmap_id)
10340 struct frame *f;
10341 int pixmap_id;
10342{
10343 Pixmap icon_pixmap;
10344
10345#ifndef USE_X_TOOLKIT
10346 Window window = FRAME_X_WINDOW (f);
10347#endif
10348
10349 if (pixmap_id > 0)
10350 {
10351 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10352 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10353 }
10354 else
10355 {
10356 /* It seems there is no way to turn off use of an icon pixmap.
10357 The following line does it, only if no icon has yet been created,
10358 for some window managers. But with mwm it crashes.
10359 Some people say it should clear the IconPixmapHint bit in this case,
10360 but that doesn't work, and the X consortium said it isn't the
10361 right thing at all. Since there is no way to win,
10362 best to explicitly give up. */
10363#if 0
10364 f->output_data.x->wm_hints.icon_pixmap = None;
10365#else
10366 return;
10367#endif
10368 }
10369
10370#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10371
10372 {
10373 Arg al[1];
10374 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10375 XtSetValues (f->output_data.x->widget, al, 1);
10376 }
10377
10378#else /* not USE_X_TOOLKIT */
10379
10380 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10381 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10382
10383#endif /* not USE_X_TOOLKIT */
10384}
10385
e0f712ba 10386#endif /* MAC_TODO */
1a578e9b
AC
10387
10388void
10389x_wm_set_icon_position (f, icon_x, icon_y)
10390 struct frame *f;
10391 int icon_x, icon_y;
10392{
10393#if 0 /* MAC_TODO: no icons on Mac */
10394#ifdef USE_X_TOOLKIT
10395 Window window = XtWindow (f->output_data.x->widget);
10396#else
10397 Window window = FRAME_X_WINDOW (f);
10398#endif
10399
10400 f->output_data.x->wm_hints.flags |= IconPositionHint;
10401 f->output_data.x->wm_hints.icon_x = icon_x;
10402 f->output_data.x->wm_hints.icon_y = icon_y;
10403
10404 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
e0f712ba 10405#endif /* MAC_TODO */
1a578e9b
AC
10406}
10407
10408\f
10409/***********************************************************************
10410 Fonts
10411 ***********************************************************************/
10412
10413/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10414
10415struct font_info *
10416x_get_font_info (f, font_idx)
10417 FRAME_PTR f;
10418 int font_idx;
10419{
10420 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10421}
10422
10423/* the global font name table */
10424char **font_name_table = NULL;
10425int font_name_table_size = 0;
10426int font_name_count = 0;
10427
10428/* compare two strings ignoring case */
10429static int
10430stricmp (const char *s, const char *t)
10431{
10432 for ( ; tolower (*s) == tolower (*t); s++, t++)
10433 if (*s == '\0')
10434 return 0;
10435 return tolower (*s) - tolower (*t);
10436}
10437
10438/* compare two strings ignoring case and handling wildcard */
10439static int
10440wildstrieq (char *s1, char *s2)
10441{
10442 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10443 return true;
10444
10445 return stricmp (s1, s2) == 0;
10446}
10447
10448/* Assume parameter 1 is fully qualified, no wildcards. */
10449static int
10450mac_font_pattern_match (fontname, pattern)
10451 char * fontname;
10452 char * pattern;
10453{
b179a3a2 10454 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
1a578e9b
AC
10455 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10456 char *ptr;
10457
10458 /* Copy fontname so we can modify it during comparison. */
10459 strcpy (font_name_copy, fontname);
10460
10461 ptr = regex;
10462 *ptr++ = '^';
10463
10464 /* Turn pattern into a regexp and do a regexp match. */
10465 for (; *pattern; pattern++)
10466 {
10467 if (*pattern == '?')
10468 *ptr++ = '.';
10469 else if (*pattern == '*')
10470 {
10471 *ptr++ = '.';
10472 *ptr++ = '*';
10473 }
10474 else
10475 *ptr++ = *pattern;
10476 }
10477 *ptr = '$';
10478 *(ptr + 1) = '\0';
10479
10480 return (fast_c_string_match_ignore_case (build_string (regex),
10481 font_name_copy) >= 0);
10482}
10483
10484/* Two font specs are considered to match if their foundry, family,
10485 weight, slant, and charset match. */
10486static int
10487mac_font_match (char *mf, char *xf)
10488{
10489 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10490 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10491
10492 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10493 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10494 return mac_font_pattern_match (mf, xf);
10495
10496 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10497 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10498 return mac_font_pattern_match (mf, xf);
10499
10500 return (wildstrieq (m_foundry, x_foundry)
10501 && wildstrieq (m_family, x_family)
10502 && wildstrieq (m_weight, x_weight)
10503 && wildstrieq (m_slant, x_slant)
10504 && wildstrieq (m_charset, x_charset))
10505 || mac_font_pattern_match (mf, xf);
10506}
10507
10508
10509static char *
10510mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10511{
10512 char foundry[32], family[32], cs[32];
10513 char xf[255], *result, *p;
10514
10515 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10516 {
10517 strcpy(foundry, "Apple");
10518 strcpy(family, name);
10519
10520 switch (scriptcode)
10521 {
10522 case smTradChinese:
10523 strcpy(cs, "big5-0");
10524 break;
10525 case smSimpChinese:
83a96b4d 10526 strcpy(cs, "gb2312.1980-0");
1a578e9b
AC
10527 break;
10528 case smJapanese:
10529 strcpy(cs, "jisx0208.1983-sjis");
10530 break;
2f64cf3a
AC
10531 case -smJapanese:
10532 /* Each Apple Japanese font is entered into the font table
10533 twice: once as a jisx0208.1983-sjis font and once as a
10534 jisx0201.1976-0 font. The latter can be used to display
10535 the ascii charset and katakana-jisx0201 charset. A
10536 negative script code signals that the name of this latter
10537 font is being built. */
10538 strcpy(cs, "jisx0201.1976-0");
10539 break;
1a578e9b 10540 case smKorean:
83a96b4d 10541 strcpy(cs, "ksc5601.1989-0");
1a578e9b
AC
10542 break;
10543 default:
10544 strcpy(cs, "mac-roman");
10545 break;
10546 }
10547 }
10548
10549 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10550 foundry, family, style & bold ? "bold" : "medium",
10551 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10552
10553 result = (char *) xmalloc (strlen (xf) + 1);
10554 strcpy (result, xf);
10555 for (p = result; *p; p++)
10556 *p = tolower(*p);
10557 return result;
10558}
10559
10560
10561/* Convert an X font spec to the corresponding mac font name, which
10562 can then be passed to GetFNum after conversion to a Pascal string.
10563 For ordinary Mac fonts, this should just be their names, like
10564 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10565 collection contain their charset designation in their names, like
10566 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10567 names are handled accordingly. */
10568static void
10569x_font_name_to_mac_font_name (char *xf, char *mf)
10570{
10571 char foundry[32], family[32], weight[20], slant[2], cs[32];
10572
10573 strcpy (mf, "");
10574
10575 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10576 foundry, family, weight, slant, cs) != 5 &&
10577 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10578 foundry, family, weight, slant, cs) != 5)
10579 return;
10580
83a96b4d 10581 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
1a578e9b 10582 || strcmp (cs, "jisx0208.1983-sjis") == 0
2f64cf3a 10583 || strcmp (cs, "jisx0201.1976-0") == 0
83a96b4d 10584 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
1a578e9b
AC
10585 strcpy(mf, family);
10586 else
10587 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10588}
10589
10590
f00691a3
AC
10591static void
10592add_font_name_table_entry (char *font_name)
10593{
10594 if (font_name_table_size == 0)
10595 {
10596 font_name_table_size = 16;
10597 font_name_table = (char **)
10598 xmalloc (font_name_table_size * sizeof (char *));
10599 }
10600 else if (font_name_count + 1 >= font_name_table_size)
10601 {
10602 font_name_table_size += 16;
10603 font_name_table = (char **)
10604 xrealloc (font_name_table,
10605 font_name_table_size * sizeof (char *));
10606 }
10607
10608 font_name_table[font_name_count++] = font_name;
10609}
10610
10611/* Sets up the table font_name_table to contain the list of all fonts
10612 in the system the first time the table is used so that the Resource
10613 Manager need not be accessed every time this information is
10614 needed. */
1a578e9b
AC
10615
10616static void
10617init_font_name_table ()
10618{
e0f712ba
AC
10619#if TARGET_API_MAC_CARBON
10620 SInt32 sv;
10621
10622 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10623 {
10624 FMFontFamilyIterator ffi;
10625 FMFontFamilyInstanceIterator ffii;
10626 FMFontFamily ff;
1a578e9b 10627
e0f712ba
AC
10628 /* Create a dummy instance iterator here to avoid creating and
10629 destroying it in the loop. */
10630 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10631 return;
10632 /* Create an iterator to enumerate the font families. */
10633 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10634 != noErr)
10635 {
10636 FMDisposeFontFamilyInstanceIterator (&ffii);
10637 return;
10638 }
1a578e9b 10639
e0f712ba
AC
10640 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10641 {
10642 Str255 name;
10643 FMFont font;
10644 FMFontStyle style;
10645 FMFontSize size;
10646 SInt16 sc;
10647
10648 if (FMGetFontFamilyName (ff, name) != noErr)
10649 break;
10650 p2cstr (name);
10651
10652 sc = FontToScript (ff);
10653
10654 /* Point the instance iterator at the current font family. */
10655 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10656 break;
10657
10658 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10659 == noErr)
f00691a3
AC
10660 if (size == 0)
10661 {
10662 add_font_name_table_entry (mac_to_x_fontname (name, size,
10663 style, sc));
10664 add_font_name_table_entry (mac_to_x_fontname (name, size,
10665 italic, sc));
10666 add_font_name_table_entry (mac_to_x_fontname (name, size,
10667 bold, sc));
10668 add_font_name_table_entry (mac_to_x_fontname (name, size,
10669 italic | bold,
10670 sc));
10671 }
10672 else
a0f593ff
AC
10673 {
10674 add_font_name_table_entry (mac_to_x_fontname (name, size,
10675 style, sc));
10676 if (smJapanese == sc)
10677 add_font_name_table_entry (mac_to_x_fontname (name, size,
10678 style,
10679 -smJapanese));
10680 }
e0f712ba
AC
10681 }
10682
10683 /* Dispose of the iterators. */
10684 FMDisposeFontFamilyIterator (&ffi);
10685 FMDisposeFontFamilyInstanceIterator (&ffii);
10686 }
10687 else
1a578e9b 10688 {
e0f712ba
AC
10689#endif /* TARGET_API_MAC_CARBON */
10690 GrafPtr port;
10691 SInt16 fontnum, old_fontnum;
10692 int num_mac_fonts = CountResources('FOND');
10693 int i, j;
10694 Handle font_handle, font_handle_2;
10695 short id, scriptcode;
10696 ResType type;
10697 Str32 name;
10698 struct FontAssoc *fat;
10699 struct AsscEntry *assc_entry;
1a578e9b 10700
e0f712ba
AC
10701 GetPort (&port); /* save the current font number used */
10702#if TARGET_API_MAC_CARBON
10703 old_fontnum = GetPortTextFont (port);
10704#else
10705 old_fontnum = port->txFont;
10706#endif
10707
10708 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10709 {
10710 font_handle = GetIndResource ('FOND', i);
10711 if (!font_handle)
10712 continue;
10713
10714 GetResInfo (font_handle, &id, &type, name);
10715 GetFNum (name, &fontnum);
10716 p2cstr (name);
10717 if (fontnum == 0)
10718 continue;
10719
10720 TextFont (fontnum);
10721 scriptcode = FontToScript (fontnum);
10722 do
10723 {
10724 HLock (font_handle);
10725
10726 if (GetResourceSizeOnDisk (font_handle)
10727 >= sizeof (struct FamRec))
10728 {
10729 fat = (struct FontAssoc *) (*font_handle
10730 + sizeof (struct FamRec));
10731 assc_entry
10732 = (struct AsscEntry *) (*font_handle
10733 + sizeof (struct FamRec)
10734 + sizeof (struct FontAssoc));
10735
10736 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
199f9270 10737 {
e0f712ba
AC
10738 if (font_name_table_size == 0)
10739 {
10740 font_name_table_size = 16;
10741 font_name_table = (char **)
10742 xmalloc (font_name_table_size * sizeof (char *));
10743 }
10744 else if (font_name_count >= font_name_table_size)
10745 {
10746 font_name_table_size += 16;
10747 font_name_table = (char **)
10748 xrealloc (font_name_table,
10749 font_name_table_size * sizeof (char *));
10750 }
199f9270 10751 font_name_table[font_name_count++]
e0f712ba 10752 = mac_to_x_fontname (name,
199f9270
AC
10753 assc_entry->fontSize,
10754 assc_entry->fontStyle,
e0f712ba
AC
10755 scriptcode);
10756 /* Both jisx0208.1983-sjis and
10757 jisx0201.1976-sjis parts are contained in
10758 Apple Japanese (SJIS) font. */
10759 if (smJapanese == scriptcode)
10760 {
10761 font_name_table[font_name_count++]
10762 = mac_to_x_fontname (name,
10763 assc_entry->fontSize,
10764 assc_entry->fontStyle,
a0f593ff 10765 -smJapanese);
e0f712ba 10766 }
199f9270 10767 }
e0f712ba
AC
10768 }
10769
10770 HUnlock (font_handle);
10771 font_handle_2 = GetNextFOND (font_handle);
10772 ReleaseResource (font_handle);
10773 font_handle = font_handle_2;
10774 }
10775 while (ResError () == noErr && font_handle);
10776 }
10777
10778 TextFont (old_fontnum);
10779#if TARGET_API_MAC_CARBON
1a578e9b 10780 }
e0f712ba 10781#endif /* TARGET_API_MAC_CARBON */
1a578e9b
AC
10782}
10783
10784
10785/* Return a list of at most MAXNAMES font specs matching the one in
10ba2aec
AC
10786 PATTERN. Cache matching fonts for patterns in
10787 dpyinfo->name_list_element to avoid looking them up again by
10788 calling mac_font_pattern_match (slow). */
1a578e9b
AC
10789
10790Lisp_Object
10791x_list_fonts (struct frame *f,
10792 Lisp_Object pattern,
10793 int size,
10794 int maxnames)
10795{
10796 char *ptnstr;
10ba2aec 10797 Lisp_Object newlist = Qnil, tem, key;
1a578e9b
AC
10798 int n_fonts = 0;
10799 int i;
b179a3a2 10800 struct gcpro gcpro1, gcpro2;
10ba2aec 10801 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
1a578e9b
AC
10802
10803 if (font_name_table == NULL) /* Initialize when first used. */
10804 init_font_name_table ();
10805
10ba2aec
AC
10806 if (dpyinfo)
10807 {
10808 tem = XCDR (dpyinfo->name_list_element);
10809 key = Fcons (pattern, make_number (maxnames));
10810
10811 newlist = Fassoc (key, tem);
10812 if (!NILP (newlist))
10813 {
10814 newlist = Fcdr_safe (newlist);
10815 goto label_cached;
10816 }
10817 }
10818
d5db4077 10819 ptnstr = SDATA (pattern);
1a578e9b 10820
b179a3a2
AC
10821 GCPRO2 (pattern, newlist);
10822
1a578e9b
AC
10823 /* Scan and matching bitmap fonts. */
10824 for (i = 0; i < font_name_count; i++)
10825 {
10826 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10827 {
10828 newlist = Fcons (build_string (font_name_table[i]), newlist);
10829
10830 n_fonts++;
10831 if (n_fonts >= maxnames)
10832 break;
10833 }
10834 }
10835
10836 /* MAC_TODO: add code for matching outline fonts here */
10837
b179a3a2
AC
10838 UNGCPRO;
10839
10ba2aec
AC
10840 if (dpyinfo)
10841 {
10842 XSETCDR (dpyinfo->name_list_element,
10843 Fcons (Fcons (key, newlist),
10844 XCDR (dpyinfo->name_list_element)));
10845 }
10846 label_cached:
10847
1a578e9b
AC
10848 return newlist;
10849}
10850
10851
10852#if GLYPH_DEBUG
10853
e0f712ba
AC
10854/* Check that FONT is valid on frame F. It is if it can be found in F's
10855 font table. */
1a578e9b
AC
10856
10857static void
10858x_check_font (f, font)
10859 struct frame *f;
10860 XFontStruct *font;
10861{
10862 int i;
10863 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10864
10865 xassert (font != NULL);
10866
10867 for (i = 0; i < dpyinfo->n_fonts; i++)
10868 if (dpyinfo->font_table[i].name
10869 && font == dpyinfo->font_table[i].font)
10870 break;
10871
10872 xassert (i < dpyinfo->n_fonts);
10873}
10874
10875#endif /* GLYPH_DEBUG != 0 */
10876
1a578e9b
AC
10877/* Set *W to the minimum width, *H to the minimum font height of FONT.
10878 Note: There are (broken) X fonts out there with invalid XFontStruct
10879 min_bounds contents. For example, handa@etl.go.jp reports that
10880 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10881 have font->min_bounds.width == 0. */
10882
10883static INLINE void
10884x_font_min_bounds (font, w, h)
10885 MacFontStruct *font;
10886 int *w, *h;
10887{
e0f712ba
AC
10888 /*
10889 * TODO: Windows does not appear to offer min bound, only
10890 * average and maximum width, and maximum height.
10891 */
1a578e9b 10892 *h = FONT_HEIGHT (font);
e0f712ba 10893 *w = FONT_WIDTH (font);
1a578e9b
AC
10894}
10895
10896
10897/* Compute the smallest character width and smallest font height over
10898 all fonts available on frame F. Set the members smallest_char_width
10899 and smallest_font_height in F's x_display_info structure to
10900 the values computed. Value is non-zero if smallest_font_height or
10901 smallest_char_width become smaller than they were before. */
10902
e0f712ba 10903int
1a578e9b
AC
10904x_compute_min_glyph_bounds (f)
10905 struct frame *f;
10906{
10907 int i;
10908 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10909 MacFontStruct *font;
10910 int old_width = dpyinfo->smallest_char_width;
10911 int old_height = dpyinfo->smallest_font_height;
10912
10913 dpyinfo->smallest_font_height = 100000;
10914 dpyinfo->smallest_char_width = 100000;
10915
10916 for (i = 0; i < dpyinfo->n_fonts; ++i)
10917 if (dpyinfo->font_table[i].name)
10918 {
10919 struct font_info *fontp = dpyinfo->font_table + i;
10920 int w, h;
10921
10922 font = (MacFontStruct *) fontp->font;
10923 xassert (font != (MacFontStruct *) ~0);
10924 x_font_min_bounds (font, &w, &h);
10925
10926 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10927 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10928 }
10929
10930 xassert (dpyinfo->smallest_char_width > 0
10931 && dpyinfo->smallest_font_height > 0);
10932
10933 return (dpyinfo->n_fonts == 1
10934 || dpyinfo->smallest_char_width < old_width
10935 || dpyinfo->smallest_font_height < old_height);
10936}
10937
10938
10939/* Determine whether given string is a fully-specified XLFD: all 14
10940 fields are present, none is '*'. */
10941
10942static int
10943is_fully_specified_xlfd (char *p)
10944{
10945 int i;
10946 char *q;
10947
10948 if (*p != '-')
10949 return 0;
10950
10951 for (i = 0; i < 13; i++)
10952 {
10953 q = strchr (p + 1, '-');
10954 if (q == NULL)
10955 return 0;
10956 if (q - p == 2 && *(p + 1) == '*')
10957 return 0;
10958 p = q;
10959 }
10960
10961 if (strchr (p + 1, '-') != NULL)
10962 return 0;
10963
10964 if (*(p + 1) == '*' && *(p + 2) == '\0')
10965 return 0;
10966
10967 return 1;
10968}
10969
10970
10971const int kDefaultFontSize = 9;
10972
10973
e0f712ba
AC
10974/* XLoadQueryFont creates and returns an internal representation for a
10975 font in a MacFontStruct struct. There is really no concept
10976 corresponding to "loading" a font on the Mac. But we check its
10977 existence and find the font number and all other information for it
10978 and store them in the returned MacFontStruct. */
1a578e9b
AC
10979
10980static MacFontStruct *
10981XLoadQueryFont (Display *dpy, char *fontname)
10982{
10983 int i, size, is_two_byte_font, char_width;
10984 char *name;
10985 GrafPtr port;
10986 SInt16 old_fontnum, old_fontsize;
10987 Style old_fontface;
10988 Str32 mfontname;
10989 SInt16 fontnum;
10990 Style fontface = normal;
10991 MacFontStruct *font;
10992 FontInfo the_fontinfo;
10993 char s_weight[7], c_slant;
10994
10995 if (is_fully_specified_xlfd (fontname))
10996 name = fontname;
10997 else
10998 {
10999 for (i = 0; i < font_name_count; i++)
11000 if (mac_font_pattern_match (font_name_table[i], fontname))
11001 break;
11002
11003 if (i >= font_name_count)
11004 return NULL;
11005
11006 name = font_name_table[i];
11007 }
11008
11009 GetPort (&port); /* save the current font number used */
e0f712ba
AC
11010#if TARGET_API_MAC_CARBON
11011 old_fontnum = GetPortTextFont (port);
11012 old_fontsize = GetPortTextSize (port);
11013 old_fontface = GetPortTextFace (port);
11014#else
1a578e9b
AC
11015 old_fontnum = port->txFont;
11016 old_fontsize = port->txSize;
11017 old_fontface = port->txFace;
e0f712ba 11018#endif
1a578e9b
AC
11019
11020 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11021 size = kDefaultFontSize;
11022
11023 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11024 if (strcmp (s_weight, "bold") == 0)
11025 fontface |= bold;
11026
11027 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11028 if (c_slant == 'i')
11029 fontface |= italic;
11030
11031 x_font_name_to_mac_font_name (name, mfontname);
11032 c2pstr (mfontname);
11033 GetFNum (mfontname, &fontnum);
11034 if (fontnum == 0)
11035 return NULL;
11036
11037 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
11038
11039 font->fontname = (char *) xmalloc (strlen (name) + 1);
11040 bcopy (name, font->fontname, strlen (name) + 1);
11041
11042 font->mac_fontnum = fontnum;
11043 font->mac_fontsize = size;
11044 font->mac_fontface = fontface;
11045 font->mac_scriptcode = FontToScript (fontnum);
11046
199f9270 11047 /* Apple Japanese (SJIS) font is listed as both
2f64cf3a 11048 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
e0f712ba 11049 (Roman script) in init_font_name_table (). The latter should be
2f64cf3a 11050 treated as a one-byte font. */
199f9270
AC
11051 {
11052 char cs[32];
11053
11054 if (sscanf (name,
11055 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11056 cs) == 1
a0f593ff 11057 && 0 == strcmp (cs, "jisx0201.1976-0"))
199f9270
AC
11058 font->mac_scriptcode = smRoman;
11059 }
11060
1a578e9b
AC
11061 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11062 font->mac_scriptcode == smTradChinese ||
11063 font->mac_scriptcode == smSimpChinese ||
11064 font->mac_scriptcode == smKorean;
11065
11066 TextFont (fontnum);
11067 TextSize (size);
11068 TextFace (fontface);
11069
11070 GetFontInfo (&the_fontinfo);
11071
11072 font->ascent = the_fontinfo.ascent;
11073 font->descent = the_fontinfo.descent;
11074
11075 font->min_byte1 = 0;
11076 if (is_two_byte_font)
11077 font->max_byte1 = 1;
11078 else
11079 font->max_byte1 = 0;
11080 font->min_char_or_byte2 = 0x20;
11081 font->max_char_or_byte2 = 0xff;
11082
11083 if (is_two_byte_font)
11084 {
11085 /* Use the width of an "ideographic space" of that font because
11086 the_fontinfo.widMax returns the wrong width for some fonts. */
11087 switch (font->mac_scriptcode)
11088 {
11089 case smJapanese:
11090 char_width = StringWidth("\p\x81\x40");
11091 break;
11092 case smTradChinese:
11093 char_width = StringWidth("\p\xa1\x40");
11094 break;
11095 case smSimpChinese:
11096 char_width = StringWidth("\p\xa1\xa1");
11097 break;
11098 case smKorean:
11099 char_width = StringWidth("\p\xa1\xa1");
11100 break;
11101 }
11102 }
11103 else
11104 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11105 returns 15 for 12-point Monaco! */
11106 char_width = CharWidth ('m');
11107
11108 font->max_bounds.rbearing = char_width;
11109 font->max_bounds.lbearing = 0;
11110 font->max_bounds.width = char_width;
11111 font->max_bounds.ascent = the_fontinfo.ascent;
11112 font->max_bounds.descent = the_fontinfo.descent;
11113
11114 font->min_bounds = font->max_bounds;
11115
11116 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11117 font->per_char = NULL;
11118 else
11119 {
11120 font->per_char = (XCharStruct *)
11121 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11122 {
11123 int c;
11124
11125 for (c = 0x20; c <= 0xff; c++)
11126 {
11127 font->per_char[c - 0x20] = font->max_bounds;
11128 font->per_char[c - 0x20].width = CharWidth (c);
11129 }
11130 }
11131 }
11132
11133 TextFont (old_fontnum); /* restore previous font number, size and face */
11134 TextSize (old_fontsize);
11135 TextFace (old_fontface);
11136
11137 return font;
11138}
11139
11140
11141/* Load font named FONTNAME of the size SIZE for frame F, and return a
11142 pointer to the structure font_info while allocating it dynamically.
11143 If SIZE is 0, load any size of font.
11144 If loading is failed, return NULL. */
11145
11146struct font_info *
11147x_load_font (f, fontname, size)
11148 struct frame *f;
11149 register char *fontname;
11150 int size;
11151{
11152 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11153 Lisp_Object font_names;
11154
11155 /* Get a list of all the fonts that match this name. Once we
11156 have a list of matching fonts, we compare them against the fonts
11157 we already have by comparing names. */
11158 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11159
11160 if (!NILP (font_names))
11161 {
11162 Lisp_Object tail;
11163 int i;
11164
11165 for (i = 0; i < dpyinfo->n_fonts; i++)
11166 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11167 if (dpyinfo->font_table[i].name
11168 && (!strcmp (dpyinfo->font_table[i].name,
d5db4077 11169 SDATA (XCAR (tail)))
1a578e9b 11170 || !strcmp (dpyinfo->font_table[i].full_name,
d5db4077 11171 SDATA (XCAR (tail)))))
1a578e9b
AC
11172 return (dpyinfo->font_table + i);
11173 }
11174
11175 /* Load the font and add it to the table. */
11176 {
11177 char *full_name;
11178 struct MacFontStruct *font;
11179 struct font_info *fontp;
11180 unsigned long value;
11181 int i;
11182
11183 /* If we have found fonts by x_list_font, load one of them. If
11184 not, we still try to load a font by the name given as FONTNAME
11185 because XListFonts (called in x_list_font) of some X server has
11186 a bug of not finding a font even if the font surely exists and
11187 is loadable by XLoadQueryFont. */
11188 if (size > 0 && !NILP (font_names))
d5db4077 11189 fontname = (char *) SDATA (XCAR (font_names));
1a578e9b
AC
11190
11191 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11192 if (!font)
11193 return NULL;
11194
11195 /* Find a free slot in the font table. */
11196 for (i = 0; i < dpyinfo->n_fonts; ++i)
11197 if (dpyinfo->font_table[i].name == NULL)
11198 break;
11199
11200 /* If no free slot found, maybe enlarge the font table. */
11201 if (i == dpyinfo->n_fonts
11202 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11203 {
11204 int sz;
11205 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11206 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11207 dpyinfo->font_table
11208 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11209 }
11210
11211 fontp = dpyinfo->font_table + i;
11212 if (i == dpyinfo->n_fonts)
11213 ++dpyinfo->n_fonts;
11214
11215 /* Now fill in the slots of *FONTP. */
11216 BLOCK_INPUT;
11217 fontp->font = font;
11218 fontp->font_idx = i;
11219 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11220 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11221
11222 fontp->full_name = fontp->name;
11223
11224 fontp->size = font->max_bounds.width;
11225 fontp->height = FONT_HEIGHT (font);
11226 {
11227 /* For some font, ascent and descent in max_bounds field is
11228 larger than the above value. */
11229 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11230 if (max_height > fontp->height)
11231 fontp->height = max_height;
11232 }
11233
11234 /* The slot `encoding' specifies how to map a character
11235 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11236 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11237 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11238 2:0xA020..0xFF7F). For the moment, we don't know which charset
11239 uses this font. So, we set information in fontp->encoding[1]
11240 which is never used by any charset. If mapping can't be
11241 decided, set FONT_ENCODING_NOT_DECIDED. */
11242 if (font->mac_scriptcode == smJapanese)
11243 fontp->encoding[1] = 4;
11244 else
11245 {
11246 fontp->encoding[1]
11247 = (font->max_byte1 == 0
11248 /* 1-byte font */
11249 ? (font->min_char_or_byte2 < 0x80
11250 ? (font->max_char_or_byte2 < 0x80
11251 ? 0 /* 0x20..0x7F */
11252 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11253 : 1) /* 0xA0..0xFF */
11254 /* 2-byte font */
11255 : (font->min_byte1 < 0x80
11256 ? (font->max_byte1 < 0x80
11257 ? (font->min_char_or_byte2 < 0x80
11258 ? (font->max_char_or_byte2 < 0x80
11259 ? 0 /* 0x2020..0x7F7F */
11260 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11261 : 3) /* 0x20A0..0x7FFF */
11262 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11263 : (font->min_char_or_byte2 < 0x80
11264 ? (font->max_char_or_byte2 < 0x80
11265 ? 2 /* 0xA020..0xFF7F */
11266 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11267 : 1))); /* 0xA0A0..0xFFFF */
11268 }
11269
11270#if 0 /* MAC_TODO: fill these out with more reasonably values */
11271 fontp->baseline_offset
11272 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11273 ? (long) value : 0);
11274 fontp->relative_compose
11275 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11276 ? (long) value : 0);
11277 fontp->default_ascent
11278 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11279 ? (long) value : 0);
11280#else
11281 fontp->baseline_offset = 0;
11282 fontp->relative_compose = 0;
11283 fontp->default_ascent = 0;
11284#endif
11285
11286 /* Set global flag fonts_changed_p to non-zero if the font loaded
11287 has a character with a smaller width than any other character
11288 before, or if the font loaded has a smalle>r height than any
11289 other font loaded before. If this happens, it will make a
11290 glyph matrix reallocation necessary. */
11291 fonts_changed_p = x_compute_min_glyph_bounds (f);
11292 UNBLOCK_INPUT;
11293 return fontp;
11294 }
11295}
11296
11297
11298/* Return a pointer to struct font_info of a font named FONTNAME for
11299 frame F. If no such font is loaded, return NULL. */
11300
11301struct font_info *
11302x_query_font (f, fontname)
11303 struct frame *f;
11304 register char *fontname;
11305{
11306 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11307 int i;
11308
11309 for (i = 0; i < dpyinfo->n_fonts; i++)
11310 if (dpyinfo->font_table[i].name
11311 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11312 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11313 return (dpyinfo->font_table + i);
11314 return NULL;
11315}
11316
11317
11318/* Find a CCL program for a font specified by FONTP, and set the member
11319 `encoder' of the structure. */
11320
11321void
11322x_find_ccl_program (fontp)
11323 struct font_info *fontp;
11324{
11325 Lisp_Object list, elt;
11326
11327 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11328 {
11329 elt = XCAR (list);
11330 if (CONSP (elt)
11331 && STRINGP (XCAR (elt))
11332 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11333 >= 0))
11334 break;
11335 }
11336 if (! NILP (list))
11337 {
11338 struct ccl_program *ccl
11339 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11340
11341 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11342 xfree (ccl);
11343 else
11344 fontp->font_encoder = ccl;
11345 }
11346}
11347
11348
11349\f
11350/***********************************************************************
11351 Initialization
11352 ***********************************************************************/
11353
11354#ifdef USE_X_TOOLKIT
11355static XrmOptionDescRec emacs_options[] = {
11356 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11357 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11358
11359 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11360 XrmoptionSepArg, NULL},
11361 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11362
11363 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11364 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11365 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11366 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11367 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11368 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11369 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11370};
11371#endif /* USE_X_TOOLKIT */
11372
11373static int x_initialized;
11374
11375#ifdef MULTI_KBOARD
11376/* Test whether two display-name strings agree up to the dot that separates
11377 the screen number from the server number. */
11378static int
11379same_x_server (name1, name2)
11380 char *name1, *name2;
11381{
11382 int seen_colon = 0;
d5db4077 11383 unsigned char *system_name = SDATA (Vsystem_name);
1a578e9b
AC
11384 int system_name_length = strlen (system_name);
11385 int length_until_period = 0;
11386
11387 while (system_name[length_until_period] != 0
11388 && system_name[length_until_period] != '.')
11389 length_until_period++;
11390
11391 /* Treat `unix' like an empty host name. */
11392 if (! strncmp (name1, "unix:", 5))
11393 name1 += 4;
11394 if (! strncmp (name2, "unix:", 5))
11395 name2 += 4;
11396 /* Treat this host's name like an empty host name. */
11397 if (! strncmp (name1, system_name, system_name_length)
11398 && name1[system_name_length] == ':')
11399 name1 += system_name_length;
11400 if (! strncmp (name2, system_name, system_name_length)
11401 && name2[system_name_length] == ':')
11402 name2 += system_name_length;
11403 /* Treat this host's domainless name like an empty host name. */
11404 if (! strncmp (name1, system_name, length_until_period)
11405 && name1[length_until_period] == ':')
e0f712ba
AC
11406 name1 += length_until_period;
11407 if (! strncmp (name2, system_name, length_until_period)
11408 && name2[length_until_period] == ':')
11409 name2 += length_until_period;
11410
11411 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11412 {
11413 if (*name1 == ':')
11414 seen_colon++;
11415 if (seen_colon && *name1 == '.')
11416 return 1;
11417 }
11418 return (seen_colon
11419 && (*name1 == '.' || *name1 == '\0')
11420 && (*name2 == '.' || *name2 == '\0'));
11421}
11422#endif
1a578e9b
AC
11423
11424
11425/* The Mac Event loop code */
11426
e0f712ba 11427#ifndef MAC_OSX
1a578e9b
AC
11428#include <Events.h>
11429#include <Quickdraw.h>
11430#include <Balloons.h>
11431#include <Devices.h>
11432#include <Fonts.h>
11433#include <Gestalt.h>
11434#include <Menus.h>
11435#include <Processes.h>
11436#include <Sound.h>
11437#include <ToolUtils.h>
11438#include <TextUtils.h>
11439#include <Dialogs.h>
11440#include <Script.h>
1a578e9b
AC
11441#include <Types.h>
11442#include <TextEncodingConverter.h>
11443#include <Resources.h>
11444
11445#if __MWERKS__
11446#include <unix.h>
11447#endif
e0f712ba 11448#endif /* ! MAC_OSX */
1a578e9b
AC
11449
11450#define M_APPLE 128
11451#define I_ABOUT 1
11452
11453#define WINDOW_RESOURCE 128
11454#define TERM_WINDOW_RESOURCE 129
11455
11456#define DEFAULT_NUM_COLS 80
11457
11458#define MIN_DOC_SIZE 64
11459#define MAX_DOC_SIZE 32767
11460
11461/* sleep time for WaitNextEvent */
11462#define WNE_SLEEP_AT_SUSPEND 10
11463#define WNE_SLEEP_AT_RESUME 1
11464
11465/* true when cannot handle any Mac OS events */
11466static int handling_window_update = 0;
11467
11468/* the flag appl_is_suspended is used both for determining the sleep
11469 time to be passed to WaitNextEvent and whether the cursor should be
11470 drawn when updating the display. The cursor is turned off when
11471 Emacs is suspended. Redrawing it is unnecessary and what needs to
11472 be done depends on whether the cursor lies inside or outside the
11473 redraw region. So we might as well skip drawing it when Emacs is
11474 suspended. */
11475static Boolean app_is_suspended = false;
11476static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11477
11478#define EXTRA_STACK_ALLOC (256 * 1024)
11479
11480#define ARGV_STRING_LIST_ID 129
11481#define ABOUT_ALERT_ID 128
2e875e36 11482#define RAM_TOO_LARGE_ALERT_ID 129
1a578e9b
AC
11483
11484Boolean terminate_flag = false;
11485
742fbed7 11486/* True if using command key as meta key. */
1a578e9b
AC
11487Lisp_Object Vmac_command_key_is_meta;
11488
742fbed7
AC
11489/* True if the ctrl and meta keys should be reversed. */
11490Lisp_Object Vmac_reverse_ctrl_meta;
11491
11492#if USE_CARBON_EVENTS
11493/* True if the mouse wheel button (i.e. button 4) should map to
11494 mouse-2, instead of mouse-3. */
11495Lisp_Object Vmac_wheel_button_is_mouse_2;
5883787c
AC
11496
11497/* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
11498 for processing before Emacs sees it. */
11499Lisp_Object Vmac_pass_command_to_system;
11500
11501/* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
11502 for processing before Emacs sees it. */
11503Lisp_Object Vmac_pass_control_to_system;
742fbed7
AC
11504#endif
11505
1a578e9b
AC
11506/* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11507 to this text encoding */
11508int mac_keyboard_text_encoding;
11509int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11510
11511/* Set in term/mac-win.el to indicate that event loop can now generate
11512 drag and drop events. */
8f47302e 11513Lisp_Object Qmac_ready_for_drag_n_drop;
1a578e9b
AC
11514
11515Lisp_Object drag_and_drop_file_list;
11516
11517Point saved_menu_event_location;
11518
11519/* Apple Events */
742fbed7 11520static void init_required_apple_events (void);
e0f712ba 11521static pascal OSErr
742fbed7 11522do_ae_open_application (const AppleEvent *, AppleEvent *, long);
e0f712ba 11523static pascal OSErr
742fbed7
AC
11524do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
11525static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
11526static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
11527
11528/* Drag and Drop */
11529static OSErr init_mac_drag_n_drop ();
11530static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
11531
11532#if USE_CARBON_EVENTS
11533/* Preliminary Support for the OSX Services Menu */
11534static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
11535static void init_service_handler ();
11536#endif
1a578e9b
AC
11537
11538extern void init_emacs_passwd_dir ();
11539extern int emacs_main (int, char **, char **);
11540extern void check_alarm ();
11541
11542extern void initialize_applescript();
11543extern void terminate_applescript();
11544
742fbed7
AC
11545static unsigned int
11546#if USE_CARBON_EVENTS
11547mac_to_emacs_modifiers (UInt32 mods)
11548#else
11549mac_to_emacs_modifiers (EventModifiers mods)
11550#endif
11551{
11552 unsigned int result = 0;
11553 if (mods & macShiftKey)
11554 result |= shift_modifier;
11555 if (mods & macCtrlKey)
11556 result |= ctrl_modifier;
11557 if (mods & macMetaKey)
11558 result |= meta_modifier;
11559 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
11560 result |= alt_modifier;
11561 return result;
11562}
11563
11564#if USE_CARBON_EVENTS
11565/* Obtains the event modifiers from the event ref and then calls
11566 mac_to_emacs_modifiers. */
11567static int
11568mac_event_to_emacs_modifiers (EventRef eventRef)
11569{
11570 UInt32 mods = 0;
11571 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
11572 sizeof (UInt32), NULL, &mods);
11573 return mac_to_emacs_modifiers (mods);
11574}
11575
11576/* Given an event ref, return the code to use for the mouse button
11577 code in the emacs input_event. */
11578static int
11579mac_get_mouse_btn (EventRef ref)
11580{
11581 EventMouseButton result = kEventMouseButtonPrimary;
11582 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
11583 sizeof (EventMouseButton), NULL, &result);
11584 switch (result)
11585 {
11586 case kEventMouseButtonPrimary:
11587 return 0;
11588 case kEventMouseButtonSecondary:
11589 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
11590 case kEventMouseButtonTertiary:
11591 case 4: /* 4 is the number for the mouse wheel button */
11592 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
11593 default:
11594 return 0;
11595 }
11596}
11597
11598/* Normally, ConvertEventRefToEventRecord will correctly handle all
11599 events. However the click of the mouse wheel is not converted to a
11600 mouseDown or mouseUp event. This calls ConvertEventRef, but then
11601 checks to see if it is a mouse up or down carbon event that has not
11602 been converted, and if so, converts it by hand (to be picked up in
11603 the XTread_socket loop). */
11604static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
11605{
11606 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
11607 /* Do special case for mouse wheel button. */
11608 if (!result && GetEventClass (eventRef) == kEventClassMouse)
11609 {
11610 UInt32 kind = GetEventKind (eventRef);
11611 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
11612 {
11613 eventRec->what = mouseDown;
11614 result=1;
11615 }
11616 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
11617 {
11618 eventRec->what = mouseUp;
11619 result=1;
11620 }
11621 if (result)
11622 {
11623 /* Need where and when. */
11624 UInt32 mods;
11625 GetEventParameter (eventRef, kEventParamMouseLocation,
11626 typeQDPoint, NULL, sizeof (Point),
11627 NULL, &eventRec->where);
11628 /* Use two step process because new event modifiers are
11629 32-bit and old are 16-bit. Currently, only loss is
11630 NumLock & Fn. */
11631 GetEventParameter (eventRef, kEventParamKeyModifiers,
11632 typeUInt32, NULL, sizeof (UInt32),
11633 NULL, &mods);
11634 eventRec->modifiers = mods;
11635
11636 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
11637 }
11638 }
11639 return result;
11640}
11641
11642#endif
1a578e9b
AC
11643
11644static void
11645do_get_menus (void)
11646{
11647 Handle menubar_handle;
11648 MenuHandle menu_handle;
11649
11650 menubar_handle = GetNewMBar (128);
11651 if(menubar_handle == NULL)
11652 abort ();
11653 SetMenuBar (menubar_handle);
11654 DrawMenuBar ();
11655
11656 menu_handle = GetMenuHandle (M_APPLE);
11657 if(menu_handle != NULL)
11658 AppendResMenu (menu_handle,'DRVR');
11659 else
11660 abort ();
11661}
11662
11663
11664static void
11665do_init_managers (void)
11666{
e0f712ba 11667#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11668 InitGraf (&qd.thePort);
11669 InitFonts ();
11670 FlushEvents (everyEvent, 0);
11671 InitWindows ();
11672 InitMenus ();
11673 TEInit ();
11674 InitDialogs (NULL);
e0f712ba
AC
11675#endif /* !TARGET_API_MAC_CARBON */
11676 InitCursor ();
1a578e9b 11677
e0f712ba 11678#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11679 /* set up some extra stack space for use by emacs */
11680 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11681
11682 /* MaxApplZone must be called for AppleScript to execute more
11683 complicated scripts */
11684 MaxApplZone ();
11685 MoreMasters ();
e0f712ba 11686#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
11687}
11688
2e875e36
AC
11689static void
11690do_check_ram_size (void)
11691{
11692 SInt32 physical_ram_size, logical_ram_size;
11693
11694 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11695 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11696 || physical_ram_size > 256 * 1024 * 1024
11697 || logical_ram_size > 256 * 1024 * 1024)
11698 {
11699 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11700 exit (1);
11701 }
11702}
11703
1a578e9b
AC
11704static void
11705do_window_update (WindowPtr win)
11706{
11707 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11708 struct frame *f = mwp->mFP;
11709
11710 if (f)
11711 {
11712 if (f->async_visible == 0)
11713 {
11714 f->async_visible = 1;
11715 f->async_iconified = 0;
11716 SET_FRAME_GARBAGED (f);
11717
11718 /* An update event is equivalent to MapNotify on X, so report
11719 visibility changes properly. */
11720 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11721 /* Force a redisplay sooner or later to update the
11722 frame titles in case this is the second frame. */
11723 record_asynch_buffer_change ();
11724 }
11725 else
11726 {
11727 BeginUpdate (win);
11728 handling_window_update = 1;
11729
2d97ff8c
AC
11730 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
11731
1a578e9b
AC
11732 expose_frame (f, 0, 0, 0, 0);
11733
11734 handling_window_update = 0;
11735 EndUpdate (win);
11736 }
11737 }
11738}
11739
e0f712ba
AC
11740static int
11741is_emacs_window (WindowPtr win)
11742{
11743 Lisp_Object tail, frame;
11744
11745 if (!win)
11746 return 0;
11747
11748 FOR_EACH_FRAME (tail, frame)
11749 if (FRAME_MAC_P (XFRAME (frame)))
11750 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11751 return 1;
11752
11753 return 0;
11754}
11755
1a578e9b
AC
11756static void
11757do_window_activate (WindowPtr win)
11758{
e0f712ba
AC
11759 mac_output *mwp;
11760 struct frame *f;
1a578e9b 11761
e0f712ba 11762 if (is_emacs_window (win))
1a578e9b 11763 {
e0f712ba
AC
11764 mwp = (mac_output *) GetWRefCon (win);
11765 f = mwp->mFP;
11766
11767 if (f)
11768 {
11769 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11770 activate_scroll_bars (f);
11771 }
1a578e9b
AC
11772 }
11773}
11774
11775static void
11776do_window_deactivate (WindowPtr win)
11777{
e0f712ba
AC
11778 mac_output *mwp;
11779 struct frame *f;
1a578e9b 11780
e0f712ba 11781 if (is_emacs_window (win))
1a578e9b 11782 {
e0f712ba
AC
11783 mwp = (mac_output *) GetWRefCon (win);
11784 f = mwp->mFP;
11785
11786 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11787 {
11788 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11789 deactivate_scroll_bars (f);
11790 }
1a578e9b
AC
11791 }
11792}
11793
11794static void
11795do_app_resume ()
11796{
e0f712ba
AC
11797 WindowPtr wp;
11798 mac_output *mwp;
11799 struct frame *f;
fa0b4c14 11800
e0f712ba
AC
11801 wp = FrontWindow();
11802 if (is_emacs_window (wp))
1a578e9b 11803 {
e0f712ba
AC
11804 mwp = (mac_output *) GetWRefCon (wp);
11805 f = mwp->mFP;
11806
11807 if (f)
11808 {
11809 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11810 activate_scroll_bars (f);
11811 }
1a578e9b
AC
11812 }
11813
11814 app_is_suspended = false;
11815 app_sleep_time = WNE_SLEEP_AT_RESUME;
11816}
11817
11818static void
11819do_app_suspend ()
11820{
e0f712ba
AC
11821 WindowPtr wp;
11822 mac_output *mwp;
11823 struct frame *f;
1a578e9b 11824
e0f712ba
AC
11825 wp = FrontWindow();
11826 if (is_emacs_window (wp))
1a578e9b 11827 {
e0f712ba
AC
11828 mwp = (mac_output *) GetWRefCon (wp);
11829 f = mwp->mFP;
11830
11831 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11832 {
11833 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11834 deactivate_scroll_bars (f);
11835 }
1a578e9b
AC
11836 }
11837
11838 app_is_suspended = true;
11839 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11840}
11841
11842
11843static void
11844do_mouse_moved (Point mouse_pos)
11845{
11846 WindowPtr wp = FrontWindow ();
5883787c 11847 struct frame *f;
1a578e9b 11848
5883787c
AC
11849 if (is_emacs_window (wp))
11850 {
11851 f = ((mac_output *) GetWRefCon (wp))->mFP;
11852
e0f712ba
AC
11853#if TARGET_API_MAC_CARBON
11854 SetPort (GetWindowPort (wp));
11855#else
11856 SetPort (wp);
11857#endif
11858
5883787c
AC
11859 GlobalToLocal (&mouse_pos);
11860
11861 note_mouse_movement (f, &mouse_pos);
11862 }
1a578e9b
AC
11863}
11864
11865
11866static void
11867do_os_event (EventRecord *erp)
11868{
11869 switch((erp->message >> 24) & 0x000000FF)
11870 {
11871 case suspendResumeMessage:
11872 if((erp->message & resumeFlag) == 1)
11873 do_app_resume ();
11874 else
11875 do_app_suspend ();
11876 break;
11877
e0f712ba 11878 case mouseMovedMessage:
1a578e9b
AC
11879 do_mouse_moved (erp->where);
11880 break;
11881 }
11882}
11883
11884static void
11885do_events (EventRecord *erp)
11886{
11887 switch (erp->what)
11888 {
11889 case updateEvt:
11890 do_window_update ((WindowPtr) erp->message);
11891 break;
11892
11893 case osEvt:
11894 do_os_event (erp);
11895 break;
11896
11897 case activateEvt:
11898 if ((erp->modifiers & activeFlag) != 0)
11899 do_window_activate ((WindowPtr) erp->message);
11900 else
11901 do_window_deactivate ((WindowPtr) erp->message);
11902 break;
11903 }
11904}
11905
11906static void
11907do_apple_menu (SInt16 menu_item)
11908{
e0f712ba 11909#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11910 Str255 item_name;
11911 SInt16 da_driver_refnum;
11912
11913 if (menu_item == I_ABOUT)
11914 NoteAlert (ABOUT_ALERT_ID, NULL);
11915 else
11916 {
11917 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11918 da_driver_refnum = OpenDeskAcc (item_name);
11919 }
e0f712ba 11920#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
11921}
11922
11923void
11924do_menu_choice (SInt32 menu_choice)
11925{
11926 SInt16 menu_id, menu_item;
11927
11928 menu_id = HiWord (menu_choice);
11929 menu_item = LoWord (menu_choice);
11930
11931 if (menu_id == 0)
11932 return;
11933
11934 switch (menu_id)
11935 {
11936 case M_APPLE:
11937 do_apple_menu (menu_item);
11938 break;
11939
11940 default:
11941 {
11942 WindowPtr wp = FrontWindow ();
11943 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11944 MenuHandle menu = GetMenuHandle (menu_id);
11945 if (menu)
11946 {
11947 UInt32 refcon;
11948
11949 GetMenuItemRefCon (menu, menu_item, &refcon);
11950 menubar_selection_callback (f, refcon);
11951 }
11952 }
11953 }
11954
11955 HiliteMenu (0);
11956}
11957
11958
11959/* Handle drags in size box. Based on code contributed by Ben
11960 Mesander and IM - Window Manager A. */
11961
11962static void
11963do_grow_window (WindowPtr w, EventRecord *e)
11964{
11965 long grow_size;
11966 Rect limit_rect;
11967 int rows, columns;
11968 mac_output *mwp = (mac_output *) GetWRefCon (w);
11969 struct frame *f = mwp->mFP;
11970
11971 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11972
11973 grow_size = GrowWindow (w, e->where, &limit_rect);
11974
11975 /* see if it really changed size */
11976 if (grow_size != 0)
11977 {
11978 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11979 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11980
11981 x_set_window_size (f, 0, columns, rows);
11982 }
11983}
11984
11985
11986/* Handle clicks in zoom box. Calculation of "standard state" based
11987 on code in IM - Window Manager A and code contributed by Ben
11988 Mesander. The standard state of an Emacs window is 80-characters
11989 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11990
11991static void
11992do_zoom_window (WindowPtr w, int zoom_in_or_out)
11993{
11994 GrafPtr save_port;
11995 Rect zoom_rect, port_rect;
11996 Point top_left;
11997 int w_title_height, columns, rows, width, height, dummy, x, y;
11998 mac_output *mwp = (mac_output *) GetWRefCon (w);
11999 struct frame *f = mwp->mFP;
12000
12001 GetPort (&save_port);
e0f712ba
AC
12002
12003#if TARGET_API_MAC_CARBON
12004 SetPort (GetWindowPort (w));
12005#else
1a578e9b 12006 SetPort (w);
e0f712ba
AC
12007#endif
12008
12009 /* Clear window to avoid flicker. */
12010#if TARGET_API_MAC_CARBON
12011 {
12012 Rect r;
12013 BitMap bm;
12014
12015 GetWindowPortBounds (w, &r);
12016 EraseRect (&r);
12017
12018 if (zoom_in_or_out == inZoomOut)
12019 {
12020 /* calculate height of window's title bar (hard card it for now). */
12021 w_title_height = 20 + GetMBarHeight ();
12022
12023 /* get maximum height of window into zoom_rect.bottom -
12024 zoom_rect.top */
12025 GetQDGlobalsScreenBits (&bm);
12026 zoom_rect = bm.bounds;
12027 zoom_rect.top += w_title_height;
12028 InsetRect (&zoom_rect, 8, 4); /* not too tight */
12029
12030 zoom_rect.right = zoom_rect.left
12031 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12032
12033 SetWindowStandardState (w, &zoom_rect);
12034 }
12035 }
12036#else /* not TARGET_API_MAC_CARBON */
12037 EraseRect (&(w->portRect));
1a578e9b
AC
12038 if (zoom_in_or_out == inZoomOut)
12039 {
e0f712ba 12040 SetPt (&top_left, w->portRect.left, w->portRect.top);
1a578e9b
AC
12041 LocalToGlobal (&top_left);
12042
12043 /* calculate height of window's title bar */
12044 w_title_height = top_left.v - 1
e0f712ba 12045 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
1a578e9b
AC
12046
12047 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
12048 zoom_rect = qd.screenBits.bounds;
12049 zoom_rect.top += w_title_height;
12050 InsetRect (&zoom_rect, 8, 4); /* not too tight */
12051
12052 zoom_rect.right = zoom_rect.left
12053 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12054
e0f712ba
AC
12055 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
12056 = zoom_rect;
1a578e9b 12057 }
e0f712ba 12058#endif /* not TARGET_API_MAC_CARBON */
1a578e9b 12059
e0f712ba 12060 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
1a578e9b
AC
12061
12062 /* retrieve window size and update application values */
e0f712ba
AC
12063#if TARGET_API_MAC_CARBON
12064 GetWindowPortBounds (w, &port_rect);
12065#else
1a578e9b 12066 port_rect = w->portRect;
e0f712ba 12067#endif
1a578e9b
AC
12068 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
12069 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
12070 x_set_window_size (mwp->mFP, 0, columns, rows);
12071
12072 SetPort (save_port);
12073}
12074
742fbed7
AC
12075/* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
12076static OSErr
12077init_mac_drag_n_drop ()
12078{
12079 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
12080 return result;
12081}
1a578e9b
AC
12082
12083/* Intialize AppleEvent dispatcher table for the required events. */
12084void
12085init_required_apple_events ()
12086{
12087 OSErr err;
12088 long result;
12089
12090 /* Make sure we have apple events before starting. */
12091 err = Gestalt (gestaltAppleEventsAttr, &result);
12092 if (err != noErr)
12093 abort ();
12094
12095 if (!(result & (1 << gestaltAppleEventsPresent)))
12096 abort ();
12097
e0f712ba 12098#if TARGET_API_MAC_CARBON
1a578e9b 12099 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
e0f712ba
AC
12100 NewAEEventHandlerUPP
12101 ((AEEventHandlerProcPtr) do_ae_open_application),
1a578e9b 12102 0L, false);
e0f712ba
AC
12103#else
12104 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12105 NewAEEventHandlerProc
12106 ((AEEventHandlerProcPtr) do_ae_open_application),
12107 0L, false);
12108#endif
1a578e9b
AC
12109 if (err != noErr)
12110 abort ();
e0f712ba
AC
12111
12112#if TARGET_API_MAC_CARBON
12113 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12114 NewAEEventHandlerUPP
12115 ((AEEventHandlerProcPtr) do_ae_open_documents),
12116 0L, false);
12117#else
1a578e9b 12118 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
e0f712ba
AC
12119 NewAEEventHandlerProc
12120 ((AEEventHandlerProcPtr) do_ae_open_documents),
1a578e9b 12121 0L, false);
e0f712ba 12122#endif
1a578e9b
AC
12123 if (err != noErr)
12124 abort ();
12125
e0f712ba
AC
12126#if TARGET_API_MAC_CARBON
12127 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12128 NewAEEventHandlerUPP
12129 ((AEEventHandlerProcPtr) do_ae_print_documents),
12130 0L, false);
12131#else
1a578e9b 12132 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
e0f712ba
AC
12133 NewAEEventHandlerProc
12134 ((AEEventHandlerProcPtr) do_ae_print_documents),
1a578e9b 12135 0L, false);
e0f712ba 12136#endif
1a578e9b
AC
12137 if (err != noErr)
12138 abort ();
12139
e0f712ba
AC
12140#if TARGET_API_MAC_CARBON
12141 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12142 NewAEEventHandlerUPP
12143 ((AEEventHandlerProcPtr) do_ae_quit_application),
12144 0L, false);
12145#else
1a578e9b 12146 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
e0f712ba
AC
12147 NewAEEventHandlerProc
12148 ((AEEventHandlerProcPtr) do_ae_quit_application),
1a578e9b 12149 0L, false);
e0f712ba 12150#endif
1a578e9b
AC
12151 if (err != noErr)
12152 abort ();
12153}
12154
742fbed7
AC
12155#if USE_CARBON_EVENTS
12156
770136ad
RS
12157void
12158init_service_handler ()
742fbed7
AC
12159{
12160 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
12161 {kEventClassService, kEventServiceCopy},
12162 {kEventClassService, kEventServicePaste}};
12163 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
12164 3, specs, NULL, NULL);
12165}
12166
12167/*
12168 MAC_TODO: Check to see if this is called by AEProcessDesc...
12169 */
770136ad
RS
12170OSStatus
12171mac_handle_service_event (EventHandlerCallRef callRef,
12172 EventRef event, void *data)
742fbed7
AC
12173{
12174 OSStatus err = noErr;
12175 switch (GetEventKind (event))
12176 {
12177 case kEventServiceGetTypes:
12178 {
12179 CFMutableArrayRef copyTypes, pasteTypes;
12180 CFStringRef type;
12181 Boolean selection = true;
12182 /*
12183 GetEventParameter(event, kEventParamServicePasteTypes,
12184 typeCFMutableArrayRef, NULL,
12185 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
12186 */
12187 GetEventParameter(event, kEventParamServiceCopyTypes,
12188 typeCFMutableArrayRef, NULL,
12189 sizeof (CFMutableArrayRef), NULL, &copyTypes);
12190 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
12191 if (type) {
12192 CFArrayAppendValue (copyTypes, type);
12193 //CFArrayAppendValue (pasteTypes, type);
12194 CFRelease (type);
12195 }
12196 }
12197 case kEventServiceCopy:
12198 {
12199 ScrapRef currentScrap, specificScrap;
12200 char * buf = "";
12201 Size byteCount = 0;
12202
12203 GetCurrentScrap (&currentScrap);
12204
12205 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
12206 if (err == noErr)
12207 {
12208 void *buffer = xmalloc (byteCount);
12209 if (buffer != NULL)
12210 {
12211 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
12212 sizeof (ScrapRef), NULL, &specificScrap);
12213
12214 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
12215 &byteCount, buffer);
12216 if (err == noErr)
12217 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
12218 kScrapFlavorMaskNone, byteCount, buffer);
12219 xfree (buffer);
12220 }
12221 }
12222 err = noErr;
12223 }
12224 case kEventServicePaste:
12225 {
12226 /*
12227 // Get the current location
12228 Size byteCount;
12229 ScrapRef specificScrap;
12230 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
12231 sizeof(ScrapRef), NULL, &specificScrap);
12232 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
12233 if (err == noErr) {
12234 void * buffer = xmalloc(byteCount);
12235 if (buffer != NULL ) {
12236 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
12237 &byteCount, buffer);
12238 if (err == noErr) {
12239 // Actually place in the buffer
12240 BLOCK_INPUT;
12241 // Get the current "selection" string here
12242 UNBLOCK_INPUT;
12243 }
12244 }
12245 xfree(buffer);
12246 }
12247 */
12248 }
12249 }
12250 return err;
12251}
12252#endif
1a578e9b
AC
12253
12254/* Open Application Apple Event */
12255static pascal OSErr
12256do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12257{
12258 return noErr;
12259}
12260
12261
12262/* Defined in mac.c. */
12263extern int
12264path_from_vol_dir_name (char *, int, short, long, char *);
12265
12266
12267/* Called when we receive an AppleEvent with an ID of
12268 "kAEOpenDocuments". This routine gets the direct parameter,
12269 extracts the FSSpecs in it, and puts their names on a list. */
12270static pascal OSErr
12271do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12272{
12273 OSErr err, err2;
12274 AEDesc the_desc;
12275 AEKeyword keyword;
12276 DescType actual_type;
12277 Size actual_size;
12278
12279 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12280 if (err != noErr)
12281 goto descriptor_error_exit;
12282
12283 /* Check to see that we got all of the required parameters from the
12284 event descriptor. For an 'odoc' event this should just be the
12285 file list. */
12286 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12287 &actual_type, (Ptr) &keyword,
12288 sizeof (keyword), &actual_size);
12289 /* No error means that we found some unused parameters.
12290 errAEDescNotFound means that there are no more parameters. If we
12291 get an error code other than that, flag it. */
12292 if ((err == noErr) || (err != errAEDescNotFound))
12293 {
12294 err = errAEEventNotHandled;
12295 goto error_exit;
12296 }
12297 err = noErr;
12298
12299 /* Got all the parameters we need. Now, go through the direct
12300 object list and parse it up. */
12301 {
12302 long num_files_to_open;
12303
12304 err = AECountItems (&the_desc, &num_files_to_open);
12305 if (err == noErr)
12306 {
12307 int i;
12308
12309 /* AE file list is one based so just use that for indexing here. */
bc21bf11
AC
12310 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
12311 {
12312 FSSpec fs;
12313 Str255 path_name, unix_path_name;
12314#ifdef MAC_OSX
12315 FSRef fref;
12316#endif
12317
12318 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12319 (Ptr) &fs, sizeof (fs), &actual_size);
12320 if (err != noErr) break;
12321
12322#ifdef MAC_OSX
12323 err = FSpMakeFSRef (&fs, &fref);
12324 if (err != noErr) break;
12325
12326 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12327#else
12328 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12329 fs.name) &&
12330 mac_to_posix_pathname (path_name, unix_path_name, 255))
12331#endif
12332 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12333 drag_and_drop_file_list);
12334 }
1a578e9b
AC
12335 }
12336 }
12337
12338error_exit:
12339 /* Nuke the coerced file list in any case */
12340 err2 = AEDisposeDesc(&the_desc);
12341
12342descriptor_error_exit:
12343 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12344 return err;
12345}
12346
12347
770136ad
RS
12348static pascal OSErr
12349mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
12350 DragReference theDrag)
742fbed7
AC
12351{
12352 short items;
12353 short index;
12354 FlavorFlags theFlags;
12355 Point mouse;
12356 OSErr result;
12357 ItemReference theItem;
12358 HFSFlavor data;
12359 FSRef fref;
12360 Size size = sizeof (HFSFlavor);
12361
12362 drag_and_drop_file_list = Qnil;
12363 GetDragMouse (theDrag, &mouse, 0L);
12364 CountDragItems (theDrag, &items);
12365 for (index = 1; index <= items; index++)
12366 {
12367 /* Only handle file references. */
12368 GetDragItemReferenceNumber (theDrag, index, &theItem);
12369 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
12370 if (result == noErr)
12371 {
12372#ifdef MAC_OSX
12373 FSRef frref;
12374#else
12375 Str255 path_name;
12376#endif
12377 Str255 unix_path_name;
12378 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
12379#ifdef MAC_OSX
12380 /* Use Carbon routines, otherwise it converts the file name
12381 to /Macintosh HD/..., which is not correct. */
12382 FSpMakeFSRef (&data.fileSpec, &fref);
12383 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
12384#else
12385 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
12386 data.fileSpec.parID, data.fileSpec.name) &&
12387 mac_to_posix_pathname (path_name, unix_path_name, 255))
12388#endif
12389 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12390 drag_and_drop_file_list);
12391 }
12392 else
12393 return;
12394 }
12395 /* If there are items in the list, construct an event and post it to
12396 the queue like an interrupt using kbd_buffer_store_event. */
12397 if (!NILP (drag_and_drop_file_list))
12398 {
12399 struct input_event event;
12400 Lisp_Object frame;
12401 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
12402 SetPort (GetWindowPort (window));
12403 GlobalToLocal (&mouse);
12404
12405 event.kind = DRAG_N_DROP_EVENT;
12406 event.code = 0;
12407 event.modifiers = 0;
12408 event.timestamp = TickCount () * (1000 / 60);
12409 XSETINT (event.x, mouse.h);
12410 XSETINT (event.y, mouse.v);
12411 XSETFRAME (frame, f);
12412 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
12413 event.arg = Qnil;
12414 /* Post to the interrupt queue */
12415 kbd_buffer_store_event (&event);
12416 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
12417 {
12418 ProcessSerialNumber psn;
12419 GetCurrentProcess (&psn);
12420 SetFrontProcess (&psn);
12421 }
12422 }
12423}
12424
12425
1a578e9b
AC
12426/* Print Document Apple Event */
12427static pascal OSErr
12428do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12429{
12430 return errAEEventNotHandled;
12431}
12432
12433
12434static pascal OSErr
12435do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12436{
12437 /* FixMe: Do we need an unwind-protect or something here? And what
12438 do we do about unsaved files. Currently just forces quit rather
12439 than doing recursive callback to get user input. */
12440
12441 terminate_flag = true;
12442
12443 /* Fkill_emacs doesn't return. We have to return. (TI) */
12444 return noErr;
12445}
12446
12447
12448#if __profile__
12449void
12450profiler_exit_proc ()
12451{
12452 ProfilerDump ("\pEmacs.prof");
12453 ProfilerTerm ();
12454}
12455#endif
12456
12457/* These few functions implement Emacs as a normal Mac application
8c1cc9e8 12458 (almost): set up the heap and the Toolbox, handle necessary
1a578e9b
AC
12459 system events plus a few simple menu events. They also set up
12460 Emacs's access to functions defined in the rest of this file.
12461 Emacs uses function hooks to perform all its terminal I/O. A
12462 complete list of these functions appear in termhooks.h. For what
12463 they do, read the comments there and see also w32term.c and
12464 xterm.c. What's noticeably missing here is the event loop, which
12465 is normally present in most Mac application. After performing the
12466 necessary Mac initializations, main passes off control to
12467 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12468 mac_read_socket (defined further below) to read input. This is
12469 where WaitNextEvent is called to process Mac events. This is also
12470 where check_alarm in sysdep.c is called to simulate alarm signals.
12471 This makes the cursor jump back to its correct position after
12472 briefly jumping to that of the matching parenthesis, print useful
12473 hints and prompts in the minibuffer after the user stops typing for
12474 a wait, etc. */
12475
e0f712ba 12476#if !TARGET_API_MAC_CARBON
1a578e9b
AC
12477#undef main
12478int
12479main (void)
12480{
12481#if __profile__ /* is the profiler on? */
12482 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12483 exit(1);
12484#endif
12485
12486#if __MWERKS__
12487 /* set creator and type for files created by MSL */
12488 _fcreator = 'EMAx';
12489 _ftype = 'TEXT';
12490#endif
12491
12492 do_init_managers ();
12493
12494 do_get_menus ();
12495
2e875e36
AC
12496 do_check_ram_size ();
12497
1a578e9b
AC
12498 init_emacs_passwd_dir ();
12499
12500 init_environ ();
12501
12502 initialize_applescript ();
12503
12504 init_required_apple_events ();
12505
12506 {
12507 char **argv;
12508 int argc = 0;
12509
12510 /* set up argv array from STR# resource */
12511 get_string_list (&argv, ARGV_STRING_LIST_ID);
12512 while (argv[argc])
12513 argc++;
12514
12515 /* free up AppleScript resources on exit */
12516 atexit (terminate_applescript);
12517
12518#if __profile__ /* is the profiler on? */
12519 atexit (profiler_exit_proc);
12520#endif
12521
12522 /* 3rd param "envp" never used in emacs_main */
12523 (void) emacs_main (argc, argv, 0);
12524 }
12525
12526 /* Never reached - real exit in Fkill_emacs */
12527 return 0;
12528}
e0f712ba 12529#endif
1a578e9b
AC
12530
12531/* Table for translating Mac keycode to X keysym values. Contributed
12532 by Sudhir Shenoy. */
12533static unsigned char keycode_to_xkeysym_table[] = {
12534/* 0x00 - 0x3f */
12535 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12536 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12537 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12538 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12539/* 0x40 */
e0f712ba
AC
12540 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12541 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12542 0, 0, 0, '\xaf' /* kp/ */,
12543 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
1a578e9b 12544/* 0x50 */
e0f712ba
AC
12545 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12546 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12547 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12548 '\xb9' /* kp9 */, 0, 0, 0,
1a578e9b 12549/* 0x60 */
e0f712ba
AC
12550 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12551 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12552 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12553 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
1a578e9b 12554/* 0x70 */
e0f712ba
AC
12555 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12556 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12557 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12558 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
1a578e9b
AC
12559};
12560
12561static int
12562keycode_to_xkeysym (int keyCode, int *xKeySym)
12563{
12564 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12565 return *xKeySym != 0;
12566}
12567
12568/* Emacs calls this whenever it wants to read an input event from the
12569 user. */
12570int
12571XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12572{
742fbed7
AC
12573 int count = 0;
12574#if USE_CARBON_EVENTS
12575 OSStatus rneResult;
12576 EventRef eventRef;
12577 EventMouseButton mouseBtn;
12578#endif
1a578e9b
AC
12579 EventRecord er;
12580 int the_modifiers;
12581 EventMask event_mask;
12582
e0f712ba 12583#if 0
1a578e9b
AC
12584 if (interrupt_input_blocked)
12585 {
12586 interrupt_input_pending = 1;
12587 return -1;
12588 }
e0f712ba 12589#endif
1a578e9b
AC
12590
12591 interrupt_input_pending = 0;
12592 BLOCK_INPUT;
12593
12594 /* So people can tell when we have read the available input. */
12595 input_signal_count++;
12596
12597 if (numchars <= 0)
12598 abort ();
12599
12600 /* Don't poll for events to process (specifically updateEvt) if
12601 window update currently already in progress. A call to redisplay
12602 (in do_window_update) can be preempted by another call to
12603 redisplay, causing blank regions to be left on the screen and the
12604 cursor to be left at strange places. */
12605 if (handling_window_update)
12606 {
12607 UNBLOCK_INPUT;
12608 return 0;
12609 }
12610
12611 if (terminate_flag)
12612 Fkill_emacs (make_number (1));
12613
12614 /* It is necessary to set this (additional) argument slot of an
12615 event to nil because keyboard.c protects incompletely processed
12616 event from being garbage collected by placing them in the
12617 kbd_buffer_gcpro vector. */
12618 bufp->arg = Qnil;
12619
12620 event_mask = everyEvent;
8f47302e 12621 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
1a578e9b
AC
12622 event_mask -= highLevelEventMask;
12623
742fbed7
AC
12624#if USE_CARBON_EVENTS
12625 rneResult = ReceiveNextEvent (0, NULL,
44fab9c1
AC
12626 expected
12627 ? TicksToEventTime (app_sleep_time)
12628 : 0,
742fbed7
AC
12629 true, &eventRef);
12630 if (!rneResult)
12631 {
12632 /* Handle new events */
12633 if (!mac_convert_event_ref (eventRef, &er))
12634 switch (GetEventClass (eventRef))
12635 {
12636 case kEventClassMouse:
12637 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
12638 {
12639 SInt32 delta;
12640 Point point;
5883787c 12641 WindowPtr window_ptr = FrontNonFloatingWindow ();
742fbed7
AC
12642 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12643 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
12644 typeSInt32, NULL, sizeof (SInt32),
12645 NULL, &delta);
12646 GetEventParameter(eventRef, kEventParamMouseLocation,
12647 typeQDPoint, NULL, sizeof (Point),
12648 NULL, &point);
12649 bufp->kind = MOUSE_WHEEL_EVENT;
12650 bufp->code = delta;
12651 bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
12652 SetPort (GetWindowPort (window_ptr));
12653 GlobalToLocal (&point);
12654 XSETINT (bufp->x, point.h);
12655 XSETINT (bufp->y, point.v);
12656 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12657 bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
12658 count++;
12659 }
12660 else
12661 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12662
12663 break;
12664 default:
12665 /* Send the event to the appropriate receiver. */
12666 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12667 }
12668 else
12669#else
c7764932 12670 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
742fbed7 12671#endif /* USE_CARBON_EVENTS */
1a578e9b
AC
12672 switch (er.what)
12673 {
12674 case mouseDown:
12675 case mouseUp:
12676 {
12677 WindowPtr window_ptr = FrontWindow ();
12678 SInt16 part_code;
12679
742fbed7 12680#if USE_CARBON_EVENTS
5883787c
AC
12681 /* This is needed to send mouse events like aqua window buttons
12682 to the correct handler. */
12683 if (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
12684 break;
12685 }
12686
12687 if (!is_emacs_window(window_ptr))
12688 break;
742fbed7
AC
12689#endif
12690
1a578e9b
AC
12691 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12692 && er.what == mouseUp)
12693 {
12694 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12695 Point mouse_loc = er.where;
12696
12697 /* Convert to local coordinates of new window. */
e0f712ba
AC
12698#if TARGET_API_MAC_CARBON
12699 SetPort (GetWindowPort (window_ptr));
12700#else
12701 SetPort (window_ptr);
12702#endif
12703
1a578e9b
AC
12704 GlobalToLocal (&mouse_loc);
12705
742fbed7
AC
12706#if USE_CARBON_EVENTS
12707 bufp->code = mac_get_mouse_btn (eventRef);
12708#else
1a578e9b 12709 bufp->code = 0; /* only one mouse button */
742fbed7 12710#endif
3b8f9651 12711 bufp->kind = SCROLL_BAR_CLICK_EVENT;
1a578e9b
AC
12712 bufp->frame_or_window = tracked_scroll_bar->window;
12713 bufp->part = scroll_bar_handle;
742fbed7
AC
12714#if USE_CARBON_EVENTS
12715 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12716#else
12717 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12718#endif
12719 bufp->modifiers |= up_modifier;
1a578e9b
AC
12720 bufp->timestamp = er.when * (1000 / 60);
12721 /* ticks to milliseconds */
12722
12723 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12724 XSETINT (bufp->y, mouse_loc.v - 24);
12725 tracked_scroll_bar->dragging = Qnil;
12726 mouse_tracking_in_progress = mouse_tracking_none;
12727 tracked_scroll_bar = NULL;
12728 count++;
12729 break;
12730 }
12731
12732 part_code = FindWindow (er.where, &window_ptr);
12733
12734 switch (part_code)
12735 {
12736 case inMenuBar:
12737 {
12738 struct frame *f = ((mac_output *)
12739 GetWRefCon (FrontWindow ()))->mFP;
12740 saved_menu_event_location = er.where;
3b8f9651 12741 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
1a578e9b
AC
12742 XSETFRAME (bufp->frame_or_window, f);
12743 count++;
12744 }
12745 break;
12746
12747 case inContent:
12748 if (window_ptr != FrontWindow ())
12749 SelectWindow (window_ptr);
12750 else
12751 {
e0f712ba 12752 SInt16 control_part_code;
1a578e9b
AC
12753 ControlHandle ch;
12754 struct mac_output *mwp = (mac_output *)
12755 GetWRefCon (window_ptr);
12756 Point mouse_loc = er.where;
12757
12758 /* convert to local coordinates of new window */
e0f712ba
AC
12759#if TARGET_API_MAC_CARBON
12760 SetPort (GetWindowPort (window_ptr));
12761#else
12762 SetPort (window_ptr);
12763#endif
12764
1a578e9b 12765 GlobalToLocal (&mouse_loc);
e0f712ba
AC
12766#if TARGET_API_MAC_CARBON
12767 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12768 &control_part_code);
12769#else
1a578e9b 12770 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
e0f712ba 12771#endif
742fbed7
AC
12772
12773#if USE_CARBON_EVENTS
12774 bufp->code = mac_get_mouse_btn (eventRef);
12775#else
1a578e9b 12776 bufp->code = 0; /* only one mouse button */
742fbed7 12777#endif
1a578e9b
AC
12778 XSETINT (bufp->x, mouse_loc.h);
12779 XSETINT (bufp->y, mouse_loc.v);
12780 bufp->timestamp = er.when * (1000 / 60);
12781 /* ticks to milliseconds */
e0f712ba
AC
12782
12783#if TARGET_API_MAC_CARBON
12784 if (ch != 0)
12785#else
1a578e9b 12786 if (control_part_code != 0)
e0f712ba 12787#endif
1a578e9b
AC
12788 {
12789 struct scroll_bar *bar = (struct scroll_bar *)
12790 GetControlReference (ch);
12791 x_scroll_bar_handle_click (bar, control_part_code, &er,
12792 bufp);
12793 if (er.what == mouseDown
12794 && control_part_code == kControlIndicatorPart)
12795 {
e0f712ba
AC
12796 mouse_tracking_in_progress
12797 = mouse_tracking_scroll_bar;
1a578e9b
AC
12798 tracked_scroll_bar = bar;
12799 }
12800 else
12801 {
12802 mouse_tracking_in_progress = mouse_tracking_none;
12803 tracked_scroll_bar = NULL;
12804 }
12805 }
12806 else
12807 {
3b8f9651 12808 bufp->kind = MOUSE_CLICK_EVENT;
1a578e9b
AC
12809 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12810 if (er.what == mouseDown)
e0f712ba
AC
12811 mouse_tracking_in_progress
12812 = mouse_tracking_mouse_movement;
1a578e9b 12813 else
e0f712ba 12814 mouse_tracking_in_progress = mouse_tracking_none;
1a578e9b
AC
12815 }
12816
742fbed7
AC
12817#if USE_CARBON_EVENTS
12818 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12819#else
12820 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12821#endif
12822
1a578e9b
AC
12823 switch (er.what)
12824 {
12825 case mouseDown:
742fbed7 12826 bufp->modifiers |= down_modifier;
1a578e9b
AC
12827 break;
12828 case mouseUp:
742fbed7 12829 bufp->modifiers |= up_modifier;
1a578e9b
AC
12830 break;
12831 }
12832
12833 count++;
12834 }
12835 break;
12836
12837 case inDrag:
e0f712ba
AC
12838#if TARGET_API_MAC_CARBON
12839 {
12840 BitMap bm;
12841
12842 GetQDGlobalsScreenBits (&bm);
12843 DragWindow (window_ptr, er.where, &bm.bounds);
12844 }
12845#else /* not TARGET_API_MAC_CARBON */
1a578e9b 12846 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
e0f712ba 12847#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
12848 break;
12849
12850 case inGoAway:
12851 if (TrackGoAway (window_ptr, er.where))
12852 {
3b8f9651 12853 bufp->kind = DELETE_WINDOW_EVENT;
1a578e9b
AC
12854 XSETFRAME (bufp->frame_or_window,
12855 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12856 count++;
12857 }
12858 break;
12859
12860 /* window resize handling added --ben */
12861 case inGrow:
12862 do_grow_window(window_ptr, &er);
12863 break;
12864
12865 /* window zoom handling added --ben */
12866 case inZoomIn:
12867 case inZoomOut:
12868 if (TrackBox (window_ptr, er.where, part_code))
12869 do_zoom_window (window_ptr, part_code);
12870 break;
12871
12872 default:
12873 break;
12874 }
12875 }
12876 break;
12877
12878 case updateEvt:
12879 case osEvt:
12880 case activateEvt:
742fbed7 12881#if USE_CARBON_EVENTS
5883787c 12882 if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
742fbed7 12883#endif
1a578e9b
AC
12884 do_events (&er);
12885 break;
12886
12887 case keyDown:
12888 case autoKey:
12889 {
12890 int keycode = (er.message & keyCodeMask) >> 8;
12891 int xkeysym;
12892
5883787c
AC
12893#if USE_CARBON_EVENTS
12894 /* When using Carbon Events, we need to pass raw keyboard events
12895 to the TSM ourselves. If TSM handles it, it will pass back
12896 noErr, otherwise it will pass back "eventNotHandledErr" and
12897 we can process it normally. */
12898 if ((!NILP (Vmac_pass_command_to_system)
12899 || !(er.modifiers & cmdKey))
12900 && (!NILP (Vmac_pass_control_to_system)
12901 || !(er.modifiers & controlKey)))
12902 {
12903 OSStatus err;
12904 err = SendEventToEventTarget (eventRef,
12905 GetEventDispatcherTarget ());
12906 if (err != eventNotHandledErr)
12907 break;
12908 }
12909#endif
12910
44fab9c1
AC
12911 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
12912 {
12913 SysBeep (1);
12914 UNBLOCK_INPUT;
12915 return 0;
12916 }
12917
1a578e9b
AC
12918 ObscureCursor ();
12919
12920 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12921 {
12922 bufp->code = 0x7f;
3b8f9651 12923 bufp->kind = ASCII_KEYSTROKE_EVENT;
1a578e9b
AC
12924 }
12925 else if (keycode_to_xkeysym (keycode, &xkeysym))
12926 {
12927 bufp->code = 0xff00 | xkeysym;
3b8f9651 12928 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
742fbed7
AC
12929 }
12930 else if (!NILP (Vmac_reverse_ctrl_meta) && (er.modifiers & controlKey))
12931 {
12932 /* This is a special case to deal with converting from
12933 a control character to non-control character */
12934 int new_modifiers = er.modifiers & ~controlKey;
12935 int new_keycode = keycode | new_modifiers;
12936 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12937 unsigned long some_state = 0;
12938 bufp->code = KeyTranslate (kchr_ptr, new_keycode, &some_state) & 0xff;
12939 bufp->kind = ASCII_KEYSTROKE_EVENT;
12940 }
1a578e9b
AC
12941 else
12942 {
742fbed7 12943 if (er.modifiers & macMetaKey)
1a578e9b
AC
12944 {
12945 /* This code comes from Keyboard Resource, Appendix
12946 C of IM - Text. This is necessary since shift is
12947 ignored in KCHR table translation when option or
12948 command is pressed. */
12949 int new_modifiers = er.modifiers & 0xf600;
12950 /* mask off option and command */
12951 int new_keycode = keycode | new_modifiers;
12952 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12953 unsigned long some_state = 0;
12954 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12955 &some_state) & 0xff;
12956 }
12957 else
12958 bufp->code = er.message & charCodeMask;
3b8f9651 12959 bufp->kind = ASCII_KEYSTROKE_EVENT;
1a578e9b
AC
12960 }
12961 }
12962
12963 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12964 convert non-ASCII characters typed at the Mac keyboard
12965 (presumed to be in the Mac Roman encoding) to iso-latin-1
12966 encoding before they are passed to Emacs. This enables the
12967 Mac keyboard to be used to enter non-ASCII iso-latin-1
12968 characters directly. */
12969 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
3b8f9651 12970 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
1a578e9b
AC
12971 {
12972 static TECObjectRef converter = NULL;
12973 OSStatus the_err = noErr;
12974 OSStatus convert_status = noErr;
12975
12976 if (converter == NULL)
12977 {
12978 the_err = TECCreateConverter (&converter,
12979 kTextEncodingMacRoman,
12980 mac_keyboard_text_encoding);
e0f712ba
AC
12981 current_mac_keyboard_text_encoding
12982 = mac_keyboard_text_encoding;
1a578e9b 12983 }
e0f712ba
AC
12984 else if (mac_keyboard_text_encoding
12985 != current_mac_keyboard_text_encoding)
1a578e9b
AC
12986 {
12987 /* Free the converter for the current encoding before
12988 creating a new one. */
12989 TECDisposeConverter (converter);
12990 the_err = TECCreateConverter (&converter,
12991 kTextEncodingMacRoman,
12992 mac_keyboard_text_encoding);
e0f712ba
AC
12993 current_mac_keyboard_text_encoding
12994 = mac_keyboard_text_encoding;
1a578e9b
AC
12995 }
12996
12997 if (the_err == noErr)
12998 {
12999 unsigned char ch = bufp->code;
13000 ByteCount actual_input_length, actual_output_length;
13001 unsigned char outch;
13002
13003 convert_status = TECConvertText (converter, &ch, 1,
13004 &actual_input_length,
13005 &outch, 1,
13006 &actual_output_length);
13007 if (convert_status == noErr
13008 && actual_input_length == 1
13009 && actual_output_length == 1)
13010 bufp->code = outch;
13011 }
13012 }
13013
742fbed7
AC
13014#if USE_CARBON_EVENTS
13015 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13016#else
13017 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13018#endif
13019
1a578e9b 13020 {
b6cce0b7
AC
13021 mac_output *mwp
13022 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
1a578e9b
AC
13023 XSETFRAME (bufp->frame_or_window, mwp->mFP);
13024 }
13025
13026 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
13027
13028 count++;
13029 break;
13030
13031 case kHighLevelEvent:
13032 drag_and_drop_file_list = Qnil;
8f47302e 13033
1a578e9b
AC
13034 AEProcessAppleEvent(&er);
13035
3b8f9651 13036 /* Build a DRAG_N_DROP_EVENT type event as is done in
1a578e9b
AC
13037 constuct_drag_n_drop in w32term.c. */
13038 if (!NILP (drag_and_drop_file_list))
13039 {
5883787c 13040 struct frame *f = NULL;
1a578e9b
AC
13041 WindowPtr wp;
13042 Lisp_Object frame;
13043
5883787c
AC
13044 wp = FrontNonFloatingWindow ();
13045 if (wp && is_emacs_window(wp))
13046 f = ((mac_output *) GetWRefCon (wp))->mFP;
13047
3b8f9651 13048 bufp->kind = DRAG_N_DROP_EVENT;
1a578e9b
AC
13049 bufp->code = 0;
13050 bufp->timestamp = er.when * (1000 / 60);
13051 /* ticks to milliseconds */
742fbed7
AC
13052#if USE_CARBON_EVENTS
13053 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13054#else
13055 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13056#endif
1a578e9b
AC
13057
13058 XSETINT (bufp->x, 0);
13059 XSETINT (bufp->y, 0);
13060
13061 XSETFRAME (frame, f);
13062 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
13063
13064 /* Regardless of whether Emacs was suspended or in the
13065 foreground, ask it to redraw its entire screen.
13066 Otherwise parts of the screen can be left in an
13067 inconsistent state. */
13068 if (wp)
e0f712ba
AC
13069#if TARGET_API_MAC_CARBON
13070 {
13071 Rect r;
13072
13073 GetWindowPortBounds (wp, &r);
13074 InvalWindowRect (wp, &r);
13075 }
13076#else /* not TARGET_API_MAC_CARBON */
1a578e9b 13077 InvalRect (&(wp->portRect));
e0f712ba 13078#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
13079
13080 count++;
13081 }
1a578e9b
AC
13082 default:
13083 break;
13084 }
742fbed7
AC
13085#if USE_CARBON_EVENTS
13086 ReleaseEvent (eventRef);
13087 }
13088#endif
1a578e9b
AC
13089
13090 /* If the focus was just given to an autoraising frame,
13091 raise it now. */
13092 /* ??? This ought to be able to handle more than one such frame. */
13093 if (pending_autoraise_frame)
13094 {
13095 x_raise_frame (pending_autoraise_frame);
13096 pending_autoraise_frame = 0;
13097 }
13098
e0f712ba 13099#if !TARGET_API_MAC_CARBON
1a578e9b 13100 check_alarm (); /* simulate the handling of a SIGALRM */
e0f712ba 13101#endif
1a578e9b
AC
13102
13103 {
13104 static Point old_mouse_pos = { -1, -1 };
13105
13106 if (app_is_suspended)
13107 {
13108 old_mouse_pos.h = -1;
13109 old_mouse_pos.v = -1;
13110 }
13111 else
13112 {
13113 Point mouse_pos;
e0f712ba
AC
13114 WindowPtr wp;
13115 struct frame *f;
1a578e9b
AC
13116 Lisp_Object bar;
13117 struct scroll_bar *sb;
13118
e0f712ba
AC
13119 wp = FrontWindow ();
13120 if (is_emacs_window (wp))
13121 {
13122 f = ((mac_output *) GetWRefCon (wp))->mFP;
1a578e9b 13123
e0f712ba
AC
13124#if TARGET_API_MAC_CARBON
13125 SetPort (GetWindowPort (wp));
13126#else
13127 SetPort (wp);
13128#endif
13129
13130 GetMouse (&mouse_pos);
13131
13132 if (!EqualPt (mouse_pos, old_mouse_pos))
13133 {
13134 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
13135 && tracked_scroll_bar)
13136 x_scroll_bar_note_movement (tracked_scroll_bar,
13137 mouse_pos.v
13138 - XINT (tracked_scroll_bar->top),
13139 TickCount() * (1000 / 60));
13140 else
13141 note_mouse_movement (f, &mouse_pos);
13142
13143 old_mouse_pos = mouse_pos;
13144 }
13145 }
1a578e9b
AC
13146 }
13147 }
13148
13149 UNBLOCK_INPUT;
13150
13151 return count;
13152}
13153
13154
13155/* Need to override CodeWarrior's input function so no conversion is
13156 done on newlines Otherwise compiled functions in .elc files will be
13157 read incorrectly. Defined in ...:MSL C:MSL
13158 Common:Source:buffer_io.c. */
13159#ifdef __MWERKS__
13160void
13161__convert_to_newlines (unsigned char * p, size_t * n)
13162{
13163#pragma unused(p,n)
13164}
13165
13166void
13167__convert_from_newlines (unsigned char * p, size_t * n)
13168{
13169#pragma unused(p,n)
13170}
13171#endif
13172
13173
13174/* Initialize the struct pointed to by MW to represent a new COLS x
13175 ROWS Macintosh window, using font with name FONTNAME and size
13176 FONTSIZE. */
13177void
13178NewMacWindow (FRAME_PTR fp)
13179{
13180 mac_output *mwp;
e0f712ba
AC
13181#if TARGET_API_MAC_CARBON
13182 static int making_terminal_window = 0;
13183#else
1a578e9b 13184 static int making_terminal_window = 1;
e0f712ba 13185#endif
1a578e9b
AC
13186
13187 mwp = fp->output_data.mac;
13188
13189 if (making_terminal_window)
13190 {
13191 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
13192 (WindowPtr) -1)))
13193 abort ();
13194 making_terminal_window = 0;
13195 }
13196 else
13197 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
13198 abort ();
13199
1a578e9b
AC
13200 SetWRefCon (mwp->mWP, (long) mwp);
13201 /* so that update events can find this mac_output struct */
13202 mwp->mFP = fp; /* point back to emacs frame */
13203
e0f712ba
AC
13204#if TARGET_API_MAC_CARBON
13205 SetPort (GetWindowPort (mwp->mWP));
13206#else
1a578e9b 13207 SetPort (mwp->mWP);
e0f712ba 13208#endif
1a578e9b
AC
13209
13210 mwp->fontset = -1;
13211
13212 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
13213 ShowWindow (mwp->mWP);
13214
13215}
13216
13217
770136ad
RS
13218void
13219make_mac_frame (struct frame *f)
1a578e9b
AC
13220{
13221 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
13222 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
668e2d32
KS
13223
13224 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
13225
1a578e9b 13226 NewMacWindow(f);
1a578e9b
AC
13227
13228 f->output_data.mac->cursor_pixel = 0;
13229 f->output_data.mac->border_pixel = 0x00ff00;
13230 f->output_data.mac->mouse_pixel = 0xff00ff;
13231 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
13232
1a578e9b
AC
13233 f->output_data.mac->fontset = -1;
13234 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13235 f->output_data.mac->scroll_bar_background_pixel = -1;
13236 f->output_data.mac->left_pos = 4;
13237 f->output_data.mac->top_pos = 4;
13238 f->output_data.mac->border_width = 0;
13239 f->output_data.mac->explicit_parent = 0;
13240
13241 f->output_data.mac->internal_border_width = 0;
13242
13243 f->output_method = output_mac;
13244
13245 f->auto_raise = 1;
13246 f->auto_lower = 1;
13247
13248 f->new_width = 0;
13249 f->new_height = 0;
13250}
13251
770136ad
RS
13252void
13253make_mac_terminal_frame (struct frame *f)
1a578e9b
AC
13254{
13255 Lisp_Object frame;
13256
13257 XSETFRAME (frame, f);
13258
13259 f->output_method = output_mac;
13260 f->output_data.mac = (struct mac_output *)
13261 xmalloc (sizeof (struct mac_output));
13262 bzero (f->output_data.mac, sizeof (struct mac_output));
13263 f->output_data.mac->fontset = -1;
13264 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13265 f->output_data.mac->scroll_bar_background_pixel = -1;
13266
13267 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
13268
13269 f->width = 96;
13270 f->height = 4;
13271
13272 make_mac_frame (f);
e0f712ba
AC
13273
13274 x_make_gc (f);
1a578e9b 13275
e0f712ba
AC
13276 /* Need to be initialized for unshow_buffer in window.c. */
13277 selected_window = f->selected_window;
13278
1a578e9b
AC
13279 Fmodify_frame_parameters (frame,
13280 Fcons (Fcons (Qfont,
13281 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
13282 Fmodify_frame_parameters (frame,
13283 Fcons (Fcons (Qforeground_color,
13284 build_string ("black")), Qnil));
13285 Fmodify_frame_parameters (frame,
13286 Fcons (Fcons (Qbackground_color,
13287 build_string ("white")), Qnil));
13288}
13289
e0f712ba
AC
13290\f
13291/***********************************************************************
13292 Initialization
13293 ***********************************************************************/
13294
13295#ifdef USE_X_TOOLKIT
13296static XrmOptionDescRec emacs_options[] = {
13297 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13298 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13299
13300 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13301 XrmoptionSepArg, NULL},
13302 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13303
13304 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13305 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13306 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13307 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13308 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13309 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13310 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13311};
13312#endif /* USE_X_TOOLKIT */
13313
13314#ifdef MULTI_KBOARD
13315/* Test whether two display-name strings agree up to the dot that separates
13316 the screen number from the server number. */
13317static int
13318same_x_server (name1, name2)
13319 char *name1, *name2;
13320{
13321 int seen_colon = 0;
d5db4077 13322 unsigned char *system_name = SDATA (Vsystem_name);
e0f712ba
AC
13323 int system_name_length = strlen (system_name);
13324 int length_until_period = 0;
13325
13326 while (system_name[length_until_period] != 0
13327 && system_name[length_until_period] != '.')
13328 length_until_period++;
13329
13330 /* Treat `unix' like an empty host name. */
13331 if (! strncmp (name1, "unix:", 5))
13332 name1 += 4;
13333 if (! strncmp (name2, "unix:", 5))
13334 name2 += 4;
13335 /* Treat this host's name like an empty host name. */
13336 if (! strncmp (name1, system_name, system_name_length)
13337 && name1[system_name_length] == ':')
13338 name1 += system_name_length;
13339 if (! strncmp (name2, system_name, system_name_length)
13340 && name2[system_name_length] == ':')
13341 name2 += system_name_length;
13342 /* Treat this host's domainless name like an empty host name. */
13343 if (! strncmp (name1, system_name, length_until_period)
13344 && name1[length_until_period] == ':')
13345 name1 += length_until_period;
13346 if (! strncmp (name2, system_name, length_until_period)
13347 && name2[length_until_period] == ':')
13348 name2 += length_until_period;
13349
13350 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13351 {
13352 if (*name1 == ':')
13353 seen_colon++;
13354 if (seen_colon && *name1 == '.')
13355 return 1;
13356 }
13357 return (seen_colon
13358 && (*name1 == '.' || *name1 == '\0')
13359 && (*name2 == '.' || *name2 == '\0'));
13360}
13361#endif
13362
13363int mac_initialized = 0;
13364
1a578e9b
AC
13365void
13366mac_initialize_display_info ()
13367{
13368 struct mac_display_info *dpyinfo = &one_mac_display_info;
13369 GDHandle main_device_handle;
13370
13371 bzero (dpyinfo, sizeof (*dpyinfo));
13372
13373 /* Put it on x_display_name_list. */
13374 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13375 x_display_name_list);
13376 dpyinfo->name_list_element = XCAR (x_display_name_list);
13377
e0f712ba
AC
13378#if 0
13379 dpyinfo->mac_id_name
d5db4077
KR
13380 = (char *) xmalloc (SCHARS (Vinvocation_name)
13381 + SCHARS (Vsystem_name)
e0f712ba
AC
13382 + 2);
13383 sprintf (dpyinfo->mac_id_name, "%s@%s",
d5db4077 13384 SDATA (Vinvocation_name), SDATA (Vsystem_name));
e0f712ba
AC
13385#else
13386 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13387 strcpy (dpyinfo->mac_id_name, "Mac Display");
13388#endif
13389
1a578e9b
AC
13390 main_device_handle = LMGetMainDevice();
13391
13392 dpyinfo->reference_count = 0;
13393 dpyinfo->resx = 75.0;
13394 dpyinfo->resy = 75.0;
13395 dpyinfo->n_planes = 1;
13396 dpyinfo->n_cbits = 16;
13397 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13398 dpyinfo->width = (**main_device_handle).gdRect.right;
13399 dpyinfo->grabbed = 0;
13400 dpyinfo->root_window = NULL;
13401
13402 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13403 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13404 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13405 dpyinfo->mouse_face_window = Qnil;
e0f712ba
AC
13406}
13407
13408struct mac_display_info *
13409mac_term_init (display_name, xrm_option, resource_name)
13410 Lisp_Object display_name;
13411 char *xrm_option;
13412 char *resource_name;
13413{
13414 struct mac_display_info *dpyinfo;
13415 GDHandle main_device_handle;
13416
13417 if (!mac_initialized)
13418 {
13419 mac_initialize ();
13420 mac_initialized = 1;
13421 }
13422
13423 mac_initialize_display_info (display_name);
13424
13425 dpyinfo = &one_mac_display_info;
13426
13427 main_device_handle = LMGetMainDevice();
13428
13429 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13430 dpyinfo->width = (**main_device_handle).gdRect.right;
1a578e9b 13431
e0f712ba 13432 return dpyinfo;
1a578e9b 13433}
e0f712ba 13434\f
8030369c 13435#ifdef MAC_OSX
770136ad
RS
13436void
13437MakeMeTheFrontProcess ()
8030369c
AC
13438{
13439 ProcessSerialNumber psn;
13440 OSErr err;
13441
13442 err = GetCurrentProcess (&psn);
13443 if (err == noErr)
13444 (void) SetFrontProcess (&psn);
13445}
13446#endif /* MAC_OSX */
13447
e0f712ba
AC
13448/* Set up use of X before we make the first connection. */
13449
13450static struct redisplay_interface x_redisplay_interface =
13451{
13452 x_produce_glyphs,
13453 x_write_glyphs,
13454 x_insert_glyphs,
13455 x_clear_end_of_line,
13456 x_scroll_run,
13457 x_after_update_window_line,
13458 x_update_window_begin,
13459 x_update_window_end,
13460 XTcursor_to,
13461 x_flush,
13462 x_clear_mouse_face,
13463 x_get_glyph_overhangs,
13464 x_fix_overlapping_area
13465};
1a578e9b
AC
13466
13467void
e0f712ba 13468mac_initialize ()
1a578e9b
AC
13469{
13470 rif = &x_redisplay_interface;
13471
13472 clear_frame_hook = x_clear_frame;
13473 ins_del_lines_hook = x_ins_del_lines;
1a578e9b
AC
13474 delete_glyphs_hook = x_delete_glyphs;
13475 ring_bell_hook = XTring_bell;
13476 reset_terminal_modes_hook = XTreset_terminal_modes;
13477 set_terminal_modes_hook = XTset_terminal_modes;
13478 update_begin_hook = x_update_begin;
13479 update_end_hook = x_update_end;
13480 set_terminal_window_hook = XTset_terminal_window;
13481 read_socket_hook = XTread_socket;
13482 frame_up_to_date_hook = XTframe_up_to_date;
1a578e9b
AC
13483 mouse_position_hook = XTmouse_position;
13484 frame_rehighlight_hook = XTframe_rehighlight;
13485 frame_raise_lower_hook = XTframe_raise_lower;
13486
13487 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13488 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13489 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13490 judge_scroll_bars_hook = XTjudge_scroll_bars;
13491
13492 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13493
e0f712ba
AC
13494 scroll_region_ok = 1; /* we'll scroll partial frames */
13495 char_ins_del_ok = 1;
13496 line_ins_del_ok = 1; /* we'll just blt 'em */
13497 fast_clear_end_of_line = 1; /* X does this well */
13498 memory_below_frame = 0; /* we don't remember what scrolls
1a578e9b
AC
13499 off the bottom */
13500 baud_rate = 19200;
13501
13502 x_noop_count = 0;
13503 last_tool_bar_item = -1;
13504 any_help_event_p = 0;
13505
13506 /* Try to use interrupt input; if we can't, then start polling. */
13507 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13508
13509#ifdef USE_X_TOOLKIT
13510 XtToolkitInitialize ();
13511 Xt_app_con = XtCreateApplicationContext ();
13512 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13513
13514 /* Install an asynchronous timer that processes Xt timeout events
13515 every 0.1s. This is necessary because some widget sets use
13516 timeouts internally, for example the LessTif menu bar, or the
13517 Xaw3d scroll bar. When Xt timouts aren't processed, these
13518 widgets don't behave normally. */
13519 {
13520 EMACS_TIME interval;
13521 EMACS_SET_SECS_USECS (interval, 0, 100000);
13522 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13523 }
13524#endif
13525
13526#if USE_TOOLKIT_SCROLL_BARS
13527 xaw3d_arrow_scroll = False;
13528 xaw3d_pick_top = True;
13529#endif
13530
13531#if 0
13532 /* Note that there is no real way portable across R3/R4 to get the
13533 original error handler. */
13534 XSetErrorHandler (x_error_handler);
13535 XSetIOErrorHandler (x_io_error_quitter);
13536
13537 /* Disable Window Change signals; they are handled by X events. */
13538#ifdef SIGWINCH
13539 signal (SIGWINCH, SIG_DFL);
13540#endif /* ! defined (SIGWINCH) */
13541
13542 signal (SIGPIPE, x_connection_signal);
13543#endif
13544
13545 mac_initialize_display_info ();
bc21bf11
AC
13546
13547#if TARGET_API_MAC_CARBON
13548 init_required_apple_events ();
13549
742fbed7
AC
13550 init_mac_drag_n_drop ();
13551
13552#if USE_CARBON_EVENTS
13553 init_service_handler ();
13554#endif
13555
bc21bf11 13556 DisableMenuCommand (NULL, kHICommandQuit);
8030369c
AC
13557
13558 if (!inhibit_window_system)
13559 MakeMeTheFrontProcess ();
bc21bf11 13560#endif
1a578e9b
AC
13561}
13562
13563
13564void
13565syms_of_macterm ()
13566{
13567#if 0
13568 staticpro (&x_error_message_string);
13569 x_error_message_string = Qnil;
13570#endif
13571
13572 staticpro (&x_display_name_list);
13573 x_display_name_list = Qnil;
13574
13575 staticpro (&last_mouse_scroll_bar);
13576 last_mouse_scroll_bar = Qnil;
13577
13578 staticpro (&Qvendor_specific_keysyms);
13579 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13580
13581 staticpro (&last_mouse_press_frame);
13582 last_mouse_press_frame = Qnil;
13583
8f47302e
AC
13584 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13585 staticpro (&Qmac_ready_for_drag_n_drop);
13586
1a578e9b
AC
13587 help_echo = Qnil;
13588 staticpro (&help_echo);
13589 help_echo_object = Qnil;
13590 staticpro (&help_echo_object);
13591 help_echo_window = Qnil;
13592 staticpro (&help_echo_window);
13593 previous_help_echo = Qnil;
13594 staticpro (&previous_help_echo);
13595 help_echo_pos = -1;
13596
e0f712ba
AC
13597 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13598 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13599 x_autoselect_window_p = 0;
13600
1a578e9b 13601 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
e0f712ba
AC
13602 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13603For example, if a block cursor is over a tab, it will be drawn as
13604wide as that tab on the display. */);
1a578e9b
AC
13605 x_stretch_cursor_p = 0;
13606
e0f712ba
AC
13607#if 0 /* TODO: Setting underline position from font properties. */
13608 DEFVAR_BOOL ("x-use-underline-position-properties",
13609 &x_use_underline_position_properties,
13610 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13611nil means ignore them. If you encounter fonts with bogus
13612UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13613to 4.1, set this to nil. */);
13614 x_use_underline_position_properties = 1;
1a578e9b
AC
13615#endif
13616
e0f712ba
AC
13617 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13618 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13619 Vx_toolkit_scroll_bars = Qt;
13620
1a578e9b
AC
13621 staticpro (&last_mouse_motion_frame);
13622 last_mouse_motion_frame = Qnil;
13623
13624 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
e0f712ba
AC
13625 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13626Otherwise the option key is used. */);
1a578e9b
AC
13627 Vmac_command_key_is_meta = Qt;
13628
742fbed7
AC
13629 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
13630 doc: /* Non-nil means that the control and meta keys are reversed. This is
13631 useful for non-standard keyboard layouts. */);
13632 Vmac_reverse_ctrl_meta = Qnil;
13633
13634#if USE_CARBON_EVENTS
13635 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
13636 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
13637the right click will be mouse-3.
13638Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
13639 Vmac_wheel_button_is_mouse_2 = Qt;
5883787c
AC
13640
13641 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
13642 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
13643Toolbox for processing before Emacs sees it. */);
13644 Vmac_pass_command_to_system = Qt;
13645
13646 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
13647 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
13648Toolbox for processing before Emacs sees it. */);
13649 Vmac_pass_control_to_system = Qt;
742fbed7
AC
13650#endif
13651
1a578e9b 13652 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
e0f712ba
AC
13653 doc: /* One of the Text Encoding Base constant values defined in the
13654Basic Text Constants section of Inside Macintosh - Text Encoding
13655Conversion Manager. Its value determines the encoding characters
13656typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13657will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13658its default value, no conversion takes place. If it is set to
13659kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13660characters typed on Mac keyboard are first converted into the
13661ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13662passed to Emacs. Together with Emacs's set-keyboard-coding-system
13663command, this enables the Mac keyboard to be used to enter non-ASCII
13664characters directly. */);
1a578e9b
AC
13665 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13666}