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