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