Most uses of XSTRING combined with STRING_BYTES or indirection changed to
[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
e0f712ba 61#else /* not MAC_OSX */
1a578e9b
AC
62#include <Quickdraw.h>
63#include <ToolUtils.h>
64#include <Sound.h>
65#include <Events.h>
66#include <Script.h>
67#include <Resources.h>
68#include <Fonts.h>
69#include <TextUtils.h>
70#include <LowMem.h>
71#include <Controls.h>
e0f712ba 72#if defined (__MRC__) || (__MSL__ >= 0x6000)
1a578e9b
AC
73#include <ControlDefinitions.h>
74#endif
e0f712ba 75#include <Gestalt.h>
1a578e9b
AC
76
77#if __profile__
78#include <profiler.h>
79#endif
e0f712ba 80#endif /* not MAC_OSX */
1a578e9b
AC
81
82#include "systty.h"
83#include "systime.h"
e0f712ba
AC
84#include "atimer.h"
85#include "keymap.h"
1a578e9b 86
1a578e9b
AC
87#include <ctype.h>
88#include <errno.h>
89#include <setjmp.h>
90#include <sys/stat.h>
91
e0f712ba 92#include "keyboard.h"
1a578e9b
AC
93#include "frame.h"
94#include "dispextern.h"
95#include "fontset.h"
96#include "termhooks.h"
97#include "termopts.h"
98#include "termchar.h"
99#include "gnu.h"
100#include "disptab.h"
101#include "buffer.h"
102#include "window.h"
1a578e9b 103#include "intervals.h"
e0f712ba 104#include "composite.h"
1a578e9b
AC
105#include "coding.h"
106
1a578e9b
AC
107#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
108
109\f
3f332ef3 110/* Fringe bitmaps. */
1a578e9b 111
3f332ef3 112enum fringe_bitmap_type
1a578e9b 113{
3f332ef3 114 NO_FRINGE_BITMAP,
1a578e9b
AC
115 LEFT_TRUNCATION_BITMAP,
116 RIGHT_TRUNCATION_BITMAP,
117 OVERLAY_ARROW_BITMAP,
118 CONTINUED_LINE_BITMAP,
119 CONTINUATION_LINE_BITMAP,
120 ZV_LINE_BITMAP
121};
122
123/* Bitmap drawn to indicate lines not displaying text if
124 `indicate-empty-lines' is non-nil. */
125
126#define zv_width 8
d33c49e8
KS
127#define zv_height 72
128#define zv_period 3
1a578e9b 129static unsigned char zv_bits[] = {
d33c49e8
KS
130 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
131 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
132 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
133 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
134 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
135 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
136 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
137 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
1a578e9b
AC
138
139/* An arrow like this: `<-'. */
140
141#define left_width 8
142#define left_height 8
143static unsigned char left_bits[] = {
144 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
145
146/* Right truncation arrow bitmap `->'. */
147
148#define right_width 8
149#define right_height 8
150static unsigned char right_bits[] = {
151 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
152
153/* Marker for continued lines. */
154
155#define continued_width 8
156#define continued_height 8
157static unsigned char continued_bits[] = {
158 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
159
160/* Marker for continuation lines. */
161
162#define continuation_width 8
163#define continuation_height 8
164static unsigned char continuation_bits[] = {
165 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
166
167/* Overlay arrow bitmap. */
168
169#if 0
170/* A bomb. */
171#define ov_width 8
172#define ov_height 8
173static unsigned char ov_bits[] = {
174 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
175#else
176/* A triangular arrow. */
177#define ov_width 8
178#define ov_height 8
179static unsigned char ov_bits[] = {
180 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
181#endif
182
183extern Lisp_Object Qhelp_echo;
184
185\f
e0f712ba 186/* Non-nil means Emacs uses toolkit scroll bars. */
1a578e9b 187
e0f712ba 188Lisp_Object Vx_toolkit_scroll_bars;
1a578e9b
AC
189
190/* If a string, XTread_socket generates an event to display that string.
191 (The display is done in read_char.) */
192
193static Lisp_Object help_echo;
194static Lisp_Object help_echo_window;
195static Lisp_Object help_echo_object;
196static int help_echo_pos;
197
198/* Temporary variable for XTread_socket. */
199
200static Lisp_Object previous_help_echo;
201
202/* Non-zero means that a HELP_EVENT has been generated since Emacs
203 start. */
204
205static int any_help_event_p;
206
e0f712ba
AC
207/* Non-zero means autoselect window with the mouse cursor. */
208
209int x_autoselect_window_p;
210
1a578e9b
AC
211/* Non-zero means draw block and hollow cursor as wide as the glyph
212 under it. For example, if a block cursor is over a tab, it will be
213 drawn as wide as that tab on the display. */
214
215int x_stretch_cursor_p;
216
e0f712ba
AC
217/* Non-zero means make use of UNDERLINE_POSITION font properties. */
218
219int x_use_underline_position_properties;
220
1a578e9b
AC
221/* This is a chain of structures for all the X displays currently in
222 use. */
223
224struct x_display_info *x_display_list;
225
226/* This is a list of cons cells, each of the form (NAME
227 . FONT-LIST-CACHE), one for each element of x_display_list and in
228 the same order. NAME is the name of the frame. FONT-LIST-CACHE
229 records previous values returned by x-list-fonts. */
230
231Lisp_Object x_display_name_list;
232
233/* This is display since Mac does not support multiple ones. */
234struct mac_display_info one_mac_display_info;
235
236/* Frame being updated by update_frame. This is declared in term.c.
237 This is set by update_begin and looked at by all the XT functions.
238 It is zero while not inside an update. In that case, the XT
239 functions assume that `selected_frame' is the frame to apply to. */
240
241extern struct frame *updating_frame;
242
e0f712ba
AC
243extern int waiting_for_input;
244
1a578e9b
AC
245/* This is a frame waiting to be auto-raised, within XTread_socket. */
246
247struct frame *pending_autoraise_frame;
248
249/* Nominal cursor position -- where to draw output.
250 HPOS and VPOS are window relative glyph matrix coordinates.
251 X and Y are window relative pixel coordinates. */
252
253struct cursor_pos output_cursor;
254
255/* Non-zero means user is interacting with a toolkit scroll bar. */
256
257static int toolkit_scroll_bar_interaction;
258
259/* Mouse movement.
260
261 Formerly, we used PointerMotionHintMask (in standard_event_mask)
262 so that we would have to call XQueryPointer after each MotionNotify
263 event to ask for another such event. However, this made mouse tracking
264 slow, and there was a bug that made it eventually stop.
265
266 Simply asking for MotionNotify all the time seems to work better.
267
268 In order to avoid asking for motion events and then throwing most
269 of them away or busy-polling the server for mouse positions, we ask
270 the server for pointer motion hints. This means that we get only
271 one event per group of mouse movements. "Groups" are delimited by
272 other kinds of events (focus changes and button clicks, for
273 example), or by XQueryPointer calls; when one of these happens, we
274 get another MotionNotify event the next time the mouse moves. This
275 is at least as efficient as getting motion events when mouse
276 tracking is on, and I suspect only negligibly worse when tracking
277 is off. */
278
279/* Where the mouse was last time we reported a mouse event. */
280
281FRAME_PTR last_mouse_frame;
282static Rect last_mouse_glyph;
283static Lisp_Object last_mouse_press_frame;
284
285/* The scroll bar in which the last X motion event occurred.
286
287 If the last X motion event occurred in a scroll bar, we set this so
288 XTmouse_position can know whether to report a scroll bar motion or
289 an ordinary motion.
290
291 If the last X motion event didn't occur in a scroll bar, we set
292 this to Qnil, to tell XTmouse_position to return an ordinary motion
293 event. */
294
295static Lisp_Object last_mouse_scroll_bar;
296
297/* This is a hack. We would really prefer that XTmouse_position would
298 return the time associated with the position it returns, but there
299 doesn't seem to be any way to wrest the time-stamp from the server
300 along with the position query. So, we just keep track of the time
301 of the last movement we received, and return that in hopes that
302 it's somewhat accurate. */
303
304static Time last_mouse_movement_time;
305
306enum mouse_tracking_type {
307 mouse_tracking_none,
308 mouse_tracking_mouse_movement,
309 mouse_tracking_scroll_bar
310};
311
312enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
313
314struct scroll_bar *tracked_scroll_bar = NULL;
315
316/* Incremented by XTread_socket whenever it really tries to read
317 events. */
318
319#ifdef __STDC__
320static int volatile input_signal_count;
321#else
322static int input_signal_count;
323#endif
324
325/* Used locally within XTread_socket. */
326
327static int x_noop_count;
328
329/* Initial values of argv and argc. */
330
331extern char **initial_argv;
332extern int initial_argc;
333
334extern Lisp_Object Vcommand_line_args, Vsystem_name;
335
336/* Tells if a window manager is present or not. */
337
338extern Lisp_Object Vx_no_window_manager;
339
340extern Lisp_Object Qface, Qmouse_face;
341
342extern int errno;
343
344/* A mask of extra modifier bits to put into every keyboard char. */
345
346extern int extra_keyboard_modifiers;
347
348static Lisp_Object Qvendor_specific_keysyms;
349
350#if 0
351extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
352#endif
353
354extern Lisp_Object x_icon_type P_ ((struct frame *));
355
356
357#if __MRC__
358QDGlobals qd; /* QuickDraw global information structure. */
359#endif
360
361
362/* Enumeration for overriding/changing the face to use for drawing
363 glyphs in x_draw_glyphs. */
364
365enum draw_glyphs_face
366{
367 DRAW_NORMAL_TEXT,
368 DRAW_INVERSE_VIDEO,
369 DRAW_CURSOR,
370 DRAW_MOUSE_FACE,
371 DRAW_IMAGE_RAISED,
372 DRAW_IMAGE_SUNKEN
373};
374
375struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
376struct mac_display_info *mac_display_info_for_display (Display *);
377static void x_update_window_end P_ ((struct window *, int, int));
378static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
1a578e9b 379static int fast_find_position P_ ((struct window *, int, int *, int *,
e0f712ba
AC
380 int *, int *, Lisp_Object));
381static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
382 int *, int *, int *, int *, int));
1a578e9b
AC
383static void set_output_cursor P_ ((struct cursor_pos *));
384static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
e0f712ba 385 int *, int *, int *, int));
1a578e9b
AC
386static void note_mode_line_highlight P_ ((struct window *, int, int));
387static void note_mouse_highlight P_ ((struct frame *, int, int));
388static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
e0f712ba 389static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
1a578e9b
AC
390static void show_mouse_face P_ ((struct x_display_info *,
391 enum draw_glyphs_face));
e0f712ba
AC
392static int cursor_in_mouse_face_p P_ ((struct window *));
393static int clear_mouse_face P_ ((struct mac_display_info *));
1a578e9b
AC
394static int x_io_error_quitter P_ ((Display *));
395int x_catch_errors P_ ((Display *));
396void x_uncatch_errors P_ ((Display *, int));
397void x_lower_frame P_ ((struct frame *));
398void x_scroll_bar_clear P_ ((struct frame *));
399int x_had_errors_p P_ ((Display *));
400void x_wm_set_size_hint P_ ((struct frame *, long, int));
401void x_raise_frame P_ ((struct frame *));
402void x_set_window_size P_ ((struct frame *, int, int, int));
403void x_wm_set_window_state P_ ((struct frame *, int));
404void x_wm_set_icon_pixmap P_ ((struct frame *, int));
e0f712ba 405void mac_initialize P_ ((void));
1a578e9b
AC
406static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
407static int x_compute_min_glyph_bounds P_ ((struct frame *));
408enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
409static void x_draw_phys_cursor_glyph P_ ((struct window *,
410 struct glyph_row *,
411 enum draw_glyphs_face));
412static void x_update_end P_ ((struct frame *));
413static void XTframe_up_to_date P_ ((struct frame *));
414static void XTreassert_line_highlight P_ ((int, int));
415static void x_change_line_highlight P_ ((int, int, int, int));
416static void XTset_terminal_modes P_ ((void));
417static void XTreset_terminal_modes P_ ((void));
418static void XTcursor_to P_ ((int, int, int, int));
419static void x_write_glyphs P_ ((struct glyph *, int));
420static void x_clear_end_of_line P_ ((int));
421static void x_clear_frame P_ ((void));
422static void x_clear_cursor P_ ((struct window *));
423static void frame_highlight P_ ((struct frame *));
424static void frame_unhighlight P_ ((struct frame *));
425static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
426static void XTframe_rehighlight P_ ((struct frame *));
427static void x_frame_rehighlight P_ ((struct x_display_info *));
428static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
429static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
430static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
431static void expose_frame P_ ((struct frame *, int, int, int, int));
e0f712ba
AC
432static int expose_window_tree P_ ((struct window *, Rect *));
433static int expose_window P_ ((struct window *, Rect *));
1a578e9b 434static void expose_area P_ ((struct window *, struct glyph_row *,
e0f712ba
AC
435 Rect *, enum glyph_row_area));
436static int expose_line P_ ((struct window *, struct glyph_row *,
437 Rect *));
1a578e9b
AC
438void x_display_cursor (struct window *, int, int, int, int, int);
439void x_update_cursor P_ ((struct frame *, int));
440static void x_update_cursor_in_window_tree P_ ((struct window *, int));
441static void x_update_window_cursor P_ ((struct window *, int));
442static void x_erase_phys_cursor P_ ((struct window *));
443void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
3f332ef3 444static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
d33c49e8 445 enum fringe_bitmap_type, int left_p));
1a578e9b
AC
446static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
447 GC, int));
448static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
3f332ef3 449static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
e0f712ba
AC
450static void notice_overwritten_cursor P_ ((struct window *,
451 enum glyph_row_area,
452 int, int, int, int));
1a578e9b
AC
453static void x_flush P_ ((struct frame *f));
454static void x_update_begin P_ ((struct frame *));
455static void x_update_window_begin P_ ((struct window *));
456static void x_draw_vertical_border P_ ((struct window *));
457static void x_after_update_window_line P_ ((struct glyph_row *));
458static INLINE void take_vertical_position_into_account P_ ((struct it *));
459static void x_produce_stretch_glyph P_ ((struct it *));
460
461static void activate_scroll_bars (FRAME_PTR);
462static void deactivate_scroll_bars (FRAME_PTR);
463
464extern int image_ascent (struct image *, struct face *);
465void x_set_offset (struct frame *, int, int, int);
466int x_bitmap_icon (struct frame *, Lisp_Object);
467void x_make_frame_visible (struct frame *);
468
469extern void window_scroll (Lisp_Object, int, int, int);
470
471/* Defined in macmenu.h. */
472extern void menubar_selection_callback (FRAME_PTR, int);
473extern void set_frame_menubar (FRAME_PTR, int, int);
474
475/* X display function emulation */
476
477/* Structure borrowed from Xlib.h to represent two-byte characters in
478 dumpglyphs. */
479
480typedef struct {
481 unsigned char byte1;
482 unsigned char byte2;
483} XChar2b;
484
485static void
486XFreePixmap (display, pixmap)
487 Display *display;
488 Pixmap pixmap;
489{
490 PixMap *p = (PixMap *) pixmap;
491
492 xfree (p->baseAddr);
493 xfree (p);
494}
495
496
497/* Set foreground color for subsequent QuickDraw commands. Assume
498 graphic port has already been set. */
499
500static void
501mac_set_forecolor (unsigned long color)
502{
503 RGBColor fg_color;
504
505 fg_color.red = RED_FROM_ULONG (color) * 256;
506 fg_color.green = GREEN_FROM_ULONG (color) * 256;
507 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
508
509 RGBForeColor (&fg_color);
510}
511
512
513/* Set background color for subsequent QuickDraw commands. Assume
514 graphic port has already been set. */
515
516static void
517mac_set_backcolor (unsigned long color)
518{
519 RGBColor bg_color;
520
521 bg_color.red = RED_FROM_ULONG (color) * 256;
522 bg_color.green = GREEN_FROM_ULONG (color) * 256;
523 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
524
525 RGBBackColor (&bg_color);
526}
527
528/* Set foreground and background color for subsequent QuickDraw
529 commands. Assume that the graphic port has already been set. */
530
531static void
532mac_set_colors (GC gc)
533{
534 mac_set_forecolor (gc->foreground);
535 mac_set_backcolor (gc->background);
536}
537
538/* Mac version of XDrawLine. */
539
540static void
541XDrawLine (display, w, gc, x1, y1, x2, y2)
542 Display *display;
543 WindowPtr w;
544 GC gc;
545 int x1, y1, x2, y2;
546{
e0f712ba
AC
547#if TARGET_API_MAC_CARBON
548 SetPort (GetWindowPort (w));
549#else
1a578e9b 550 SetPort (w);
e0f712ba
AC
551#endif
552
1a578e9b
AC
553 mac_set_colors (gc);
554
555 MoveTo (x1, y1);
556 LineTo (x2, y2);
557}
558
559/* Mac version of XClearArea. */
560
2e875e36 561void
1a578e9b
AC
562XClearArea (display, w, x, y, width, height, exposures)
563 Display *display;
564 WindowPtr w;
565 int x, y;
566 unsigned int width, height;
567 int exposures;
568{
569 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
570 Rect r;
571 XGCValues xgc;
572
e0f712ba
AC
573 xgc.foreground = mwp->x_compatible.foreground_pixel;
574 xgc.background = mwp->x_compatible.background_pixel;
1a578e9b 575
e0f712ba
AC
576#if TARGET_API_MAC_CARBON
577 SetPort (GetWindowPort (w));
578#else
1a578e9b 579 SetPort (w);
e0f712ba
AC
580#endif
581
1a578e9b
AC
582 mac_set_colors (&xgc);
583 SetRect (&r, x, y, x + width, y + height);
584
585 EraseRect (&r);
586}
587
588/* Mac version of XClearWindow. */
589
590static void
591XClearWindow (display, w)
592 Display *display;
593 WindowPtr w;
594{
595 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
596 XGCValues xgc;
597
e0f712ba
AC
598 xgc.foreground = mwp->x_compatible.foreground_pixel;
599 xgc.background = mwp->x_compatible.background_pixel;
1a578e9b 600
e0f712ba
AC
601#if TARGET_API_MAC_CARBON
602 SetPort (GetWindowPort (w));
603#else
1a578e9b 604 SetPort (w);
e0f712ba
AC
605#endif
606
1a578e9b
AC
607 mac_set_colors (&xgc);
608
e0f712ba
AC
609#if TARGET_API_MAC_CARBON
610 {
611 Rect r;
612
613 GetWindowPortBounds (w, &r);
614 EraseRect (&r);
615 }
616#else /* not TARGET_API_MAC_CARBON */
617 EraseRect (&(w->portRect));
618#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
619}
620
621
622/* Mac replacement for XCopyArea. */
623
624static void
625mac_draw_bitmap (display, w, gc, x, y, bitmap)
626 Display *display;
627 WindowPtr w;
628 GC gc;
629 int x, y;
630 BitMap *bitmap;
631{
632 Rect r;
633
e0f712ba
AC
634#if TARGET_API_MAC_CARBON
635 SetPort (GetWindowPort (w));
636#else
1a578e9b 637 SetPort (w);
e0f712ba
AC
638#endif
639
1a578e9b
AC
640 mac_set_colors (gc);
641 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
642
e0f712ba
AC
643#if TARGET_API_MAC_CARBON
644 {
645 PixMapHandle pmh;
646
647 LockPortBits (GetWindowPort (w));
648 pmh = GetPortPixMap (GetWindowPort (w));
649 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
650 UnlockPortBits (GetWindowPort (w));
651 }
652#else /* not TARGET_API_MAC_CARBON */
1a578e9b 653 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
e0f712ba 654#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
655}
656
657
658/* Mac replacement for XSetClipRectangles. */
659
660static void
661mac_set_clip_rectangle (display, w, r)
662 Display *display;
663 WindowPtr w;
664 Rect *r;
665{
e0f712ba
AC
666#if TARGET_API_MAC_CARBON
667 SetPort (GetWindowPort (w));
668#else
1a578e9b 669 SetPort (w);
e0f712ba 670#endif
1a578e9b
AC
671
672 ClipRect (r);
673}
674
675
676/* Mac replacement for XSetClipMask. */
677
678static void
679mac_reset_clipping (display, w)
680 Display *display;
681 WindowPtr w;
682{
683 Rect r;
684
e0f712ba
AC
685#if TARGET_API_MAC_CARBON
686 SetPort (GetWindowPort (w));
687#else
1a578e9b 688 SetPort (w);
e0f712ba 689#endif
1a578e9b
AC
690
691 SetRect (&r, -32767, -32767, 32767, 32767);
692 ClipRect (&r);
693}
694
695
696/* Mac replacement for XCreateBitmapFromBitmapData. */
697
698static void
699mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
700 BitMap *bitmap;
701 char *bits;
702 int w, h;
703{
704 int bytes_per_row, i, j;
705
706 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
707 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
708 if (!bitmap->baseAddr)
709 abort ();
710
711 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
712 for (i = 0; i < h; i++)
713 for (j = 0; j < w; j++)
714 if (BitTst (bits, i * w + j))
715 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
716
717 SetRect (&(bitmap->bounds), 0, 0, w, h);
718}
719
720
721static void
722mac_free_bitmap (bitmap)
723 BitMap *bitmap;
724{
725 xfree (bitmap->baseAddr);
726}
727
728/* Mac replacement for XFillRectangle. */
729
730static void
731XFillRectangle (display, w, gc, x, y, width, height)
732 Display *display;
733 WindowPtr w;
734 GC gc;
735 int x, y;
736 unsigned int width, height;
737{
738 Rect r;
739
e0f712ba
AC
740#if TARGET_API_MAC_CARBON
741 SetPort (GetWindowPort (w));
742#else
1a578e9b 743 SetPort (w);
e0f712ba
AC
744#endif
745
1a578e9b
AC
746 mac_set_colors (gc);
747 SetRect (&r, x, y, x + width, y + height);
748
749 PaintRect (&r); /* using foreground color of gc */
750}
751
752
753/* Mac replacement for XDrawRectangle: dest is a window. */
754
755static void
756mac_draw_rectangle (display, w, gc, x, y, width, height)
757 Display *display;
758 WindowPtr w;
759 GC gc;
760 int x, y;
761 unsigned int width, height;
762{
763 Rect r;
764
e0f712ba
AC
765#if TARGET_API_MAC_CARBON
766 SetPort (GetWindowPort (w));
767#else
1a578e9b 768 SetPort (w);
e0f712ba
AC
769#endif
770
1a578e9b
AC
771 mac_set_colors (gc);
772 SetRect (&r, x, y, x + width + 1, y + height + 1);
773
774 FrameRect (&r); /* using foreground color of gc */
775}
776
777
778/* Mac replacement for XDrawRectangle: dest is a Pixmap. */
779
780static void
781mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
782 Display *display;
783 Pixmap p;
784 GC gc;
785 int x, y;
786 unsigned int width, height;
787{
788#if 0 /* MAC_TODO: draw a rectangle in a PixMap */
789 Rect r;
790
e0f712ba
AC
791#if TARGET_API_MAC_CARBON
792 SetPort (GetWindowPort (w));
793#else
1a578e9b 794 SetPort (w);
e0f712ba
AC
795#endif
796
1a578e9b
AC
797 mac_set_colors (gc);
798 SetRect (&r, x, y, x + width, y + height);
799
800 FrameRect (&r); /* using foreground color of gc */
e0f712ba 801#endif /* 0 */
1a578e9b
AC
802}
803
804
805static void
806mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
807 bytes_per_char)
808 Display *display;
809 WindowPtr w;
810 GC gc;
811 int x, y;
812 char *buf;
813 int nchars, mode, bytes_per_char;
814{
e0f712ba
AC
815#if TARGET_API_MAC_CARBON
816 SetPort (GetWindowPort (w));
817#else
1a578e9b 818 SetPort (w);
e0f712ba
AC
819#endif
820
1a578e9b
AC
821 mac_set_colors (gc);
822
823 TextFont (gc->font->mac_fontnum);
824 TextSize (gc->font->mac_fontsize);
825 TextFace (gc->font->mac_fontface);
826 TextMode (mode);
827
828 MoveTo (x, y);
829 DrawText (buf, 0, nchars * bytes_per_char);
830}
831
832
833/* Mac replacement for XDrawString. */
834
835static void
836XDrawString (display, w, gc, x, y, buf, nchars)
837 Display *display;
838 WindowPtr w;
839 GC gc;
840 int x, y;
841 char *buf;
842 int nchars;
843{
844 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
845}
846
847
848/* Mac replacement for XDrawString16. */
849
850static void
851XDrawString16 (display, w, gc, x, y, buf, nchars)
852 Display *display;
853 WindowPtr w;
854 GC gc;
855 int x, y;
856 XChar2b *buf;
857 int nchars;
858{
859 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
860 2);
861}
862
863
864/* Mac replacement for XDrawImageString. */
865
866static void
867XDrawImageString (display, w, gc, x, y, buf, nchars)
868 Display *display;
869 WindowPtr w;
870 GC gc;
871 int x, y;
872 char *buf;
873 int nchars;
874{
875 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
876}
877
878
879/* Mac replacement for XDrawString16. */
880
881static void
882XDrawImageString16 (display, w, gc, x, y, buf, nchars)
883 Display *display;
884 WindowPtr w;
885 GC gc;
886 int x, y;
887 XChar2b *buf;
888 int nchars;
889{
890 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
891 2);
892}
893
894
895/* Mac replacement for XCopyArea: dest must be window. */
896
897static void
898mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
899 dest_y)
900 Display *display;
901 Pixmap src;
902 WindowPtr dest;
903 GC gc;
904 int src_x, src_y;
905 unsigned int width, height;
906 int dest_x, dest_y;
907{
908 Rect src_r, dest_r;
909
e0f712ba
AC
910#if TARGET_API_MAC_CARBON
911 SetPort (GetWindowPort (dest));
912#else
1a578e9b 913 SetPort (dest);
e0f712ba
AC
914#endif
915
1a578e9b
AC
916 mac_set_colors (gc);
917
918 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
919 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
920
e0f712ba
AC
921#if TARGET_API_MAC_CARBON
922 {
923 PixMapHandle pmh;
924
925 LockPortBits (GetWindowPort (dest));
926 pmh = GetPortPixMap (GetWindowPort (dest));
927 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
928 UnlockPortBits (GetWindowPort (dest));
929 }
930#else /* not TARGET_API_MAC_CARBON */
931 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
932#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
933}
934
935
f9e25d0c 936#if 0
1a578e9b
AC
937/* Convert a pair of local coordinates to global (screen) coordinates.
938 Assume graphic port has been properly set. */
939static void
940local_to_global_coord (short *h, short *v)
941{
942 Point p;
943
944 p.h = *h;
945 p.v = *v;
946
947 LocalToGlobal (&p);
948
949 *h = p.h;
950 *v = p.v;
951}
f9e25d0c 952#endif
1a578e9b
AC
953
954/* Mac replacement for XCopyArea: used only for scrolling. */
955
956static void
957mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
958 Display *display;
959 WindowPtr w;
960 GC gc;
961 int src_x, src_y;
962 unsigned int width, height;
963 int dest_x, dest_y;
964{
e0f712ba
AC
965#if TARGET_API_MAC_CARBON
966 Rect gw_r, src_r, dest_r;
967 PixMapHandle pmh;
968
969 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
970 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
971
972 SetPort (GetWindowPort (w));
2d97ff8c
AC
973
974 ForeColor (blackColor);
975 BackColor (whiteColor);
e0f712ba
AC
976
977 LockPortBits (GetWindowPort (w));
978 pmh = GetPortPixMap (GetWindowPort (w));
979 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
980 UnlockPortBits (GetWindowPort (w));
2d97ff8c
AC
981
982 mac_set_colors (gc);
e0f712ba 983#else /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
984 Rect src_r, dest_r;
985
986 SetPort (w);
f9e25d0c 987#if 0
1a578e9b 988 mac_set_colors (gc);
f9e25d0c 989#endif
1a578e9b
AC
990
991 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
992 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
993
f9e25d0c 994#if 0
1a578e9b
AC
995 /* Need to use global coordinates and screenBits since src and dest
996 areas overlap in general. */
997 local_to_global_coord (&src_r.left, &src_r.top);
998 local_to_global_coord (&src_r.right, &src_r.bottom);
999 local_to_global_coord (&dest_r.left, &dest_r.top);
1000 local_to_global_coord (&dest_r.right, &dest_r.bottom);
1001
1002 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
f9e25d0c
AC
1003#else
1004 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1005 color mapping in CopyBits. Otherwise, it will be slow. */
1006 ForeColor (blackColor);
1007 BackColor (whiteColor);
1008 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1009
1010 mac_set_colors (gc);
1011#endif
e0f712ba 1012#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
1013}
1014
1015
1016/* Mac replacement for XCopyArea: dest must be Pixmap. */
1017
1018static void
1019mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1020 dest_x, dest_y)
1021 Display *display;
1022 Pixmap src;
1023 Pixmap dest;
1024 GC gc;
1025 int src_x, src_y;
1026 unsigned int width, height;
1027 int dest_x, dest_y;
1028{
1029 Rect src_r, dest_r;
1030 int src_right = ((PixMap *) src)->bounds.right;
1031 int src_bottom = ((PixMap *) src)->bounds.bottom;
1032 int w = src_right - src_x;
1033 int h = src_bottom - src_y;
1034
1035 mac_set_colors (gc);
1036
1037 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1038 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1039
e0f712ba 1040 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1a578e9b
AC
1041}
1042
1043
1044/* Mac replacement for XChangeGC. */
1045
1046static void
1047XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1048 XGCValues *xgcv)
1049{
1050 if (mask & GCForeground)
1051 gc->foreground = xgcv->foreground;
1052 if (mask & GCBackground)
1053 gc->background = xgcv->background;
1054 if (mask & GCFont)
1055 gc->font = xgcv->font;
1056}
1057
1058
1059/* Mac replacement for XCreateGC. */
1060
1061XGCValues *
1062XCreateGC (void * ignore, Window window, unsigned long mask,
1063 XGCValues *xgcv)
1064{
1065 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1066 bzero (gc, sizeof (XGCValues));
1067
1068 XChangeGC (ignore, gc, mask, xgcv);
1069
1070 return gc;
1071}
1072
1073
1074/* Used in xfaces.c. */
1075
1076void
1077XFreeGC (display, gc)
1078 Display *display;
1079 GC gc;
1080{
1081 xfree (gc);
1082}
1083
1084
1085/* Mac replacement for XGetGCValues. */
1086
1087static void
1088XGetGCValues (void* ignore, XGCValues *gc,
1089 unsigned long mask, XGCValues *xgcv)
1090{
1091 XChangeGC (ignore, xgcv, mask, gc);
1092}
1093
1094
1095/* Mac replacement for XSetForeground. */
1096
1097static void
1098XSetForeground (display, gc, color)
1099 Display *display;
1100 GC gc;
1101 unsigned long color;
1102{
1103 gc->foreground = color;
1104}
1105
1106
1107/* Mac replacement for XSetFont. */
1108
1109static void
1110XSetFont (display, gc, font)
1111 Display *display;
1112 GC gc;
1113 XFontStruct *font;
1114{
1115 gc->font = font;
1116}
1117
1118
1119static void
1120XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1121 int *direction,int *font_ascent,
1122 int *font_descent, XCharStruct *cs)
1123{
1124 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1125}
1126
1127
1128/* x_sync is a no-op on Mac. */
1129void
1130x_sync (f)
1131 void *f;
1132{
1133}
1134
1135
e0f712ba
AC
1136/* Remove calls to XFlush by defining XFlush to an empty replacement.
1137 Calls to XFlush should be unnecessary because the X output buffer
1138 is flushed automatically as needed by calls to XPending,
1139 XNextEvent, or XWindowEvent according to the XFlush man page.
1140 XTread_socket calls XPending. Removing XFlush improves
1141 performance. */
1142
1143#if TARGET_API_MAC_CARBON
1144#define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1145#else
1146#define XFlush(DISPLAY) (void) 0
1147#endif
1148
1a578e9b
AC
1149/* Flush display of frame F, or of all frames if F is null. */
1150
1151void
1152x_flush (f)
1153 struct frame *f;
1154{
e0f712ba 1155#if TARGET_API_MAC_CARBON
1a578e9b
AC
1156 BLOCK_INPUT;
1157 if (f == NULL)
1158 {
1159 Lisp_Object rest, frame;
1160 FOR_EACH_FRAME (rest, frame)
1161 x_flush (XFRAME (frame));
1162 }
1163 else if (FRAME_X_P (f))
1164 XFlush (FRAME_MAC_DISPLAY (f));
1165 UNBLOCK_INPUT;
e0f712ba 1166#endif /* TARGET_API_MAC_CARBON */
1a578e9b
AC
1167}
1168
1169
1a578e9b
AC
1170\f
1171/* Return the struct mac_display_info corresponding to DPY. There's
1172 only one. */
1173
1174struct mac_display_info *
1175mac_display_info_for_display (dpy)
1176 Display *dpy;
1177{
1178 return &one_mac_display_info;
1179}
1180
1181
1182\f
1183/***********************************************************************
1184 Starting and ending an update
1185 ***********************************************************************/
1186
1187/* Start an update of frame F. This function is installed as a hook
1188 for update_begin, i.e. it is called when update_begin is called.
1189 This function is called prior to calls to x_update_window_begin for
e0f712ba 1190 each window being updated. */
1a578e9b 1191
e0f712ba 1192static void
1a578e9b
AC
1193x_update_begin (f)
1194 struct frame *f;
1195{
1196 /* Nothing to do. */
1197}
1198
1199
1200/* Start update of window W. Set the global variable updated_window
1201 to the window being updated and set output_cursor to the cursor
1202 position of W. */
1203
e0f712ba 1204static void
1a578e9b
AC
1205x_update_window_begin (w)
1206 struct window *w;
1207{
1208 struct frame *f = XFRAME (WINDOW_FRAME (w));
1209 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1210
1211 updated_window = w;
1212 set_output_cursor (&w->cursor);
1213
1214 BLOCK_INPUT;
1215
1216 if (f == display_info->mouse_face_mouse_frame)
1217 {
1218 /* Don't do highlighting for mouse motion during the update. */
1219 display_info->mouse_face_defer = 1;
1220
1221 /* If F needs to be redrawn, simply forget about any prior mouse
1222 highlighting. */
1223 if (FRAME_GARBAGED_P (f))
1224 display_info->mouse_face_window = Qnil;
1225
1226#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1227 their mouse_face_p flag set, which means that they are always
1228 unequal to rows in a desired matrix which never have that
1229 flag set. So, rows containing mouse-face glyphs are never
1230 scrolled, and we don't have to switch the mouse highlight off
1231 here to prevent it from being scrolled. */
1232
1233 /* Can we tell that this update does not affect the window
1234 where the mouse highlight is? If so, no need to turn off.
1235 Likewise, don't do anything if the frame is garbaged;
1236 in that case, the frame's current matrix that we would use
1237 is all wrong, and we will redisplay that line anyway. */
1238 if (!NILP (display_info->mouse_face_window)
1239 && w == XWINDOW (display_info->mouse_face_window))
1240 {
1241 int i;
1242
e0f712ba 1243 for (i = 0; i < w->desired_matrix->nrows; ++i)
1a578e9b
AC
1244 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1245 break;
1246
1247 if (i < w->desired_matrix->nrows)
1248 clear_mouse_face (display_info);
1249 }
1250#endif /* 0 */
1251 }
1252
1253 UNBLOCK_INPUT;
1254}
1255
1256
1257/* Draw a vertical window border to the right of window W if W doesn't
1258 have vertical scroll bars. */
1259
1260static void
1261x_draw_vertical_border (w)
1262 struct window *w;
1263{
1264 struct frame *f = XFRAME (WINDOW_FRAME (w));
1265
1266 /* Redraw borders between horizontally adjacent windows. Don't
1267 do it for frames with vertical scroll bars because either the
1268 right scroll bar of a window, or the left scroll bar of its
1269 neighbor will suffice as a border. */
1270 if (!WINDOW_RIGHTMOST_P (w)
1271 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1272 {
1273 int x0, x1, y0, y1;
1274
1275 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
3f332ef3 1276 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1a578e9b
AC
1277 y1 -= 1;
1278
1279 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1280 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1281 }
1282}
e0f712ba 1283
1a578e9b
AC
1284
1285/* End update of window W (which is equal to updated_window).
1286
1287 Draw vertical borders between horizontally adjacent windows, and
1288 display W's cursor if CURSOR_ON_P is non-zero.
1289
1290 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1291 glyphs in mouse-face were overwritten. In that case we have to
1292 make sure that the mouse-highlight is properly redrawn.
1293
1294 W may be a menu bar pseudo-window in case we don't have X toolkit
e0f712ba
AC
1295 support. Such windows don't have a cursor, so don't display it
1296 here. */
1a578e9b 1297
e0f712ba 1298static void
1a578e9b
AC
1299x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1300 struct window *w;
1301 int cursor_on_p, mouse_face_overwritten_p;
1302{
e0f712ba
AC
1303 struct mac_display_info *dpyinfo
1304 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1305
1a578e9b
AC
1306 if (!w->pseudo_window_p)
1307 {
1a578e9b
AC
1308 BLOCK_INPUT;
1309
1a578e9b
AC
1310 if (cursor_on_p)
1311 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1312 output_cursor.vpos,
1313 output_cursor.x, output_cursor.y);
1314
1315 x_draw_vertical_border (w);
1316 UNBLOCK_INPUT;
1317 }
e0f712ba
AC
1318
1319 /* If a row with mouse-face was overwritten, arrange for
1320 XTframe_up_to_date to redisplay the mouse highlight. */
1321 if (mouse_face_overwritten_p)
1322 {
1323 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1324 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1325 dpyinfo->mouse_face_window = Qnil;
1326 }
1327
1328#if 0
1329 /* Unhide the caret. This won't actually show the cursor, unless it
1330 was visible before the corresponding call to HideCaret in
1331 x_update_window_begin. */
1332 if (w32_use_visible_system_caret)
1333 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1334#endif
1335
1a578e9b
AC
1336 updated_window = NULL;
1337}
1338
1339
1340/* End update of frame F. This function is installed as a hook in
1341 update_end. */
1342
e0f712ba 1343static void
1a578e9b
AC
1344x_update_end (f)
1345 struct frame *f;
1346{
1347 /* Reset the background color of Mac OS Window to that of the frame after
1348 update so that it is used by Mac Toolbox to clear the update region before
1349 an update event is generated. */
e0f712ba
AC
1350#if TARGET_API_MAC_CARBON
1351 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1352#else
1a578e9b 1353 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
1354#endif
1355
1a578e9b
AC
1356 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1357
1358 /* Mouse highlight may be displayed again. */
1359 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1360
1361 BLOCK_INPUT;
1362 XFlush (FRAME_MAC_DISPLAY (f));
1363 UNBLOCK_INPUT;
1364}
1365
1366
1367/* This function is called from various places in xdisp.c whenever a
1368 complete update has been performed. The global variable
1369 updated_window is not available here. */
1370
e0f712ba 1371static void
1a578e9b
AC
1372XTframe_up_to_date (f)
1373 struct frame *f;
1374{
1375 if (FRAME_X_P (f))
1376 {
1377 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1378
1379 if (dpyinfo->mouse_face_deferred_gc
1380 || f == dpyinfo->mouse_face_mouse_frame)
1381 {
1382 BLOCK_INPUT;
1383 if (dpyinfo->mouse_face_mouse_frame)
1384 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1385 dpyinfo->mouse_face_mouse_x,
1386 dpyinfo->mouse_face_mouse_y);
1387 dpyinfo->mouse_face_deferred_gc = 0;
1388 UNBLOCK_INPUT;
1389 }
1390 }
1391}
1392
1393
1394/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
3f332ef3 1395 arrow bitmaps, or clear the fringes if no bitmaps are required
1a578e9b 1396 before DESIRED_ROW is made current. The window being updated is
e0f712ba 1397 found in updated_window. This function is called from
1a578e9b
AC
1398 update_window_line only if it is known that there are differences
1399 between bitmaps to be drawn between current row and DESIRED_ROW. */
1400
e0f712ba 1401static void
1a578e9b
AC
1402x_after_update_window_line (desired_row)
1403 struct glyph_row *desired_row;
1404{
1405 struct window *w = updated_window;
e0f712ba
AC
1406 struct frame *f;
1407 int width, height;
1408
1a578e9b
AC
1409 xassert (w);
1410
1411 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1412 {
1413 BLOCK_INPUT;
3f332ef3 1414 x_draw_row_fringe_bitmaps (w, desired_row);
e0f712ba
AC
1415 UNBLOCK_INPUT;
1416 }
1a578e9b 1417
e0f712ba
AC
1418 /* When a window has disappeared, make sure that no rest of
1419 full-width rows stays visible in the internal border. Could
1420 check here if updated_window is the leftmost/rightmost window,
1421 but I guess it's not worth doing since vertically split windows
1422 are almost never used, internal border is rarely set, and the
1423 overhead is very small. */
1424 if (windows_or_buffers_changed
1425 && desired_row->full_width_p
1426 && (f = XFRAME (w->frame),
1427 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1428 width != 0)
1429 && (height = desired_row->visible_height,
1430 height > 0))
1431 {
1432 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1433 /* Internal border is drawn below the tool bar. */
1434 if (WINDOWP (f->tool_bar_window)
1435 && w == XWINDOW (f->tool_bar_window))
1436 y -= width;
1a578e9b 1437
e0f712ba
AC
1438 BLOCK_INPUT;
1439
1440 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1441 0, y, width, height, 0);
1442 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1443 f->output_data.mac->pixel_width - width, y,
1444 width, height, 0);
1a578e9b
AC
1445
1446 UNBLOCK_INPUT;
1447 }
1448}
1449
1450
3f332ef3 1451/* Draw the bitmap WHICH in one of the left or right fringes of
1a578e9b
AC
1452 window W. ROW is the glyph row for which to display the bitmap; it
1453 determines the vertical position at which the bitmap has to be
1454 drawn. */
1455
1456static void
d33c49e8 1457x_draw_fringe_bitmap (w, row, which, left_p)
1a578e9b
AC
1458 struct window *w;
1459 struct glyph_row *row;
3f332ef3 1460 enum fringe_bitmap_type which;
d33c49e8 1461 int left_p;
1a578e9b
AC
1462{
1463 struct frame *f = XFRAME (WINDOW_FRAME (w));
1464 Display *display = FRAME_MAC_DISPLAY (f);
1465 WindowPtr window = FRAME_MAC_WINDOW (f);
1466 int x, y, wd, h, dy;
d33c49e8 1467 int b1, b2;
1a578e9b
AC
1468 unsigned char *bits;
1469 BitMap bitmap;
1470 XGCValues gcv;
e0f712ba 1471 GC gc = f->output_data.mac->normal_gc;
1a578e9b
AC
1472 struct face *face;
1473
1474 /* Must clip because of partially visible lines. */
e0f712ba 1475 x_clip_to_row (w, row, gc, 1);
1a578e9b 1476
d33c49e8
KS
1477 /* Convert row to frame coordinates. */
1478 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1479
1a578e9b
AC
1480 switch (which)
1481 {
d33c49e8
KS
1482 case NO_FRINGE_BITMAP:
1483 wd = 0;
1484 h = 0;
1485 break;
1486
1a578e9b
AC
1487 case LEFT_TRUNCATION_BITMAP:
1488 wd = left_width;
1489 h = left_height;
1490 bits = left_bits;
1a578e9b
AC
1491 break;
1492
1493 case OVERLAY_ARROW_BITMAP:
d33c49e8
KS
1494 wd = ov_width;
1495 h = ov_height;
1a578e9b 1496 bits = ov_bits;
1a578e9b
AC
1497 break;
1498
1499 case RIGHT_TRUNCATION_BITMAP:
1500 wd = right_width;
1501 h = right_height;
1502 bits = right_bits;
1a578e9b
AC
1503 break;
1504
1505 case CONTINUED_LINE_BITMAP:
d33c49e8
KS
1506 wd = continued_width;
1507 h = continued_height;
1a578e9b 1508 bits = continued_bits;
1a578e9b
AC
1509 break;
1510
1511 case CONTINUATION_LINE_BITMAP:
1512 wd = continuation_width;
1513 h = continuation_height;
1514 bits = continuation_bits;
1a578e9b
AC
1515 break;
1516
1517 case ZV_LINE_BITMAP:
1518 wd = zv_width;
d33c49e8
KS
1519 h = zv_height - (y % zv_period);
1520 bits = zv_bits + (y % zv_period);
1a578e9b
AC
1521 break;
1522
1523 default:
1524 abort ();
1525 }
1526
d33c49e8
KS
1527 /* Clip bitmap if too high. */
1528 if (h > row->height)
1529 h = row->height;
1530
1531 /* Set dy to the offset in the row to start drawing the bitmap. */
1a578e9b
AC
1532 dy = (row->height - h) / 2;
1533
e0f712ba 1534 /* Draw the bitmap. */
3f332ef3 1535 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
d33c49e8
KS
1536 PREPARE_FACE_FOR_DISPLAY (f, face);
1537
1538 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1539 the fringe. */
1540 b1 = -1;
1541 if (left_p)
1542 {
1543 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1544 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1545 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1546 - wd
1547 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1548 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1549 {
1550 /* If W has a vertical border to its left, don't draw over it. */
1551 int border = ((XFASTINT (w->left) > 0
1552 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1553 ? 1 : 0);
1554 b1 = (window_box_left (w, -1)
1555 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1556 + border);
1557 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1558 }
1559 }
1560 else
1561 {
1562 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1563 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1564 x = (window_box_right (w, -1)
1565 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1566 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1567 the fringe. */
1568 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1569 {
1570 b1 = window_box_right (w, -1);
1571 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1572 }
1573 }
1574
1575 if (b1 >= 0)
1576 {
1577 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1578 XGCValues gcv;
1579 gcv.foreground = face->background;
1580
1581#if 0 /* MAC_TODO: stipple */
1582 /* In case the same realized face is used for fringes and
1583 for something displayed in the text (e.g. face `region' on
1584 mono-displays, the fill style may have been changed to
1585 FillSolid in x_draw_glyph_string_background. */
1586 if (face->stipple)
1587 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1588 else
1589 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1590#endif
1591
1592 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1593 &gcv,
1594 b1,
1595 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1596 row->y)),
1597 b2,
1598 row->visible_height);
1599
1600#if 0 /* MAC_TODO: stipple */
1601 if (!face->stipple)
1602 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1603#endif
1604 }
1605
1606 if (which == NO_FRINGE_BITMAP)
e0f712ba
AC
1607 {
1608 mac_reset_clipping (display, window);
1609 return;
1610 }
1a578e9b
AC
1611
1612 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1613 gcv.foreground = face->foreground;
1614 gcv.background = face->background;
1615
1616 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1617
1618 mac_free_bitmap (&bitmap);
1619 mac_reset_clipping (display, window);
1620}
1621
1622
3f332ef3 1623/* Draw fringe bitmaps for glyph row ROW on window W. Call this
1a578e9b
AC
1624 function with input blocked. */
1625
1626static void
3f332ef3 1627x_draw_row_fringe_bitmaps (w, row)
1a578e9b
AC
1628 struct window *w;
1629 struct glyph_row *row;
1630{
1631 struct frame *f = XFRAME (w->frame);
3f332ef3 1632 enum fringe_bitmap_type bitmap;
1a578e9b
AC
1633
1634 xassert (interrupt_input_blocked);
1635
1636 /* If row is completely invisible, because of vscrolling, we
1637 don't have to draw anything. */
1638 if (row->visible_height <= 0)
1639 return;
1640
d33c49e8
KS
1641 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1642 {
1643 /* Decide which bitmap to draw in the left fringe. */
1644 if (row->overlay_arrow_p)
1645 bitmap = OVERLAY_ARROW_BITMAP;
1646 else if (row->truncated_on_left_p)
1647 bitmap = LEFT_TRUNCATION_BITMAP;
1648 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1649 bitmap = CONTINUATION_LINE_BITMAP;
1650 else if (row->indicate_empty_line_p)
1651 bitmap = ZV_LINE_BITMAP;
1a578e9b 1652 else
d33c49e8 1653 bitmap = NO_FRINGE_BITMAP;
1a578e9b 1654
d33c49e8
KS
1655 x_draw_fringe_bitmap (w, row, bitmap, 1);
1656 }
1a578e9b 1657
d33c49e8 1658 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1a578e9b 1659 {
d33c49e8
KS
1660 /* Decide which bitmap to draw in the right fringe. */
1661 if (row->truncated_on_right_p)
1662 bitmap = RIGHT_TRUNCATION_BITMAP;
1663 else if (row->continued_p)
1664 bitmap = CONTINUED_LINE_BITMAP;
1665 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1666 bitmap = ZV_LINE_BITMAP;
1a578e9b 1667 else
d33c49e8 1668 bitmap = NO_FRINGE_BITMAP;
1a578e9b 1669
d33c49e8 1670 x_draw_fringe_bitmap (w, row, bitmap, 0);
1a578e9b 1671 }
1a578e9b
AC
1672}
1673
1674\f
1a578e9b 1675/* This is called when starting Emacs and when restarting after
e0f712ba 1676 suspend. When starting Emacs, no window is mapped. And nothing
1a578e9b
AC
1677 must be done to Emacs's own window if it is suspended (though that
1678 rarely happens). */
1679
e0f712ba 1680static void
1a578e9b
AC
1681XTset_terminal_modes ()
1682{
1683}
1684
1685/* This is called when exiting or suspending Emacs. Exiting will make
e0f712ba 1686 the windows go away, and suspending requires no action. */
1a578e9b 1687
e0f712ba 1688static void
1a578e9b
AC
1689XTreset_terminal_modes ()
1690{
1691}
1692
1693
1694\f
1695/***********************************************************************
1696 Output Cursor
1697 ***********************************************************************/
1698
1699/* Set the global variable output_cursor to CURSOR. All cursor
1700 positions are relative to updated_window. */
1701
1702static void
1703set_output_cursor (cursor)
1704 struct cursor_pos *cursor;
1705{
1706 output_cursor.hpos = cursor->hpos;
1707 output_cursor.vpos = cursor->vpos;
1708 output_cursor.x = cursor->x;
1709 output_cursor.y = cursor->y;
1710}
1711
1712
1713/* Set a nominal cursor position.
1714
1715 HPOS and VPOS are column/row positions in a window glyph matrix. X
1716 and Y are window text area relative pixel positions.
1717
1718 If this is done during an update, updated_window will contain the
1719 window that is being updated and the position is the future output
1720 cursor position for that window. If updated_window is null, use
1721 selected_window and display the cursor at the given position. */
1722
e0f712ba 1723static void
1a578e9b
AC
1724XTcursor_to (vpos, hpos, y, x)
1725 int vpos, hpos, y, x;
1726{
1727 struct window *w;
1728
1729 /* If updated_window is not set, work on selected_window. */
1730 if (updated_window)
1731 w = updated_window;
1732 else
1733 w = XWINDOW (selected_window);
1734
1735 /* Set the output cursor. */
1736 output_cursor.hpos = hpos;
1737 output_cursor.vpos = vpos;
1738 output_cursor.x = x;
1739 output_cursor.y = y;
1740
1741 /* If not called as part of an update, really display the cursor.
1742 This will also set the cursor position of W. */
1743 if (updated_window == NULL)
1744 {
1745 BLOCK_INPUT;
1746 x_display_cursor (w, 1, hpos, vpos, x, y);
1747 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1748 UNBLOCK_INPUT;
1749 }
1750}
1751
1752
1753\f
1754/***********************************************************************
1755 Display Iterator
1756 ***********************************************************************/
1757
1758/* Function prototypes of this page. */
1759
1760static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1761 struct glyph *,
1762 XChar2b *,
1763 int *));
1764static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1765 int, XChar2b *, int));
1766static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1767static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1768static void x_append_glyph P_ ((struct it *));
1769static void x_append_composite_glyph P_ ((struct it *));
1770static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1771 int, int, double));
1772static void x_produce_glyphs P_ ((struct it *));
1773static void x_produce_image_glyph P_ ((struct it *it));
1774
1775
1776/* Return a pointer to per-char metric information in FONT of a
1777 character pointed by B which is a pointer to an XChar2b. */
1778
1779#define PER_CHAR_METRIC(font, b) \
1780 ((font)->per_char \
1781 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1782 + (((font)->min_byte1 || (font)->max_byte1) \
1783 ? (((b)->byte1 - (font)->min_byte1) \
1784 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1785 : 0)) \
1786 : &((font)->max_bounds))
1787
1788
1789/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1790 is not contained in the font. */
1791
1792static INLINE XCharStruct *
1793x_per_char_metric (font, char2b)
1794 XFontStruct *font;
1795 XChar2b *char2b;
1796{
1797 /* The result metric information. */
1798 XCharStruct *pcm = NULL;
1799
1800 xassert (font && char2b);
1801
1802 if (font->per_char != NULL)
1803 {
1804 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1805 {
1806 /* min_char_or_byte2 specifies the linear character index
1807 corresponding to the first element of the per_char array,
1808 max_char_or_byte2 is the index of the last character. A
1809 character with non-zero CHAR2B->byte1 is not in the font.
1810 A character with byte2 less than min_char_or_byte2 or
1811 greater max_char_or_byte2 is not in the font. */
1812 if (char2b->byte1 == 0
1813 && char2b->byte2 >= font->min_char_or_byte2
1814 && char2b->byte2 <= font->max_char_or_byte2)
1815 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1816 }
1817 else
1818 {
1819 /* If either min_byte1 or max_byte1 are nonzero, both
1820 min_char_or_byte2 and max_char_or_byte2 are less than
1821 256, and the 2-byte character index values corresponding
1822 to the per_char array element N (counting from 0) are:
1823
1824 byte1 = N/D + min_byte1
1825 byte2 = N\D + min_char_or_byte2
1826
1827 where:
1828
1829 D = max_char_or_byte2 - min_char_or_byte2 + 1
1830 / = integer division
1831 \ = integer modulus */
1832 if (char2b->byte1 >= font->min_byte1
1833 && char2b->byte1 <= font->max_byte1
1834 && char2b->byte2 >= font->min_char_or_byte2
1835 && char2b->byte2 <= font->max_char_or_byte2)
1836 {
1837 pcm = (font->per_char
1838 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1839 * (char2b->byte1 - font->min_byte1))
1840 + (char2b->byte2 - font->min_char_or_byte2));
1841 }
1842 }
1843 }
1844 else
1845 {
1846 /* If the per_char pointer is null, all glyphs between the first
1847 and last character indexes inclusive have the same
1848 information, as given by both min_bounds and max_bounds. */
1849 if (char2b->byte2 >= font->min_char_or_byte2
1850 && char2b->byte2 <= font->max_char_or_byte2)
1851 pcm = &font->max_bounds;
1852 }
1853
1854 return ((pcm == NULL
1855 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1856 ? NULL : pcm);
1857}
1858
1859
1860/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1861 the two-byte form of C. Encoding is returned in *CHAR2B. */
1862
1863static INLINE void
1864x_encode_char (c, char2b, font_info)
1865 int c;
1866 XChar2b *char2b;
1867 struct font_info *font_info;
1868{
1869 int charset = CHAR_CHARSET (c);
1870 XFontStruct *font = font_info->font;
1871
1872 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1873 This may be either a program in a special encoder language or a
1874 fixed encoding. */
1875 if (font_info->font_encoder)
1876 {
1877 /* It's a program. */
1878 struct ccl_program *ccl = font_info->font_encoder;
1879
1880 if (CHARSET_DIMENSION (charset) == 1)
1881 {
1882 ccl->reg[0] = charset;
1883 ccl->reg[1] = char2b->byte2;
1884 }
1885 else
1886 {
1887 ccl->reg[0] = charset;
1888 ccl->reg[1] = char2b->byte1;
1889 ccl->reg[2] = char2b->byte2;
1890 }
1891
1892 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1893
1894 /* We assume that MSBs are appropriately set/reset by CCL
1895 program. */
1896 if (font->max_byte1 == 0) /* 1-byte font */
1897 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1898 else
1899 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1900 }
1901 else if (font_info->encoding[charset])
1902 {
1903 /* Fixed encoding scheme. See fontset.h for the meaning of the
1904 encoding numbers. */
1905 int enc = font_info->encoding[charset];
1906
1907 if ((enc == 1 || enc == 2)
1908 && CHARSET_DIMENSION (charset) == 2)
1909 char2b->byte1 |= 0x80;
1910
1911 if (enc == 1 || enc == 3)
1912 char2b->byte2 |= 0x80;
1913
1914 if (enc == 4)
1915 {
1916 int sjis1, sjis2;
1917
1918 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1919 char2b->byte1 = sjis1;
1920 char2b->byte2 = sjis2;
1921 }
1922 }
1923}
1924
1925
1926/* Get face and two-byte form of character C in face FACE_ID on frame
1927 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1928 means we want to display multibyte text. Value is a pointer to a
1929 realized face that is ready for display. */
1930
1931static INLINE struct face *
1932x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1933 struct frame *f;
1934 int c, face_id;
1935 XChar2b *char2b;
1936 int multibyte_p;
1937{
1938 struct face *face = FACE_FROM_ID (f, face_id);
1939
1940 if (!multibyte_p)
1941 {
1942 /* Unibyte case. We don't have to encode, but we have to make
1943 sure to use a face suitable for unibyte. */
1944 char2b->byte1 = 0;
1945 char2b->byte2 = c;
1946 face_id = FACE_FOR_CHAR (f, face, c);
1947 face = FACE_FROM_ID (f, face_id);
1948 }
1949 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1950 {
1951 /* Case of ASCII in a face known to fit ASCII. */
1952 char2b->byte1 = 0;
1953 char2b->byte2 = c;
1954 }
1955 else
1956 {
1957 int c1, c2, charset;
1958
1959 /* Split characters into bytes. If c2 is -1 afterwards, C is
1960 really a one-byte character so that byte1 is zero. */
1961 SPLIT_CHAR (c, charset, c1, c2);
1962 if (c2 > 0)
1963 char2b->byte1 = c1, char2b->byte2 = c2;
1964 else
1965 char2b->byte1 = 0, char2b->byte2 = c1;
1966
1967 /* Maybe encode the character in *CHAR2B. */
1968 if (face->font != NULL)
1969 {
1970 struct font_info *font_info
1971 = FONT_INFO_FROM_ID (f, face->font_info_id);
1972 if (font_info)
1973 x_encode_char (c, char2b, font_info);
1974 }
1975 }
1976
1977 /* Make sure X resources of the face are allocated. */
1978 xassert (face != NULL);
1979 PREPARE_FACE_FOR_DISPLAY (f, face);
1980
1981 return face;
1982}
1983
1984
1985/* Get face and two-byte form of character glyph GLYPH on frame F.
1986 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1987 a pointer to a realized face that is ready for display. */
1988
1989static INLINE struct face *
1990x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1991 struct frame *f;
1992 struct glyph *glyph;
1993 XChar2b *char2b;
1994 int *two_byte_p;
1995{
1996 struct face *face;
1997
1998 xassert (glyph->type == CHAR_GLYPH);
1999 face = FACE_FROM_ID (f, glyph->face_id);
2000
2001 if (two_byte_p)
2002 *two_byte_p = 0;
2003
2004 if (!glyph->multibyte_p)
2005 {
2006 /* Unibyte case. We don't have to encode, but we have to make
2007 sure to use a face suitable for unibyte. */
2008 char2b->byte1 = 0;
2009 char2b->byte2 = glyph->u.ch;
2010 }
2011 else if (glyph->u.ch < 128
2012 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2013 {
2014 /* Case of ASCII in a face known to fit ASCII. */
2015 char2b->byte1 = 0;
2016 char2b->byte2 = glyph->u.ch;
2017 }
2018 else
2019 {
2020 int c1, c2, charset;
2021
2022 /* Split characters into bytes. If c2 is -1 afterwards, C is
2023 really a one-byte character so that byte1 is zero. */
2024 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2025 if (c2 > 0)
2026 char2b->byte1 = c1, char2b->byte2 = c2;
2027 else
2028 char2b->byte1 = 0, char2b->byte2 = c1;
2029
2030 /* Maybe encode the character in *CHAR2B. */
2031 if (charset != CHARSET_ASCII)
2032 {
2033 struct font_info *font_info
2034 = FONT_INFO_FROM_ID (f, face->font_info_id);
2035 if (font_info)
2036 {
2037 x_encode_char (glyph->u.ch, char2b, font_info);
2038 if (two_byte_p)
2039 *two_byte_p
2040 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2041 }
2042 }
2043 }
2044
2045 /* Make sure X resources of the face are allocated. */
2046 xassert (face != NULL);
2047 PREPARE_FACE_FOR_DISPLAY (f, face);
2048 return face;
2049}
2050
2051
2052/* Store one glyph for IT->char_to_display in IT->glyph_row.
2053 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2054
2055static INLINE void
2056x_append_glyph (it)
2057 struct it *it;
2058{
2059 struct glyph *glyph;
2060 enum glyph_row_area area = it->area;
2061
2062 xassert (it->glyph_row);
2063 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2064
2065 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2066 if (glyph < it->glyph_row->glyphs[area + 1])
2067 {
2068 glyph->charpos = CHARPOS (it->position);
2069 glyph->object = it->object;
2070 glyph->pixel_width = it->pixel_width;
2071 glyph->voffset = it->voffset;
2072 glyph->type = CHAR_GLYPH;
2073 glyph->multibyte_p = it->multibyte_p;
2074 glyph->left_box_line_p = it->start_of_box_run_p;
2075 glyph->right_box_line_p = it->end_of_box_run_p;
2076 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2077 || it->phys_descent > it->descent);
2078 glyph->padding_p = 0;
2079 glyph->glyph_not_available_p = it->glyph_not_available_p;
2080 glyph->face_id = it->face_id;
2081 glyph->u.ch = it->char_to_display;
2082 ++it->glyph_row->used[area];
2083 }
2084}
2085
2086/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2087 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2088
2089static INLINE void
2090x_append_composite_glyph (it)
2091 struct it *it;
2092{
2093 struct glyph *glyph;
2094 enum glyph_row_area area = it->area;
2095
2096 xassert (it->glyph_row);
2097
2098 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2099 if (glyph < it->glyph_row->glyphs[area + 1])
2100 {
2101 glyph->charpos = CHARPOS (it->position);
2102 glyph->object = it->object;
2103 glyph->pixel_width = it->pixel_width;
2104 glyph->voffset = it->voffset;
2105 glyph->type = COMPOSITE_GLYPH;
2106 glyph->multibyte_p = it->multibyte_p;
2107 glyph->left_box_line_p = it->start_of_box_run_p;
2108 glyph->right_box_line_p = it->end_of_box_run_p;
2109 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2110 || it->phys_descent > it->descent);
2111 glyph->padding_p = 0;
2112 glyph->glyph_not_available_p = 0;
2113 glyph->face_id = it->face_id;
2114 glyph->u.cmp_id = it->cmp_id;
2115 ++it->glyph_row->used[area];
2116 }
2117}
2118
2119
2120/* Change IT->ascent and IT->height according to the setting of
2121 IT->voffset. */
2122
2123static INLINE void
2124take_vertical_position_into_account (it)
2125 struct it *it;
2126{
2127 if (it->voffset)
2128 {
2129 if (it->voffset < 0)
2130 /* Increase the ascent so that we can display the text higher
2131 in the line. */
2132 it->ascent += abs (it->voffset);
2133 else
2134 /* Increase the descent so that we can display the text lower
2135 in the line. */
2136 it->descent += it->voffset;
2137 }
2138}
2139
2140
2141/* Produce glyphs/get display metrics for the image IT is loaded with.
2142 See the description of struct display_iterator in dispextern.h for
2143 an overview of struct display_iterator. */
2144
2145static void
2146x_produce_image_glyph (it)
2147 struct it *it;
2148{
2149 struct image *img;
2150 struct face *face;
2151
2152 xassert (it->what == IT_IMAGE);
2153
2154 face = FACE_FROM_ID (it->f, it->face_id);
2155 img = IMAGE_FROM_ID (it->f, it->image_id);
2156 xassert (img);
2157
2158 /* Make sure X resources of the face and image are loaded. */
2159 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2160 prepare_image_for_display (it->f, img);
2161
2162 it->ascent = it->phys_ascent = image_ascent (img, face);
83a96b4d
AC
2163 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2164 it->pixel_width = img->width + 2 * img->hmargin;
1a578e9b
AC
2165
2166 it->nglyphs = 1;
2167
2168 if (face->box != FACE_NO_BOX)
2169 {
e0f712ba
AC
2170 if (face->box_line_width > 0)
2171 {
2172 it->ascent += face->box_line_width;
2173 it->descent += face->box_line_width;
2174 }
1a578e9b
AC
2175
2176 if (it->start_of_box_run_p)
e0f712ba 2177 it->pixel_width += abs (face->box_line_width);
1a578e9b 2178 if (it->end_of_box_run_p)
e0f712ba 2179 it->pixel_width += abs (face->box_line_width);
1a578e9b
AC
2180 }
2181
2182 take_vertical_position_into_account (it);
2183
2184 if (it->glyph_row)
2185 {
2186 struct glyph *glyph;
2187 enum glyph_row_area area = it->area;
2188
2189 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2190 if (glyph < it->glyph_row->glyphs[area + 1])
2191 {
2192 glyph->charpos = CHARPOS (it->position);
2193 glyph->object = it->object;
2194 glyph->pixel_width = it->pixel_width;
2195 glyph->voffset = it->voffset;
2196 glyph->type = IMAGE_GLYPH;
2197 glyph->multibyte_p = it->multibyte_p;
2198 glyph->left_box_line_p = it->start_of_box_run_p;
2199 glyph->right_box_line_p = it->end_of_box_run_p;
2200 glyph->overlaps_vertically_p = 0;
2201 glyph->padding_p = 0;
2202 glyph->glyph_not_available_p = 0;
2203 glyph->face_id = it->face_id;
2204 glyph->u.img_id = img->id;
2205 ++it->glyph_row->used[area];
2206 }
2207 }
2208}
2209
2210
2211/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2212 of the glyph, WIDTH and HEIGHT are the width and height of the
2213 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2214 ascent of the glyph (0 <= ASCENT <= 1). */
2215
2216static void
2217x_append_stretch_glyph (it, object, width, height, ascent)
2218 struct it *it;
2219 Lisp_Object object;
2220 int width, height;
2221 double ascent;
2222{
2223 struct glyph *glyph;
2224 enum glyph_row_area area = it->area;
2225
2226 xassert (ascent >= 0 && ascent <= 1);
2227
2228 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2229 if (glyph < it->glyph_row->glyphs[area + 1])
2230 {
2231 glyph->charpos = CHARPOS (it->position);
2232 glyph->object = object;
2233 glyph->pixel_width = width;
2234 glyph->voffset = it->voffset;
2235 glyph->type = STRETCH_GLYPH;
2236 glyph->multibyte_p = it->multibyte_p;
2237 glyph->left_box_line_p = it->start_of_box_run_p;
2238 glyph->right_box_line_p = it->end_of_box_run_p;
2239 glyph->overlaps_vertically_p = 0;
2240 glyph->padding_p = 0;
2241 glyph->glyph_not_available_p = 0;
2242 glyph->face_id = it->face_id;
2243 glyph->u.stretch.ascent = height * ascent;
2244 glyph->u.stretch.height = height;
2245 ++it->glyph_row->used[area];
2246 }
2247}
2248
2249
2250/* Produce a stretch glyph for iterator IT. IT->object is the value
2251 of the glyph property displayed. The value must be a list
2252 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2253 being recognized:
2254
2255 1. `:width WIDTH' specifies that the space should be WIDTH *
2256 canonical char width wide. WIDTH may be an integer or floating
2257 point number.
2258
2259 2. `:relative-width FACTOR' specifies that the width of the stretch
2260 should be computed from the width of the first character having the
2261 `glyph' property, and should be FACTOR times that width.
2262
2263 3. `:align-to HPOS' specifies that the space should be wide enough
2264 to reach HPOS, a value in canonical character units.
2265
2266 Exactly one of the above pairs must be present.
2267
2268 4. `:height HEIGHT' specifies that the height of the stretch produced
2269 should be HEIGHT, measured in canonical character units.
2270
e0f712ba
AC
2271 5. `:relative-height FACTOR' specifies that the height of the
2272 stretch should be FACTOR times the height of the characters having
2273 the glyph property.
1a578e9b
AC
2274
2275 Either none or exactly one of 4 or 5 must be present.
2276
2277 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2278 of the stretch should be used for the ascent of the stretch.
2279 ASCENT must be in the range 0 <= ASCENT <= 100. */
2280
2281#define NUMVAL(X) \
2282 ((INTEGERP (X) || FLOATP (X)) \
2283 ? XFLOATINT (X) \
2284 : - 1)
2285
2286
2287static void
2288x_produce_stretch_glyph (it)
2289 struct it *it;
2290{
2291 /* (space :width WIDTH :height HEIGHT. */
2292#if GLYPH_DEBUG
2293 extern Lisp_Object Qspace;
2294#endif
2295 extern Lisp_Object QCwidth, QCheight, QCascent;
2296 extern Lisp_Object QCrelative_width, QCrelative_height;
2297 extern Lisp_Object QCalign_to;
2298 Lisp_Object prop, plist;
2299 double width = 0, height = 0, ascent = 0;
2300 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2301 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2302
2303 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2304
2305 /* List should start with `space'. */
2306 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2307 plist = XCDR (it->object);
2308
2309 /* Compute the width of the stretch. */
2310 if (prop = Fplist_get (plist, QCwidth),
2311 NUMVAL (prop) > 0)
2312 /* Absolute width `:width WIDTH' specified and valid. */
2313 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2314 else if (prop = Fplist_get (plist, QCrelative_width),
2315 NUMVAL (prop) > 0)
2316 {
2317 /* Relative width `:relative-width FACTOR' specified and valid.
2318 Compute the width of the characters having the `glyph'
2319 property. */
2320 struct it it2;
2321 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2322
2323 it2 = *it;
2324 if (it->multibyte_p)
2325 {
2326 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2327 - IT_BYTEPOS (*it));
2328 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2329 }
2330 else
2331 it2.c = *p, it2.len = 1;
2332
2333 it2.glyph_row = NULL;
2334 it2.what = IT_CHARACTER;
2335 x_produce_glyphs (&it2);
2336 width = NUMVAL (prop) * it2.pixel_width;
2337 }
2338 else if (prop = Fplist_get (plist, QCalign_to),
2339 NUMVAL (prop) > 0)
2340 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2341 else
2342 /* Nothing specified -> width defaults to canonical char width. */
2343 width = CANON_X_UNIT (it->f);
2344
2345 /* Compute height. */
2346 if (prop = Fplist_get (plist, QCheight),
2347 NUMVAL (prop) > 0)
2348 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2349 else if (prop = Fplist_get (plist, QCrelative_height),
2350 NUMVAL (prop) > 0)
2351 height = FONT_HEIGHT (font) * NUMVAL (prop);
2352 else
2353 height = FONT_HEIGHT (font);
2354
2355 /* Compute percentage of height used for ascent. If
2356 `:ascent ASCENT' is present and valid, use that. Otherwise,
2357 derive the ascent from the font in use. */
2358 if (prop = Fplist_get (plist, QCascent),
2359 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2360 ascent = NUMVAL (prop) / 100.0;
2361 else
e0f712ba 2362 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
1a578e9b
AC
2363
2364 if (width <= 0)
2365 width = 1;
2366 if (height <= 0)
2367 height = 1;
2368
2369 if (it->glyph_row)
2370 {
2371 Lisp_Object object = it->stack[it->sp - 1].string;
2372 if (!STRINGP (object))
2373 object = it->w->buffer;
2374 x_append_stretch_glyph (it, object, width, height, ascent);
2375 }
2376
2377 it->pixel_width = width;
2378 it->ascent = it->phys_ascent = height * ascent;
2379 it->descent = it->phys_descent = height - it->ascent;
2380 it->nglyphs = 1;
2381
2382 if (face->box != FACE_NO_BOX)
2383 {
e0f712ba
AC
2384 if (face->box_line_width > 0)
2385 {
2386 it->ascent += face->box_line_width;
2387 it->descent += face->box_line_width;
2388 }
1a578e9b
AC
2389
2390 if (it->start_of_box_run_p)
e0f712ba 2391 it->pixel_width += abs (face->box_line_width);
1a578e9b 2392 if (it->end_of_box_run_p)
e0f712ba 2393 it->pixel_width += abs (face->box_line_width);
1a578e9b
AC
2394 }
2395
2396 take_vertical_position_into_account (it);
2397}
2398
2399/* Return proper value to be used as baseline offset of font that has
2400 ASCENT and DESCENT to draw characters by the font at the vertical
2401 center of the line of frame F.
2402
2403 Here, out task is to find the value of BOFF in the following figure;
2404
2405 -------------------------+-----------+-
2406 -+-+---------+-+ | |
2407 | | | | | |
2408 | | | | F_ASCENT F_HEIGHT
2409 | | | ASCENT | |
2410 HEIGHT | | | | |
2411 | | |-|-+------+-----------|------- baseline
2412 | | | | BOFF | |
2413 | |---------|-+-+ | |
2414 | | | DESCENT | |
2415 -+-+---------+-+ F_DESCENT |
2416 -------------------------+-----------+-
2417
2418 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2419 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2420 DESCENT = FONT->descent
2421 HEIGHT = FONT_HEIGHT (FONT)
2422 F_DESCENT = (F->output_data.x->font->descent
2423 - F->output_data.x->baseline_offset)
2424 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2425*/
2426
e0f712ba
AC
2427#define VCENTER_BASELINE_OFFSET(FONT, F) \
2428 (FONT_DESCENT (FONT) \
2429 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2430 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2431 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
1a578e9b
AC
2432
2433/* Produce glyphs/get display metrics for the display element IT is
2434 loaded with. See the description of struct display_iterator in
2435 dispextern.h for an overview of struct display_iterator. */
2436
e0f712ba 2437static void
1a578e9b
AC
2438x_produce_glyphs (it)
2439 struct it *it;
2440{
2441 it->glyph_not_available_p = 0;
2442
2443 if (it->what == IT_CHARACTER)
2444 {
2445 XChar2b char2b;
2446 XFontStruct *font;
2447 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2448 XCharStruct *pcm;
2449 int font_not_found_p;
2450 struct font_info *font_info;
e0f712ba
AC
2451 int boff; /* baseline offset */
2452 /* We may change it->multibyte_p upon unibyte<->multibyte
2453 conversion. So, save the current value now and restore it
2454 later.
2455
2456 Note: It seems that we don't have to record multibyte_p in
2457 struct glyph because the character code itself tells if or
2458 not the character is multibyte. Thus, in the future, we must
2459 consider eliminating the field `multibyte_p' in the struct
2460 glyph.
2461 */
2462 int saved_multibyte_p = it->multibyte_p;
1a578e9b
AC
2463
2464 /* Maybe translate single-byte characters to multibyte, or the
e0f712ba 2465 other way. */
1a578e9b
AC
2466 it->char_to_display = it->c;
2467 if (!ASCII_BYTE_P (it->c))
e0f712ba
AC
2468 {
2469 if (unibyte_display_via_language_environment
2470 && SINGLE_BYTE_CHAR_P (it->c)
2471 && (it->c >= 0240
2472 || !NILP (Vnonascii_translation_table)))
2473 {
2474 it->char_to_display = unibyte_char_to_multibyte (it->c);
2475 it->multibyte_p = 1;
1a578e9b
AC
2476 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2477 face = FACE_FROM_ID (it->f, it->face_id);
2478 }
2479 else if (!SINGLE_BYTE_CHAR_P (it->c)
2480 && !it->multibyte_p)
2481 {
e0f712ba 2482 it->multibyte_p = 1;
1a578e9b
AC
2483 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2484 face = FACE_FROM_ID (it->f, it->face_id);
2485 }
e0f712ba 2486 }
1a578e9b
AC
2487
2488 /* Get font to use. Encode IT->char_to_display. */
2489 x_get_char_face_and_encoding (it->f, it->char_to_display,
e0f712ba
AC
2490 it->face_id, &char2b,
2491 it->multibyte_p);
1a578e9b
AC
2492 font = face->font;
2493
2494 /* When no suitable font found, use the default font. */
2495 font_not_found_p = font == NULL;
2496 if (font_not_found_p)
2497 {
2498 font = FRAME_FONT (it->f);
2499 boff = it->f->output_data.mac->baseline_offset;
2500 font_info = NULL;
2501 }
2502 else
2503 {
2504 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2505 boff = font_info->baseline_offset;
2506 if (font_info->vertical_centering)
2507 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2508 }
2509
2510 if (it->char_to_display >= ' '
2511 && (!it->multibyte_p || it->char_to_display < 128))
2512 {
2513 /* Either unibyte or ASCII. */
2514 int stretched_p;
2515
2516 it->nglyphs = 1;
2517
e0f712ba
AC
2518 pcm = x_per_char_metric (font, &char2b);
2519 it->ascent = FONT_BASE (font) + boff;
2520 it->descent = FONT_DESCENT (font) - boff;
1a578e9b 2521
e0f712ba
AC
2522 if (pcm)
2523 {
2524 it->phys_ascent = pcm->ascent + boff;
2525 it->phys_descent = pcm->descent - boff;
2526 it->pixel_width = pcm->width;
2527 }
2528 else
2529 {
2530 it->glyph_not_available_p = 1;
2531 it->phys_ascent = FONT_BASE (font) + boff;
2532 it->phys_descent = FONT_DESCENT (font) - boff;
2533 it->pixel_width = FONT_WIDTH (font);
2534 }
2535
1a578e9b
AC
2536 /* If this is a space inside a region of text with
2537 `space-width' property, change its width. */
2538 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2539 if (stretched_p)
2540 it->pixel_width *= XFLOATINT (it->space_width);
2541
2542 /* If face has a box, add the box thickness to the character
2543 height. If character has a box line to the left and/or
2544 right, add the box line width to the character's width. */
2545 if (face->box != FACE_NO_BOX)
2546 {
2547 int thick = face->box_line_width;
2548
e0f712ba
AC
2549 if (thick > 0)
2550 {
2551 it->ascent += thick;
2552 it->descent += thick;
2553 }
2554 else
2555 thick = -thick;
1a578e9b
AC
2556
2557 if (it->start_of_box_run_p)
2558 it->pixel_width += thick;
2559 if (it->end_of_box_run_p)
2560 it->pixel_width += thick;
2561 }
2562
2563 /* If face has an overline, add the height of the overline
2564 (1 pixel) and a 1 pixel margin to the character height. */
2565 if (face->overline_p)
2566 it->ascent += 2;
2567
2568 take_vertical_position_into_account (it);
2569
2570 /* If we have to actually produce glyphs, do it. */
2571 if (it->glyph_row)
2572 {
2573 if (stretched_p)
2574 {
2575 /* Translate a space with a `space-width' property
2576 into a stretch glyph. */
e0f712ba
AC
2577 double ascent = (double) FONT_BASE (font)
2578 / FONT_HEIGHT (font);
1a578e9b
AC
2579 x_append_stretch_glyph (it, it->object, it->pixel_width,
2580 it->ascent + it->descent, ascent);
2581 }
2582 else
2583 x_append_glyph (it);
2584
2585 /* If characters with lbearing or rbearing are displayed
2586 in this line, record that fact in a flag of the
2587 glyph row. This is used to optimize X output code. */
2588 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2589 it->glyph_row->contains_overlapping_glyphs_p = 1;
2590 }
2591 }
2592 else if (it->char_to_display == '\n')
2593 {
2594 /* A newline has no width but we need the height of the line. */
2595 it->pixel_width = 0;
2596 it->nglyphs = 0;
e0f712ba
AC
2597 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2598 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1a578e9b 2599
e0f712ba
AC
2600 if (face->box != FACE_NO_BOX
2601 && face->box_line_width > 0)
1a578e9b 2602 {
e0f712ba
AC
2603 it->ascent += face->box_line_width;
2604 it->descent += face->box_line_width;
1a578e9b
AC
2605 }
2606 }
2607 else if (it->char_to_display == '\t')
2608 {
2609 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2610 int x = it->current_x + it->continuation_lines_width;
2611 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2612
e0f712ba
AC
2613 /* If the distance from the current position to the next tab
2614 stop is less than a canonical character width, use the
2615 tab stop after that. */
2616 if (next_tab_x - x < CANON_X_UNIT (it->f))
2617 next_tab_x += tab_width;
2618
1a578e9b
AC
2619 it->pixel_width = next_tab_x - x;
2620 it->nglyphs = 1;
e0f712ba
AC
2621 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2622 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2623
2624 if (it->glyph_row)
2625 {
2626 double ascent = (double) it->ascent / (it->ascent + it->descent);
2627 x_append_stretch_glyph (it, it->object, it->pixel_width,
2628 it->ascent + it->descent, ascent);
2629 }
2630 }
2631 else
2632 {
2633 /* A multi-byte character. Assume that the display width of the
2634 character is the width of the character multiplied by the
2635 width of the font. */
2636
2637 /* If we found a font, this font should give us the right
2638 metrics. If we didn't find a font, use the frame's
2639 default font and calculate the width of the character
2640 from the charset width; this is what old redisplay code
2641 did. */
2642 pcm = x_per_char_metric (font, &char2b);
2643 if (font_not_found_p || !pcm)
2644 {
2645 int charset = CHAR_CHARSET (it->char_to_display);
2646
2647 it->glyph_not_available_p = 1;
2648 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2649 * CHARSET_WIDTH (charset));
e0f712ba
AC
2650 it->phys_ascent = FONT_BASE (font) + boff;
2651 it->phys_descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2652 }
2653 else
2654 {
2655 it->pixel_width = pcm->width;
e0f712ba
AC
2656 it->phys_ascent = pcm->ascent + boff;
2657 it->phys_descent = pcm->descent - boff;
2658 if (it->glyph_row
2659 && (pcm->lbearing < 0
2660 || pcm->rbearing > pcm->width))
2661 it->glyph_row->contains_overlapping_glyphs_p = 1;
2662 }
2663 it->nglyphs = 1;
2664 it->ascent = FONT_BASE (font) + boff;
2665 it->descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2666 if (face->box != FACE_NO_BOX)
2667 {
2668 int thick = face->box_line_width;
e0f712ba
AC
2669
2670 if (thick > 0)
2671 {
2672 it->ascent += thick;
2673 it->descent += thick;
2674 }
2675 else
2676 thick = - thick;
1a578e9b
AC
2677
2678 if (it->start_of_box_run_p)
2679 it->pixel_width += thick;
2680 if (it->end_of_box_run_p)
2681 it->pixel_width += thick;
2682 }
2683
2684 /* If face has an overline, add the height of the overline
2685 (1 pixel) and a 1 pixel margin to the character height. */
2686 if (face->overline_p)
2687 it->ascent += 2;
2688
2689 take_vertical_position_into_account (it);
2690
2691 if (it->glyph_row)
2692 x_append_glyph (it);
2693 }
e0f712ba 2694 it->multibyte_p = saved_multibyte_p;
1a578e9b
AC
2695 }
2696 else if (it->what == IT_COMPOSITION)
2697 {
2698 /* Note: A composition is represented as one glyph in the
2699 glyph matrix. There are no padding glyphs. */
2700 XChar2b char2b;
2701 XFontStruct *font;
2702 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2703 XCharStruct *pcm;
2704 int font_not_found_p;
2705 struct font_info *font_info;
2706 int boff; /* baseline offset */
2707 struct composition *cmp = composition_table[it->cmp_id];
2708
2709 /* Maybe translate single-byte characters to multibyte. */
2710 it->char_to_display = it->c;
2711 if (unibyte_display_via_language_environment
2712 && SINGLE_BYTE_CHAR_P (it->c)
2713 && (it->c >= 0240
2714 || (it->c >= 0200
2715 && !NILP (Vnonascii_translation_table))))
2716 {
2717 it->char_to_display = unibyte_char_to_multibyte (it->c);
2718 }
e0f712ba 2719
1a578e9b
AC
2720 /* Get face and font to use. Encode IT->char_to_display. */
2721 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2722 face = FACE_FROM_ID (it->f, it->face_id);
2723 x_get_char_face_and_encoding (it->f, it->char_to_display,
2724 it->face_id, &char2b, it->multibyte_p);
2725 font = face->font;
2726
2727 /* When no suitable font found, use the default font. */
2728 font_not_found_p = font == NULL;
2729 if (font_not_found_p)
2730 {
2731 font = FRAME_FONT (it->f);
2732 boff = it->f->output_data.mac->baseline_offset;
2733 font_info = NULL;
2734 }
2735 else
2736 {
2737 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2738 boff = font_info->baseline_offset;
2739 if (font_info->vertical_centering)
2740 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2741 }
2742
2743 /* There are no padding glyphs, so there is only one glyph to
2744 produce for the composition. Important is that pixel_width,
2745 ascent and descent are the values of what is drawn by
2746 draw_glyphs (i.e. the values of the overall glyphs composed). */
2747 it->nglyphs = 1;
2748
2749 /* If we have not yet calculated pixel size data of glyphs of
2750 the composition for the current face font, calculate them
2751 now. Theoretically, we have to check all fonts for the
2752 glyphs, but that requires much time and memory space. So,
2753 here we check only the font of the first glyph. This leads
2754 to incorrect display very rarely, and C-l (recenter) can
2755 correct the display anyway. */
2756 if (cmp->font != (void *) font)
2757 {
2758 /* Ascent and descent of the font of the first character of
2759 this composition (adjusted by baseline offset). Ascent
2760 and descent of overall glyphs should not be less than
2761 them respectively. */
e0f712ba
AC
2762 int font_ascent = FONT_BASE (font) + boff;
2763 int font_descent = FONT_DESCENT (font) - boff;
1a578e9b
AC
2764 /* Bounding box of the overall glyphs. */
2765 int leftmost, rightmost, lowest, highest;
2766 int i, width, ascent, descent;
2767
2768 cmp->font = (void *) font;
2769
2770 /* Initialize the bounding box. */
2771 pcm = x_per_char_metric (font, &char2b);
2772 if (pcm)
2773 {
2774 width = pcm->width;
2775 ascent = pcm->ascent;
2776 descent = pcm->descent;
2777 }
2778 else
2779 {
2780 width = FONT_WIDTH (font);
e0f712ba
AC
2781 ascent = FONT_BASE (font);
2782 descent = FONT_DESCENT (font);
1a578e9b
AC
2783 }
2784
2785 rightmost = width;
2786 lowest = - descent + boff;
2787 highest = ascent + boff;
2788 leftmost = 0;
2789
2790 if (font_info
2791 && font_info->default_ascent
2792 && CHAR_TABLE_P (Vuse_default_ascent)
2793 && !NILP (Faref (Vuse_default_ascent,
2794 make_number (it->char_to_display))))
2795 highest = font_info->default_ascent + boff;
2796
2797 /* Draw the first glyph at the normal position. It may be
2798 shifted to right later if some other glyphs are drawn at
2799 the left. */
2800 cmp->offsets[0] = 0;
2801 cmp->offsets[1] = boff;
2802
2803 /* Set cmp->offsets for the remaining glyphs. */
2804 for (i = 1; i < cmp->glyph_len; i++)
2805 {
2806 int left, right, btm, top;
2807 int ch = COMPOSITION_GLYPH (cmp, i);
2808 int face_id = FACE_FOR_CHAR (it->f, face, ch);
e0f712ba 2809
1a578e9b
AC
2810 face = FACE_FROM_ID (it->f, face_id);
2811 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2812 it->multibyte_p);
2813 font = face->font;
2814 if (font == NULL)
2815 {
2816 font = FRAME_FONT (it->f);
2817 boff = it->f->output_data.mac->baseline_offset;
2818 font_info = NULL;
2819 }
2820 else
2821 {
2822 font_info
2823 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2824 boff = font_info->baseline_offset;
2825 if (font_info->vertical_centering)
2826 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2827 }
2828
2829 pcm = x_per_char_metric (font, &char2b);
2830 if (pcm)
2831 {
2832 width = pcm->width;
2833 ascent = pcm->ascent;
2834 descent = pcm->descent;
2835 }
2836 else
2837 {
2838 width = FONT_WIDTH (font);
e0f712ba
AC
2839 ascent = 1;
2840 descent = 0;
1a578e9b
AC
2841 }
2842
2843 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2844 {
2845 /* Relative composition with or without
2846 alternate chars. */
2847 left = (leftmost + rightmost - width) / 2;
2848 btm = - descent + boff;
2849 if (font_info && font_info->relative_compose
2850 && (! CHAR_TABLE_P (Vignore_relative_composition)
2851 || NILP (Faref (Vignore_relative_composition,
2852 make_number (ch)))))
2853 {
2854
2855 if (- descent >= font_info->relative_compose)
2856 /* One extra pixel between two glyphs. */
2857 btm = highest + 1;
2858 else if (ascent <= 0)
2859 /* One extra pixel between two glyphs. */
2860 btm = lowest - 1 - ascent - descent;
2861 }
2862 }
2863 else
2864 {
2865 /* A composition rule is specified by an integer
2866 value that encodes global and new reference
2867 points (GREF and NREF). GREF and NREF are
2868 specified by numbers as below:
2869
2870 0---1---2 -- ascent
2871 | |
2872 | |
2873 | |
2874 9--10--11 -- center
2875 | |
2876 ---3---4---5--- baseline
2877 | |
2878 6---7---8 -- descent
2879 */
2880 int rule = COMPOSITION_RULE (cmp, i);
2881 int gref, nref, grefx, grefy, nrefx, nrefy;
2882
2883 COMPOSITION_DECODE_RULE (rule, gref, nref);
2884 grefx = gref % 3, nrefx = nref % 3;
2885 grefy = gref / 3, nrefy = nref / 3;
2886
2887 left = (leftmost
2888 + grefx * (rightmost - leftmost) / 2
2889 - nrefx * width / 2);
2890 btm = ((grefy == 0 ? highest
2891 : grefy == 1 ? 0
2892 : grefy == 2 ? lowest
2893 : (highest + lowest) / 2)
2894 - (nrefy == 0 ? ascent + descent
2895 : nrefy == 1 ? descent - boff
2896 : nrefy == 2 ? 0
2897 : (ascent + descent) / 2));
2898 }
2899
2900 cmp->offsets[i * 2] = left;
2901 cmp->offsets[i * 2 + 1] = btm + descent;
2902
2903 /* Update the bounding box of the overall glyphs. */
2904 right = left + width;
2905 top = btm + descent + ascent;
2906 if (left < leftmost)
2907 leftmost = left;
2908 if (right > rightmost)
2909 rightmost = right;
2910 if (top > highest)
2911 highest = top;
2912 if (btm < lowest)
2913 lowest = btm;
2914 }
2915
2916 /* If there are glyphs whose x-offsets are negative,
2917 shift all glyphs to the right and make all x-offsets
2918 non-negative. */
2919 if (leftmost < 0)
2920 {
2921 for (i = 0; i < cmp->glyph_len; i++)
2922 cmp->offsets[i * 2] -= leftmost;
2923 rightmost -= leftmost;
2924 }
2925
2926 cmp->pixel_width = rightmost;
2927 cmp->ascent = highest;
2928 cmp->descent = - lowest;
2929 if (cmp->ascent < font_ascent)
2930 cmp->ascent = font_ascent;
2931 if (cmp->descent < font_descent)
2932 cmp->descent = font_descent;
2933 }
2934
2935 it->pixel_width = cmp->pixel_width;
2936 it->ascent = it->phys_ascent = cmp->ascent;
2937 it->descent = it->phys_descent = cmp->descent;
2938
2939 if (face->box != FACE_NO_BOX)
2940 {
2941 int thick = face->box_line_width;
e0f712ba
AC
2942
2943 if (thick > 0)
2944 {
2945 it->ascent += thick;
2946 it->descent += thick;
2947 }
2948 else
2949 thick = - thick;
1a578e9b
AC
2950
2951 if (it->start_of_box_run_p)
2952 it->pixel_width += thick;
2953 if (it->end_of_box_run_p)
2954 it->pixel_width += thick;
2955 }
2956
2957 /* If face has an overline, add the height of the overline
2958 (1 pixel) and a 1 pixel margin to the character height. */
2959 if (face->overline_p)
2960 it->ascent += 2;
2961
2962 take_vertical_position_into_account (it);
2963
2964 if (it->glyph_row)
2965 x_append_composite_glyph (it);
2966 }
2967 else if (it->what == IT_IMAGE)
2968 x_produce_image_glyph (it);
2969 else if (it->what == IT_STRETCH)
2970 x_produce_stretch_glyph (it);
2971
2972 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2973 because this isn't true for images with `:ascent 100'. */
2974 xassert (it->ascent >= 0 && it->descent >= 0);
2975 if (it->area == TEXT_AREA)
2976 it->current_x += it->pixel_width;
e0f712ba 2977
1a578e9b 2978 it->descent += it->extra_line_spacing;
e0f712ba 2979
1a578e9b
AC
2980 it->max_ascent = max (it->max_ascent, it->ascent);
2981 it->max_descent = max (it->max_descent, it->descent);
2982 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2983 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2984}
2985
2986
2987/* Estimate the pixel height of the mode or top line on frame F.
2988 FACE_ID specifies what line's height to estimate. */
2989
2990int
2991x_estimate_mode_line_height (f, face_id)
2992 struct frame *f;
2993 enum face_id face_id;
2994{
e0f712ba 2995 int height = FONT_HEIGHT (FRAME_FONT (f));
1a578e9b
AC
2996
2997 /* This function is called so early when Emacs starts that the face
2998 cache and mode line face are not yet initialized. */
2999 if (FRAME_FACE_CACHE (f))
3000 {
3001 struct face *face = FACE_FROM_ID (f, face_id);
3002 if (face)
e0f712ba
AC
3003 {
3004 if (face->font)
3005 height = FONT_HEIGHT (face->font);
3006 if (face->box_line_width > 0)
3007 height += 2 * face->box_line_width;
3008 }
1a578e9b
AC
3009 }
3010
3011 return height;
3012}
3013
3014\f
3015/***********************************************************************
3016 Glyph display
3017 ***********************************************************************/
3018
3019/* A sequence of glyphs to be drawn in the same face.
3020
3021 This data structure is not really completely X specific, so it
3022 could possibly, at least partially, be useful for other systems. It
3023 is currently not part of the external redisplay interface because
3024 it's not clear what other systems will need. */
3025
3026struct glyph_string
3027{
3028 /* X-origin of the string. */
3029 int x;
3030
3031 /* Y-origin and y-position of the base line of this string. */
3032 int y, ybase;
3033
3034 /* The width of the string, not including a face extension. */
3035 int width;
3036
3037 /* The width of the string, including a face extension. */
3038 int background_width;
3039
3040 /* The height of this string. This is the height of the line this
3041 string is drawn in, and can be different from the height of the
3042 font the string is drawn in. */
3043 int height;
3044
3045 /* Number of pixels this string overwrites in front of its x-origin.
3046 This number is zero if the string has an lbearing >= 0; it is
3047 -lbearing, if the string has an lbearing < 0. */
3048 int left_overhang;
3049
3050 /* Number of pixels this string overwrites past its right-most
3051 nominal x-position, i.e. x + width. Zero if the string's
3052 rbearing is <= its nominal width, rbearing - width otherwise. */
3053 int right_overhang;
3054
3055 /* The frame on which the glyph string is drawn. */
3056 struct frame *f;
3057
3058 /* The window on which the glyph string is drawn. */
3059 struct window *w;
3060
3061 /* X display and window for convenience. */
3062 Display *display;
3063 Window window;
3064
3065 /* The glyph row for which this string was built. It determines the
3066 y-origin and height of the string. */
3067 struct glyph_row *row;
3068
3069 /* The area within row. */
3070 enum glyph_row_area area;
3071
3072 /* Characters to be drawn, and number of characters. */
3073 XChar2b *char2b;
3074 int nchars;
3075
3076 /* A face-override for drawing cursors, mouse face and similar. */
3077 enum draw_glyphs_face hl;
3078
3079 /* Face in which this string is to be drawn. */
3080 struct face *face;
3081
3082 /* Font in which this string is to be drawn. */
3083 XFontStruct *font;
3084
3085 /* Font info for this string. */
3086 struct font_info *font_info;
3087
3088 /* Non-null means this string describes (part of) a composition.
3089 All characters from char2b are drawn composed. */
3090 struct composition *cmp;
3091
3092 /* Index of this glyph string's first character in the glyph
3093 definition of CMP. If this is zero, this glyph string describes
3094 the first character of a composition. */
3095 int gidx;
3096
3097 /* 1 means this glyph strings face has to be drawn to the right end
3098 of the window's drawing area. */
3099 unsigned extends_to_end_of_line_p : 1;
3100
3101 /* 1 means the background of this string has been drawn. */
3102 unsigned background_filled_p : 1;
3103
3104 /* 1 means glyph string must be drawn with 16-bit functions. */
3105 unsigned two_byte_p : 1;
3106
3107 /* 1 means that the original font determined for drawing this glyph
3108 string could not be loaded. The member `font' has been set to
3109 the frame's default font in this case. */
3110 unsigned font_not_found_p : 1;
3111
3112 /* 1 means that the face in which this glyph string is drawn has a
3113 stipple pattern. */
3114 unsigned stippled_p : 1;
3115
3116 /* 1 means only the foreground of this glyph string must be drawn,
3117 and we should use the physical height of the line this glyph
3118 string appears in as clip rect. */
3119 unsigned for_overlaps_p : 1;
3120
3121 /* The GC to use for drawing this glyph string. */
3122 GC gc;
3123
3124 /* A pointer to the first glyph in the string. This glyph
3125 corresponds to char2b[0]. Needed to draw rectangles if
3126 font_not_found_p is 1. */
3127 struct glyph *first_glyph;
3128
3129 /* Image, if any. */
3130 struct image *img;
3131
3132 struct glyph_string *next, *prev;
3133};
3134
3135
3136#if 0
3137
3138static void
3139x_dump_glyph_string (s)
3140 struct glyph_string *s;
3141{
3142 fprintf (stderr, "glyph string\n");
3143 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3144 s->x, s->y, s->width, s->height);
3145 fprintf (stderr, " ybase = %d\n", s->ybase);
3146 fprintf (stderr, " hl = %d\n", s->hl);
3147 fprintf (stderr, " left overhang = %d, right = %d\n",
3148 s->left_overhang, s->right_overhang);
3149 fprintf (stderr, " nchars = %d\n", s->nchars);
3150 fprintf (stderr, " extends to end of line = %d\n",
3151 s->extends_to_end_of_line_p);
3152 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3153 fprintf (stderr, " bg width = %d\n", s->background_width);
3154}
3155
3156#endif /* GLYPH_DEBUG */
3157
3158
3159
3160static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3161 struct glyph_string **,
3162 struct glyph_string *,
3163 struct glyph_string *));
3164static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3165 struct glyph_string **,
3166 struct glyph_string *,
3167 struct glyph_string *));
3168static void x_append_glyph_string P_ ((struct glyph_string **,
3169 struct glyph_string **,
3170 struct glyph_string *));
3171static int x_left_overwritten P_ ((struct glyph_string *));
3172static int x_left_overwriting P_ ((struct glyph_string *));
3173static int x_right_overwritten P_ ((struct glyph_string *));
3174static int x_right_overwriting P_ ((struct glyph_string *));
3175static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3176 int));
3177static void x_init_glyph_string P_ ((struct glyph_string *,
3178 XChar2b *, struct window *,
3179 struct glyph_row *,
3180 enum glyph_row_area, int,
3181 enum draw_glyphs_face));
3182static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3183 enum glyph_row_area, int, int,
e0f712ba 3184 enum draw_glyphs_face, int));
1a578e9b
AC
3185static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3186static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3187static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3188 int));
3189static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3190static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3191static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3192static void x_draw_glyph_string P_ ((struct glyph_string *));
3193static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3194static void x_set_cursor_gc P_ ((struct glyph_string *));
3195static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3196static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3197static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3198 int *, int *));
3199static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
e0f712ba
AC
3200/*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3201 unsigned long *, double, int));*/
1a578e9b
AC
3202static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3203 double, int, unsigned long));
3204static void x_setup_relief_colors P_ ((struct glyph_string *));
3205static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3206static void x_draw_image_relief P_ ((struct glyph_string *));
3207static void x_draw_image_foreground P_ ((struct glyph_string *));
3208static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3209static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3210static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3211 int, int, int));
3212static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
e0f712ba 3213 int, int, int, int, Rect *));
1a578e9b 3214static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
e0f712ba 3215 int, int, int, Rect *));
1a578e9b
AC
3216static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3217 enum glyph_row_area));
3218static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3219 struct glyph_row *,
3220 enum glyph_row_area, int, int));
3221
3222#if GLYPH_DEBUG
3223static void x_check_font P_ ((struct frame *, XFontStruct *));
3224#endif
3225
e0f712ba 3226
1a578e9b
AC
3227/* Append the list of glyph strings with head H and tail T to the list
3228 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3229
3230static INLINE void
3231x_append_glyph_string_lists (head, tail, h, t)
3232 struct glyph_string **head, **tail;
3233 struct glyph_string *h, *t;
3234{
3235 if (h)
3236 {
3237 if (*head)
3238 (*tail)->next = h;
3239 else
3240 *head = h;
3241 h->prev = *tail;
3242 *tail = t;
3243 }
3244}
3245
3246
3247/* Prepend the list of glyph strings with head H and tail T to the
3248 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3249 result. */
3250
3251static INLINE void
3252x_prepend_glyph_string_lists (head, tail, h, t)
3253 struct glyph_string **head, **tail;
3254 struct glyph_string *h, *t;
3255{
3256 if (h)
3257 {
3258 if (*head)
3259 (*head)->prev = t;
3260 else
3261 *tail = t;
3262 t->next = *head;
3263 *head = h;
3264 }
3265}
3266
3267
3268/* Append glyph string S to the list with head *HEAD and tail *TAIL.
3269 Set *HEAD and *TAIL to the resulting list. */
3270
3271static INLINE void
3272x_append_glyph_string (head, tail, s)
3273 struct glyph_string **head, **tail;
3274 struct glyph_string *s;
3275{
3276 s->next = s->prev = NULL;
3277 x_append_glyph_string_lists (head, tail, s, s);
3278}
3279
3280
3281/* Set S->gc to a suitable GC for drawing glyph string S in cursor
3282 face. */
3283
3284static void
3285x_set_cursor_gc (s)
3286 struct glyph_string *s;
3287{
3288 if (s->font == FRAME_FONT (s->f)
3289 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3290 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3291 && !s->cmp)
3292 s->gc = s->f->output_data.mac->cursor_gc;
3293 else
3294 {
3295 /* Cursor on non-default face: must merge. */
3296 XGCValues xgcv;
3297 unsigned long mask;
3298
3299 xgcv.background = s->f->output_data.mac->cursor_pixel;
3300 xgcv.foreground = s->face->background;
3301
3302 /* If the glyph would be invisible, try a different foreground. */
3303 if (xgcv.foreground == xgcv.background)
3304 xgcv.foreground = s->face->foreground;
3305 if (xgcv.foreground == xgcv.background)
3306 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3307 if (xgcv.foreground == xgcv.background)
3308 xgcv.foreground = s->face->foreground;
3309
3310 /* Make sure the cursor is distinct from text in this face. */
3311 if (xgcv.background == s->face->background
3312 && xgcv.foreground == s->face->foreground)
3313 {
3314 xgcv.background = s->face->foreground;
3315 xgcv.foreground = s->face->background;
3316 }
3317
3318 IF_DEBUG (x_check_font (s->f, s->font));
3319 xgcv.font = s->font;
3320 mask = GCForeground | GCBackground | GCFont;
3321
3322 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3323 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3324 mask, &xgcv);
3325 else
3326 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3327 = XCreateGC (s->display, s->window, mask, &xgcv);
3328
3329 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3330 }
3331}
3332
3333
3334/* Set up S->gc of glyph string S for drawing text in mouse face. */
3335
3336static void
3337x_set_mouse_face_gc (s)
3338 struct glyph_string *s;
3339{
3340 int face_id;
3341 struct face *face;
3342
e0f712ba 3343 /* What face has to be used last for the mouse face? */
1a578e9b
AC
3344 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3345 face = FACE_FROM_ID (s->f, face_id);
e0f712ba
AC
3346 if (face == NULL)
3347 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3348
1a578e9b
AC
3349 if (s->first_glyph->type == CHAR_GLYPH)
3350 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3351 else
3352 face_id = FACE_FOR_CHAR (s->f, face, 0);
3353 s->face = FACE_FROM_ID (s->f, face_id);
3354 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3355
3356 /* If font in this face is same as S->font, use it. */
3357 if (s->font == s->face->font)
3358 s->gc = s->face->gc;
3359 else
3360 {
3361 /* Otherwise construct scratch_cursor_gc with values from FACE
3362 but font FONT. */
3363 XGCValues xgcv;
3364 unsigned long mask;
3365
3366 xgcv.background = s->face->background;
3367 xgcv.foreground = s->face->foreground;
3368 IF_DEBUG (x_check_font (s->f, s->font));
3369 xgcv.font = s->font;
3370 mask = GCForeground | GCBackground | GCFont;
3371
3372 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3373 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3374 mask, &xgcv);
3375 else
3376 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3377 = XCreateGC (s->display, s->window, mask, &xgcv);
3378
3379 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3380 }
3381
3382 xassert (s->gc != 0);
3383}
3384
3385
3386/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3387 Faces to use in the mode line have already been computed when the
3388 matrix was built, so there isn't much to do, here. */
3389
3390static INLINE void
3391x_set_mode_line_face_gc (s)
3392 struct glyph_string *s;
3393{
3394 s->gc = s->face->gc;
3395}
3396
3397
3398/* Set S->gc of glyph string S for drawing that glyph string. Set
3399 S->stippled_p to a non-zero value if the face of S has a stipple
3400 pattern. */
3401
3402static INLINE void
3403x_set_glyph_string_gc (s)
3404 struct glyph_string *s;
3405{
3406 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3407
3408 if (s->hl == DRAW_NORMAL_TEXT)
3409 {
3410 s->gc = s->face->gc;
3411 s->stippled_p = s->face->stipple != 0;
3412 }
3413 else if (s->hl == DRAW_INVERSE_VIDEO)
3414 {
3415 x_set_mode_line_face_gc (s);
3416 s->stippled_p = s->face->stipple != 0;
3417 }
3418 else if (s->hl == DRAW_CURSOR)
3419 {
3420 x_set_cursor_gc (s);
3421 s->stippled_p = 0;
3422 }
3423 else if (s->hl == DRAW_MOUSE_FACE)
3424 {
3425 x_set_mouse_face_gc (s);
3426 s->stippled_p = s->face->stipple != 0;
3427 }
3428 else if (s->hl == DRAW_IMAGE_RAISED
3429 || s->hl == DRAW_IMAGE_SUNKEN)
3430 {
3431 s->gc = s->face->gc;
3432 s->stippled_p = s->face->stipple != 0;
3433 }
3434 else
3435 {
3436 s->gc = s->face->gc;
3437 s->stippled_p = s->face->stipple != 0;
3438 }
3439
3440 /* GC must have been set. */
3441 xassert (s->gc != 0);
3442}
3443
3444
3445/* Return in *R the clipping rectangle for glyph string S. */
3446
3447static void
3448x_get_glyph_string_clip_rect (s, r)
3449 struct glyph_string *s;
3450 Rect *r;
3451{
3452 int r_height, r_width;
3453
3454 if (s->row->full_width_p)
3455 {
3456 /* Draw full-width. X coordinates are relative to S->w->left. */
3457 int canon_x = CANON_X_UNIT (s->f);
3458
3459 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3460 r_width = XFASTINT (s->w->width) * canon_x;
3461
3462 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3463 {
3464 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3465 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3466 r->left -= width;
3467 }
3468
3469 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3470
3471 /* Unless displaying a mode or menu bar line, which are always
3472 fully visible, clip to the visible part of the row. */
3473 if (s->w->pseudo_window_p)
3474 r_height = s->row->visible_height;
3475 else
3476 r_height = s->height;
3477 }
3478 else
3479 {
3480 /* This is a text line that may be partially visible. */
3481 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3482 r_width = window_box_width (s->w, s->area);
3483 r_height = s->row->visible_height;
3484 }
3485
1a578e9b
AC
3486 /* If S draws overlapping rows, it's sufficient to use the top and
3487 bottom of the window for clipping because this glyph string
3488 intentionally draws over other lines. */
3489 if (s->for_overlaps_p)
3490 {
3491 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3492 r_height = window_text_bottom_y (s->w) - r->top;
3493 }
e0f712ba
AC
3494 else
3495 {
3496 /* Don't use S->y for clipping because it doesn't take partially
3497 visible lines into account. For example, it can be negative for
3498 partially visible lines at the top of a window. */
3499 if (!s->row->full_width_p
3500 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3501 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3502 else
3503 r->top = max (0, s->row->y);
3504
3505 /* If drawing a tool-bar window, draw it over the internal border
3506 at the top of the window. */
3507 if (s->w == XWINDOW (s->f->tool_bar_window))
3508 r->top -= s->f->output_data.mac->internal_border_width;
3509 }
3510
1a578e9b
AC
3511 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3512
3513 r->bottom = r->top + r_height;
3514 r->right = r->left + r_width;
3515}
3516
3517
3518/* Set clipping for output of glyph string S. S may be part of a mode
3519 line or menu if we don't have X toolkit support. */
3520
3521static INLINE void
3522x_set_glyph_string_clipping (s)
3523 struct glyph_string *s;
3524{
3525 Rect r;
3526 x_get_glyph_string_clip_rect (s, &r);
3527 mac_set_clip_rectangle (s->display, s->window, &r);
3528}
3529
3530
3531/* Compute left and right overhang of glyph string S. If S is a glyph
3532 string for a composition, assume overhangs don't exist. */
3533
3534static INLINE void
3535x_compute_glyph_string_overhangs (s)
3536 struct glyph_string *s;
3537{
3538 if (s->cmp == NULL
3539 && s->first_glyph->type == CHAR_GLYPH)
3540 {
3541 XCharStruct cs;
3542 int direction, font_ascent, font_descent;
3543 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3544 &font_ascent, &font_descent, &cs);
3545 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3546 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3547 }
3548}
3549
3550
3551/* Compute overhangs and x-positions for glyph string S and its
3552 predecessors, or successors. X is the starting x-position for S.
3553 BACKWARD_P non-zero means process predecessors. */
3554
3555static void
3556x_compute_overhangs_and_x (s, x, backward_p)
3557 struct glyph_string *s;
3558 int x;
3559 int backward_p;
3560{
3561 if (backward_p)
3562 {
3563 while (s)
3564 {
3565 x_compute_glyph_string_overhangs (s);
3566 x -= s->width;
3567 s->x = x;
3568 s = s->prev;
3569 }
3570 }
3571 else
3572 {
3573 while (s)
3574 {
3575 x_compute_glyph_string_overhangs (s);
3576 s->x = x;
3577 x += s->width;
3578 s = s->next;
3579 }
3580 }
3581}
3582
3583
3584/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3585 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3586 assumed to be zero. */
3587
3588void
3589x_get_glyph_overhangs (glyph, f, left, right)
3590 struct glyph *glyph;
3591 struct frame *f;
3592 int *left, *right;
3593{
3594 *left = *right = 0;
3595
3596 if (glyph->type == CHAR_GLYPH)
3597 {
3598 XFontStruct *font;
3599 struct face *face;
3600 struct font_info *font_info;
3601 XChar2b char2b;
3602 XCharStruct *pcm;
3603
3604 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3605 font = face->font;
3606 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3607 if (font
3608 && (pcm = x_per_char_metric (font, &char2b)))
3609 {
3610 if (pcm->rbearing > pcm->width)
3611 *right = pcm->rbearing - pcm->width;
3612 if (pcm->lbearing < 0)
3613 *left = -pcm->lbearing;
3614 }
3615 }
3616}
3617
3618
3619/* Return the index of the first glyph preceding glyph string S that
3620 is overwritten by S because of S's left overhang. Value is -1
3621 if no glyphs are overwritten. */
3622
3623static int
3624x_left_overwritten (s)
3625 struct glyph_string *s;
3626{
3627 int k;
3628
3629 if (s->left_overhang)
3630 {
3631 int x = 0, i;
3632 struct glyph *glyphs = s->row->glyphs[s->area];
3633 int first = s->first_glyph - glyphs;
3634
3635 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3636 x -= glyphs[i].pixel_width;
3637
3638 k = i + 1;
3639 }
3640 else
3641 k = -1;
3642
3643 return k;
3644}
3645
3646
3647/* Return the index of the first glyph preceding glyph string S that
3648 is overwriting S because of its right overhang. Value is -1 if no
3649 glyph in front of S overwrites S. */
3650
3651static int
3652x_left_overwriting (s)
3653 struct glyph_string *s;
3654{
3655 int i, k, x;
3656 struct glyph *glyphs = s->row->glyphs[s->area];
3657 int first = s->first_glyph - glyphs;
3658
3659 k = -1;
3660 x = 0;
3661 for (i = first - 1; i >= 0; --i)
3662 {
3663 int left, right;
3664 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3665 if (x + right > 0)
3666 k = i;
3667 x -= glyphs[i].pixel_width;
3668 }
3669
3670 return k;
3671}
3672
3673
3674/* Return the index of the last glyph following glyph string S that is
3675 not overwritten by S because of S's right overhang. Value is -1 if
3676 no such glyph is found. */
3677
3678static int
3679x_right_overwritten (s)
3680 struct glyph_string *s;
3681{
3682 int k = -1;
3683
3684 if (s->right_overhang)
3685 {
3686 int x = 0, i;
3687 struct glyph *glyphs = s->row->glyphs[s->area];
3688 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3689 int end = s->row->used[s->area];
3690
3691 for (i = first; i < end && s->right_overhang > x; ++i)
3692 x += glyphs[i].pixel_width;
3693
3694 k = i;
3695 }
3696
3697 return k;
3698}
3699
3700
3701/* Return the index of the last glyph following glyph string S that
3702 overwrites S because of its left overhang. Value is negative
3703 if no such glyph is found. */
3704
3705static int
3706x_right_overwriting (s)
3707 struct glyph_string *s;
3708{
3709 int i, k, x;
3710 int end = s->row->used[s->area];
3711 struct glyph *glyphs = s->row->glyphs[s->area];
3712 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3713
3714 k = -1;
3715 x = 0;
3716 for (i = first; i < end; ++i)
3717 {
3718 int left, right;
3719 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3720 if (x - left < 0)
3721 k = i;
3722 x += glyphs[i].pixel_width;
3723 }
3724
3725 return k;
3726}
3727
3728
3729/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3730
3731static INLINE void
3732x_clear_glyph_string_rect (s, x, y, w, h)
3733 struct glyph_string *s;
3734 int x, y, w, h;
3735{
3736 XGCValues xgcv;
3737
3738 xgcv.foreground = s->gc->background;
3739 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3740}
3741
3742
3743/* Draw the background of glyph_string S. If S->background_filled_p
3744 is non-zero don't draw it. FORCE_P non-zero means draw the
3745 background even if it wouldn't be drawn normally. This is used
3746 when a string preceding S draws into the background of S, or S
3747 contains the first component of a composition. */
3748
3749static void
3750x_draw_glyph_string_background (s, force_p)
3751 struct glyph_string *s;
3752 int force_p;
3753{
3754 /* Nothing to do if background has already been drawn or if it
3755 shouldn't be drawn in the first place. */
3756 if (!s->background_filled_p)
3757 {
e0f712ba
AC
3758 int box_line_width = max (s->face->box_line_width, 0);
3759
1a578e9b
AC
3760#if 0 /* MAC_TODO: stipple */
3761 if (s->stippled_p)
3762 {
3763 /* Fill background with a stipple pattern. */
3764 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3765 XFillRectangle (s->display, s->window, s->gc, s->x,
e0f712ba 3766 s->y + box_line_width,
1a578e9b 3767 s->background_width,
e0f712ba 3768 s->height - 2 * box_line_width);
1a578e9b
AC
3769 XSetFillStyle (s->display, s->gc, FillSolid);
3770 s->background_filled_p = 1;
3771 }
3772 else
3773#endif
e0f712ba 3774 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1a578e9b
AC
3775 || s->font_not_found_p
3776 || s->extends_to_end_of_line_p
3777 || force_p)
3778 {
e0f712ba 3779 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1a578e9b 3780 s->background_width,
e0f712ba 3781 s->height - 2 * box_line_width);
1a578e9b
AC
3782 s->background_filled_p = 1;
3783 }
3784 }
3785}
3786
3787
3788/* Draw the foreground of glyph string S. */
3789
3790static void
3791x_draw_glyph_string_foreground (s)
3792 struct glyph_string *s;
3793{
3794 int i, x;
3795
3796 /* If first glyph of S has a left box line, start drawing the text
3797 of S to the right of that box line. */
3798 if (s->face->box != FACE_NO_BOX
3799 && s->first_glyph->left_box_line_p)
e0f712ba 3800 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
3801 else
3802 x = s->x;
3803
3804 /* Draw characters of S as rectangles if S's font could not be
3805 loaded. */
3806 if (s->font_not_found_p)
3807 {
3808 for (i = 0; i < s->nchars; ++i)
3809 {
3810 struct glyph *g = s->first_glyph + i;
3811 mac_draw_rectangle (s->display, s->window,
3812 s->gc, x, s->y, g->pixel_width - 1,
3813 s->height - 1);
3814 x += g->pixel_width;
3815 }
3816 }
3817 else
3818 {
3819 char *char1b = (char *) s->char2b;
3820 int boff = s->font_info->baseline_offset;
3821
3822 if (s->font_info->vertical_centering)
3823 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3824
3825 /* If we can use 8-bit functions, condense S->char2b. */
3826 if (!s->two_byte_p)
3827 for (i = 0; i < s->nchars; ++i)
3828 char1b[i] = s->char2b[i].byte2;
3829
3830 /* Draw text with XDrawString if background has already been
3831 filled. Otherwise, use XDrawImageString. (Note that
3832 XDrawImageString is usually faster than XDrawString.) Always
3833 use XDrawImageString when drawing the cursor so that there is
3834 no chance that characters under a box cursor are invisible. */
3835 if (s->for_overlaps_p
3836 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3837 {
3838 /* Draw characters with 16-bit or 8-bit functions. */
3839 if (s->two_byte_p)
3840 XDrawString16 (s->display, s->window, s->gc, x,
3841 s->ybase - boff, s->char2b, s->nchars);
3842 else
3843 XDrawString (s->display, s->window, s->gc, x,
3844 s->ybase - boff, char1b, s->nchars);
3845 }
3846 else
3847 {
3848 if (s->two_byte_p)
3849 XDrawImageString16 (s->display, s->window, s->gc, x,
3850 s->ybase - boff, s->char2b, s->nchars);
3851 else
3852 XDrawImageString (s->display, s->window, s->gc, x,
3853 s->ybase - boff, char1b, s->nchars);
3854 }
3855 }
3856}
3857
3858/* Draw the foreground of composite glyph string S. */
3859
3860static void
3861x_draw_composite_glyph_string_foreground (s)
3862 struct glyph_string *s;
3863{
3864 int i, x;
3865
3866 /* If first glyph of S has a left box line, start drawing the text
3867 of S to the right of that box line. */
3868 if (s->face->box != FACE_NO_BOX
3869 && s->first_glyph->left_box_line_p)
e0f712ba 3870 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
3871 else
3872 x = s->x;
3873
3874 /* S is a glyph string for a composition. S->gidx is the index of
3875 the first character drawn for glyphs of this composition.
3876 S->gidx == 0 means we are drawing the very first character of
3877 this composition. */
3878
3879 /* Draw a rectangle for the composition if the font for the very
3880 first character of the composition could not be loaded. */
3881 if (s->font_not_found_p)
3882 {
3883 if (s->gidx == 0)
3884 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3885 s->width - 1, s->height - 1);
3886 }
3887 else
3888 {
3889 for (i = 0; i < s->nchars; i++, ++s->gidx)
3890 XDrawString16 (s->display, s->window, s->gc,
3891 x + s->cmp->offsets[s->gidx * 2],
3892 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3893 s->char2b + i, 1);
3894 }
3895}
3896
3897
3898#ifdef USE_X_TOOLKIT
3899
3900static struct frame *x_frame_of_widget P_ ((Widget));
3901
3902
3903/* Return the frame on which widget WIDGET is used.. Abort if frame
3904 cannot be determined. */
3905
3906static struct frame *
3907x_frame_of_widget (widget)
3908 Widget widget;
3909{
3910 struct x_display_info *dpyinfo;
3911 Lisp_Object tail;
3912 struct frame *f;
3913
3914 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3915
3916 /* Find the top-level shell of the widget. Note that this function
3917 can be called when the widget is not yet realized, so XtWindow
3918 (widget) == 0. That's the reason we can't simply use
3919 x_any_window_to_frame. */
3920 while (!XtIsTopLevelShell (widget))
3921 widget = XtParent (widget);
3922
3923 /* Look for a frame with that top-level widget. Allocate the color
3924 on that frame to get the right gamma correction value. */
3925 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3926 if (GC_FRAMEP (XCAR (tail))
3927 && (f = XFRAME (XCAR (tail)),
3928 (f->output_data.nothing != 1
3929 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3930 && f->output_data.x->widget == widget)
3931 return f;
3932
3933 abort ();
3934}
3935
3936
3937/* Allocate the color COLOR->pixel on the screen and display of
3938 widget WIDGET in colormap CMAP. If an exact match cannot be
3939 allocated, try the nearest color available. Value is non-zero
3940 if successful. This is called from lwlib. */
3941
3942int
3943x_alloc_nearest_color_for_widget (widget, cmap, color)
3944 Widget widget;
3945 Colormap cmap;
3946 XColor *color;
3947{
3948 struct frame *f = x_frame_of_widget (widget);
3949 return x_alloc_nearest_color (f, cmap, color);
3950}
3951
3952
3953#endif /* USE_X_TOOLKIT */
3954
e0f712ba 3955#if 0 /* MAC_TODO */
1a578e9b
AC
3956
3957/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3958 CMAP. If an exact match can't be allocated, try the nearest color
3959 available. Value is non-zero if successful. Set *COLOR to the
3960 color allocated. */
3961
3962int
3963x_alloc_nearest_color (f, cmap, color)
3964 struct frame *f;
3965 Colormap cmap;
3966 XColor *color;
3967{
3968 Display *display = FRAME_X_DISPLAY (f);
3969 Screen *screen = FRAME_X_SCREEN (f);
3970 int rc;
3971
3972 gamma_correct (f, color);
3973 rc = XAllocColor (display, cmap, color);
3974 if (rc == 0)
3975 {
3976 /* If we got to this point, the colormap is full, so we're going
3977 to try to get the next closest color. The algorithm used is
3978 a least-squares matching, which is what X uses for closest
3979 color matching with StaticColor visuals. */
3980 int nearest, i;
3981 unsigned long nearest_delta = ~0;
3982 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3983 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3984
3985 for (i = 0; i < ncells; ++i)
3986 cells[i].pixel = i;
3987 XQueryColors (display, cmap, cells, ncells);
3988
3989 for (nearest = i = 0; i < ncells; ++i)
3990 {
3991 long dred = (color->red >> 8) - (cells[i].red >> 8);
3992 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3993 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3994 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3995
3996 if (delta < nearest_delta)
3997 {
3998 nearest = i;
3999 nearest_delta = delta;
4000 }
4001 }
4002
4003 color->red = cells[nearest].red;
4004 color->green = cells[nearest].green;
4005 color->blue = cells[nearest].blue;
4006 rc = XAllocColor (display, cmap, color);
4007 }
4008
4009#ifdef DEBUG_X_COLORS
4010 if (rc)
4011 register_color (color->pixel);
4012#endif /* DEBUG_X_COLORS */
4013
4014 return rc;
4015}
4016
4017
4018/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4019 It's necessary to do this instead of just using PIXEL directly to
4020 get color reference counts right. */
4021
4022unsigned long
4023x_copy_color (f, pixel)
4024 struct frame *f;
4025 unsigned long pixel;
4026{
4027 XColor color;
4028
4029 color.pixel = pixel;
4030 BLOCK_INPUT;
4031 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4032 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4033 UNBLOCK_INPUT;
4034#ifdef DEBUG_X_COLORS
4035 register_color (pixel);
4036#endif
4037 return color.pixel;
4038}
4039
4040
4041/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4042 It's necessary to do this instead of just using PIXEL directly to
4043 get color reference counts right. */
4044
4045unsigned long
4046x_copy_dpy_color (dpy, cmap, pixel)
4047 Display *dpy;
4048 Colormap cmap;
4049 unsigned long pixel;
4050{
4051 XColor color;
4052
4053 color.pixel = pixel;
4054 BLOCK_INPUT;
4055 XQueryColor (dpy, cmap, &color);
4056 XAllocColor (dpy, cmap, &color);
4057 UNBLOCK_INPUT;
4058#ifdef DEBUG_X_COLORS
4059 register_color (pixel);
4060#endif
4061 return color.pixel;
4062}
4063
e0f712ba 4064#endif /* MAC_TODO */
1a578e9b
AC
4065
4066/* Allocate a color which is lighter or darker than *COLOR by FACTOR
4067 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4068 If this produces the same color as COLOR, try a color where all RGB
4069 values have DELTA added. Return the allocated color in *COLOR.
4070 DISPLAY is the X display, CMAP is the colormap to operate on.
4071 Value is non-zero if successful. */
4072
4073static int
4074mac_alloc_lighter_color (f, color, factor, delta)
4075 struct frame *f;
4076 unsigned long *color;
4077 double factor;
4078 int delta;
4079{
4080 unsigned long new;
4081
4082 /* Change RGB values by specified FACTOR. Avoid overflow! */
4083 xassert (factor >= 0);
4084 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4085 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4086 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4087 if (new == *color)
4088 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4089 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4090 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4091
4092 /* MAC_TODO: Map to palette and retry with delta if same? */
4093 /* MAC_TODO: Free colors (if using palette)? */
4094
4095 if (new == *color)
4096 return 0;
4097
4098 *color = new;
4099
4100 return 1;
4101}
4102
4103
4104/* Set up the foreground color for drawing relief lines of glyph
4105 string S. RELIEF is a pointer to a struct relief containing the GC
4106 with which lines will be drawn. Use a color that is FACTOR or
4107 DELTA lighter or darker than the relief's background which is found
4108 in S->f->output_data.x->relief_background. If such a color cannot
4109 be allocated, use DEFAULT_PIXEL, instead. */
4110
4111static void
4112x_setup_relief_color (f, relief, factor, delta, default_pixel)
4113 struct frame *f;
4114 struct relief *relief;
4115 double factor;
4116 int delta;
4117 unsigned long default_pixel;
4118{
4119 XGCValues xgcv;
4120 struct mac_output *di = f->output_data.mac;
4121 unsigned long mask = GCForeground;
4122 unsigned long pixel;
4123 unsigned long background = di->relief_background;
4124 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4125
4126 /* MAC_TODO: Free colors (if using palette)? */
4127
4128 /* Allocate new color. */
4129 xgcv.foreground = default_pixel;
4130 pixel = background;
4131 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4132 {
4133 relief->allocated_p = 1;
4134 xgcv.foreground = relief->pixel = pixel;
4135 }
4136
4137 if (relief->gc == 0)
4138 {
4139#if 0 /* MAC_TODO: stipple */
4140 xgcv.stipple = dpyinfo->gray;
4141 mask |= GCStipple;
4142#endif
4143 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4144 }
4145 else
4146 XChangeGC (NULL, relief->gc, mask, &xgcv);
4147}
4148
4149
4150/* Set up colors for the relief lines around glyph string S. */
4151
4152static void
4153x_setup_relief_colors (s)
4154 struct glyph_string *s;
4155{
4156 struct mac_output *di = s->f->output_data.mac;
4157 unsigned long color;
4158
4159 if (s->face->use_box_color_for_shadows_p)
4160 color = s->face->box_color;
4161 else
4162 {
4163 XGCValues xgcv;
4164
4165 /* Get the background color of the face. */
4166 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4167 color = xgcv.background;
4168 }
4169
4170 if (di->white_relief.gc == 0
4171 || color != di->relief_background)
4172 {
4173 di->relief_background = color;
4174 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4175 WHITE_PIX_DEFAULT (s->f));
4176 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4177 BLACK_PIX_DEFAULT (s->f));
4178 }
4179}
4180
4181
4182/* Draw a relief on frame F inside the rectangle given by LEFT_X,
4183 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4184 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4185 relief. LEFT_P non-zero means draw a relief on the left side of
4186 the rectangle. RIGHT_P non-zero means draw a relief on the right
4187 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4188 when drawing. */
4189
4190static void
4191x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4192 raised_p, left_p, right_p, clip_rect)
4193 struct frame *f;
4194 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4195 Rect *clip_rect;
4196{
4197 int i;
4198 GC gc;
4199
4200 if (raised_p)
4201 gc = f->output_data.mac->white_relief.gc;
4202 else
4203 gc = f->output_data.mac->black_relief.gc;
4204 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4205
4206 /* Top. */
4207 for (i = 0; i < width; ++i)
4208 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4209 left_x + i * left_p, top_y + i,
4210 right_x + 1 - i * right_p, top_y + i);
4211
4212 /* Left. */
4213 if (left_p)
4214 for (i = 0; i < width; ++i)
4215 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4216 left_x + i, top_y + i, left_x + i, bottom_y - i);
4217
4218 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4219 if (raised_p)
4220 gc = f->output_data.mac->black_relief.gc;
4221 else
4222 gc = f->output_data.mac->white_relief.gc;
e0f712ba
AC
4223 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4224 clip_rect);
1a578e9b
AC
4225
4226 /* Bottom. */
4227 for (i = 0; i < width; ++i)
4228 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4229 left_x + i * left_p, bottom_y - i,
4230 right_x + 1 - i * right_p, bottom_y - i);
4231
4232 /* Right. */
4233 if (right_p)
4234 for (i = 0; i < width; ++i)
4235 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4236 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4237
4238 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4239}
4240
4241
4242/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4243 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4244 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4245 left side of the rectangle. RIGHT_P non-zero means draw a line
4246 on the right side of the rectangle. CLIP_RECT is the clipping
4247 rectangle to use when drawing. */
4248
4249static void
4250x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4251 left_p, right_p, clip_rect)
4252 struct glyph_string *s;
4253 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4254 Rect *clip_rect;
4255{
4256 XGCValues xgcv;
4257
4258 xgcv.foreground = s->face->box_color;
4259 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4260
4261 /* Top. */
4262 XFillRectangle (s->display, s->window, &xgcv,
4263 left_x, top_y, right_x - left_x, width);
4264
4265 /* Left. */
4266 if (left_p)
4267 XFillRectangle (s->display, s->window, &xgcv,
4268 left_x, top_y, width, bottom_y - top_y);
4269
4270 /* Bottom. */
4271 XFillRectangle (s->display, s->window, &xgcv,
4272 left_x, bottom_y - width, right_x - left_x, width);
4273
4274 /* Right. */
4275 if (right_p)
4276 XFillRectangle (s->display, s->window, &xgcv,
4277 right_x - width, top_y, width, bottom_y - top_y);
4278
4279 mac_reset_clipping (s->display, s->window);
4280}
4281
4282
4283/* Draw a box around glyph string S. */
4284
4285static void
4286x_draw_glyph_string_box (s)
4287 struct glyph_string *s;
4288{
4289 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4290 int left_p, right_p;
4291 struct glyph *last_glyph;
4292 Rect clip_rect;
4293
4294 last_x = window_box_right (s->w, s->area);
4295 if (s->row->full_width_p
4296 && !s->w->pseudo_window_p)
4297 {
3f332ef3 4298 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
1a578e9b
AC
4299 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4300 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4301 }
4302
4303 /* The glyph that may have a right box line. */
4304 last_glyph = (s->cmp || s->img
4305 ? s->first_glyph
4306 : s->first_glyph + s->nchars - 1);
4307
e0f712ba 4308 width = abs (s->face->box_line_width);
1a578e9b
AC
4309 raised_p = s->face->box == FACE_RAISED_BOX;
4310 left_x = s->x;
e0f712ba 4311 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
1a578e9b
AC
4312 ? last_x - 1
4313 : min (last_x, s->x + s->background_width) - 1));
4314 top_y = s->y;
4315 bottom_y = top_y + s->height - 1;
4316
4317 left_p = (s->first_glyph->left_box_line_p
4318 || (s->hl == DRAW_MOUSE_FACE
4319 && (s->prev == NULL
4320 || s->prev->hl != s->hl)));
4321 right_p = (last_glyph->right_box_line_p
4322 || (s->hl == DRAW_MOUSE_FACE
4323 && (s->next == NULL
4324 || s->next->hl != s->hl)));
4325
4326 x_get_glyph_string_clip_rect (s, &clip_rect);
4327
4328 if (s->face->box == FACE_SIMPLE_BOX)
4329 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4330 left_p, right_p, &clip_rect);
4331 else
4332 {
4333 x_setup_relief_colors (s);
4334 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4335 width, raised_p, left_p, right_p, &clip_rect);
4336 }
4337}
4338
4339
4340/* Draw foreground of image glyph string S. */
4341
4342static void
4343x_draw_image_foreground (s)
4344 struct glyph_string *s;
4345{
4346 int x;
4347 int y = s->ybase - image_ascent (s->img, s->face);
4348
4349 /* If first glyph of S has a left box line, start drawing it to the
4350 right of that line. */
4351 if (s->face->box != FACE_NO_BOX
4352 && s->first_glyph->left_box_line_p)
e0f712ba 4353 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
4354 else
4355 x = s->x;
4356
4357 /* If there is a margin around the image, adjust x- and y-position
4358 by that margin. */
83a96b4d
AC
4359 x += s->img->hmargin;
4360 y += s->img->vmargin;
1a578e9b
AC
4361
4362 if (s->img->pixmap)
4363 {
4364#if 0 /* MAC_TODO: image mask */
4365 if (s->img->mask)
4366 {
4367 /* We can't set both a clip mask and use XSetClipRectangles
4368 because the latter also sets a clip mask. We also can't
4369 trust on the shape extension to be available
4370 (XShapeCombineRegion). So, compute the rectangle to draw
4371 manually. */
4372 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4373 | GCFunction);
4374 XGCValues xgcv;
4375 XRectangle clip_rect, image_rect, r;
4376
4377 xgcv.clip_mask = s->img->mask;
4378 xgcv.clip_x_origin = x;
4379 xgcv.clip_y_origin = y;
4380 xgcv.function = GXcopy;
4381 XChangeGC (s->display, s->gc, mask, &xgcv);
4382
4383 x_get_glyph_string_clip_rect (s, &clip_rect);
4384 image_rect.x = x;
4385 image_rect.y = y;
4386 image_rect.width = s->img->width;
4387 image_rect.height = s->img->height;
4388 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4389 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4390 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4391 }
4392 else
e0f712ba 4393#endif /* MAC_TODO */
1a578e9b
AC
4394 {
4395 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4396 0, 0, s->img->width, s->img->height, x, y);
4397
4398 /* When the image has a mask, we can expect that at
4399 least part of a mouse highlight or a block cursor will
4400 be visible. If the image doesn't have a mask, make
4401 a block cursor visible by drawing a rectangle around
4402 the image. I believe it's looking better if we do
4403 nothing here for mouse-face. */
4404 if (s->hl == DRAW_CURSOR)
534c20b2
KS
4405 {
4406 int r = s->img->relief;
4407 if (r < 0) r = -r;
4408 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4409 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4410 }
1a578e9b
AC
4411 }
4412 }
4413 else
4414 /* Draw a rectangle if image could not be loaded. */
4415 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4416 s->img->width - 1, s->img->height - 1);
4417}
4418
4419
e0f712ba 4420
1a578e9b
AC
4421/* Draw a relief around the image glyph string S. */
4422
4423static void
4424x_draw_image_relief (s)
4425 struct glyph_string *s;
4426{
4427 int x0, y0, x1, y1, thick, raised_p;
4428 Rect r;
4429 int x;
4430 int y = s->ybase - image_ascent (s->img, s->face);
e0f712ba 4431
1a578e9b
AC
4432 /* If first glyph of S has a left box line, start drawing it to the
4433 right of that line. */
4434 if (s->face->box != FACE_NO_BOX
4435 && s->first_glyph->left_box_line_p)
e0f712ba 4436 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
4437 else
4438 x = s->x;
4439
4440 /* If there is a margin around the image, adjust x- and y-position
4441 by that margin. */
83a96b4d
AC
4442 x += s->img->hmargin;
4443 y += s->img->vmargin;
1a578e9b
AC
4444
4445 if (s->hl == DRAW_IMAGE_SUNKEN
4446 || s->hl == DRAW_IMAGE_RAISED)
4447 {
e0f712ba 4448 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1a578e9b
AC
4449 raised_p = s->hl == DRAW_IMAGE_RAISED;
4450 }
4451 else
4452 {
4453 thick = abs (s->img->relief);
4454 raised_p = s->img->relief > 0;
4455 }
4456
4457 x0 = x - thick;
4458 y0 = y - thick;
4459 x1 = x + s->img->width + thick - 1;
4460 y1 = y + s->img->height + thick - 1;
4461
4462 x_setup_relief_colors (s);
4463 x_get_glyph_string_clip_rect (s, &r);
4464 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4465}
4466
4467
4468/* Draw the foreground of image glyph string S to PIXMAP. */
4469
4470static void
4471x_draw_image_foreground_1 (s, pixmap)
4472 struct glyph_string *s;
4473 Pixmap pixmap;
4474{
4475 int x;
4476 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4477
4478 /* If first glyph of S has a left box line, start drawing it to the
4479 right of that line. */
4480 if (s->face->box != FACE_NO_BOX
4481 && s->first_glyph->left_box_line_p)
e0f712ba 4482 x = abs (s->face->box_line_width);
1a578e9b
AC
4483 else
4484 x = 0;
4485
4486 /* If there is a margin around the image, adjust x- and y-position
4487 by that margin. */
83a96b4d
AC
4488 x += s->img->hmargin;
4489 y += s->img->vmargin;
1a578e9b
AC
4490
4491 if (s->img->pixmap)
4492 {
4493#if 0 /* MAC_TODO: image mask */
4494 if (s->img->mask)
4495 {
4496 /* We can't set both a clip mask and use XSetClipRectangles
4497 because the latter also sets a clip mask. We also can't
4498 trust on the shape extension to be available
4499 (XShapeCombineRegion). So, compute the rectangle to draw
4500 manually. */
4501 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4502 | GCFunction);
4503 XGCValues xgcv;
4504
4505 xgcv.clip_mask = s->img->mask;
4506 xgcv.clip_x_origin = x;
4507 xgcv.clip_y_origin = y;
4508 xgcv.function = GXcopy;
4509 XChangeGC (s->display, s->gc, mask, &xgcv);
4510
4511 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4512 0, 0, s->img->width, s->img->height, x, y);
4513 XSetClipMask (s->display, s->gc, None);
4514 }
4515 else
e0f712ba 4516#endif /* MAC_TODO */
1a578e9b
AC
4517 {
4518 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4519 0, 0, s->img->width, s->img->height, x, y);
4520
4521 /* When the image has a mask, we can expect that at
4522 least part of a mouse highlight or a block cursor will
4523 be visible. If the image doesn't have a mask, make
4524 a block cursor visible by drawing a rectangle around
4525 the image. I believe it's looking better if we do
4526 nothing here for mouse-face. */
4527 if (s->hl == DRAW_CURSOR)
534c20b2
KS
4528 {
4529 int r = s->img->relief;
4530 if (r < 0) r = -r;
4531 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4532 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4533 }
1a578e9b
AC
4534 }
4535 }
4536 else
4537 /* Draw a rectangle if image could not be loaded. */
4538 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4539 s->img->width - 1, s->img->height - 1);
4540}
4541
4542
4543/* Draw part of the background of glyph string S. X, Y, W, and H
4544 give the rectangle to draw. */
4545
4546static void
4547x_draw_glyph_string_bg_rect (s, x, y, w, h)
4548 struct glyph_string *s;
4549 int x, y, w, h;
4550{
4551#if 0 /* MAC_TODO: stipple */
4552 if (s->stippled_p)
4553 {
4554 /* Fill background with a stipple pattern. */
4555 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4556 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4557 XSetFillStyle (s->display, s->gc, FillSolid);
4558 }
4559 else
e0f712ba 4560#endif /* MAC_TODO */
1a578e9b
AC
4561 x_clear_glyph_string_rect (s, x, y, w, h);
4562}
4563
4564
4565/* Draw image glyph string S.
4566
4567 s->y
4568 s->x +-------------------------
4569 | s->face->box
4570 |
4571 | +-------------------------
83a96b4d 4572 | | s->img->vmargin
1a578e9b
AC
4573 | |
4574 | | +-------------------
4575 | | | the image
4576
4577 */
4578
4579static void
4580x_draw_image_glyph_string (s)
4581 struct glyph_string *s;
4582{
4583 int x, y;
e0f712ba
AC
4584 int box_line_hwidth = abs (s->face->box_line_width);
4585 int box_line_vwidth = max (s->face->box_line_width, 0);
1a578e9b
AC
4586 int height;
4587 Pixmap pixmap = 0;
4588
e0f712ba 4589 height = s->height - 2 * box_line_vwidth;
1a578e9b
AC
4590
4591 /* Fill background with face under the image. Do it only if row is
4592 taller than image or if image has a clip mask to reduce
4593 flickering. */
4594 s->stippled_p = s->face->stipple != 0;
4595 if (height > s->img->height
83a96b4d 4596 || s->img->hmargin
e0f712ba
AC
4597 || s->img->vmargin
4598#if 0 /* TODO: image mask */
1a578e9b
AC
4599 || s->img->mask
4600#endif
4601 || s->img->pixmap == 0
4602 || s->width != s->background_width)
4603 {
e0f712ba
AC
4604 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4605 x = s->x + box_line_hwidth;
1a578e9b
AC
4606 else
4607 x = s->x;
4608
e0f712ba
AC
4609 y = s->y + box_line_vwidth;
4610#if 0 /* TODO: image mask */
1a578e9b
AC
4611 if (s->img->mask)
4612 {
e0f712ba
AC
4613 /* Create a pixmap as large as the glyph string. Fill it
4614 with the background color. Copy the image to it, using
4615 its mask. Copy the temporary pixmap to the display. */
1a578e9b
AC
4616 Screen *screen = FRAME_X_SCREEN (s->f);
4617 int depth = DefaultDepthOfScreen (screen);
4618
4619 /* Create a pixmap as large as the glyph string. */
4620 pixmap = XCreatePixmap (s->display, s->window,
4621 s->background_width,
4622 s->height, depth);
4623
4624 /* Don't clip in the following because we're working on the
4625 pixmap. */
4626 XSetClipMask (s->display, s->gc, None);
4627
4628 /* Fill the pixmap with the background color/stipple. */
4629 if (s->stippled_p)
4630 {
4631 /* Fill background with a stipple pattern. */
4632 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4633 XFillRectangle (s->display, pixmap, s->gc,
4634 0, 0, s->background_width, s->height);
4635 XSetFillStyle (s->display, s->gc, FillSolid);
4636 }
4637 else
4638 {
4639 XGCValues xgcv;
4640 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4641 &xgcv);
4642 XSetForeground (s->display, s->gc, xgcv.background);
4643 XFillRectangle (s->display, pixmap, s->gc,
4644 0, 0, s->background_width, s->height);
4645 XSetForeground (s->display, s->gc, xgcv.foreground);
4646 }
4647 }
4648 else
4649#endif
1a578e9b
AC
4650 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4651
4652 s->background_filled_p = 1;
4653 }
4654
4655 /* Draw the foreground. */
4656 if (pixmap != 0)
4657 {
4658 x_draw_image_foreground_1 (s, pixmap);
4659 x_set_glyph_string_clipping (s);
4660 mac_copy_area (s->display, pixmap, s->window, s->gc,
4661 0, 0, s->background_width, s->height, s->x, s->y);
e0f712ba 4662 mac_reset_clipping (s->display, s->window);
1a578e9b
AC
4663 XFreePixmap (s->display, pixmap);
4664 }
4665 else
4666 x_draw_image_foreground (s);
4667
4668 /* If we must draw a relief around the image, do it. */
4669 if (s->img->relief
4670 || s->hl == DRAW_IMAGE_RAISED
4671 || s->hl == DRAW_IMAGE_SUNKEN)
4672 x_draw_image_relief (s);
4673}
4674
4675
4676/* Draw stretch glyph string S. */
4677
4678static void
4679x_draw_stretch_glyph_string (s)
4680 struct glyph_string *s;
4681{
4682 xassert (s->first_glyph->type == STRETCH_GLYPH);
4683 s->stippled_p = s->face->stipple != 0;
4684
4685 if (s->hl == DRAW_CURSOR
4686 && !x_stretch_cursor_p)
4687 {
4688 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4689 as wide as the stretch glyph. */
4690 int width = min (CANON_X_UNIT (s->f), s->background_width);
4691
4692 /* Draw cursor. */
4693 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4694
4695 /* Clear rest using the GC of the original non-cursor face. */
4696 if (width < s->background_width)
4697 {
4698 GC gc = s->face->gc;
4699 int x = s->x + width, y = s->y;
4700 int w = s->background_width - width, h = s->height;
4701 Rect r;
4702
e0f712ba
AC
4703 if (s->row->mouse_face_p
4704 && cursor_in_mouse_face_p (s->w))
4705 {
4706 x_set_mouse_face_gc (s);
4707 gc = s->gc;
4708 }
4709 else
4710 gc = s->face->gc;
4711
1a578e9b
AC
4712 x_get_glyph_string_clip_rect (s, &r);
4713 mac_set_clip_rectangle (s->display, s->window, &r);
4714
4715#if 0 /* MAC_TODO: stipple */
4716 if (s->face->stipple)
4717 {
4718 /* Fill background with a stipple pattern. */
4719 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4720 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4721 XSetFillStyle (s->display, gc, FillSolid);
4722 }
4723 else
e0f712ba 4724#endif /* MAC_TODO */
1a578e9b
AC
4725 {
4726 XGCValues xgcv;
4727 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4728 XSetForeground (s->display, gc, xgcv.background);
4729 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4730 XSetForeground (s->display, gc, xgcv.foreground);
4731 }
e0f712ba
AC
4732
4733 mac_reset_clipping (s->display, s->window);
1a578e9b
AC
4734 }
4735 }
e0f712ba 4736 else if (!s->background_filled_p)
1a578e9b
AC
4737 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4738 s->height);
4739
4740 s->background_filled_p = 1;
4741}
4742
4743
4744/* Draw glyph string S. */
4745
4746static void
4747x_draw_glyph_string (s)
4748 struct glyph_string *s;
4749{
e0f712ba
AC
4750 int relief_drawn_p = 0;
4751
1a578e9b
AC
4752 /* If S draws into the background of its successor, draw the
4753 background of the successor first so that S can draw into it.
4754 This makes S->next use XDrawString instead of XDrawImageString. */
4755 if (s->next && s->right_overhang && !s->for_overlaps_p)
4756 {
4757 xassert (s->next->img == NULL);
4758 x_set_glyph_string_gc (s->next);
4759 x_set_glyph_string_clipping (s->next);
4760 x_draw_glyph_string_background (s->next, 1);
e0f712ba 4761
1a578e9b
AC
4762 }
4763
4764 /* Set up S->gc, set clipping and draw S. */
4765 x_set_glyph_string_gc (s);
e0f712ba
AC
4766
4767 /* Draw relief (if any) in advance for char/composition so that the
4768 glyph string can be drawn over it. */
4769 if (!s->for_overlaps_p
4770 && s->face->box != FACE_NO_BOX
4771 && (s->first_glyph->type == CHAR_GLYPH
4772 || s->first_glyph->type == COMPOSITE_GLYPH))
4773
4774 {
4775 x_set_glyph_string_clipping (s);
4776 x_draw_glyph_string_background (s, 1);
4777 x_draw_glyph_string_box (s);
4778 x_set_glyph_string_clipping (s);
4779 relief_drawn_p = 1;
4780 }
4781 else
4782 x_set_glyph_string_clipping (s);
1a578e9b
AC
4783
4784 switch (s->first_glyph->type)
4785 {
4786 case IMAGE_GLYPH:
4787 x_draw_image_glyph_string (s);
4788 break;
4789
4790 case STRETCH_GLYPH:
4791 x_draw_stretch_glyph_string (s);
4792 break;
4793
4794 case CHAR_GLYPH:
4795 if (s->for_overlaps_p)
4796 s->background_filled_p = 1;
4797 else
e0f712ba 4798 x_draw_glyph_string_background (s, 0);
1a578e9b
AC
4799 x_draw_glyph_string_foreground (s);
4800 break;
4801
4802 case COMPOSITE_GLYPH:
4803 if (s->for_overlaps_p || s->gidx > 0)
4804 s->background_filled_p = 1;
4805 else
4806 x_draw_glyph_string_background (s, 1);
4807 x_draw_composite_glyph_string_foreground (s);
4808 break;
4809
4810 default:
4811 abort ();
4812 }
4813
4814 if (!s->for_overlaps_p)
4815 {
4816 /* Draw underline. */
4817 if (s->face->underline_p)
4818 {
4819 unsigned long h = 1;
4820 unsigned long dy = s->height - h;
4821
4822 if (s->face->underline_defaulted_p)
4823 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4824 s->width, h);
4825 else
4826 {
4827 XGCValues xgcv;
4828 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4829 XSetForeground (s->display, s->gc, s->face->underline_color);
4830 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4831 s->width, h);
4832 XSetForeground (s->display, s->gc, xgcv.foreground);
4833 }
4834 }
4835
4836 /* Draw overline. */
4837 if (s->face->overline_p)
4838 {
4839 unsigned long dy = 0, h = 1;
4840
4841 if (s->face->overline_color_defaulted_p)
4842 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4843 s->width, h);
4844 else
4845 {
4846 XGCValues xgcv;
4847 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4848 XSetForeground (s->display, s->gc, s->face->overline_color);
4849 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4850 s->width, h);
4851 XSetForeground (s->display, s->gc, xgcv.foreground);
4852 }
4853 }
4854
4855 /* Draw strike-through. */
4856 if (s->face->strike_through_p)
4857 {
4858 unsigned long h = 1;
4859 unsigned long dy = (s->height - h) / 2;
4860
4861 if (s->face->strike_through_color_defaulted_p)
4862 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4863 s->width, h);
4864 else
4865 {
4866 XGCValues xgcv;
4867 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4868 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4869 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4870 s->width, h);
4871 XSetForeground (s->display, s->gc, xgcv.foreground);
4872 }
4873 }
4874
4875 /* Draw relief. */
e0f712ba
AC
4876 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4877 x_draw_glyph_string_box (s);
1a578e9b 4878 }
e0f712ba 4879
1a578e9b
AC
4880 /* Reset clipping. */
4881 mac_reset_clipping (s->display, s->window);
4882}
4883
4884
4885static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4886 struct face **, int));
4887
4888
4889/* Fill glyph string S with composition components specified by S->cmp.
4890
4891 FACES is an array of faces for all components of this composition.
4892 S->gidx is the index of the first component for S.
4893 OVERLAPS_P non-zero means S should draw the foreground only, and
4894 use its physical height for clipping.
4895
4896 Value is the index of a component not in S. */
4897
4898static int
4899x_fill_composite_glyph_string (s, faces, overlaps_p)
4900 struct glyph_string *s;
4901 struct face **faces;
4902 int overlaps_p;
4903{
4904 int i;
4905
4906 xassert (s);
4907
4908 s->for_overlaps_p = overlaps_p;
e0f712ba 4909
1a578e9b
AC
4910 s->face = faces[s->gidx];
4911 s->font = s->face->font;
4912 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4913
4914 /* For all glyphs of this composition, starting at the offset
4915 S->gidx, until we reach the end of the definition or encounter a
4916 glyph that requires the different face, add it to S. */
4917 ++s->nchars;
4918 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4919 ++s->nchars;
4920
4921 /* All glyph strings for the same composition has the same width,
4922 i.e. the width set for the first component of the composition. */
4923
4924 s->width = s->first_glyph->pixel_width;
4925
4926 /* If the specified font could not be loaded, use the frame's
4927 default font, but record the fact that we couldn't load it in
4928 the glyph string so that we can draw rectangles for the
4929 characters of the glyph string. */
4930 if (s->font == NULL)
4931 {
4932 s->font_not_found_p = 1;
4933 s->font = FRAME_FONT (s->f);
4934 }
4935
4936 /* Adjust base line for subscript/superscript text. */
4937 s->ybase += s->first_glyph->voffset;
4938
4939 xassert (s->face && s->face->gc);
4940
4941 /* This glyph string must always be drawn with 16-bit functions. */
4942 s->two_byte_p = 1;
4943
4944 return s->gidx + s->nchars;
4945}
4946
4947
4948/* Fill glyph string S from a sequence of character glyphs.
4949
4950 FACE_ID is the face id of the string. START is the index of the
4951 first glyph to consider, END is the index of the last + 1.
4952 OVERLAPS_P non-zero means S should draw the foreground only, and
4953 use its physical height for clipping.
4954
4955 Value is the index of the first glyph not in S. */
4956
4957static int
4958x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4959 struct glyph_string *s;
4960 int face_id;
4961 int start, end, overlaps_p;
4962{
4963 struct glyph *glyph, *last;
4964 int voffset;
4965 int glyph_not_available_p;
e0f712ba 4966
1a578e9b
AC
4967 xassert (s->f == XFRAME (s->w->frame));
4968 xassert (s->nchars == 0);
4969 xassert (start >= 0 && end > start);
4970
e0f712ba 4971 s->for_overlaps_p = overlaps_p;
1a578e9b
AC
4972 glyph = s->row->glyphs[s->area] + start;
4973 last = s->row->glyphs[s->area] + end;
4974 voffset = glyph->voffset;
e0f712ba 4975
1a578e9b
AC
4976 glyph_not_available_p = glyph->glyph_not_available_p;
4977
4978 while (glyph < last
4979 && glyph->type == CHAR_GLYPH
4980 && glyph->voffset == voffset
4981 /* Same face id implies same font, nowadays. */
4982 && glyph->face_id == face_id
e0f712ba 4983 && glyph->glyph_not_available_p == glyph_not_available_p)
1a578e9b
AC
4984 {
4985 int two_byte_p;
4986
4987 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4988 s->char2b + s->nchars,
e0f712ba 4989 &two_byte_p);
1a578e9b
AC
4990 s->two_byte_p = two_byte_p;
4991 ++s->nchars;
4992 xassert (s->nchars <= end - start);
4993 s->width += glyph->pixel_width;
4994 ++glyph;
4995 }
4996
4997 s->font = s->face->font;
4998 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4999
5000 /* If the specified font could not be loaded, use the frame's font,
5001 but record the fact that we couldn't load it in
5002 S->font_not_found_p so that we can draw rectangles for the
5003 characters of the glyph string. */
5004 if (s->font == NULL || glyph_not_available_p)
5005 {
5006 s->font_not_found_p = 1;
5007 s->font = FRAME_FONT (s->f);
5008 }
5009
5010 /* Adjust base line for subscript/superscript text. */
5011 s->ybase += voffset;
e0f712ba 5012
1a578e9b
AC
5013 xassert (s->face && s->face->gc);
5014 return glyph - s->row->glyphs[s->area];
5015}
5016
5017
5018/* Fill glyph string S from image glyph S->first_glyph. */
5019
5020static void
5021x_fill_image_glyph_string (s)
5022 struct glyph_string *s;
5023{
5024 xassert (s->first_glyph->type == IMAGE_GLYPH);
5025 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5026 xassert (s->img);
5027 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5028 s->font = s->face->font;
5029 s->width = s->first_glyph->pixel_width;
5030
5031 /* Adjust base line for subscript/superscript text. */
5032 s->ybase += s->first_glyph->voffset;
5033}
5034
5035
5036/* Fill glyph string S from a sequence of stretch glyphs.
5037
5038 ROW is the glyph row in which the glyphs are found, AREA is the
5039 area within the row. START is the index of the first glyph to
5040 consider, END is the index of the last + 1.
5041
5042 Value is the index of the first glyph not in S. */
5043
5044static int
5045x_fill_stretch_glyph_string (s, row, area, start, end)
5046 struct glyph_string *s;
5047 struct glyph_row *row;
5048 enum glyph_row_area area;
5049 int start, end;
5050{
5051 struct glyph *glyph, *last;
5052 int voffset, face_id;
5053
5054 xassert (s->first_glyph->type == STRETCH_GLYPH);
5055
5056 glyph = s->row->glyphs[s->area] + start;
5057 last = s->row->glyphs[s->area] + end;
5058 face_id = glyph->face_id;
5059 s->face = FACE_FROM_ID (s->f, face_id);
5060 s->font = s->face->font;
5061 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5062 s->width = glyph->pixel_width;
5063 voffset = glyph->voffset;
5064
5065 for (++glyph;
5066 (glyph < last
5067 && glyph->type == STRETCH_GLYPH
5068 && glyph->voffset == voffset
5069 && glyph->face_id == face_id);
5070 ++glyph)
5071 s->width += glyph->pixel_width;
5072
5073 /* Adjust base line for subscript/superscript text. */
5074 s->ybase += voffset;
5075
e0f712ba 5076 xassert (s->face);
1a578e9b
AC
5077 return glyph - s->row->glyphs[s->area];
5078}
5079
5080
5081/* Initialize glyph string S. CHAR2B is a suitably allocated vector
5082 of XChar2b structures for S; it can't be allocated in
5083 x_init_glyph_string because it must be allocated via `alloca'. W
5084 is the window on which S is drawn. ROW and AREA are the glyph row
5085 and area within the row from which S is constructed. START is the
5086 index of the first glyph structure covered by S. HL is a
5087 face-override for drawing S. */
5088
5089static void
5090x_init_glyph_string (s, char2b, w, row, area, start, hl)
5091 struct glyph_string *s;
5092 XChar2b *char2b;
5093 struct window *w;
5094 struct glyph_row *row;
5095 enum glyph_row_area area;
5096 int start;
5097 enum draw_glyphs_face hl;
5098{
5099 bzero (s, sizeof *s);
5100 s->w = w;
5101 s->f = XFRAME (w->frame);
5102 s->display = FRAME_MAC_DISPLAY (s->f);
5103 s->window = FRAME_MAC_WINDOW (s->f);
5104 s->char2b = char2b;
5105 s->hl = hl;
5106 s->row = row;
5107 s->area = area;
5108 s->first_glyph = row->glyphs[area] + start;
5109 s->height = row->height;
5110 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5111
5112 /* Display the internal border below the tool-bar window. */
5113 if (s->w == XWINDOW (s->f->tool_bar_window))
5114 s->y -= s->f->output_data.mac->internal_border_width;
5115
5116 s->ybase = s->y + row->ascent;
5117}
5118
5119
5120/* Set background width of glyph string S. START is the index of the
5121 first glyph following S. LAST_X is the right-most x-position + 1
5122 in the drawing area. */
5123
5124static INLINE void
5125x_set_glyph_string_background_width (s, start, last_x)
5126 struct glyph_string *s;
5127 int start;
5128 int last_x;
5129{
5130 /* If the face of this glyph string has to be drawn to the end of
5131 the drawing area, set S->extends_to_end_of_line_p. */
5132 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
5133
5134 if (start == s->row->used[s->area]
e0f712ba
AC
5135 && s->area == TEXT_AREA
5136 && ((s->hl == DRAW_NORMAL_TEXT
5137 && (s->row->fill_line_p
5138 || s->face->background != default_face->background
5139 || s->face->stipple != default_face->stipple
5140 || s->row->mouse_face_p))
5141 || s->hl == DRAW_MOUSE_FACE
5142 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5143 && s->row->fill_line_p)))
1a578e9b
AC
5144 s->extends_to_end_of_line_p = 1;
5145
5146 /* If S extends its face to the end of the line, set its
5147 background_width to the distance to the right edge of the drawing
5148 area. */
5149 if (s->extends_to_end_of_line_p)
5150 s->background_width = last_x - s->x + 1;
5151 else
5152 s->background_width = s->width;
5153}
5154
5155
5156/* Add a glyph string for a stretch glyph to the list of strings
5157 between HEAD and TAIL. START is the index of the stretch glyph in
5158 row area AREA of glyph row ROW. END is the index of the last glyph
5159 in that glyph row area. X is the current output position assigned
5160 to the new glyph string constructed. HL overrides that face of the
5161 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5162 is the right-most x-position of the drawing area. */
5163
5164/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5165 and below -- keep them on one line. */
5166#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5167 do \
5168 { \
5169 s = (struct glyph_string *) alloca (sizeof *s); \
5170 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5171 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5172 x_append_glyph_string (&HEAD, &TAIL, s); \
5173 s->x = (X); \
5174 } \
5175 while (0)
5176
5177
5178/* Add a glyph string for an image glyph to the list of strings
5179 between HEAD and TAIL. START is the index of the image glyph in
5180 row area AREA of glyph row ROW. END is the index of the last glyph
5181 in that glyph row area. X is the current output position assigned
5182 to the new glyph string constructed. HL overrides that face of the
5183 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5184 is the right-most x-position of the drawing area. */
5185
5186#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5187 do \
5188 { \
5189 s = (struct glyph_string *) alloca (sizeof *s); \
5190 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5191 x_fill_image_glyph_string (s); \
5192 x_append_glyph_string (&HEAD, &TAIL, s); \
5193 ++START; \
5194 s->x = (X); \
5195 } \
5196 while (0)
5197
5198
5199/* Add a glyph string for a sequence of character glyphs to the list
5200 of strings between HEAD and TAIL. START is the index of the first
5201 glyph in row area AREA of glyph row ROW that is part of the new
5202 glyph string. END is the index of the last glyph in that glyph row
5203 area. X is the current output position assigned to the new glyph
5204 string constructed. HL overrides that face of the glyph; e.g. it
5205 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5206 right-most x-position of the drawing area. */
5207
5208#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5209 do \
5210 { \
5211 int c, face_id; \
5212 XChar2b *char2b; \
5213 \
5214 c = (ROW)->glyphs[AREA][START].u.ch; \
5215 face_id = (ROW)->glyphs[AREA][START].face_id; \
5216 \
5217 s = (struct glyph_string *) alloca (sizeof *s); \
5218 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5219 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5220 x_append_glyph_string (&HEAD, &TAIL, s); \
5221 s->x = (X); \
5222 START = x_fill_glyph_string (s, face_id, START, END, \
5223 OVERLAPS_P); \
5224 } \
5225 while (0)
5226
5227
5228/* Add a glyph string for a composite sequence to the list of strings
5229 between HEAD and TAIL. START is the index of the first glyph in
5230 row area AREA of glyph row ROW that is part of the new glyph
5231 string. END is the index of the last glyph in that glyph row area.
5232 X is the current output position assigned to the new glyph string
5233 constructed. HL overrides that face of the glyph; e.g. it is
5234 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5235 x-position of the drawing area. */
5236
5237#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5238 do { \
5239 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5240 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5241 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5242 struct composition *cmp = composition_table[cmp_id]; \
5243 int glyph_len = cmp->glyph_len; \
5244 XChar2b *char2b; \
5245 struct face **faces; \
5246 struct glyph_string *first_s = NULL; \
5247 int n; \
5248 \
5249 base_face = base_face->ascii_face; \
5250 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5251 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5252 /* At first, fill in `char2b' and `faces'. */ \
5253 for (n = 0; n < glyph_len; n++) \
5254 { \
5255 int c = COMPOSITION_GLYPH (cmp, n); \
5256 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5257 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5258 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5259 this_face_id, char2b + n, 1); \
5260 } \
5261 \
5262 /* Make glyph_strings for each glyph sequence that is drawable by \
5263 the same face, and append them to HEAD/TAIL. */ \
5264 for (n = 0; n < cmp->glyph_len;) \
5265 { \
5266 s = (struct glyph_string *) alloca (sizeof *s); \
5267 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5268 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5269 s->cmp = cmp; \
5270 s->gidx = n; \
5271 s->x = (X); \
5272 \
5273 if (n == 0) \
5274 first_s = s; \
5275 \
5276 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5277 } \
5278 \
5279 ++START; \
5280 s = first_s; \
5281 } while (0)
5282
5283
5284/* Build a list of glyph strings between HEAD and TAIL for the glyphs
5285 of AREA of glyph row ROW on window W between indices START and END.
5286 HL overrides the face for drawing glyph strings, e.g. it is
5287 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5288 x-positions of the drawing area.
5289
5290 This is an ugly monster macro construct because we must use alloca
5291 to allocate glyph strings (because x_draw_glyphs can be called
5292 asynchronously). */
5293
5294#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5295 do \
5296 { \
5297 HEAD = TAIL = NULL; \
5298 while (START < END) \
5299 { \
5300 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5301 switch (first_glyph->type) \
5302 { \
5303 case CHAR_GLYPH: \
5304 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5305 TAIL, HL, X, LAST_X, \
5306 OVERLAPS_P); \
5307 break; \
5308 \
5309 case COMPOSITE_GLYPH: \
5310 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5311 HEAD, TAIL, HL, X, LAST_X,\
5312 OVERLAPS_P); \
5313 break; \
5314 \
5315 case STRETCH_GLYPH: \
5316 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5317 HEAD, TAIL, HL, X, LAST_X); \
5318 break; \
5319 \
5320 case IMAGE_GLYPH: \
5321 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5322 TAIL, HL, X, LAST_X); \
5323 break; \
5324 \
5325 default: \
5326 abort (); \
5327 } \
5328 \
5329 x_set_glyph_string_background_width (s, START, LAST_X); \
5330 (X) += s->width; \
5331 } \
5332 } \
5333 while (0)
5334
5335
5336/* Draw glyphs between START and END in AREA of ROW on window W,
5337 starting at x-position X. X is relative to AREA in W. HL is a
5338 face-override with the following meaning:
5339
5340 DRAW_NORMAL_TEXT draw normally
5341 DRAW_CURSOR draw in cursor face
5342 DRAW_MOUSE_FACE draw in mouse face.
5343 DRAW_INVERSE_VIDEO draw in mode line face
5344 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5345 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5346
1a578e9b
AC
5347 If OVERLAPS_P is non-zero, draw only the foreground of characters
5348 and clip to the physical height of ROW.
5349
5350 Value is the x-position reached, relative to AREA of W. */
5351
5352static int
e0f712ba 5353x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
1a578e9b
AC
5354 struct window *w;
5355 int x;
5356 struct glyph_row *row;
5357 enum glyph_row_area area;
5358 int start, end;
5359 enum draw_glyphs_face hl;
1a578e9b
AC
5360 int overlaps_p;
5361{
5362 struct glyph_string *head, *tail;
5363 struct glyph_string *s;
5364 int last_x, area_width;
5365 int x_reached;
5366 int i, j;
5367
5368 /* Let's rather be paranoid than getting a SEGV. */
1a578e9b 5369 end = min (end, row->used[area]);
e0f712ba
AC
5370 start = max (0, start);
5371 start = min (end, start);
1a578e9b
AC
5372
5373 /* Translate X to frame coordinates. Set last_x to the right
5374 end of the drawing area. */
5375 if (row->full_width_p)
5376 {
5377 /* X is relative to the left edge of W, without scroll bars
3f332ef3 5378 or fringes. */
e0f712ba 5379 struct frame *f = XFRAME (WINDOW_FRAME (w));
1a578e9b
AC
5380 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5381
5382 x += window_left_x;
5383 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5384 last_x = window_left_x + area_width;
5385
5386 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5387 {
5388 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5389 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5390 last_x += width;
5391 else
5392 x -= width;
5393 }
5394
5395 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5396 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5397 }
5398 else
5399 {
5400 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5401 area_width = window_box_width (w, area);
5402 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5403 }
5404
5405 /* Build a doubly-linked list of glyph_string structures between
5406 head and tail from what we have to draw. Note that the macro
5407 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5408 the reason we use a separate variable `i'. */
5409 i = start;
5410 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
e0f712ba 5411 overlaps_p);
1a578e9b
AC
5412 if (tail)
5413 x_reached = tail->x + tail->background_width;
5414 else
5415 x_reached = x;
5416
5417 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5418 the row, redraw some glyphs in front or following the glyph
5419 strings built above. */
e0f712ba 5420 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
1a578e9b
AC
5421 {
5422 int dummy_x = 0;
5423 struct glyph_string *h, *t;
5424
5425 /* Compute overhangs for all glyph strings. */
5426 for (s = head; s; s = s->next)
5427 x_compute_glyph_string_overhangs (s);
5428
5429 /* Prepend glyph strings for glyphs in front of the first glyph
5430 string that are overwritten because of the first glyph
5431 string's left overhang. The background of all strings
5432 prepended must be drawn because the first glyph string
5433 draws over it. */
5434 i = x_left_overwritten (head);
5435 if (i >= 0)
5436 {
5437 j = i;
5438 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5439 DRAW_NORMAL_TEXT, dummy_x, last_x,
e0f712ba 5440 overlaps_p);
1a578e9b 5441 start = i;
1a578e9b
AC
5442 x_compute_overhangs_and_x (t, head->x, 1);
5443 x_prepend_glyph_string_lists (&head, &tail, h, t);
5444 }
5445
5446 /* Prepend glyph strings for glyphs in front of the first glyph
5447 string that overwrite that glyph string because of their
5448 right overhang. For these strings, only the foreground must
5449 be drawn, because it draws over the glyph string at `head'.
5450 The background must not be drawn because this would overwrite
5451 right overhangs of preceding glyphs for which no glyph
5452 strings exist. */
5453 i = x_left_overwriting (head);
5454 if (i >= 0)
5455 {
5456 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5457 DRAW_NORMAL_TEXT, dummy_x, last_x,
e0f712ba 5458 overlaps_p);
1a578e9b
AC
5459 for (s = h; s; s = s->next)
5460 s->background_filled_p = 1;
1a578e9b
AC
5461 x_compute_overhangs_and_x (t, head->x, 1);
5462 x_prepend_glyph_string_lists (&head, &tail, h, t);
5463 }
5464
5465 /* Append glyphs strings for glyphs following the last glyph
5466 string tail that are overwritten by tail. The background of
5467 these strings has to be drawn because tail's foreground draws
5468 over it. */
5469 i = x_right_overwritten (tail);
5470 if (i >= 0)
5471 {
5472 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5473 DRAW_NORMAL_TEXT, x, last_x,
e0f712ba 5474 overlaps_p);
1a578e9b
AC
5475 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5476 x_append_glyph_string_lists (&head, &tail, h, t);
1a578e9b
AC
5477 }
5478
5479 /* Append glyph strings for glyphs following the last glyph
5480 string tail that overwrite tail. The foreground of such
5481 glyphs has to be drawn because it writes into the background
5482 of tail. The background must not be drawn because it could
5483 paint over the foreground of following glyphs. */
5484 i = x_right_overwriting (tail);
5485 if (i >= 0)
5486 {
5487 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5488 DRAW_NORMAL_TEXT, x, last_x,
e0f712ba 5489 overlaps_p);
1a578e9b
AC
5490 for (s = h; s; s = s->next)
5491 s->background_filled_p = 1;
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
5497 /* Draw all strings. */
5498 for (s = head; s; s = s->next)
5499 x_draw_glyph_string (s);
5500
e0f712ba
AC
5501 if (area == TEXT_AREA
5502 && !row->full_width_p
5503 /* When drawing overlapping rows, only the glyph strings'
5504 foreground is drawn, which doesn't erase a cursor
5505 completely. */
5506 && !overlaps_p)
5507 {
5508 int x0 = head ? head->x : x;
5509 int x1 = tail ? tail->x + tail->background_width : x;
5510
5511 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5512 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5513
5514 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5515 {
5516 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5517 x0 -= left_area_width;
5518 x1 -= left_area_width;
5519 }
5520
5521 notice_overwritten_cursor (w, area, x0, x1,
5522 row->y, MATRIX_ROW_BOTTOM_Y (row));
5523 }
5524
1a578e9b
AC
5525 /* Value is the x-position up to which drawn, relative to AREA of W.
5526 This doesn't include parts drawn because of overhangs. */
5527 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5528 if (!row->full_width_p)
5529 {
5530 if (area > LEFT_MARGIN_AREA)
5531 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5532 if (area > TEXT_AREA)
5533 x_reached -= window_box_width (w, TEXT_AREA);
5534 }
e0f712ba 5535
1a578e9b
AC
5536 return x_reached;
5537}
5538
5539
5540/* Fix the display of area AREA of overlapping row ROW in window W. */
5541
e0f712ba 5542static void
1a578e9b
AC
5543x_fix_overlapping_area (w, row, area)
5544 struct window *w;
5545 struct glyph_row *row;
5546 enum glyph_row_area area;
5547{
5548 int i, x;
5549
5550 BLOCK_INPUT;
5551
5552 if (area == LEFT_MARGIN_AREA)
5553 x = 0;
5554 else if (area == TEXT_AREA)
5555 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5556 else
5557 x = (window_box_width (w, LEFT_MARGIN_AREA)
5558 + window_box_width (w, TEXT_AREA));
5559
5560 for (i = 0; i < row->used[area];)
5561 {
5562 if (row->glyphs[area][i].overlaps_vertically_p)
5563 {
5564 int start = i, start_x = x;
5565
5566 do
5567 {
5568 x += row->glyphs[area][i].pixel_width;
5569 ++i;
5570 }
5571 while (i < row->used[area]
5572 && row->glyphs[area][i].overlaps_vertically_p);
5573
5574 x_draw_glyphs (w, start_x, row, area, start, i,
e0f712ba 5575 DRAW_NORMAL_TEXT, 1);
1a578e9b
AC
5576 }
5577 else
5578 {
5579 x += row->glyphs[area][i].pixel_width;
5580 ++i;
5581 }
5582 }
5583
5584 UNBLOCK_INPUT;
5585}
5586
5587
5588/* Output LEN glyphs starting at START at the nominal cursor position.
5589 Advance the nominal cursor over the text. The global variable
5590 updated_window contains the window being updated, updated_row is
5591 the glyph row being updated, and updated_area is the area of that
5592 row being updated. */
5593
e0f712ba 5594static void
1a578e9b
AC
5595x_write_glyphs (start, len)
5596 struct glyph *start;
5597 int len;
5598{
e0f712ba 5599 int x, hpos;
1a578e9b
AC
5600
5601 xassert (updated_window && updated_row);
5602 BLOCK_INPUT;
5603
5604 /* Write glyphs. */
5605
5606 hpos = start - updated_row->glyphs[updated_area];
5607 x = x_draw_glyphs (updated_window, output_cursor.x,
5608 updated_row, updated_area,
5609 hpos, hpos + len,
e0f712ba 5610 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
5611
5612 UNBLOCK_INPUT;
5613
5614 /* Advance the output cursor. */
5615 output_cursor.hpos += len;
5616 output_cursor.x = x;
5617}
5618
5619
5620/* Insert LEN glyphs from START at the nominal cursor position. */
5621
e0f712ba 5622static void
1a578e9b
AC
5623x_insert_glyphs (start, len)
5624 struct glyph *start;
5625 register int len;
5626{
5627 struct frame *f;
5628 struct window *w;
5629 int line_height, shift_by_width, shifted_region_width;
5630 struct glyph_row *row;
5631 struct glyph *glyph;
e0f712ba 5632 int frame_x, frame_y, hpos;
1a578e9b
AC
5633
5634 xassert (updated_window && updated_row);
5635 BLOCK_INPUT;
5636 w = updated_window;
5637 f = XFRAME (WINDOW_FRAME (w));
5638
5639 /* Get the height of the line we are in. */
5640 row = updated_row;
5641 line_height = row->height;
5642
5643 /* Get the width of the glyphs to insert. */
5644 shift_by_width = 0;
5645 for (glyph = start; glyph < start + len; ++glyph)
5646 shift_by_width += glyph->pixel_width;
5647
5648 /* Get the width of the region to shift right. */
5649 shifted_region_width = (window_box_width (w, updated_area)
5650 - output_cursor.x
5651 - shift_by_width);
5652
5653 /* Shift right. */
e0f712ba 5654 frame_x = window_box_left (w, updated_area) + output_cursor.x;
1a578e9b
AC
5655 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5656
5657 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5658 f->output_data.mac->normal_gc,
5659 frame_x, frame_y,
5660 shifted_region_width, line_height,
5661 frame_x + shift_by_width, frame_y);
5662
5663 /* Write the glyphs. */
5664 hpos = start - row->glyphs[updated_area];
5665 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
e0f712ba
AC
5666 DRAW_NORMAL_TEXT, 0);
5667
1a578e9b
AC
5668 /* Advance the output cursor. */
5669 output_cursor.hpos += len;
5670 output_cursor.x += shift_by_width;
5671 UNBLOCK_INPUT;
5672}
5673
5674
5675/* Delete N glyphs at the nominal cursor position. Not implemented
5676 for X frames. */
5677
e0f712ba 5678static void
1a578e9b
AC
5679x_delete_glyphs (n)
5680 register int n;
5681{
5682 abort ();
5683}
5684
5685
5686/* Erase the current text line from the nominal cursor position
5687 (inclusive) to pixel column TO_X (exclusive). The idea is that
5688 everything from TO_X onward is already erased.
5689
5690 TO_X is a pixel position relative to updated_area of
5691 updated_window. TO_X == -1 means clear to the end of this area. */
5692
e0f712ba 5693static void
1a578e9b
AC
5694x_clear_end_of_line (to_x)
5695 int to_x;
5696{
5697 struct frame *f;
5698 struct window *w = updated_window;
5699 int max_x, min_y, max_y;
5700 int from_x, from_y, to_y;
5701
5702 xassert (updated_window && updated_row);
5703 f = XFRAME (w->frame);
5704
5705 if (updated_row->full_width_p)
5706 {
5707 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5708 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5709 && !w->pseudo_window_p)
5710 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5711 }
5712 else
5713 max_x = window_box_width (w, updated_area);
5714 max_y = window_text_bottom_y (w);
5715
5716 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5717 of window. For TO_X > 0, truncate to end of drawing area. */
5718 if (to_x == 0)
5719 return;
5720 else if (to_x < 0)
5721 to_x = max_x;
5722 else
5723 to_x = min (to_x, max_x);
5724
5725 to_y = min (max_y, output_cursor.y + updated_row->height);
5726
5727 /* Notice if the cursor will be cleared by this operation. */
5728 if (!updated_row->full_width_p)
e0f712ba
AC
5729 notice_overwritten_cursor (w, updated_area,
5730 output_cursor.x, -1,
5731 updated_row->y,
5732 MATRIX_ROW_BOTTOM_Y (updated_row));
1a578e9b
AC
5733
5734 from_x = output_cursor.x;
e0f712ba 5735
1a578e9b
AC
5736 /* Translate to frame coordinates. */
5737 if (updated_row->full_width_p)
5738 {
5739 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5740 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5741 }
5742 else
5743 {
5744 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5745 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5746 }
5747
5748 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5749 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5750 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5751
5752 /* Prevent inadvertently clearing to end of the X window. */
5753 if (to_x > from_x && to_y > from_y)
5754 {
5755 BLOCK_INPUT;
5756 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5757 from_x, from_y, to_x - from_x, to_y - from_y,
5758 0);
5759 UNBLOCK_INPUT;
5760 }
5761}
5762
5763
5764/* Clear entire frame. If updating_frame is non-null, clear that
5765 frame. Otherwise clear the selected frame. */
5766
e0f712ba 5767static void
1a578e9b
AC
5768x_clear_frame ()
5769{
5770 struct frame *f;
5771
5772 if (updating_frame)
5773 f = updating_frame;
5774 else
5775 f = SELECTED_FRAME ();
5776
5777 /* Clearing the frame will erase any cursor, so mark them all as no
5778 longer visible. */
5779 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5780 output_cursor.hpos = output_cursor.vpos = 0;
5781 output_cursor.x = -1;
5782
5783 /* We don't set the output cursor here because there will always
5784 follow an explicit cursor_to. */
5785 BLOCK_INPUT;
5786 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5787
5788#if 0 /* Clearing frame on Mac OS clears scroll bars. */
5789 /* We have to clear the scroll bars, too. If we have changed
5790 colors or something like that, then they should be notified. */
5791 x_scroll_bar_clear (f);
5792#endif
5793
5794 XFlush (FRAME_MAC_DISPLAY (f));
5795 UNBLOCK_INPUT;
5796}
5797
5798
5799\f
5800/* Invert the middle quarter of the frame for .15 sec. */
5801
5802/* We use the select system call to do the waiting, so we have to make
5803 sure it's available. If it isn't, we just won't do visual bells. */
5804
5805#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5806
5807/* Subtract the `struct timeval' values X and Y, storing the result in
5808 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5809
5810static int
5811timeval_subtract (result, x, y)
5812 struct timeval *result, x, y;
5813{
5814 /* Perform the carry for the later subtraction by updating y. This
5815 is safer because on some systems the tv_sec member is unsigned. */
5816 if (x.tv_usec < y.tv_usec)
5817 {
5818 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5819 y.tv_usec -= 1000000 * nsec;
5820 y.tv_sec += nsec;
5821 }
5822
5823 if (x.tv_usec - y.tv_usec > 1000000)
5824 {
5825 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5826 y.tv_usec += 1000000 * nsec;
5827 y.tv_sec -= nsec;
5828 }
5829
5830 /* Compute the time remaining to wait. tv_usec is certainly
5831 positive. */
5832 result->tv_sec = x.tv_sec - y.tv_sec;
5833 result->tv_usec = x.tv_usec - y.tv_usec;
5834
5835 /* Return indication of whether the result should be considered
5836 negative. */
5837 return x.tv_sec < y.tv_sec;
5838}
5839
5840void
5841XTflash (f)
5842 struct frame *f;
5843{
5844 BLOCK_INPUT;
5845
5846 FlashMenuBar (0);
5847
5848 {
5849 struct timeval wakeup;
5850
5851 EMACS_GET_TIME (wakeup);
5852
5853 /* Compute time to wait until, propagating carry from usecs. */
5854 wakeup.tv_usec += 150000;
5855 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5856 wakeup.tv_usec %= 1000000;
5857
5858 /* Keep waiting until past the time wakeup. */
5859 while (1)
5860 {
5861 struct timeval timeout;
5862
5863 EMACS_GET_TIME (timeout);
5864
5865 /* In effect, timeout = wakeup - timeout.
5866 Break if result would be negative. */
5867 if (timeval_subtract (&timeout, wakeup, timeout))
5868 break;
5869
5870 /* Try to wait that long--but we might wake up sooner. */
5871 select (0, NULL, NULL, NULL, &timeout);
5872 }
5873 }
5874
5875 FlashMenuBar (0);
5876
5877 UNBLOCK_INPUT;
5878}
5879
5880#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5881
5882
5883/* Make audible bell. */
5884
5885void
5886XTring_bell ()
5887{
5888 struct frame *f = SELECTED_FRAME ();
5889
5890#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5891 if (visible_bell)
5892 XTflash (f);
5893 else
5894#endif
5895 {
5896 BLOCK_INPUT;
5897 SysBeep (1);
5898 XFlush (FRAME_MAC_DISPLAY (f));
5899 UNBLOCK_INPUT;
5900 }
5901}
5902
5903
5904\f
5905/* Specify how many text lines, from the top of the window,
5906 should be affected by insert-lines and delete-lines operations.
5907 This, and those operations, are used only within an update
5908 that is bounded by calls to x_update_begin and x_update_end. */
5909
5910void
5911XTset_terminal_window (n)
5912 register int n;
5913{
5914 /* This function intentionally left blank. */
5915}
5916
5917
5918\f
5919/***********************************************************************
5920 Line Dance
5921 ***********************************************************************/
5922
5923/* Perform an insert-lines or delete-lines operation, inserting N
5924 lines or deleting -N lines at vertical position VPOS. */
5925
e0f712ba 5926static void
1a578e9b
AC
5927x_ins_del_lines (vpos, n)
5928 int vpos, n;
5929{
5930 abort ();
5931}
5932
5933
5934/* Scroll part of the display as described by RUN. */
5935
e0f712ba 5936static void
1a578e9b
AC
5937x_scroll_run (w, run)
5938 struct window *w;
5939 struct run *run;
5940{
5941 struct frame *f = XFRAME (w->frame);
5942 int x, y, width, height, from_y, to_y, bottom_y;
5943
5944 /* Get frame-relative bounding box of the text display area of W,
3f332ef3
KS
5945 without mode lines. Include in this box the left and right
5946 fringes of W. */
1a578e9b 5947 window_box (w, -1, &x, &y, &width, &height);
3f332ef3
KS
5948 width += FRAME_X_FRINGE_WIDTH (f);
5949 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
1a578e9b
AC
5950
5951 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5952 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5953 bottom_y = y + height;
5954
5955 if (to_y < from_y)
5956 {
5957 /* Scrolling up. Make sure we don't copy part of the mode
5958 line at the bottom. */
5959 if (from_y + run->height > bottom_y)
5960 height = bottom_y - from_y;
5961 else
5962 height = run->height;
5963 }
5964 else
5965 {
5966 /* Scolling down. Make sure we don't copy over the mode line.
5967 at the bottom. */
5968 if (to_y + run->height > bottom_y)
5969 height = bottom_y - to_y;
5970 else
5971 height = run->height;
5972 }
5973
5974 BLOCK_INPUT;
5975
5976 /* Cursor off. Will be switched on again in x_update_window_end. */
5977 updated_window = w;
5978 x_clear_cursor (w);
5979
5980 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5981 f->output_data.mac->normal_gc,
5982 x, from_y,
5983 width, height,
5984 x, to_y);
5985
5986 UNBLOCK_INPUT;
5987}
5988
5989
5990\f
5991/***********************************************************************
5992 Exposure Events
5993 ***********************************************************************/
5994
5995/* Redisplay an exposed area of frame F. X and Y are the upper-left
5996 corner of the exposed rectangle. W and H are width and height of
5997 the exposed area. All are pixel values. W or H zero means redraw
5998 the entire frame. */
5999
6000static void
6001expose_frame (f, x, y, w, h)
6002 struct frame *f;
6003 int x, y, w, h;
6004{
6005 Rect r;
e0f712ba 6006 int mouse_face_overwritten_p = 0;
1a578e9b
AC
6007
6008 TRACE ((stderr, "expose_frame "));
6009
6010 /* No need to redraw if frame will be redrawn soon. */
6011 if (FRAME_GARBAGED_P (f))
6012 {
6013 TRACE ((stderr, " garbaged\n"));
6014 return;
6015 }
6016
6017 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6018 or deactivated here, for unknown reasons, activated scroll bars
6019 are shown in deactivated frames in some instances. */
6020 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6021 activate_scroll_bars (f);
6022 else
6023 deactivate_scroll_bars (f);
6024
6025 /* If basic faces haven't been realized yet, there is no point in
6026 trying to redraw anything. This can happen when we get an expose
6027 event while Emacs is starting, e.g. by moving another window. */
6028 if (FRAME_FACE_CACHE (f) == NULL
6029 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6030 {
6031 TRACE ((stderr, " no faces\n"));
6032 return;
6033 }
6034
6035 if (w == 0 || h == 0)
6036 {
6037 r.left = r.top = 0;
6038 r.right = CANON_X_UNIT (f) * f->width;
6039 r.bottom = CANON_Y_UNIT (f) * f->height;
6040 }
6041 else
6042 {
6043 r.left = x;
6044 r.top = y;
6045 r.right = x + w;
6046 r.bottom = y + h;
6047 }
6048
6049 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
e0f712ba 6050 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
1a578e9b
AC
6051
6052 if (WINDOWP (f->tool_bar_window))
e0f712ba
AC
6053 mouse_face_overwritten_p
6054 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6055
6056 /* Some window managers support a focus-follows-mouse style with
6057 delayed raising of frames. Imagine a partially obscured frame,
6058 and moving the mouse into partially obscured mouse-face on that
6059 frame. The visible part of the mouse-face will be highlighted,
6060 then the WM raises the obscured frame. With at least one WM, KDE
6061 2.1, Emacs is not getting any event for the raising of the frame
6062 (even tried with SubstructureRedirectMask), only Expose events.
6063 These expose events will draw text normally, i.e. not
6064 highlighted. Which means we must redo the highlight here.
6065 Subsume it under ``we love X''. --gerd 2001-08-15 */
6066 /* Included in Windows version because Windows most likely does not
6067 do the right thing if any third party tool offers
6068 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6069 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
1a578e9b 6070 {
e0f712ba
AC
6071 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6072 if (f == dpyinfo->mouse_face_mouse_frame)
6073 {
6074 int x = dpyinfo->mouse_face_mouse_x;
6075 int y = dpyinfo->mouse_face_mouse_y;
6076 clear_mouse_face (dpyinfo);
6077 note_mouse_highlight (f, x, y);
6078 }
1a578e9b 6079 }
1a578e9b
AC
6080}
6081
6082
6083/* Redraw (parts) of all windows in the window tree rooted at W that
6084 intersect R. R contains frame pixel coordinates. */
6085
e0f712ba 6086static int
1a578e9b
AC
6087expose_window_tree (w, r)
6088 struct window *w;
6089 Rect *r;
6090{
e0f712ba
AC
6091 struct frame *f = XFRAME (w->frame);
6092 int mouse_face_overwritten_p = 0;
6093
6094 while (w && !FRAME_GARBAGED_P (f))
1a578e9b
AC
6095 {
6096 if (!NILP (w->hchild))
e0f712ba
AC
6097 mouse_face_overwritten_p
6098 |= expose_window_tree (XWINDOW (w->hchild), r);
1a578e9b 6099 else if (!NILP (w->vchild))
e0f712ba
AC
6100 mouse_face_overwritten_p
6101 |= expose_window_tree (XWINDOW (w->vchild), r);
1a578e9b 6102 else
e0f712ba 6103 mouse_face_overwritten_p |= expose_window (w, r);
1a578e9b 6104
e0f712ba 6105 w = NILP (w->next) ? NULL : XWINDOW (w->next);
1a578e9b 6106 }
e0f712ba
AC
6107
6108 return mouse_face_overwritten_p;
1a578e9b
AC
6109}
6110
6111
6112/* Redraw the part of glyph row area AREA of glyph row ROW on window W
6113 which intersects rectangle R. R is in window-relative coordinates. */
6114
6115static void
6116expose_area (w, row, r, area)
6117 struct window *w;
6118 struct glyph_row *row;
6119 Rect *r;
6120 enum glyph_row_area area;
6121{
1a578e9b
AC
6122 struct glyph *first = row->glyphs[area];
6123 struct glyph *end = row->glyphs[area] + row->used[area];
6124 struct glyph *last;
e0f712ba 6125 int first_x, start_x, x;
1a578e9b
AC
6126
6127 if (area == TEXT_AREA && row->fill_line_p)
6128 /* If row extends face to end of line write the whole line. */
e0f712ba 6129 x_draw_glyphs (w, 0, row, area,
1a578e9b 6130 0, row->used[area],
e0f712ba 6131 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
6132 else
6133 {
e0f712ba
AC
6134 /* Set START_X to the window-relative start position for drawing glyphs of
6135 AREA. The first glyph of the text area can be partially visible.
6136 The first glyphs of other areas cannot. */
6137 if (area == LEFT_MARGIN_AREA)
6138 start_x = 0;
6139 else if (area == TEXT_AREA)
6140 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6141 else
6142 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6143 + window_box_width (w, TEXT_AREA));
6144 x = start_x;
6145
1a578e9b
AC
6146 /* Find the first glyph that must be redrawn. */
6147 while (first < end
6148 && x + first->pixel_width < r->left)
6149 {
6150 x += first->pixel_width;
6151 ++first;
6152 }
6153
6154 /* Find the last one. */
6155 last = first;
6156 first_x = x;
6157 while (last < end
6158 && x < r->right)
6159 {
6160 x += last->pixel_width;
6161 ++last;
6162 }
e0f712ba 6163
1a578e9b
AC
6164 /* Repaint. */
6165 if (last > first)
e0f712ba
AC
6166 x_draw_glyphs (w, first_x - start_x, row, area,
6167 first - row->glyphs[area],
6168 last - row->glyphs[area],
6169 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
6170 }
6171}
e0f712ba 6172
1a578e9b
AC
6173
6174/* Redraw the parts of the glyph row ROW on window W intersecting
e0f712ba
AC
6175 rectangle R. R is in window-relative coordinates. Value is
6176 non-zero if mouse face was overwritten. */
1a578e9b 6177
e0f712ba 6178static int
1a578e9b
AC
6179expose_line (w, row, r)
6180 struct window *w;
6181 struct glyph_row *row;
6182 Rect *r;
6183{
6184 xassert (row->enabled_p);
6185
6186 if (row->mode_line_p || w->pseudo_window_p)
6187 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
e0f712ba 6188 DRAW_NORMAL_TEXT, 0);
1a578e9b
AC
6189 else
6190 {
6191 if (row->used[LEFT_MARGIN_AREA])
6192 expose_area (w, row, r, LEFT_MARGIN_AREA);
6193 if (row->used[TEXT_AREA])
6194 expose_area (w, row, r, TEXT_AREA);
6195 if (row->used[RIGHT_MARGIN_AREA])
6196 expose_area (w, row, r, RIGHT_MARGIN_AREA);
3f332ef3 6197 x_draw_row_fringe_bitmaps (w, row);
1a578e9b 6198 }
e0f712ba
AC
6199
6200 return row->mouse_face_p;
1a578e9b
AC
6201}
6202
6203
6204/* Return non-zero if W's cursor intersects rectangle R. */
6205
6206static int
6207x_phys_cursor_in_rect_p (w, r)
6208 struct window *w;
6209 Rect *r;
6210{
6211 Rect cr, result;
6212 struct glyph *cursor_glyph;
6213
6214 cursor_glyph = get_phys_cursor_glyph (w);
6215 if (cursor_glyph)
6216 {
6217 cr.left = w->phys_cursor.x;
6218 cr.top = w->phys_cursor.y;
6219 cr.right = cr.left + cursor_glyph->pixel_width;
6220 cr.bottom = cr.top + w->phys_cursor_height;
6221 return x_intersect_rectangles (&cr, r, &result);
6222 }
6223 else
6224 return 0;
6225}
6226
6227
e0f712ba
AC
6228/* Redraw the part of window W intersection rectagle FR. Pixel
6229 coordinates in FR are frame relative. Call this function with
6230 input blocked. Value is non-zero if the exposure overwrites
6231 mouse-face. */
1a578e9b 6232
e0f712ba
AC
6233static int
6234expose_window (w, fr)
1a578e9b 6235 struct window *w;
e0f712ba 6236 Rect *fr;
1a578e9b 6237{
e0f712ba
AC
6238 struct frame *f = XFRAME (w->frame);
6239 Rect wr, r;
6240 int mouse_face_overwritten_p = 0;
1a578e9b
AC
6241
6242 /* If window is not yet fully initialized, do nothing. This can
6243 happen when toolkit scroll bars are used and a window is split.
6244 Reconfiguring the scroll bar will generate an expose for a newly
6245 created window. */
6246 if (w->current_matrix == NULL)
e0f712ba 6247 return 0;
1a578e9b 6248
e0f712ba
AC
6249 /* When we're currently updating the window, display and current
6250 matrix usually don't agree. Arrange for a thorough display
6251 later. */
6252 if (w == updated_window)
1a578e9b 6253 {
e0f712ba
AC
6254 SET_FRAME_GARBAGED (f);
6255 return 0;
1a578e9b 6256 }
1a578e9b 6257
e0f712ba
AC
6258 /* Frame-relative pixel rectangle of W. */
6259 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6260 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6261 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6262 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6263
6264 if (x_intersect_rectangles (fr, &wr, &r))
1a578e9b 6265 {
e0f712ba
AC
6266 int yb = window_text_bottom_y (w);
6267 struct glyph_row *row;
6268 int cursor_cleared_p;
1a578e9b 6269
e0f712ba
AC
6270 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6271 r.left, r.top, r.right, r.bottom));
1a578e9b 6272
e0f712ba
AC
6273 /* Convert to window coordinates. */
6274 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6275 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6276 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6277 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6278
6279 /* Turn off the cursor. */
6280 if (!w->pseudo_window_p
6281 && x_phys_cursor_in_rect_p (w, &r))
6282 {
6283 x_clear_cursor (w);
6284 cursor_cleared_p = 1;
6285 }
6286 else
6287 cursor_cleared_p = 0;
6288
6289 /* Find the first row intersecting the rectangle R. */
6290 for (row = w->current_matrix->rows;
6291 row->enabled_p;
6292 ++row)
6293 {
6294 int y0 = row->y;
6295 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6296
6297 if ((y0 >= r.top && y0 < r.bottom)
6298 || (y1 > r.top && y1 < r.bottom)
6299 || (r.top >= y0 && r.top < y1)
6300 || (r.bottom > y0 && r.bottom < y1))
6301 {
6302 if (expose_line (w, row, &r))
6303 mouse_face_overwritten_p = 1;
6304 }
6305
6306 if (y1 >= yb)
6307 break;
6308 }
6309
6310 /* Display the mode line if there is one. */
6311 if (WINDOW_WANTS_MODELINE_P (w)
6312 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6313 row->enabled_p)
6314 && row->y < r.bottom)
6315 {
6316 if (expose_line (w, row, &r))
6317 mouse_face_overwritten_p = 1;
6318 }
6319
6320 if (!w->pseudo_window_p)
6321 {
6322 /* Draw border between windows. */
6323 x_draw_vertical_border (w);
6324
6325 /* Turn the cursor on again. */
6326 if (cursor_cleared_p)
6327 x_update_window_cursor (w, 1);
6328 }
1a578e9b 6329 }
e0f712ba 6330
1a578e9b
AC
6331 /* Display scroll bar for this window. */
6332 if (!NILP (w->vertical_scroll_bar))
6333 {
6334 ControlHandle ch
e0f712ba 6335 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
1a578e9b
AC
6336
6337 Draw1Control (ch);
6338 }
1a578e9b 6339
e0f712ba
AC
6340 return mouse_face_overwritten_p;
6341}
1a578e9b
AC
6342
6343static int
6344x_intersect_rectangles (r1, r2, result)
6345 Rect *r1, *r2, *result;
6346{
6347 Rect *left, *right;
6348 Rect *upper, *lower;
6349 int intersection_p = 0;
6350
6351 /* Rerrange so that R1 is the left-most rectangle. */
6352 if (r1->left < r2->left)
6353 left = r1, right = r2;
6354 else
6355 left = r2, right = r1;
6356
6357 /* X0 of the intersection is right.x0, if this is inside R1,
6358 otherwise there is no intersection. */
6359 if (right->left <= left->right)
6360 {
6361 result->left = right->left;
6362
6363 /* The right end of the intersection is the minimum of the
6364 the right ends of left and right. */
6365 result->right = min (left->right, right->right);
6366
6367 /* Same game for Y. */
6368 if (r1->top < r2->top)
6369 upper = r1, lower = r2;
6370 else
6371 upper = r2, lower = r1;
6372
6373 /* The upper end of the intersection is lower.y0, if this is inside
6374 of upper. Otherwise, there is no intersection. */
6375 if (lower->top <= upper->bottom)
6376 {
6377 result->top = lower->top;
6378
6379 /* The lower end of the intersection is the minimum of the lower
6380 ends of upper and lower. */
6381 result->bottom = min (lower->bottom, upper->bottom);
6382 intersection_p = 1;
6383 }
6384 }
6385
6386 return intersection_p;
6387}
6388
6389
6390
6391
6392\f
6393static void
6394frame_highlight (f)
6395 struct frame *f;
6396{
6397 x_update_cursor (f, 1);
6398}
6399
6400static void
6401frame_unhighlight (f)
6402 struct frame *f;
6403{
6404 x_update_cursor (f, 1);
6405}
6406
6407/* The focus has changed. Update the frames as necessary to reflect
6408 the new situation. Note that we can't change the selected frame
6409 here, because the Lisp code we are interrupting might become confused.
6410 Each event gets marked with the frame in which it occurred, so the
6411 Lisp code can tell when the switch took place by examining the events. */
6412
6413static void
6414x_new_focus_frame (dpyinfo, frame)
6415 struct x_display_info *dpyinfo;
6416 struct frame *frame;
6417{
6418 struct frame *old_focus = dpyinfo->x_focus_frame;
6419
6420 if (frame != dpyinfo->x_focus_frame)
6421 {
6422 /* Set this before calling other routines, so that they see
6423 the correct value of x_focus_frame. */
6424 dpyinfo->x_focus_frame = frame;
6425
6426 if (old_focus && old_focus->auto_lower)
6427 x_lower_frame (old_focus);
6428
6429#if 0
6430 selected_frame = frame;
6431 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6432 selected_frame);
6433 Fselect_window (selected_frame->selected_window);
6434 choose_minibuf_frame ();
6435#endif /* ! 0 */
6436
6437 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6438 pending_autoraise_frame = dpyinfo->x_focus_frame;
6439 else
6440 pending_autoraise_frame = 0;
6441 }
6442
6443 x_frame_rehighlight (dpyinfo);
6444}
6445
6446/* Handle an event saying the mouse has moved out of an Emacs frame. */
6447
e0f712ba 6448void
1a578e9b
AC
6449x_mouse_leave (dpyinfo)
6450 struct x_display_info *dpyinfo;
6451{
6452 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6453}
6454
6455/* The focus has changed, or we have redirected a frame's focus to
6456 another frame (this happens when a frame uses a surrogate
6457 mini-buffer frame). Shift the highlight as appropriate.
6458
6459 The FRAME argument doesn't necessarily have anything to do with which
6460 frame is being highlighted or un-highlighted; we only use it to find
6461 the appropriate X display info. */
6462
e0f712ba 6463static void
1a578e9b
AC
6464XTframe_rehighlight (frame)
6465 struct frame *frame;
6466{
6467 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6468}
6469
6470static void
6471x_frame_rehighlight (dpyinfo)
6472 struct x_display_info *dpyinfo;
6473{
6474 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6475
6476 if (dpyinfo->x_focus_frame)
6477 {
6478 dpyinfo->x_highlight_frame
6479 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6480 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6481 : dpyinfo->x_focus_frame);
6482 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6483 {
6484 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6485 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6486 }
6487 }
6488 else
6489 dpyinfo->x_highlight_frame = 0;
6490
6491 if (dpyinfo->x_highlight_frame != old_highlight)
6492 {
6493 if (old_highlight)
6494 frame_unhighlight (old_highlight);
6495 if (dpyinfo->x_highlight_frame)
6496 frame_highlight (dpyinfo->x_highlight_frame);
6497 }
6498}
6499
6500
6501\f
6502/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6503
e0f712ba 6504#if 0 /* MAC_TODO */
1a578e9b
AC
6505/* Initialize mode_switch_bit and modifier_meaning. */
6506static void
6507x_find_modifier_meanings (dpyinfo)
6508 struct x_display_info *dpyinfo;
6509{
6510 int min_code, max_code;
6511 KeySym *syms;
6512 int syms_per_code;
6513 XModifierKeymap *mods;
6514
6515 dpyinfo->meta_mod_mask = 0;
6516 dpyinfo->shift_lock_mask = 0;
6517 dpyinfo->alt_mod_mask = 0;
6518 dpyinfo->super_mod_mask = 0;
6519 dpyinfo->hyper_mod_mask = 0;
6520
6521#ifdef HAVE_X11R4
6522 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6523#else
6524 min_code = dpyinfo->display->min_keycode;
6525 max_code = dpyinfo->display->max_keycode;
6526#endif
6527
6528 syms = XGetKeyboardMapping (dpyinfo->display,
6529 min_code, max_code - min_code + 1,
6530 &syms_per_code);
6531 mods = XGetModifierMapping (dpyinfo->display);
6532
6533 /* Scan the modifier table to see which modifier bits the Meta and
6534 Alt keysyms are on. */
6535 {
6536 int row, col; /* The row and column in the modifier table. */
6537
6538 for (row = 3; row < 8; row++)
6539 for (col = 0; col < mods->max_keypermod; col++)
6540 {
6541 KeyCode code
6542 = mods->modifiermap[(row * mods->max_keypermod) + col];
6543
6544 /* Zeroes are used for filler. Skip them. */
6545 if (code == 0)
6546 continue;
6547
6548 /* Are any of this keycode's keysyms a meta key? */
6549 {
6550 int code_col;
6551
6552 for (code_col = 0; code_col < syms_per_code; code_col++)
6553 {
6554 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6555
6556 switch (sym)
6557 {
6558 case XK_Meta_L:
6559 case XK_Meta_R:
6560 dpyinfo->meta_mod_mask |= (1 << row);
6561 break;
6562
6563 case XK_Alt_L:
6564 case XK_Alt_R:
6565 dpyinfo->alt_mod_mask |= (1 << row);
6566 break;
6567
6568 case XK_Hyper_L:
6569 case XK_Hyper_R:
6570 dpyinfo->hyper_mod_mask |= (1 << row);
6571 break;
6572
6573 case XK_Super_L:
6574 case XK_Super_R:
6575 dpyinfo->super_mod_mask |= (1 << row);
6576 break;
6577
6578 case XK_Shift_Lock:
6579 /* Ignore this if it's not on the lock modifier. */
6580 if ((1 << row) == LockMask)
6581 dpyinfo->shift_lock_mask = LockMask;
6582 break;
6583 }
6584 }
6585 }
6586 }
6587 }
6588
6589 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6590 if (! dpyinfo->meta_mod_mask)
6591 {
6592 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6593 dpyinfo->alt_mod_mask = 0;
6594 }
6595
6596 /* If some keys are both alt and meta,
6597 make them just meta, not alt. */
6598 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6599 {
6600 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6601 }
6602
6603 XFree ((char *) syms);
6604 XFreeModifiermap (mods);
6605}
6606
e0f712ba 6607#endif /* MAC_TODO */
1a578e9b
AC
6608
6609/* Convert between the modifier bits X uses and the modifier bits
6610 Emacs uses. */
6611
6612static unsigned int
6613x_mac_to_emacs_modifiers (dpyinfo, state)
6614 struct x_display_info *dpyinfo;
6615 unsigned short state;
6616{
6617 return (((state & shiftKey) ? shift_modifier : 0)
6618 | ((state & controlKey) ? ctrl_modifier : 0)
6619 | ((state & cmdKey) ? meta_modifier : 0)
6620 | ((state & optionKey) ? alt_modifier : 0));
6621}
6622
e0f712ba 6623#if 0 /* MAC_TODO */
1a578e9b
AC
6624static unsigned short
6625x_emacs_to_x_modifiers (dpyinfo, state)
6626 struct x_display_info *dpyinfo;
6627 unsigned int state;
6628{
6629 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6630 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6631 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6632 | ((state & shift_modifier) ? ShiftMask : 0)
6633 | ((state & ctrl_modifier) ? ControlMask : 0)
6634 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6635}
e0f712ba 6636#endif /* MAC_TODO */
1a578e9b
AC
6637
6638/* Convert a keysym to its name. */
6639
6640char *
6641x_get_keysym_name (keysym)
6642 int keysym;
6643{
6644 char *value;
6645
6646 BLOCK_INPUT;
6647#if 0
6648 value = XKeysymToString (keysym);
6649#else
6650 value = 0;
6651#endif
6652 UNBLOCK_INPUT;
6653
6654 return value;
6655}
6656
6657
6658\f
6659/* Mouse clicks and mouse movement. Rah. */
6660
6661/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6662 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6663 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6664 not force the value into range. */
6665
6666void
6667pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6668 FRAME_PTR f;
6669 register int pix_x, pix_y;
6670 register int *x, *y;
6671 Rect *bounds;
6672 int noclip;
6673{
e0f712ba
AC
6674 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6675 if (NILP (Vwindow_system))
6676 {
6677 *x = pix_x;
6678 *y = pix_y;
6679 return;
6680 }
6681
6682 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1a578e9b
AC
6683 even for negative values. */
6684 if (pix_x < 0)
e0f712ba 6685 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
1a578e9b
AC
6686 if (pix_y < 0)
6687 pix_y -= (f)->output_data.mac->line_height - 1;
6688
6689 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6690 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6691
6692 if (bounds)
6693 {
6694 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6695 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
e0f712ba
AC
6696 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6697 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
1a578e9b
AC
6698 }
6699
6700 if (!noclip)
6701 {
6702 if (pix_x < 0)
6703 pix_x = 0;
6704 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6705 pix_x = FRAME_WINDOW_WIDTH (f);
6706
6707 if (pix_y < 0)
6708 pix_y = 0;
6709 else if (pix_y > f->height)
6710 pix_y = f->height;
6711 }
6712
6713 *x = pix_x;
6714 *y = pix_y;
6715}
6716
6717
6718/* Given HPOS/VPOS in the current matrix of W, return corresponding
6719 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6720 can't tell the positions because W's display is not up to date,
6721 return 0. */
6722
e0f712ba 6723int
1a578e9b
AC
6724glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6725 struct window *w;
6726 int hpos, vpos;
6727 int *frame_x, *frame_y;
6728{
6729 int success_p;
6730
6731 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6732 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6733
6734 if (display_completed)
6735 {
6736 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6737 struct glyph *glyph = row->glyphs[TEXT_AREA];
6738 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6739
6740 *frame_y = row->y;
6741 *frame_x = row->x;
6742 while (glyph < end)
6743 {
6744 *frame_x += glyph->pixel_width;
6745 ++glyph;
6746 }
6747
6748 success_p = 1;
6749 }
6750 else
6751 {
6752 *frame_y = *frame_x = 0;
6753 success_p = 0;
6754 }
6755
6756 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6757 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6758 return success_p;
6759}
6760
6761
6762/* Prepare a mouse-event in *RESULT for placement in the input queue.
6763
6764 If the event is a button press, then note that we have grabbed
6765 the mouse. */
6766
6767static Lisp_Object
6768construct_mouse_click (result, event, f)
6769 struct input_event *result;
6770 EventRecord *event;
6771 struct frame *f;
6772{
6773 Point mouseLoc;
6774
3b8f9651 6775 result->kind = MOUSE_CLICK_EVENT;
1a578e9b
AC
6776 result->code = 0; /* only one mouse button */
6777 result->timestamp = event->when;
6778 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6779
6780 mouseLoc = event->where;
e0f712ba
AC
6781
6782#if TARGET_API_MAC_CARBON
6783 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6784#else
1a578e9b 6785 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
6786#endif
6787
1a578e9b
AC
6788 GlobalToLocal (&mouseLoc);
6789 XSETINT (result->x, mouseLoc.h);
6790 XSETINT (result->y, mouseLoc.v);
6791
6792 XSETFRAME (result->frame_or_window, f);
6793
6794 result->arg = Qnil;
6795 return Qnil;
6796}
6797
6798\f
6799/* Function to report a mouse movement to the mainstream Emacs code.
6800 The input handler calls this.
6801
6802 We have received a mouse movement event, which is given in *event.
6803 If the mouse is over a different glyph than it was last time, tell
6804 the mainstream emacs code by setting mouse_moved. If not, ask for
6805 another motion event, so we can check again the next time it moves. */
6806
6807static Point last_mouse_motion_position;
6808static Lisp_Object last_mouse_motion_frame;
6809
6810static void
6811note_mouse_movement (frame, pos)
6812 FRAME_PTR frame;
6813 Point *pos;
6814{
e0f712ba
AC
6815#if TARGET_API_MAC_CARBON
6816 Rect r;
6817#endif
6818
1a578e9b
AC
6819 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6820 last_mouse_motion_position = *pos;
6821 XSETFRAME (last_mouse_motion_frame, frame);
6822
e0f712ba
AC
6823#if TARGET_API_MAC_CARBON
6824 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6825#else
1a578e9b 6826 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
e0f712ba 6827#endif
1a578e9b
AC
6828 {
6829 frame->mouse_moved = 1;
6830 last_mouse_scroll_bar = Qnil;
6831 note_mouse_highlight (frame, -1, -1);
6832 }
6833 /* Has the mouse moved off the glyph it was on at the last sighting? */
6834 else if (pos->h < last_mouse_glyph.left
6835 || pos->h >= last_mouse_glyph.right
6836 || pos->v < last_mouse_glyph.top
6837 || pos->v >= last_mouse_glyph.bottom)
6838 {
6839 frame->mouse_moved = 1;
6840 last_mouse_scroll_bar = Qnil;
6841 note_mouse_highlight (frame, pos->h, pos->v);
6842 }
6843}
6844
6845/* This is used for debugging, to turn off note_mouse_highlight. */
6846
6847int disable_mouse_highlight;
6848
6849
6850\f
6851/************************************************************************
6852 Mouse Face
6853 ************************************************************************/
6854
6855/* Find the glyph under window-relative coordinates X/Y in window W.
6856 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6857 strings. Return in *HPOS and *VPOS the row and column number of
6858 the glyph found. Return in *AREA the glyph area containing X.
6859 Value is a pointer to the glyph found or null if X/Y is not on
6860 text, or we can't tell because W's current matrix is not up to
6861 date. */
6862
6863static struct glyph *
e0f712ba 6864x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
1a578e9b
AC
6865 struct window *w;
6866 int x, y;
6867 int *hpos, *vpos, *area;
e0f712ba 6868 int buffer_only_p;
1a578e9b
AC
6869{
6870 struct glyph *glyph, *end;
6871 struct glyph_row *row = NULL;
6872 int x0, i, left_area_width;
6873
6874 /* Find row containing Y. Give up if some row is not enabled. */
6875 for (i = 0; i < w->current_matrix->nrows; ++i)
6876 {
6877 row = MATRIX_ROW (w->current_matrix, i);
6878 if (!row->enabled_p)
6879 return NULL;
6880 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6881 break;
6882 }
6883
6884 *vpos = i;
6885 *hpos = 0;
6886
6887 /* Give up if Y is not in the window. */
6888 if (i == w->current_matrix->nrows)
6889 return NULL;
6890
6891 /* Get the glyph area containing X. */
6892 if (w->pseudo_window_p)
6893 {
6894 *area = TEXT_AREA;
6895 x0 = 0;
6896 }
6897 else
6898 {
6899 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6900 if (x < left_area_width)
6901 {
6902 *area = LEFT_MARGIN_AREA;
6903 x0 = 0;
6904 }
6905 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6906 {
6907 *area = TEXT_AREA;
6908 x0 = row->x + left_area_width;
6909 }
6910 else
6911 {
6912 *area = RIGHT_MARGIN_AREA;
6913 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6914 }
6915 }
6916
6917 /* Find glyph containing X. */
6918 glyph = row->glyphs[*area];
6919 end = glyph + row->used[*area];
6920 while (glyph < end)
6921 {
6922 if (x < x0 + glyph->pixel_width)
6923 {
6924 if (w->pseudo_window_p)
6925 break;
e0f712ba 6926 else if (!buffer_only_p || BUFFERP (glyph->object))
1a578e9b
AC
6927 break;
6928 }
6929
6930 x0 += glyph->pixel_width;
6931 ++glyph;
6932 }
6933
6934 if (glyph == end)
6935 return NULL;
6936
6937 *hpos = glyph - row->glyphs[*area];
6938 return glyph;
6939}
6940
6941
6942/* Convert frame-relative x/y to coordinates relative to window W.
6943 Takes pseudo-windows into account. */
6944
6945static void
6946frame_to_window_pixel_xy (w, x, y)
6947 struct window *w;
6948 int *x, *y;
6949{
6950 if (w->pseudo_window_p)
6951 {
6952 /* A pseudo-window is always full-width, and starts at the
6953 left edge of the frame, plus a frame border. */
6954 struct frame *f = XFRAME (w->frame);
6955 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6956 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6957 }
6958 else
6959 {
6960 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6961 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6962 }
6963}
6964
6965
e0f712ba 6966/* Take proper action when mouse has moved to the mode or header line of
1a578e9b
AC
6967 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6968 mode line. X is relative to the start of the text display area of
3f332ef3 6969 W, so the width of fringes and scroll bars must be subtracted
1a578e9b
AC
6970 to get a position relative to the start of the mode line. */
6971
6972static void
6973note_mode_line_highlight (w, x, mode_line_p)
6974 struct window *w;
6975 int x, mode_line_p;
6976{
6977 struct frame *f = XFRAME (w->frame);
6978 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
e0f712ba 6979 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
1a578e9b
AC
6980 struct glyph_row *row;
6981
6982 if (mode_line_p)
6983 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6984 else
6985 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
e0f712ba 6986
1a578e9b
AC
6987 if (row->enabled_p)
6988 {
6989 struct glyph *glyph, *end;
6990 Lisp_Object help, map;
6991 int x0;
6992
6993 /* Find the glyph under X. */
6994 glyph = row->glyphs[TEXT_AREA];
6995 end = glyph + row->used[TEXT_AREA];
6996 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
3f332ef3 6997 + FRAME_X_LEFT_FRINGE_WIDTH (f));
e0f712ba 6998
1a578e9b
AC
6999 while (glyph < end
7000 && x >= x0 + glyph->pixel_width)
7001 {
7002 x0 += glyph->pixel_width;
7003 ++glyph;
7004 }
7005
7006 if (glyph < end
7007 && STRINGP (glyph->object)
d5db4077 7008 && STRING_INTERVALS (glyph->object)
1a578e9b 7009 && glyph->charpos >= 0
d5db4077 7010 && glyph->charpos < SCHARS (glyph->object))
1a578e9b
AC
7011 {
7012 /* If we're on a string with `help-echo' text property,
7013 arrange for the help to be displayed. This is done by
7014 setting the global variable help_echo to the help string. */
7015 help = Fget_text_property (make_number (glyph->charpos),
7016 Qhelp_echo, glyph->object);
7017 if (!NILP (help))
e0f712ba
AC
7018 {
7019 help_echo = help;
7020 XSETWINDOW (help_echo_window, w);
7021 help_echo_object = glyph->object;
7022 help_echo_pos = glyph->charpos;
7023 }
1a578e9b
AC
7024
7025 /* Change the mouse pointer according to what is under X/Y. */
7026 map = Fget_text_property (make_number (glyph->charpos),
7027 Qlocal_map, glyph->object);
e7cbccd1 7028 if (KEYMAPP (map))
1a578e9b
AC
7029 cursor = f->output_data.mac->nontext_cursor;
7030 else
7031 {
7032 map = Fget_text_property (make_number (glyph->charpos),
7033 Qkeymap, glyph->object);
e7cbccd1 7034 if (KEYMAPP (map))
1a578e9b
AC
7035 cursor = f->output_data.mac->nontext_cursor;
7036 }
7037 }
7038 }
7039
7040#if 0 /* MAC_TODO: mouse cursor */
7041 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7042#endif
7043}
7044
7045
7046/* Take proper action when the mouse has moved to position X, Y on
7047 frame F as regards highlighting characters that have mouse-face
7048 properties. Also de-highlighting chars where the mouse was before.
7049 X and Y can be negative or out of range. */
7050
7051static void
7052note_mouse_highlight (f, x, y)
7053 struct frame *f;
7054 int x, y;
7055{
7056 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7057 int portion;
7058 Lisp_Object window;
7059 struct window *w;
e0f712ba 7060 struct buffer *b;
1a578e9b 7061
e0f712ba
AC
7062#if 0
7063 /* When a menu is active, don't highlight because this looks odd. */
1a578e9b
AC
7064 if (popup_activated ())
7065 return;
7066#endif
7067
e0f712ba 7068 if (NILP (Vmouse_highlight)
1a578e9b
AC
7069 || !f->glyphs_initialized_p)
7070 return;
7071
7072 dpyinfo->mouse_face_mouse_x = x;
7073 dpyinfo->mouse_face_mouse_y = y;
7074 dpyinfo->mouse_face_mouse_frame = f;
7075
7076 if (dpyinfo->mouse_face_defer)
7077 return;
7078
7079 if (gc_in_progress)
7080 {
7081 dpyinfo->mouse_face_deferred_gc = 1;
7082 return;
7083 }
7084
7085 /* Which window is that in? */
7086 window = window_from_coordinates (f, x, y, &portion, 1);
7087
7088 /* If we were displaying active text in another window, clear that. */
7089 if (! EQ (window, dpyinfo->mouse_face_window))
7090 clear_mouse_face (dpyinfo);
7091
7092 /* Not on a window -> return. */
7093 if (!WINDOWP (window))
7094 return;
7095
e0f712ba
AC
7096 /* Reset help_echo. It will get recomputed below. */
7097 help_echo = Qnil;
7098
1a578e9b
AC
7099 /* Convert to window-relative pixel coordinates. */
7100 w = XWINDOW (window);
7101 frame_to_window_pixel_xy (w, &x, &y);
7102
7103 /* Handle tool-bar window differently since it doesn't display a
7104 buffer. */
7105 if (EQ (window, f->tool_bar_window))
7106 {
7107 note_tool_bar_highlight (f, x, y);
7108 return;
7109 }
7110
e0f712ba 7111 /* Mouse is on the mode or header line? */
1a578e9b
AC
7112 if (portion == 1 || portion == 3)
7113 {
1a578e9b
AC
7114 note_mode_line_highlight (w, x, portion == 1);
7115 return;
7116 }
e0f712ba
AC
7117#if 0 /* TODO: mouse cursor */
7118 if (portion == 2)
7119 cursor = f->output_data.x->horizontal_drag_cursor;
1a578e9b 7120 else
e0f712ba 7121 cursor = f->output_data.x->text_cursor;
1a578e9b 7122#endif
1a578e9b
AC
7123 /* Are we in a window whose display is up to date?
7124 And verify the buffer's text has not changed. */
e0f712ba 7125 b = XBUFFER (w->buffer);
1a578e9b
AC
7126 if (/* Within text portion of the window. */
7127 portion == 0
7128 && EQ (w->window_end_valid, w->buffer)
e0f712ba
AC
7129 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7130 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
1a578e9b
AC
7131 {
7132 int hpos, vpos, pos, i, area;
7133 struct glyph *glyph;
e0f712ba
AC
7134 Lisp_Object object;
7135 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7136 Lisp_Object *overlay_vec = NULL;
7137 int len, noverlays;
7138 struct buffer *obuf;
7139 int obegv, ozv, same_region;
1a578e9b
AC
7140
7141 /* Find the glyph under X/Y. */
e0f712ba 7142 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
1a578e9b
AC
7143
7144 /* Clear mouse face if X/Y not over text. */
7145 if (glyph == NULL
7146 || area != TEXT_AREA
7147 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7148 {
7149 clear_mouse_face (dpyinfo);
e0f712ba
AC
7150 /* TODO: mouse cursor */
7151 goto set_cursor;
1a578e9b
AC
7152 }
7153
7154 pos = glyph->charpos;
e0f712ba
AC
7155 object = glyph->object;
7156 if (!STRINGP (object) && !BUFFERP (object))
7157 goto set_cursor;
7158
7159 /* If we get an out-of-range value, return now; avoid an error. */
7160 if (BUFFERP (object) && pos > BUF_Z (b))
7161 goto set_cursor;
7162
7163 /* Make the window's buffer temporarily current for
7164 overlays_at and compute_char_face. */
7165 obuf = current_buffer;
7166 current_buffer = b;
7167 obegv = BEGV;
7168 ozv = ZV;
7169 BEGV = BEG;
7170 ZV = Z;
7171
7172 /* Is this char mouse-active or does it have help-echo? */
7173 position = make_number (pos);
7174
7175 if (BUFFERP (object))
7176 {
7177 /* Put all the overlays we want in a vector in overlay_vec.
7178 Store the length in len. If there are more than 10, make
7179 enough space for all, and try again. */
7180 len = 10;
7181 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7182 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7183 if (noverlays > len)
7184 {
7185 len = noverlays;
7186 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7187 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7188 }
1a578e9b 7189
e0f712ba
AC
7190 /* Sort overlays into increasing priority order. */
7191 noverlays = sort_overlays (overlay_vec, noverlays, w);
7192 }
7193 else
7194 noverlays = 0;
7195
7196 same_region = (EQ (window, dpyinfo->mouse_face_window)
7197 && vpos >= dpyinfo->mouse_face_beg_row
7198 && vpos <= dpyinfo->mouse_face_end_row
7199 && (vpos > dpyinfo->mouse_face_beg_row
7200 || hpos >= dpyinfo->mouse_face_beg_col)
7201 && (vpos < dpyinfo->mouse_face_end_row
7202 || hpos < dpyinfo->mouse_face_end_col
7203 || dpyinfo->mouse_face_past_end));
7204
7205 /* TODO: if (same_region)
7206 mouse cursor */
7207
7208 /* Check mouse-face highlighting. */
7209 if (! same_region
7210 /* If there exists an overlay with mouse-face overlapping
7211 the one we are currently highlighting, we have to
7212 check if we enter the overlapping overlay, and then
7213 highlight that. */
7214 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7215 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7216 {
7217 /* Find the highest priority overlay that has a mouse-face
7218 property. */
7219 overlay = Qnil;
7220 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7221 {
7222 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7223 if (!NILP (mouse_face))
7224 overlay = overlay_vec[i];
7225 }
1a578e9b 7226
e0f712ba
AC
7227 /* If we're actually highlighting the same overlay as
7228 before, there's no need to do that again. */
7229 if (!NILP (overlay)
7230 && EQ (overlay, dpyinfo->mouse_face_overlay))
7231 goto check_help_echo;
1a578e9b 7232
e0f712ba 7233 dpyinfo->mouse_face_overlay = overlay;
1a578e9b 7234
e0f712ba
AC
7235 /* Clear the display of the old active region, if any. */
7236 clear_mouse_face (dpyinfo);
7237 /* TODO: mouse cursor changes. */
1a578e9b 7238
e0f712ba
AC
7239 /* If no overlay applies, get a text property. */
7240 if (NILP (overlay))
7241 mouse_face = Fget_text_property (position, Qmouse_face, object);
1a578e9b 7242
e0f712ba
AC
7243 /* Handle the overlay case. */
7244 if (!NILP (overlay))
7245 {
7246 /* Find the range of text around this char that
7247 should be active. */
7248 Lisp_Object before, after;
7249 int ignore;
7250
7251 before = Foverlay_start (overlay);
7252 after = Foverlay_end (overlay);
7253 /* Record this as the current active region. */
7254 fast_find_position (w, XFASTINT (before),
7255 &dpyinfo->mouse_face_beg_col,
7256 &dpyinfo->mouse_face_beg_row,
7257 &dpyinfo->mouse_face_beg_x,
7258 &dpyinfo->mouse_face_beg_y, Qnil);
7259
7260 dpyinfo->mouse_face_past_end
7261 = !fast_find_position (w, XFASTINT (after),
7262 &dpyinfo->mouse_face_end_col,
7263 &dpyinfo->mouse_face_end_row,
7264 &dpyinfo->mouse_face_end_x,
7265 &dpyinfo->mouse_face_end_y, Qnil);
7266 dpyinfo->mouse_face_window = window;
7267
7268 dpyinfo->mouse_face_face_id
7269 = face_at_buffer_position (w, pos, 0, 0,
7270 &ignore, pos + 1, 1);
7271
7272 /* Display it as active. */
7273 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7274 /* TODO: mouse cursor changes. */
7275 }
7276 /* Handle the text property case. */
7277 else if (! NILP (mouse_face) && BUFFERP (object))
7278 {
7279 /* Find the range of text around this char that
7280 should be active. */
7281 Lisp_Object before, after, beginning, end;
7282 int ignore;
7283
7284 beginning = Fmarker_position (w->start);
7285 end = make_number (BUF_Z (XBUFFER (object))
7286 - XFASTINT (w->window_end_pos));
7287 before
7288 = Fprevious_single_property_change (make_number (pos + 1),
7289 Qmouse_face,
7290 object, beginning);
7291 after
7292 = Fnext_single_property_change (position, Qmouse_face,
7293 object, end);
7294
7295 /* Record this as the current active region. */
7296 fast_find_position (w, XFASTINT (before),
7297 &dpyinfo->mouse_face_beg_col,
7298 &dpyinfo->mouse_face_beg_row,
7299 &dpyinfo->mouse_face_beg_x,
7300 &dpyinfo->mouse_face_beg_y, Qnil);
7301 dpyinfo->mouse_face_past_end
7302 = !fast_find_position (w, XFASTINT (after),
7303 &dpyinfo->mouse_face_end_col,
7304 &dpyinfo->mouse_face_end_row,
7305 &dpyinfo->mouse_face_end_x,
7306 &dpyinfo->mouse_face_end_y, Qnil);
7307 dpyinfo->mouse_face_window = window;
7308
7309 if (BUFFERP (object))
1a578e9b
AC
7310 dpyinfo->mouse_face_face_id
7311 = face_at_buffer_position (w, pos, 0, 0,
7312 &ignore, pos + 1, 1);
7313
e0f712ba
AC
7314 /* Display it as active. */
7315 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7316 /* TODO: mouse cursor changes. */
7317 }
7318 else if (!NILP (mouse_face) && STRINGP (object))
7319 {
7320 Lisp_Object b, e;
7321 int ignore;
7322
7323 b = Fprevious_single_property_change (make_number (pos + 1),
7324 Qmouse_face,
7325 object, Qnil);
7326 e = Fnext_single_property_change (position, Qmouse_face,
7327 object, Qnil);
7328 if (NILP (b))
7329 b = make_number (0);
7330 if (NILP (e))
d5db4077 7331 e = make_number (SCHARS (object) - 1);
e0f712ba 7332 fast_find_string_pos (w, XINT (b), object,
1a578e9b
AC
7333 &dpyinfo->mouse_face_beg_col,
7334 &dpyinfo->mouse_face_beg_row,
7335 &dpyinfo->mouse_face_beg_x,
e0f712ba
AC
7336 &dpyinfo->mouse_face_beg_y, 0);
7337 fast_find_string_pos (w, XINT (e), object,
7338 &dpyinfo->mouse_face_end_col,
7339 &dpyinfo->mouse_face_end_row,
7340 &dpyinfo->mouse_face_end_x,
7341 &dpyinfo->mouse_face_end_y, 1);
7342 dpyinfo->mouse_face_past_end = 0;
7343 dpyinfo->mouse_face_window = window;
7344 dpyinfo->mouse_face_face_id
7345 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7346 glyph->face_id, 1);
7347 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7348 /* TODO: mouse cursor changes. */
1a578e9b 7349 }
e0f712ba 7350 else if (STRINGP (object) && NILP (mouse_face))
1a578e9b 7351 {
e0f712ba
AC
7352 /* A string which doesn't have mouse-face, but
7353 the text ``under'' it might have. */
7354 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7355 int start = MATRIX_ROW_START_CHARPOS (r);
7356
7357 pos = string_buffer_position (w, object, start);
7358 if (pos > 0)
7359 mouse_face = get_char_property_and_overlay (make_number (pos),
7360 Qmouse_face,
7361 w->buffer,
7362 &overlay);
7363 if (!NILP (mouse_face) && !NILP (overlay))
1a578e9b 7364 {
e0f712ba
AC
7365 Lisp_Object before = Foverlay_start (overlay);
7366 Lisp_Object after = Foverlay_end (overlay);
7367 int ignore;
7368
7369 /* Note that we might not be able to find position
7370 BEFORE in the glyph matrix if the overlay is
7371 entirely covered by a `display' property. In
7372 this case, we overshoot. So let's stop in
7373 the glyph matrix before glyphs for OBJECT. */
7374 fast_find_position (w, XFASTINT (before),
7375 &dpyinfo->mouse_face_beg_col,
7376 &dpyinfo->mouse_face_beg_row,
7377 &dpyinfo->mouse_face_beg_x,
7378 &dpyinfo->mouse_face_beg_y,
7379 object);
7380
7381 dpyinfo->mouse_face_past_end
7382 = !fast_find_position (w, XFASTINT (after),
7383 &dpyinfo->mouse_face_end_col,
7384 &dpyinfo->mouse_face_end_row,
7385 &dpyinfo->mouse_face_end_x,
7386 &dpyinfo->mouse_face_end_y,
7387 Qnil);
7388 dpyinfo->mouse_face_window = window;
7389 dpyinfo->mouse_face_face_id
7390 = face_at_buffer_position (w, pos, 0, 0,
7391 &ignore, pos + 1, 1);
7392
7393 /* Display it as active. */
7394 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7395 /* TODO: mouse cursor changes. */
1a578e9b
AC
7396 }
7397 }
7398 }
1a578e9b 7399
e0f712ba
AC
7400 check_help_echo:
7401
7402 /* Look for a `help-echo' property. */
7403 {
7404 Lisp_Object help, overlay;
7405
7406 /* Check overlays first. */
7407 help = overlay = Qnil;
7408 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7409 {
7410 overlay = overlay_vec[i];
7411 help = Foverlay_get (overlay, Qhelp_echo);
7412 }
7413
7414 if (!NILP (help))
7415 {
7416 help_echo = help;
7417 help_echo_window = window;
7418 help_echo_object = overlay;
7419 help_echo_pos = pos;
7420 }
7421 else
7422 {
7423 Lisp_Object object = glyph->object;
7424 int charpos = glyph->charpos;
7425
7426 /* Try text properties. */
7427 if (STRINGP (object)
7428 && charpos >= 0
d5db4077 7429 && charpos < SCHARS (object))
e0f712ba
AC
7430 {
7431 help = Fget_text_property (make_number (charpos),
7432 Qhelp_echo, object);
7433 if (NILP (help))
7434 {
7435 /* If the string itself doesn't specify a help-echo,
7436 see if the buffer text ``under'' it does. */
7437 struct glyph_row *r
7438 = MATRIX_ROW (w->current_matrix, vpos);
7439 int start = MATRIX_ROW_START_CHARPOS (r);
7440 int pos = string_buffer_position (w, object, start);
7441 if (pos > 0)
7442 {
7443 help = Fget_char_property (make_number (pos),
7444 Qhelp_echo, w->buffer);
7445 if (!NILP (help))
7446 {
7447 charpos = pos;
7448 object = w->buffer;
7449 }
7450 }
7451 }
7452 }
7453 else if (BUFFERP (object)
7454 && charpos >= BEGV
7455 && charpos < ZV)
7456 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7457 object);
7458
7459 if (!NILP (help))
7460 {
7461 help_echo = help;
7462 help_echo_window = window;
7463 help_echo_object = object;
7464 help_echo_pos = charpos;
7465 }
7466 }
7467 }
7468
7469 BEGV = obegv;
7470 ZV = ozv;
7471 current_buffer = obuf;
7472 }
7473
7474 set_cursor:
7475 /* TODO: mouse cursor changes. */
7476 ;
7477}
7478
7479static void
7480redo_mouse_highlight ()
7481{
7482 if (!NILP (last_mouse_motion_frame)
7483 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
1a578e9b
AC
7484 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7485 last_mouse_motion_position.h,
7486 last_mouse_motion_position.v);
7487}
7488
7489
7490\f
7491/***********************************************************************
7492 Tool-bars
7493 ***********************************************************************/
7494
7495static int x_tool_bar_item P_ ((struct frame *, int, int,
7496 struct glyph **, int *, int *, int *));
7497
7498/* Tool-bar item index of the item on which a mouse button was pressed
7499 or -1. */
7500
7501static int last_tool_bar_item;
7502
7503
7504/* Get information about the tool-bar item at position X/Y on frame F.
7505 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7506 the current matrix of the tool-bar window of F, or NULL if not
7507 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7508 item in F->current_tool_bar_items. Value is
7509
7510 -1 if X/Y is not on a tool-bar item
7511 0 if X/Y is on the same item that was highlighted before.
7512 1 otherwise. */
7513
7514static int
7515x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7516 struct frame *f;
7517 int x, y;
7518 struct glyph **glyph;
7519 int *hpos, *vpos, *prop_idx;
7520{
7521 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7522 struct window *w = XWINDOW (f->tool_bar_window);
7523 int area;
7524
7525 /* Find the glyph under X/Y. */
e0f712ba 7526 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
1a578e9b
AC
7527 if (*glyph == NULL)
7528 return -1;
7529
7530 /* Get the start of this tool-bar item's properties in
7531 f->current_tool_bar_items. */
7532 if (!tool_bar_item_info (f, *glyph, prop_idx))
7533 return -1;
7534
7535 /* Is mouse on the highlighted item? */
7536 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7537 && *vpos >= dpyinfo->mouse_face_beg_row
7538 && *vpos <= dpyinfo->mouse_face_end_row
7539 && (*vpos > dpyinfo->mouse_face_beg_row
7540 || *hpos >= dpyinfo->mouse_face_beg_col)
7541 && (*vpos < dpyinfo->mouse_face_end_row
7542 || *hpos < dpyinfo->mouse_face_end_col
7543 || dpyinfo->mouse_face_past_end))
7544 return 0;
7545
7546 return 1;
7547}
7548
7549
7550/* Handle mouse button event on the tool-bar of frame F, at
7551 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7552 or ButtonRelase. */
7553
7554static void
7555x_handle_tool_bar_click (f, button_event)
7556 struct frame *f;
7557 EventRecord *button_event;
7558{
7559 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7560 struct window *w = XWINDOW (f->tool_bar_window);
7561 int hpos, vpos, prop_idx;
7562 struct glyph *glyph;
7563 Lisp_Object enabled_p;
7564 int x = button_event->where.h;
7565 int y = button_event->where.v;
7566
7567 /* If not on the highlighted tool-bar item, return. */
7568 frame_to_window_pixel_xy (w, &x, &y);
7569 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7570 return;
7571
7572 /* If item is disabled, do nothing. */
2d4bc735 7573 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
1a578e9b
AC
7574 if (NILP (enabled_p))
7575 return;
7576
7577 if (button_event->what == mouseDown)
7578 {
7579 /* Show item in pressed state. */
7580 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7581 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7582 last_tool_bar_item = prop_idx;
7583 }
7584 else
7585 {
7586 Lisp_Object key, frame;
7587 struct input_event event;
7588
7589 /* Show item in released state. */
7590 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7591 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7592
2d4bc735 7593 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
1a578e9b
AC
7594
7595 XSETFRAME (frame, f);
7596 event.kind = TOOL_BAR_EVENT;
7597 event.frame_or_window = frame;
7598 event.arg = frame;
7599 kbd_buffer_store_event (&event);
7600
7601 event.kind = TOOL_BAR_EVENT;
7602 event.frame_or_window = frame;
7603 event.arg = key;
7604 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7605 button_event->modifiers);
7606 kbd_buffer_store_event (&event);
7607 last_tool_bar_item = -1;
7608 }
7609}
7610
7611
7612/* Possibly highlight a tool-bar item on frame F when mouse moves to
7613 tool-bar window-relative coordinates X/Y. Called from
7614 note_mouse_highlight. */
7615
7616static void
7617note_tool_bar_highlight (f, x, y)
7618 struct frame *f;
7619 int x, y;
7620{
7621 Lisp_Object window = f->tool_bar_window;
7622 struct window *w = XWINDOW (window);
7623 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7624 int hpos, vpos;
7625 struct glyph *glyph;
7626 struct glyph_row *row;
7627 int i;
7628 Lisp_Object enabled_p;
7629 int prop_idx;
7630 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7631 int mouse_down_p, rc;
7632
7633 /* Function note_mouse_highlight is called with negative x(y
7634 values when mouse moves outside of the frame. */
7635 if (x <= 0 || y <= 0)
7636 {
7637 clear_mouse_face (dpyinfo);
7638 return;
7639 }
7640
7641 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7642 if (rc < 0)
7643 {
7644 /* Not on tool-bar item. */
7645 clear_mouse_face (dpyinfo);
7646 return;
7647 }
7648 else if (rc == 0)
7649 /* On same tool-bar item as before. */
7650 goto set_help_echo;
7651
7652 clear_mouse_face (dpyinfo);
7653
7654 /* Mouse is down, but on different tool-bar item? */
7655 mouse_down_p = (dpyinfo->grabbed
7656 && f == last_mouse_frame
7657 && FRAME_LIVE_P (f));
7658 if (mouse_down_p
7659 && last_tool_bar_item != prop_idx)
7660 return;
7661
7662 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7663 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7664
7665 /* If tool-bar item is not enabled, don't highlight it. */
2d4bc735 7666 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
1a578e9b
AC
7667 if (!NILP (enabled_p))
7668 {
7669 /* Compute the x-position of the glyph. In front and past the
7670 image is a space. We include this is the highlighted area. */
7671 row = MATRIX_ROW (w->current_matrix, vpos);
7672 for (i = x = 0; i < hpos; ++i)
7673 x += row->glyphs[TEXT_AREA][i].pixel_width;
7674
7675 /* Record this as the current active region. */
7676 dpyinfo->mouse_face_beg_col = hpos;
7677 dpyinfo->mouse_face_beg_row = vpos;
7678 dpyinfo->mouse_face_beg_x = x;
7679 dpyinfo->mouse_face_beg_y = row->y;
7680 dpyinfo->mouse_face_past_end = 0;
7681
7682 dpyinfo->mouse_face_end_col = hpos + 1;
7683 dpyinfo->mouse_face_end_row = vpos;
7684 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7685 dpyinfo->mouse_face_end_y = row->y;
7686 dpyinfo->mouse_face_window = window;
7687 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7688
7689 /* Display it as active. */
7690 show_mouse_face (dpyinfo, draw);
7691 dpyinfo->mouse_face_image_state = draw;
7692 }
7693
7694 set_help_echo:
7695
7696 /* Set help_echo to a help string.to display for this tool-bar item.
7697 XTread_socket does the rest. */
7698 help_echo_object = help_echo_window = Qnil;
7699 help_echo_pos = -1;
2d4bc735 7700 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
1a578e9b 7701 if (NILP (help_echo))
2d4bc735 7702 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
1a578e9b
AC
7703}
7704
7705
7706\f
e0f712ba
AC
7707/* Find the glyph matrix position of buffer position CHARPOS in window
7708 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7709 current glyphs must be up to date. If CHARPOS is above window
7710 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7711 of last line in W. In the row containing CHARPOS, stop before glyphs
7712 having STOP as object. */
7713
7714#if 0 /* This is a version of fast_find_position that's more correct
7715 in the presence of hscrolling, for example. I didn't install
7716 it right away because the problem fixed is minor, it failed
7717 in 20.x as well, and I think it's too risky to install
7718 so near the release of 21.1. 2001-09-25 gerd. */
7719
7720static int
7721fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7722 struct window *w;
7723 int charpos;
7724 int *hpos, *vpos, *x, *y;
7725 Lisp_Object stop;
7726{
7727 struct glyph_row *row, *first;
7728 struct glyph *glyph, *end;
7729 int i, past_end = 0;
7730
7731 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7732 row = row_containing_pos (w, charpos, first, NULL, 0);
7733 if (row == NULL)
7734 {
7735 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7736 {
7737 *x = *y = *hpos = *vpos = 0;
7738 return 0;
7739 }
7740 else
7741 {
7742 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7743 past_end = 1;
7744 }
7745 }
7746
7747 *x = row->x;
7748 *y = row->y;
7749 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7750
7751 glyph = row->glyphs[TEXT_AREA];
7752 end = glyph + row->used[TEXT_AREA];
7753
7754 /* Skip over glyphs not having an object at the start of the row.
7755 These are special glyphs like truncation marks on terminal
7756 frames. */
7757 if (row->displays_text_p)
7758 while (glyph < end
7759 && INTEGERP (glyph->object)
7760 && !EQ (stop, glyph->object)
7761 && glyph->charpos < 0)
7762 {
7763 *x += glyph->pixel_width;
7764 ++glyph;
7765 }
7766
7767 while (glyph < end
7768 && !INTEGERP (glyph->object)
7769 && !EQ (stop, glyph->object)
7770 && (!BUFFERP (glyph->object)
7771 || glyph->charpos < charpos))
7772 {
7773 *x += glyph->pixel_width;
7774 ++glyph;
7775 }
7776
7777 *hpos = glyph - row->glyphs[TEXT_AREA];
7778 return past_end;
7779}
7780
7781#else /* not 0 */
1a578e9b
AC
7782
7783static int
e0f712ba 7784fast_find_position (w, pos, hpos, vpos, x, y, stop)
1a578e9b
AC
7785 struct window *w;
7786 int pos;
7787 int *hpos, *vpos, *x, *y;
e0f712ba 7788 Lisp_Object stop;
1a578e9b
AC
7789{
7790 int i;
7791 int lastcol;
7792 int maybe_next_line_p = 0;
7793 int line_start_position;
7794 int yb = window_text_bottom_y (w);
e0f712ba
AC
7795 struct glyph_row *row, *best_row;
7796 int row_vpos, best_row_vpos;
1a578e9b
AC
7797 int current_x;
7798
e0f712ba
AC
7799 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7800 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7801
1a578e9b
AC
7802 while (row->y < yb)
7803 {
7804 if (row->used[TEXT_AREA])
7805 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7806 else
7807 line_start_position = 0;
7808
7809 if (line_start_position > pos)
7810 break;
7811 /* If the position sought is the end of the buffer,
7812 don't include the blank lines at the bottom of the window. */
7813 else if (line_start_position == pos
e0f712ba 7814 && pos == BUF_ZV (XBUFFER (w->buffer)))
1a578e9b
AC
7815 {
7816 maybe_next_line_p = 1;
7817 break;
7818 }
7819 else if (line_start_position > 0)
e0f712ba
AC
7820 {
7821 best_row = row;
7822 best_row_vpos = row_vpos;
7823 }
1a578e9b
AC
7824
7825 if (row->y + row->height >= yb)
e0f712ba
AC
7826 break;
7827
1a578e9b
AC
7828 ++row;
7829 ++row_vpos;
7830 }
e0f712ba 7831
1a578e9b
AC
7832 /* Find the right column within BEST_ROW. */
7833 lastcol = 0;
7834 current_x = best_row->x;
7835 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7836 {
7837 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
e0f712ba 7838 int charpos = glyph->charpos;
1a578e9b 7839
e0f712ba 7840 if (BUFFERP (glyph->object))
1a578e9b 7841 {
e0f712ba
AC
7842 if (charpos == pos)
7843 {
7844 *hpos = i;
7845 *vpos = best_row_vpos;
7846 *x = current_x;
7847 *y = best_row->y;
7848 return 1;
7849 }
7850 else if (charpos > pos)
7851 break;
1a578e9b 7852 }
e0f712ba 7853 else if (EQ (glyph->object, stop))
1a578e9b 7854 break;
1a578e9b 7855
e0f712ba
AC
7856 if (charpos > 0)
7857 lastcol = i;
1a578e9b
AC
7858 current_x += glyph->pixel_width;
7859 }
7860
7861 /* If we're looking for the end of the buffer,
7862 and we didn't find it in the line we scanned,
7863 use the start of the following line. */
7864 if (maybe_next_line_p)
7865 {
7866 ++best_row;
7867 ++best_row_vpos;
7868 lastcol = 0;
7869 current_x = best_row->x;
7870 }
7871
7872 *vpos = best_row_vpos;
7873 *hpos = lastcol + 1;
7874 *x = current_x;
7875 *y = best_row->y;
7876 return 0;
7877}
7878
e0f712ba
AC
7879#endif /* not 0 */
7880
7881
7882/* Find the position of the glyph for position POS in OBJECT in
7883 window W's current matrix, and return in *X/*Y the pixel
7884 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7885
7886 RIGHT_P non-zero means return the position of the right edge of the
7887 glyph, RIGHT_P zero means return the left edge position.
7888
7889 If no glyph for POS exists in the matrix, return the position of
7890 the glyph with the next smaller position that is in the matrix, if
7891 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7892 exists in the matrix, return the position of the glyph with the
7893 next larger position in OBJECT.
7894
7895 Value is non-zero if a glyph was found. */
7896
7897static int
7898fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7899 struct window *w;
7900 int pos;
7901 Lisp_Object object;
7902 int *hpos, *vpos, *x, *y;
7903 int right_p;
7904{
7905 int yb = window_text_bottom_y (w);
7906 struct glyph_row *r;
7907 struct glyph *best_glyph = NULL;
7908 struct glyph_row *best_row = NULL;
7909 int best_x = 0;
7910
7911 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7912 r->enabled_p && r->y < yb;
7913 ++r)
7914 {
7915 struct glyph *g = r->glyphs[TEXT_AREA];
7916 struct glyph *e = g + r->used[TEXT_AREA];
7917 int gx;
7918
7919 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7920 if (EQ (g->object, object))
7921 {
7922 if (g->charpos == pos)
7923 {
7924 best_glyph = g;
7925 best_x = gx;
7926 best_row = r;
7927 goto found;
7928 }
7929 else if (best_glyph == NULL
7930 || ((abs (g->charpos - pos)
7931 < abs (best_glyph->charpos - pos))
7932 && (right_p
7933 ? g->charpos < pos
7934 : g->charpos > pos)))
7935 {
7936 best_glyph = g;
7937 best_x = gx;
7938 best_row = r;
7939 }
7940 }
7941 }
7942
7943 found:
7944
7945 if (best_glyph)
7946 {
7947 *x = best_x;
7948 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7949
7950 if (right_p)
7951 {
7952 *x += best_glyph->pixel_width;
7953 ++*hpos;
7954 }
7955
7956 *y = best_row->y;
7957 *vpos = best_row - w->current_matrix->rows;
7958 }
7959
7960 return best_glyph != NULL;
7961}
7962
1a578e9b
AC
7963
7964/* Display the active region described by mouse_face_*
7965 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7966
7967static void
7968show_mouse_face (dpyinfo, draw)
7969 struct mac_display_info *dpyinfo;
7970 enum draw_glyphs_face draw;
7971{
7972 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7973 struct frame *f = XFRAME (WINDOW_FRAME (w));
1a578e9b 7974
e0f712ba
AC
7975 if (/* If window is in the process of being destroyed, don't bother
7976 to do anything. */
7977 w->current_matrix != NULL
7978 /* Don't update mouse highlight if hidden */
7979 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7980 /* Recognize when we are called to operate on rows that don't exist
7981 anymore. This can happen when a window is split. */
7982 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
1a578e9b 7983 {
e0f712ba
AC
7984 int phys_cursor_on_p = w->phys_cursor_on_p;
7985 struct glyph_row *row, *first, *last;
1a578e9b 7986
e0f712ba
AC
7987 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7988 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7989
7990 for (row = first; row <= last && row->enabled_p; ++row)
1a578e9b 7991 {
e0f712ba 7992 int start_hpos, end_hpos, start_x;
1a578e9b 7993
e0f712ba
AC
7994 /* For all but the first row, the highlight starts at column 0. */
7995 if (row == first)
7996 {
7997 start_hpos = dpyinfo->mouse_face_beg_col;
7998 start_x = dpyinfo->mouse_face_beg_x;
7999 }
8000 else
8001 {
8002 start_hpos = 0;
8003 start_x = 0;
8004 }
1a578e9b 8005
e0f712ba
AC
8006 if (row == last)
8007 end_hpos = dpyinfo->mouse_face_end_col;
8008 else
8009 end_hpos = row->used[TEXT_AREA];
1a578e9b 8010
e0f712ba
AC
8011 if (end_hpos > start_hpos)
8012 {
8013 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8014 start_hpos, end_hpos, draw, 0);
1a578e9b 8015
e0f712ba
AC
8016 row->mouse_face_p
8017 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8018 }
8019 }
1a578e9b 8020
e0f712ba
AC
8021 /* When we've written over the cursor, arrange for it to
8022 be displayed again. */
8023 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8024 x_display_cursor (w, 1,
8025 w->phys_cursor.hpos, w->phys_cursor.vpos,
8026 w->phys_cursor.x, w->phys_cursor.y);
8027 }
1a578e9b 8028
1a578e9b
AC
8029#if 0 /* MAC_TODO: mouse cursor */
8030 /* Change the mouse cursor. */
8031 if (draw == DRAW_NORMAL_TEXT)
8032 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8033 f->output_data.x->text_cursor);
8034 else if (draw == DRAW_MOUSE_FACE)
8035 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8036 f->output_data.x->cross_cursor);
8037 else
8038 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8039 f->output_data.x->nontext_cursor);
8040#endif
1a578e9b
AC
8041}
8042
8043/* Clear out the mouse-highlighted active region.
8044 Redraw it un-highlighted first. */
8045
e0f712ba 8046static int
1a578e9b
AC
8047clear_mouse_face (dpyinfo)
8048 struct mac_display_info *dpyinfo;
8049{
e0f712ba
AC
8050 int cleared = 0;
8051
1a578e9b 8052 if (! NILP (dpyinfo->mouse_face_window))
e0f712ba
AC
8053 {
8054 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8055 cleared = 1;
8056 }
1a578e9b
AC
8057
8058 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8059 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8060 dpyinfo->mouse_face_window = Qnil;
e0f712ba
AC
8061 dpyinfo->mouse_face_overlay = Qnil;
8062 return cleared;
1a578e9b
AC
8063}
8064
8065
8066/* Clear any mouse-face on window W. This function is part of the
8067 redisplay interface, and is called from try_window_id and similar
8068 functions to ensure the mouse-highlight is off. */
8069
e0f712ba 8070static void
1a578e9b
AC
8071x_clear_mouse_face (w)
8072 struct window *w;
8073{
8074 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8075 Lisp_Object window;
8076
e0f712ba 8077 BLOCK_INPUT;
1a578e9b
AC
8078 XSETWINDOW (window, w);
8079 if (EQ (window, dpyinfo->mouse_face_window))
8080 clear_mouse_face (dpyinfo);
e0f712ba 8081 UNBLOCK_INPUT;
1a578e9b
AC
8082}
8083
8084
8085/* Just discard the mouse face information for frame F, if any.
8086 This is used when the size of F is changed. */
8087
e0f712ba 8088void
1a578e9b
AC
8089cancel_mouse_face (f)
8090 FRAME_PTR f;
8091{
8092 Lisp_Object window;
8093 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8094
8095 window = dpyinfo->mouse_face_window;
8096 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8097 {
8098 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8099 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8100 dpyinfo->mouse_face_window = Qnil;
8101 }
8102}
8103\f
8104static struct scroll_bar *x_window_to_scroll_bar ();
8105static void x_scroll_bar_report_motion ();
e0f712ba
AC
8106static void x_check_fullscreen P_ ((struct frame *));
8107static void x_check_fullscreen_move P_ ((struct frame *));
8108static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8109
8110
8111/* Try to determine frame pixel position and size of the glyph under
8112 frame pixel coordinates X/Y on frame F . Return the position and
8113 size in *RECT. Value is non-zero if we could compute these
8114 values. */
8115
8116static int
8117glyph_rect (f, x, y, rect)
8118 struct frame *f;
8119 int x, y;
8120 Rect *rect;
8121{
8122 Lisp_Object window;
8123 int part;
8124
8125 window = window_from_coordinates (f, x, y, &part, 0);
8126 if (!NILP (window))
8127 {
8128 struct window *w = XWINDOW (window);
8129 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8130 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8131
8132 frame_to_window_pixel_xy (w, &x, &y);
8133
8134 for (; r < end && r->enabled_p; ++r)
8135 if (r->y <= y && r->y + r->height > y)
8136 {
8137 /* Found the row at y. */
8138 struct glyph *g = r->glyphs[TEXT_AREA];
8139 struct glyph *end = g + r->used[TEXT_AREA];
8140 int gx;
8141
8142 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8143 rect->bottom = rect->top + r->height;
8144
8145 if (x < r->x)
8146 {
8147 /* x is to the left of the first glyph in the row. */
8148 rect->left = XINT (w->left);
8149 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8150 return 1;
8151 }
8152
8153 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8154 if (gx <= x && gx + g->pixel_width > x)
8155 {
8156 /* x is on a glyph. */
8157 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8158 rect->right = rect->left + g->pixel_width;
8159 return 1;
8160 }
8161
8162 /* x is to the right of the last glyph in the row. */
8163 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8164 rect->right = XINT (w->left) + XINT (w->width);
8165 return 1;
8166 }
8167 }
8168
8169 /* The y is not on any row. */
8170 return 0;
8171}
8172
8173/* Record the position of the mouse in last_mouse_glyph. */
8174static void
8175remember_mouse_glyph (f1, gx, gy)
8176 struct frame * f1;
8177 int gx, gy;
8178{
8179 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8180 {
8181 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8182 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8183
8184 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8185 round down even for negative values. */
8186 if (gx < 0)
8187 gx -= width - 1;
8188 if (gy < 0)
8189 gy -= height - 1;
8190#if 0
8191 /* This was the original code from XTmouse_position, but it seems
8192 to give the position of the glyph diagonally next to the one
8193 the mouse is over. */
8194 gx = (gx + width - 1) / width * width;
8195 gy = (gy + height - 1) / height * height;
8196#else
8197 gx = gx / width * width;
8198 gy = gy / height * height;
8199#endif
8200
8201 last_mouse_glyph.left = gx;
8202 last_mouse_glyph.top = gy;
8203 last_mouse_glyph.right = gx + width;
8204 last_mouse_glyph.bottom = gy + height;
8205 }
8206}
1a578e9b
AC
8207
8208/* Return the current position of the mouse.
8209 *fp should be a frame which indicates which display to ask about.
8210
8211 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8212 and *part to the frame, window, and scroll bar part that the mouse
8213 is over. Set *x and *y to the portion and whole of the mouse's
8214 position on the scroll bar.
8215
8216 If the mouse movement started elsewhere, set *fp to the frame the
8217 mouse is on, *bar_window to nil, and *x and *y to the character cell
8218 the mouse is over.
8219
8220 Set *time to the server time-stamp for the time at which the mouse
8221 was at this position.
8222
8223 Don't store anything if we don't have a valid set of values to report.
8224
8225 This clears the mouse_moved flag, so we can wait for the next mouse
8226 movement. */
8227
e0f712ba 8228static void
1a578e9b
AC
8229XTmouse_position (fp, insist, bar_window, part, x, y, time)
8230 FRAME_PTR *fp;
8231 int insist;
8232 Lisp_Object *bar_window;
8233 enum scroll_bar_part *part;
8234 Lisp_Object *x, *y;
8235 unsigned long *time;
8236{
8237 Point mouse_pos;
8238 int ignore1, ignore2;
8239 WindowPtr wp = FrontWindow ();
8240 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8241 Lisp_Object frame, tail;
8242
8243 BLOCK_INPUT;
8244
8245 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8246 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8247 else
8248 {
8249 /* Clear the mouse-moved flag for every frame on this display. */
8250 FOR_EACH_FRAME (tail, frame)
8251 XFRAME (frame)->mouse_moved = 0;
8252
8253 last_mouse_scroll_bar = Qnil;
8254
e0f712ba
AC
8255#if TARGET_API_MAC_CARBON
8256 SetPort (GetWindowPort (wp));
8257#else
1a578e9b 8258 SetPort (wp);
e0f712ba
AC
8259#endif
8260
1a578e9b
AC
8261 GetMouse (&mouse_pos);
8262
8263 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8264 &last_mouse_glyph, insist);
8265
8266 *bar_window = Qnil;
8267 *part = scroll_bar_handle;
8268 *fp = f;
8269 XSETINT (*x, mouse_pos.h);
8270 XSETINT (*y, mouse_pos.v);
8271 *time = last_mouse_movement_time;
8272 }
8273
8274 UNBLOCK_INPUT;
8275}
8276
8277\f
8278/************************************************************************
8279 Scroll bars, general
8280 ************************************************************************/
8281
8282/* Create a scroll bar and return the scroll bar vector for it. W is
8283 the Emacs window on which to create the scroll bar. TOP, LEFT,
e0f712ba 8284 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
1a578e9b
AC
8285 scroll bar. */
8286
8287static struct scroll_bar *
8288x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8289 struct window *w;
8290 int top, left, width, height, disp_top, disp_height;
8291{
8292 struct frame *f = XFRAME (w->frame);
8293 struct scroll_bar *bar
8294 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8295 Rect r;
8296 ControlHandle ch;
8297
8298 BLOCK_INPUT;
8299
8300 r.left = left;
8301 r.top = disp_top;
8302 r.right = left + width;
8303 r.bottom = disp_top + disp_height;
8304
e0f712ba
AC
8305#ifdef TARGET_API_MAC_CARBON
8306 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8307 kControlScrollBarProc, 0L);
8308#else
1a578e9b
AC
8309 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8310 0L);
e0f712ba 8311#endif
1a578e9b
AC
8312 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8313 SetControlReference (ch, (long) bar);
8314
8315 XSETWINDOW (bar->window, w);
8316 XSETINT (bar->top, top);
8317 XSETINT (bar->left, left);
8318 XSETINT (bar->width, width);
8319 XSETINT (bar->height, height);
8320 XSETINT (bar->start, 0);
8321 XSETINT (bar->end, 0);
8322 bar->dragging = Qnil;
8323
8324 /* Add bar to its frame's list of scroll bars. */
8325 bar->next = FRAME_SCROLL_BARS (f);
8326 bar->prev = Qnil;
8327 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8328 if (!NILP (bar->next))
8329 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8330
8331 UNBLOCK_INPUT;
8332 return bar;
8333}
8334
8335
8336/* Draw BAR's handle in the proper position.
8337
8338 If the handle is already drawn from START to END, don't bother
8339 redrawing it, unless REBUILD is non-zero; in that case, always
8340 redraw it. (REBUILD is handy for drawing the handle after expose
8341 events.)
8342
8343 Normally, we want to constrain the start and end of the handle to
8344 fit inside its rectangle, but if the user is dragging the scroll
8345 bar handle, we want to let them drag it down all the way, so that
8346 the bar's top is as far down as it goes; otherwise, there's no way
8347 to move to the very end of the buffer. */
8348
8349static void
8350x_scroll_bar_set_handle (bar, start, end, rebuild)
8351 struct scroll_bar *bar;
8352 int start, end;
8353 int rebuild;
8354{
8355 int dragging = ! NILP (bar->dragging);
8356 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8357 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba
AC
8358 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8359 int length = end - start;
1a578e9b
AC
8360
8361 /* If the display is already accurate, do nothing. */
8362 if (! rebuild
8363 && start == XINT (bar->start)
8364 && end == XINT (bar->end))
8365 return;
8366
8367 BLOCK_INPUT;
8368
e0f712ba
AC
8369 /* Make sure the values are reasonable, and try to preserve the
8370 distance between start and end. */
8371 if (start < 0)
8372 start = 0;
8373 else if (start > top_range)
8374 start = top_range;
8375 end = start + length;
8376
8377 if (end < start)
8378 end = start;
8379 else if (end > top_range && ! dragging)
8380 end = top_range;
8381
8382 /* Store the adjusted setting in the scroll bar. */
8383 XSETINT (bar->start, start);
8384 XSETINT (bar->end, end);
8385
8386 /* Clip the end position, just for display. */
8387 if (end > top_range)
8388 end = top_range;
8389
8390 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8391 top positions, to make sure the handle is always at least that
8392 many pixels tall. */
8393 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8394
8395 SetControlMinimum (ch, 0);
8396 /* Don't inadvertently activate deactivated scroll bars */
8397 if (GetControlMaximum (ch) != -1)
8398 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8399 - (end - start));
8400 SetControlValue (ch, start);
8401#if TARGET_API_MAC_CARBON
8402 SetControlViewSize (ch, end - start);
1a578e9b 8403#endif
1a578e9b
AC
8404
8405 UNBLOCK_INPUT;
8406}
8407
8408
8409/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8410 nil. */
8411
8412static void
8413x_scroll_bar_remove (bar)
8414 struct scroll_bar *bar;
8415{
8416 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba 8417
1a578e9b
AC
8418 BLOCK_INPUT;
8419
8420 /* Destroy the Mac scroll bar control */
8421 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8422
8423 /* Disassociate this scroll bar from its window. */
8424 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8425
8426 UNBLOCK_INPUT;
8427}
8428
1a578e9b
AC
8429/* Set the handle of the vertical scroll bar for WINDOW to indicate
8430 that we are displaying PORTION characters out of a total of WHOLE
8431 characters, starting at POSITION. If WINDOW has no scroll bar,
8432 create one. */
1a578e9b
AC
8433static void
8434XTset_vertical_scroll_bar (w, portion, whole, position)
8435 struct window *w;
8436 int portion, whole, position;
8437{
8438 struct frame *f = XFRAME (w->frame);
8439 struct scroll_bar *bar;
8440 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8441 int window_x, window_y, window_width, window_height;
8442
8443 /* Get window dimensions. */
8444 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8445 top = window_y;
e0f712ba
AC
8446#ifdef MAC_OSX
8447 width = 16;
8448#else
1a578e9b 8449 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
e0f712ba 8450#endif
1a578e9b
AC
8451 height = window_height;
8452
8453 /* Compute the left edge of the scroll bar area. */
8454 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8455 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8456 else
8457 left = XFASTINT (w->left);
8458 left *= CANON_X_UNIT (f);
8459 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8460
8461 /* Compute the width of the scroll bar which might be less than
8462 the width of the area reserved for the scroll bar. */
8463 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8464 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8465 else
8466 sb_width = width;
8467
8468 /* Compute the left edge of the scroll bar. */
8469 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8470 sb_left = left + width - sb_width - (width - sb_width) / 2;
8471 else
8472 sb_left = left + (width - sb_width) / 2;
8473
8474 /* Adjustments according to Inside Macintosh to make it look nice */
8475 disp_top = top;
8476 disp_height = height;
8477 if (disp_top == 0)
8478 {
8479 disp_top = -1;
8480 disp_height++;
8481 }
8482 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8483 {
8484 disp_top++;
8485 disp_height--;
8486 }
8487
8488 if (sb_left + sb_width == PIXEL_WIDTH (f))
8489 sb_left++;
8490
8491 /* Does the scroll bar exist yet? */
8492 if (NILP (w->vertical_scroll_bar))
8493 {
8494 BLOCK_INPUT;
8495 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8496 left, top, width, height, 0);
8497 UNBLOCK_INPUT;
8498 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8499 disp_height);
8500 XSETVECTOR (w->vertical_scroll_bar, bar);
8501 }
8502 else
8503 {
8504 /* It may just need to be moved and resized. */
8505 ControlHandle ch;
8506
8507 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8508 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8509
8510 BLOCK_INPUT;
8511
8512 /* If already correctly positioned, do nothing. */
8513 if (XINT (bar->left) == sb_left
8514 && XINT (bar->top) == top
8515 && XINT (bar->width) == sb_width
8516 && XINT (bar->height) == height)
8517 Draw1Control (ch);
8518 else
8519 {
e0f712ba
AC
8520 /* Clear areas not covered by the scroll bar because it's not as
8521 wide as the area reserved for it . This makes sure a
8522 previous mode line display is cleared after C-x 2 C-x 1, for
8523 example. */
8524 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8525 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8526 left, top, area_width, height, 0);
8527
8528#if 0
1a578e9b
AC
8529 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8530 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8531 sb_left - 1, top, 1, height, 0);
e0f712ba 8532#endif
1a578e9b
AC
8533
8534 HideControl (ch);
8535 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8536 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8537 disp_height);
8538 ShowControl (ch);
8539
8540 /* Remember new settings. */
8541 XSETINT (bar->left, sb_left);
8542 XSETINT (bar->top, top);
8543 XSETINT (bar->width, sb_width);
8544 XSETINT (bar->height, height);
8545 }
8546
8547 UNBLOCK_INPUT;
8548 }
8549
8550 /* Set the scroll bar's current state, unless we're currently being
8551 dragged. */
8552 if (NILP (bar->dragging))
8553 {
8554 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8555
8556 if (whole == 0)
8557 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8558 else
8559 {
8560 int start = ((double) position * top_range) / whole;
8561 int end = ((double) (position + portion) * top_range) / whole;
8562 x_scroll_bar_set_handle (bar, start, end, 0);
8563 }
8564 }
8565}
8566
8567
8568/* The following three hooks are used when we're doing a thorough
8569 redisplay of the frame. We don't explicitly know which scroll bars
8570 are going to be deleted, because keeping track of when windows go
8571 away is a real pain - "Can you say set-window-configuration, boys
8572 and girls?" Instead, we just assert at the beginning of redisplay
8573 that *all* scroll bars are to be removed, and then save a scroll bar
8574 from the fiery pit when we actually redisplay its window. */
8575
8576/* Arrange for all scroll bars on FRAME to be removed at the next call
8577 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8578 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8579
8580static void
8581XTcondemn_scroll_bars (frame)
8582 FRAME_PTR frame;
8583{
8584 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8585 while (! NILP (FRAME_SCROLL_BARS (frame)))
8586 {
8587 Lisp_Object bar;
8588 bar = FRAME_SCROLL_BARS (frame);
8589 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8590 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8591 XSCROLL_BAR (bar)->prev = Qnil;
8592 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8593 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8594 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8595 }
8596}
8597
e0f712ba 8598
1a578e9b
AC
8599/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8600 Note that WINDOW isn't necessarily condemned at all. */
e0f712ba 8601
1a578e9b
AC
8602static void
8603XTredeem_scroll_bar (window)
8604 struct window *window;
8605{
8606 struct scroll_bar *bar;
8607
8608 /* We can't redeem this window's scroll bar if it doesn't have one. */
8609 if (NILP (window->vertical_scroll_bar))
8610 abort ();
8611
8612 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8613
8614 /* Unlink it from the condemned list. */
8615 {
8616 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8617
8618 if (NILP (bar->prev))
8619 {
8620 /* If the prev pointer is nil, it must be the first in one of
8621 the lists. */
8622 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8623 /* It's not condemned. Everything's fine. */
8624 return;
8625 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8626 window->vertical_scroll_bar))
8627 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8628 else
8629 /* If its prev pointer is nil, it must be at the front of
8630 one or the other! */
8631 abort ();
8632 }
8633 else
8634 XSCROLL_BAR (bar->prev)->next = bar->next;
8635
8636 if (! NILP (bar->next))
8637 XSCROLL_BAR (bar->next)->prev = bar->prev;
8638
8639 bar->next = FRAME_SCROLL_BARS (f);
8640 bar->prev = Qnil;
8641 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8642 if (! NILP (bar->next))
8643 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8644 }
8645}
8646
8647/* Remove all scroll bars on FRAME that haven't been saved since the
8648 last call to `*condemn_scroll_bars_hook'. */
8649
8650static void
8651XTjudge_scroll_bars (f)
8652 FRAME_PTR f;
8653{
8654 Lisp_Object bar, next;
8655
8656 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8657
8658 /* Clear out the condemned list now so we won't try to process any
8659 more events on the hapless scroll bars. */
8660 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8661
8662 for (; ! NILP (bar); bar = next)
8663 {
8664 struct scroll_bar *b = XSCROLL_BAR (bar);
8665
8666 x_scroll_bar_remove (b);
8667
8668 next = b->next;
8669 b->next = b->prev = Qnil;
8670 }
8671
8672 /* Now there should be no references to the condemned scroll bars,
8673 and they should get garbage-collected. */
8674}
8675
8676
8677static void
8678activate_scroll_bars (frame)
8679 FRAME_PTR frame;
8680{
8681 Lisp_Object bar;
8682 ControlHandle ch;
8683
8684 bar = FRAME_SCROLL_BARS (frame);
8685 while (! NILP (bar))
8686 {
8687 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
e0f712ba
AC
8688#ifdef TARGET_API_MAC_CARBON
8689 ActivateControl (ch);
8690#else
1a578e9b
AC
8691 SetControlMaximum (ch,
8692 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8693 XINT (XSCROLL_BAR (bar)
8694 ->height)) - 1);
e0f712ba 8695#endif
1a578e9b
AC
8696 bar = XSCROLL_BAR (bar)->next;
8697 }
8698}
8699
8700
8701static void
8702deactivate_scroll_bars (frame)
8703 FRAME_PTR frame;
8704{
8705 Lisp_Object bar;
8706 ControlHandle ch;
8707
8708 bar = FRAME_SCROLL_BARS (frame);
8709 while (! NILP (bar))
8710 {
8711 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
e0f712ba
AC
8712#ifdef TARGET_API_MAC_CARBON
8713 DeactivateControl (ch);
8714#else
1a578e9b 8715 SetControlMaximum (ch, XINT (-1));
e0f712ba 8716#endif
1a578e9b
AC
8717 bar = XSCROLL_BAR (bar)->next;
8718 }
8719}
8720
8721/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3b8f9651 8722 is set to something other than NO_EVENT, it is enqueued.
1a578e9b
AC
8723
8724 This may be called from a signal handler, so we have to ignore GC
8725 mark bits. */
8726
8727static void
8728x_scroll_bar_handle_click (bar, part_code, er, bufp)
8729 struct scroll_bar *bar;
8730 int part_code;
8731 EventRecord *er;
8732 struct input_event *bufp;
8733{
8734 if (! GC_WINDOWP (bar->window))
8735 abort ();
8736
3b8f9651 8737 bufp->kind = SCROLL_BAR_CLICK_EVENT;
1a578e9b
AC
8738 bufp->frame_or_window = bar->window;
8739 bufp->arg = Qnil;
8740
8741 bar->dragging = Qnil;
8742
8743 switch (part_code)
8744 {
8745 case kControlUpButtonPart:
8746 bufp->part = scroll_bar_up_arrow;
8747 break;
8748 case kControlDownButtonPart:
8749 bufp->part = scroll_bar_down_arrow;
8750 break;
8751 case kControlPageUpPart:
8752 bufp->part = scroll_bar_above_handle;
8753 break;
8754 case kControlPageDownPart:
8755 bufp->part = scroll_bar_below_handle;
8756 break;
e0f712ba
AC
8757#ifdef TARGET_API_MAC_CARBON
8758 default:
8759#else
1a578e9b 8760 case kControlIndicatorPart:
e0f712ba 8761#endif
1a578e9b
AC
8762 if (er->what == mouseDown)
8763 bar->dragging = make_number (0);
8764 XSETVECTOR (last_mouse_scroll_bar, bar);
8765 bufp->part = scroll_bar_handle;
8766 break;
8767 }
8768}
8769
8770
8771/* Handle some mouse motion while someone is dragging the scroll bar.
8772
8773 This may be called from a signal handler, so we have to ignore GC
8774 mark bits. */
8775
8776static void
8777x_scroll_bar_note_movement (bar, y_pos, t)
8778 struct scroll_bar *bar;
8779 int y_pos;
8780 Time t;
8781{
8782 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8783
8784 last_mouse_movement_time = t;
8785
8786 f->mouse_moved = 1;
8787 XSETVECTOR (last_mouse_scroll_bar, bar);
8788
8789 /* If we're dragging the bar, display it. */
8790 if (! GC_NILP (bar->dragging))
8791 {
8792 /* Where should the handle be now? */
8793 int new_start = y_pos - 24;
8794
8795 if (new_start != XINT (bar->start))
8796 {
8797 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8798
8799 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8800 }
8801 }
8802}
8803
8804
8805/* Return information to the user about the current position of the
8806 mouse on the scroll bar. */
8807
8808static void
8809x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8810 FRAME_PTR *fp;
8811 Lisp_Object *bar_window;
8812 enum scroll_bar_part *part;
8813 Lisp_Object *x, *y;
8814 unsigned long *time;
8815{
8816 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8817 WindowPtr wp = FrontWindow ();
8818 Point mouse_pos;
8819 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8820 int win_y, top_range;
8821
e0f712ba
AC
8822#if TARGET_API_MAC_CARBON
8823 SetPort (GetWindowPort (wp));
8824#else
1a578e9b 8825 SetPort (wp);
e0f712ba
AC
8826#endif
8827
1a578e9b
AC
8828 GetMouse (&mouse_pos);
8829
8830 win_y = mouse_pos.v - XINT (bar->top);
8831 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8832
8833 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8834
8835 win_y -= 24;
8836
8837 if (! NILP (bar->dragging))
8838 win_y -= XINT (bar->dragging);
8839
8840 if (win_y < 0)
8841 win_y = 0;
8842 if (win_y > top_range)
8843 win_y = top_range;
8844
8845 *fp = f;
8846 *bar_window = bar->window;
8847
8848 if (! NILP (bar->dragging))
8849 *part = scroll_bar_handle;
8850 else if (win_y < XINT (bar->start))
8851 *part = scroll_bar_above_handle;
8852 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8853 *part = scroll_bar_handle;
8854 else
8855 *part = scroll_bar_below_handle;
8856
8857 XSETINT (*x, win_y);
8858 XSETINT (*y, top_range);
8859
8860 f->mouse_moved = 0;
8861 last_mouse_scroll_bar = Qnil;
8862
8863 *time = last_mouse_movement_time;
8864}
8865\f
8866/***********************************************************************
8867 Text Cursor
8868 ***********************************************************************/
8869
e0f712ba
AC
8870/* Notice if the text cursor of window W has been overwritten by a
8871 drawing operation that outputs glyphs starting at START_X and
8872 ending at END_X in the line given by output_cursor.vpos.
8873 Coordinates are area-relative. END_X < 0 means all the rest
8874 of the line after START_X has been written. */
1a578e9b
AC
8875
8876static void
e0f712ba 8877notice_overwritten_cursor (w, area, x0, x1, y0, y1)
1a578e9b 8878 struct window *w;
e0f712ba
AC
8879 enum glyph_row_area area;
8880 int x0, x1, y0, y1;
8881{
8882 if (area == TEXT_AREA
8883 && w->phys_cursor_on_p
8884 && y0 <= w->phys_cursor.y
8885 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8886 && x0 <= w->phys_cursor.x
8887 && (x1 < 0 || x1 > w->phys_cursor.x))
1a578e9b
AC
8888 w->phys_cursor_on_p = 0;
8889}
8890
8891
8892/* Set clipping for output in glyph row ROW. W is the window in which
8893 we operate. GC is the graphics context to set clipping in.
8894 WHOLE_LINE_P non-zero means include the areas used for truncation
8895 mark display and alike in the clipping rectangle.
8896
8897 ROW may be a text row or, e.g., a mode line. Text rows must be
8898 clipped to the interior of the window dedicated to text display,
8899 mode lines must be clipped to the whole window. */
8900
8901static void
8902x_clip_to_row (w, row, gc, whole_line_p)
8903 struct window *w;
8904 struct glyph_row *row;
8905 GC gc;
8906 int whole_line_p;
8907{
8908 struct frame *f = XFRAME (WINDOW_FRAME (w));
8909 Rect clip_rect;
8910 int window_x, window_y, window_width, window_height;
8911
8912 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8913
8914 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8915 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8916 clip_rect.top = max (clip_rect.top, window_y);
8917 clip_rect.right = clip_rect.left + window_width;
8918 clip_rect.bottom = clip_rect.top + row->visible_height;
8919
8920 /* If clipping to the whole line, including trunc marks, extend
8921 the rectangle to the left and increase its width. */
8922 if (whole_line_p)
8923 {
3f332ef3
KS
8924 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8925 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
1a578e9b
AC
8926 }
8927
8928 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8929}
8930
8931
8932/* Draw a hollow box cursor on window W in glyph row ROW. */
8933
8934static void
8935x_draw_hollow_cursor (w, row)
8936 struct window *w;
8937 struct glyph_row *row;
8938{
8939 struct frame *f = XFRAME (WINDOW_FRAME (w));
8940 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8941 Display *dpy = FRAME_MAC_DISPLAY (f);
8942 int x, y, wd, h;
8943 XGCValues xgcv;
8944 struct glyph *cursor_glyph;
8945 GC gc;
8946
8947 /* Compute frame-relative coordinates from window-relative
8948 coordinates. */
8949 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8950 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8951 + row->ascent - w->phys_cursor_ascent);
8952 h = row->height - 1;
8953
8954 /* Get the glyph the cursor is on. If we can't tell because
8955 the current matrix is invalid or such, give up. */
8956 cursor_glyph = get_phys_cursor_glyph (w);
8957 if (cursor_glyph == NULL)
8958 return;
8959
8960 /* Compute the width of the rectangle to draw. If on a stretch
8961 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8962 rectangle as wide as the glyph, but use a canonical character
8963 width instead. */
8964 wd = cursor_glyph->pixel_width - 1;
8965 if (cursor_glyph->type == STRETCH_GLYPH
8966 && !x_stretch_cursor_p)
8967 wd = min (CANON_X_UNIT (f), wd);
8968
8969 /* The foreground of cursor_gc is typically the same as the normal
8970 background color, which can cause the cursor box to be invisible. */
8971 xgcv.foreground = f->output_data.mac->cursor_pixel;
8972 if (dpyinfo->scratch_cursor_gc)
8973 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8974 else
8975 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8976 GCForeground, &xgcv);
8977 gc = dpyinfo->scratch_cursor_gc;
8978
8979 /* Set clipping, draw the rectangle, and reset clipping again. */
8980 x_clip_to_row (w, row, gc, 0);
8981 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
8982 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8983}
8984
8985
8986/* Draw a bar cursor on window W in glyph row ROW.
8987
8988 Implementation note: One would like to draw a bar cursor with an
8989 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8990 Unfortunately, I didn't find a font yet that has this property set.
8991 --gerd. */
8992
8993static void
8994x_draw_bar_cursor (w, row, width)
8995 struct window *w;
8996 struct glyph_row *row;
8997 int width;
8998{
8999 /* If cursor hpos is out of bounds, don't draw garbage. This can
9000 happen in mini-buffer windows when switching between echo area
9001 glyphs and mini-buffer. */
9002 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9003 {
9004 struct frame *f = XFRAME (w->frame);
9005 struct glyph *cursor_glyph;
9006 GC gc;
9007 int x;
9008 unsigned long mask;
9009 XGCValues xgcv;
9010 Display *dpy;
9011 Window window;
9012
9013 cursor_glyph = get_phys_cursor_glyph (w);
9014 if (cursor_glyph == NULL)
9015 return;
9016
9017 xgcv.background = f->output_data.mac->cursor_pixel;
9018 xgcv.foreground = f->output_data.mac->cursor_pixel;
9019 mask = GCForeground | GCBackground;
9020 dpy = FRAME_MAC_DISPLAY (f);
9021 window = FRAME_MAC_WINDOW (f);
9022 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9023
9024 if (gc)
9025 XChangeGC (dpy, gc, mask, &xgcv);
9026 else
9027 {
9028 gc = XCreateGC (dpy, window, mask, &xgcv);
9029 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9030 }
9031
9032 if (width < 0)
9033 width = f->output_data.mac->cursor_width;
9034
9035 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9036 x_clip_to_row (w, row, gc, 0);
9037 XFillRectangle (dpy, window, gc,
9038 x,
9039 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9040 min (cursor_glyph->pixel_width, width),
9041 row->height);
9042 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9043 }
9044}
9045
9046
9047/* Clear the cursor of window W to background color, and mark the
9048 cursor as not shown. This is used when the text where the cursor
9049 is is about to be rewritten. */
9050
9051static void
9052x_clear_cursor (w)
9053 struct window *w;
9054{
9055 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9056 x_update_window_cursor (w, 0);
9057}
9058
9059
9060/* Draw the cursor glyph of window W in glyph row ROW. See the
9061 comment of x_draw_glyphs for the meaning of HL. */
9062
9063static void
9064x_draw_phys_cursor_glyph (w, row, hl)
9065 struct window *w;
9066 struct glyph_row *row;
9067 enum draw_glyphs_face hl;
9068{
9069 /* If cursor hpos is out of bounds, don't draw garbage. This can
9070 happen in mini-buffer windows when switching between echo area
9071 glyphs and mini-buffer. */
9072 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9073 {
e0f712ba 9074 int on_p = w->phys_cursor_on_p;
1a578e9b 9075 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
e0f712ba
AC
9076 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9077 hl, 0);
9078 w->phys_cursor_on_p = on_p;
1a578e9b
AC
9079
9080 /* When we erase the cursor, and ROW is overlapped by other
9081 rows, make sure that these overlapping parts of other rows
9082 are redrawn. */
9083 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9084 {
9085 if (row > w->current_matrix->rows
9086 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9087 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9088
9089 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9090 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9091 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9092 }
9093 }
9094}
9095
9096
9097/* Erase the image of a cursor of window W from the screen. */
9098
9099static void
9100x_erase_phys_cursor (w)
9101 struct window *w;
9102{
9103 struct frame *f = XFRAME (w->frame);
9104 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9105 int hpos = w->phys_cursor.hpos;
9106 int vpos = w->phys_cursor.vpos;
9107 int mouse_face_here_p = 0;
9108 struct glyph_matrix *active_glyphs = w->current_matrix;
9109 struct glyph_row *cursor_row;
9110 struct glyph *cursor_glyph;
9111 enum draw_glyphs_face hl;
9112
9113 /* No cursor displayed or row invalidated => nothing to do on the
9114 screen. */
9115 if (w->phys_cursor_type == NO_CURSOR)
9116 goto mark_cursor_off;
9117
9118 /* VPOS >= active_glyphs->nrows means that window has been resized.
9119 Don't bother to erase the cursor. */
9120 if (vpos >= active_glyphs->nrows)
9121 goto mark_cursor_off;
9122
9123 /* If row containing cursor is marked invalid, there is nothing we
9124 can do. */
9125 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9126 if (!cursor_row->enabled_p)
9127 goto mark_cursor_off;
9128
796d4ec7 9129 /* If row is completely invisible, don't attempt to delete a cursor which
e0f712ba 9130 isn't there. This may happen if cursor is at top of window, and
796d4ec7
KS
9131 we switch to a buffer with a header line in that window. */
9132 if (cursor_row->visible_height <= 0)
9133 goto mark_cursor_off;
9134
1a578e9b
AC
9135 /* This can happen when the new row is shorter than the old one.
9136 In this case, either x_draw_glyphs or clear_end_of_line
9137 should have cleared the cursor. Note that we wouldn't be
9138 able to erase the cursor in this case because we don't have a
9139 cursor glyph at hand. */
9140 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9141 goto mark_cursor_off;
9142
9143 /* If the cursor is in the mouse face area, redisplay that when
9144 we clear the cursor. */
9145 if (! NILP (dpyinfo->mouse_face_window)
9146 && w == XWINDOW (dpyinfo->mouse_face_window)
9147 && (vpos > dpyinfo->mouse_face_beg_row
9148 || (vpos == dpyinfo->mouse_face_beg_row
9149 && hpos >= dpyinfo->mouse_face_beg_col))
9150 && (vpos < dpyinfo->mouse_face_end_row
9151 || (vpos == dpyinfo->mouse_face_end_row
9152 && hpos < dpyinfo->mouse_face_end_col))
9153 /* Don't redraw the cursor's spot in mouse face if it is at the
9154 end of a line (on a newline). The cursor appears there, but
9155 mouse highlighting does not. */
9156 && cursor_row->used[TEXT_AREA] > hpos)
9157 mouse_face_here_p = 1;
9158
9159 /* Maybe clear the display under the cursor. */
9160 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9161 {
9162 int x;
9163 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9164
9165 cursor_glyph = get_phys_cursor_glyph (w);
9166 if (cursor_glyph == NULL)
9167 goto mark_cursor_off;
9168
9169 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9170
9171 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9172 x,
9173 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9174 cursor_row->y)),
9175 cursor_glyph->pixel_width,
9176 cursor_row->visible_height,
9177 0);
9178 }
9179
9180 /* Erase the cursor by redrawing the character underneath it. */
9181 if (mouse_face_here_p)
9182 hl = DRAW_MOUSE_FACE;
1a578e9b
AC
9183 else
9184 hl = DRAW_NORMAL_TEXT;
9185 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9186
9187 mark_cursor_off:
9188 w->phys_cursor_on_p = 0;
9189 w->phys_cursor_type = NO_CURSOR;
9190}
9191
9192
e0f712ba
AC
9193/* Non-zero if physical cursor of window W is within mouse face. */
9194
9195static int
9196cursor_in_mouse_face_p (w)
9197 struct window *w;
9198{
9199 struct mac_display_info *dpyinfo
9200 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9201 int in_mouse_face = 0;
9202
9203 if (WINDOWP (dpyinfo->mouse_face_window)
9204 && XWINDOW (dpyinfo->mouse_face_window) == w)
9205 {
9206 int hpos = w->phys_cursor.hpos;
9207 int vpos = w->phys_cursor.vpos;
9208
9209 if (vpos >= dpyinfo->mouse_face_beg_row
9210 && vpos <= dpyinfo->mouse_face_end_row
9211 && (vpos > dpyinfo->mouse_face_beg_row
9212 || hpos >= dpyinfo->mouse_face_beg_col)
9213 && (vpos < dpyinfo->mouse_face_end_row
9214 || hpos < dpyinfo->mouse_face_end_col
9215 || dpyinfo->mouse_face_past_end))
9216 in_mouse_face = 1;
9217 }
9218
9219 return in_mouse_face;
9220}
9221
9222
1a578e9b
AC
9223/* Display or clear cursor of window W. If ON is zero, clear the
9224 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9225 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9226
9227void
9228x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9229 struct window *w;
9230 int on, hpos, vpos, x, y;
9231{
9232 struct frame *f = XFRAME (w->frame);
9233 int new_cursor_type;
9234 int new_cursor_width;
9235 struct glyph_matrix *current_glyphs;
9236 struct glyph_row *glyph_row;
9237 struct glyph *glyph;
e0f712ba
AC
9238 int cursor_non_selected;
9239 int active_cursor = 1;
1a578e9b
AC
9240
9241 /* This is pointless on invisible frames, and dangerous on garbaged
9242 windows and frames; in the latter case, the frame or window may
9243 be in the midst of changing its size, and x and y may be off the
9244 window. */
9245 if (! FRAME_VISIBLE_P (f)
9246 || FRAME_GARBAGED_P (f)
9247 || vpos >= w->current_matrix->nrows
9248 || hpos >= w->current_matrix->matrix_w)
9249 return;
9250
9251 /* If cursor is off and we want it off, return quickly. */
9252 if (!on && !w->phys_cursor_on_p)
9253 return;
9254
9255 current_glyphs = w->current_matrix;
9256 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9257 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9258
9259 /* If cursor row is not enabled, we don't really know where to
9260 display the cursor. */
9261 if (!glyph_row->enabled_p)
9262 {
9263 w->phys_cursor_on_p = 0;
9264 return;
9265 }
9266
9267 xassert (interrupt_input_blocked);
9268
9269 /* Set new_cursor_type to the cursor we want to be displayed. In a
9270 mini-buffer window, we want the cursor only to appear if we are
9271 reading input from this window. For the selected window, we want
9272 the cursor type given by the frame parameter. If explicitly
9273 marked off, draw no cursor. In all other cases, we want a hollow
9274 box cursor. */
e0f712ba
AC
9275 cursor_non_selected
9276 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
9277 w->buffer));
1a578e9b
AC
9278 new_cursor_width = -1;
9279 if (cursor_in_echo_area
9280 && FRAME_HAS_MINIBUF_P (f)
9281 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
9282 {
9283 if (w == XWINDOW (echo_area_window))
9284 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9285 else
1a578e9b 9286 {
e0f712ba 9287 if (cursor_non_selected)
1a578e9b 9288 new_cursor_type = HOLLOW_BOX_CURSOR;
e0f712ba
AC
9289 else
9290 new_cursor_type = NO_CURSOR;
9291 active_cursor = 0;
1a578e9b 9292 }
e0f712ba
AC
9293 }
9294 else
9295 {
9296 if (f != FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame
9297 || w != XWINDOW (f->selected_window))
9298 {
9299 active_cursor = 0;
9300
9301 if (MINI_WINDOW_P (w)
9302 || !cursor_non_selected
9303 || NILP (XBUFFER (w->buffer)->cursor_type))
9304 new_cursor_type = NO_CURSOR;
9305 else
9306 new_cursor_type = HOLLOW_BOX_CURSOR;
9307 }
1a578e9b 9308 else
e0f712ba 9309 {
1a578e9b
AC
9310 struct buffer *b = XBUFFER (w->buffer);
9311
9312 if (EQ (b->cursor_type, Qt))
e0f712ba 9313 new_cursor_type = FRAME_DESIRED_CURSOR (f);
1a578e9b
AC
9314 else
9315 new_cursor_type = x_specified_cursor_type (b->cursor_type,
9316 &new_cursor_width);
e0f712ba
AC
9317 if (w->cursor_off_p)
9318 {
9319 if (new_cursor_type == FILLED_BOX_CURSOR)
9320 new_cursor_type = HOLLOW_BOX_CURSOR;
9321 else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
9322 new_cursor_width = 1;
9323 else
9324 new_cursor_type = NO_CURSOR;
9325 }
1a578e9b
AC
9326 }
9327 }
9328
9329 /* If cursor is currently being shown and we don't want it to be or
9330 it is in the wrong place, or the cursor type is not what we want,
9331 erase it. */
9332 if (w->phys_cursor_on_p
9333 && (!on
9334 || w->phys_cursor.x != x
9335 || w->phys_cursor.y != y
e0f712ba
AC
9336 || new_cursor_type != w->phys_cursor_type
9337 || (new_cursor_type == BAR_CURSOR
9338 && new_cursor_width != w->phys_cursor_width)))
1a578e9b
AC
9339 x_erase_phys_cursor (w);
9340
9341 /* If the cursor is now invisible and we want it to be visible,
9342 display it. */
9343 if (on && !w->phys_cursor_on_p)
9344 {
9345 w->phys_cursor_ascent = glyph_row->ascent;
9346 w->phys_cursor_height = glyph_row->height;
9347
9348 /* Set phys_cursor_.* before x_draw_.* is called because some
9349 of them may need the information. */
9350 w->phys_cursor.x = x;
9351 w->phys_cursor.y = glyph_row->y;
9352 w->phys_cursor.hpos = hpos;
9353 w->phys_cursor.vpos = vpos;
9354 w->phys_cursor_type = new_cursor_type;
e0f712ba 9355 w->phys_cursor_width = new_cursor_width;
1a578e9b
AC
9356 w->phys_cursor_on_p = 1;
9357
9358 switch (new_cursor_type)
9359 {
9360 case HOLLOW_BOX_CURSOR:
9361 x_draw_hollow_cursor (w, glyph_row);
9362 break;
9363
9364 case FILLED_BOX_CURSOR:
9365 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9366 break;
9367
9368 case BAR_CURSOR:
9369 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9370 break;
9371
9372 case NO_CURSOR:
9373 break;
9374
9375 default:
9376 abort ();
9377 }
1a578e9b 9378 }
1a578e9b
AC
9379}
9380
9381
9382/* Display the cursor on window W, or clear it. X and Y are window
9383 relative pixel coordinates. HPOS and VPOS are glyph matrix
9384 positions. If W is not the selected window, display a hollow
9385 cursor. ON non-zero means display the cursor at X, Y which
9386 correspond to HPOS, VPOS, otherwise it is cleared. */
9387
9388void
9389x_display_cursor (w, on, hpos, vpos, x, y)
9390 struct window *w;
9391 int on, hpos, vpos, x, y;
9392{
9393 BLOCK_INPUT;
9394 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9395 UNBLOCK_INPUT;
9396}
9397
9398
9399/* Display the cursor on window W, or clear it, according to ON_P.
9400 Don't change the cursor's position. */
9401
9402void
9403x_update_cursor (f, on_p)
9404 struct frame *f;
e0f712ba 9405 int on_p;
1a578e9b
AC
9406{
9407 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9408}
9409
9410
9411/* Call x_update_window_cursor with parameter ON_P on all leaf windows
9412 in the window tree rooted at W. */
9413
9414static void
9415x_update_cursor_in_window_tree (w, on_p)
9416 struct window *w;
9417 int on_p;
9418{
9419 while (w)
9420 {
9421 if (!NILP (w->hchild))
9422 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9423 else if (!NILP (w->vchild))
9424 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9425 else
9426 x_update_window_cursor (w, on_p);
9427
9428 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9429 }
9430}
9431
9432
9433/* Switch the display of W's cursor on or off, according to the value
9434 of ON. */
9435
9436static void
9437x_update_window_cursor (w, on)
9438 struct window *w;
9439 int on;
9440{
9441 /* Don't update cursor in windows whose frame is in the process
9442 of being deleted. */
9443 if (w->current_matrix)
9444 {
9445 BLOCK_INPUT;
e0f712ba
AC
9446 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9447 w->phys_cursor.vpos, w->phys_cursor.x,
9448 w->phys_cursor.y);
1a578e9b
AC
9449 UNBLOCK_INPUT;
9450 }
9451}
9452
1a578e9b 9453
1a578e9b 9454
e0f712ba
AC
9455\f
9456/* Icons. */
1a578e9b 9457
e0f712ba 9458#if 0 /* MAC_TODO: no icon support yet. */
1a578e9b 9459int
e0f712ba 9460x_bitmap_icon (f, icon)
1a578e9b 9461 struct frame *f;
e0f712ba 9462 Lisp_Object icon;
1a578e9b 9463{
e0f712ba 9464 HANDLE hicon;
1a578e9b 9465
e0f712ba 9466 if (FRAME_W32_WINDOW (f) == 0)
1a578e9b
AC
9467 return 1;
9468
e0f712ba
AC
9469 if (NILP (icon))
9470 hicon = LoadIcon (hinst, EMACS_CLASS);
9471 else if (STRINGP (icon))
d5db4077 9472 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
e0f712ba
AC
9473 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9474 else if (SYMBOLP (icon))
9475 {
9476 LPCTSTR name;
9477
9478 if (EQ (icon, intern ("application")))
9479 name = (LPCTSTR) IDI_APPLICATION;
9480 else if (EQ (icon, intern ("hand")))
9481 name = (LPCTSTR) IDI_HAND;
9482 else if (EQ (icon, intern ("question")))
9483 name = (LPCTSTR) IDI_QUESTION;
9484 else if (EQ (icon, intern ("exclamation")))
9485 name = (LPCTSTR) IDI_EXCLAMATION;
9486 else if (EQ (icon, intern ("asterisk")))
9487 name = (LPCTSTR) IDI_ASTERISK;
9488 else if (EQ (icon, intern ("winlogo")))
9489 name = (LPCTSTR) IDI_WINLOGO;
9490 else
9491 return 1;
1a578e9b 9492
e0f712ba 9493 hicon = LoadIcon (NULL, name);
1a578e9b 9494 }
e0f712ba 9495 else
1a578e9b
AC
9496 return 1;
9497
e0f712ba
AC
9498 if (hicon == NULL)
9499 return 1;
1a578e9b 9500
e0f712ba
AC
9501 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9502 (LPARAM) hicon);
1a578e9b
AC
9503
9504 return 0;
9505}
e0f712ba 9506#endif /* MAC_TODO */
1a578e9b 9507\f
e0f712ba
AC
9508/************************************************************************
9509 Handling X errors
9510 ************************************************************************/
1a578e9b 9511
e0f712ba
AC
9512/* Display Error Handling functions not used on W32. Listing them here
9513 helps diff stay in step when comparing w32term.c with xterm.c.
1a578e9b 9514
1a578e9b 9515x_error_catcher (display, error)
1a578e9b 9516x_catch_errors (dpy)
1a578e9b 9517x_catch_errors_unwind (old_val)
1a578e9b 9518x_check_errors (dpy, format)
1a578e9b 9519x_had_errors_p (dpy)
1a578e9b 9520x_clear_errors (dpy)
1a578e9b 9521x_uncatch_errors (dpy, count)
1a578e9b 9522x_trace_wire ()
e0f712ba
AC
9523x_connection_signal (signalnum)
9524x_connection_closed (dpy, error_message)
1a578e9b 9525x_error_quitter (display, error)
1a578e9b 9526x_error_handler (display, error)
1a578e9b 9527x_io_error_quitter (display)
1a578e9b 9528
e0f712ba
AC
9529 */
9530
1a578e9b
AC
9531\f
9532/* Changing the font of the frame. */
9533
9534/* Give frame F the font named FONTNAME as its default font, and
9535 return the full name of that font. FONTNAME may be a wildcard
9536 pattern; in that case, we choose some font that fits the pattern.
9537 The return value shows which font we chose. */
9538
9539Lisp_Object
9540x_new_font (f, fontname)
9541 struct frame *f;
9542 register char *fontname;
9543{
9544 struct font_info *fontp
9545 = FS_LOAD_FONT (f, 0, fontname, -1);
9546
9547 if (!fontp)
9548 return Qnil;
9549
e0f712ba
AC
9550 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9551 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9552 FRAME_FONTSET (f) = -1;
9553
1a578e9b
AC
9554 /* Compute the scroll bar width in character columns. */
9555 if (f->scroll_bar_pixel_width > 0)
9556 {
e0f712ba 9557 int wid = FONT_WIDTH (FRAME_FONT (f));
1a578e9b
AC
9558 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9559 }
9560 else
9561 {
e0f712ba 9562 int wid = FONT_WIDTH (FRAME_FONT (f));
1a578e9b
AC
9563 f->scroll_bar_cols = (14 + wid - 1) / wid;
9564 }
9565
9566 /* Now make the frame display the given font. */
9567 if (FRAME_MAC_WINDOW (f) != 0)
9568 {
f00691a3
AC
9569 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9570 f->output_data.mac->font);
9571 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9572 f->output_data.mac->font);
9573 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9574 f->output_data.mac->font);
9575
1a578e9b 9576 frame_update_line_height (f);
e0f712ba
AC
9577 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9578 x_set_window_size (f, 0, f->width, f->height);
1a578e9b
AC
9579 }
9580 else
e0f712ba
AC
9581 /* If we are setting a new frame's font for the first time,
9582 there are no faces yet, so this font's height is the line height. */
9583 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
1a578e9b
AC
9584
9585 return build_string (fontp->full_name);
9586}
e0f712ba 9587\f
1a578e9b 9588/* Give frame F the fontset named FONTSETNAME as its default font, and
e0f712ba
AC
9589 return the full name of that fontset. FONTSETNAME may be a wildcard
9590 pattern; in that case, we choose some fontset that fits the pattern.
9591 The return value shows which fontset we chose. */
1a578e9b
AC
9592
9593Lisp_Object
9594x_new_fontset (f, fontsetname)
9595 struct frame *f;
9596 char *fontsetname;
9597{
9598 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9599 Lisp_Object result;
9600
9601 if (fontset < 0)
9602 return Qnil;
9603
e0f712ba 9604 if (FRAME_FONTSET (f) == fontset)
1a578e9b
AC
9605 /* This fontset is already set in frame F. There's nothing more
9606 to do. */
9607 return fontset_name (fontset);
9608
d5db4077 9609 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
1a578e9b
AC
9610
9611 if (!STRINGP (result))
9612 /* Can't load ASCII font. */
9613 return Qnil;
9614
e0f712ba
AC
9615 /* Since x_new_font doesn't update any fontset information, do it now. */
9616 FRAME_FONTSET(f) = fontset;
1a578e9b 9617
1a578e9b
AC
9618 return build_string (fontsetname);
9619}
9620
d33c49e8
KS
9621/* Compute actual fringe widths */
9622
9623void
9624x_compute_fringe_widths (f, redraw)
9625 struct frame *f;
9626 int redraw;
9627{
9628 int o_left = f->output_data.mac->left_fringe_width;
9629 int o_right = f->output_data.mac->right_fringe_width;
9630 int o_cols = f->output_data.mac->fringe_cols;
9631
9632 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9633 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9634 int left_fringe_width, right_fringe_width;
9635
9636 if (!NILP (left_fringe))
9637 left_fringe = Fcdr (left_fringe);
9638 if (!NILP (right_fringe))
9639 right_fringe = Fcdr (right_fringe);
9640
9641 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9642 XINT (left_fringe));
9643 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9644 XINT (right_fringe));
9645
9646 if (left_fringe_width || right_fringe_width)
9647 {
9648 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9649 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9650 int conf_wid = left_wid + right_wid;
9651 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9652 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9653 int real_wid = cols * font_wid;
9654 if (left_wid && right_wid)
9655 {
9656 if (left_fringe_width < 0)
9657 {
9658 /* Left fringe width is fixed, adjust right fringe if necessary */
9659 f->output_data.mac->left_fringe_width = left_wid;
9660 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9661 }
9662 else if (right_fringe_width < 0)
9663 {
9664 /* Right fringe width is fixed, adjust left fringe if necessary */
9665 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9666 f->output_data.mac->right_fringe_width = right_wid;
9667 }
9668 else
9669 {
9670 /* Adjust both fringes with an equal amount.
9671 Note that we are doing integer arithmetic here, so don't
9672 lose a pixel if the total width is an odd number. */
9673 int fill = real_wid - conf_wid;
9674 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9675 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9676 }
9677 }
9678 else if (left_fringe_width)
9679 {
9680 f->output_data.mac->left_fringe_width = real_wid;
9681 f->output_data.mac->right_fringe_width = 0;
9682 }
9683 else
9684 {
9685 f->output_data.mac->left_fringe_width = 0;
9686 f->output_data.mac->right_fringe_width = real_wid;
9687 }
9688 f->output_data.mac->fringe_cols = cols;
9689 f->output_data.mac->fringes_extra = real_wid;
9690 }
9691 else
9692 {
9693 f->output_data.mac->left_fringe_width = 0;
9694 f->output_data.mac->right_fringe_width = 0;
9695 f->output_data.mac->fringe_cols = 0;
9696 f->output_data.mac->fringes_extra = 0;
9697 }
9698
9699 if (redraw && FRAME_VISIBLE_P (f))
9700 if (o_left != f->output_data.mac->left_fringe_width ||
9701 o_right != f->output_data.mac->right_fringe_width ||
9702 o_cols != f->output_data.mac->fringe_cols)
9703 redraw_frame (f);
9704}
1a578e9b
AC
9705\f
9706/***********************************************************************
e0f712ba 9707 TODO: W32 Input Methods
1a578e9b 9708 ***********************************************************************/
e0f712ba 9709/* Listing missing functions from xterm.c helps diff stay in step.
1a578e9b 9710
1a578e9b 9711xim_destroy_callback (xim, client_data, call_data)
1a578e9b 9712xim_open_dpy (dpyinfo, resource_name)
1a578e9b 9713struct xim_inst_t
1a578e9b 9714xim_instantiate_callback (display, client_data, call_data)
1a578e9b 9715xim_initialize (dpyinfo, resource_name)
1a578e9b 9716xim_close_dpy (dpyinfo)
1a578e9b 9717
e0f712ba 9718 */
1a578e9b 9719
1a578e9b
AC
9720\f
9721/* Calculate the absolute position in frame F
9722 from its current recorded position values and gravity. */
9723
e0f712ba 9724void
1a578e9b
AC
9725x_calc_absolute_position (f)
9726 struct frame *f;
9727{
9728 Point pt;
9729 int flags = f->output_data.mac->size_hint_flags;
9730
9731 pt.h = pt.v = 0;
9732
9733 /* Find the position of the outside upper-left corner of
9734 the inner window, with respect to the outer window. */
9735 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9736 {
9737 GrafPtr savePort;
9738 GetPort (&savePort);
e0f712ba
AC
9739
9740#if TARGET_API_MAC_CARBON
9741 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9742#else
1a578e9b 9743 SetPort (FRAME_MAC_WINDOW (f));
e0f712ba
AC
9744#endif
9745
9746#if TARGET_API_MAC_CARBON
9747 {
9748 Rect r;
9749
9750 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9751 SetPt(&pt, r.left, r.top);
9752 }
9753#else /* not TARGET_API_MAC_CARBON */
1a578e9b 9754 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
e0f712ba 9755#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
9756 LocalToGlobal (&pt);
9757 SetPort (savePort);
9758 }
9759
9760 /* Treat negative positions as relative to the leftmost bottommost
9761 position that fits on the screen. */
9762 if (flags & XNegative)
9763 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9764 - 2 * f->output_data.mac->border_width - pt.h
9765 - PIXEL_WIDTH (f)
9766 + f->output_data.mac->left_pos);
9767 /* NTEMACS_TODO: Subtract menubar height? */
9768 if (flags & YNegative)
9769 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9770 - 2 * f->output_data.mac->border_width - pt.v
9771 - PIXEL_HEIGHT (f)
9772 + f->output_data.mac->top_pos);
9773 /* The left_pos and top_pos
9774 are now relative to the top and left screen edges,
9775 so the flags should correspond. */
9776 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9777}
9778
9779/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9780 to really change the position, and 0 when calling from
9781 x_make_frame_visible (in that case, XOFF and YOFF are the current
9782 position values). It is -1 when calling from x_set_frame_parameters,
9783 which means, do adjust for borders but don't change the gravity. */
9784
9785void
9786x_set_offset (f, xoff, yoff, change_gravity)
9787 struct frame *f;
9788 register int xoff, yoff;
9789 int change_gravity;
9790{
e0f712ba
AC
9791 int modified_top, modified_left;
9792
1a578e9b
AC
9793 if (change_gravity > 0)
9794 {
9795 f->output_data.mac->top_pos = yoff;
9796 f->output_data.mac->left_pos = xoff;
9797 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9798 if (xoff < 0)
9799 f->output_data.mac->size_hint_flags |= XNegative;
9800 if (yoff < 0)
9801 f->output_data.mac->size_hint_flags |= YNegative;
9802 f->output_data.mac->win_gravity = NorthWestGravity;
9803 }
9804 x_calc_absolute_position (f);
9805
9806 BLOCK_INPUT;
9807 x_wm_set_size_hint (f, (long) 0, 0);
9808
e0f712ba
AC
9809 modified_left = f->output_data.mac->left_pos;
9810 modified_top = f->output_data.mac->top_pos;
9811
9812 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9813 modified_top + 42, false);
1a578e9b
AC
9814
9815 UNBLOCK_INPUT;
9816}
9817
9818/* Call this to change the size of frame F's x-window.
9819 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9820 for this size change and subsequent size changes.
9821 Otherwise we leave the window gravity unchanged. */
9822
9823void
9824x_set_window_size (f, change_gravity, cols, rows)
9825 struct frame *f;
9826 int change_gravity;
9827 int cols, rows;
9828{
9829 int pixelwidth, pixelheight;
e0f712ba
AC
9830
9831 BLOCK_INPUT;
9832
1a578e9b
AC
9833 check_frame_size (f, &rows, &cols);
9834 f->output_data.mac->vertical_scroll_bar_extra
9835 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9836 ? 0
1a578e9b 9837 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
d33c49e8
KS
9838
9839 x_compute_fringe_widths (f, 0);
9840
1a578e9b
AC
9841 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9842 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9843
9844 f->output_data.mac->win_gravity = NorthWestGravity;
9845 x_wm_set_size_hint (f, (long) 0, 0);
9846
9847 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9848
9849 /* Now, strictly speaking, we can't be sure that this is accurate,
9850 but the window manager will get around to dealing with the size
9851 change request eventually, and we'll hear how it went when the
9852 ConfigureNotify event gets here.
e0f712ba 9853
1a578e9b
AC
9854 We could just not bother storing any of this information here,
9855 and let the ConfigureNotify event set everything up, but that
9856 might be kind of confusing to the Lisp code, since size changes
9857 wouldn't be reported in the frame parameters until some random
9858 point in the future when the ConfigureNotify event arrives.
9859
9860 We pass 1 for DELAY since we can't run Lisp code inside of
9861 a BLOCK_INPUT. */
9862 change_frame_size (f, rows, cols, 0, 1, 0);
9863 PIXEL_WIDTH (f) = pixelwidth;
9864 PIXEL_HEIGHT (f) = pixelheight;
9865
9866 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9867 receive in the ConfigureNotify event; if we get what we asked
9868 for, then the event won't cause the screen to become garbaged, so
9869 we have to make sure to do it here. */
9870 SET_FRAME_GARBAGED (f);
9871
9872 XFlush (FRAME_X_DISPLAY (f));
9873
9874 /* If cursor was outside the new size, mark it as off. */
9875 mark_window_cursors_off (XWINDOW (f->root_window));
9876
9877 /* Clear out any recollection of where the mouse highlighting was,
9878 since it might be in a place that's outside the new frame size.
9879 Actually checking whether it is outside is a pain in the neck,
9880 so don't try--just let the highlighting be done afresh with new size. */
9881 cancel_mouse_face (f);
e0f712ba
AC
9882
9883 UNBLOCK_INPUT;
1a578e9b
AC
9884}
9885\f
9886/* Mouse warping. */
9887
9888void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9889
9890void
9891x_set_mouse_position (f, x, y)
9892 struct frame *f;
9893 int x, y;
9894{
9895 int pix_x, pix_y;
9896
9897 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9898 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9899
9900 if (pix_x < 0) pix_x = 0;
9901 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9902
9903 if (pix_y < 0) pix_y = 0;
9904 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9905
9906 x_set_mouse_pixel_position (f, pix_x, pix_y);
9907}
9908
1a578e9b
AC
9909void
9910x_set_mouse_pixel_position (f, pix_x, pix_y)
9911 struct frame *f;
9912 int pix_x, pix_y;
9913{
9914#if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9915 BLOCK_INPUT;
9916
9917 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9918 0, 0, 0, 0, pix_x, pix_y);
9919 UNBLOCK_INPUT;
9920#endif
9921}
e0f712ba 9922
1a578e9b
AC
9923\f
9924/* focus shifting, raising and lowering. */
9925
e0f712ba 9926void
1a578e9b
AC
9927x_focus_on_frame (f)
9928 struct frame *f;
9929{
9930#if 0 /* This proves to be unpleasant. */
9931 x_raise_frame (f);
9932#endif
9933#if 0
9934 /* I don't think that the ICCCM allows programs to do things like this
9935 without the interaction of the window manager. Whatever you end up
9936 doing with this code, do it to x_unfocus_frame too. */
9937 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9938 RevertToPointerRoot, CurrentTime);
9939#endif /* ! 0 */
9940}
9941
e0f712ba 9942void
1a578e9b
AC
9943x_unfocus_frame (f)
9944 struct frame *f;
9945{
1a578e9b
AC
9946}
9947
9948/* Raise frame F. */
1a578e9b
AC
9949void
9950x_raise_frame (f)
9951 struct frame *f;
9952{
9953 if (f->async_visible)
9954 SelectWindow (FRAME_MAC_WINDOW (f));
9955}
9956
9957/* Lower frame F. */
1a578e9b
AC
9958void
9959x_lower_frame (f)
9960 struct frame *f;
9961{
9962 if (f->async_visible)
9963 SendBehind (FRAME_MAC_WINDOW (f), nil);
9964}
9965
e0f712ba 9966static void
1a578e9b
AC
9967XTframe_raise_lower (f, raise_flag)
9968 FRAME_PTR f;
9969 int raise_flag;
9970{
9971 if (raise_flag)
9972 x_raise_frame (f);
9973 else
9974 x_lower_frame (f);
9975}
9976\f
9977/* Change of visibility. */
9978
9979/* This tries to wait until the frame is really visible.
9980 However, if the window manager asks the user where to position
9981 the frame, this will return before the user finishes doing that.
9982 The frame will not actually be visible at that time,
9983 but it will become visible later when the window manager
9984 finishes with it. */
9985
9986void
9987x_make_frame_visible (f)
9988 struct frame *f;
9989{
9990 Lisp_Object type;
9991 int original_top, original_left;
9992
9993 BLOCK_INPUT;
9994
9995 if (! FRAME_VISIBLE_P (f))
9996 {
9997 /* We test FRAME_GARBAGED_P here to make sure we don't
9998 call x_set_offset a second time
9999 if we get to x_make_frame_visible a second time
10000 before the window gets really visible. */
10001 if (! FRAME_ICONIFIED_P (f)
10002 && ! f->output_data.mac->asked_for_visible)
10003 x_set_offset (f, f->output_data.mac->left_pos,
10004 f->output_data.mac->top_pos, 0);
10005
10006 f->output_data.mac->asked_for_visible = 1;
10007
10008 ShowWindow (FRAME_MAC_WINDOW (f));
10009 }
10010
10011 XFlush (FRAME_MAC_DISPLAY (f));
10012
e0f712ba 10013#if 0 /* MAC_TODO */
1a578e9b
AC
10014 /* Synchronize to ensure Emacs knows the frame is visible
10015 before we do anything else. We do this loop with input not blocked
10016 so that incoming events are handled. */
10017 {
10018 Lisp_Object frame;
10019 int count;
10020
10021 /* This must come after we set COUNT. */
10022 UNBLOCK_INPUT;
10023
10024 XSETFRAME (frame, f);
10025
10026 /* Wait until the frame is visible. Process X events until a
10027 MapNotify event has been seen, or until we think we won't get a
10028 MapNotify at all.. */
10029 for (count = input_signal_count + 10;
10030 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10031 {
10032 /* Force processing of queued events. */
10033 x_sync (f);
10034
10035 /* Machines that do polling rather than SIGIO have been
10036 observed to go into a busy-wait here. So we'll fake an
10037 alarm signal to let the handler know that there's something
10038 to be read. We used to raise a real alarm, but it seems
10039 that the handler isn't always enabled here. This is
10040 probably a bug. */
10041 if (input_polling_used ())
10042 {
10043 /* It could be confusing if a real alarm arrives while
10044 processing the fake one. Turn it off and let the
10045 handler reset it. */
10046 extern void poll_for_input_1 P_ ((void));
10047 int old_poll_suppress_count = poll_suppress_count;
10048 poll_suppress_count = 1;
10049 poll_for_input_1 ();
10050 poll_suppress_count = old_poll_suppress_count;
10051 }
10052
10053 /* See if a MapNotify event has been processed. */
10054 FRAME_SAMPLE_VISIBILITY (f);
10055 }
10056 }
e0f712ba 10057#endif /* MAC_TODO */
1a578e9b
AC
10058}
10059
10060/* Change from mapped state to withdrawn state. */
10061
10062/* Make the frame visible (mapped and not iconified). */
10063
10064void
10065x_make_frame_invisible (f)
10066 struct frame *f;
10067{
10068 /* Don't keep the highlight on an invisible frame. */
10069 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10070 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10071
10072 BLOCK_INPUT;
10073
10074 HideWindow (FRAME_MAC_WINDOW (f));
10075
10076 /* We can't distinguish this from iconification
10077 just by the event that we get from the server.
10078 So we can't win using the usual strategy of letting
10079 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10080 and synchronize with the server to make sure we agree. */
10081 f->visible = 0;
10082 FRAME_ICONIFIED_P (f) = 0;
10083 f->async_visible = 0;
10084 f->async_iconified = 0;
10085
10086 UNBLOCK_INPUT;
10087}
10088
10089/* Change window state from mapped to iconified. */
10090
10091void
10092x_iconify_frame (f)
10093 struct frame *f;
10094{
10095#if 0 /* MAC_TODO: really no iconify on Mac */
10096 int result;
10097 Lisp_Object type;
10098
10099 /* Don't keep the highlight on an invisible frame. */
10100 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
10101 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
10102
10103 if (f->async_iconified)
10104 return;
10105
10106 BLOCK_INPUT;
10107
10108 FRAME_SAMPLE_VISIBILITY (f);
10109
10110 type = x_icon_type (f);
10111 if (!NILP (type))
10112 x_bitmap_icon (f, type);
10113
10114#ifdef USE_X_TOOLKIT
10115
10116 if (! FRAME_VISIBLE_P (f))
10117 {
10118 if (! EQ (Vx_no_window_manager, Qt))
10119 x_wm_set_window_state (f, IconicState);
10120 /* This was XtPopup, but that did nothing for an iconified frame. */
10121 XtMapWidget (f->output_data.x->widget);
10122 /* The server won't give us any event to indicate
10123 that an invisible frame was changed to an icon,
10124 so we have to record it here. */
10125 f->iconified = 1;
10126 f->visible = 1;
10127 f->async_iconified = 1;
10128 f->async_visible = 0;
10129 UNBLOCK_INPUT;
10130 return;
10131 }
10132
10133 result = XIconifyWindow (FRAME_X_DISPLAY (f),
10134 XtWindow (f->output_data.x->widget),
10135 DefaultScreen (FRAME_X_DISPLAY (f)));
10136 UNBLOCK_INPUT;
10137
10138 if (!result)
10139 error ("Can't notify window manager of iconification");
10140
10141 f->async_iconified = 1;
10142 f->async_visible = 0;
10143
10144
10145 BLOCK_INPUT;
10146 XFlush (FRAME_X_DISPLAY (f));
10147 UNBLOCK_INPUT;
10148#else /* not USE_X_TOOLKIT */
10149
10150 /* Make sure the X server knows where the window should be positioned,
10151 in case the user deiconifies with the window manager. */
10152 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
10153 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
10154
10155 /* Since we don't know which revision of X we're running, we'll use both
10156 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
10157
10158 /* X11R4: send a ClientMessage to the window manager using the
10159 WM_CHANGE_STATE type. */
10160 {
10161 XEvent message;
10162
10163 message.xclient.window = FRAME_X_WINDOW (f);
10164 message.xclient.type = ClientMessage;
10165 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
10166 message.xclient.format = 32;
10167 message.xclient.data.l[0] = IconicState;
10168
10169 if (! XSendEvent (FRAME_X_DISPLAY (f),
10170 DefaultRootWindow (FRAME_X_DISPLAY (f)),
10171 False,
10172 SubstructureRedirectMask | SubstructureNotifyMask,
10173 &message))
10174 {
10175 UNBLOCK_INPUT_RESIGNAL;
10176 error ("Can't notify window manager of iconification");
10177 }
10178 }
10179
10180 /* X11R3: set the initial_state field of the window manager hints to
10181 IconicState. */
10182 x_wm_set_window_state (f, IconicState);
10183
10184 if (!FRAME_VISIBLE_P (f))
10185 {
10186 /* If the frame was withdrawn, before, we must map it. */
10187 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10188 }
10189
10190 f->async_iconified = 1;
10191 f->async_visible = 0;
10192
10193 XFlush (FRAME_X_DISPLAY (f));
10194 UNBLOCK_INPUT;
10195#endif /* not USE_X_TOOLKIT */
e0f712ba 10196#endif /* MAC_TODO */
1a578e9b 10197}
e0f712ba 10198
1a578e9b
AC
10199\f
10200/* Destroy the X window of frame F. */
10201
10202void
10203x_destroy_window (f)
10204 struct frame *f;
10205{
10206 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10207
10208 BLOCK_INPUT;
10209
10210 DisposeWindow (FRAME_MAC_WINDOW (f));
10211
10212 free_frame_menubar (f);
10213 free_frame_faces (f);
10214
10215 xfree (f->output_data.mac);
10216 f->output_data.mac = 0;
10217 if (f == dpyinfo->x_focus_frame)
10218 dpyinfo->x_focus_frame = 0;
10219 if (f == dpyinfo->x_focus_event_frame)
10220 dpyinfo->x_focus_event_frame = 0;
10221 if (f == dpyinfo->x_highlight_frame)
10222 dpyinfo->x_highlight_frame = 0;
10223
10224 dpyinfo->reference_count--;
10225
10226 if (f == dpyinfo->mouse_face_mouse_frame)
10227 {
10228 dpyinfo->mouse_face_beg_row
10229 = dpyinfo->mouse_face_beg_col = -1;
10230 dpyinfo->mouse_face_end_row
10231 = dpyinfo->mouse_face_end_col = -1;
10232 dpyinfo->mouse_face_window = Qnil;
10233 dpyinfo->mouse_face_deferred_gc = 0;
10234 dpyinfo->mouse_face_mouse_frame = 0;
10235 }
10236
10237 UNBLOCK_INPUT;
10238}
10239\f
10240/* Setting window manager hints. */
10241
10242/* Set the normal size hints for the window manager, for frame F.
10243 FLAGS is the flags word to use--or 0 meaning preserve the flags
10244 that the window now has.
10245 If USER_POSITION is nonzero, we set the USPosition
10246 flag (this is useful when FLAGS is 0). */
1a578e9b
AC
10247void
10248x_wm_set_size_hint (f, flags, user_position)
10249 struct frame *f;
10250 long flags;
10251 int user_position;
10252{
10253#if 0 /* MAC_TODO: connect this to the Appearance Manager */
10254 XSizeHints size_hints;
10255
10256#ifdef USE_X_TOOLKIT
10257 Arg al[2];
10258 int ac = 0;
10259 Dimension widget_width, widget_height;
10260 Window window = XtWindow (f->output_data.x->widget);
10261#else /* not USE_X_TOOLKIT */
10262 Window window = FRAME_X_WINDOW (f);
10263#endif /* not USE_X_TOOLKIT */
10264
10265 /* Setting PMaxSize caused various problems. */
10266 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10267
10268 size_hints.x = f->output_data.x->left_pos;
10269 size_hints.y = f->output_data.x->top_pos;
10270
10271#ifdef USE_X_TOOLKIT
10272 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10273 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10274 XtGetValues (f->output_data.x->widget, al, ac);
10275 size_hints.height = widget_height;
10276 size_hints.width = widget_width;
10277#else /* not USE_X_TOOLKIT */
10278 size_hints.height = PIXEL_HEIGHT (f);
10279 size_hints.width = PIXEL_WIDTH (f);
10280#endif /* not USE_X_TOOLKIT */
10281
10282 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10283 size_hints.height_inc = f->output_data.x->line_height;
10284 size_hints.max_width
10285 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10286 size_hints.max_height
10287 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10288
10289 /* Calculate the base and minimum sizes.
10290
10291 (When we use the X toolkit, we don't do it here.
10292 Instead we copy the values that the widgets are using, below.) */
10293#ifndef USE_X_TOOLKIT
10294 {
10295 int base_width, base_height;
10296 int min_rows = 0, min_cols = 0;
10297
10298 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10299 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10300
10301 check_frame_size (f, &min_rows, &min_cols);
10302
10303 /* The window manager uses the base width hints to calculate the
10304 current number of rows and columns in the frame while
10305 resizing; min_width and min_height aren't useful for this
10306 purpose, since they might not give the dimensions for a
10307 zero-row, zero-column frame.
10308
10309 We use the base_width and base_height members if we have
10310 them; otherwise, we set the min_width and min_height members
10311 to the size for a zero x zero frame. */
10312
10313#ifdef HAVE_X11R4
10314 size_hints.flags |= PBaseSize;
10315 size_hints.base_width = base_width;
10316 size_hints.base_height = base_height;
10317 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10318 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10319#else
10320 size_hints.min_width = base_width;
10321 size_hints.min_height = base_height;
10322#endif
10323 }
10324
10325 /* If we don't need the old flags, we don't need the old hint at all. */
10326 if (flags)
10327 {
10328 size_hints.flags |= flags;
10329 goto no_read;
10330 }
10331#endif /* not USE_X_TOOLKIT */
10332
10333 {
10334 XSizeHints hints; /* Sometimes I hate X Windows... */
10335 long supplied_return;
10336 int value;
10337
10338#ifdef HAVE_X11R4
10339 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10340 &supplied_return);
10341#else
10342 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10343#endif
10344
10345#ifdef USE_X_TOOLKIT
10346 size_hints.base_height = hints.base_height;
10347 size_hints.base_width = hints.base_width;
10348 size_hints.min_height = hints.min_height;
10349 size_hints.min_width = hints.min_width;
10350#endif
10351
10352 if (flags)
10353 size_hints.flags |= flags;
10354 else
10355 {
10356 if (value == 0)
10357 hints.flags = 0;
10358 if (hints.flags & PSize)
10359 size_hints.flags |= PSize;
10360 if (hints.flags & PPosition)
10361 size_hints.flags |= PPosition;
10362 if (hints.flags & USPosition)
10363 size_hints.flags |= USPosition;
10364 if (hints.flags & USSize)
10365 size_hints.flags |= USSize;
10366 }
10367 }
10368
10369#ifndef USE_X_TOOLKIT
10370 no_read:
10371#endif
10372
10373#ifdef PWinGravity
10374 size_hints.win_gravity = f->output_data.x->win_gravity;
10375 size_hints.flags |= PWinGravity;
10376
10377 if (user_position)
10378 {
10379 size_hints.flags &= ~ PPosition;
10380 size_hints.flags |= USPosition;
10381 }
10382#endif /* PWinGravity */
10383
10384#ifdef HAVE_X11R4
10385 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10386#else
10387 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10388#endif
e0f712ba 10389#endif /* MAC_TODO */
1a578e9b
AC
10390}
10391
e0f712ba 10392#if 0 /* MAC_TODO: hide application instead of iconify? */
1a578e9b
AC
10393/* Used for IconicState or NormalState */
10394
10395void
10396x_wm_set_window_state (f, state)
10397 struct frame *f;
10398 int state;
10399{
10400#ifdef USE_X_TOOLKIT
10401 Arg al[1];
10402
10403 XtSetArg (al[0], XtNinitialState, state);
10404 XtSetValues (f->output_data.x->widget, al, 1);
10405#else /* not USE_X_TOOLKIT */
10406 Window window = FRAME_X_WINDOW (f);
10407
10408 f->output_data.x->wm_hints.flags |= StateHint;
10409 f->output_data.x->wm_hints.initial_state = state;
10410
10411 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10412#endif /* not USE_X_TOOLKIT */
10413}
10414
10415void
10416x_wm_set_icon_pixmap (f, pixmap_id)
10417 struct frame *f;
10418 int pixmap_id;
10419{
10420 Pixmap icon_pixmap;
10421
10422#ifndef USE_X_TOOLKIT
10423 Window window = FRAME_X_WINDOW (f);
10424#endif
10425
10426 if (pixmap_id > 0)
10427 {
10428 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10429 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10430 }
10431 else
10432 {
10433 /* It seems there is no way to turn off use of an icon pixmap.
10434 The following line does it, only if no icon has yet been created,
10435 for some window managers. But with mwm it crashes.
10436 Some people say it should clear the IconPixmapHint bit in this case,
10437 but that doesn't work, and the X consortium said it isn't the
10438 right thing at all. Since there is no way to win,
10439 best to explicitly give up. */
10440#if 0
10441 f->output_data.x->wm_hints.icon_pixmap = None;
10442#else
10443 return;
10444#endif
10445 }
10446
10447#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10448
10449 {
10450 Arg al[1];
10451 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10452 XtSetValues (f->output_data.x->widget, al, 1);
10453 }
10454
10455#else /* not USE_X_TOOLKIT */
10456
10457 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10458 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10459
10460#endif /* not USE_X_TOOLKIT */
10461}
10462
e0f712ba 10463#endif /* MAC_TODO */
1a578e9b
AC
10464
10465void
10466x_wm_set_icon_position (f, icon_x, icon_y)
10467 struct frame *f;
10468 int icon_x, icon_y;
10469{
10470#if 0 /* MAC_TODO: no icons on Mac */
10471#ifdef USE_X_TOOLKIT
10472 Window window = XtWindow (f->output_data.x->widget);
10473#else
10474 Window window = FRAME_X_WINDOW (f);
10475#endif
10476
10477 f->output_data.x->wm_hints.flags |= IconPositionHint;
10478 f->output_data.x->wm_hints.icon_x = icon_x;
10479 f->output_data.x->wm_hints.icon_y = icon_y;
10480
10481 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
e0f712ba 10482#endif /* MAC_TODO */
1a578e9b
AC
10483}
10484
10485\f
10486/***********************************************************************
10487 Fonts
10488 ***********************************************************************/
10489
10490/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10491
10492struct font_info *
10493x_get_font_info (f, font_idx)
10494 FRAME_PTR f;
10495 int font_idx;
10496{
10497 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10498}
10499
10500/* the global font name table */
10501char **font_name_table = NULL;
10502int font_name_table_size = 0;
10503int font_name_count = 0;
10504
10505/* compare two strings ignoring case */
10506static int
10507stricmp (const char *s, const char *t)
10508{
10509 for ( ; tolower (*s) == tolower (*t); s++, t++)
10510 if (*s == '\0')
10511 return 0;
10512 return tolower (*s) - tolower (*t);
10513}
10514
10515/* compare two strings ignoring case and handling wildcard */
10516static int
10517wildstrieq (char *s1, char *s2)
10518{
10519 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10520 return true;
10521
10522 return stricmp (s1, s2) == 0;
10523}
10524
10525/* Assume parameter 1 is fully qualified, no wildcards. */
10526static int
10527mac_font_pattern_match (fontname, pattern)
10528 char * fontname;
10529 char * pattern;
10530{
b179a3a2 10531 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
1a578e9b
AC
10532 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10533 char *ptr;
10534
10535 /* Copy fontname so we can modify it during comparison. */
10536 strcpy (font_name_copy, fontname);
10537
10538 ptr = regex;
10539 *ptr++ = '^';
10540
10541 /* Turn pattern into a regexp and do a regexp match. */
10542 for (; *pattern; pattern++)
10543 {
10544 if (*pattern == '?')
10545 *ptr++ = '.';
10546 else if (*pattern == '*')
10547 {
10548 *ptr++ = '.';
10549 *ptr++ = '*';
10550 }
10551 else
10552 *ptr++ = *pattern;
10553 }
10554 *ptr = '$';
10555 *(ptr + 1) = '\0';
10556
10557 return (fast_c_string_match_ignore_case (build_string (regex),
10558 font_name_copy) >= 0);
10559}
10560
10561/* Two font specs are considered to match if their foundry, family,
10562 weight, slant, and charset match. */
10563static int
10564mac_font_match (char *mf, char *xf)
10565{
10566 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10567 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10568
10569 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10570 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10571 return mac_font_pattern_match (mf, xf);
10572
10573 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10574 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10575 return mac_font_pattern_match (mf, xf);
10576
10577 return (wildstrieq (m_foundry, x_foundry)
10578 && wildstrieq (m_family, x_family)
10579 && wildstrieq (m_weight, x_weight)
10580 && wildstrieq (m_slant, x_slant)
10581 && wildstrieq (m_charset, x_charset))
10582 || mac_font_pattern_match (mf, xf);
10583}
10584
10585
10586static char *
10587mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10588{
10589 char foundry[32], family[32], cs[32];
10590 char xf[255], *result, *p;
10591
10592 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10593 {
10594 strcpy(foundry, "Apple");
10595 strcpy(family, name);
10596
10597 switch (scriptcode)
10598 {
10599 case smTradChinese:
10600 strcpy(cs, "big5-0");
10601 break;
10602 case smSimpChinese:
83a96b4d 10603 strcpy(cs, "gb2312.1980-0");
1a578e9b
AC
10604 break;
10605 case smJapanese:
10606 strcpy(cs, "jisx0208.1983-sjis");
10607 break;
2f64cf3a
AC
10608 case -smJapanese:
10609 /* Each Apple Japanese font is entered into the font table
10610 twice: once as a jisx0208.1983-sjis font and once as a
10611 jisx0201.1976-0 font. The latter can be used to display
10612 the ascii charset and katakana-jisx0201 charset. A
10613 negative script code signals that the name of this latter
10614 font is being built. */
10615 strcpy(cs, "jisx0201.1976-0");
10616 break;
1a578e9b 10617 case smKorean:
83a96b4d 10618 strcpy(cs, "ksc5601.1989-0");
1a578e9b
AC
10619 break;
10620 default:
10621 strcpy(cs, "mac-roman");
10622 break;
10623 }
10624 }
10625
10626 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10627 foundry, family, style & bold ? "bold" : "medium",
10628 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10629
10630 result = (char *) xmalloc (strlen (xf) + 1);
10631 strcpy (result, xf);
10632 for (p = result; *p; p++)
10633 *p = tolower(*p);
10634 return result;
10635}
10636
10637
10638/* Convert an X font spec to the corresponding mac font name, which
10639 can then be passed to GetFNum after conversion to a Pascal string.
10640 For ordinary Mac fonts, this should just be their names, like
10641 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10642 collection contain their charset designation in their names, like
10643 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10644 names are handled accordingly. */
10645static void
10646x_font_name_to_mac_font_name (char *xf, char *mf)
10647{
10648 char foundry[32], family[32], weight[20], slant[2], cs[32];
10649
10650 strcpy (mf, "");
10651
10652 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10653 foundry, family, weight, slant, cs) != 5 &&
10654 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10655 foundry, family, weight, slant, cs) != 5)
10656 return;
10657
83a96b4d 10658 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
1a578e9b 10659 || strcmp (cs, "jisx0208.1983-sjis") == 0
2f64cf3a 10660 || strcmp (cs, "jisx0201.1976-0") == 0
83a96b4d 10661 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
1a578e9b
AC
10662 strcpy(mf, family);
10663 else
10664 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10665}
10666
10667
f00691a3
AC
10668static void
10669add_font_name_table_entry (char *font_name)
10670{
10671 if (font_name_table_size == 0)
10672 {
10673 font_name_table_size = 16;
10674 font_name_table = (char **)
10675 xmalloc (font_name_table_size * sizeof (char *));
10676 }
10677 else if (font_name_count + 1 >= font_name_table_size)
10678 {
10679 font_name_table_size += 16;
10680 font_name_table = (char **)
10681 xrealloc (font_name_table,
10682 font_name_table_size * sizeof (char *));
10683 }
10684
10685 font_name_table[font_name_count++] = font_name;
10686}
10687
10688/* Sets up the table font_name_table to contain the list of all fonts
10689 in the system the first time the table is used so that the Resource
10690 Manager need not be accessed every time this information is
10691 needed. */
1a578e9b
AC
10692
10693static void
10694init_font_name_table ()
10695{
e0f712ba
AC
10696#if TARGET_API_MAC_CARBON
10697 SInt32 sv;
10698
10699 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10700 {
10701 FMFontFamilyIterator ffi;
10702 FMFontFamilyInstanceIterator ffii;
10703 FMFontFamily ff;
1a578e9b 10704
e0f712ba
AC
10705 /* Create a dummy instance iterator here to avoid creating and
10706 destroying it in the loop. */
10707 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10708 return;
10709 /* Create an iterator to enumerate the font families. */
10710 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10711 != noErr)
10712 {
10713 FMDisposeFontFamilyInstanceIterator (&ffii);
10714 return;
10715 }
1a578e9b 10716
e0f712ba
AC
10717 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10718 {
10719 Str255 name;
10720 FMFont font;
10721 FMFontStyle style;
10722 FMFontSize size;
10723 SInt16 sc;
10724
10725 if (FMGetFontFamilyName (ff, name) != noErr)
10726 break;
10727 p2cstr (name);
10728
10729 sc = FontToScript (ff);
10730
10731 /* Point the instance iterator at the current font family. */
10732 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10733 break;
10734
10735 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10736 == noErr)
f00691a3
AC
10737 if (size == 0)
10738 {
10739 add_font_name_table_entry (mac_to_x_fontname (name, size,
10740 style, sc));
10741 add_font_name_table_entry (mac_to_x_fontname (name, size,
10742 italic, sc));
10743 add_font_name_table_entry (mac_to_x_fontname (name, size,
10744 bold, sc));
10745 add_font_name_table_entry (mac_to_x_fontname (name, size,
10746 italic | bold,
10747 sc));
10748 }
10749 else
a0f593ff
AC
10750 {
10751 add_font_name_table_entry (mac_to_x_fontname (name, size,
10752 style, sc));
10753 if (smJapanese == sc)
10754 add_font_name_table_entry (mac_to_x_fontname (name, size,
10755 style,
10756 -smJapanese));
10757 }
e0f712ba
AC
10758 }
10759
10760 /* Dispose of the iterators. */
10761 FMDisposeFontFamilyIterator (&ffi);
10762 FMDisposeFontFamilyInstanceIterator (&ffii);
10763 }
10764 else
1a578e9b 10765 {
e0f712ba
AC
10766#endif /* TARGET_API_MAC_CARBON */
10767 GrafPtr port;
10768 SInt16 fontnum, old_fontnum;
10769 int num_mac_fonts = CountResources('FOND');
10770 int i, j;
10771 Handle font_handle, font_handle_2;
10772 short id, scriptcode;
10773 ResType type;
10774 Str32 name;
10775 struct FontAssoc *fat;
10776 struct AsscEntry *assc_entry;
1a578e9b 10777
e0f712ba
AC
10778 GetPort (&port); /* save the current font number used */
10779#if TARGET_API_MAC_CARBON
10780 old_fontnum = GetPortTextFont (port);
10781#else
10782 old_fontnum = port->txFont;
10783#endif
10784
10785 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10786 {
10787 font_handle = GetIndResource ('FOND', i);
10788 if (!font_handle)
10789 continue;
10790
10791 GetResInfo (font_handle, &id, &type, name);
10792 GetFNum (name, &fontnum);
10793 p2cstr (name);
10794 if (fontnum == 0)
10795 continue;
10796
10797 TextFont (fontnum);
10798 scriptcode = FontToScript (fontnum);
10799 do
10800 {
10801 HLock (font_handle);
10802
10803 if (GetResourceSizeOnDisk (font_handle)
10804 >= sizeof (struct FamRec))
10805 {
10806 fat = (struct FontAssoc *) (*font_handle
10807 + sizeof (struct FamRec));
10808 assc_entry
10809 = (struct AsscEntry *) (*font_handle
10810 + sizeof (struct FamRec)
10811 + sizeof (struct FontAssoc));
10812
10813 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
199f9270 10814 {
e0f712ba
AC
10815 if (font_name_table_size == 0)
10816 {
10817 font_name_table_size = 16;
10818 font_name_table = (char **)
10819 xmalloc (font_name_table_size * sizeof (char *));
10820 }
10821 else if (font_name_count >= font_name_table_size)
10822 {
10823 font_name_table_size += 16;
10824 font_name_table = (char **)
10825 xrealloc (font_name_table,
10826 font_name_table_size * sizeof (char *));
10827 }
199f9270 10828 font_name_table[font_name_count++]
e0f712ba 10829 = mac_to_x_fontname (name,
199f9270
AC
10830 assc_entry->fontSize,
10831 assc_entry->fontStyle,
e0f712ba
AC
10832 scriptcode);
10833 /* Both jisx0208.1983-sjis and
10834 jisx0201.1976-sjis parts are contained in
10835 Apple Japanese (SJIS) font. */
10836 if (smJapanese == scriptcode)
10837 {
10838 font_name_table[font_name_count++]
10839 = mac_to_x_fontname (name,
10840 assc_entry->fontSize,
10841 assc_entry->fontStyle,
a0f593ff 10842 -smJapanese);
e0f712ba 10843 }
199f9270 10844 }
e0f712ba
AC
10845 }
10846
10847 HUnlock (font_handle);
10848 font_handle_2 = GetNextFOND (font_handle);
10849 ReleaseResource (font_handle);
10850 font_handle = font_handle_2;
10851 }
10852 while (ResError () == noErr && font_handle);
10853 }
10854
10855 TextFont (old_fontnum);
10856#if TARGET_API_MAC_CARBON
1a578e9b 10857 }
e0f712ba 10858#endif /* TARGET_API_MAC_CARBON */
1a578e9b
AC
10859}
10860
10861
10862/* Return a list of at most MAXNAMES font specs matching the one in
10ba2aec
AC
10863 PATTERN. Cache matching fonts for patterns in
10864 dpyinfo->name_list_element to avoid looking them up again by
10865 calling mac_font_pattern_match (slow). */
1a578e9b
AC
10866
10867Lisp_Object
10868x_list_fonts (struct frame *f,
10869 Lisp_Object pattern,
10870 int size,
10871 int maxnames)
10872{
10873 char *ptnstr;
10ba2aec 10874 Lisp_Object newlist = Qnil, tem, key;
1a578e9b
AC
10875 int n_fonts = 0;
10876 int i;
b179a3a2 10877 struct gcpro gcpro1, gcpro2;
10ba2aec 10878 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
1a578e9b
AC
10879
10880 if (font_name_table == NULL) /* Initialize when first used. */
10881 init_font_name_table ();
10882
10ba2aec
AC
10883 if (dpyinfo)
10884 {
10885 tem = XCDR (dpyinfo->name_list_element);
10886 key = Fcons (pattern, make_number (maxnames));
10887
10888 newlist = Fassoc (key, tem);
10889 if (!NILP (newlist))
10890 {
10891 newlist = Fcdr_safe (newlist);
10892 goto label_cached;
10893 }
10894 }
10895
d5db4077 10896 ptnstr = SDATA (pattern);
1a578e9b 10897
b179a3a2
AC
10898 GCPRO2 (pattern, newlist);
10899
1a578e9b
AC
10900 /* Scan and matching bitmap fonts. */
10901 for (i = 0; i < font_name_count; i++)
10902 {
10903 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10904 {
10905 newlist = Fcons (build_string (font_name_table[i]), newlist);
10906
10907 n_fonts++;
10908 if (n_fonts >= maxnames)
10909 break;
10910 }
10911 }
10912
10913 /* MAC_TODO: add code for matching outline fonts here */
10914
b179a3a2
AC
10915 UNGCPRO;
10916
10ba2aec
AC
10917 if (dpyinfo)
10918 {
10919 XSETCDR (dpyinfo->name_list_element,
10920 Fcons (Fcons (key, newlist),
10921 XCDR (dpyinfo->name_list_element)));
10922 }
10923 label_cached:
10924
1a578e9b
AC
10925 return newlist;
10926}
10927
10928
10929#if GLYPH_DEBUG
10930
e0f712ba
AC
10931/* Check that FONT is valid on frame F. It is if it can be found in F's
10932 font table. */
1a578e9b
AC
10933
10934static void
10935x_check_font (f, font)
10936 struct frame *f;
10937 XFontStruct *font;
10938{
10939 int i;
10940 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10941
10942 xassert (font != NULL);
10943
10944 for (i = 0; i < dpyinfo->n_fonts; i++)
10945 if (dpyinfo->font_table[i].name
10946 && font == dpyinfo->font_table[i].font)
10947 break;
10948
10949 xassert (i < dpyinfo->n_fonts);
10950}
10951
10952#endif /* GLYPH_DEBUG != 0 */
10953
1a578e9b
AC
10954/* Set *W to the minimum width, *H to the minimum font height of FONT.
10955 Note: There are (broken) X fonts out there with invalid XFontStruct
10956 min_bounds contents. For example, handa@etl.go.jp reports that
10957 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10958 have font->min_bounds.width == 0. */
10959
10960static INLINE void
10961x_font_min_bounds (font, w, h)
10962 MacFontStruct *font;
10963 int *w, *h;
10964{
e0f712ba
AC
10965 /*
10966 * TODO: Windows does not appear to offer min bound, only
10967 * average and maximum width, and maximum height.
10968 */
1a578e9b 10969 *h = FONT_HEIGHT (font);
e0f712ba 10970 *w = FONT_WIDTH (font);
1a578e9b
AC
10971}
10972
10973
10974/* Compute the smallest character width and smallest font height over
10975 all fonts available on frame F. Set the members smallest_char_width
10976 and smallest_font_height in F's x_display_info structure to
10977 the values computed. Value is non-zero if smallest_font_height or
10978 smallest_char_width become smaller than they were before. */
10979
e0f712ba 10980int
1a578e9b
AC
10981x_compute_min_glyph_bounds (f)
10982 struct frame *f;
10983{
10984 int i;
10985 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10986 MacFontStruct *font;
10987 int old_width = dpyinfo->smallest_char_width;
10988 int old_height = dpyinfo->smallest_font_height;
10989
10990 dpyinfo->smallest_font_height = 100000;
10991 dpyinfo->smallest_char_width = 100000;
10992
10993 for (i = 0; i < dpyinfo->n_fonts; ++i)
10994 if (dpyinfo->font_table[i].name)
10995 {
10996 struct font_info *fontp = dpyinfo->font_table + i;
10997 int w, h;
10998
10999 font = (MacFontStruct *) fontp->font;
11000 xassert (font != (MacFontStruct *) ~0);
11001 x_font_min_bounds (font, &w, &h);
11002
11003 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
11004 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
11005 }
11006
11007 xassert (dpyinfo->smallest_char_width > 0
11008 && dpyinfo->smallest_font_height > 0);
11009
11010 return (dpyinfo->n_fonts == 1
11011 || dpyinfo->smallest_char_width < old_width
11012 || dpyinfo->smallest_font_height < old_height);
11013}
11014
11015
11016/* Determine whether given string is a fully-specified XLFD: all 14
11017 fields are present, none is '*'. */
11018
11019static int
11020is_fully_specified_xlfd (char *p)
11021{
11022 int i;
11023 char *q;
11024
11025 if (*p != '-')
11026 return 0;
11027
11028 for (i = 0; i < 13; i++)
11029 {
11030 q = strchr (p + 1, '-');
11031 if (q == NULL)
11032 return 0;
11033 if (q - p == 2 && *(p + 1) == '*')
11034 return 0;
11035 p = q;
11036 }
11037
11038 if (strchr (p + 1, '-') != NULL)
11039 return 0;
11040
11041 if (*(p + 1) == '*' && *(p + 2) == '\0')
11042 return 0;
11043
11044 return 1;
11045}
11046
11047
11048const int kDefaultFontSize = 9;
11049
11050
e0f712ba
AC
11051/* XLoadQueryFont creates and returns an internal representation for a
11052 font in a MacFontStruct struct. There is really no concept
11053 corresponding to "loading" a font on the Mac. But we check its
11054 existence and find the font number and all other information for it
11055 and store them in the returned MacFontStruct. */
1a578e9b
AC
11056
11057static MacFontStruct *
11058XLoadQueryFont (Display *dpy, char *fontname)
11059{
11060 int i, size, is_two_byte_font, char_width;
11061 char *name;
11062 GrafPtr port;
11063 SInt16 old_fontnum, old_fontsize;
11064 Style old_fontface;
11065 Str32 mfontname;
11066 SInt16 fontnum;
11067 Style fontface = normal;
11068 MacFontStruct *font;
11069 FontInfo the_fontinfo;
11070 char s_weight[7], c_slant;
11071
11072 if (is_fully_specified_xlfd (fontname))
11073 name = fontname;
11074 else
11075 {
11076 for (i = 0; i < font_name_count; i++)
11077 if (mac_font_pattern_match (font_name_table[i], fontname))
11078 break;
11079
11080 if (i >= font_name_count)
11081 return NULL;
11082
11083 name = font_name_table[i];
11084 }
11085
11086 GetPort (&port); /* save the current font number used */
e0f712ba
AC
11087#if TARGET_API_MAC_CARBON
11088 old_fontnum = GetPortTextFont (port);
11089 old_fontsize = GetPortTextSize (port);
11090 old_fontface = GetPortTextFace (port);
11091#else
1a578e9b
AC
11092 old_fontnum = port->txFont;
11093 old_fontsize = port->txSize;
11094 old_fontface = port->txFace;
e0f712ba 11095#endif
1a578e9b
AC
11096
11097 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11098 size = kDefaultFontSize;
11099
11100 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11101 if (strcmp (s_weight, "bold") == 0)
11102 fontface |= bold;
11103
11104 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11105 if (c_slant == 'i')
11106 fontface |= italic;
11107
11108 x_font_name_to_mac_font_name (name, mfontname);
11109 c2pstr (mfontname);
11110 GetFNum (mfontname, &fontnum);
11111 if (fontnum == 0)
11112 return NULL;
11113
11114 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
11115
11116 font->fontname = (char *) xmalloc (strlen (name) + 1);
11117 bcopy (name, font->fontname, strlen (name) + 1);
11118
11119 font->mac_fontnum = fontnum;
11120 font->mac_fontsize = size;
11121 font->mac_fontface = fontface;
11122 font->mac_scriptcode = FontToScript (fontnum);
11123
199f9270 11124 /* Apple Japanese (SJIS) font is listed as both
2f64cf3a 11125 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
e0f712ba 11126 (Roman script) in init_font_name_table (). The latter should be
2f64cf3a 11127 treated as a one-byte font. */
199f9270
AC
11128 {
11129 char cs[32];
11130
11131 if (sscanf (name,
11132 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11133 cs) == 1
a0f593ff 11134 && 0 == strcmp (cs, "jisx0201.1976-0"))
199f9270
AC
11135 font->mac_scriptcode = smRoman;
11136 }
11137
1a578e9b
AC
11138 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11139 font->mac_scriptcode == smTradChinese ||
11140 font->mac_scriptcode == smSimpChinese ||
11141 font->mac_scriptcode == smKorean;
11142
11143 TextFont (fontnum);
11144 TextSize (size);
11145 TextFace (fontface);
11146
11147 GetFontInfo (&the_fontinfo);
11148
11149 font->ascent = the_fontinfo.ascent;
11150 font->descent = the_fontinfo.descent;
11151
11152 font->min_byte1 = 0;
11153 if (is_two_byte_font)
11154 font->max_byte1 = 1;
11155 else
11156 font->max_byte1 = 0;
11157 font->min_char_or_byte2 = 0x20;
11158 font->max_char_or_byte2 = 0xff;
11159
11160 if (is_two_byte_font)
11161 {
11162 /* Use the width of an "ideographic space" of that font because
11163 the_fontinfo.widMax returns the wrong width for some fonts. */
11164 switch (font->mac_scriptcode)
11165 {
11166 case smJapanese:
11167 char_width = StringWidth("\p\x81\x40");
11168 break;
11169 case smTradChinese:
11170 char_width = StringWidth("\p\xa1\x40");
11171 break;
11172 case smSimpChinese:
11173 char_width = StringWidth("\p\xa1\xa1");
11174 break;
11175 case smKorean:
11176 char_width = StringWidth("\p\xa1\xa1");
11177 break;
11178 }
11179 }
11180 else
11181 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11182 returns 15 for 12-point Monaco! */
11183 char_width = CharWidth ('m');
11184
11185 font->max_bounds.rbearing = char_width;
11186 font->max_bounds.lbearing = 0;
11187 font->max_bounds.width = char_width;
11188 font->max_bounds.ascent = the_fontinfo.ascent;
11189 font->max_bounds.descent = the_fontinfo.descent;
11190
11191 font->min_bounds = font->max_bounds;
11192
11193 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11194 font->per_char = NULL;
11195 else
11196 {
11197 font->per_char = (XCharStruct *)
11198 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11199 {
11200 int c;
11201
11202 for (c = 0x20; c <= 0xff; c++)
11203 {
11204 font->per_char[c - 0x20] = font->max_bounds;
11205 font->per_char[c - 0x20].width = CharWidth (c);
11206 }
11207 }
11208 }
11209
11210 TextFont (old_fontnum); /* restore previous font number, size and face */
11211 TextSize (old_fontsize);
11212 TextFace (old_fontface);
11213
11214 return font;
11215}
11216
11217
11218/* Load font named FONTNAME of the size SIZE for frame F, and return a
11219 pointer to the structure font_info while allocating it dynamically.
11220 If SIZE is 0, load any size of font.
11221 If loading is failed, return NULL. */
11222
11223struct font_info *
11224x_load_font (f, fontname, size)
11225 struct frame *f;
11226 register char *fontname;
11227 int size;
11228{
11229 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11230 Lisp_Object font_names;
11231
11232 /* Get a list of all the fonts that match this name. Once we
11233 have a list of matching fonts, we compare them against the fonts
11234 we already have by comparing names. */
11235 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11236
11237 if (!NILP (font_names))
11238 {
11239 Lisp_Object tail;
11240 int i;
11241
11242 for (i = 0; i < dpyinfo->n_fonts; i++)
11243 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11244 if (dpyinfo->font_table[i].name
11245 && (!strcmp (dpyinfo->font_table[i].name,
d5db4077 11246 SDATA (XCAR (tail)))
1a578e9b 11247 || !strcmp (dpyinfo->font_table[i].full_name,
d5db4077 11248 SDATA (XCAR (tail)))))
1a578e9b
AC
11249 return (dpyinfo->font_table + i);
11250 }
11251
11252 /* Load the font and add it to the table. */
11253 {
11254 char *full_name;
11255 struct MacFontStruct *font;
11256 struct font_info *fontp;
11257 unsigned long value;
11258 int i;
11259
11260 /* If we have found fonts by x_list_font, load one of them. If
11261 not, we still try to load a font by the name given as FONTNAME
11262 because XListFonts (called in x_list_font) of some X server has
11263 a bug of not finding a font even if the font surely exists and
11264 is loadable by XLoadQueryFont. */
11265 if (size > 0 && !NILP (font_names))
d5db4077 11266 fontname = (char *) SDATA (XCAR (font_names));
1a578e9b
AC
11267
11268 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11269 if (!font)
11270 return NULL;
11271
11272 /* Find a free slot in the font table. */
11273 for (i = 0; i < dpyinfo->n_fonts; ++i)
11274 if (dpyinfo->font_table[i].name == NULL)
11275 break;
11276
11277 /* If no free slot found, maybe enlarge the font table. */
11278 if (i == dpyinfo->n_fonts
11279 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11280 {
11281 int sz;
11282 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11283 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11284 dpyinfo->font_table
11285 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11286 }
11287
11288 fontp = dpyinfo->font_table + i;
11289 if (i == dpyinfo->n_fonts)
11290 ++dpyinfo->n_fonts;
11291
11292 /* Now fill in the slots of *FONTP. */
11293 BLOCK_INPUT;
11294 fontp->font = font;
11295 fontp->font_idx = i;
11296 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11297 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11298
11299 fontp->full_name = fontp->name;
11300
11301 fontp->size = font->max_bounds.width;
11302 fontp->height = FONT_HEIGHT (font);
11303 {
11304 /* For some font, ascent and descent in max_bounds field is
11305 larger than the above value. */
11306 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11307 if (max_height > fontp->height)
11308 fontp->height = max_height;
11309 }
11310
11311 /* The slot `encoding' specifies how to map a character
11312 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11313 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11314 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11315 2:0xA020..0xFF7F). For the moment, we don't know which charset
11316 uses this font. So, we set information in fontp->encoding[1]
11317 which is never used by any charset. If mapping can't be
11318 decided, set FONT_ENCODING_NOT_DECIDED. */
11319 if (font->mac_scriptcode == smJapanese)
11320 fontp->encoding[1] = 4;
11321 else
11322 {
11323 fontp->encoding[1]
11324 = (font->max_byte1 == 0
11325 /* 1-byte font */
11326 ? (font->min_char_or_byte2 < 0x80
11327 ? (font->max_char_or_byte2 < 0x80
11328 ? 0 /* 0x20..0x7F */
11329 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11330 : 1) /* 0xA0..0xFF */
11331 /* 2-byte font */
11332 : (font->min_byte1 < 0x80
11333 ? (font->max_byte1 < 0x80
11334 ? (font->min_char_or_byte2 < 0x80
11335 ? (font->max_char_or_byte2 < 0x80
11336 ? 0 /* 0x2020..0x7F7F */
11337 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11338 : 3) /* 0x20A0..0x7FFF */
11339 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11340 : (font->min_char_or_byte2 < 0x80
11341 ? (font->max_char_or_byte2 < 0x80
11342 ? 2 /* 0xA020..0xFF7F */
11343 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11344 : 1))); /* 0xA0A0..0xFFFF */
11345 }
11346
11347#if 0 /* MAC_TODO: fill these out with more reasonably values */
11348 fontp->baseline_offset
11349 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11350 ? (long) value : 0);
11351 fontp->relative_compose
11352 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11353 ? (long) value : 0);
11354 fontp->default_ascent
11355 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11356 ? (long) value : 0);
11357#else
11358 fontp->baseline_offset = 0;
11359 fontp->relative_compose = 0;
11360 fontp->default_ascent = 0;
11361#endif
11362
11363 /* Set global flag fonts_changed_p to non-zero if the font loaded
11364 has a character with a smaller width than any other character
11365 before, or if the font loaded has a smalle>r height than any
11366 other font loaded before. If this happens, it will make a
11367 glyph matrix reallocation necessary. */
11368 fonts_changed_p = x_compute_min_glyph_bounds (f);
11369 UNBLOCK_INPUT;
11370 return fontp;
11371 }
11372}
11373
11374
11375/* Return a pointer to struct font_info of a font named FONTNAME for
11376 frame F. If no such font is loaded, return NULL. */
11377
11378struct font_info *
11379x_query_font (f, fontname)
11380 struct frame *f;
11381 register char *fontname;
11382{
11383 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11384 int i;
11385
11386 for (i = 0; i < dpyinfo->n_fonts; i++)
11387 if (dpyinfo->font_table[i].name
11388 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11389 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11390 return (dpyinfo->font_table + i);
11391 return NULL;
11392}
11393
11394
11395/* Find a CCL program for a font specified by FONTP, and set the member
11396 `encoder' of the structure. */
11397
11398void
11399x_find_ccl_program (fontp)
11400 struct font_info *fontp;
11401{
11402 Lisp_Object list, elt;
11403
11404 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11405 {
11406 elt = XCAR (list);
11407 if (CONSP (elt)
11408 && STRINGP (XCAR (elt))
11409 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11410 >= 0))
11411 break;
11412 }
11413 if (! NILP (list))
11414 {
11415 struct ccl_program *ccl
11416 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11417
11418 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11419 xfree (ccl);
11420 else
11421 fontp->font_encoder = ccl;
11422 }
11423}
11424
11425
11426\f
11427/***********************************************************************
11428 Initialization
11429 ***********************************************************************/
11430
11431#ifdef USE_X_TOOLKIT
11432static XrmOptionDescRec emacs_options[] = {
11433 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11434 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11435
11436 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11437 XrmoptionSepArg, NULL},
11438 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11439
11440 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11441 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11442 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11443 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11444 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11445 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11446 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11447};
11448#endif /* USE_X_TOOLKIT */
11449
11450static int x_initialized;
11451
11452#ifdef MULTI_KBOARD
11453/* Test whether two display-name strings agree up to the dot that separates
11454 the screen number from the server number. */
11455static int
11456same_x_server (name1, name2)
11457 char *name1, *name2;
11458{
11459 int seen_colon = 0;
d5db4077 11460 unsigned char *system_name = SDATA (Vsystem_name);
1a578e9b
AC
11461 int system_name_length = strlen (system_name);
11462 int length_until_period = 0;
11463
11464 while (system_name[length_until_period] != 0
11465 && system_name[length_until_period] != '.')
11466 length_until_period++;
11467
11468 /* Treat `unix' like an empty host name. */
11469 if (! strncmp (name1, "unix:", 5))
11470 name1 += 4;
11471 if (! strncmp (name2, "unix:", 5))
11472 name2 += 4;
11473 /* Treat this host's name like an empty host name. */
11474 if (! strncmp (name1, system_name, system_name_length)
11475 && name1[system_name_length] == ':')
11476 name1 += system_name_length;
11477 if (! strncmp (name2, system_name, system_name_length)
11478 && name2[system_name_length] == ':')
11479 name2 += system_name_length;
11480 /* Treat this host's domainless name like an empty host name. */
11481 if (! strncmp (name1, system_name, length_until_period)
11482 && name1[length_until_period] == ':')
e0f712ba
AC
11483 name1 += length_until_period;
11484 if (! strncmp (name2, system_name, length_until_period)
11485 && name2[length_until_period] == ':')
11486 name2 += length_until_period;
11487
11488 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11489 {
11490 if (*name1 == ':')
11491 seen_colon++;
11492 if (seen_colon && *name1 == '.')
11493 return 1;
11494 }
11495 return (seen_colon
11496 && (*name1 == '.' || *name1 == '\0')
11497 && (*name2 == '.' || *name2 == '\0'));
11498}
11499#endif
1a578e9b
AC
11500
11501
11502/* The Mac Event loop code */
11503
e0f712ba 11504#ifndef MAC_OSX
1a578e9b
AC
11505#include <Events.h>
11506#include <Quickdraw.h>
11507#include <Balloons.h>
11508#include <Devices.h>
11509#include <Fonts.h>
11510#include <Gestalt.h>
11511#include <Menus.h>
11512#include <Processes.h>
11513#include <Sound.h>
11514#include <ToolUtils.h>
11515#include <TextUtils.h>
11516#include <Dialogs.h>
11517#include <Script.h>
1a578e9b
AC
11518#include <Types.h>
11519#include <TextEncodingConverter.h>
11520#include <Resources.h>
11521
11522#if __MWERKS__
11523#include <unix.h>
11524#endif
e0f712ba 11525#endif /* ! MAC_OSX */
1a578e9b
AC
11526
11527#define M_APPLE 128
11528#define I_ABOUT 1
11529
11530#define WINDOW_RESOURCE 128
11531#define TERM_WINDOW_RESOURCE 129
11532
11533#define DEFAULT_NUM_COLS 80
11534
11535#define MIN_DOC_SIZE 64
11536#define MAX_DOC_SIZE 32767
11537
11538/* sleep time for WaitNextEvent */
11539#define WNE_SLEEP_AT_SUSPEND 10
11540#define WNE_SLEEP_AT_RESUME 1
11541
11542/* true when cannot handle any Mac OS events */
11543static int handling_window_update = 0;
11544
11545/* the flag appl_is_suspended is used both for determining the sleep
11546 time to be passed to WaitNextEvent and whether the cursor should be
11547 drawn when updating the display. The cursor is turned off when
11548 Emacs is suspended. Redrawing it is unnecessary and what needs to
11549 be done depends on whether the cursor lies inside or outside the
11550 redraw region. So we might as well skip drawing it when Emacs is
11551 suspended. */
11552static Boolean app_is_suspended = false;
11553static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11554
11555#define EXTRA_STACK_ALLOC (256 * 1024)
11556
11557#define ARGV_STRING_LIST_ID 129
11558#define ABOUT_ALERT_ID 128
2e875e36 11559#define RAM_TOO_LARGE_ALERT_ID 129
1a578e9b
AC
11560
11561Boolean terminate_flag = false;
11562
11563/* true if using command key as meta key */
11564Lisp_Object Vmac_command_key_is_meta;
11565
11566/* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11567 to this text encoding */
11568int mac_keyboard_text_encoding;
11569int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11570
11571/* Set in term/mac-win.el to indicate that event loop can now generate
11572 drag and drop events. */
8f47302e 11573Lisp_Object Qmac_ready_for_drag_n_drop;
1a578e9b
AC
11574
11575Lisp_Object drag_and_drop_file_list;
11576
11577Point saved_menu_event_location;
11578
11579/* Apple Events */
11580static void init_required_apple_events(void);
e0f712ba
AC
11581static pascal OSErr
11582do_ae_open_application(const AppleEvent *, AppleEvent *, long);
11583static pascal OSErr
11584do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
1a578e9b
AC
11585static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
11586static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
11587
11588extern void init_emacs_passwd_dir ();
11589extern int emacs_main (int, char **, char **);
11590extern void check_alarm ();
11591
11592extern void initialize_applescript();
11593extern void terminate_applescript();
11594
11595
11596static void
11597do_get_menus (void)
11598{
11599 Handle menubar_handle;
11600 MenuHandle menu_handle;
11601
11602 menubar_handle = GetNewMBar (128);
11603 if(menubar_handle == NULL)
11604 abort ();
11605 SetMenuBar (menubar_handle);
11606 DrawMenuBar ();
11607
11608 menu_handle = GetMenuHandle (M_APPLE);
11609 if(menu_handle != NULL)
11610 AppendResMenu (menu_handle,'DRVR');
11611 else
11612 abort ();
11613}
11614
11615
11616static void
11617do_init_managers (void)
11618{
e0f712ba 11619#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11620 InitGraf (&qd.thePort);
11621 InitFonts ();
11622 FlushEvents (everyEvent, 0);
11623 InitWindows ();
11624 InitMenus ();
11625 TEInit ();
11626 InitDialogs (NULL);
e0f712ba
AC
11627#endif /* !TARGET_API_MAC_CARBON */
11628 InitCursor ();
1a578e9b 11629
e0f712ba 11630#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11631 /* set up some extra stack space for use by emacs */
11632 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11633
11634 /* MaxApplZone must be called for AppleScript to execute more
11635 complicated scripts */
11636 MaxApplZone ();
11637 MoreMasters ();
e0f712ba 11638#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
11639}
11640
2e875e36
AC
11641static void
11642do_check_ram_size (void)
11643{
11644 SInt32 physical_ram_size, logical_ram_size;
11645
11646 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11647 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11648 || physical_ram_size > 256 * 1024 * 1024
11649 || logical_ram_size > 256 * 1024 * 1024)
11650 {
11651 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11652 exit (1);
11653 }
11654}
11655
1a578e9b
AC
11656static void
11657do_window_update (WindowPtr win)
11658{
11659 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11660 struct frame *f = mwp->mFP;
11661
11662 if (f)
11663 {
11664 if (f->async_visible == 0)
11665 {
11666 f->async_visible = 1;
11667 f->async_iconified = 0;
11668 SET_FRAME_GARBAGED (f);
11669
11670 /* An update event is equivalent to MapNotify on X, so report
11671 visibility changes properly. */
11672 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11673 /* Force a redisplay sooner or later to update the
11674 frame titles in case this is the second frame. */
11675 record_asynch_buffer_change ();
11676 }
11677 else
11678 {
11679 BeginUpdate (win);
11680 handling_window_update = 1;
11681
2d97ff8c
AC
11682 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
11683
1a578e9b
AC
11684 expose_frame (f, 0, 0, 0, 0);
11685
11686 handling_window_update = 0;
11687 EndUpdate (win);
11688 }
11689 }
11690}
11691
e0f712ba
AC
11692static int
11693is_emacs_window (WindowPtr win)
11694{
11695 Lisp_Object tail, frame;
11696
11697 if (!win)
11698 return 0;
11699
11700 FOR_EACH_FRAME (tail, frame)
11701 if (FRAME_MAC_P (XFRAME (frame)))
11702 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11703 return 1;
11704
11705 return 0;
11706}
11707
1a578e9b
AC
11708static void
11709do_window_activate (WindowPtr win)
11710{
e0f712ba
AC
11711 mac_output *mwp;
11712 struct frame *f;
1a578e9b 11713
e0f712ba 11714 if (is_emacs_window (win))
1a578e9b 11715 {
e0f712ba
AC
11716 mwp = (mac_output *) GetWRefCon (win);
11717 f = mwp->mFP;
11718
11719 if (f)
11720 {
11721 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11722 activate_scroll_bars (f);
11723 }
1a578e9b
AC
11724 }
11725}
11726
11727static void
11728do_window_deactivate (WindowPtr win)
11729{
e0f712ba
AC
11730 mac_output *mwp;
11731 struct frame *f;
1a578e9b 11732
e0f712ba 11733 if (is_emacs_window (win))
1a578e9b 11734 {
e0f712ba
AC
11735 mwp = (mac_output *) GetWRefCon (win);
11736 f = mwp->mFP;
11737
11738 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11739 {
11740 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11741 deactivate_scroll_bars (f);
11742 }
1a578e9b
AC
11743 }
11744}
11745
11746static void
11747do_app_resume ()
11748{
e0f712ba
AC
11749 WindowPtr wp;
11750 mac_output *mwp;
11751 struct frame *f;
fa0b4c14 11752
e0f712ba
AC
11753 wp = FrontWindow();
11754 if (is_emacs_window (wp))
1a578e9b 11755 {
e0f712ba
AC
11756 mwp = (mac_output *) GetWRefCon (wp);
11757 f = mwp->mFP;
11758
11759 if (f)
11760 {
11761 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11762 activate_scroll_bars (f);
11763 }
1a578e9b
AC
11764 }
11765
11766 app_is_suspended = false;
11767 app_sleep_time = WNE_SLEEP_AT_RESUME;
11768}
11769
11770static void
11771do_app_suspend ()
11772{
e0f712ba
AC
11773 WindowPtr wp;
11774 mac_output *mwp;
11775 struct frame *f;
1a578e9b 11776
e0f712ba
AC
11777 wp = FrontWindow();
11778 if (is_emacs_window (wp))
1a578e9b 11779 {
e0f712ba
AC
11780 mwp = (mac_output *) GetWRefCon (wp);
11781 f = mwp->mFP;
11782
11783 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11784 {
11785 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11786 deactivate_scroll_bars (f);
11787 }
1a578e9b
AC
11788 }
11789
11790 app_is_suspended = true;
11791 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11792}
11793
11794
11795static void
11796do_mouse_moved (Point mouse_pos)
11797{
11798 WindowPtr wp = FrontWindow ();
11799 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11800
e0f712ba
AC
11801#if TARGET_API_MAC_CARBON
11802 SetPort (GetWindowPort (wp));
11803#else
11804 SetPort (wp);
11805#endif
11806
1a578e9b
AC
11807 GlobalToLocal (&mouse_pos);
11808
11809 note_mouse_movement (f, &mouse_pos);
11810}
11811
11812
11813static void
11814do_os_event (EventRecord *erp)
11815{
11816 switch((erp->message >> 24) & 0x000000FF)
11817 {
11818 case suspendResumeMessage:
11819 if((erp->message & resumeFlag) == 1)
11820 do_app_resume ();
11821 else
11822 do_app_suspend ();
11823 break;
11824
e0f712ba 11825 case mouseMovedMessage:
1a578e9b
AC
11826 do_mouse_moved (erp->where);
11827 break;
11828 }
11829}
11830
11831static void
11832do_events (EventRecord *erp)
11833{
11834 switch (erp->what)
11835 {
11836 case updateEvt:
11837 do_window_update ((WindowPtr) erp->message);
11838 break;
11839
11840 case osEvt:
11841 do_os_event (erp);
11842 break;
11843
11844 case activateEvt:
11845 if ((erp->modifiers & activeFlag) != 0)
11846 do_window_activate ((WindowPtr) erp->message);
11847 else
11848 do_window_deactivate ((WindowPtr) erp->message);
11849 break;
11850 }
11851}
11852
11853static void
11854do_apple_menu (SInt16 menu_item)
11855{
e0f712ba 11856#if !TARGET_API_MAC_CARBON
1a578e9b
AC
11857 Str255 item_name;
11858 SInt16 da_driver_refnum;
11859
11860 if (menu_item == I_ABOUT)
11861 NoteAlert (ABOUT_ALERT_ID, NULL);
11862 else
11863 {
11864 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11865 da_driver_refnum = OpenDeskAcc (item_name);
11866 }
e0f712ba 11867#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
11868}
11869
11870void
11871do_menu_choice (SInt32 menu_choice)
11872{
11873 SInt16 menu_id, menu_item;
11874
11875 menu_id = HiWord (menu_choice);
11876 menu_item = LoWord (menu_choice);
11877
11878 if (menu_id == 0)
11879 return;
11880
11881 switch (menu_id)
11882 {
11883 case M_APPLE:
11884 do_apple_menu (menu_item);
11885 break;
11886
11887 default:
11888 {
11889 WindowPtr wp = FrontWindow ();
11890 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11891 MenuHandle menu = GetMenuHandle (menu_id);
11892 if (menu)
11893 {
11894 UInt32 refcon;
11895
11896 GetMenuItemRefCon (menu, menu_item, &refcon);
11897 menubar_selection_callback (f, refcon);
11898 }
11899 }
11900 }
11901
11902 HiliteMenu (0);
11903}
11904
11905
11906/* Handle drags in size box. Based on code contributed by Ben
11907 Mesander and IM - Window Manager A. */
11908
11909static void
11910do_grow_window (WindowPtr w, EventRecord *e)
11911{
11912 long grow_size;
11913 Rect limit_rect;
11914 int rows, columns;
11915 mac_output *mwp = (mac_output *) GetWRefCon (w);
11916 struct frame *f = mwp->mFP;
11917
11918 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11919
11920 grow_size = GrowWindow (w, e->where, &limit_rect);
11921
11922 /* see if it really changed size */
11923 if (grow_size != 0)
11924 {
11925 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11926 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11927
11928 x_set_window_size (f, 0, columns, rows);
11929 }
11930}
11931
11932
11933/* Handle clicks in zoom box. Calculation of "standard state" based
11934 on code in IM - Window Manager A and code contributed by Ben
11935 Mesander. The standard state of an Emacs window is 80-characters
11936 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11937
11938static void
11939do_zoom_window (WindowPtr w, int zoom_in_or_out)
11940{
11941 GrafPtr save_port;
11942 Rect zoom_rect, port_rect;
11943 Point top_left;
11944 int w_title_height, columns, rows, width, height, dummy, x, y;
11945 mac_output *mwp = (mac_output *) GetWRefCon (w);
11946 struct frame *f = mwp->mFP;
11947
11948 GetPort (&save_port);
e0f712ba
AC
11949
11950#if TARGET_API_MAC_CARBON
11951 SetPort (GetWindowPort (w));
11952#else
1a578e9b 11953 SetPort (w);
e0f712ba
AC
11954#endif
11955
11956 /* Clear window to avoid flicker. */
11957#if TARGET_API_MAC_CARBON
11958 {
11959 Rect r;
11960 BitMap bm;
11961
11962 GetWindowPortBounds (w, &r);
11963 EraseRect (&r);
11964
11965 if (zoom_in_or_out == inZoomOut)
11966 {
11967 /* calculate height of window's title bar (hard card it for now). */
11968 w_title_height = 20 + GetMBarHeight ();
11969
11970 /* get maximum height of window into zoom_rect.bottom -
11971 zoom_rect.top */
11972 GetQDGlobalsScreenBits (&bm);
11973 zoom_rect = bm.bounds;
11974 zoom_rect.top += w_title_height;
11975 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11976
11977 zoom_rect.right = zoom_rect.left
11978 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11979
11980 SetWindowStandardState (w, &zoom_rect);
11981 }
11982 }
11983#else /* not TARGET_API_MAC_CARBON */
11984 EraseRect (&(w->portRect));
1a578e9b
AC
11985 if (zoom_in_or_out == inZoomOut)
11986 {
e0f712ba 11987 SetPt (&top_left, w->portRect.left, w->portRect.top);
1a578e9b
AC
11988 LocalToGlobal (&top_left);
11989
11990 /* calculate height of window's title bar */
11991 w_title_height = top_left.v - 1
e0f712ba 11992 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
1a578e9b
AC
11993
11994 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
11995 zoom_rect = qd.screenBits.bounds;
11996 zoom_rect.top += w_title_height;
11997 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11998
11999 zoom_rect.right = zoom_rect.left
12000 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12001
e0f712ba
AC
12002 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
12003 = zoom_rect;
1a578e9b 12004 }
e0f712ba 12005#endif /* not TARGET_API_MAC_CARBON */
1a578e9b 12006
e0f712ba 12007 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
1a578e9b
AC
12008
12009 /* retrieve window size and update application values */
e0f712ba
AC
12010#if TARGET_API_MAC_CARBON
12011 GetWindowPortBounds (w, &port_rect);
12012#else
1a578e9b 12013 port_rect = w->portRect;
e0f712ba 12014#endif
1a578e9b
AC
12015 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
12016 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
12017 x_set_window_size (mwp->mFP, 0, columns, rows);
12018
12019 SetPort (save_port);
12020}
12021
12022
12023/* Intialize AppleEvent dispatcher table for the required events. */
12024void
12025init_required_apple_events ()
12026{
12027 OSErr err;
12028 long result;
12029
12030 /* Make sure we have apple events before starting. */
12031 err = Gestalt (gestaltAppleEventsAttr, &result);
12032 if (err != noErr)
12033 abort ();
12034
12035 if (!(result & (1 << gestaltAppleEventsPresent)))
12036 abort ();
12037
e0f712ba 12038#if TARGET_API_MAC_CARBON
1a578e9b 12039 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
e0f712ba
AC
12040 NewAEEventHandlerUPP
12041 ((AEEventHandlerProcPtr) do_ae_open_application),
1a578e9b 12042 0L, false);
e0f712ba
AC
12043#else
12044 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12045 NewAEEventHandlerProc
12046 ((AEEventHandlerProcPtr) do_ae_open_application),
12047 0L, false);
12048#endif
1a578e9b
AC
12049 if (err != noErr)
12050 abort ();
e0f712ba
AC
12051
12052#if TARGET_API_MAC_CARBON
12053 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12054 NewAEEventHandlerUPP
12055 ((AEEventHandlerProcPtr) do_ae_open_documents),
12056 0L, false);
12057#else
1a578e9b 12058 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
e0f712ba
AC
12059 NewAEEventHandlerProc
12060 ((AEEventHandlerProcPtr) do_ae_open_documents),
1a578e9b 12061 0L, false);
e0f712ba 12062#endif
1a578e9b
AC
12063 if (err != noErr)
12064 abort ();
12065
e0f712ba
AC
12066#if TARGET_API_MAC_CARBON
12067 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12068 NewAEEventHandlerUPP
12069 ((AEEventHandlerProcPtr) do_ae_print_documents),
12070 0L, false);
12071#else
1a578e9b 12072 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
e0f712ba
AC
12073 NewAEEventHandlerProc
12074 ((AEEventHandlerProcPtr) do_ae_print_documents),
1a578e9b 12075 0L, false);
e0f712ba 12076#endif
1a578e9b
AC
12077 if (err != noErr)
12078 abort ();
12079
e0f712ba
AC
12080#if TARGET_API_MAC_CARBON
12081 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12082 NewAEEventHandlerUPP
12083 ((AEEventHandlerProcPtr) do_ae_quit_application),
12084 0L, false);
12085#else
1a578e9b 12086 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
e0f712ba
AC
12087 NewAEEventHandlerProc
12088 ((AEEventHandlerProcPtr) do_ae_quit_application),
1a578e9b 12089 0L, false);
e0f712ba 12090#endif
1a578e9b
AC
12091 if (err != noErr)
12092 abort ();
12093}
12094
12095
12096/* Open Application Apple Event */
12097static pascal OSErr
12098do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12099{
12100 return noErr;
12101}
12102
12103
12104/* Defined in mac.c. */
12105extern int
12106path_from_vol_dir_name (char *, int, short, long, char *);
12107
12108
12109/* Called when we receive an AppleEvent with an ID of
12110 "kAEOpenDocuments". This routine gets the direct parameter,
12111 extracts the FSSpecs in it, and puts their names on a list. */
12112static pascal OSErr
12113do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12114{
12115 OSErr err, err2;
12116 AEDesc the_desc;
12117 AEKeyword keyword;
12118 DescType actual_type;
12119 Size actual_size;
12120
12121 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12122 if (err != noErr)
12123 goto descriptor_error_exit;
12124
12125 /* Check to see that we got all of the required parameters from the
12126 event descriptor. For an 'odoc' event this should just be the
12127 file list. */
12128 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12129 &actual_type, (Ptr) &keyword,
12130 sizeof (keyword), &actual_size);
12131 /* No error means that we found some unused parameters.
12132 errAEDescNotFound means that there are no more parameters. If we
12133 get an error code other than that, flag it. */
12134 if ((err == noErr) || (err != errAEDescNotFound))
12135 {
12136 err = errAEEventNotHandled;
12137 goto error_exit;
12138 }
12139 err = noErr;
12140
12141 /* Got all the parameters we need. Now, go through the direct
12142 object list and parse it up. */
12143 {
12144 long num_files_to_open;
12145
12146 err = AECountItems (&the_desc, &num_files_to_open);
12147 if (err == noErr)
12148 {
12149 int i;
12150
12151 /* AE file list is one based so just use that for indexing here. */
bc21bf11
AC
12152 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
12153 {
12154 FSSpec fs;
12155 Str255 path_name, unix_path_name;
12156#ifdef MAC_OSX
12157 FSRef fref;
12158#endif
12159
12160 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12161 (Ptr) &fs, sizeof (fs), &actual_size);
12162 if (err != noErr) break;
12163
12164#ifdef MAC_OSX
12165 err = FSpMakeFSRef (&fs, &fref);
12166 if (err != noErr) break;
12167
12168 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12169#else
12170 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12171 fs.name) &&
12172 mac_to_posix_pathname (path_name, unix_path_name, 255))
12173#endif
12174 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12175 drag_and_drop_file_list);
12176 }
1a578e9b
AC
12177 }
12178 }
12179
12180error_exit:
12181 /* Nuke the coerced file list in any case */
12182 err2 = AEDisposeDesc(&the_desc);
12183
12184descriptor_error_exit:
12185 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12186 return err;
12187}
12188
12189
12190/* Print Document Apple Event */
12191static pascal OSErr
12192do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12193{
12194 return errAEEventNotHandled;
12195}
12196
12197
12198static pascal OSErr
12199do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12200{
12201 /* FixMe: Do we need an unwind-protect or something here? And what
12202 do we do about unsaved files. Currently just forces quit rather
12203 than doing recursive callback to get user input. */
12204
12205 terminate_flag = true;
12206
12207 /* Fkill_emacs doesn't return. We have to return. (TI) */
12208 return noErr;
12209}
12210
12211
12212#if __profile__
12213void
12214profiler_exit_proc ()
12215{
12216 ProfilerDump ("\pEmacs.prof");
12217 ProfilerTerm ();
12218}
12219#endif
12220
12221/* These few functions implement Emacs as a normal Mac application
8c1cc9e8 12222 (almost): set up the heap and the Toolbox, handle necessary
1a578e9b
AC
12223 system events plus a few simple menu events. They also set up
12224 Emacs's access to functions defined in the rest of this file.
12225 Emacs uses function hooks to perform all its terminal I/O. A
12226 complete list of these functions appear in termhooks.h. For what
12227 they do, read the comments there and see also w32term.c and
12228 xterm.c. What's noticeably missing here is the event loop, which
12229 is normally present in most Mac application. After performing the
12230 necessary Mac initializations, main passes off control to
12231 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12232 mac_read_socket (defined further below) to read input. This is
12233 where WaitNextEvent is called to process Mac events. This is also
12234 where check_alarm in sysdep.c is called to simulate alarm signals.
12235 This makes the cursor jump back to its correct position after
12236 briefly jumping to that of the matching parenthesis, print useful
12237 hints and prompts in the minibuffer after the user stops typing for
12238 a wait, etc. */
12239
e0f712ba 12240#if !TARGET_API_MAC_CARBON
1a578e9b
AC
12241#undef main
12242int
12243main (void)
12244{
12245#if __profile__ /* is the profiler on? */
12246 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12247 exit(1);
12248#endif
12249
12250#if __MWERKS__
12251 /* set creator and type for files created by MSL */
12252 _fcreator = 'EMAx';
12253 _ftype = 'TEXT';
12254#endif
12255
12256 do_init_managers ();
12257
12258 do_get_menus ();
12259
2e875e36
AC
12260 do_check_ram_size ();
12261
1a578e9b
AC
12262 init_emacs_passwd_dir ();
12263
12264 init_environ ();
12265
12266 initialize_applescript ();
12267
12268 init_required_apple_events ();
12269
12270 {
12271 char **argv;
12272 int argc = 0;
12273
12274 /* set up argv array from STR# resource */
12275 get_string_list (&argv, ARGV_STRING_LIST_ID);
12276 while (argv[argc])
12277 argc++;
12278
12279 /* free up AppleScript resources on exit */
12280 atexit (terminate_applescript);
12281
12282#if __profile__ /* is the profiler on? */
12283 atexit (profiler_exit_proc);
12284#endif
12285
12286 /* 3rd param "envp" never used in emacs_main */
12287 (void) emacs_main (argc, argv, 0);
12288 }
12289
12290 /* Never reached - real exit in Fkill_emacs */
12291 return 0;
12292}
e0f712ba 12293#endif
1a578e9b
AC
12294
12295/* Table for translating Mac keycode to X keysym values. Contributed
12296 by Sudhir Shenoy. */
12297static unsigned char keycode_to_xkeysym_table[] = {
12298/* 0x00 - 0x3f */
12299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12302 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12303/* 0x40 */
e0f712ba
AC
12304 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12305 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12306 0, 0, 0, '\xaf' /* kp/ */,
12307 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
1a578e9b 12308/* 0x50 */
e0f712ba
AC
12309 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12310 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12311 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12312 '\xb9' /* kp9 */, 0, 0, 0,
1a578e9b 12313/* 0x60 */
e0f712ba
AC
12314 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12315 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12316 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12317 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
1a578e9b 12318/* 0x70 */
e0f712ba
AC
12319 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12320 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12321 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12322 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
1a578e9b
AC
12323};
12324
12325static int
12326keycode_to_xkeysym (int keyCode, int *xKeySym)
12327{
12328 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12329 return *xKeySym != 0;
12330}
12331
12332/* Emacs calls this whenever it wants to read an input event from the
12333 user. */
12334int
12335XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12336{
12337 int count = 0;
12338 EventRecord er;
12339 int the_modifiers;
12340 EventMask event_mask;
12341
e0f712ba 12342#if 0
1a578e9b
AC
12343 if (interrupt_input_blocked)
12344 {
12345 interrupt_input_pending = 1;
12346 return -1;
12347 }
e0f712ba 12348#endif
1a578e9b
AC
12349
12350 interrupt_input_pending = 0;
12351 BLOCK_INPUT;
12352
12353 /* So people can tell when we have read the available input. */
12354 input_signal_count++;
12355
12356 if (numchars <= 0)
12357 abort ();
12358
12359 /* Don't poll for events to process (specifically updateEvt) if
12360 window update currently already in progress. A call to redisplay
12361 (in do_window_update) can be preempted by another call to
12362 redisplay, causing blank regions to be left on the screen and the
12363 cursor to be left at strange places. */
12364 if (handling_window_update)
12365 {
12366 UNBLOCK_INPUT;
12367 return 0;
12368 }
12369
12370 if (terminate_flag)
12371 Fkill_emacs (make_number (1));
12372
12373 /* It is necessary to set this (additional) argument slot of an
12374 event to nil because keyboard.c protects incompletely processed
12375 event from being garbage collected by placing them in the
12376 kbd_buffer_gcpro vector. */
12377 bufp->arg = Qnil;
12378
12379 event_mask = everyEvent;
8f47302e 12380 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
1a578e9b
AC
12381 event_mask -= highLevelEventMask;
12382
c7764932 12383 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
1a578e9b
AC
12384 switch (er.what)
12385 {
12386 case mouseDown:
12387 case mouseUp:
12388 {
12389 WindowPtr window_ptr = FrontWindow ();
12390 SInt16 part_code;
12391
12392 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12393 && er.what == mouseUp)
12394 {
12395 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12396 Point mouse_loc = er.where;
12397
12398 /* Convert to local coordinates of new window. */
e0f712ba
AC
12399#if TARGET_API_MAC_CARBON
12400 SetPort (GetWindowPort (window_ptr));
12401#else
12402 SetPort (window_ptr);
12403#endif
12404
1a578e9b
AC
12405 GlobalToLocal (&mouse_loc);
12406
12407 bufp->code = 0; /* only one mouse button */
3b8f9651 12408 bufp->kind = SCROLL_BAR_CLICK_EVENT;
1a578e9b
AC
12409 bufp->frame_or_window = tracked_scroll_bar->window;
12410 bufp->part = scroll_bar_handle;
12411 bufp->modifiers = up_modifier;
12412 bufp->timestamp = er.when * (1000 / 60);
12413 /* ticks to milliseconds */
12414
12415 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12416 XSETINT (bufp->y, mouse_loc.v - 24);
12417 tracked_scroll_bar->dragging = Qnil;
12418 mouse_tracking_in_progress = mouse_tracking_none;
12419 tracked_scroll_bar = NULL;
12420 count++;
12421 break;
12422 }
12423
12424 part_code = FindWindow (er.where, &window_ptr);
12425
12426 switch (part_code)
12427 {
12428 case inMenuBar:
12429 {
12430 struct frame *f = ((mac_output *)
12431 GetWRefCon (FrontWindow ()))->mFP;
12432 saved_menu_event_location = er.where;
3b8f9651 12433 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
1a578e9b
AC
12434 XSETFRAME (bufp->frame_or_window, f);
12435 count++;
12436 }
12437 break;
12438
12439 case inContent:
12440 if (window_ptr != FrontWindow ())
12441 SelectWindow (window_ptr);
12442 else
12443 {
e0f712ba 12444 SInt16 control_part_code;
1a578e9b
AC
12445 ControlHandle ch;
12446 struct mac_output *mwp = (mac_output *)
12447 GetWRefCon (window_ptr);
12448 Point mouse_loc = er.where;
12449
12450 /* convert to local coordinates of new window */
e0f712ba
AC
12451#if TARGET_API_MAC_CARBON
12452 SetPort (GetWindowPort (window_ptr));
12453#else
12454 SetPort (window_ptr);
12455#endif
12456
1a578e9b 12457 GlobalToLocal (&mouse_loc);
e0f712ba
AC
12458#if TARGET_API_MAC_CARBON
12459 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12460 &control_part_code);
12461#else
1a578e9b 12462 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
e0f712ba 12463#endif
1a578e9b
AC
12464 bufp->code = 0; /* only one mouse button */
12465 XSETINT (bufp->x, mouse_loc.h);
12466 XSETINT (bufp->y, mouse_loc.v);
12467 bufp->timestamp = er.when * (1000 / 60);
12468 /* ticks to milliseconds */
e0f712ba
AC
12469
12470#if TARGET_API_MAC_CARBON
12471 if (ch != 0)
12472#else
1a578e9b 12473 if (control_part_code != 0)
e0f712ba 12474#endif
1a578e9b
AC
12475 {
12476 struct scroll_bar *bar = (struct scroll_bar *)
12477 GetControlReference (ch);
12478 x_scroll_bar_handle_click (bar, control_part_code, &er,
12479 bufp);
12480 if (er.what == mouseDown
12481 && control_part_code == kControlIndicatorPart)
12482 {
e0f712ba
AC
12483 mouse_tracking_in_progress
12484 = mouse_tracking_scroll_bar;
1a578e9b
AC
12485 tracked_scroll_bar = bar;
12486 }
12487 else
12488 {
12489 mouse_tracking_in_progress = mouse_tracking_none;
12490 tracked_scroll_bar = NULL;
12491 }
12492 }
12493 else
12494 {
3b8f9651 12495 bufp->kind = MOUSE_CLICK_EVENT;
1a578e9b
AC
12496 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12497 if (er.what == mouseDown)
e0f712ba
AC
12498 mouse_tracking_in_progress
12499 = mouse_tracking_mouse_movement;
1a578e9b 12500 else
e0f712ba 12501 mouse_tracking_in_progress = mouse_tracking_none;
1a578e9b
AC
12502 }
12503
12504 switch (er.what)
12505 {
12506 case mouseDown:
12507 bufp->modifiers = down_modifier;
12508 break;
12509 case mouseUp:
12510 bufp->modifiers = up_modifier;
12511 break;
12512 }
12513
12514 count++;
12515 }
12516 break;
12517
12518 case inDrag:
e0f712ba
AC
12519#if TARGET_API_MAC_CARBON
12520 {
12521 BitMap bm;
12522
12523 GetQDGlobalsScreenBits (&bm);
12524 DragWindow (window_ptr, er.where, &bm.bounds);
12525 }
12526#else /* not TARGET_API_MAC_CARBON */
1a578e9b 12527 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
e0f712ba 12528#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
12529 break;
12530
12531 case inGoAway:
12532 if (TrackGoAway (window_ptr, er.where))
12533 {
3b8f9651 12534 bufp->kind = DELETE_WINDOW_EVENT;
1a578e9b
AC
12535 XSETFRAME (bufp->frame_or_window,
12536 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12537 count++;
12538 }
12539 break;
12540
12541 /* window resize handling added --ben */
12542 case inGrow:
12543 do_grow_window(window_ptr, &er);
12544 break;
12545
12546 /* window zoom handling added --ben */
12547 case inZoomIn:
12548 case inZoomOut:
12549 if (TrackBox (window_ptr, er.where, part_code))
12550 do_zoom_window (window_ptr, part_code);
12551 break;
12552
12553 default:
12554 break;
12555 }
12556 }
12557 break;
12558
12559 case updateEvt:
12560 case osEvt:
12561 case activateEvt:
12562 do_events (&er);
12563 break;
12564
12565 case keyDown:
12566 case autoKey:
12567 {
12568 int keycode = (er.message & keyCodeMask) >> 8;
12569 int xkeysym;
12570
12571 ObscureCursor ();
12572
12573 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12574 {
12575 bufp->code = 0x7f;
3b8f9651 12576 bufp->kind = ASCII_KEYSTROKE_EVENT;
1a578e9b
AC
12577 }
12578 else if (keycode_to_xkeysym (keycode, &xkeysym))
12579 {
12580 bufp->code = 0xff00 | xkeysym;
3b8f9651 12581 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
1a578e9b
AC
12582 }
12583 else
12584 {
12585 if (er.modifiers
12586 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12587 {
12588 /* This code comes from Keyboard Resource, Appendix
12589 C of IM - Text. This is necessary since shift is
12590 ignored in KCHR table translation when option or
12591 command is pressed. */
12592 int new_modifiers = er.modifiers & 0xf600;
12593 /* mask off option and command */
12594 int new_keycode = keycode | new_modifiers;
12595 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12596 unsigned long some_state = 0;
12597 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12598 &some_state) & 0xff;
12599 }
12600 else
12601 bufp->code = er.message & charCodeMask;
3b8f9651 12602 bufp->kind = ASCII_KEYSTROKE_EVENT;
1a578e9b
AC
12603 }
12604 }
12605
12606 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12607 convert non-ASCII characters typed at the Mac keyboard
12608 (presumed to be in the Mac Roman encoding) to iso-latin-1
12609 encoding before they are passed to Emacs. This enables the
12610 Mac keyboard to be used to enter non-ASCII iso-latin-1
12611 characters directly. */
12612 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
3b8f9651 12613 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
1a578e9b
AC
12614 {
12615 static TECObjectRef converter = NULL;
12616 OSStatus the_err = noErr;
12617 OSStatus convert_status = noErr;
12618
12619 if (converter == NULL)
12620 {
12621 the_err = TECCreateConverter (&converter,
12622 kTextEncodingMacRoman,
12623 mac_keyboard_text_encoding);
e0f712ba
AC
12624 current_mac_keyboard_text_encoding
12625 = mac_keyboard_text_encoding;
1a578e9b 12626 }
e0f712ba
AC
12627 else if (mac_keyboard_text_encoding
12628 != current_mac_keyboard_text_encoding)
1a578e9b
AC
12629 {
12630 /* Free the converter for the current encoding before
12631 creating a new one. */
12632 TECDisposeConverter (converter);
12633 the_err = TECCreateConverter (&converter,
12634 kTextEncodingMacRoman,
12635 mac_keyboard_text_encoding);
e0f712ba
AC
12636 current_mac_keyboard_text_encoding
12637 = mac_keyboard_text_encoding;
1a578e9b
AC
12638 }
12639
12640 if (the_err == noErr)
12641 {
12642 unsigned char ch = bufp->code;
12643 ByteCount actual_input_length, actual_output_length;
12644 unsigned char outch;
12645
12646 convert_status = TECConvertText (converter, &ch, 1,
12647 &actual_input_length,
12648 &outch, 1,
12649 &actual_output_length);
12650 if (convert_status == noErr
12651 && actual_input_length == 1
12652 && actual_output_length == 1)
12653 bufp->code = outch;
12654 }
12655 }
12656
12657 the_modifiers = 0;
12658 if (er.modifiers & shiftKey)
12659 the_modifiers |= shift_modifier;
12660 if (er.modifiers & controlKey)
12661 the_modifiers |= ctrl_modifier;
b432b442
AC
12662 /* Use option or command key as meta depending on value of
12663 mac-command-key-is-meta. */
1a578e9b
AC
12664 if (er.modifiers
12665 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12666 the_modifiers |= meta_modifier;
b432b442
AC
12667
12668 /* If the Mac option key is meta, then make Emacs recognize
12669 the Mac command key as alt. */
12670 if (NILP (Vmac_command_key_is_meta) && (er.modifiers & cmdKey))
12671 the_modifiers |= alt_modifier;
12672
1a578e9b
AC
12673 bufp->modifiers = the_modifiers;
12674
12675 {
b6cce0b7
AC
12676 mac_output *mwp
12677 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
1a578e9b
AC
12678 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12679 }
12680
12681 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
12682
12683 count++;
12684 break;
12685
12686 case kHighLevelEvent:
12687 drag_and_drop_file_list = Qnil;
8f47302e 12688
1a578e9b
AC
12689 AEProcessAppleEvent(&er);
12690
3b8f9651 12691 /* Build a DRAG_N_DROP_EVENT type event as is done in
1a578e9b
AC
12692 constuct_drag_n_drop in w32term.c. */
12693 if (!NILP (drag_and_drop_file_list))
12694 {
12695 struct frame *f;
12696 WindowPtr wp;
12697 Lisp_Object frame;
12698
12699 wp = FrontWindow ();
12700 if (!wp)
12701 f = NULL;
12702 else
12703 f = ((mac_output *) GetWRefCon (wp))->mFP;
12704
3b8f9651 12705 bufp->kind = DRAG_N_DROP_EVENT;
1a578e9b
AC
12706 bufp->code = 0;
12707 bufp->timestamp = er.when * (1000 / 60);
12708 /* ticks to milliseconds */
12709 bufp->modifiers = 0;
12710
12711 XSETINT (bufp->x, 0);
12712 XSETINT (bufp->y, 0);
12713
12714 XSETFRAME (frame, f);
12715 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
12716
12717 /* Regardless of whether Emacs was suspended or in the
12718 foreground, ask it to redraw its entire screen.
12719 Otherwise parts of the screen can be left in an
12720 inconsistent state. */
12721 if (wp)
e0f712ba
AC
12722#if TARGET_API_MAC_CARBON
12723 {
12724 Rect r;
12725
12726 GetWindowPortBounds (wp, &r);
12727 InvalWindowRect (wp, &r);
12728 }
12729#else /* not TARGET_API_MAC_CARBON */
1a578e9b 12730 InvalRect (&(wp->portRect));
e0f712ba 12731#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
12732
12733 count++;
12734 }
12735
12736 default:
12737 break;
12738 }
12739
12740 /* If the focus was just given to an autoraising frame,
12741 raise it now. */
12742 /* ??? This ought to be able to handle more than one such frame. */
12743 if (pending_autoraise_frame)
12744 {
12745 x_raise_frame (pending_autoraise_frame);
12746 pending_autoraise_frame = 0;
12747 }
12748
e0f712ba 12749#if !TARGET_API_MAC_CARBON
1a578e9b 12750 check_alarm (); /* simulate the handling of a SIGALRM */
e0f712ba 12751#endif
1a578e9b
AC
12752
12753 {
12754 static Point old_mouse_pos = { -1, -1 };
12755
12756 if (app_is_suspended)
12757 {
12758 old_mouse_pos.h = -1;
12759 old_mouse_pos.v = -1;
12760 }
12761 else
12762 {
12763 Point mouse_pos;
e0f712ba
AC
12764 WindowPtr wp;
12765 struct frame *f;
1a578e9b
AC
12766 Lisp_Object bar;
12767 struct scroll_bar *sb;
12768
e0f712ba
AC
12769 wp = FrontWindow ();
12770 if (is_emacs_window (wp))
12771 {
12772 f = ((mac_output *) GetWRefCon (wp))->mFP;
1a578e9b 12773
e0f712ba
AC
12774#if TARGET_API_MAC_CARBON
12775 SetPort (GetWindowPort (wp));
12776#else
12777 SetPort (wp);
12778#endif
12779
12780 GetMouse (&mouse_pos);
12781
12782 if (!EqualPt (mouse_pos, old_mouse_pos))
12783 {
12784 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12785 && tracked_scroll_bar)
12786 x_scroll_bar_note_movement (tracked_scroll_bar,
12787 mouse_pos.v
12788 - XINT (tracked_scroll_bar->top),
12789 TickCount() * (1000 / 60));
12790 else
12791 note_mouse_movement (f, &mouse_pos);
12792
12793 old_mouse_pos = mouse_pos;
12794 }
12795 }
1a578e9b
AC
12796 }
12797 }
12798
12799 UNBLOCK_INPUT;
12800
12801 return count;
12802}
12803
12804
12805/* Need to override CodeWarrior's input function so no conversion is
12806 done on newlines Otherwise compiled functions in .elc files will be
12807 read incorrectly. Defined in ...:MSL C:MSL
12808 Common:Source:buffer_io.c. */
12809#ifdef __MWERKS__
12810void
12811__convert_to_newlines (unsigned char * p, size_t * n)
12812{
12813#pragma unused(p,n)
12814}
12815
12816void
12817__convert_from_newlines (unsigned char * p, size_t * n)
12818{
12819#pragma unused(p,n)
12820}
12821#endif
12822
12823
12824/* Initialize the struct pointed to by MW to represent a new COLS x
12825 ROWS Macintosh window, using font with name FONTNAME and size
12826 FONTSIZE. */
12827void
12828NewMacWindow (FRAME_PTR fp)
12829{
12830 mac_output *mwp;
e0f712ba
AC
12831#if TARGET_API_MAC_CARBON
12832 static int making_terminal_window = 0;
12833#else
1a578e9b 12834 static int making_terminal_window = 1;
e0f712ba 12835#endif
1a578e9b
AC
12836
12837 mwp = fp->output_data.mac;
12838
12839 if (making_terminal_window)
12840 {
12841 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
12842 (WindowPtr) -1)))
12843 abort ();
12844 making_terminal_window = 0;
12845 }
12846 else
12847 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
12848 abort ();
12849
12850
12851 SetWRefCon (mwp->mWP, (long) mwp);
12852 /* so that update events can find this mac_output struct */
12853 mwp->mFP = fp; /* point back to emacs frame */
12854
e0f712ba
AC
12855#if TARGET_API_MAC_CARBON
12856 SetPort (GetWindowPort (mwp->mWP));
12857#else
1a578e9b 12858 SetPort (mwp->mWP);
e0f712ba 12859#endif
1a578e9b
AC
12860
12861 mwp->fontset = -1;
12862
12863 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
12864 ShowWindow (mwp->mWP);
12865
12866}
12867
12868
12869void make_mac_frame (struct frame *f)
12870{
12871 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12872 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12873
12874 NewMacWindow(f);
1a578e9b
AC
12875
12876 f->output_data.mac->cursor_pixel = 0;
12877 f->output_data.mac->border_pixel = 0x00ff00;
12878 f->output_data.mac->mouse_pixel = 0xff00ff;
12879 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12880
12881 f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
12882
12883 f->output_data.mac->fontset = -1;
12884 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12885 f->output_data.mac->scroll_bar_background_pixel = -1;
12886 f->output_data.mac->left_pos = 4;
12887 f->output_data.mac->top_pos = 4;
12888 f->output_data.mac->border_width = 0;
12889 f->output_data.mac->explicit_parent = 0;
12890
12891 f->output_data.mac->internal_border_width = 0;
12892
12893 f->output_method = output_mac;
12894
12895 f->auto_raise = 1;
12896 f->auto_lower = 1;
12897
12898 f->new_width = 0;
12899 f->new_height = 0;
12900}
12901
12902void make_mac_terminal_frame (struct frame *f)
12903{
12904 Lisp_Object frame;
12905
12906 XSETFRAME (frame, f);
12907
12908 f->output_method = output_mac;
12909 f->output_data.mac = (struct mac_output *)
12910 xmalloc (sizeof (struct mac_output));
12911 bzero (f->output_data.mac, sizeof (struct mac_output));
12912 f->output_data.mac->fontset = -1;
12913 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12914 f->output_data.mac->scroll_bar_background_pixel = -1;
12915
12916 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12917
12918 f->width = 96;
12919 f->height = 4;
12920
12921 make_mac_frame (f);
e0f712ba
AC
12922
12923 x_make_gc (f);
1a578e9b 12924
e0f712ba
AC
12925 /* Need to be initialized for unshow_buffer in window.c. */
12926 selected_window = f->selected_window;
12927
1a578e9b
AC
12928 Fmodify_frame_parameters (frame,
12929 Fcons (Fcons (Qfont,
12930 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12931 Fmodify_frame_parameters (frame,
12932 Fcons (Fcons (Qforeground_color,
12933 build_string ("black")), Qnil));
12934 Fmodify_frame_parameters (frame,
12935 Fcons (Fcons (Qbackground_color,
12936 build_string ("white")), Qnil));
12937}
12938
e0f712ba
AC
12939\f
12940/***********************************************************************
12941 Initialization
12942 ***********************************************************************/
12943
12944#ifdef USE_X_TOOLKIT
12945static XrmOptionDescRec emacs_options[] = {
12946 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12947 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12948
12949 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12950 XrmoptionSepArg, NULL},
12951 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12952
12953 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12954 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12955 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12956 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12957 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12958 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12959 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12960};
12961#endif /* USE_X_TOOLKIT */
12962
12963#ifdef MULTI_KBOARD
12964/* Test whether two display-name strings agree up to the dot that separates
12965 the screen number from the server number. */
12966static int
12967same_x_server (name1, name2)
12968 char *name1, *name2;
12969{
12970 int seen_colon = 0;
d5db4077 12971 unsigned char *system_name = SDATA (Vsystem_name);
e0f712ba
AC
12972 int system_name_length = strlen (system_name);
12973 int length_until_period = 0;
12974
12975 while (system_name[length_until_period] != 0
12976 && system_name[length_until_period] != '.')
12977 length_until_period++;
12978
12979 /* Treat `unix' like an empty host name. */
12980 if (! strncmp (name1, "unix:", 5))
12981 name1 += 4;
12982 if (! strncmp (name2, "unix:", 5))
12983 name2 += 4;
12984 /* Treat this host's name like an empty host name. */
12985 if (! strncmp (name1, system_name, system_name_length)
12986 && name1[system_name_length] == ':')
12987 name1 += system_name_length;
12988 if (! strncmp (name2, system_name, system_name_length)
12989 && name2[system_name_length] == ':')
12990 name2 += system_name_length;
12991 /* Treat this host's domainless name like an empty host name. */
12992 if (! strncmp (name1, system_name, length_until_period)
12993 && name1[length_until_period] == ':')
12994 name1 += length_until_period;
12995 if (! strncmp (name2, system_name, length_until_period)
12996 && name2[length_until_period] == ':')
12997 name2 += length_until_period;
12998
12999 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13000 {
13001 if (*name1 == ':')
13002 seen_colon++;
13003 if (seen_colon && *name1 == '.')
13004 return 1;
13005 }
13006 return (seen_colon
13007 && (*name1 == '.' || *name1 == '\0')
13008 && (*name2 == '.' || *name2 == '\0'));
13009}
13010#endif
13011
13012int mac_initialized = 0;
13013
1a578e9b
AC
13014void
13015mac_initialize_display_info ()
13016{
13017 struct mac_display_info *dpyinfo = &one_mac_display_info;
13018 GDHandle main_device_handle;
13019
13020 bzero (dpyinfo, sizeof (*dpyinfo));
13021
13022 /* Put it on x_display_name_list. */
13023 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13024 x_display_name_list);
13025 dpyinfo->name_list_element = XCAR (x_display_name_list);
13026
e0f712ba
AC
13027#if 0
13028 dpyinfo->mac_id_name
d5db4077
KR
13029 = (char *) xmalloc (SCHARS (Vinvocation_name)
13030 + SCHARS (Vsystem_name)
e0f712ba
AC
13031 + 2);
13032 sprintf (dpyinfo->mac_id_name, "%s@%s",
d5db4077 13033 SDATA (Vinvocation_name), SDATA (Vsystem_name));
e0f712ba
AC
13034#else
13035 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13036 strcpy (dpyinfo->mac_id_name, "Mac Display");
13037#endif
13038
1a578e9b
AC
13039 main_device_handle = LMGetMainDevice();
13040
13041 dpyinfo->reference_count = 0;
13042 dpyinfo->resx = 75.0;
13043 dpyinfo->resy = 75.0;
13044 dpyinfo->n_planes = 1;
13045 dpyinfo->n_cbits = 16;
13046 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13047 dpyinfo->width = (**main_device_handle).gdRect.right;
13048 dpyinfo->grabbed = 0;
13049 dpyinfo->root_window = NULL;
13050
13051 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13052 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13053 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13054 dpyinfo->mouse_face_window = Qnil;
e0f712ba
AC
13055}
13056
13057struct mac_display_info *
13058mac_term_init (display_name, xrm_option, resource_name)
13059 Lisp_Object display_name;
13060 char *xrm_option;
13061 char *resource_name;
13062{
13063 struct mac_display_info *dpyinfo;
13064 GDHandle main_device_handle;
13065
13066 if (!mac_initialized)
13067 {
13068 mac_initialize ();
13069 mac_initialized = 1;
13070 }
13071
13072 mac_initialize_display_info (display_name);
13073
13074 dpyinfo = &one_mac_display_info;
13075
13076 main_device_handle = LMGetMainDevice();
13077
13078 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13079 dpyinfo->width = (**main_device_handle).gdRect.right;
1a578e9b 13080
e0f712ba 13081 return dpyinfo;
1a578e9b 13082}
e0f712ba
AC
13083\f
13084/* Set up use of X before we make the first connection. */
13085
13086static struct redisplay_interface x_redisplay_interface =
13087{
13088 x_produce_glyphs,
13089 x_write_glyphs,
13090 x_insert_glyphs,
13091 x_clear_end_of_line,
13092 x_scroll_run,
13093 x_after_update_window_line,
13094 x_update_window_begin,
13095 x_update_window_end,
13096 XTcursor_to,
13097 x_flush,
13098 x_clear_mouse_face,
13099 x_get_glyph_overhangs,
13100 x_fix_overlapping_area
13101};
1a578e9b
AC
13102
13103void
e0f712ba 13104mac_initialize ()
1a578e9b
AC
13105{
13106 rif = &x_redisplay_interface;
13107
13108 clear_frame_hook = x_clear_frame;
13109 ins_del_lines_hook = x_ins_del_lines;
1a578e9b
AC
13110 delete_glyphs_hook = x_delete_glyphs;
13111 ring_bell_hook = XTring_bell;
13112 reset_terminal_modes_hook = XTreset_terminal_modes;
13113 set_terminal_modes_hook = XTset_terminal_modes;
13114 update_begin_hook = x_update_begin;
13115 update_end_hook = x_update_end;
13116 set_terminal_window_hook = XTset_terminal_window;
13117 read_socket_hook = XTread_socket;
13118 frame_up_to_date_hook = XTframe_up_to_date;
1a578e9b
AC
13119 mouse_position_hook = XTmouse_position;
13120 frame_rehighlight_hook = XTframe_rehighlight;
13121 frame_raise_lower_hook = XTframe_raise_lower;
13122
13123 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13124 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13125 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13126 judge_scroll_bars_hook = XTjudge_scroll_bars;
13127
13128 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13129
e0f712ba
AC
13130 scroll_region_ok = 1; /* we'll scroll partial frames */
13131 char_ins_del_ok = 1;
13132 line_ins_del_ok = 1; /* we'll just blt 'em */
13133 fast_clear_end_of_line = 1; /* X does this well */
13134 memory_below_frame = 0; /* we don't remember what scrolls
1a578e9b
AC
13135 off the bottom */
13136 baud_rate = 19200;
13137
13138 x_noop_count = 0;
13139 last_tool_bar_item = -1;
13140 any_help_event_p = 0;
13141
13142 /* Try to use interrupt input; if we can't, then start polling. */
13143 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13144
13145#ifdef USE_X_TOOLKIT
13146 XtToolkitInitialize ();
13147 Xt_app_con = XtCreateApplicationContext ();
13148 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13149
13150 /* Install an asynchronous timer that processes Xt timeout events
13151 every 0.1s. This is necessary because some widget sets use
13152 timeouts internally, for example the LessTif menu bar, or the
13153 Xaw3d scroll bar. When Xt timouts aren't processed, these
13154 widgets don't behave normally. */
13155 {
13156 EMACS_TIME interval;
13157 EMACS_SET_SECS_USECS (interval, 0, 100000);
13158 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13159 }
13160#endif
13161
13162#if USE_TOOLKIT_SCROLL_BARS
13163 xaw3d_arrow_scroll = False;
13164 xaw3d_pick_top = True;
13165#endif
13166
13167#if 0
13168 /* Note that there is no real way portable across R3/R4 to get the
13169 original error handler. */
13170 XSetErrorHandler (x_error_handler);
13171 XSetIOErrorHandler (x_io_error_quitter);
13172
13173 /* Disable Window Change signals; they are handled by X events. */
13174#ifdef SIGWINCH
13175 signal (SIGWINCH, SIG_DFL);
13176#endif /* ! defined (SIGWINCH) */
13177
13178 signal (SIGPIPE, x_connection_signal);
13179#endif
13180
13181 mac_initialize_display_info ();
bc21bf11
AC
13182
13183#if TARGET_API_MAC_CARBON
13184 init_required_apple_events ();
13185
13186 DisableMenuCommand (NULL, kHICommandQuit);
13187#endif
1a578e9b
AC
13188}
13189
13190
13191void
13192syms_of_macterm ()
13193{
13194#if 0
13195 staticpro (&x_error_message_string);
13196 x_error_message_string = Qnil;
13197#endif
13198
13199 staticpro (&x_display_name_list);
13200 x_display_name_list = Qnil;
13201
13202 staticpro (&last_mouse_scroll_bar);
13203 last_mouse_scroll_bar = Qnil;
13204
13205 staticpro (&Qvendor_specific_keysyms);
13206 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13207
13208 staticpro (&last_mouse_press_frame);
13209 last_mouse_press_frame = Qnil;
13210
8f47302e
AC
13211 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13212 staticpro (&Qmac_ready_for_drag_n_drop);
13213
1a578e9b
AC
13214 help_echo = Qnil;
13215 staticpro (&help_echo);
13216 help_echo_object = Qnil;
13217 staticpro (&help_echo_object);
13218 help_echo_window = Qnil;
13219 staticpro (&help_echo_window);
13220 previous_help_echo = Qnil;
13221 staticpro (&previous_help_echo);
13222 help_echo_pos = -1;
13223
e0f712ba
AC
13224 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13225 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13226 x_autoselect_window_p = 0;
13227
1a578e9b 13228 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
e0f712ba
AC
13229 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13230For example, if a block cursor is over a tab, it will be drawn as
13231wide as that tab on the display. */);
1a578e9b
AC
13232 x_stretch_cursor_p = 0;
13233
e0f712ba
AC
13234#if 0 /* TODO: Setting underline position from font properties. */
13235 DEFVAR_BOOL ("x-use-underline-position-properties",
13236 &x_use_underline_position_properties,
13237 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13238nil means ignore them. If you encounter fonts with bogus
13239UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13240to 4.1, set this to nil. */);
13241 x_use_underline_position_properties = 1;
1a578e9b
AC
13242#endif
13243
e0f712ba
AC
13244 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13245 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13246 Vx_toolkit_scroll_bars = Qt;
13247
1a578e9b
AC
13248 staticpro (&last_mouse_motion_frame);
13249 last_mouse_motion_frame = Qnil;
13250
13251 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
e0f712ba
AC
13252 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13253Otherwise the option key is used. */);
1a578e9b
AC
13254 Vmac_command_key_is_meta = Qt;
13255
1a578e9b 13256 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
e0f712ba
AC
13257 doc: /* One of the Text Encoding Base constant values defined in the
13258Basic Text Constants section of Inside Macintosh - Text Encoding
13259Conversion Manager. Its value determines the encoding characters
13260typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13261will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13262its default value, no conversion takes place. If it is set to
13263kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13264characters typed on Mac keyboard are first converted into the
13265ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13266passed to Emacs. Together with Emacs's set-keyboard-coding-system
13267command, this enables the Mac keyboard to be used to enter non-ASCII
13268characters directly. */);
1a578e9b
AC
13269 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13270}