* dispextern.h: Change HAVE_CARBON to MAC_OS.
[bpt/emacs.git] / src / macterm.c
CommitLineData
1a578e9b 1/* Implementation of GUI terminal on the Mac OS.
181e6a61 2 Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
1a578e9b
AC
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
e0f712ba 21/* Contributed by Andrew Choi (akochoi@mac.com). */
1a578e9b
AC
22
23#include <config.h>
1a578e9b 24#include <signal.h>
1a578e9b 25#include <stdio.h>
e0f712ba 26#include <stdlib.h>
1a578e9b 27#include "lisp.h"
e0f712ba 28#include "charset.h"
1a578e9b
AC
29#include "blockinput.h"
30
1a578e9b
AC
31#include "macterm.h"
32
e0f712ba 33#ifndef MAC_OSX
1a578e9b 34#include <alloca.h>
e0f712ba 35#endif
1a578e9b 36
e0f712ba 37#ifdef MAC_OSX
742fbed7
AC
38/* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
39 obtain events from the event queue. If set to 0, WaitNextEvent is
40 used instead. */
41#define USE_CARBON_EVENTS 1
e0f712ba 42#else /* not MAC_OSX */
1a578e9b
AC
43#include <Quickdraw.h>
44#include <ToolUtils.h>
45#include <Sound.h>
46#include <Events.h>
47#include <Script.h>
48#include <Resources.h>
49#include <Fonts.h>
50#include <TextUtils.h>
51#include <LowMem.h>
52#include <Controls.h>
bf06c82f 53#include <Windows.h>
e0f712ba 54#if defined (__MRC__) || (__MSL__ >= 0x6000)
1a578e9b
AC
55#include <ControlDefinitions.h>
56#endif
57
58#if __profile__
59#include <profiler.h>
60#endif
e0f712ba 61#endif /* not MAC_OSX */
1a578e9b
AC
62
63#include "systty.h"
64#include "systime.h"
e0f712ba
AC
65#include "atimer.h"
66#include "keymap.h"
1a578e9b 67
1a578e9b
AC
68#include <ctype.h>
69#include <errno.h>
70#include <setjmp.h>
71#include <sys/stat.h>
72
e0f712ba 73#include "keyboard.h"
1a578e9b
AC
74#include "frame.h"
75#include "dispextern.h"
76#include "fontset.h"
77#include "termhooks.h"
78#include "termopts.h"
79#include "termchar.h"
80#include "gnu.h"
81#include "disptab.h"
82#include "buffer.h"
83#include "window.h"
1a578e9b 84#include "intervals.h"
e0f712ba 85#include "composite.h"
1a578e9b
AC
86#include "coding.h"
87
742fbed7
AC
88/* Set of macros that handle mapping of Mac modifier keys to emacs. */
89#define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
90 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
91#define macShiftKey (shiftKey)
92#define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
93 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
94 : controlKey)
95#define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
96
1a578e9b 97\f
1a578e9b 98
e0f712ba 99/* Non-nil means Emacs uses toolkit scroll bars. */
1a578e9b 100
e0f712ba 101Lisp_Object Vx_toolkit_scroll_bars;
1a578e9b 102
1a578e9b
AC
103/* Non-zero means that a HELP_EVENT has been generated since Emacs
104 start. */
105
106static int any_help_event_p;
107
e0f712ba
AC
108/* Non-zero means autoselect window with the mouse cursor. */
109
110int x_autoselect_window_p;
111
d243e605
AC
112/* Non-zero means make use of UNDERLINE_POSITION font properties. */
113
114int x_use_underline_position_properties;
115
1a578e9b
AC
116/* Non-zero means draw block and hollow cursor as wide as the glyph
117 under it. For example, if a block cursor is over a tab, it will be
118 drawn as wide as that tab on the display. */
119
e0f712ba 120
1a578e9b
AC
121/* This is a chain of structures for all the X displays currently in
122 use. */
123
124struct x_display_info *x_display_list;
125
126/* This is a list of cons cells, each of the form (NAME
127 . FONT-LIST-CACHE), one for each element of x_display_list and in
128 the same order. NAME is the name of the frame. FONT-LIST-CACHE
129 records previous values returned by x-list-fonts. */
130
131Lisp_Object x_display_name_list;
132
133/* This is display since Mac does not support multiple ones. */
134struct mac_display_info one_mac_display_info;
135
136/* Frame being updated by update_frame. This is declared in term.c.
137 This is set by update_begin and looked at by all the XT functions.
138 It is zero while not inside an update. In that case, the XT
139 functions assume that `selected_frame' is the frame to apply to. */
140
141extern struct frame *updating_frame;
142
e0f712ba
AC
143extern int waiting_for_input;
144
1a578e9b
AC
145/* This is a frame waiting to be auto-raised, within XTread_socket. */
146
147struct frame *pending_autoraise_frame;
148
1a578e9b
AC
149/* Non-zero means user is interacting with a toolkit scroll bar. */
150
151static int toolkit_scroll_bar_interaction;
152
153/* Mouse movement.
154
155 Formerly, we used PointerMotionHintMask (in standard_event_mask)
156 so that we would have to call XQueryPointer after each MotionNotify
157 event to ask for another such event. However, this made mouse tracking
158 slow, and there was a bug that made it eventually stop.
159
160 Simply asking for MotionNotify all the time seems to work better.
161
162 In order to avoid asking for motion events and then throwing most
163 of them away or busy-polling the server for mouse positions, we ask
164 the server for pointer motion hints. This means that we get only
165 one event per group of mouse movements. "Groups" are delimited by
166 other kinds of events (focus changes and button clicks, for
167 example), or by XQueryPointer calls; when one of these happens, we
168 get another MotionNotify event the next time the mouse moves. This
169 is at least as efficient as getting motion events when mouse
170 tracking is on, and I suspect only negligibly worse when tracking
171 is off. */
172
173/* Where the mouse was last time we reported a mouse event. */
174
1a578e9b
AC
175static Rect last_mouse_glyph;
176static Lisp_Object last_mouse_press_frame;
177
178/* The scroll bar in which the last X motion event occurred.
179
180 If the last X motion event occurred in a scroll bar, we set this so
181 XTmouse_position can know whether to report a scroll bar motion or
182 an ordinary motion.
183
184 If the last X motion event didn't occur in a scroll bar, we set
185 this to Qnil, to tell XTmouse_position to return an ordinary motion
186 event. */
187
188static Lisp_Object last_mouse_scroll_bar;
189
190/* This is a hack. We would really prefer that XTmouse_position would
191 return the time associated with the position it returns, but there
192 doesn't seem to be any way to wrest the time-stamp from the server
193 along with the position query. So, we just keep track of the time
194 of the last movement we received, and return that in hopes that
195 it's somewhat accurate. */
196
197static Time last_mouse_movement_time;
198
1a578e9b
AC
199struct scroll_bar *tracked_scroll_bar = NULL;
200
201/* Incremented by XTread_socket whenever it really tries to read
202 events. */
203
204#ifdef __STDC__
205static int volatile input_signal_count;
206#else
207static int input_signal_count;
208#endif
209
210/* Used locally within XTread_socket. */
211
212static int x_noop_count;
213
214/* Initial values of argv and argc. */
215
216extern char **initial_argv;
217extern int initial_argc;
218
219extern Lisp_Object Vcommand_line_args, Vsystem_name;
220
221/* Tells if a window manager is present or not. */
222
223extern Lisp_Object Vx_no_window_manager;
224
1a578e9b
AC
225extern int errno;
226
227/* A mask of extra modifier bits to put into every keyboard char. */
228
229extern int extra_keyboard_modifiers;
230
a36f1680
JW
231/* The keysyms to use for the various modifiers. */
232
233static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
234
1a578e9b
AC
235static Lisp_Object Qvendor_specific_keysyms;
236
237#if 0
238extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
239#endif
240
8030369c 241extern int inhibit_window_system;
1a578e9b
AC
242
243#if __MRC__
244QDGlobals qd; /* QuickDraw global information structure. */
245#endif
246
247
1a578e9b
AC
248struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
249struct mac_display_info *mac_display_info_for_display (Display *);
250static void x_update_window_end P_ ((struct window *, int, int));
f9e65eb3 251static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
1a578e9b
AC
252static int x_io_error_quitter P_ ((Display *));
253int x_catch_errors P_ ((Display *));
254void x_uncatch_errors P_ ((Display *, int));
255void x_lower_frame P_ ((struct frame *));
256void x_scroll_bar_clear P_ ((struct frame *));
257int x_had_errors_p P_ ((Display *));
258void x_wm_set_size_hint P_ ((struct frame *, long, int));
259void x_raise_frame P_ ((struct frame *));
260void x_set_window_size P_ ((struct frame *, int, int, int));
261void x_wm_set_window_state P_ ((struct frame *, int));
262void x_wm_set_icon_pixmap P_ ((struct frame *, int));
e0f712ba 263void mac_initialize P_ ((void));
1a578e9b
AC
264static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
265static int x_compute_min_glyph_bounds P_ ((struct frame *));
1a578e9b
AC
266static void x_update_end P_ ((struct frame *));
267static void XTframe_up_to_date P_ ((struct frame *));
268static void XTreassert_line_highlight P_ ((int, int));
269static void x_change_line_highlight P_ ((int, int, int, int));
270static void XTset_terminal_modes P_ ((void));
271static void XTreset_terminal_modes P_ ((void));
1a578e9b 272static void x_clear_frame P_ ((void));
1a578e9b
AC
273static void frame_highlight P_ ((struct frame *));
274static void frame_unhighlight P_ ((struct frame *));
275static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
276static void XTframe_rehighlight P_ ((struct frame *));
277static void x_frame_rehighlight P_ ((struct x_display_info *));
278static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
e3564461
ST
279static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
280 enum text_cursor_kinds));
281
08f66682 282static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
1a578e9b
AC
283static void x_flush P_ ((struct frame *f));
284static void x_update_begin P_ ((struct frame *));
285static void x_update_window_begin P_ ((struct window *));
1a578e9b 286static void x_after_update_window_line P_ ((struct glyph_row *));
1a578e9b 287
f9e65eb3
KS
288void activate_scroll_bars (FRAME_PTR);
289void deactivate_scroll_bars (FRAME_PTR);
1a578e9b 290
5883787c
AC
291static int is_emacs_window (WindowPtr);
292
1a578e9b
AC
293int x_bitmap_icon (struct frame *, Lisp_Object);
294void x_make_frame_visible (struct frame *);
295
296extern void window_scroll (Lisp_Object, int, int, int);
297
298/* Defined in macmenu.h. */
299extern void menubar_selection_callback (FRAME_PTR, int);
300extern void set_frame_menubar (FRAME_PTR, int, int);
301
302/* X display function emulation */
303
e3564461 304void
1a578e9b 305XFreePixmap (display, pixmap)
e3564461 306 Display *display; /* not used */
1a578e9b
AC
307 Pixmap pixmap;
308{
ffe8b3f4 309 DisposeGWorld (pixmap);
1a578e9b
AC
310}
311
312
313/* Set foreground color for subsequent QuickDraw commands. Assume
314 graphic port has already been set. */
315
316static void
317mac_set_forecolor (unsigned long color)
318{
319 RGBColor fg_color;
177c0ea7 320
e3564461
ST
321 fg_color.red = RED16_FROM_ULONG (color);
322 fg_color.green = GREEN16_FROM_ULONG (color);
323 fg_color.blue = BLUE16_FROM_ULONG (color);
177c0ea7
JB
324
325 RGBForeColor (&fg_color);
1a578e9b
AC
326}
327
328
329/* Set background color for subsequent QuickDraw commands. Assume
330 graphic port has already been set. */
331
332static void
333mac_set_backcolor (unsigned long color)
334{
335 RGBColor bg_color;
177c0ea7 336
e3564461
ST
337 bg_color.red = RED16_FROM_ULONG (color);
338 bg_color.green = GREEN16_FROM_ULONG (color);
339 bg_color.blue = BLUE16_FROM_ULONG (color);
177c0ea7
JB
340
341 RGBBackColor (&bg_color);
1a578e9b
AC
342}
343
344/* Set foreground and background color for subsequent QuickDraw
345 commands. Assume that the graphic port has already been set. */
346
347static void
348mac_set_colors (GC gc)
349{
350 mac_set_forecolor (gc->foreground);
351 mac_set_backcolor (gc->background);
352}
353
354/* Mac version of XDrawLine. */
355
356static void
357XDrawLine (display, w, gc, x1, y1, x2, y2)
358 Display *display;
359 WindowPtr w;
360 GC gc;
361 int x1, y1, x2, y2;
362{
50bf7673 363 SetPortWindowPort (w);
e0f712ba 364
1a578e9b
AC
365 mac_set_colors (gc);
366
367 MoveTo (x1, y1);
368 LineTo (x2, y2);
369}
370
e3564461
ST
371void
372mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
373 Display *display;
374 Pixmap p;
375 GC gc;
376 int x1, y1, x2, y2;
377{
2a316a84
ST
378 CGrafPtr old_port;
379 GDHandle old_gdh;
380
381 GetGWorld (&old_port, &old_gdh);
e3564461
ST
382 SetGWorld (p, NULL);
383
384 mac_set_colors (gc);
385
386 LockPixels (GetGWorldPixMap (p));
387 MoveTo (x1, y1);
388 LineTo (x2, y2);
389 UnlockPixels (GetGWorldPixMap (p));
2a316a84
ST
390
391 SetGWorld (old_port, old_gdh);
e3564461
ST
392}
393
1a578e9b
AC
394/* Mac version of XClearArea. */
395
2e875e36 396void
1a578e9b
AC
397XClearArea (display, w, x, y, width, height, exposures)
398 Display *display;
399 WindowPtr w;
400 int x, y;
401 unsigned int width, height;
402 int exposures;
403{
404 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
405 Rect r;
406 XGCValues xgc;
407
e0f712ba
AC
408 xgc.foreground = mwp->x_compatible.foreground_pixel;
409 xgc.background = mwp->x_compatible.background_pixel;
1a578e9b 410
50bf7673 411 SetPortWindowPort (w);
e0f712ba 412
1a578e9b
AC
413 mac_set_colors (&xgc);
414 SetRect (&r, x, y, x + width, y + height);
415
416 EraseRect (&r);
417}
418
419/* Mac version of XClearWindow. */
420
421static void
422XClearWindow (display, w)
423 Display *display;
424 WindowPtr w;
425{
426 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
427 XGCValues xgc;
428
e0f712ba
AC
429 xgc.foreground = mwp->x_compatible.foreground_pixel;
430 xgc.background = mwp->x_compatible.background_pixel;
1a578e9b 431
50bf7673 432 SetPortWindowPort (w);
e0f712ba 433
1a578e9b
AC
434 mac_set_colors (&xgc);
435
e0f712ba
AC
436#if TARGET_API_MAC_CARBON
437 {
438 Rect r;
177c0ea7 439
e0f712ba
AC
440 GetWindowPortBounds (w, &r);
441 EraseRect (&r);
442 }
443#else /* not TARGET_API_MAC_CARBON */
444 EraseRect (&(w->portRect));
445#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
446}
447
448
449/* Mac replacement for XCopyArea. */
450
451static void
dcd0c645 452mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
1a578e9b
AC
453 Display *display;
454 WindowPtr w;
455 GC gc;
dcd0c645
KS
456 int x, y, width, height;
457 unsigned short *bits;
41840482 458 int overlay_p;
1a578e9b 459{
dcd0c645 460 BitMap bitmap;
1a578e9b
AC
461 Rect r;
462
dcd0c645 463 bitmap.rowBytes = sizeof(unsigned short);
e3564461 464 bitmap.baseAddr = (char *)bits;
dcd0c645
KS
465 SetRect (&(bitmap.bounds), 0, 0, width, height);
466
50bf7673 467 SetPortWindowPort (w);
e0f712ba 468
1a578e9b 469 mac_set_colors (gc);
e3564461 470 SetRect (&r, x, y, x + width, y + height);
1a578e9b 471
e0f712ba 472#if TARGET_API_MAC_CARBON
e3564461
ST
473 LockPortBits (GetWindowPort (w));
474 CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
475 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
476 UnlockPortBits (GetWindowPort (w));
e0f712ba 477#else /* not TARGET_API_MAC_CARBON */
dcd0c645 478 CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
41840482 479 overlay_p ? srcOr : srcCopy, 0);
e0f712ba 480#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
481}
482
483
484/* Mac replacement for XSetClipRectangles. */
485
486static void
487mac_set_clip_rectangle (display, w, r)
488 Display *display;
489 WindowPtr w;
490 Rect *r;
491{
50bf7673 492 SetPortWindowPort (w);
1a578e9b
AC
493
494 ClipRect (r);
495}
496
497
498/* Mac replacement for XSetClipMask. */
499
500static void
501mac_reset_clipping (display, w)
502 Display *display;
503 WindowPtr w;
504{
505 Rect r;
177c0ea7 506
50bf7673 507 SetPortWindowPort (w);
1a578e9b
AC
508
509 SetRect (&r, -32767, -32767, 32767, 32767);
510 ClipRect (&r);
511}
512
513
e3564461
ST
514/* XBM bits seem to be backward within bytes compared with how
515 Mac does things. */
516static unsigned char
517reflect_byte (orig)
518 unsigned char orig;
519{
520 int i;
521 unsigned char reflected = 0x00;
522 for (i = 0; i < 8; i++)
523 {
524 if (orig & (0x01 << i))
525 reflected |= 0x80 >> i;
526 }
527 return reflected;
528}
529
530
1a578e9b
AC
531/* Mac replacement for XCreateBitmapFromBitmapData. */
532
533static void
534mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
535 BitMap *bitmap;
536 char *bits;
537 int w, h;
538{
e3564461
ST
539 int i, j, w1;
540 char *p;
1a578e9b 541
e3564461
ST
542 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
543 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
1a578e9b 544 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
1a578e9b
AC
545 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
546 for (i = 0; i < h; i++)
e3564461
ST
547 {
548 p = bitmap->baseAddr + i * bitmap->rowBytes;
549 for (j = 0; j < w1; j++)
550 *p++ = reflect_byte (*bits++);
551 }
1a578e9b
AC
552
553 SetRect (&(bitmap->bounds), 0, 0, w, h);
554}
555
556
557static void
558mac_free_bitmap (bitmap)
559 BitMap *bitmap;
560{
561 xfree (bitmap->baseAddr);
562}
563
e3564461
ST
564
565Pixmap
566XCreatePixmap (display, w, width, height, depth)
567 Display *display; /* not used */
568 WindowPtr w;
569 unsigned int width, height;
fc7a70cc 570 unsigned int depth;
e3564461
ST
571{
572 Pixmap pixmap;
573 Rect r;
574 QDErr err;
575
50bf7673 576 SetPortWindowPort (w);
e3564461
ST
577
578 SetRect (&r, 0, 0, width, height);
579 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
580 if (err != noErr)
581 return NULL;
582 return pixmap;
583}
584
585
586Pixmap
587XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
588 Display *display; /* not used */
589 WindowPtr w;
590 char *data;
591 unsigned int width, height;
592 unsigned long fg, bg;
593 unsigned int depth; /* not used */
594{
595 Pixmap pixmap;
596 BitMap bitmap;
2a316a84
ST
597 CGrafPtr old_port;
598 GDHandle old_gdh;
e3564461
ST
599
600 pixmap = XCreatePixmap (display, w, width, height, depth);
601 if (pixmap == NULL)
602 return NULL;
603
2a316a84 604 GetGWorld (&old_port, &old_gdh);
e3564461
ST
605 SetGWorld (pixmap, NULL);
606 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
607 mac_set_forecolor (fg);
608 mac_set_backcolor (bg);
609 LockPixels (GetGWorldPixMap (pixmap));
610#if TARGET_API_MAC_CARBON
611 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
612 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
613#else /* not TARGET_API_MAC_CARBON */
614 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
615 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
616#endif /* not TARGET_API_MAC_CARBON */
617 UnlockPixels (GetGWorldPixMap (pixmap));
2a316a84 618 SetGWorld (old_port, old_gdh);
e3564461
ST
619 mac_free_bitmap (&bitmap);
620
621 return pixmap;
622}
623
624
1a578e9b
AC
625/* Mac replacement for XFillRectangle. */
626
627static void
628XFillRectangle (display, w, gc, x, y, width, height)
629 Display *display;
630 WindowPtr w;
631 GC gc;
632 int x, y;
633 unsigned int width, height;
634{
635 Rect r;
636
50bf7673 637 SetPortWindowPort (w);
e0f712ba 638
1a578e9b
AC
639 mac_set_colors (gc);
640 SetRect (&r, x, y, x + width, y + height);
641
642 PaintRect (&r); /* using foreground color of gc */
643}
644
645
fc7a70cc 646#if 0 /* TODO: figure out if we need to do this on Mac. */
e3564461
ST
647static void
648mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
649 Display *display;
650 Pixmap p;
651 GC gc;
652 int x, y;
653 unsigned int width, height;
654{
2a316a84
ST
655 CGrafPtr old_port;
656 GDHandle old_gdh;
e3564461
ST
657 Rect r;
658
2a316a84 659 GetGWorld (&old_port, &old_gdh);
e3564461
ST
660 SetGWorld (p, NULL);
661 mac_set_colors (gc);
662 SetRect (&r, x, y, x + width, y + height);
663
664 LockPixels (GetGWorldPixMap (p));
665 PaintRect (&r); /* using foreground color of gc */
666 UnlockPixels (GetGWorldPixMap (p));
2a316a84
ST
667
668 SetGWorld (old_port, old_gdh);
e3564461 669}
fc7a70cc 670#endif
e3564461
ST
671
672
1a578e9b
AC
673/* Mac replacement for XDrawRectangle: dest is a window. */
674
675static void
676mac_draw_rectangle (display, w, gc, x, y, width, height)
677 Display *display;
678 WindowPtr w;
679 GC gc;
680 int x, y;
681 unsigned int width, height;
682{
683 Rect r;
684
50bf7673 685 SetPortWindowPort (w);
e0f712ba 686
1a578e9b
AC
687 mac_set_colors (gc);
688 SetRect (&r, x, y, x + width + 1, y + height + 1);
689
690 FrameRect (&r); /* using foreground color of gc */
691}
692
693
fc7a70cc 694#if 0 /* TODO: figure out if we need to do this on Mac. */
1a578e9b
AC
695/* Mac replacement for XDrawRectangle: dest is a Pixmap. */
696
697static void
698mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
699 Display *display;
700 Pixmap p;
701 GC gc;
702 int x, y;
703 unsigned int width, height;
704{
2a316a84
ST
705 CGrafPtr old_port;
706 GDHandle old_gdh;
1a578e9b
AC
707 Rect r;
708
2a316a84 709 GetGWorld (&old_port, &old_gdh);
e3564461 710 SetGWorld (p, NULL);
1a578e9b 711 mac_set_colors (gc);
e3564461 712 SetRect (&r, x, y, x + width + 1, y + height + 1);
1a578e9b 713
e3564461 714 LockPixels (GetGWorldPixMap (p));
1a578e9b 715 FrameRect (&r); /* using foreground color of gc */
e3564461 716 UnlockPixels (GetGWorldPixMap (p));
2a316a84
ST
717
718 SetGWorld (old_port, old_gdh);
1a578e9b 719}
fc7a70cc 720#endif
1a578e9b
AC
721
722
723static void
724mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
725 bytes_per_char)
726 Display *display;
727 WindowPtr w;
728 GC gc;
729 int x, y;
730 char *buf;
731 int nchars, mode, bytes_per_char;
732{
50bf7673 733 SetPortWindowPort (w);
e0f712ba 734
1a578e9b
AC
735 mac_set_colors (gc);
736
737 TextFont (gc->font->mac_fontnum);
738 TextSize (gc->font->mac_fontsize);
739 TextFace (gc->font->mac_fontface);
740 TextMode (mode);
741
742 MoveTo (x, y);
743 DrawText (buf, 0, nchars * bytes_per_char);
744}
745
746
747/* Mac replacement for XDrawString. */
748
749static void
750XDrawString (display, w, gc, x, y, buf, nchars)
751 Display *display;
752 WindowPtr w;
753 GC gc;
754 int x, y;
755 char *buf;
756 int nchars;
757{
758 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
759}
760
761
762/* Mac replacement for XDrawString16. */
763
764static void
765XDrawString16 (display, w, gc, x, y, buf, nchars)
766 Display *display;
767 WindowPtr w;
768 GC gc;
769 int x, y;
770 XChar2b *buf;
771 int nchars;
772{
773 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
774 2);
775}
776
777
778/* Mac replacement for XDrawImageString. */
779
780static void
781XDrawImageString (display, w, gc, x, y, buf, nchars)
782 Display *display;
783 WindowPtr w;
784 GC gc;
785 int x, y;
786 char *buf;
787 int nchars;
788{
789 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
790}
791
792
793/* Mac replacement for XDrawString16. */
794
795static void
796XDrawImageString16 (display, w, gc, x, y, buf, nchars)
797 Display *display;
798 WindowPtr w;
799 GC gc;
800 int x, y;
801 XChar2b *buf;
802 int nchars;
803{
804 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
805 2);
806}
807
808
809/* Mac replacement for XCopyArea: dest must be window. */
810
811static void
812mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
813 dest_y)
814 Display *display;
815 Pixmap src;
816 WindowPtr dest;
817 GC gc;
818 int src_x, src_y;
819 unsigned int width, height;
820 int dest_x, dest_y;
821{
822 Rect src_r, dest_r;
823
50bf7673 824 SetPortWindowPort (dest);
e0f712ba 825
1a578e9b
AC
826 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
827 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
828
e3564461
ST
829 ForeColor (blackColor);
830 BackColor (whiteColor);
831
832 LockPixels (GetGWorldPixMap (src));
e0f712ba 833#if TARGET_API_MAC_CARBON
e3564461
ST
834 LockPortBits (GetWindowPort (dest));
835 CopyBits (GetPortBitMapForCopyBits (src),
836 GetPortBitMapForCopyBits (GetWindowPort (dest)),
837 &src_r, &dest_r, srcCopy, 0);
838 UnlockPortBits (GetWindowPort (dest));
839#else /* not TARGET_API_MAC_CARBON */
840 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
841 &src_r, &dest_r, srcCopy, 0);
842#endif /* not TARGET_API_MAC_CARBON */
843 UnlockPixels (GetGWorldPixMap (src));
844}
e0f712ba 845
e3564461
ST
846
847static void
848mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
849 width, height, dest_x, dest_y)
850 Display *display;
851 Pixmap src, mask;
852 WindowPtr dest;
853 GC gc;
854 int src_x, src_y;
855 unsigned int width, height;
856 int dest_x, dest_y;
857{
858 Rect src_r, dest_r;
859
50bf7673 860 SetPortWindowPort (dest);
e3564461
ST
861
862 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
863 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
864
865 ForeColor (blackColor);
866 BackColor (whiteColor);
867
868 LockPixels (GetGWorldPixMap (src));
869 LockPixels (GetGWorldPixMap (mask));
870#if TARGET_API_MAC_CARBON
871 LockPortBits (GetWindowPort (dest));
872 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
873 GetPortBitMapForCopyBits (GetWindowPort (dest)),
874 &src_r, &src_r, &dest_r);
875 UnlockPortBits (GetWindowPort (dest));
e0f712ba 876#else /* not TARGET_API_MAC_CARBON */
e3564461
ST
877 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
878 &(dest->portBits), &src_r, &src_r, &dest_r);
e0f712ba 879#endif /* not TARGET_API_MAC_CARBON */
e3564461
ST
880 UnlockPixels (GetGWorldPixMap (mask));
881 UnlockPixels (GetGWorldPixMap (src));
1a578e9b
AC
882}
883
884
f9e25d0c 885#if 0
1a578e9b
AC
886/* Convert a pair of local coordinates to global (screen) coordinates.
887 Assume graphic port has been properly set. */
888static void
889local_to_global_coord (short *h, short *v)
890{
891 Point p;
177c0ea7 892
1a578e9b
AC
893 p.h = *h;
894 p.v = *v;
177c0ea7 895
1a578e9b 896 LocalToGlobal (&p);
177c0ea7 897
1a578e9b
AC
898 *h = p.h;
899 *v = p.v;
900}
f9e25d0c 901#endif
1a578e9b
AC
902
903/* Mac replacement for XCopyArea: used only for scrolling. */
904
905static void
906mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
907 Display *display;
908 WindowPtr w;
909 GC gc;
910 int src_x, src_y;
911 unsigned int width, height;
912 int dest_x, dest_y;
913{
e0f712ba 914#if TARGET_API_MAC_CARBON
fc7a70cc
ST
915 Rect src_r;
916 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
e0f712ba
AC
917
918 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
fc7a70cc
ST
919 ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
920 kScrollWindowNoOptions, dummy);
921 DisposeRgn (dummy);
e0f712ba 922#else /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
923 Rect src_r, dest_r;
924
925 SetPort (w);
f9e25d0c 926#if 0
1a578e9b 927 mac_set_colors (gc);
f9e25d0c 928#endif
1a578e9b
AC
929
930 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
931 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
932
f9e25d0c 933#if 0
1a578e9b
AC
934 /* Need to use global coordinates and screenBits since src and dest
935 areas overlap in general. */
936 local_to_global_coord (&src_r.left, &src_r.top);
937 local_to_global_coord (&src_r.right, &src_r.bottom);
938 local_to_global_coord (&dest_r.left, &dest_r.top);
939 local_to_global_coord (&dest_r.right, &dest_r.bottom);
940
941 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
f9e25d0c
AC
942#else
943 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
944 color mapping in CopyBits. Otherwise, it will be slow. */
945 ForeColor (blackColor);
946 BackColor (whiteColor);
947 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
177c0ea7 948
f9e25d0c
AC
949 mac_set_colors (gc);
950#endif
e0f712ba 951#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
952}
953
954
fc7a70cc 955#if 0 /* TODO: figure out if we need to do this on Mac. */
1a578e9b
AC
956/* Mac replacement for XCopyArea: dest must be Pixmap. */
957
958static void
177c0ea7 959mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1a578e9b
AC
960 dest_x, dest_y)
961 Display *display;
e3564461 962 Pixmap src, dest;
1a578e9b
AC
963 GC gc;
964 int src_x, src_y;
965 unsigned int width, height;
966 int dest_x, dest_y;
967{
2a316a84
ST
968 CGrafPtr old_port;
969 GDHandle old_gdh;
1a578e9b 970 Rect src_r, dest_r;
1a578e9b 971
2a316a84 972 GetGWorld (&old_port, &old_gdh);
e3564461
ST
973 SetGWorld (dest, NULL);
974 ForeColor (blackColor);
975 BackColor (whiteColor);
976
977 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
978 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
979
980 LockPixels (GetGWorldPixMap (src));
981 LockPixels (GetGWorldPixMap (dest));
982#if TARGET_API_MAC_CARBON
983 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
984 &src_r, &dest_r, srcCopy, 0);
985#else /* not TARGET_API_MAC_CARBON */
986 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
987 &src_r, &dest_r, srcCopy, 0);
988#endif /* not TARGET_API_MAC_CARBON */
989 UnlockPixels (GetGWorldPixMap (dest));
990 UnlockPixels (GetGWorldPixMap (src));
2a316a84
ST
991
992 SetGWorld (old_port, old_gdh);
e3564461
ST
993}
994
995
996static void
997mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
998 width, height, dest_x, dest_y)
999 Display *display;
1000 Pixmap src, mask, dest;
1001 GC gc;
1002 int src_x, src_y;
1003 unsigned int width, height;
1004 int dest_x, dest_y;
1005{
2a316a84
ST
1006 CGrafPtr old_port;
1007 GDHandle old_gdh;
e3564461
ST
1008 Rect src_r, dest_r;
1009
2a316a84 1010 GetGWorld (&old_port, &old_gdh);
e3564461
ST
1011 SetGWorld (dest, NULL);
1012 ForeColor (blackColor);
1013 BackColor (whiteColor);
177c0ea7 1014
e3564461
ST
1015 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1016 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1a578e9b 1017
e3564461
ST
1018 LockPixels (GetGWorldPixMap (src));
1019 LockPixels (GetGWorldPixMap (mask));
1020 LockPixels (GetGWorldPixMap (dest));
1021#if TARGET_API_MAC_CARBON
1022 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1023 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
1024#else /* not TARGET_API_MAC_CARBON */
1025 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1026 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
1027#endif /* not TARGET_API_MAC_CARBON */
1028 UnlockPixels (GetGWorldPixMap (dest));
1029 UnlockPixels (GetGWorldPixMap (mask));
1030 UnlockPixels (GetGWorldPixMap (src));
2a316a84
ST
1031
1032 SetGWorld (old_port, old_gdh);
1a578e9b 1033}
fc7a70cc 1034#endif
1a578e9b
AC
1035
1036
1037/* Mac replacement for XChangeGC. */
1038
1039static void
1040XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1041 XGCValues *xgcv)
1042{
1043 if (mask & GCForeground)
1044 gc->foreground = xgcv->foreground;
1045 if (mask & GCBackground)
1046 gc->background = xgcv->background;
1047 if (mask & GCFont)
1048 gc->font = xgcv->font;
1049}
1050
1051
1052/* Mac replacement for XCreateGC. */
1053
1054XGCValues *
1055XCreateGC (void * ignore, Window window, unsigned long mask,
1056 XGCValues *xgcv)
1057{
1058 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1059 bzero (gc, sizeof (XGCValues));
1060
1061 XChangeGC (ignore, gc, mask, xgcv);
1062
1063 return gc;
1064}
1065
1066
1067/* Used in xfaces.c. */
1068
1069void
1070XFreeGC (display, gc)
1071 Display *display;
1072 GC gc;
1073{
1074 xfree (gc);
1075}
1076
1077
1078/* Mac replacement for XGetGCValues. */
1079
1080static void
1081XGetGCValues (void* ignore, XGCValues *gc,
1082 unsigned long mask, XGCValues *xgcv)
1083{
1084 XChangeGC (ignore, xgcv, mask, gc);
1085}
1086
1087
1088/* Mac replacement for XSetForeground. */
1089
e3564461 1090void
1a578e9b
AC
1091XSetForeground (display, gc, color)
1092 Display *display;
1093 GC gc;
1094 unsigned long color;
1095{
1096 gc->foreground = color;
1097}
1098
1099
1100/* Mac replacement for XSetFont. */
1101
1102static void
1103XSetFont (display, gc, font)
1104 Display *display;
1105 GC gc;
1106 XFontStruct *font;
1107{
1108 gc->font = font;
1109}
1110
1111
1112static void
1113XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1114 int *direction,int *font_ascent,
1115 int *font_descent, XCharStruct *cs)
1116{
1117 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1118}
1119
1120
1121/* x_sync is a no-op on Mac. */
1122void
1123x_sync (f)
1124 void *f;
1125{
1126}
1127
1128
1129/* Flush display of frame F, or of all frames if F is null. */
1130
fc7a70cc 1131static void
1a578e9b
AC
1132x_flush (f)
1133 struct frame *f;
1134{
e0f712ba 1135#if TARGET_API_MAC_CARBON
1a578e9b 1136 BLOCK_INPUT;
fc7a70cc
ST
1137 if (f)
1138 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1139 else
1140 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1a578e9b 1141 UNBLOCK_INPUT;
fc7a70cc 1142#endif
1a578e9b
AC
1143}
1144
1145
fc7a70cc
ST
1146/* Remove calls to XFlush by defining XFlush to an empty replacement.
1147 Calls to XFlush should be unnecessary because the X output buffer
1148 is flushed automatically as needed by calls to XPending,
1149 XNextEvent, or XWindowEvent according to the XFlush man page.
1150 XTread_socket calls XPending. Removing XFlush improves
1151 performance. */
1152
1153#define XFlush(DISPLAY) (void) 0
1154
1a578e9b
AC
1155\f
1156/* Return the struct mac_display_info corresponding to DPY. There's
1157 only one. */
1158
1159struct mac_display_info *
1160mac_display_info_for_display (dpy)
1161 Display *dpy;
1162{
1163 return &one_mac_display_info;
1164}
1165
1166
1167\f
1168/***********************************************************************
1169 Starting and ending an update
1170 ***********************************************************************/
177c0ea7 1171
1a578e9b
AC
1172/* Start an update of frame F. This function is installed as a hook
1173 for update_begin, i.e. it is called when update_begin is called.
1174 This function is called prior to calls to x_update_window_begin for
e0f712ba 1175 each window being updated. */
1a578e9b 1176
e0f712ba 1177static void
1a578e9b
AC
1178x_update_begin (f)
1179 struct frame *f;
1180{
b15325b2
ST
1181#if TARGET_API_MAC_CARBON
1182 /* During update of a frame, availability of input events is
1183 periodically checked with ReceiveNextEvent if
1184 redisplay-dont-pause is nil. That normally flushes window buffer
1185 changes for every check, and thus screen update looks waving even
1186 if no input is available. So we disable screen updates during
1187 update of a frame. */
1188 BLOCK_INPUT;
1189 DisableScreenUpdates ();
1190 UNBLOCK_INPUT;
1191#endif
1a578e9b
AC
1192}
1193
1194
1195/* Start update of window W. Set the global variable updated_window
1196 to the window being updated and set output_cursor to the cursor
1197 position of W. */
1198
e0f712ba 1199static void
1a578e9b
AC
1200x_update_window_begin (w)
1201 struct window *w;
1202{
1203 struct frame *f = XFRAME (WINDOW_FRAME (w));
1204 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
177c0ea7 1205
1a578e9b
AC
1206 updated_window = w;
1207 set_output_cursor (&w->cursor);
1208
1209 BLOCK_INPUT;
1210
1211 if (f == display_info->mouse_face_mouse_frame)
1212 {
1213 /* Don't do highlighting for mouse motion during the update. */
1214 display_info->mouse_face_defer = 1;
1215
1216 /* If F needs to be redrawn, simply forget about any prior mouse
1217 highlighting. */
1218 if (FRAME_GARBAGED_P (f))
1219 display_info->mouse_face_window = Qnil;
1220
1221#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1222 their mouse_face_p flag set, which means that they are always
1223 unequal to rows in a desired matrix which never have that
1224 flag set. So, rows containing mouse-face glyphs are never
1225 scrolled, and we don't have to switch the mouse highlight off
1226 here to prevent it from being scrolled. */
177c0ea7 1227
1a578e9b
AC
1228 /* Can we tell that this update does not affect the window
1229 where the mouse highlight is? If so, no need to turn off.
1230 Likewise, don't do anything if the frame is garbaged;
1231 in that case, the frame's current matrix that we would use
1232 is all wrong, and we will redisplay that line anyway. */
1233 if (!NILP (display_info->mouse_face_window)
1234 && w == XWINDOW (display_info->mouse_face_window))
1235 {
1236 int i;
1237
50bf7673 1238 for (i = 0; i < w->desired_matrix->nrows; ++i)
1a578e9b
AC
1239 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1240 break;
1241
1242 if (i < w->desired_matrix->nrows)
1243 clear_mouse_face (display_info);
1244 }
1245#endif /* 0 */
1246 }
1247
1248 UNBLOCK_INPUT;
1249}
1250
1251
f9e65eb3 1252/* Draw a vertical window border from (x,y0) to (x,y1) */
1a578e9b
AC
1253
1254static void
f9e65eb3 1255mac_draw_vertical_window_border (w, x, y0, y1)
1a578e9b 1256 struct window *w;
f9e65eb3 1257 int x, y0, y1;
1a578e9b
AC
1258{
1259 struct frame *f = XFRAME (WINDOW_FRAME (w));
ffe8b3f4 1260
f9e65eb3
KS
1261 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1262 f->output_data.mac->normal_gc, x, y0, x, y1);
1a578e9b 1263}
e0f712ba 1264
177c0ea7 1265
1a578e9b
AC
1266/* End update of window W (which is equal to updated_window).
1267
1268 Draw vertical borders between horizontally adjacent windows, and
1269 display W's cursor if CURSOR_ON_P is non-zero.
1270
1271 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1272 glyphs in mouse-face were overwritten. In that case we have to
1273 make sure that the mouse-highlight is properly redrawn.
1274
1275 W may be a menu bar pseudo-window in case we don't have X toolkit
b15325b2 1276 support. Such windows don't have a cursor, so don't display it
e0f712ba 1277 here. */
1a578e9b 1278
e0f712ba 1279static void
1a578e9b
AC
1280x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1281 struct window *w;
1282 int cursor_on_p, mouse_face_overwritten_p;
1283{
f9e65eb3 1284 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
e0f712ba 1285
1a578e9b
AC
1286 if (!w->pseudo_window_p)
1287 {
1a578e9b
AC
1288 BLOCK_INPUT;
1289
1a578e9b 1290 if (cursor_on_p)
f9e65eb3
KS
1291 display_and_set_cursor (w, 1, output_cursor.hpos,
1292 output_cursor.vpos,
1293 output_cursor.x, output_cursor.y);
177c0ea7 1294
f94a2622
KS
1295 if (draw_window_fringes (w, 1))
1296 x_draw_vertical_border (w);
797dc7b8 1297
1a578e9b
AC
1298 UNBLOCK_INPUT;
1299 }
e0f712ba
AC
1300
1301 /* If a row with mouse-face was overwritten, arrange for
1302 XTframe_up_to_date to redisplay the mouse highlight. */
1303 if (mouse_face_overwritten_p)
1304 {
1305 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1306 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1307 dpyinfo->mouse_face_window = Qnil;
1308 }
1309
1310#if 0
1311 /* Unhide the caret. This won't actually show the cursor, unless it
1312 was visible before the corresponding call to HideCaret in
1313 x_update_window_begin. */
1314 if (w32_use_visible_system_caret)
1315 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1316#endif
1317
1a578e9b
AC
1318 updated_window = NULL;
1319}
1320
1321
1322/* End update of frame F. This function is installed as a hook in
1323 update_end. */
1324
e0f712ba 1325static void
1a578e9b
AC
1326x_update_end (f)
1327 struct frame *f;
1328{
404e4b84
ST
1329 /* Mouse highlight may be displayed again. */
1330 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1331
1332 BLOCK_INPUT;
1a578e9b
AC
1333 /* Reset the background color of Mac OS Window to that of the frame after
1334 update so that it is used by Mac Toolbox to clear the update region before
1335 an update event is generated. */
50bf7673 1336 SetPortWindowPort (FRAME_MAC_WINDOW (f));
e0f712ba 1337
1a578e9b 1338 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
177c0ea7 1339
b15325b2
ST
1340#if TARGET_API_MAC_CARBON
1341 EnableScreenUpdates ();
1342#endif
1a578e9b
AC
1343 XFlush (FRAME_MAC_DISPLAY (f));
1344 UNBLOCK_INPUT;
1345}
1346
1347
1348/* This function is called from various places in xdisp.c whenever a
1349 complete update has been performed. The global variable
1350 updated_window is not available here. */
1351
e0f712ba 1352static void
1a578e9b
AC
1353XTframe_up_to_date (f)
1354 struct frame *f;
1355{
fe97e8df 1356 if (FRAME_MAC_P (f))
1a578e9b
AC
1357 {
1358 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1359
1360 if (dpyinfo->mouse_face_deferred_gc
1361 || f == dpyinfo->mouse_face_mouse_frame)
1362 {
1363 BLOCK_INPUT;
1364 if (dpyinfo->mouse_face_mouse_frame)
1365 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1366 dpyinfo->mouse_face_mouse_x,
1367 dpyinfo->mouse_face_mouse_y);
1368 dpyinfo->mouse_face_deferred_gc = 0;
1369 UNBLOCK_INPUT;
1370 }
1371 }
1372}
1373
1374
1375/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
3f332ef3 1376 arrow bitmaps, or clear the fringes if no bitmaps are required
1a578e9b 1377 before DESIRED_ROW is made current. The window being updated is
e0f712ba 1378 found in updated_window. This function is called from
1a578e9b
AC
1379 update_window_line only if it is known that there are differences
1380 between bitmaps to be drawn between current row and DESIRED_ROW. */
1381
e0f712ba 1382static void
1a578e9b
AC
1383x_after_update_window_line (desired_row)
1384 struct glyph_row *desired_row;
1385{
1386 struct window *w = updated_window;
e0f712ba
AC
1387 struct frame *f;
1388 int width, height;
1389
1a578e9b 1390 xassert (w);
177c0ea7 1391
1a578e9b 1392 if (!desired_row->mode_line_p && !w->pseudo_window_p)
797dc7b8 1393 desired_row->redraw_fringe_bitmaps_p = 1;
1a578e9b 1394
e0f712ba
AC
1395 /* When a window has disappeared, make sure that no rest of
1396 full-width rows stays visible in the internal border. Could
1397 check here if updated_window is the leftmost/rightmost window,
1398 but I guess it's not worth doing since vertically split windows
1399 are almost never used, internal border is rarely set, and the
1400 overhead is very small. */
1401 if (windows_or_buffers_changed
1402 && desired_row->full_width_p
1403 && (f = XFRAME (w->frame),
1404 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1405 width != 0)
1406 && (height = desired_row->visible_height,
1407 height > 0))
1408 {
1409 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1410 /* Internal border is drawn below the tool bar. */
1411 if (WINDOWP (f->tool_bar_window)
1412 && w == XWINDOW (f->tool_bar_window))
1413 y -= width;
1a578e9b 1414
e0f712ba
AC
1415 BLOCK_INPUT;
1416
1417 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1418 0, y, width, height, 0);
1419 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
f1a83aab 1420 FRAME_PIXEL_WIDTH (f) - width, y,
e0f712ba 1421 width, height, 0);
177c0ea7 1422
1a578e9b
AC
1423 UNBLOCK_INPUT;
1424 }
1425}
1426
1427
3f332ef3 1428/* Draw the bitmap WHICH in one of the left or right fringes of
1a578e9b
AC
1429 window W. ROW is the glyph row for which to display the bitmap; it
1430 determines the vertical position at which the bitmap has to be
1431 drawn. */
1432
1433static void
5958f265 1434x_draw_fringe_bitmap (w, row, p)
1a578e9b
AC
1435 struct window *w;
1436 struct glyph_row *row;
5958f265 1437 struct draw_fringe_bitmap_params *p;
1a578e9b
AC
1438{
1439 struct frame *f = XFRAME (WINDOW_FRAME (w));
1440 Display *display = FRAME_MAC_DISPLAY (f);
1441 WindowPtr window = FRAME_MAC_WINDOW (f);
1a578e9b 1442 XGCValues gcv;
e0f712ba 1443 GC gc = f->output_data.mac->normal_gc;
5958f265 1444 struct face *face = p->face;
797dc7b8 1445 int rowY;
1a578e9b
AC
1446
1447 /* Must clip because of partially visible lines. */
797dc7b8
KS
1448 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1449 if (p->y < rowY)
1450 {
1451 /* Adjust position of "bottom aligned" bitmap on partially
1452 visible last row. */
1453 int oldY = row->y;
1454 int oldVH = row->visible_height;
1455 row->visible_height = p->h;
1456 row->y -= rowY - p->y;
08f66682 1457 x_clip_to_row (w, row, -1, gc);
797dc7b8
KS
1458 row->y = oldY;
1459 row->visible_height = oldVH;
1460 }
1461 else
08f66682 1462 x_clip_to_row (w, row, -1, gc);
1a578e9b 1463
288670f5 1464 if (p->bx >= 0 && !p->overlay_p)
d33c49e8 1465 {
d33c49e8
KS
1466 XGCValues gcv;
1467 gcv.foreground = face->background;
1468
1469#if 0 /* MAC_TODO: stipple */
1470 /* In case the same realized face is used for fringes and
1471 for something displayed in the text (e.g. face `region' on
1472 mono-displays, the fill style may have been changed to
1473 FillSolid in x_draw_glyph_string_background. */
1474 if (face->stipple)
1475 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1476 else
1477 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1478#endif
1479
1480 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1481 &gcv,
5958f265 1482 p->bx, p->by, p->nx, p->ny);
d33c49e8
KS
1483
1484#if 0 /* MAC_TODO: stipple */
1485 if (!face->stipple)
1486 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1487#endif
1488 }
1489
288670f5 1490 if (p->which)
e0f712ba 1491 {
dcd0c645 1492 unsigned short *bits = p->bits + p->dh;
1a578e9b 1493
288670f5
KS
1494 gcv.foreground = (p->cursor_p
1495 ? (p->overlay_p ? face->background
1496 : f->output_data.mac->cursor_pixel)
41840482
KS
1497 : face->foreground);
1498 gcv.background = face->background;
1a578e9b 1499
ffe8b3f4 1500 mac_draw_bitmap (display, window, &gcv, p->x, p->y,
dcd0c645 1501 p->wd, p->h, bits, p->overlay_p);
d33c49e8 1502 }
1a578e9b 1503
5958f265 1504 mac_reset_clipping (display, window);
1a578e9b
AC
1505}
1506
1507\f
1a578e9b 1508/* This is called when starting Emacs and when restarting after
e0f712ba 1509 suspend. When starting Emacs, no window is mapped. And nothing
1a578e9b
AC
1510 must be done to Emacs's own window if it is suspended (though that
1511 rarely happens). */
1512
e0f712ba 1513static void
1a578e9b
AC
1514XTset_terminal_modes ()
1515{
1516}
1517
1518/* This is called when exiting or suspending Emacs. Exiting will make
e0f712ba 1519 the windows go away, and suspending requires no action. */
1a578e9b 1520
e0f712ba 1521static void
1a578e9b
AC
1522XTreset_terminal_modes ()
1523{
1524}
1525
1a578e9b
AC
1526\f
1527/***********************************************************************
1528 Display Iterator
1529 ***********************************************************************/
1530
1531/* Function prototypes of this page. */
1532
1a578e9b 1533static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
750fc673 1534static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1a578e9b
AC
1535
1536
1537/* Return a pointer to per-char metric information in FONT of a
1538 character pointed by B which is a pointer to an XChar2b. */
1539
1540#define PER_CHAR_METRIC(font, b) \
1541 ((font)->per_char \
1542 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1543 + (((font)->min_byte1 || (font)->max_byte1) \
1544 ? (((b)->byte1 - (font)->min_byte1) \
1545 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1546 : 0)) \
1547 : &((font)->max_bounds))
1548
1549
1550/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1551 is not contained in the font. */
1552
1553static INLINE XCharStruct *
1554x_per_char_metric (font, char2b)
1555 XFontStruct *font;
1556 XChar2b *char2b;
1557{
1558 /* The result metric information. */
1559 XCharStruct *pcm = NULL;
1560
1561 xassert (font && char2b);
1562
1563 if (font->per_char != NULL)
1564 {
1565 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1566 {
1567 /* min_char_or_byte2 specifies the linear character index
1568 corresponding to the first element of the per_char array,
1569 max_char_or_byte2 is the index of the last character. A
1570 character with non-zero CHAR2B->byte1 is not in the font.
1571 A character with byte2 less than min_char_or_byte2 or
1572 greater max_char_or_byte2 is not in the font. */
1573 if (char2b->byte1 == 0
1574 && char2b->byte2 >= font->min_char_or_byte2
1575 && char2b->byte2 <= font->max_char_or_byte2)
1576 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1577 }
1578 else
1579 {
1580 /* If either min_byte1 or max_byte1 are nonzero, both
1581 min_char_or_byte2 and max_char_or_byte2 are less than
1582 256, and the 2-byte character index values corresponding
1583 to the per_char array element N (counting from 0) are:
1584
1585 byte1 = N/D + min_byte1
1586 byte2 = N\D + min_char_or_byte2
1587
1588 where:
1589
1590 D = max_char_or_byte2 - min_char_or_byte2 + 1
1591 / = integer division
1592 \ = integer modulus */
1593 if (char2b->byte1 >= font->min_byte1
1594 && char2b->byte1 <= font->max_byte1
1595 && char2b->byte2 >= font->min_char_or_byte2
1596 && char2b->byte2 <= font->max_char_or_byte2)
1597 {
1598 pcm = (font->per_char
1599 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1600 * (char2b->byte1 - font->min_byte1))
1601 + (char2b->byte2 - font->min_char_or_byte2));
1602 }
1603 }
1604 }
1605 else
1606 {
1607 /* If the per_char pointer is null, all glyphs between the first
1608 and last character indexes inclusive have the same
1609 information, as given by both min_bounds and max_bounds. */
1610 if (char2b->byte2 >= font->min_char_or_byte2
1611 && char2b->byte2 <= font->max_char_or_byte2)
1612 pcm = &font->max_bounds;
1613 }
1614
1615 return ((pcm == NULL
1616 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1617 ? NULL : pcm);
1618}
1619
750fc673
KS
1620/* RIF:
1621 */
1622
1623static XCharStruct *
1624mac_per_char_metric (font, char2b, font_type)
1625 XFontStruct *font;
1626 XChar2b *char2b;
1627 int font_type;
1628{
1629 return x_per_char_metric (font, char2b);
1630}
1a578e9b 1631
750fc673
KS
1632/* RIF:
1633 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1a578e9b
AC
1634 the two-byte form of C. Encoding is returned in *CHAR2B. */
1635
750fc673
KS
1636static int
1637mac_encode_char (c, char2b, font_info, two_byte_p)
1a578e9b
AC
1638 int c;
1639 XChar2b *char2b;
1640 struct font_info *font_info;
750fc673 1641 int *two_byte_p;
1a578e9b
AC
1642{
1643 int charset = CHAR_CHARSET (c);
1644 XFontStruct *font = font_info->font;
1645
1646 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1647 This may be either a program in a special encoder language or a
1648 fixed encoding. */
1649 if (font_info->font_encoder)
1650 {
1651 /* It's a program. */
1652 struct ccl_program *ccl = font_info->font_encoder;
1653
1654 if (CHARSET_DIMENSION (charset) == 1)
1655 {
1656 ccl->reg[0] = charset;
1657 ccl->reg[1] = char2b->byte2;
1658 }
1659 else
1660 {
1661 ccl->reg[0] = charset;
1662 ccl->reg[1] = char2b->byte1;
1663 ccl->reg[2] = char2b->byte2;
1664 }
177c0ea7 1665
1a578e9b 1666 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
177c0ea7 1667
1a578e9b
AC
1668 /* We assume that MSBs are appropriately set/reset by CCL
1669 program. */
1670 if (font->max_byte1 == 0) /* 1-byte font */
1671 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1672 else
1673 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1674 }
1675 else if (font_info->encoding[charset])
1676 {
1677 /* Fixed encoding scheme. See fontset.h for the meaning of the
1678 encoding numbers. */
1679 int enc = font_info->encoding[charset];
177c0ea7 1680
1a578e9b
AC
1681 if ((enc == 1 || enc == 2)
1682 && CHARSET_DIMENSION (charset) == 2)
1683 char2b->byte1 |= 0x80;
177c0ea7 1684
1a578e9b
AC
1685 if (enc == 1 || enc == 3)
1686 char2b->byte2 |= 0x80;
1687
1688 if (enc == 4)
1689 {
1690 int sjis1, sjis2;
1691
1692 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1693 char2b->byte1 = sjis1;
1694 char2b->byte2 = sjis2;
1695 }
1696 }
1a578e9b
AC
1697
1698 if (two_byte_p)
750fc673 1699 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1a578e9b 1700
750fc673 1701 return FONT_TYPE_UNKNOWN;
1a578e9b
AC
1702}
1703
1704
1a578e9b
AC
1705\f
1706/***********************************************************************
1707 Glyph display
1708 ***********************************************************************/
1709
1a578e9b 1710
1a578e9b
AC
1711static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1712static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1713static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1714 int));
1715static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1716static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1717static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1718static void x_draw_glyph_string P_ ((struct glyph_string *));
1a578e9b
AC
1719static void x_set_cursor_gc P_ ((struct glyph_string *));
1720static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1721static void x_set_mouse_face_gc P_ ((struct glyph_string *));
e0f712ba
AC
1722/*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1723 unsigned long *, double, int));*/
1a578e9b
AC
1724static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1725 double, int, unsigned long));
1726static void x_setup_relief_colors P_ ((struct glyph_string *));
1727static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1728static void x_draw_image_relief P_ ((struct glyph_string *));
1729static void x_draw_image_foreground P_ ((struct glyph_string *));
1730static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1a578e9b
AC
1731static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1732 int, int, int));
1733static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
ffe8b3f4
KS
1734 int, int, int, int, int, int,
1735 Rect *));
1a578e9b 1736static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
e0f712ba 1737 int, int, int, Rect *));
1a578e9b
AC
1738
1739#if GLYPH_DEBUG
1740static void x_check_font P_ ((struct frame *, XFontStruct *));
1741#endif
1742
177c0ea7 1743
1a578e9b
AC
1744/* Set S->gc to a suitable GC for drawing glyph string S in cursor
1745 face. */
1746
1747static void
1748x_set_cursor_gc (s)
1749 struct glyph_string *s;
1750{
1751 if (s->font == FRAME_FONT (s->f)
1752 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1753 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1754 && !s->cmp)
1755 s->gc = s->f->output_data.mac->cursor_gc;
1756 else
1757 {
1758 /* Cursor on non-default face: must merge. */
1759 XGCValues xgcv;
1760 unsigned long mask;
1761
1762 xgcv.background = s->f->output_data.mac->cursor_pixel;
1763 xgcv.foreground = s->face->background;
1764
1765 /* If the glyph would be invisible, try a different foreground. */
1766 if (xgcv.foreground == xgcv.background)
1767 xgcv.foreground = s->face->foreground;
1768 if (xgcv.foreground == xgcv.background)
1769 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1770 if (xgcv.foreground == xgcv.background)
1771 xgcv.foreground = s->face->foreground;
1772
1773 /* Make sure the cursor is distinct from text in this face. */
1774 if (xgcv.background == s->face->background
1775 && xgcv.foreground == s->face->foreground)
1776 {
1777 xgcv.background = s->face->foreground;
1778 xgcv.foreground = s->face->background;
1779 }
1780
1781 IF_DEBUG (x_check_font (s->f, s->font));
1782 xgcv.font = s->font;
1783 mask = GCForeground | GCBackground | GCFont;
1784
1785 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1786 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1787 mask, &xgcv);
1788 else
1789 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1790 = XCreateGC (s->display, s->window, mask, &xgcv);
1791
1792 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1793 }
1794}
1795
1796
1797/* Set up S->gc of glyph string S for drawing text in mouse face. */
177c0ea7 1798
1a578e9b
AC
1799static void
1800x_set_mouse_face_gc (s)
1801 struct glyph_string *s;
177c0ea7 1802{
1a578e9b
AC
1803 int face_id;
1804 struct face *face;
1805
e0f712ba 1806 /* What face has to be used last for the mouse face? */
1a578e9b
AC
1807 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1808 face = FACE_FROM_ID (s->f, face_id);
e0f712ba
AC
1809 if (face == NULL)
1810 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
177c0ea7 1811
1a578e9b
AC
1812 if (s->first_glyph->type == CHAR_GLYPH)
1813 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1814 else
1815 face_id = FACE_FOR_CHAR (s->f, face, 0);
1816 s->face = FACE_FROM_ID (s->f, face_id);
1817 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1818
1819 /* If font in this face is same as S->font, use it. */
1820 if (s->font == s->face->font)
1821 s->gc = s->face->gc;
1822 else
1823 {
1824 /* Otherwise construct scratch_cursor_gc with values from FACE
1825 but font FONT. */
1826 XGCValues xgcv;
1827 unsigned long mask;
177c0ea7 1828
1a578e9b
AC
1829 xgcv.background = s->face->background;
1830 xgcv.foreground = s->face->foreground;
1831 IF_DEBUG (x_check_font (s->f, s->font));
1832 xgcv.font = s->font;
1833 mask = GCForeground | GCBackground | GCFont;
177c0ea7 1834
1a578e9b
AC
1835 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1836 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1837 mask, &xgcv);
1838 else
1839 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1840 = XCreateGC (s->display, s->window, mask, &xgcv);
177c0ea7 1841
1a578e9b
AC
1842 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1843 }
1844
1845 xassert (s->gc != 0);
1846}
1847
1848
1849/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1850 Faces to use in the mode line have already been computed when the
1851 matrix was built, so there isn't much to do, here. */
1852
1853static INLINE void
1854x_set_mode_line_face_gc (s)
1855 struct glyph_string *s;
177c0ea7 1856{
1a578e9b
AC
1857 s->gc = s->face->gc;
1858}
1859
1860
1861/* Set S->gc of glyph string S for drawing that glyph string. Set
1862 S->stippled_p to a non-zero value if the face of S has a stipple
1863 pattern. */
1864
1865static INLINE void
1866x_set_glyph_string_gc (s)
1867 struct glyph_string *s;
1868{
1869 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
177c0ea7 1870
1a578e9b
AC
1871 if (s->hl == DRAW_NORMAL_TEXT)
1872 {
1873 s->gc = s->face->gc;
1874 s->stippled_p = s->face->stipple != 0;
1875 }
1876 else if (s->hl == DRAW_INVERSE_VIDEO)
1877 {
1878 x_set_mode_line_face_gc (s);
1879 s->stippled_p = s->face->stipple != 0;
1880 }
1881 else if (s->hl == DRAW_CURSOR)
1882 {
1883 x_set_cursor_gc (s);
1884 s->stippled_p = 0;
1885 }
1886 else if (s->hl == DRAW_MOUSE_FACE)
1887 {
1888 x_set_mouse_face_gc (s);
1889 s->stippled_p = s->face->stipple != 0;
1890 }
1891 else if (s->hl == DRAW_IMAGE_RAISED
1892 || s->hl == DRAW_IMAGE_SUNKEN)
1893 {
1894 s->gc = s->face->gc;
1895 s->stippled_p = s->face->stipple != 0;
1896 }
1897 else
1898 {
1899 s->gc = s->face->gc;
1900 s->stippled_p = s->face->stipple != 0;
1901 }
1902
1903 /* GC must have been set. */
1904 xassert (s->gc != 0);
1905}
1906
1907
1a578e9b
AC
1908/* Set clipping for output of glyph string S. S may be part of a mode
1909 line or menu if we don't have X toolkit support. */
1910
1911static INLINE void
1912x_set_glyph_string_clipping (s)
1913 struct glyph_string *s;
1914{
1915 Rect r;
f9e65eb3 1916 get_glyph_string_clip_rect (s, &r);
1a578e9b
AC
1917 mac_set_clip_rectangle (s->display, s->window, &r);
1918}
1919
1920
750fc673
KS
1921/* RIF:
1922 Compute left and right overhang of glyph string S. If S is a glyph
1a578e9b
AC
1923 string for a composition, assume overhangs don't exist. */
1924
750fc673
KS
1925static void
1926mac_compute_glyph_string_overhangs (s)
1a578e9b
AC
1927 struct glyph_string *s;
1928{
750fc673
KS
1929#if 0
1930 /* MAC_TODO: XTextExtents16 does nothing yet... */
1931
1a578e9b
AC
1932 if (s->cmp == NULL
1933 && s->first_glyph->type == CHAR_GLYPH)
1934 {
1935 XCharStruct cs;
1936 int direction, font_ascent, font_descent;
1937 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
1938 &font_ascent, &font_descent, &cs);
1939 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
1940 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
1941 }
750fc673 1942#endif
1a578e9b
AC
1943}
1944
1945
1946/* Fill rectangle X, Y, W, H with background color of glyph string S. */
1947
1948static INLINE void
1949x_clear_glyph_string_rect (s, x, y, w, h)
1950 struct glyph_string *s;
1951 int x, y, w, h;
1952{
1953 XGCValues xgcv;
1954
1955 xgcv.foreground = s->gc->background;
1956 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
1957}
1958
1959
fc7a70cc
ST
1960/* We prefer not to use XDrawImageString (srcCopy text transfer mode)
1961 on Mac OS X because:
1962 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1963 into an offscreen graphics world first. So performance gain
1964 cannot be expected.)
1965 - It lowers rendering quality.
1966 - Some fonts leave garbage on cursor movement. */
1967
1a578e9b
AC
1968/* Draw the background of glyph_string S. If S->background_filled_p
1969 is non-zero don't draw it. FORCE_P non-zero means draw the
1970 background even if it wouldn't be drawn normally. This is used
1971 when a string preceding S draws into the background of S, or S
1972 contains the first component of a composition. */
1973
1974static void
1975x_draw_glyph_string_background (s, force_p)
1976 struct glyph_string *s;
1977 int force_p;
1978{
1979 /* Nothing to do if background has already been drawn or if it
1980 shouldn't be drawn in the first place. */
1981 if (!s->background_filled_p)
1982 {
e0f712ba
AC
1983 int box_line_width = max (s->face->box_line_width, 0);
1984
1a578e9b
AC
1985#if 0 /* MAC_TODO: stipple */
1986 if (s->stippled_p)
1987 {
1988 /* Fill background with a stipple pattern. */
1989 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1990 XFillRectangle (s->display, s->window, s->gc, s->x,
e0f712ba 1991 s->y + box_line_width,
1a578e9b 1992 s->background_width,
e0f712ba 1993 s->height - 2 * box_line_width);
1a578e9b
AC
1994 XSetFillStyle (s->display, s->gc, FillSolid);
1995 s->background_filled_p = 1;
1996 }
1997 else
1998#endif
b15325b2 1999#ifdef MAC_OS8
e0f712ba 2000 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1a578e9b
AC
2001 || s->font_not_found_p
2002 || s->extends_to_end_of_line_p
2003 || force_p)
fc7a70cc 2004#endif
1a578e9b 2005 {
e0f712ba 2006 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1a578e9b 2007 s->background_width,
e0f712ba 2008 s->height - 2 * box_line_width);
1a578e9b
AC
2009 s->background_filled_p = 1;
2010 }
2011 }
2012}
2013
2014
2015/* Draw the foreground of glyph string S. */
2016
2017static void
2018x_draw_glyph_string_foreground (s)
2019 struct glyph_string *s;
2020{
2021 int i, x;
2022
2023 /* If first glyph of S has a left box line, start drawing the text
2024 of S to the right of that box line. */
2025 if (s->face->box != FACE_NO_BOX
2026 && s->first_glyph->left_box_line_p)
e0f712ba 2027 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
2028 else
2029 x = s->x;
2030
2031 /* Draw characters of S as rectangles if S's font could not be
2032 loaded. */
2033 if (s->font_not_found_p)
2034 {
2035 for (i = 0; i < s->nchars; ++i)
2036 {
2037 struct glyph *g = s->first_glyph + i;
2038 mac_draw_rectangle (s->display, s->window,
2039 s->gc, x, s->y, g->pixel_width - 1,
2040 s->height - 1);
2041 x += g->pixel_width;
2042 }
2043 }
2044 else
2045 {
2046 char *char1b = (char *) s->char2b;
2047 int boff = s->font_info->baseline_offset;
2048
2049 if (s->font_info->vertical_centering)
2050 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2051
2052 /* If we can use 8-bit functions, condense S->char2b. */
2053 if (!s->two_byte_p)
2054 for (i = 0; i < s->nchars; ++i)
2055 char1b[i] = s->char2b[i].byte2;
2056
b15325b2 2057#ifdef MAC_OS8
1a578e9b
AC
2058 /* Draw text with XDrawString if background has already been
2059 filled. Otherwise, use XDrawImageString. (Note that
2060 XDrawImageString is usually faster than XDrawString.) Always
2061 use XDrawImageString when drawing the cursor so that there is
2062 no chance that characters under a box cursor are invisible. */
2063 if (s->for_overlaps_p
2064 || (s->background_filled_p && s->hl != DRAW_CURSOR))
fc7a70cc 2065#endif
1a578e9b
AC
2066 {
2067 /* Draw characters with 16-bit or 8-bit functions. */
2068 if (s->two_byte_p)
2069 XDrawString16 (s->display, s->window, s->gc, x,
2070 s->ybase - boff, s->char2b, s->nchars);
2071 else
2072 XDrawString (s->display, s->window, s->gc, x,
2073 s->ybase - boff, char1b, s->nchars);
2074 }
b15325b2 2075#ifdef MAC_OS8
1a578e9b
AC
2076 else
2077 {
2078 if (s->two_byte_p)
2079 XDrawImageString16 (s->display, s->window, s->gc, x,
2080 s->ybase - boff, s->char2b, s->nchars);
2081 else
2082 XDrawImageString (s->display, s->window, s->gc, x,
2083 s->ybase - boff, char1b, s->nchars);
2084 }
fc7a70cc 2085#endif
1a578e9b
AC
2086 }
2087}
2088
2089/* Draw the foreground of composite glyph string S. */
2090
2091static void
2092x_draw_composite_glyph_string_foreground (s)
2093 struct glyph_string *s;
2094{
2095 int i, x;
2096
2097 /* If first glyph of S has a left box line, start drawing the text
2098 of S to the right of that box line. */
2099 if (s->face->box != FACE_NO_BOX
2100 && s->first_glyph->left_box_line_p)
e0f712ba 2101 x = s->x + abs (s->face->box_line_width);
1a578e9b
AC
2102 else
2103 x = s->x;
2104
2105 /* S is a glyph string for a composition. S->gidx is the index of
2106 the first character drawn for glyphs of this composition.
2107 S->gidx == 0 means we are drawing the very first character of
2108 this composition. */
2109
2110 /* Draw a rectangle for the composition if the font for the very
2111 first character of the composition could not be loaded. */
2112 if (s->font_not_found_p)
2113 {
2114 if (s->gidx == 0)
2115 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
2116 s->width - 1, s->height - 1);
2117 }
2118 else
2119 {
2120 for (i = 0; i < s->nchars; i++, ++s->gidx)
2121 XDrawString16 (s->display, s->window, s->gc,
2122 x + s->cmp->offsets[s->gidx * 2],
2123 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2124 s->char2b + i, 1);
2125 }
2126}
2127
2128
2129#ifdef USE_X_TOOLKIT
2130
2131static struct frame *x_frame_of_widget P_ ((Widget));
2132
2133
2134/* Return the frame on which widget WIDGET is used.. Abort if frame
2135 cannot be determined. */
2136
2137static struct frame *
2138x_frame_of_widget (widget)
2139 Widget widget;
2140{
2141 struct x_display_info *dpyinfo;
2142 Lisp_Object tail;
2143 struct frame *f;
177c0ea7 2144
1a578e9b 2145 dpyinfo = x_display_info_for_display (XtDisplay (widget));
177c0ea7 2146
1a578e9b
AC
2147 /* Find the top-level shell of the widget. Note that this function
2148 can be called when the widget is not yet realized, so XtWindow
2149 (widget) == 0. That's the reason we can't simply use
2150 x_any_window_to_frame. */
2151 while (!XtIsTopLevelShell (widget))
2152 widget = XtParent (widget);
2153
2154 /* Look for a frame with that top-level widget. Allocate the color
2155 on that frame to get the right gamma correction value. */
2156 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2157 if (GC_FRAMEP (XCAR (tail))
2158 && (f = XFRAME (XCAR (tail)),
2159 (f->output_data.nothing != 1
2160 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2161 && f->output_data.x->widget == widget)
2162 return f;
2163
2164 abort ();
2165}
2166
2167
2168/* Allocate the color COLOR->pixel on the screen and display of
2169 widget WIDGET in colormap CMAP. If an exact match cannot be
2170 allocated, try the nearest color available. Value is non-zero
2171 if successful. This is called from lwlib. */
2172
2173int
2174x_alloc_nearest_color_for_widget (widget, cmap, color)
2175 Widget widget;
2176 Colormap cmap;
2177 XColor *color;
2178{
2179 struct frame *f = x_frame_of_widget (widget);
2180 return x_alloc_nearest_color (f, cmap, color);
2181}
2182
2183
2184#endif /* USE_X_TOOLKIT */
2185
e0f712ba 2186#if 0 /* MAC_TODO */
1a578e9b
AC
2187
2188/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2189 CMAP. If an exact match can't be allocated, try the nearest color
2190 available. Value is non-zero if successful. Set *COLOR to the
2191 color allocated. */
2192
2193int
2194x_alloc_nearest_color (f, cmap, color)
2195 struct frame *f;
2196 Colormap cmap;
2197 XColor *color;
2198{
2199 Display *display = FRAME_X_DISPLAY (f);
2200 Screen *screen = FRAME_X_SCREEN (f);
2201 int rc;
2202
2203 gamma_correct (f, color);
2204 rc = XAllocColor (display, cmap, color);
2205 if (rc == 0)
2206 {
2207 /* If we got to this point, the colormap is full, so we're going
2208 to try to get the next closest color. The algorithm used is
2209 a least-squares matching, which is what X uses for closest
2210 color matching with StaticColor visuals. */
2211 int nearest, i;
2212 unsigned long nearest_delta = ~0;
2213 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2214 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2215
2216 for (i = 0; i < ncells; ++i)
2217 cells[i].pixel = i;
2218 XQueryColors (display, cmap, cells, ncells);
2219
2220 for (nearest = i = 0; i < ncells; ++i)
2221 {
2222 long dred = (color->red >> 8) - (cells[i].red >> 8);
2223 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2224 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2225 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2226
2227 if (delta < nearest_delta)
2228 {
2229 nearest = i;
2230 nearest_delta = delta;
2231 }
2232 }
177c0ea7 2233
1a578e9b
AC
2234 color->red = cells[nearest].red;
2235 color->green = cells[nearest].green;
2236 color->blue = cells[nearest].blue;
2237 rc = XAllocColor (display, cmap, color);
2238 }
2239
2240#ifdef DEBUG_X_COLORS
2241 if (rc)
2242 register_color (color->pixel);
2243#endif /* DEBUG_X_COLORS */
177c0ea7 2244
1a578e9b
AC
2245 return rc;
2246}
2247
2248
2249/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2250 It's necessary to do this instead of just using PIXEL directly to
2251 get color reference counts right. */
2252
2253unsigned long
2254x_copy_color (f, pixel)
2255 struct frame *f;
2256 unsigned long pixel;
2257{
2258 XColor color;
2259
2260 color.pixel = pixel;
2261 BLOCK_INPUT;
2262 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2263 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2264 UNBLOCK_INPUT;
2265#ifdef DEBUG_X_COLORS
2266 register_color (pixel);
2267#endif
2268 return color.pixel;
2269}
2270
2271
2272/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2273 It's necessary to do this instead of just using PIXEL directly to
2274 get color reference counts right. */
2275
2276unsigned long
2277x_copy_dpy_color (dpy, cmap, pixel)
2278 Display *dpy;
2279 Colormap cmap;
2280 unsigned long pixel;
2281{
2282 XColor color;
2283
2284 color.pixel = pixel;
2285 BLOCK_INPUT;
2286 XQueryColor (dpy, cmap, &color);
2287 XAllocColor (dpy, cmap, &color);
2288 UNBLOCK_INPUT;
2289#ifdef DEBUG_X_COLORS
2290 register_color (pixel);
2291#endif
2292 return color.pixel;
2293}
2294
e0f712ba 2295#endif /* MAC_TODO */
1a578e9b 2296
e3564461
ST
2297
2298/* Brightness beyond which a color won't have its highlight brightness
2299 boosted.
2300
2301 Nominally, highlight colors for `3d' faces are calculated by
2302 brightening an object's color by a constant scale factor, but this
2303 doesn't yield good results for dark colors, so for colors who's
2304 brightness is less than this value (on a scale of 0-255) have to
2305 use an additional additive factor.
2306
2307 The value here is set so that the default menu-bar/mode-line color
2308 (grey75) will not have its highlights changed at all. */
2309#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2310
2311
1a578e9b
AC
2312/* Allocate a color which is lighter or darker than *COLOR by FACTOR
2313 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2314 If this produces the same color as COLOR, try a color where all RGB
2315 values have DELTA added. Return the allocated color in *COLOR.
2316 DISPLAY is the X display, CMAP is the colormap to operate on.
2317 Value is non-zero if successful. */
2318
2319static int
2320mac_alloc_lighter_color (f, color, factor, delta)
2321 struct frame *f;
2322 unsigned long *color;
2323 double factor;
2324 int delta;
2325{
2326 unsigned long new;
e3564461
ST
2327 long bright;
2328
2329 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2330 delta /= 256;
1a578e9b
AC
2331
2332 /* Change RGB values by specified FACTOR. Avoid overflow! */
2333 xassert (factor >= 0);
2334 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2335 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2336 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
e3564461
ST
2337
2338 /* Calculate brightness of COLOR. */
2339 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2340 + BLUE_FROM_ULONG (*color)) / 6;
2341
2342 /* We only boost colors that are darker than
2343 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2344 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2345 /* Make an additive adjustment to NEW, because it's dark enough so
2346 that scaling by FACTOR alone isn't enough. */
2347 {
2348 /* How far below the limit this color is (0 - 1, 1 being darker). */
2349 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2350 /* The additive adjustment. */
2351 int min_delta = delta * dimness * factor / 2;
2352
2353 if (factor < 1)
2354 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2355 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2356 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2357 else
2358 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2359 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2360 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2361 }
2362
1a578e9b
AC
2363 if (new == *color)
2364 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2365 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2366 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2367
2368 /* MAC_TODO: Map to palette and retry with delta if same? */
2369 /* MAC_TODO: Free colors (if using palette)? */
2370
2371 if (new == *color)
2372 return 0;
2373
2374 *color = new;
2375
2376 return 1;
2377}
2378
2379
2380/* Set up the foreground color for drawing relief lines of glyph
2381 string S. RELIEF is a pointer to a struct relief containing the GC
2382 with which lines will be drawn. Use a color that is FACTOR or
2383 DELTA lighter or darker than the relief's background which is found
2384 in S->f->output_data.x->relief_background. If such a color cannot
2385 be allocated, use DEFAULT_PIXEL, instead. */
177c0ea7 2386
1a578e9b
AC
2387static void
2388x_setup_relief_color (f, relief, factor, delta, default_pixel)
2389 struct frame *f;
2390 struct relief *relief;
2391 double factor;
2392 int delta;
2393 unsigned long default_pixel;
2394{
2395 XGCValues xgcv;
2396 struct mac_output *di = f->output_data.mac;
2397 unsigned long mask = GCForeground;
2398 unsigned long pixel;
2399 unsigned long background = di->relief_background;
2400 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2401
2402 /* MAC_TODO: Free colors (if using palette)? */
2403
2404 /* Allocate new color. */
2405 xgcv.foreground = default_pixel;
2406 pixel = background;
e3564461
ST
2407 if (dpyinfo->n_planes != 1
2408 && mac_alloc_lighter_color (f, &pixel, factor, delta))
1a578e9b
AC
2409 {
2410 relief->allocated_p = 1;
2411 xgcv.foreground = relief->pixel = pixel;
2412 }
177c0ea7 2413
1a578e9b
AC
2414 if (relief->gc == 0)
2415 {
2416#if 0 /* MAC_TODO: stipple */
2417 xgcv.stipple = dpyinfo->gray;
2418 mask |= GCStipple;
2419#endif
2420 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2421 }
2422 else
2423 XChangeGC (NULL, relief->gc, mask, &xgcv);
2424}
2425
2426
2427/* Set up colors for the relief lines around glyph string S. */
2428
2429static void
2430x_setup_relief_colors (s)
2431 struct glyph_string *s;
2432{
2433 struct mac_output *di = s->f->output_data.mac;
2434 unsigned long color;
2435
2436 if (s->face->use_box_color_for_shadows_p)
2437 color = s->face->box_color;
e3564461
ST
2438 else if (s->first_glyph->type == IMAGE_GLYPH
2439 && s->img->pixmap
2440 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2441 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1a578e9b
AC
2442 else
2443 {
2444 XGCValues xgcv;
177c0ea7 2445
1a578e9b
AC
2446 /* Get the background color of the face. */
2447 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2448 color = xgcv.background;
2449 }
2450
2451 if (di->white_relief.gc == 0
2452 || color != di->relief_background)
2453 {
2454 di->relief_background = color;
2455 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2456 WHITE_PIX_DEFAULT (s->f));
2457 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2458 BLACK_PIX_DEFAULT (s->f));
2459 }
2460}
2461
2462
2463/* Draw a relief on frame F inside the rectangle given by LEFT_X,
2464 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2465 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2466 relief. LEFT_P non-zero means draw a relief on the left side of
2467 the rectangle. RIGHT_P non-zero means draw a relief on the right
2468 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2469 when drawing. */
2470
2471static void
2472x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
ffe8b3f4 2473 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
1a578e9b 2474 struct frame *f;
ffe8b3f4
KS
2475 int left_x, top_y, right_x, bottom_y, width;
2476 int top_p, bot_p, left_p, right_p, raised_p;
1a578e9b
AC
2477 Rect *clip_rect;
2478{
e3564461
ST
2479 Display *dpy = FRAME_MAC_DISPLAY (f);
2480 Window window = FRAME_MAC_WINDOW (f);
1a578e9b
AC
2481 int i;
2482 GC gc;
177c0ea7 2483
1a578e9b
AC
2484 if (raised_p)
2485 gc = f->output_data.mac->white_relief.gc;
2486 else
2487 gc = f->output_data.mac->black_relief.gc;
e3564461 2488 mac_set_clip_rectangle (dpy, window, clip_rect);
1a578e9b
AC
2489
2490 /* Top. */
ffe8b3f4
KS
2491 if (top_p)
2492 for (i = 0; i < width; ++i)
2493 XDrawLine (dpy, window, gc,
2494 left_x + i * left_p, top_y + i,
2495 right_x - i * right_p, top_y + i);
1a578e9b
AC
2496
2497 /* Left. */
2498 if (left_p)
2499 for (i = 0; i < width; ++i)
e3564461 2500 XDrawLine (dpy, window, gc,
1a578e9b
AC
2501 left_x + i, top_y + i, left_x + i, bottom_y - i);
2502
e3564461 2503 mac_reset_clipping (dpy, window);
1a578e9b
AC
2504 if (raised_p)
2505 gc = f->output_data.mac->black_relief.gc;
2506 else
2507 gc = f->output_data.mac->white_relief.gc;
e3564461 2508 mac_set_clip_rectangle (dpy, window,
e0f712ba 2509 clip_rect);
177c0ea7 2510
1a578e9b 2511 /* Bottom. */
ffe8b3f4
KS
2512 if (bot_p)
2513 for (i = 0; i < width; ++i)
2514 XDrawLine (dpy, window, gc,
2515 left_x + i * left_p, bottom_y - i,
2516 right_x - i * right_p, bottom_y - i);
177c0ea7 2517
1a578e9b
AC
2518 /* Right. */
2519 if (right_p)
2520 for (i = 0; i < width; ++i)
e3564461
ST
2521 XDrawLine (dpy, window, gc,
2522 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
1a578e9b 2523
e3564461 2524 mac_reset_clipping (dpy, window);
1a578e9b
AC
2525}
2526
2527
2528/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2529 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2530 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2531 left side of the rectangle. RIGHT_P non-zero means draw a line
2532 on the right side of the rectangle. CLIP_RECT is the clipping
2533 rectangle to use when drawing. */
2534
2535static void
2536x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2537 left_p, right_p, clip_rect)
2538 struct glyph_string *s;
e3564461 2539 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
1a578e9b
AC
2540 Rect *clip_rect;
2541{
2542 XGCValues xgcv;
177c0ea7 2543
1a578e9b
AC
2544 xgcv.foreground = s->face->box_color;
2545 mac_set_clip_rectangle (s->display, s->window, clip_rect);
177c0ea7 2546
1a578e9b
AC
2547 /* Top. */
2548 XFillRectangle (s->display, s->window, &xgcv,
e3564461 2549 left_x, top_y, right_x - left_x + 1, width);
1a578e9b
AC
2550
2551 /* Left. */
2552 if (left_p)
2553 XFillRectangle (s->display, s->window, &xgcv,
e3564461 2554 left_x, top_y, width, bottom_y - top_y + 1);
1a578e9b
AC
2555
2556 /* Bottom. */
2557 XFillRectangle (s->display, s->window, &xgcv,
e3564461 2558 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
177c0ea7 2559
1a578e9b
AC
2560 /* Right. */
2561 if (right_p)
2562 XFillRectangle (s->display, s->window, &xgcv,
e3564461 2563 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
1a578e9b
AC
2564
2565 mac_reset_clipping (s->display, s->window);
2566}
2567
2568
2569/* Draw a box around glyph string S. */
2570
2571static void
2572x_draw_glyph_string_box (s)
2573 struct glyph_string *s;
2574{
2575 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2576 int left_p, right_p;
2577 struct glyph *last_glyph;
2578 Rect clip_rect;
2579
2580 last_x = window_box_right (s->w, s->area);
2581 if (s->row->full_width_p
2582 && !s->w->pseudo_window_p)
2583 {
f1a83aab
KS
2584 last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
2585 if (s->area != RIGHT_MARGIN_AREA
2586 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
2587 last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
1a578e9b 2588 }
177c0ea7 2589
1a578e9b
AC
2590 /* The glyph that may have a right box line. */
2591 last_glyph = (s->cmp || s->img
2592 ? s->first_glyph
2593 : s->first_glyph + s->nchars - 1);
2594
e0f712ba 2595 width = abs (s->face->box_line_width);
1a578e9b
AC
2596 raised_p = s->face->box == FACE_RAISED_BOX;
2597 left_x = s->x;
e3564461
ST
2598 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2599 ? last_x - 1
2600 : min (last_x, s->x + s->background_width) - 1);
1a578e9b
AC
2601 top_y = s->y;
2602 bottom_y = top_y + s->height - 1;
2603
2604 left_p = (s->first_glyph->left_box_line_p
2605 || (s->hl == DRAW_MOUSE_FACE
2606 && (s->prev == NULL
2607 || s->prev->hl != s->hl)));
2608 right_p = (last_glyph->right_box_line_p
2609 || (s->hl == DRAW_MOUSE_FACE
2610 && (s->next == NULL
2611 || s->next->hl != s->hl)));
177c0ea7 2612
f9e65eb3 2613 get_glyph_string_clip_rect (s, &clip_rect);
1a578e9b
AC
2614
2615 if (s->face->box == FACE_SIMPLE_BOX)
2616 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2617 left_p, right_p, &clip_rect);
2618 else
2619 {
2620 x_setup_relief_colors (s);
2621 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
ffe8b3f4 2622 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
1a578e9b
AC
2623 }
2624}
2625
2626
2627/* Draw foreground of image glyph string S. */
2628
2629static void
2630x_draw_image_foreground (s)
2631 struct glyph_string *s;
2632{
ffe8b3f4
KS
2633 int x = s->x;
2634 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1a578e9b
AC
2635
2636 /* If first glyph of S has a left box line, start drawing it to the
2637 right of that line. */
2638 if (s->face->box != FACE_NO_BOX
ffe8b3f4
KS
2639 && s->first_glyph->left_box_line_p
2640 && s->slice.x == 0)
2641 x += abs (s->face->box_line_width);
1a578e9b
AC
2642
2643 /* If there is a margin around the image, adjust x- and y-position
2644 by that margin. */
ffe8b3f4
KS
2645 if (s->slice.x == 0)
2646 x += s->img->hmargin;
2647 if (s->slice.y == 0)
2648 y += s->img->vmargin;
1a578e9b
AC
2649
2650 if (s->img->pixmap)
2651 {
fc7a70cc
ST
2652 x_set_glyph_string_clipping (s);
2653
1a578e9b 2654 if (s->img->mask)
fc7a70cc
ST
2655 mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
2656 s->window, s->gc, s->slice.x, s->slice.y,
2657 s->slice.width, s->slice.height, x, y);
1a578e9b 2658 else
1a578e9b 2659 {
fc7a70cc
ST
2660 mac_copy_area (s->display, s->img->pixmap,
2661 s->window, s->gc, s->slice.x, s->slice.y,
2662 s->slice.width, s->slice.height, x, y);
177c0ea7 2663
1a578e9b
AC
2664 /* When the image has a mask, we can expect that at
2665 least part of a mouse highlight or a block cursor will
2666 be visible. If the image doesn't have a mask, make
2667 a block cursor visible by drawing a rectangle around
2668 the image. I believe it's looking better if we do
2669 nothing here for mouse-face. */
2670 if (s->hl == DRAW_CURSOR)
534c20b2
KS
2671 {
2672 int r = s->img->relief;
2673 if (r < 0) r = -r;
ffe8b3f4
KS
2674 mac_draw_rectangle (s->display, s->window, s->gc,
2675 x - r, y - r,
2676 s->slice.width + r*2 - 1,
2677 s->slice.height + r*2 - 1);
534c20b2 2678 }
1a578e9b
AC
2679 }
2680 }
2681 else
2682 /* Draw a rectangle if image could not be loaded. */
2683 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
ffe8b3f4 2684 s->slice.width - 1, s->slice.height - 1);
1a578e9b
AC
2685}
2686
2687
2688/* Draw a relief around the image glyph string S. */
2689
2690static void
2691x_draw_image_relief (s)
2692 struct glyph_string *s;
2693{
2694 int x0, y0, x1, y1, thick, raised_p;
2695 Rect r;
ffe8b3f4
KS
2696 int x = s->x;
2697 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
177c0ea7 2698
1a578e9b
AC
2699 /* If first glyph of S has a left box line, start drawing it to the
2700 right of that line. */
2701 if (s->face->box != FACE_NO_BOX
ffe8b3f4
KS
2702 && s->first_glyph->left_box_line_p
2703 && s->slice.x == 0)
2704 x += abs (s->face->box_line_width);
177c0ea7 2705
1a578e9b
AC
2706 /* If there is a margin around the image, adjust x- and y-position
2707 by that margin. */
ffe8b3f4
KS
2708 if (s->slice.x == 0)
2709 x += s->img->hmargin;
2710 if (s->slice.y == 0)
2711 y += s->img->vmargin;
177c0ea7 2712
1a578e9b
AC
2713 if (s->hl == DRAW_IMAGE_SUNKEN
2714 || s->hl == DRAW_IMAGE_RAISED)
2715 {
e0f712ba 2716 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1a578e9b
AC
2717 raised_p = s->hl == DRAW_IMAGE_RAISED;
2718 }
2719 else
2720 {
2721 thick = abs (s->img->relief);
2722 raised_p = s->img->relief > 0;
2723 }
177c0ea7 2724
1a578e9b
AC
2725 x0 = x - thick;
2726 y0 = y - thick;
ffe8b3f4
KS
2727 x1 = x + s->slice.width + thick - 1;
2728 y1 = y + s->slice.height + thick - 1;
177c0ea7 2729
1a578e9b 2730 x_setup_relief_colors (s);
f9e65eb3 2731 get_glyph_string_clip_rect (s, &r);
ffe8b3f4
KS
2732 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2733 s->slice.y == 0,
2734 s->slice.y + s->slice.height == s->img->height,
2735 s->slice.x == 0,
2736 s->slice.x + s->slice.width == s->img->width,
2737 &r);
1a578e9b
AC
2738}
2739
2740
fc7a70cc 2741#if 0 /* TODO: figure out if we need to do this on Mac. */
1a578e9b
AC
2742/* Draw the foreground of image glyph string S to PIXMAP. */
2743
2744static void
2745x_draw_image_foreground_1 (s, pixmap)
2746 struct glyph_string *s;
2747 Pixmap pixmap;
2748{
ffe8b3f4
KS
2749 int x = 0;
2750 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
1a578e9b
AC
2751
2752 /* If first glyph of S has a left box line, start drawing it to the
2753 right of that line. */
2754 if (s->face->box != FACE_NO_BOX
ffe8b3f4
KS
2755 && s->first_glyph->left_box_line_p
2756 && s->slice.x == 0)
2757 x += abs (s->face->box_line_width);
1a578e9b
AC
2758
2759 /* If there is a margin around the image, adjust x- and y-position
2760 by that margin. */
ffe8b3f4
KS
2761 if (s->slice.x == 0)
2762 x += s->img->hmargin;
2763 if (s->slice.y == 0)
2764 y += s->img->vmargin;
1a578e9b
AC
2765
2766 if (s->img->pixmap)
2767 {
1a578e9b 2768 if (s->img->mask)
e3564461
ST
2769 mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
2770 s->img->mask, pixmap, s->gc,
ffe8b3f4
KS
2771 s->slice.x, s->slice.y,
2772 s->slice.width, s->slice.height,
e3564461 2773 x, y);
1a578e9b 2774 else
1a578e9b
AC
2775 {
2776 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
ffe8b3f4
KS
2777 s->slice.x, s->slice.y,
2778 s->slice.width, s->slice.height,
2779 x, y);
177c0ea7 2780
1a578e9b
AC
2781 /* When the image has a mask, we can expect that at
2782 least part of a mouse highlight or a block cursor will
2783 be visible. If the image doesn't have a mask, make
2784 a block cursor visible by drawing a rectangle around
2785 the image. I believe it's looking better if we do
2786 nothing here for mouse-face. */
2787 if (s->hl == DRAW_CURSOR)
534c20b2
KS
2788 {
2789 int r = s->img->relief;
2790 if (r < 0) r = -r;
e3564461 2791 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
ffe8b3f4
KS
2792 s->slice.width + r*2 - 1,
2793 s->slice.height + r*2 - 1);
534c20b2 2794 }
1a578e9b
AC
2795 }
2796 }
2797 else
2798 /* Draw a rectangle if image could not be loaded. */
2799 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
ffe8b3f4 2800 s->slice.width - 1, s->slice.height - 1);
1a578e9b 2801}
fc7a70cc 2802#endif
1a578e9b
AC
2803
2804
2805/* Draw part of the background of glyph string S. X, Y, W, and H
2806 give the rectangle to draw. */
2807
2808static void
2809x_draw_glyph_string_bg_rect (s, x, y, w, h)
2810 struct glyph_string *s;
2811 int x, y, w, h;
2812{
2813#if 0 /* MAC_TODO: stipple */
2814 if (s->stippled_p)
2815 {
2816 /* Fill background with a stipple pattern. */
2817 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2818 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2819 XSetFillStyle (s->display, s->gc, FillSolid);
2820 }
2821 else
e0f712ba 2822#endif /* MAC_TODO */
1a578e9b
AC
2823 x_clear_glyph_string_rect (s, x, y, w, h);
2824}
2825
2826
177c0ea7 2827/* Draw image glyph string S.
1a578e9b
AC
2828
2829 s->y
2830 s->x +-------------------------
2831 | s->face->box
2832 |
2833 | +-------------------------
e3564461 2834 | | s->img->margin
1a578e9b
AC
2835 | |
2836 | | +-------------------
2837 | | | the image
2838
2839 */
2840
2841static void
2842x_draw_image_glyph_string (s)
2843 struct glyph_string *s;
2844{
2845 int x, y;
e0f712ba
AC
2846 int box_line_hwidth = abs (s->face->box_line_width);
2847 int box_line_vwidth = max (s->face->box_line_width, 0);
1a578e9b
AC
2848 int height;
2849 Pixmap pixmap = 0;
2850
e0f712ba 2851 height = s->height - 2 * box_line_vwidth;
1a578e9b 2852
e3564461 2853
1a578e9b
AC
2854 /* Fill background with face under the image. Do it only if row is
2855 taller than image or if image has a clip mask to reduce
2856 flickering. */
2857 s->stippled_p = s->face->stipple != 0;
ffe8b3f4 2858 if (height > s->slice.height
83a96b4d 2859 || s->img->hmargin
e0f712ba 2860 || s->img->vmargin
1a578e9b 2861 || s->img->mask
1a578e9b
AC
2862 || s->img->pixmap == 0
2863 || s->width != s->background_width)
2864 {
ffe8b3f4
KS
2865 x = s->x;
2866 if (s->first_glyph->left_box_line_p
2867 && s->slice.x == 0)
2868 x += box_line_hwidth;
177c0ea7 2869
ffe8b3f4
KS
2870 y = s->y;
2871 if (s->slice.y == 0)
2872 y += box_line_vwidth;
e3564461 2873
fc7a70cc 2874#if 0 /* TODO: figure out if we need to do this on Mac. */
1a578e9b
AC
2875 if (s->img->mask)
2876 {
e0f712ba
AC
2877 /* Create a pixmap as large as the glyph string. Fill it
2878 with the background color. Copy the image to it, using
2879 its mask. Copy the temporary pixmap to the display. */
e3564461 2880 int depth = one_mac_display_info.n_planes;
1a578e9b
AC
2881
2882 /* Create a pixmap as large as the glyph string. */
2883 pixmap = XCreatePixmap (s->display, s->window,
2884 s->background_width,
2885 s->height, depth);
177c0ea7 2886
1a578e9b 2887 /* Fill the pixmap with the background color/stipple. */
e3564461 2888#if 0 /* TODO: stipple */
1a578e9b
AC
2889 if (s->stippled_p)
2890 {
2891 /* Fill background with a stipple pattern. */
2892 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2893 XFillRectangle (s->display, pixmap, s->gc,
2894 0, 0, s->background_width, s->height);
2895 XSetFillStyle (s->display, s->gc, FillSolid);
2896 }
2897 else
e3564461 2898#endif
1a578e9b
AC
2899 {
2900 XGCValues xgcv;
2901 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2902 &xgcv);
2903 XSetForeground (s->display, s->gc, xgcv.background);
e3564461
ST
2904 mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
2905 0, 0, s->background_width,
2906 s->height);
1a578e9b
AC
2907 XSetForeground (s->display, s->gc, xgcv.foreground);
2908 }
2909 }
2910 else
fc7a70cc 2911#endif
1a578e9b 2912 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
177c0ea7 2913
1a578e9b
AC
2914 s->background_filled_p = 1;
2915 }
2916
2917 /* Draw the foreground. */
fc7a70cc 2918#if 0 /* TODO: figure out if we need to do this on Mac. */
1a578e9b
AC
2919 if (pixmap != 0)
2920 {
2921 x_draw_image_foreground_1 (s, pixmap);
2922 x_set_glyph_string_clipping (s);
2923 mac_copy_area (s->display, pixmap, s->window, s->gc,
e3564461 2924 0, 0, s->background_width, s->height, s->x, s->y);
e0f712ba 2925 mac_reset_clipping (s->display, s->window);
1a578e9b
AC
2926 XFreePixmap (s->display, pixmap);
2927 }
2928 else
fc7a70cc 2929#endif
1a578e9b
AC
2930 x_draw_image_foreground (s);
2931
2932 /* If we must draw a relief around the image, do it. */
2933 if (s->img->relief
2934 || s->hl == DRAW_IMAGE_RAISED
2935 || s->hl == DRAW_IMAGE_SUNKEN)
2936 x_draw_image_relief (s);
2937}
2938
2939
2940/* Draw stretch glyph string S. */
2941
2942static void
2943x_draw_stretch_glyph_string (s)
2944 struct glyph_string *s;
2945{
2946 xassert (s->first_glyph->type == STRETCH_GLYPH);
2947 s->stippled_p = s->face->stipple != 0;
2948
2949 if (s->hl == DRAW_CURSOR
2950 && !x_stretch_cursor_p)
2951 {
2952 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2953 as wide as the stretch glyph. */
f1a83aab 2954 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
1a578e9b
AC
2955
2956 /* Draw cursor. */
2957 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
2958
2959 /* Clear rest using the GC of the original non-cursor face. */
2960 if (width < s->background_width)
2961 {
1a578e9b
AC
2962 int x = s->x + width, y = s->y;
2963 int w = s->background_width - width, h = s->height;
2964 Rect r;
e3564461 2965 GC gc;
1a578e9b 2966
e0f712ba
AC
2967 if (s->row->mouse_face_p
2968 && cursor_in_mouse_face_p (s->w))
2969 {
2970 x_set_mouse_face_gc (s);
2971 gc = s->gc;
2972 }
2973 else
2974 gc = s->face->gc;
177c0ea7 2975
f9e65eb3 2976 get_glyph_string_clip_rect (s, &r);
1a578e9b
AC
2977 mac_set_clip_rectangle (s->display, s->window, &r);
2978
2979#if 0 /* MAC_TODO: stipple */
2980 if (s->face->stipple)
2981 {
2982 /* Fill background with a stipple pattern. */
2983 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2984 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2985 XSetFillStyle (s->display, gc, FillSolid);
2986 }
2987 else
e0f712ba 2988#endif /* MAC_TODO */
1a578e9b
AC
2989 {
2990 XGCValues xgcv;
2991 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2992 XSetForeground (s->display, gc, xgcv.background);
2993 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2994 XSetForeground (s->display, gc, xgcv.foreground);
2995 }
e0f712ba
AC
2996
2997 mac_reset_clipping (s->display, s->window);
1a578e9b
AC
2998 }
2999 }
e0f712ba 3000 else if (!s->background_filled_p)
1a578e9b
AC
3001 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3002 s->height);
177c0ea7 3003
1a578e9b
AC
3004 s->background_filled_p = 1;
3005}
3006
3007
3008/* Draw glyph string S. */
3009
3010static void
3011x_draw_glyph_string (s)
3012 struct glyph_string *s;
3013{
e0f712ba
AC
3014 int relief_drawn_p = 0;
3015
1a578e9b
AC
3016 /* If S draws into the background of its successor, draw the
3017 background of the successor first so that S can draw into it.
3018 This makes S->next use XDrawString instead of XDrawImageString. */
3019 if (s->next && s->right_overhang && !s->for_overlaps_p)
3020 {
3021 xassert (s->next->img == NULL);
3022 x_set_glyph_string_gc (s->next);
3023 x_set_glyph_string_clipping (s->next);
3024 x_draw_glyph_string_background (s->next, 1);
3025 }
3026
3027 /* Set up S->gc, set clipping and draw S. */
3028 x_set_glyph_string_gc (s);
e0f712ba
AC
3029
3030 /* Draw relief (if any) in advance for char/composition so that the
3031 glyph string can be drawn over it. */
3032 if (!s->for_overlaps_p
3033 && s->face->box != FACE_NO_BOX
3034 && (s->first_glyph->type == CHAR_GLYPH
3035 || s->first_glyph->type == COMPOSITE_GLYPH))
3036
3037 {
3038 x_set_glyph_string_clipping (s);
3039 x_draw_glyph_string_background (s, 1);
3040 x_draw_glyph_string_box (s);
3041 x_set_glyph_string_clipping (s);
3042 relief_drawn_p = 1;
3043 }
3044 else
3045 x_set_glyph_string_clipping (s);
1a578e9b
AC
3046
3047 switch (s->first_glyph->type)
3048 {
3049 case IMAGE_GLYPH:
3050 x_draw_image_glyph_string (s);
3051 break;
3052
3053 case STRETCH_GLYPH:
3054 x_draw_stretch_glyph_string (s);
3055 break;
3056
3057 case CHAR_GLYPH:
3058 if (s->for_overlaps_p)
3059 s->background_filled_p = 1;
3060 else
e3564461 3061 x_draw_glyph_string_background (s, 0);
1a578e9b
AC
3062 x_draw_glyph_string_foreground (s);
3063 break;
3064
3065 case COMPOSITE_GLYPH:
3066 if (s->for_overlaps_p || s->gidx > 0)
3067 s->background_filled_p = 1;
3068 else
3069 x_draw_glyph_string_background (s, 1);
3070 x_draw_composite_glyph_string_foreground (s);
3071 break;
3072
3073 default:
3074 abort ();
3075 }
3076
3077 if (!s->for_overlaps_p)
3078 {
3079 /* Draw underline. */
3080 if (s->face->underline_p)
3081 {
3082 unsigned long h = 1;
3083 unsigned long dy = s->height - h;
177c0ea7 3084
1a578e9b
AC
3085 if (s->face->underline_defaulted_p)
3086 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3087 s->width, h);
3088 else
3089 {
3090 XGCValues xgcv;
3091 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3092 XSetForeground (s->display, s->gc, s->face->underline_color);
3093 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3094 s->width, h);
3095 XSetForeground (s->display, s->gc, xgcv.foreground);
3096 }
3097 }
3098
3099 /* Draw overline. */
3100 if (s->face->overline_p)
3101 {
3102 unsigned long dy = 0, h = 1;
3103
3104 if (s->face->overline_color_defaulted_p)
3105 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3106 s->width, h);
3107 else
3108 {
3109 XGCValues xgcv;
3110 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3111 XSetForeground (s->display, s->gc, s->face->overline_color);
3112 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3113 s->width, h);
3114 XSetForeground (s->display, s->gc, xgcv.foreground);
3115 }
3116 }
177c0ea7 3117
1a578e9b
AC
3118 /* Draw strike-through. */
3119 if (s->face->strike_through_p)
3120 {
3121 unsigned long h = 1;
3122 unsigned long dy = (s->height - h) / 2;
3123
3124 if (s->face->strike_through_color_defaulted_p)
3125 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3126 s->width, h);
3127 else
3128 {
3129 XGCValues xgcv;
3130 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3131 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3132 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3133 s->width, h);
3134 XSetForeground (s->display, s->gc, xgcv.foreground);
3135 }
3136 }
177c0ea7 3137
e3564461 3138 /* Draw relief if not yet drawn. */
e0f712ba 3139 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
e3564461 3140 x_draw_glyph_string_box (s);
1a578e9b 3141 }
e0f712ba 3142
1a578e9b
AC
3143 /* Reset clipping. */
3144 mac_reset_clipping (s->display, s->window);
3145}
3146
f9e65eb3 3147/* Shift display to make room for inserted glyphs. */
1a578e9b 3148
f9e65eb3
KS
3149void
3150mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3151 struct frame *f;
3152 int x, y, width, height, shift_by;
1a578e9b 3153{
1a578e9b 3154 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
f9e65eb3
KS
3155 f->output_data.mac->normal_gc,
3156 x, y, width, height,
3157 x + shift_by, y);
1a578e9b
AC
3158}
3159
1a578e9b
AC
3160/* Delete N glyphs at the nominal cursor position. Not implemented
3161 for X frames. */
3162
e0f712ba 3163static void
1a578e9b
AC
3164x_delete_glyphs (n)
3165 register int n;
3166{
3167 abort ();
3168}
3169
3170
1a578e9b
AC
3171/* Clear entire frame. If updating_frame is non-null, clear that
3172 frame. Otherwise clear the selected frame. */
3173
e0f712ba 3174static void
1a578e9b
AC
3175x_clear_frame ()
3176{
3177 struct frame *f;
3178
3179 if (updating_frame)
3180 f = updating_frame;
3181 else
3182 f = SELECTED_FRAME ();
3183
3184 /* Clearing the frame will erase any cursor, so mark them all as no
3185 longer visible. */
3186 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3187 output_cursor.hpos = output_cursor.vpos = 0;
3188 output_cursor.x = -1;
3189
3190 /* We don't set the output cursor here because there will always
3191 follow an explicit cursor_to. */
3192 BLOCK_INPUT;
3193 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3194
3195#if 0 /* Clearing frame on Mac OS clears scroll bars. */
3196 /* We have to clear the scroll bars, too. If we have changed
3197 colors or something like that, then they should be notified. */
3198 x_scroll_bar_clear (f);
3199#endif
3200
3201 XFlush (FRAME_MAC_DISPLAY (f));
3202 UNBLOCK_INPUT;
3203}
3204
3205
3206\f
3207/* Invert the middle quarter of the frame for .15 sec. */
3208
3209/* We use the select system call to do the waiting, so we have to make
3210 sure it's available. If it isn't, we just won't do visual bells. */
3211
3212#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3213
e3564461 3214
1a578e9b
AC
3215/* Subtract the `struct timeval' values X and Y, storing the result in
3216 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3217
3218static int
3219timeval_subtract (result, x, y)
3220 struct timeval *result, x, y;
3221{
3222 /* Perform the carry for the later subtraction by updating y. This
3223 is safer because on some systems the tv_sec member is unsigned. */
3224 if (x.tv_usec < y.tv_usec)
3225 {
3226 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3227 y.tv_usec -= 1000000 * nsec;
3228 y.tv_sec += nsec;
3229 }
177c0ea7 3230
1a578e9b
AC
3231 if (x.tv_usec - y.tv_usec > 1000000)
3232 {
3233 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3234 y.tv_usec += 1000000 * nsec;
3235 y.tv_sec -= nsec;
3236 }
3237
3238 /* Compute the time remaining to wait. tv_usec is certainly
3239 positive. */
3240 result->tv_sec = x.tv_sec - y.tv_sec;
3241 result->tv_usec = x.tv_usec - y.tv_usec;
3242
3243 /* Return indication of whether the result should be considered
3244 negative. */
3245 return x.tv_sec < y.tv_sec;
3246}
3247
3248void
3249XTflash (f)
3250 struct frame *f;
3251{
3252 BLOCK_INPUT;
3253
3254 FlashMenuBar (0);
3255
3256 {
3257 struct timeval wakeup;
3258
3259 EMACS_GET_TIME (wakeup);
3260
3261 /* Compute time to wait until, propagating carry from usecs. */
3262 wakeup.tv_usec += 150000;
3263 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3264 wakeup.tv_usec %= 1000000;
3265
3266 /* Keep waiting until past the time wakeup. */
3267 while (1)
3268 {
3269 struct timeval timeout;
3270
3271 EMACS_GET_TIME (timeout);
3272
3273 /* In effect, timeout = wakeup - timeout.
3274 Break if result would be negative. */
3275 if (timeval_subtract (&timeout, wakeup, timeout))
3276 break;
3277
3278 /* Try to wait that long--but we might wake up sooner. */
3279 select (0, NULL, NULL, NULL, &timeout);
3280 }
3281 }
177c0ea7 3282
1a578e9b
AC
3283 FlashMenuBar (0);
3284
3285 UNBLOCK_INPUT;
3286}
3287
3288#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3289
3290
3291/* Make audible bell. */
3292
3293void
3294XTring_bell ()
3295{
3296 struct frame *f = SELECTED_FRAME ();
177c0ea7 3297
1a578e9b
AC
3298#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3299 if (visible_bell)
3300 XTflash (f);
3301 else
3302#endif
3303 {
3304 BLOCK_INPUT;
3305 SysBeep (1);
3306 XFlush (FRAME_MAC_DISPLAY (f));
3307 UNBLOCK_INPUT;
3308 }
3309}
3310
3311
3312\f
3313/* Specify how many text lines, from the top of the window,
3314 should be affected by insert-lines and delete-lines operations.
3315 This, and those operations, are used only within an update
3316 that is bounded by calls to x_update_begin and x_update_end. */
3317
e3564461 3318static void
1a578e9b
AC
3319XTset_terminal_window (n)
3320 register int n;
3321{
3322 /* This function intentionally left blank. */
3323}
3324
3325
3326\f
3327/***********************************************************************
3328 Line Dance
3329 ***********************************************************************/
3330
3331/* Perform an insert-lines or delete-lines operation, inserting N
3332 lines or deleting -N lines at vertical position VPOS. */
3333
e0f712ba 3334static void
1a578e9b
AC
3335x_ins_del_lines (vpos, n)
3336 int vpos, n;
3337{
3338 abort ();
3339}
3340
3341
3342/* Scroll part of the display as described by RUN. */
3343
e0f712ba 3344static void
1a578e9b
AC
3345x_scroll_run (w, run)
3346 struct window *w;
3347 struct run *run;
3348{
3349 struct frame *f = XFRAME (w->frame);
3350 int x, y, width, height, from_y, to_y, bottom_y;
3351
3352 /* Get frame-relative bounding box of the text display area of W,
3f332ef3 3353 without mode lines. Include in this box the left and right
e3564461 3354 fringe of W. */
1a578e9b 3355 window_box (w, -1, &x, &y, &width, &height);
1a578e9b
AC
3356
3357 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3358 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3359 bottom_y = y + height;
3360
3361 if (to_y < from_y)
3362 {
3363 /* Scrolling up. Make sure we don't copy part of the mode
3364 line at the bottom. */
3365 if (from_y + run->height > bottom_y)
3366 height = bottom_y - from_y;
3367 else
3368 height = run->height;
3369 }
3370 else
3371 {
3372 /* Scolling down. Make sure we don't copy over the mode line.
3373 at the bottom. */
3374 if (to_y + run->height > bottom_y)
3375 height = bottom_y - to_y;
3376 else
3377 height = run->height;
3378 }
3379
3380 BLOCK_INPUT;
177c0ea7 3381
1a578e9b
AC
3382 /* Cursor off. Will be switched on again in x_update_window_end. */
3383 updated_window = w;
3384 x_clear_cursor (w);
3385
3386 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3387 f->output_data.mac->normal_gc,
3388 x, from_y,
3389 width, height,
3390 x, to_y);
177c0ea7 3391
1a578e9b
AC
3392 UNBLOCK_INPUT;
3393}
3394
3395
3396\f
3397/***********************************************************************
3398 Exposure Events
3399 ***********************************************************************/
177c0ea7 3400
f9e65eb3
KS
3401\f
3402static void
3403frame_highlight (f)
3404 struct frame *f;
3405{
3406 x_update_cursor (f, 1);
3407}
1a578e9b
AC
3408
3409static void
f9e65eb3 3410frame_unhighlight (f)
1a578e9b 3411 struct frame *f;
1a578e9b 3412{
f9e65eb3
KS
3413 x_update_cursor (f, 1);
3414}
3415
3416/* The focus has changed. Update the frames as necessary to reflect
3417 the new situation. Note that we can't change the selected frame
3418 here, because the Lisp code we are interrupting might become confused.
3419 Each event gets marked with the frame in which it occurred, so the
3420 Lisp code can tell when the switch took place by examining the events. */
1a578e9b 3421
f9e65eb3
KS
3422static void
3423x_new_focus_frame (dpyinfo, frame)
3424 struct x_display_info *dpyinfo;
3425 struct frame *frame;
3426{
3427 struct frame *old_focus = dpyinfo->x_focus_frame;
1a578e9b 3428
f9e65eb3 3429 if (frame != dpyinfo->x_focus_frame)
1a578e9b 3430 {
f9e65eb3
KS
3431 /* Set this before calling other routines, so that they see
3432 the correct value of x_focus_frame. */
3433 dpyinfo->x_focus_frame = frame;
1a578e9b 3434
f9e65eb3
KS
3435 if (old_focus && old_focus->auto_lower)
3436 x_lower_frame (old_focus);
1a578e9b 3437
f9e65eb3
KS
3438#if 0
3439 selected_frame = frame;
3440 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3441 selected_frame);
f1321dc3 3442 Fselect_window (selected_frame->selected_window, Qnil);
f9e65eb3
KS
3443 choose_minibuf_frame ();
3444#endif /* ! 0 */
1a578e9b 3445
f9e65eb3
KS
3446 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3447 pending_autoraise_frame = dpyinfo->x_focus_frame;
3448 else
3449 pending_autoraise_frame = 0;
1a578e9b 3450 }
1a578e9b 3451
f9e65eb3
KS
3452 x_frame_rehighlight (dpyinfo);
3453}
1a578e9b 3454
f9e65eb3 3455/* Handle an event saying the mouse has moved out of an Emacs frame. */
1a578e9b 3456
f9e65eb3
KS
3457void
3458x_mouse_leave (dpyinfo)
3459 struct x_display_info *dpyinfo;
1a578e9b 3460{
f9e65eb3 3461 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
1a578e9b
AC
3462}
3463
f9e65eb3
KS
3464/* The focus has changed, or we have redirected a frame's focus to
3465 another frame (this happens when a frame uses a surrogate
3466 mini-buffer frame). Shift the highlight as appropriate.
1a578e9b 3467
f9e65eb3
KS
3468 The FRAME argument doesn't necessarily have anything to do with which
3469 frame is being highlighted or un-highlighted; we only use it to find
3470 the appropriate X display info. */
1a578e9b
AC
3471
3472static void
f9e65eb3 3473XTframe_rehighlight (frame)
1a578e9b
AC
3474 struct frame *frame;
3475{
1a578e9b
AC
3476 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3477}
3478
3479static void
3480x_frame_rehighlight (dpyinfo)
3481 struct x_display_info *dpyinfo;
3482{
3483 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3484
3485 if (dpyinfo->x_focus_frame)
3486 {
3487 dpyinfo->x_highlight_frame
3488 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3489 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3490 : dpyinfo->x_focus_frame);
3491 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3492 {
3493 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3494 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3495 }
3496 }
3497 else
3498 dpyinfo->x_highlight_frame = 0;
3499
3500 if (dpyinfo->x_highlight_frame != old_highlight)
3501 {
3502 if (old_highlight)
3503 frame_unhighlight (old_highlight);
3504 if (dpyinfo->x_highlight_frame)
3505 frame_highlight (dpyinfo->x_highlight_frame);
3506 }
3507}
3508
3509
3510\f
3511/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3512
e0f712ba 3513#if 0 /* MAC_TODO */
1a578e9b
AC
3514/* Initialize mode_switch_bit and modifier_meaning. */
3515static void
3516x_find_modifier_meanings (dpyinfo)
3517 struct x_display_info *dpyinfo;
3518{
3519 int min_code, max_code;
3520 KeySym *syms;
3521 int syms_per_code;
3522 XModifierKeymap *mods;
3523
3524 dpyinfo->meta_mod_mask = 0;
3525 dpyinfo->shift_lock_mask = 0;
3526 dpyinfo->alt_mod_mask = 0;
3527 dpyinfo->super_mod_mask = 0;
3528 dpyinfo->hyper_mod_mask = 0;
3529
3530#ifdef HAVE_X11R4
3531 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3532#else
3533 min_code = dpyinfo->display->min_keycode;
3534 max_code = dpyinfo->display->max_keycode;
3535#endif
3536
3537 syms = XGetKeyboardMapping (dpyinfo->display,
3538 min_code, max_code - min_code + 1,
3539 &syms_per_code);
3540 mods = XGetModifierMapping (dpyinfo->display);
3541
3542 /* Scan the modifier table to see which modifier bits the Meta and
3543 Alt keysyms are on. */
3544 {
3545 int row, col; /* The row and column in the modifier table. */
3546
3547 for (row = 3; row < 8; row++)
3548 for (col = 0; col < mods->max_keypermod; col++)
3549 {
3550 KeyCode code
3551 = mods->modifiermap[(row * mods->max_keypermod) + col];
3552
3553 /* Zeroes are used for filler. Skip them. */
3554 if (code == 0)
3555 continue;
3556
3557 /* Are any of this keycode's keysyms a meta key? */
3558 {
3559 int code_col;
3560
3561 for (code_col = 0; code_col < syms_per_code; code_col++)
3562 {
3563 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3564
3565 switch (sym)
3566 {
3567 case XK_Meta_L:
3568 case XK_Meta_R:
3569 dpyinfo->meta_mod_mask |= (1 << row);
3570 break;
3571
3572 case XK_Alt_L:
3573 case XK_Alt_R:
3574 dpyinfo->alt_mod_mask |= (1 << row);
3575 break;
3576
3577 case XK_Hyper_L:
3578 case XK_Hyper_R:
3579 dpyinfo->hyper_mod_mask |= (1 << row);
3580 break;
3581
3582 case XK_Super_L:
3583 case XK_Super_R:
3584 dpyinfo->super_mod_mask |= (1 << row);
3585 break;
3586
3587 case XK_Shift_Lock:
3588 /* Ignore this if it's not on the lock modifier. */
3589 if ((1 << row) == LockMask)
3590 dpyinfo->shift_lock_mask = LockMask;
3591 break;
3592 }
3593 }
3594 }
3595 }
3596 }
3597
3598 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3599 if (! dpyinfo->meta_mod_mask)
3600 {
3601 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3602 dpyinfo->alt_mod_mask = 0;
3603 }
3604
3605 /* If some keys are both alt and meta,
3606 make them just meta, not alt. */
3607 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3608 {
3609 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3610 }
3611
3612 XFree ((char *) syms);
3613 XFreeModifiermap (mods);
3614}
3615
e0f712ba 3616#endif /* MAC_TODO */
1a578e9b
AC
3617
3618/* Convert between the modifier bits X uses and the modifier bits
3619 Emacs uses. */
3620
3621static unsigned int
3622x_mac_to_emacs_modifiers (dpyinfo, state)
3623 struct x_display_info *dpyinfo;
3624 unsigned short state;
3625{
3626 return (((state & shiftKey) ? shift_modifier : 0)
3627 | ((state & controlKey) ? ctrl_modifier : 0)
3628 | ((state & cmdKey) ? meta_modifier : 0)
3629 | ((state & optionKey) ? alt_modifier : 0));
3630}
3631
e0f712ba 3632#if 0 /* MAC_TODO */
1a578e9b
AC
3633static unsigned short
3634x_emacs_to_x_modifiers (dpyinfo, state)
3635 struct x_display_info *dpyinfo;
3636 unsigned int state;
3637{
3638 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3639 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3640 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3641 | ((state & shift_modifier) ? ShiftMask : 0)
3642 | ((state & ctrl_modifier) ? ControlMask : 0)
3643 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3644}
e0f712ba 3645#endif /* MAC_TODO */
1a578e9b
AC
3646
3647/* Convert a keysym to its name. */
3648
3649char *
3650x_get_keysym_name (keysym)
3651 int keysym;
3652{
3653 char *value;
3654
3655 BLOCK_INPUT;
3656#if 0
3657 value = XKeysymToString (keysym);
3658#else
3659 value = 0;
3660#endif
3661 UNBLOCK_INPUT;
3662
3663 return value;
3664}
3665
3666
3667\f
b15325b2 3668#if 0
1a578e9b
AC
3669/* Mouse clicks and mouse movement. Rah. */
3670
f9e65eb3 3671/* Prepare a mouse-event in *RESULT for placement in the input queue.
1a578e9b 3672
f9e65eb3
KS
3673 If the event is a button press, then note that we have grabbed
3674 the mouse. */
1a578e9b 3675
f9e65eb3
KS
3676static Lisp_Object
3677construct_mouse_click (result, event, f)
3678 struct input_event *result;
3679 EventRecord *event;
3680 struct frame *f;
3681{
3682 Point mouseLoc;
1a578e9b 3683
f9e65eb3
KS
3684 result->kind = MOUSE_CLICK_EVENT;
3685 result->code = 0; /* only one mouse button */
3686 result->timestamp = event->when;
3687 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
1a578e9b 3688
f9e65eb3 3689 mouseLoc = event->where;
1a578e9b 3690
50bf7673 3691 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1a578e9b 3692
f9e65eb3
KS
3693 GlobalToLocal (&mouseLoc);
3694 XSETINT (result->x, mouseLoc.h);
3695 XSETINT (result->y, mouseLoc.v);
e0f712ba 3696
f9e65eb3 3697 XSETFRAME (result->frame_or_window, f);
1a578e9b 3698
f9e65eb3
KS
3699 result->arg = Qnil;
3700 return Qnil;
1a578e9b 3701}
b15325b2 3702#endif
1a578e9b 3703
f9e65eb3
KS
3704\f
3705/* Function to report a mouse movement to the mainstream Emacs code.
3706 The input handler calls this.
3707
3708 We have received a mouse movement event, which is given in *event.
3709 If the mouse is over a different glyph than it was last time, tell
3710 the mainstream emacs code by setting mouse_moved. If not, ask for
3711 another motion event, so we can check again the next time it moves. */
1a578e9b 3712
f9e65eb3
KS
3713static Point last_mouse_motion_position;
3714static Lisp_Object last_mouse_motion_frame;
1a578e9b 3715
e0f712ba 3716static void
f9e65eb3
KS
3717note_mouse_movement (frame, pos)
3718 FRAME_PTR frame;
3719 Point *pos;
1a578e9b 3720{
50bf7673 3721 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
f9e65eb3
KS
3722#if TARGET_API_MAC_CARBON
3723 Rect r;
3724#endif
1a578e9b 3725
f9e65eb3
KS
3726 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3727 last_mouse_motion_position = *pos;
3728 XSETFRAME (last_mouse_motion_frame, frame);
3729
3730#if TARGET_API_MAC_CARBON
3731 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3732#else
3733 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3734#endif
3735 {
50bf7673
ST
3736 if (frame == dpyinfo->mouse_face_mouse_frame)
3737 /* This case corresponds to LeaveNotify in X11. */
3738 {
3739 /* If we move outside the frame, then we're certainly no
3740 longer on any text in the frame. */
3741 clear_mouse_face (dpyinfo);
3742 dpyinfo->mouse_face_mouse_frame = 0;
3743 if (!dpyinfo->grabbed)
3744 rif->define_frame_cursor (frame,
3745 frame->output_data.mac->nontext_cursor);
3746 }
f9e65eb3
KS
3747 }
3748 /* Has the mouse moved off the glyph it was on at the last sighting? */
3749 else if (pos->h < last_mouse_glyph.left
3750 || pos->h >= last_mouse_glyph.right
3751 || pos->v < last_mouse_glyph.top
3752 || pos->v >= last_mouse_glyph.bottom)
3753 {
3754 frame->mouse_moved = 1;
3755 last_mouse_scroll_bar = Qnil;
3756 note_mouse_highlight (frame, pos->h, pos->v);
3757 }
1a578e9b
AC
3758}
3759
f9e65eb3 3760/* This is used for debugging, to turn off note_mouse_highlight. */
1a578e9b 3761
f9e65eb3 3762int disable_mouse_highlight;
1a578e9b 3763
1a578e9b 3764
1a578e9b 3765\f
f9e65eb3
KS
3766/************************************************************************
3767 Mouse Face
3768 ************************************************************************/
3769
1a578e9b
AC
3770static struct scroll_bar *x_window_to_scroll_bar ();
3771static void x_scroll_bar_report_motion ();
e0f712ba
AC
3772static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3773
3774
f9e65eb3
KS
3775/* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3776
3777static void
3778redo_mouse_highlight ()
3779{
3780 if (!NILP (last_mouse_motion_frame)
3781 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3782 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3783 last_mouse_motion_position.h,
3784 last_mouse_motion_position.v);
3785}
3786
3787
e0f712ba
AC
3788/* Try to determine frame pixel position and size of the glyph under
3789 frame pixel coordinates X/Y on frame F . Return the position and
3790 size in *RECT. Value is non-zero if we could compute these
3791 values. */
3792
3793static int
3794glyph_rect (f, x, y, rect)
3795 struct frame *f;
3796 int x, y;
3797 Rect *rect;
3798{
3799 Lisp_Object window;
e0f712ba 3800
f1a83aab
KS
3801 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3802
e0f712ba
AC
3803 if (!NILP (window))
3804 {
3805 struct window *w = XWINDOW (window);
3806 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3807 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3808
e0f712ba
AC
3809 for (; r < end && r->enabled_p; ++r)
3810 if (r->y <= y && r->y + r->height > y)
3811 {
3812 /* Found the row at y. */
3813 struct glyph *g = r->glyphs[TEXT_AREA];
3814 struct glyph *end = g + r->used[TEXT_AREA];
3815 int gx;
3816
3817 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3818 rect->bottom = rect->top + r->height;
3819
3820 if (x < r->x)
3821 {
3822 /* x is to the left of the first glyph in the row. */
f1a83aab
KS
3823 /* Shouldn't this be a pixel value?
3824 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3825 ++KFS */
3826 rect->left = WINDOW_LEFT_EDGE_COL (w);
e0f712ba
AC
3827 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3828 return 1;
3829 }
3830
3831 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3832 if (gx <= x && gx + g->pixel_width > x)
3833 {
3834 /* x is on a glyph. */
3835 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3836 rect->right = rect->left + g->pixel_width;
3837 return 1;
3838 }
3839
3840 /* x is to the right of the last glyph in the row. */
3841 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
ffe8b3f4 3842 /* Shouldn't this be a pixel value?
f1a83aab
KS
3843 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3844 ++KFS */
3845 rect->right = WINDOW_RIGHT_EDGE_COL (w);
e0f712ba
AC
3846 return 1;
3847 }
3848 }
3849
3850 /* The y is not on any row. */
3851 return 0;
3852}
3853
f9e65eb3
KS
3854/* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3855
e0f712ba
AC
3856/* Record the position of the mouse in last_mouse_glyph. */
3857static void
3858remember_mouse_glyph (f1, gx, gy)
3859 struct frame * f1;
3860 int gx, gy;
3861{
3862 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3863 {
3864 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3865 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3866
f1a83aab 3867 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
e0f712ba
AC
3868 round down even for negative values. */
3869 if (gx < 0)
3870 gx -= width - 1;
3871 if (gy < 0)
3872 gy -= height - 1;
3873#if 0
3874 /* This was the original code from XTmouse_position, but it seems
3875 to give the position of the glyph diagonally next to the one
3876 the mouse is over. */
3877 gx = (gx + width - 1) / width * width;
3878 gy = (gy + height - 1) / height * height;
3879#else
3880 gx = gx / width * width;
3881 gy = gy / height * height;
3882#endif
3883
3884 last_mouse_glyph.left = gx;
3885 last_mouse_glyph.top = gy;
3886 last_mouse_glyph.right = gx + width;
3887 last_mouse_glyph.bottom = gy + height;
3888 }
3889}
1a578e9b 3890
f9e65eb3 3891
50bf7673 3892static WindowPtr
bf06c82f 3893front_emacs_window ()
50bf7673
ST
3894{
3895#if TARGET_API_MAC_CARBON
bf06c82f
ST
3896 WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
3897
3898 while (wp && !is_emacs_window (wp))
3899 wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
50bf7673 3900#else
bf06c82f 3901 WindowPtr wp = FrontWindow ();
50bf7673 3902
bf06c82f
ST
3903 while (wp && (wp == tip_window || !is_emacs_window (wp)))
3904 wp = GetNextWindow (wp);
50bf7673 3905#endif
bf06c82f
ST
3906
3907 return wp;
50bf7673
ST
3908}
3909
3910#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3911
1a578e9b
AC
3912/* Return the current position of the mouse.
3913 *fp should be a frame which indicates which display to ask about.
3914
3915 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3916 and *part to the frame, window, and scroll bar part that the mouse
3917 is over. Set *x and *y to the portion and whole of the mouse's
3918 position on the scroll bar.
3919
3920 If the mouse movement started elsewhere, set *fp to the frame the
3921 mouse is on, *bar_window to nil, and *x and *y to the character cell
3922 the mouse is over.
3923
3924 Set *time to the server time-stamp for the time at which the mouse
3925 was at this position.
3926
3927 Don't store anything if we don't have a valid set of values to report.
3928
3929 This clears the mouse_moved flag, so we can wait for the next mouse
3930 movement. */
3931
e0f712ba 3932static void
1a578e9b
AC
3933XTmouse_position (fp, insist, bar_window, part, x, y, time)
3934 FRAME_PTR *fp;
3935 int insist;
3936 Lisp_Object *bar_window;
3937 enum scroll_bar_part *part;
3938 Lisp_Object *x, *y;
3939 unsigned long *time;
3940{
3941 Point mouse_pos;
3942 int ignore1, ignore2;
bf06c82f 3943 WindowPtr wp = front_emacs_window ();
5883787c 3944 struct frame *f;
1a578e9b
AC
3945 Lisp_Object frame, tail;
3946
5883787c 3947 if (is_emacs_window(wp))
50bf7673 3948 f = mac_window_to_frame (wp);
5883787c 3949
1a578e9b
AC
3950 BLOCK_INPUT;
3951
3952 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3953 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3954 else
3955 {
3956 /* Clear the mouse-moved flag for every frame on this display. */
3957 FOR_EACH_FRAME (tail, frame)
3958 XFRAME (frame)->mouse_moved = 0;
3959
3960 last_mouse_scroll_bar = Qnil;
3961
50bf7673 3962 SetPortWindowPort (wp);
e0f712ba 3963
1a578e9b
AC
3964 GetMouse (&mouse_pos);
3965
3966 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
3967 &last_mouse_glyph, insist);
3968
3969 *bar_window = Qnil;
3970 *part = scroll_bar_handle;
3971 *fp = f;
3972 XSETINT (*x, mouse_pos.h);
3973 XSETINT (*y, mouse_pos.v);
3974 *time = last_mouse_movement_time;
3975 }
177c0ea7 3976
1a578e9b
AC
3977 UNBLOCK_INPUT;
3978}
3979
3980\f
f9e65eb3
KS
3981/***********************************************************************
3982 Tool-bars
3983 ***********************************************************************/
3984
3985/* Handle mouse button event on the tool-bar of frame F, at
3986 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3987 or ButtonRelase. */
3988
3989static void
3990mac_handle_tool_bar_click (f, button_event)
3991 struct frame *f;
3992 EventRecord *button_event;
3993{
3994 int x = button_event->where.h;
3995 int y = button_event->where.v;
3996
3997 if (button_event->what == mouseDown)
3998 handle_tool_bar_click (f, x, y, 1, 0);
3999 else
ffe8b3f4 4000 handle_tool_bar_click (f, x, y, 0,
f9e65eb3
KS
4001 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
4002 button_event->modifiers));
4003}
4004
4005\f
1a578e9b
AC
4006/************************************************************************
4007 Scroll bars, general
4008 ************************************************************************/
177c0ea7 4009
1a578e9b
AC
4010/* Create a scroll bar and return the scroll bar vector for it. W is
4011 the Emacs window on which to create the scroll bar. TOP, LEFT,
e0f712ba 4012 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
1a578e9b
AC
4013 scroll bar. */
4014
4015static struct scroll_bar *
4016x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4017 struct window *w;
4018 int top, left, width, height, disp_top, disp_height;
4019{
4020 struct frame *f = XFRAME (w->frame);
4021 struct scroll_bar *bar
4022 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4023 Rect r;
4024 ControlHandle ch;
4025
4026 BLOCK_INPUT;
4027
4028 r.left = left;
4029 r.top = disp_top;
4030 r.right = left + width;
4031 r.bottom = disp_top + disp_height;
177c0ea7 4032
b15325b2 4033#if TARGET_API_MAC_CARBON
e0f712ba
AC
4034 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4035 kControlScrollBarProc, 0L);
4036#else
1a578e9b
AC
4037 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
4038 0L);
e0f712ba 4039#endif
1a578e9b
AC
4040 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4041 SetControlReference (ch, (long) bar);
4042
4043 XSETWINDOW (bar->window, w);
4044 XSETINT (bar->top, top);
4045 XSETINT (bar->left, left);
4046 XSETINT (bar->width, width);
4047 XSETINT (bar->height, height);
4048 XSETINT (bar->start, 0);
4049 XSETINT (bar->end, 0);
4050 bar->dragging = Qnil;
4051
4052 /* Add bar to its frame's list of scroll bars. */
4053 bar->next = FRAME_SCROLL_BARS (f);
4054 bar->prev = Qnil;
4055 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4056 if (!NILP (bar->next))
4057 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4058
4059 UNBLOCK_INPUT;
4060 return bar;
4061}
4062
4063
4064/* Draw BAR's handle in the proper position.
177c0ea7 4065
1a578e9b
AC
4066 If the handle is already drawn from START to END, don't bother
4067 redrawing it, unless REBUILD is non-zero; in that case, always
4068 redraw it. (REBUILD is handy for drawing the handle after expose
4069 events.)
4070
4071 Normally, we want to constrain the start and end of the handle to
4072 fit inside its rectangle, but if the user is dragging the scroll
4073 bar handle, we want to let them drag it down all the way, so that
4074 the bar's top is as far down as it goes; otherwise, there's no way
4075 to move to the very end of the buffer. */
4076
4077static void
4078x_scroll_bar_set_handle (bar, start, end, rebuild)
4079 struct scroll_bar *bar;
4080 int start, end;
4081 int rebuild;
4082{
4083 int dragging = ! NILP (bar->dragging);
4084 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4085 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba
AC
4086 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4087 int length = end - start;
1a578e9b
AC
4088
4089 /* If the display is already accurate, do nothing. */
4090 if (! rebuild
4091 && start == XINT (bar->start)
4092 && end == XINT (bar->end))
4093 return;
4094
4095 BLOCK_INPUT;
4096
e0f712ba
AC
4097 /* Make sure the values are reasonable, and try to preserve the
4098 distance between start and end. */
4099 if (start < 0)
4100 start = 0;
4101 else if (start > top_range)
4102 start = top_range;
4103 end = start + length;
177c0ea7 4104
e0f712ba
AC
4105 if (end < start)
4106 end = start;
4107 else if (end > top_range && ! dragging)
4108 end = top_range;
4109
4110 /* Store the adjusted setting in the scroll bar. */
4111 XSETINT (bar->start, start);
4112 XSETINT (bar->end, end);
4113
4114 /* Clip the end position, just for display. */
4115 if (end > top_range)
4116 end = top_range;
4117
4118 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4119 top positions, to make sure the handle is always at least that
4120 many pixels tall. */
4121 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4122
4123 SetControlMinimum (ch, 0);
4124 /* Don't inadvertently activate deactivated scroll bars */
4125 if (GetControlMaximum (ch) != -1)
4126 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4127 - (end - start));
4128 SetControlValue (ch, start);
4129#if TARGET_API_MAC_CARBON
4130 SetControlViewSize (ch, end - start);
1a578e9b 4131#endif
1a578e9b
AC
4132
4133 UNBLOCK_INPUT;
4134}
4135
4136
4137/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4138 nil. */
4139
4140static void
4141x_scroll_bar_remove (bar)
4142 struct scroll_bar *bar;
4143{
4144 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
e0f712ba 4145
1a578e9b
AC
4146 BLOCK_INPUT;
4147
4148 /* Destroy the Mac scroll bar control */
4149 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4150
4151 /* Disassociate this scroll bar from its window. */
4152 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4153
4154 UNBLOCK_INPUT;
4155}
4156
1a578e9b
AC
4157/* Set the handle of the vertical scroll bar for WINDOW to indicate
4158 that we are displaying PORTION characters out of a total of WHOLE
4159 characters, starting at POSITION. If WINDOW has no scroll bar,
4160 create one. */
1a578e9b
AC
4161static void
4162XTset_vertical_scroll_bar (w, portion, whole, position)
4163 struct window *w;
4164 int portion, whole, position;
4165{
4166 struct frame *f = XFRAME (w->frame);
4167 struct scroll_bar *bar;
4168 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
f1a83aab 4169 int window_y, window_height;
1a578e9b
AC
4170
4171 /* Get window dimensions. */
f1a83aab 4172 window_box (w, -1, 0, &window_y, 0, &window_height);
1a578e9b 4173 top = window_y;
e0f712ba
AC
4174#ifdef MAC_OSX
4175 width = 16;
4176#else
f1a83aab 4177 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
e0f712ba 4178#endif
1a578e9b
AC
4179 height = window_height;
4180
4181 /* Compute the left edge of the scroll bar area. */
f1a83aab 4182 left = WINDOW_SCROLL_BAR_AREA_X (w);
1a578e9b
AC
4183
4184 /* Compute the width of the scroll bar which might be less than
4185 the width of the area reserved for the scroll bar. */
f1a83aab
KS
4186 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4187 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
1a578e9b
AC
4188 else
4189 sb_width = width;
4190
4191 /* Compute the left edge of the scroll bar. */
f1a83aab 4192 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
177c0ea7 4193 sb_left = left + width - sb_width - (width - sb_width) / 2;
1a578e9b
AC
4194 else
4195 sb_left = left + (width - sb_width) / 2;
177c0ea7 4196
1a578e9b
AC
4197 /* Adjustments according to Inside Macintosh to make it look nice */
4198 disp_top = top;
4199 disp_height = height;
4200 if (disp_top == 0)
4201 {
4202 disp_top = -1;
4203 disp_height++;
4204 }
f1a83aab 4205 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
1a578e9b
AC
4206 {
4207 disp_top++;
4208 disp_height--;
4209 }
177c0ea7 4210
f1a83aab 4211 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
1a578e9b 4212 sb_left++;
177c0ea7 4213
1a578e9b
AC
4214 /* Does the scroll bar exist yet? */
4215 if (NILP (w->vertical_scroll_bar))
4216 {
4217 BLOCK_INPUT;
4218 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4219 left, top, width, height, 0);
4220 UNBLOCK_INPUT;
4221 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4222 disp_height);
4223 XSETVECTOR (w->vertical_scroll_bar, bar);
4224 }
4225 else
4226 {
4227 /* It may just need to be moved and resized. */
4228 ControlHandle ch;
177c0ea7 4229
1a578e9b
AC
4230 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4231 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4232
4233 BLOCK_INPUT;
4234
4235 /* If already correctly positioned, do nothing. */
4236 if (XINT (bar->left) == sb_left
4237 && XINT (bar->top) == top
4238 && XINT (bar->width) == sb_width
4239 && XINT (bar->height) == height)
4240 Draw1Control (ch);
4241 else
4242 {
e0f712ba
AC
4243 /* Clear areas not covered by the scroll bar because it's not as
4244 wide as the area reserved for it . This makes sure a
4245 previous mode line display is cleared after C-x 2 C-x 1, for
4246 example. */
f1a83aab 4247 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
e0f712ba
AC
4248 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4249 left, top, area_width, height, 0);
4250
4251#if 0
f1a83aab 4252 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
1a578e9b
AC
4253 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4254 sb_left - 1, top, 1, height, 0);
e0f712ba 4255#endif
1a578e9b
AC
4256
4257 HideControl (ch);
4258 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4259 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4260 disp_height);
4261 ShowControl (ch);
177c0ea7 4262
1a578e9b
AC
4263 /* Remember new settings. */
4264 XSETINT (bar->left, sb_left);
4265 XSETINT (bar->top, top);
4266 XSETINT (bar->width, sb_width);
4267 XSETINT (bar->height, height);
4268 }
4269
4270 UNBLOCK_INPUT;
4271 }
4272
4273 /* Set the scroll bar's current state, unless we're currently being
4274 dragged. */
4275 if (NILP (bar->dragging))
4276 {
4277 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4278
4279 if (whole == 0)
4280 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4281 else
4282 {
4283 int start = ((double) position * top_range) / whole;
4284 int end = ((double) (position + portion) * top_range) / whole;
4285 x_scroll_bar_set_handle (bar, start, end, 0);
4286 }
4287 }
4288}
4289
4290
4291/* The following three hooks are used when we're doing a thorough
4292 redisplay of the frame. We don't explicitly know which scroll bars
4293 are going to be deleted, because keeping track of when windows go
4294 away is a real pain - "Can you say set-window-configuration, boys
4295 and girls?" Instead, we just assert at the beginning of redisplay
4296 that *all* scroll bars are to be removed, and then save a scroll bar
4297 from the fiery pit when we actually redisplay its window. */
4298
4299/* Arrange for all scroll bars on FRAME to be removed at the next call
4300 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4301 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4302
4303static void
4304XTcondemn_scroll_bars (frame)
4305 FRAME_PTR frame;
4306{
4307 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4308 while (! NILP (FRAME_SCROLL_BARS (frame)))
4309 {
4310 Lisp_Object bar;
4311 bar = FRAME_SCROLL_BARS (frame);
4312 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4313 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4314 XSCROLL_BAR (bar)->prev = Qnil;
4315 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4316 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4317 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4318 }
4319}
4320
e0f712ba 4321
1a578e9b
AC
4322/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4323 Note that WINDOW isn't necessarily condemned at all. */
e0f712ba 4324
1a578e9b
AC
4325static void
4326XTredeem_scroll_bar (window)
4327 struct window *window;
4328{
4329 struct scroll_bar *bar;
4330
4331 /* We can't redeem this window's scroll bar if it doesn't have one. */
4332 if (NILP (window->vertical_scroll_bar))
4333 abort ();
4334
4335 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4336
4337 /* Unlink it from the condemned list. */
4338 {
4339 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4340
4341 if (NILP (bar->prev))
4342 {
4343 /* If the prev pointer is nil, it must be the first in one of
4344 the lists. */
4345 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4346 /* It's not condemned. Everything's fine. */
4347 return;
4348 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4349 window->vertical_scroll_bar))
4350 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4351 else
4352 /* If its prev pointer is nil, it must be at the front of
4353 one or the other! */
4354 abort ();
4355 }
4356 else
4357 XSCROLL_BAR (bar->prev)->next = bar->next;
4358
4359 if (! NILP (bar->next))
4360 XSCROLL_BAR (bar->next)->prev = bar->prev;
4361
4362 bar->next = FRAME_SCROLL_BARS (f);
4363 bar->prev = Qnil;
4364 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4365 if (! NILP (bar->next))
4366 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4367 }
4368}
4369
4370/* Remove all scroll bars on FRAME that haven't been saved since the
4371 last call to `*condemn_scroll_bars_hook'. */
4372
4373static void
4374XTjudge_scroll_bars (f)
4375 FRAME_PTR f;
4376{
4377 Lisp_Object bar, next;
4378
4379 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4380
4381 /* Clear out the condemned list now so we won't try to process any
4382 more events on the hapless scroll bars. */
4383 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4384
4385 for (; ! NILP (bar); bar = next)
4386 {
4387 struct scroll_bar *b = XSCROLL_BAR (bar);
4388
4389 x_scroll_bar_remove (b);
4390
4391 next = b->next;
4392 b->next = b->prev = Qnil;
4393 }
4394
4395 /* Now there should be no references to the condemned scroll bars,
4396 and they should get garbage-collected. */
4397}
4398
4399
f9e65eb3 4400void
1a578e9b
AC
4401activate_scroll_bars (frame)
4402 FRAME_PTR frame;
4403{
4404 Lisp_Object bar;
4405 ControlHandle ch;
177c0ea7 4406
1a578e9b
AC
4407 bar = FRAME_SCROLL_BARS (frame);
4408 while (! NILP (bar))
4409 {
4410 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
b15325b2 4411#if 1 /* TARGET_API_MAC_CARBON */
e0f712ba
AC
4412 ActivateControl (ch);
4413#else
1a578e9b
AC
4414 SetControlMaximum (ch,
4415 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
4416 XINT (XSCROLL_BAR (bar)
4417 ->height)) - 1);
e0f712ba 4418#endif
1a578e9b
AC
4419 bar = XSCROLL_BAR (bar)->next;
4420 }
4421}
4422
4423
f9e65eb3 4424void
1a578e9b
AC
4425deactivate_scroll_bars (frame)
4426 FRAME_PTR frame;
4427{
4428 Lisp_Object bar;
4429 ControlHandle ch;
177c0ea7 4430
1a578e9b
AC
4431 bar = FRAME_SCROLL_BARS (frame);
4432 while (! NILP (bar))
4433 {
4434 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
b15325b2 4435#if 1 /* TARGET_API_MAC_CARBON */
e0f712ba
AC
4436 DeactivateControl (ch);
4437#else
b15325b2 4438 SetControlMaximum (ch, -1);
177c0ea7 4439#endif
1a578e9b
AC
4440 bar = XSCROLL_BAR (bar)->next;
4441 }
4442}
4443
4444/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3b8f9651 4445 is set to something other than NO_EVENT, it is enqueued.
1a578e9b
AC
4446
4447 This may be called from a signal handler, so we have to ignore GC
4448 mark bits. */
4449
4450static void
4451x_scroll_bar_handle_click (bar, part_code, er, bufp)
4452 struct scroll_bar *bar;
4453 int part_code;
4454 EventRecord *er;
4455 struct input_event *bufp;
4456{
50bf7673
ST
4457 int win_y, top_range;
4458
1a578e9b
AC
4459 if (! GC_WINDOWP (bar->window))
4460 abort ();
4461
3b8f9651 4462 bufp->kind = SCROLL_BAR_CLICK_EVENT;
1a578e9b
AC
4463 bufp->frame_or_window = bar->window;
4464 bufp->arg = Qnil;
4465
4466 bar->dragging = Qnil;
177c0ea7 4467
1a578e9b
AC
4468 switch (part_code)
4469 {
4470 case kControlUpButtonPart:
4471 bufp->part = scroll_bar_up_arrow;
4472 break;
4473 case kControlDownButtonPart:
4474 bufp->part = scroll_bar_down_arrow;
4475 break;
4476 case kControlPageUpPart:
4477 bufp->part = scroll_bar_above_handle;
4478 break;
4479 case kControlPageDownPart:
4480 bufp->part = scroll_bar_below_handle;
4481 break;
b15325b2 4482#if TARGET_API_MAC_CARBON
e0f712ba
AC
4483 default:
4484#else
1a578e9b 4485 case kControlIndicatorPart:
e0f712ba 4486#endif
1a578e9b
AC
4487 if (er->what == mouseDown)
4488 bar->dragging = make_number (0);
4489 XSETVECTOR (last_mouse_scroll_bar, bar);
4490 bufp->part = scroll_bar_handle;
4491 break;
4492 }
50bf7673
ST
4493
4494 win_y = XINT (bufp->y) - XINT (bar->top);
4495 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4496
4497 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4498
4499 win_y -= 24;
4500
4501 if (! NILP (bar->dragging))
4502 win_y -= XINT (bar->dragging);
4503
4504 if (win_y < 0)
4505 win_y = 0;
4506 if (win_y > top_range)
4507 win_y = top_range;
4508
4509 XSETINT (bufp->x, win_y);
4510 XSETINT (bufp->y, top_range);
1a578e9b
AC
4511}
4512
4513
4514/* Handle some mouse motion while someone is dragging the scroll bar.
4515
4516 This may be called from a signal handler, so we have to ignore GC
4517 mark bits. */
4518
4519static void
4520x_scroll_bar_note_movement (bar, y_pos, t)
4521 struct scroll_bar *bar;
4522 int y_pos;
4523 Time t;
4524{
4525 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4526
4527 last_mouse_movement_time = t;
4528
4529 f->mouse_moved = 1;
4530 XSETVECTOR (last_mouse_scroll_bar, bar);
4531
4532 /* If we're dragging the bar, display it. */
4533 if (! GC_NILP (bar->dragging))
4534 {
4535 /* Where should the handle be now? */
4536 int new_start = y_pos - 24;
4537
4538 if (new_start != XINT (bar->start))
4539 {
4540 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4541
4542 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4543 }
4544 }
4545}
4546
4547
4548/* Return information to the user about the current position of the
4549 mouse on the scroll bar. */
4550
4551static void
4552x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4553 FRAME_PTR *fp;
4554 Lisp_Object *bar_window;
4555 enum scroll_bar_part *part;
4556 Lisp_Object *x, *y;
4557 unsigned long *time;
4558{
4559 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
bf06c82f 4560 WindowPtr wp = front_emacs_window ();
1a578e9b 4561 Point mouse_pos;
50bf7673 4562 struct frame *f = mac_window_to_frame (wp);
1a578e9b
AC
4563 int win_y, top_range;
4564
50bf7673 4565 SetPortWindowPort (wp);
e0f712ba 4566
1a578e9b
AC
4567 GetMouse (&mouse_pos);
4568
4569 win_y = mouse_pos.v - XINT (bar->top);
4570 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4571
4572 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4573
4574 win_y -= 24;
4575
4576 if (! NILP (bar->dragging))
4577 win_y -= XINT (bar->dragging);
4578
4579 if (win_y < 0)
4580 win_y = 0;
4581 if (win_y > top_range)
4582 win_y = top_range;
4583
4584 *fp = f;
4585 *bar_window = bar->window;
4586
4587 if (! NILP (bar->dragging))
4588 *part = scroll_bar_handle;
4589 else if (win_y < XINT (bar->start))
4590 *part = scroll_bar_above_handle;
4591 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4592 *part = scroll_bar_handle;
4593 else
4594 *part = scroll_bar_below_handle;
4595
4596 XSETINT (*x, win_y);
4597 XSETINT (*y, top_range);
4598
4599 f->mouse_moved = 0;
4600 last_mouse_scroll_bar = Qnil;
4601
4602 *time = last_mouse_movement_time;
4603}
4604\f
4605/***********************************************************************
4606 Text Cursor
4607 ***********************************************************************/
4608
1a578e9b
AC
4609/* Set clipping for output in glyph row ROW. W is the window in which
4610 we operate. GC is the graphics context to set clipping in.
1a578e9b
AC
4611
4612 ROW may be a text row or, e.g., a mode line. Text rows must be
4613 clipped to the interior of the window dedicated to text display,
4614 mode lines must be clipped to the whole window. */
4615
4616static void
08f66682 4617x_clip_to_row (w, row, area, gc)
1a578e9b
AC
4618 struct window *w;
4619 struct glyph_row *row;
08f66682 4620 int area;
1a578e9b 4621 GC gc;
1a578e9b
AC
4622{
4623 struct frame *f = XFRAME (WINDOW_FRAME (w));
4624 Rect clip_rect;
08f66682 4625 int window_x, window_y, window_width;
1a578e9b 4626
08f66682 4627 window_box (w, area, &window_x, &window_y, &window_width, 0);
1a578e9b 4628
08f66682 4629 clip_rect.left = window_x;
1a578e9b
AC
4630 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4631 clip_rect.top = max (clip_rect.top, window_y);
4632 clip_rect.right = clip_rect.left + window_width;
4633 clip_rect.bottom = clip_rect.top + row->visible_height;
4634
1a578e9b
AC
4635 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4636}
4637
4638
4639/* Draw a hollow box cursor on window W in glyph row ROW. */
4640
4641static void
4642x_draw_hollow_cursor (w, row)
4643 struct window *w;
4644 struct glyph_row *row;
4645{
4646 struct frame *f = XFRAME (WINDOW_FRAME (w));
4647 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4648 Display *dpy = FRAME_MAC_DISPLAY (f);
4649 int x, y, wd, h;
4650 XGCValues xgcv;
4651 struct glyph *cursor_glyph;
4652 GC gc;
4653
1a578e9b
AC
4654 /* Get the glyph the cursor is on. If we can't tell because
4655 the current matrix is invalid or such, give up. */
4656 cursor_glyph = get_phys_cursor_glyph (w);
4657 if (cursor_glyph == NULL)
4658 return;
4659
4660 /* Compute the width of the rectangle to draw. If on a stretch
4661 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4662 rectangle as wide as the glyph, but use a canonical character
4663 width instead. */
4664 wd = cursor_glyph->pixel_width - 1;
4665 if (cursor_glyph->type == STRETCH_GLYPH
4666 && !x_stretch_cursor_p)
f1a83aab 4667 wd = min (FRAME_COLUMN_WIDTH (f), wd);
e3564461
ST
4668 w->phys_cursor_width = wd;
4669
4670 /* Compute frame-relative coordinates from window-relative
4671 coordinates. */
4672 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4673 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
4674
4675 /* Compute the proper height and ascent of the rectangle, based
4676 on the actual glyph. Using the full height of the row looks
4677 bad when there are tall images on that row. */
5970dbf7
KS
4678 h = max (min (FRAME_LINE_HEIGHT (f), row->height),
4679 cursor_glyph->ascent + cursor_glyph->descent);
e3564461
ST
4680 if (h < row->height)
4681 y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
4682 h--;
177c0ea7 4683
1a578e9b
AC
4684 /* The foreground of cursor_gc is typically the same as the normal
4685 background color, which can cause the cursor box to be invisible. */
4686 xgcv.foreground = f->output_data.mac->cursor_pixel;
4687 if (dpyinfo->scratch_cursor_gc)
4688 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4689 else
4690 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4691 GCForeground, &xgcv);
4692 gc = dpyinfo->scratch_cursor_gc;
4693
4694 /* Set clipping, draw the rectangle, and reset clipping again. */
08f66682 4695 x_clip_to_row (w, row, TEXT_AREA, gc);
1a578e9b
AC
4696 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4697 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4698}
4699
4700
4701/* Draw a bar cursor on window W in glyph row ROW.
4702
4703 Implementation note: One would like to draw a bar cursor with an
4704 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4705 Unfortunately, I didn't find a font yet that has this property set.
4706 --gerd. */
4707
4708static void
e3564461 4709x_draw_bar_cursor (w, row, width, kind)
1a578e9b
AC
4710 struct window *w;
4711 struct glyph_row *row;
4712 int width;
e3564461 4713 enum text_cursor_kinds kind;
1a578e9b 4714{
e3564461
ST
4715 struct frame *f = XFRAME (w->frame);
4716 struct glyph *cursor_glyph;
4717
4718 /* If cursor is out of bounds, don't draw garbage. This can happen
4719 in mini-buffer windows when switching between echo area glyphs
4720 and mini-buffer. */
4721 cursor_glyph = get_phys_cursor_glyph (w);
4722 if (cursor_glyph == NULL)
4723 return;
4724
4725 /* If on an image, draw like a normal cursor. That's usually better
4726 visible than drawing a bar, esp. if the image is large so that
4727 the bar might not be in the window. */
4728 if (cursor_glyph->type == IMAGE_GLYPH)
1a578e9b 4729 {
e3564461
ST
4730 struct glyph_row *row;
4731 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4732 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4733 }
4734 else
4735 {
4736 Display *dpy = FRAME_MAC_DISPLAY (f);
4737 Window window = FRAME_MAC_WINDOW (f);
4738 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
4739 unsigned long mask = GCForeground | GCBackground;
4740 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
1a578e9b 4741 XGCValues xgcv;
177c0ea7 4742
e3564461
ST
4743 /* If the glyph's background equals the color we normally draw
4744 the bar cursor in, the bar cursor in its normal color is
4745 invisible. Use the glyph's foreground color instead in this
4746 case, on the assumption that the glyph's colors are chosen so
4747 that the glyph is legible. */
4748 if (face->background == f->output_data.mac->cursor_pixel)
4749 xgcv.background = xgcv.foreground = face->foreground;
4750 else
4751 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
177c0ea7 4752
1a578e9b
AC
4753 if (gc)
4754 XChangeGC (dpy, gc, mask, &xgcv);
4755 else
4756 {
4757 gc = XCreateGC (dpy, window, mask, &xgcv);
4758 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4759 }
4760
4761 if (width < 0)
668e2d32 4762 width = FRAME_CURSOR_WIDTH (f);
e3564461 4763 width = min (cursor_glyph->pixel_width, width);
1a578e9b 4764
e3564461 4765 w->phys_cursor_width = width;
08f66682 4766 x_clip_to_row (w, row, TEXT_AREA, gc);
e3564461
ST
4767
4768 if (kind == BAR_CURSOR)
4769 XFillRectangle (dpy, window, gc,
4770 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4771 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4772 width, row->height);
4773 else
4774 XFillRectangle (dpy, window, gc,
4775 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4776 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
4777 row->height - width),
4778 cursor_glyph->pixel_width,
4779 width);
4780
1a578e9b
AC
4781 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4782 }
4783}
4784
4785
f9e65eb3 4786/* RIF: Define cursor CURSOR on frame F. */
1a578e9b
AC
4787
4788static void
f9e65eb3
KS
4789mac_define_frame_cursor (f, cursor)
4790 struct frame *f;
4791 Cursor cursor;
1a578e9b 4792{
50bf7673
ST
4793#if TARGET_API_MAC_CARBON
4794 SetThemeCursor (cursor);
4795#else
4796 SetCursor (*cursor);
4797#endif
1a578e9b
AC
4798}
4799
4800
f9e65eb3 4801/* RIF: Clear area on frame F. */
1a578e9b
AC
4802
4803static void
f9e65eb3
KS
4804mac_clear_frame_area (f, x, y, width, height)
4805 struct frame *f;
4806 int x, y, width, height;
1a578e9b 4807{
f9e65eb3
KS
4808 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4809 x, y, width, height, 0);
1a578e9b
AC
4810}
4811
4812
f9e65eb3 4813/* RIF: Draw cursor on window W. */
1a578e9b
AC
4814
4815static void
e5a3b7d9 4816mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
1a578e9b 4817 struct window *w;
f9e65eb3 4818 struct glyph_row *glyph_row;
e5a3b7d9
KS
4819 int x, y;
4820 int cursor_type, cursor_width;
4821 int on_p, active_p;
1a578e9b 4822{
e5a3b7d9 4823 if (on_p)
1a578e9b 4824 {
e5a3b7d9 4825 w->phys_cursor_type = cursor_type;
1a578e9b
AC
4826 w->phys_cursor_on_p = 1;
4827
797dc7b8
KS
4828 if (glyph_row->exact_window_width_line_p
4829 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4830 {
4831 glyph_row->cursor_in_fringe_p = 1;
4832 draw_fringe_bitmap (w, glyph_row, 0);
797dc7b8 4833 }
e3564461 4834 else
e5a3b7d9 4835 switch (cursor_type)
1a578e9b
AC
4836 {
4837 case HOLLOW_BOX_CURSOR:
4838 x_draw_hollow_cursor (w, glyph_row);
4839 break;
4840
4841 case FILLED_BOX_CURSOR:
f9e65eb3 4842 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
1a578e9b
AC
4843 break;
4844
4845 case BAR_CURSOR:
e3564461
ST
4846 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4847 break;
4848
4849 case HBAR_CURSOR:
4850 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
1a578e9b
AC
4851 break;
4852
4853 case NO_CURSOR:
e3564461 4854 w->phys_cursor_width = 0;
1a578e9b
AC
4855 break;
4856
4857 default:
4858 abort ();
4859 }
1a578e9b 4860 }
1a578e9b
AC
4861}
4862
e0f712ba
AC
4863\f
4864/* Icons. */
1a578e9b 4865
e0f712ba 4866#if 0 /* MAC_TODO: no icon support yet. */
1a578e9b 4867int
e0f712ba 4868x_bitmap_icon (f, icon)
1a578e9b 4869 struct frame *f;
e0f712ba 4870 Lisp_Object icon;
1a578e9b 4871{
e0f712ba 4872 HANDLE hicon;
1a578e9b 4873
e0f712ba 4874 if (FRAME_W32_WINDOW (f) == 0)
1a578e9b
AC
4875 return 1;
4876
e0f712ba
AC
4877 if (NILP (icon))
4878 hicon = LoadIcon (hinst, EMACS_CLASS);
4879 else if (STRINGP (icon))
d5db4077 4880 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
e0f712ba
AC
4881 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4882 else if (SYMBOLP (icon))
4883 {
4884 LPCTSTR name;
4885
4886 if (EQ (icon, intern ("application")))
4887 name = (LPCTSTR) IDI_APPLICATION;
4888 else if (EQ (icon, intern ("hand")))
4889 name = (LPCTSTR) IDI_HAND;
4890 else if (EQ (icon, intern ("question")))
4891 name = (LPCTSTR) IDI_QUESTION;
4892 else if (EQ (icon, intern ("exclamation")))
4893 name = (LPCTSTR) IDI_EXCLAMATION;
4894 else if (EQ (icon, intern ("asterisk")))
4895 name = (LPCTSTR) IDI_ASTERISK;
4896 else if (EQ (icon, intern ("winlogo")))
4897 name = (LPCTSTR) IDI_WINLOGO;
4898 else
4899 return 1;
1a578e9b 4900
e0f712ba 4901 hicon = LoadIcon (NULL, name);
1a578e9b 4902 }
e0f712ba 4903 else
1a578e9b
AC
4904 return 1;
4905
e0f712ba
AC
4906 if (hicon == NULL)
4907 return 1;
1a578e9b 4908
e0f712ba
AC
4909 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4910 (LPARAM) hicon);
1a578e9b
AC
4911
4912 return 0;
4913}
e0f712ba 4914#endif /* MAC_TODO */
1a578e9b 4915\f
e0f712ba
AC
4916/************************************************************************
4917 Handling X errors
4918 ************************************************************************/
1a578e9b 4919
e0f712ba
AC
4920/* Display Error Handling functions not used on W32. Listing them here
4921 helps diff stay in step when comparing w32term.c with xterm.c.
1a578e9b 4922
1a578e9b 4923x_error_catcher (display, error)
1a578e9b 4924x_catch_errors (dpy)
1a578e9b 4925x_catch_errors_unwind (old_val)
1a578e9b 4926x_check_errors (dpy, format)
1a578e9b 4927x_had_errors_p (dpy)
1a578e9b 4928x_clear_errors (dpy)
1a578e9b 4929x_uncatch_errors (dpy, count)
1a578e9b 4930x_trace_wire ()
e0f712ba
AC
4931x_connection_signal (signalnum)
4932x_connection_closed (dpy, error_message)
1a578e9b 4933x_error_quitter (display, error)
1a578e9b 4934x_error_handler (display, error)
1a578e9b 4935x_io_error_quitter (display)
1a578e9b 4936
e0f712ba
AC
4937 */
4938
1a578e9b
AC
4939\f
4940/* Changing the font of the frame. */
4941
4942/* Give frame F the font named FONTNAME as its default font, and
4943 return the full name of that font. FONTNAME may be a wildcard
4944 pattern; in that case, we choose some font that fits the pattern.
4945 The return value shows which font we chose. */
4946
4947Lisp_Object
4948x_new_font (f, fontname)
4949 struct frame *f;
4950 register char *fontname;
4951{
4952 struct font_info *fontp
4953 = FS_LOAD_FONT (f, 0, fontname, -1);
4954
4955 if (!fontp)
4956 return Qnil;
4957
e0f712ba
AC
4958 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4959 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4960 FRAME_FONTSET (f) = -1;
4961
f1a83aab
KS
4962 FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
4963 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
4964
4965 compute_fringe_widths (f, 1);
4966
1a578e9b 4967 /* Compute the scroll bar width in character columns. */
f1a83aab 4968 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
1a578e9b 4969 {
f1a83aab 4970 int wid = FRAME_COLUMN_WIDTH (f);
ffe8b3f4 4971 FRAME_CONFIG_SCROLL_BAR_COLS (f)
f1a83aab 4972 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
1a578e9b
AC
4973 }
4974 else
4975 {
f1a83aab
KS
4976 int wid = FRAME_COLUMN_WIDTH (f);
4977 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
1a578e9b
AC
4978 }
4979
4980 /* Now make the frame display the given font. */
4981 if (FRAME_MAC_WINDOW (f) != 0)
4982 {
f00691a3 4983 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
f1a83aab 4984 FRAME_FONT (f));
f00691a3 4985 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
f1a83aab 4986 FRAME_FONT (f));
f00691a3 4987 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
f1a83aab 4988 FRAME_FONT (f));
f00691a3 4989
b15325b2
ST
4990 /* Don't change the size of a tip frame; there's no point in
4991 doing it because it's done in Fx_show_tip, and it leads to
4992 problems because the tip frame has no widget. */
e0f712ba 4993 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
f1a83aab 4994 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
1a578e9b 4995 }
1a578e9b
AC
4996
4997 return build_string (fontp->full_name);
4998}
b15325b2 4999
1a578e9b 5000/* Give frame F the fontset named FONTSETNAME as its default font, and
e0f712ba
AC
5001 return the full name of that fontset. FONTSETNAME may be a wildcard
5002 pattern; in that case, we choose some fontset that fits the pattern.
5003 The return value shows which fontset we chose. */
1a578e9b
AC
5004
5005Lisp_Object
5006x_new_fontset (f, fontsetname)
5007 struct frame *f;
5008 char *fontsetname;
5009{
5010 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5011 Lisp_Object result;
5012
5013 if (fontset < 0)
5014 return Qnil;
5015
e0f712ba 5016 if (FRAME_FONTSET (f) == fontset)
1a578e9b
AC
5017 /* This fontset is already set in frame F. There's nothing more
5018 to do. */
5019 return fontset_name (fontset);
5020
d5db4077 5021 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
1a578e9b
AC
5022
5023 if (!STRINGP (result))
5024 /* Can't load ASCII font. */
5025 return Qnil;
5026
e0f712ba
AC
5027 /* Since x_new_font doesn't update any fontset information, do it now. */
5028 FRAME_FONTSET(f) = fontset;
1a578e9b 5029
1a578e9b
AC
5030 return build_string (fontsetname);
5031}
5032
1a578e9b
AC
5033\f
5034/***********************************************************************
e0f712ba 5035 TODO: W32 Input Methods
1a578e9b 5036 ***********************************************************************/
e0f712ba 5037/* Listing missing functions from xterm.c helps diff stay in step.
1a578e9b 5038
1a578e9b 5039xim_destroy_callback (xim, client_data, call_data)
1a578e9b 5040xim_open_dpy (dpyinfo, resource_name)
1a578e9b 5041struct xim_inst_t
1a578e9b 5042xim_instantiate_callback (display, client_data, call_data)
1a578e9b 5043xim_initialize (dpyinfo, resource_name)
1a578e9b 5044xim_close_dpy (dpyinfo)
1a578e9b 5045
e0f712ba 5046 */
1a578e9b 5047
1a578e9b 5048\f
bf06c82f
ST
5049void
5050mac_get_window_bounds (f, inner, outer)
5051 struct frame *f;
5052 Rect *inner, *outer;
5053{
5054#if TARGET_API_MAC_CARBON
5055 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5056 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5057#else /* not TARGET_API_MAC_CARBON */
5058 RgnHandle region = NewRgn ();
f94a2622 5059
bf06c82f
ST
5060 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5061 *inner = (*region)->rgnBBox;
5062 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5063 *outer = (*region)->rgnBBox;
5064 DisposeRgn (region);
5065#endif /* not TARGET_API_MAC_CARBON */
5066}
5067
5068
1a578e9b
AC
5069/* Calculate the absolute position in frame F
5070 from its current recorded position values and gravity. */
5071
e0f712ba 5072void
1a578e9b
AC
5073x_calc_absolute_position (f)
5074 struct frame *f;
5075{
bf06c82f 5076 int width_diff = 0, height_diff = 0;
f1a83aab 5077 int flags = f->size_hint_flags;
bf06c82f 5078 Rect inner, outer;
1a578e9b 5079
bf06c82f
ST
5080 /* We have nothing to do if the current position
5081 is already for the top-left corner. */
5082 if (! ((flags & XNegative) || (flags & YNegative)))
5083 return;
1a578e9b 5084
bf06c82f 5085 /* Find the offsets of the outside upper-left corner of
1a578e9b 5086 the inner window, with respect to the outer window. */
bf06c82f 5087 mac_get_window_bounds (f, &inner, &outer);
e0f712ba 5088
bf06c82f
ST
5089 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5090 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
1a578e9b
AC
5091
5092 /* Treat negative positions as relative to the leftmost bottommost
5093 position that fits on the screen. */
5094 if (flags & XNegative)
f1a83aab 5095 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
bf06c82f 5096 - width_diff
f1a83aab
KS
5097 - FRAME_PIXEL_WIDTH (f)
5098 + f->left_pos);
bf06c82f 5099
1a578e9b 5100 if (flags & YNegative)
f1a83aab 5101 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
bf06c82f 5102 - height_diff
f1a83aab
KS
5103 - FRAME_PIXEL_HEIGHT (f)
5104 + f->top_pos);
bf06c82f 5105
1a578e9b
AC
5106 /* The left_pos and top_pos
5107 are now relative to the top and left screen edges,
5108 so the flags should correspond. */
f1a83aab 5109 f->size_hint_flags &= ~ (XNegative | YNegative);
1a578e9b
AC
5110}
5111
5112/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5113 to really change the position, and 0 when calling from
5114 x_make_frame_visible (in that case, XOFF and YOFF are the current
5115 position values). It is -1 when calling from x_set_frame_parameters,
5116 which means, do adjust for borders but don't change the gravity. */
5117
5118void
5119x_set_offset (f, xoff, yoff, change_gravity)
5120 struct frame *f;
5121 register int xoff, yoff;
5122 int change_gravity;
5123{
5124 if (change_gravity > 0)
5125 {
f1a83aab
KS
5126 f->top_pos = yoff;
5127 f->left_pos = xoff;
5128 f->size_hint_flags &= ~ (XNegative | YNegative);
1a578e9b 5129 if (xoff < 0)
f1a83aab 5130 f->size_hint_flags |= XNegative;
1a578e9b 5131 if (yoff < 0)
f1a83aab
KS
5132 f->size_hint_flags |= YNegative;
5133 f->win_gravity = NorthWestGravity;
1a578e9b
AC
5134 }
5135 x_calc_absolute_position (f);
5136
5137 BLOCK_INPUT;
5138 x_wm_set_size_hint (f, (long) 0, 0);
5139
bf06c82f
ST
5140#if TARGET_API_MAC_CARBON
5141 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5142 /* If the title bar is completely outside the screen, adjust the
5143 position. */
5144 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5145 kWindowConstrainMoveRegardlessOfFit
5146 | kWindowConstrainAllowPartial, NULL, NULL);
5147 x_real_positions (f, &f->left_pos, &f->top_pos);
5148#else
5149 {
5150 Rect inner, outer, screen_rect, dummy;
5151 RgnHandle region = NewRgn ();
f94a2622 5152
bf06c82f
ST
5153 mac_get_window_bounds (f, &inner, &outer);
5154 f->x_pixels_diff = inner.left - outer.left;
5155 f->y_pixels_diff = inner.top - outer.top;
5156 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5157 f->top_pos + f->y_pixels_diff, false);
5158
5159 /* If the title bar is completely outside the screen, adjust the
5160 position. The variable `outer' holds the title bar rectangle.
5161 The variable `inner' holds slightly smaller one than `outer',
5162 so that the calculation of overlapping may not become too
5163 strict. */
5164 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5165 outer = (*region)->rgnBBox;
5166 DisposeRgn (region);
5167 inner = outer;
5168 InsetRect (&inner, 8, 8);
5169 screen_rect = qd.screenBits.bounds;
5170 screen_rect.top += GetMBarHeight ();
5171
5172 if (!SectRect (&inner, &screen_rect, &dummy))
5173 {
5174 if (inner.right <= screen_rect.left)
5175 f->left_pos = screen_rect.left;
5176 else if (inner.left >= screen_rect.right)
5177 f->left_pos = screen_rect.right - (outer.right - outer.left);
5178
5179 if (inner.bottom <= screen_rect.top)
5180 f->top_pos = screen_rect.top;
5181 else if (inner.top >= screen_rect.bottom)
5182 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5183
5184 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5185 f->top_pos + f->y_pixels_diff, false);
5186 }
5187 }
5188#endif
1a578e9b
AC
5189
5190 UNBLOCK_INPUT;
5191}
5192
5193/* Call this to change the size of frame F's x-window.
5194 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5195 for this size change and subsequent size changes.
5196 Otherwise we leave the window gravity unchanged. */
5197
5198void
5199x_set_window_size (f, change_gravity, cols, rows)
5200 struct frame *f;
5201 int change_gravity;
5202 int cols, rows;
5203{
5204 int pixelwidth, pixelheight;
177c0ea7 5205
e0f712ba 5206 BLOCK_INPUT;
177c0ea7 5207
1a578e9b 5208 check_frame_size (f, &rows, &cols);
f1a83aab
KS
5209 f->scroll_bar_actual_width
5210 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
d33c49e8 5211
5958f265 5212 compute_fringe_widths (f, 0);
d33c49e8 5213
f1a83aab
KS
5214 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5215 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
1a578e9b 5216
f1a83aab 5217 f->win_gravity = NorthWestGravity;
1a578e9b
AC
5218 x_wm_set_size_hint (f, (long) 0, 0);
5219
5220 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5221
5222 /* Now, strictly speaking, we can't be sure that this is accurate,
5223 but the window manager will get around to dealing with the size
5224 change request eventually, and we'll hear how it went when the
5225 ConfigureNotify event gets here.
177c0ea7 5226
1a578e9b
AC
5227 We could just not bother storing any of this information here,
5228 and let the ConfigureNotify event set everything up, but that
5229 might be kind of confusing to the Lisp code, since size changes
5230 wouldn't be reported in the frame parameters until some random
5231 point in the future when the ConfigureNotify event arrives.
5232
5233 We pass 1 for DELAY since we can't run Lisp code inside of
5234 a BLOCK_INPUT. */
5235 change_frame_size (f, rows, cols, 0, 1, 0);
f1a83aab
KS
5236 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5237 FRAME_PIXEL_HEIGHT (f) = pixelheight;
1a578e9b
AC
5238
5239 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5240 receive in the ConfigureNotify event; if we get what we asked
5241 for, then the event won't cause the screen to become garbaged, so
5242 we have to make sure to do it here. */
5243 SET_FRAME_GARBAGED (f);
5244
5245 XFlush (FRAME_X_DISPLAY (f));
5246
5247 /* If cursor was outside the new size, mark it as off. */
5248 mark_window_cursors_off (XWINDOW (f->root_window));
5249
5250 /* Clear out any recollection of where the mouse highlighting was,
177c0ea7 5251 since it might be in a place that's outside the new frame size.
1a578e9b
AC
5252 Actually checking whether it is outside is a pain in the neck,
5253 so don't try--just let the highlighting be done afresh with new size. */
5254 cancel_mouse_face (f);
e0f712ba
AC
5255
5256 UNBLOCK_INPUT;
1a578e9b
AC
5257}
5258\f
5259/* Mouse warping. */
5260
5261void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5262
5263void
5264x_set_mouse_position (f, x, y)
5265 struct frame *f;
5266 int x, y;
5267{
5268 int pix_x, pix_y;
5269
f1a83aab
KS
5270 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5271 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
1a578e9b
AC
5272
5273 if (pix_x < 0) pix_x = 0;
f1a83aab 5274 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
1a578e9b
AC
5275
5276 if (pix_y < 0) pix_y = 0;
f1a83aab 5277 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
1a578e9b
AC
5278
5279 x_set_mouse_pixel_position (f, pix_x, pix_y);
5280}
5281
1a578e9b
AC
5282void
5283x_set_mouse_pixel_position (f, pix_x, pix_y)
5284 struct frame *f;
5285 int pix_x, pix_y;
5286{
5287#if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5288 BLOCK_INPUT;
5289
5290 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5291 0, 0, 0, 0, pix_x, pix_y);
5292 UNBLOCK_INPUT;
5293#endif
5294}
e0f712ba 5295
1a578e9b
AC
5296\f
5297/* focus shifting, raising and lowering. */
5298
e0f712ba 5299void
1a578e9b
AC
5300x_focus_on_frame (f)
5301 struct frame *f;
5302{
5303#if 0 /* This proves to be unpleasant. */
5304 x_raise_frame (f);
5305#endif
5306#if 0
5307 /* I don't think that the ICCCM allows programs to do things like this
5308 without the interaction of the window manager. Whatever you end up
5309 doing with this code, do it to x_unfocus_frame too. */
5310 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5311 RevertToPointerRoot, CurrentTime);
5312#endif /* ! 0 */
5313}
5314
e0f712ba 5315void
1a578e9b
AC
5316x_unfocus_frame (f)
5317 struct frame *f;
5318{
1a578e9b
AC
5319}
5320
5321/* Raise frame F. */
1a578e9b
AC
5322void
5323x_raise_frame (f)
5324 struct frame *f;
5325{
5326 if (f->async_visible)
c3f4c690
ST
5327 {
5328 BLOCK_INPUT;
5329 SelectWindow (FRAME_MAC_WINDOW (f));
5330 UNBLOCK_INPUT;
5331 }
1a578e9b
AC
5332}
5333
5334/* Lower frame F. */
1a578e9b
AC
5335void
5336x_lower_frame (f)
5337 struct frame *f;
5338{
5339 if (f->async_visible)
c3f4c690
ST
5340 {
5341 BLOCK_INPUT;
5342 SendBehind (FRAME_MAC_WINDOW (f), nil);
5343 UNBLOCK_INPUT;
5344 }
1a578e9b
AC
5345}
5346
e0f712ba 5347static void
1a578e9b
AC
5348XTframe_raise_lower (f, raise_flag)
5349 FRAME_PTR f;
5350 int raise_flag;
5351{
5352 if (raise_flag)
5353 x_raise_frame (f);
5354 else
5355 x_lower_frame (f);
5356}
5357\f
5358/* Change of visibility. */
5359
5360/* This tries to wait until the frame is really visible.
5361 However, if the window manager asks the user where to position
5362 the frame, this will return before the user finishes doing that.
5363 The frame will not actually be visible at that time,
5364 but it will become visible later when the window manager
5365 finishes with it. */
5366
5367void
5368x_make_frame_visible (f)
5369 struct frame *f;
5370{
5371 Lisp_Object type;
5372 int original_top, original_left;
5373
5374 BLOCK_INPUT;
5375
5376 if (! FRAME_VISIBLE_P (f))
5377 {
5378 /* We test FRAME_GARBAGED_P here to make sure we don't
5379 call x_set_offset a second time
5380 if we get to x_make_frame_visible a second time
5381 before the window gets really visible. */
5382 if (! FRAME_ICONIFIED_P (f)
5383 && ! f->output_data.mac->asked_for_visible)
f1a83aab 5384 x_set_offset (f, f->left_pos, f->top_pos, 0);
1a578e9b
AC
5385
5386 f->output_data.mac->asked_for_visible = 1;
177c0ea7 5387
b15325b2
ST
5388#if TARGET_API_MAC_CARBON
5389 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
5390 {
5391 struct frame *sf = SELECTED_FRAME ();
5392 if (!FRAME_MAC_P (sf))
5393 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
5394 kWindowCenterOnMainScreen);
5395 else
5396 RepositionWindow (FRAME_MAC_WINDOW (f),
5397 FRAME_MAC_WINDOW (sf),
5398#ifdef MAC_OS_X_VERSION_10_2
5399 kWindowCascadeStartAtParentWindowScreen
5400#else
5401 kWindowCascadeOnParentWindowScreen
5402#endif
5403 );
5404 x_real_positions (f, &f->left_pos, &f->top_pos);
5405 }
5406#endif
1a578e9b
AC
5407 ShowWindow (FRAME_MAC_WINDOW (f));
5408 }
5409
5410 XFlush (FRAME_MAC_DISPLAY (f));
5411
5412 /* Synchronize to ensure Emacs knows the frame is visible
5413 before we do anything else. We do this loop with input not blocked
5414 so that incoming events are handled. */
5415 {
5416 Lisp_Object frame;
5417 int count;
5418
5419 /* This must come after we set COUNT. */
5420 UNBLOCK_INPUT;
5421
5422 XSETFRAME (frame, f);
5423
5424 /* Wait until the frame is visible. Process X events until a
5425 MapNotify event has been seen, or until we think we won't get a
5426 MapNotify at all.. */
5427 for (count = input_signal_count + 10;
5428 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5429 {
5430 /* Force processing of queued events. */
5431 x_sync (f);
5432
5433 /* Machines that do polling rather than SIGIO have been
5434 observed to go into a busy-wait here. So we'll fake an
5435 alarm signal to let the handler know that there's something
5436 to be read. We used to raise a real alarm, but it seems
5437 that the handler isn't always enabled here. This is
5438 probably a bug. */
5439 if (input_polling_used ())
5440 {
5441 /* It could be confusing if a real alarm arrives while
5442 processing the fake one. Turn it off and let the
5443 handler reset it. */
5444 extern void poll_for_input_1 P_ ((void));
5445 int old_poll_suppress_count = poll_suppress_count;
5446 poll_suppress_count = 1;
5447 poll_for_input_1 ();
5448 poll_suppress_count = old_poll_suppress_count;
5449 }
5450
5451 /* See if a MapNotify event has been processed. */
5452 FRAME_SAMPLE_VISIBILITY (f);
5453 }
5454 }
5455}
5456
5457/* Change from mapped state to withdrawn state. */
5458
5459/* Make the frame visible (mapped and not iconified). */
5460
5461void
5462x_make_frame_invisible (f)
5463 struct frame *f;
5464{
5465 /* Don't keep the highlight on an invisible frame. */
5466 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5467 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
177c0ea7 5468
1a578e9b 5469 BLOCK_INPUT;
177c0ea7 5470
1a578e9b 5471 HideWindow (FRAME_MAC_WINDOW (f));
177c0ea7 5472
1a578e9b
AC
5473 /* We can't distinguish this from iconification
5474 just by the event that we get from the server.
5475 So we can't win using the usual strategy of letting
5476 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5477 and synchronize with the server to make sure we agree. */
5478 f->visible = 0;
5479 FRAME_ICONIFIED_P (f) = 0;
5480 f->async_visible = 0;
5481 f->async_iconified = 0;
177c0ea7 5482
1a578e9b
AC
5483 UNBLOCK_INPUT;
5484}
5485
5486/* Change window state from mapped to iconified. */
5487
5488void
5489x_iconify_frame (f)
5490 struct frame *f;
5491{
1a578e9b 5492 /* Don't keep the highlight on an invisible frame. */
742fbed7
AC
5493 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5494 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
1a578e9b 5495
742fbed7
AC
5496#if 0
5497 /* Review: Since window is still visible in dock, still allow updates? */
1a578e9b
AC
5498 if (f->async_iconified)
5499 return;
742fbed7 5500#endif
1a578e9b
AC
5501
5502 BLOCK_INPUT;
5503
742fbed7 5504 CollapseWindow (FRAME_MAC_WINDOW (f), true);
177c0ea7 5505
1a578e9b 5506 UNBLOCK_INPUT;
1a578e9b 5507}
e0f712ba 5508
1a578e9b 5509\f
e3564461 5510/* Free X resources of frame F. */
1a578e9b
AC
5511
5512void
e3564461 5513x_free_frame_resources (f)
1a578e9b
AC
5514 struct frame *f;
5515{
5516 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
50bf7673 5517 WindowPtr wp = FRAME_MAC_WINDOW (f);
1a578e9b
AC
5518
5519 BLOCK_INPUT;
5520
50bf7673
ST
5521 DisposeWindow (wp);
5522 if (wp == tip_window)
5523 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5524 closed' event. So we reset tip_window here. */
5525 tip_window = NULL;
1a578e9b
AC
5526
5527 free_frame_menubar (f);
e3564461
ST
5528
5529 if (FRAME_FACE_CACHE (f))
5530 free_frame_faces (f);
5531
5532 x_free_gcs (f);
1a578e9b 5533
b15325b2
ST
5534 if (FRAME_SIZE_HINTS (f))
5535 xfree (FRAME_SIZE_HINTS (f));
5536
1a578e9b 5537 xfree (f->output_data.mac);
e3564461
ST
5538 f->output_data.mac = NULL;
5539
1a578e9b
AC
5540 if (f == dpyinfo->x_focus_frame)
5541 dpyinfo->x_focus_frame = 0;
5542 if (f == dpyinfo->x_focus_event_frame)
5543 dpyinfo->x_focus_event_frame = 0;
5544 if (f == dpyinfo->x_highlight_frame)
5545 dpyinfo->x_highlight_frame = 0;
5546
1a578e9b
AC
5547 if (f == dpyinfo->mouse_face_mouse_frame)
5548 {
5549 dpyinfo->mouse_face_beg_row
5550 = dpyinfo->mouse_face_beg_col = -1;
5551 dpyinfo->mouse_face_end_row
5552 = dpyinfo->mouse_face_end_col = -1;
5553 dpyinfo->mouse_face_window = Qnil;
5554 dpyinfo->mouse_face_deferred_gc = 0;
5555 dpyinfo->mouse_face_mouse_frame = 0;
5556 }
5557
5558 UNBLOCK_INPUT;
5559}
e3564461
ST
5560
5561
5562/* Destroy the X window of frame F. */
5563
5564void
5565x_destroy_window (f)
5566 struct frame *f;
5567{
5568 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5569
5570 x_free_frame_resources (f);
5571
5572 dpyinfo->reference_count--;
5573}
5574
1a578e9b
AC
5575\f
5576/* Setting window manager hints. */
5577
5578/* Set the normal size hints for the window manager, for frame F.
5579 FLAGS is the flags word to use--or 0 meaning preserve the flags
5580 that the window now has.
5581 If USER_POSITION is nonzero, we set the USPosition
5582 flag (this is useful when FLAGS is 0). */
1a578e9b
AC
5583void
5584x_wm_set_size_hint (f, flags, user_position)
5585 struct frame *f;
5586 long flags;
5587 int user_position;
5588{
b15325b2
ST
5589 int base_width, base_height, width_inc, height_inc;
5590 int min_rows = 0, min_cols = 0;
5591 XSizeHints *size_hints;
1a578e9b 5592
b15325b2
ST
5593 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5594 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5595 width_inc = FRAME_COLUMN_WIDTH (f);
5596 height_inc = FRAME_LINE_HEIGHT (f);
1a578e9b 5597
b15325b2 5598 check_frame_size (f, &min_rows, &min_cols);
1a578e9b 5599
b15325b2
ST
5600 size_hints = FRAME_SIZE_HINTS (f);
5601 if (size_hints == NULL)
1a578e9b 5602 {
b15325b2
ST
5603 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
5604 bzero (size_hints, sizeof (XSizeHints));
1a578e9b 5605 }
1a578e9b 5606
b15325b2
ST
5607 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
5608 size_hints->width_inc = width_inc;
5609 size_hints->height_inc = height_inc;
5610 size_hints->min_width = base_width + min_cols * width_inc;
5611 size_hints->min_height = base_height + min_rows * height_inc;
5612 size_hints->base_width = base_width;
5613 size_hints->base_height = base_height;
1a578e9b 5614
b15325b2
ST
5615 if (flags)
5616 size_hints->flags = flags;
5617 else if (user_position)
1a578e9b 5618 {
b15325b2
ST
5619 size_hints->flags &= ~ PPosition;
5620 size_hints->flags |= USPosition;
1a578e9b 5621 }
1a578e9b
AC
5622}
5623
e0f712ba 5624#if 0 /* MAC_TODO: hide application instead of iconify? */
1a578e9b
AC
5625/* Used for IconicState or NormalState */
5626
5627void
5628x_wm_set_window_state (f, state)
5629 struct frame *f;
5630 int state;
5631{
5632#ifdef USE_X_TOOLKIT
5633 Arg al[1];
5634
5635 XtSetArg (al[0], XtNinitialState, state);
5636 XtSetValues (f->output_data.x->widget, al, 1);
5637#else /* not USE_X_TOOLKIT */
5638 Window window = FRAME_X_WINDOW (f);
5639
5640 f->output_data.x->wm_hints.flags |= StateHint;
5641 f->output_data.x->wm_hints.initial_state = state;
5642
5643 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5644#endif /* not USE_X_TOOLKIT */
5645}
5646
5647void
5648x_wm_set_icon_pixmap (f, pixmap_id)
5649 struct frame *f;
5650 int pixmap_id;
5651{
5652 Pixmap icon_pixmap;
5653
5654#ifndef USE_X_TOOLKIT
5655 Window window = FRAME_X_WINDOW (f);
5656#endif
5657
5658 if (pixmap_id > 0)
5659 {
5660 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5661 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5662 }
5663 else
5664 {
5665 /* It seems there is no way to turn off use of an icon pixmap.
5666 The following line does it, only if no icon has yet been created,
5667 for some window managers. But with mwm it crashes.
5668 Some people say it should clear the IconPixmapHint bit in this case,
5669 but that doesn't work, and the X consortium said it isn't the
5670 right thing at all. Since there is no way to win,
5671 best to explicitly give up. */
5672#if 0
5673 f->output_data.x->wm_hints.icon_pixmap = None;
5674#else
5675 return;
5676#endif
5677 }
5678
5679#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5680
5681 {
5682 Arg al[1];
5683 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5684 XtSetValues (f->output_data.x->widget, al, 1);
5685 }
5686
5687#else /* not USE_X_TOOLKIT */
177c0ea7 5688
1a578e9b
AC
5689 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5690 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5691
5692#endif /* not USE_X_TOOLKIT */
5693}
5694
e0f712ba 5695#endif /* MAC_TODO */
1a578e9b
AC
5696
5697void
5698x_wm_set_icon_position (f, icon_x, icon_y)
5699 struct frame *f;
5700 int icon_x, icon_y;
5701{
5702#if 0 /* MAC_TODO: no icons on Mac */
5703#ifdef USE_X_TOOLKIT
5704 Window window = XtWindow (f->output_data.x->widget);
5705#else
5706 Window window = FRAME_X_WINDOW (f);
5707#endif
5708
5709 f->output_data.x->wm_hints.flags |= IconPositionHint;
5710 f->output_data.x->wm_hints.icon_x = icon_x;
5711 f->output_data.x->wm_hints.icon_y = icon_y;
5712
5713 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
e0f712ba 5714#endif /* MAC_TODO */
1a578e9b
AC
5715}
5716
5717\f
5718/***********************************************************************
5719 Fonts
5720 ***********************************************************************/
5721
5722/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5723
5724struct font_info *
5725x_get_font_info (f, font_idx)
5726 FRAME_PTR f;
5727 int font_idx;
5728{
5729 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5730}
5731
5732/* the global font name table */
5733char **font_name_table = NULL;
5734int font_name_table_size = 0;
5735int font_name_count = 0;
5736
e3564461 5737#if 0
1a578e9b
AC
5738/* compare two strings ignoring case */
5739static int
5740stricmp (const char *s, const char *t)
5741{
5742 for ( ; tolower (*s) == tolower (*t); s++, t++)
5743 if (*s == '\0')
5744 return 0;
5745 return tolower (*s) - tolower (*t);
5746}
5747
5748/* compare two strings ignoring case and handling wildcard */
5749static int
5750wildstrieq (char *s1, char *s2)
5751{
5752 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5753 return true;
5754
5755 return stricmp (s1, s2) == 0;
5756}
5757
5758/* Assume parameter 1 is fully qualified, no wildcards. */
177c0ea7 5759static int
1a578e9b
AC
5760mac_font_pattern_match (fontname, pattern)
5761 char * fontname;
5762 char * pattern;
5763{
b179a3a2 5764 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
1a578e9b
AC
5765 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5766 char *ptr;
5767
5768 /* Copy fontname so we can modify it during comparison. */
5769 strcpy (font_name_copy, fontname);
5770
5771 ptr = regex;
5772 *ptr++ = '^';
5773
5774 /* Turn pattern into a regexp and do a regexp match. */
5775 for (; *pattern; pattern++)
5776 {
5777 if (*pattern == '?')
5778 *ptr++ = '.';
5779 else if (*pattern == '*')
5780 {
5781 *ptr++ = '.';
5782 *ptr++ = '*';
5783 }
5784 else
5785 *ptr++ = *pattern;
5786 }
5787 *ptr = '$';
5788 *(ptr + 1) = '\0';
5789
5790 return (fast_c_string_match_ignore_case (build_string (regex),
5791 font_name_copy) >= 0);
5792}
5793
5794/* Two font specs are considered to match if their foundry, family,
5795 weight, slant, and charset match. */
177c0ea7 5796static int
1a578e9b
AC
5797mac_font_match (char *mf, char *xf)
5798{
5799 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5800 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5801
5802 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5803 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5804 return mac_font_pattern_match (mf, xf);
5805
5806 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5807 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5808 return mac_font_pattern_match (mf, xf);
5809
5810 return (wildstrieq (m_foundry, x_foundry)
5811 && wildstrieq (m_family, x_family)
5812 && wildstrieq (m_weight, x_weight)
5813 && wildstrieq (m_slant, x_slant)
5814 && wildstrieq (m_charset, x_charset))
5815 || mac_font_pattern_match (mf, xf);
5816}
e3564461
ST
5817#endif
5818
5819static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
5820
5821static void
fc7a70cc
ST
5822decode_mac_font_name (name, size, scriptcode)
5823 char *name;
5824 int size;
5825#if TARGET_API_MAC_CARBON
5826 int scriptcode;
5827#else
5828 short scriptcode;
5829#endif
e3564461
ST
5830{
5831 Lisp_Object coding_system;
5832 struct coding_system coding;
5833 char *buf;
5834
5835 switch (scriptcode)
5836 {
5837 case smTradChinese:
5838 coding_system = Qbig5;
5839 break;
5840 case smSimpChinese:
5841 coding_system = Qcn_gb;
5842 break;
5843 case smJapanese:
5844 coding_system = Qsjis;
5845 break;
5846 case smKorean:
5847 coding_system = Qeuc_kr;
ffe8b3f4 5848 break;
e3564461
ST
5849 default:
5850 return;
5851 }
5852
5853 setup_coding_system (coding_system, &coding);
5854 coding.src_multibyte = 0;
5855 coding.dst_multibyte = 1;
5856 coding.mode |= CODING_MODE_LAST_BLOCK;
5857 coding.composing = COMPOSITION_DISABLED;
5858 buf = (char *) alloca (size);
5859
5860 decode_coding (&coding, name, buf, strlen (name), size - 1);
5861 bcopy (buf, name, coding.produced);
5862 name[coding.produced] = '\0';
5863}
1a578e9b
AC
5864
5865
5866static char *
fc7a70cc
ST
5867mac_to_x_fontname (name, size, style, scriptcode, encoding_base)
5868 char *name;
5869 int size;
5870 Style style;
5871#if TARGET_API_MAC_CARBON
5872 int scriptcode;
5873#else
5874 short scriptcode;
5875#endif
1a578e9b
AC
5876{
5877 char foundry[32], family[32], cs[32];
e3564461 5878 char xf[256], *result, *p;
1a578e9b
AC
5879
5880 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5881 {
5882 strcpy(foundry, "Apple");
5883 strcpy(family, name);
5884
5885 switch (scriptcode)
5886 {
fc7a70cc 5887 case smTradChinese: /* == kTextEncodingMacChineseTrad */
1a578e9b
AC
5888 strcpy(cs, "big5-0");
5889 break;
fc7a70cc 5890 case smSimpChinese: /* == kTextEncodingMacChineseSimp */
83a96b4d 5891 strcpy(cs, "gb2312.1980-0");
1a578e9b 5892 break;
fc7a70cc 5893 case smJapanese: /* == kTextEncodingMacJapanese */
1a578e9b
AC
5894 strcpy(cs, "jisx0208.1983-sjis");
5895 break;
2f64cf3a
AC
5896 case -smJapanese:
5897 /* Each Apple Japanese font is entered into the font table
5898 twice: once as a jisx0208.1983-sjis font and once as a
5899 jisx0201.1976-0 font. The latter can be used to display
5900 the ascii charset and katakana-jisx0201 charset. A
5901 negative script code signals that the name of this latter
5902 font is being built. */
5903 strcpy(cs, "jisx0201.1976-0");
5904 break;
fc7a70cc 5905 case smKorean: /* == kTextEncodingMacKorean */
83a96b4d 5906 strcpy(cs, "ksc5601.1989-0");
177c0ea7 5907 break;
fc7a70cc
ST
5908#if TARGET_API_MAC_CARBON
5909 case kTextEncodingMacCyrillic:
5910 strcpy(cs, "mac-cyrillic");
5911 break;
5912 case kTextEncodingMacCentralEurRoman:
fbe6152f 5913 strcpy(cs, "mac-centraleurroman");
fc7a70cc
ST
5914 break;
5915 case kTextEncodingMacSymbol:
5916 case kTextEncodingMacDingbats:
5917 strcpy(cs, "adobe-fontspecific");
5918 break;
5919#endif
1a578e9b 5920 default:
fc7a70cc
ST
5921 strcpy(cs, "mac-roman");
5922 break;
1a578e9b
AC
5923 }
5924 }
5925
5926 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5927 foundry, family, style & bold ? "bold" : "medium",
5928 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
177c0ea7 5929
1a578e9b
AC
5930 result = (char *) xmalloc (strlen (xf) + 1);
5931 strcpy (result, xf);
5932 for (p = result; *p; p++)
5933 *p = tolower(*p);
5934 return result;
5935}
177c0ea7 5936
1a578e9b
AC
5937
5938/* Convert an X font spec to the corresponding mac font name, which
5939 can then be passed to GetFNum after conversion to a Pascal string.
5940 For ordinary Mac fonts, this should just be their names, like
5941 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5942 collection contain their charset designation in their names, like
5943 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5944 names are handled accordingly. */
5945static void
5946x_font_name_to_mac_font_name (char *xf, char *mf)
5947{
5948 char foundry[32], family[32], weight[20], slant[2], cs[32];
e3564461
ST
5949 Lisp_Object coding_system = Qnil;
5950 struct coding_system coding;
1a578e9b
AC
5951
5952 strcpy (mf, "");
5953
5954 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5955 foundry, family, weight, slant, cs) != 5 &&
5956 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5957 foundry, family, weight, slant, cs) != 5)
5958 return;
5959
e3564461
ST
5960 if (strcmp (cs, "big5-0") == 0)
5961 coding_system = Qbig5;
5962 else if (strcmp (cs, "gb2312.1980-0") == 0)
5963 coding_system = Qcn_gb;
5964 else if (strcmp (cs, "jisx0208.1983-sjis") == 0
5965 || strcmp (cs, "jisx0201.1976-0") == 0)
5966 coding_system = Qsjis;
5967 else if (strcmp (cs, "ksc5601.1989-0") == 0)
5968 coding_system = Qeuc_kr;
fc7a70cc
ST
5969 else if (strcmp (cs, "mac-roman") == 0
5970 || strcmp (cs, "mac-cyrillic") == 0
fbe6152f 5971 || strcmp (cs, "mac-centraleurroman") == 0
fc7a70cc 5972 || strcmp (cs, "adobe-fontspecific") == 0)
e3564461 5973 strcpy (mf, family);
1a578e9b 5974 else
e3564461
ST
5975 sprintf (mf, "%s-%s-%s", foundry, family, cs);
5976
5977 if (!NILP (coding_system))
5978 {
5979 setup_coding_system (coding_system, &coding);
5980 coding.src_multibyte = 1;
5981 coding.dst_multibyte = 1;
5982 coding.mode |= CODING_MODE_LAST_BLOCK;
5983 encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
5984 mf[coding.produced] = '\0';
5985 }
1a578e9b
AC
5986}
5987
5988
f00691a3
AC
5989static void
5990add_font_name_table_entry (char *font_name)
5991{
5992 if (font_name_table_size == 0)
5993 {
5994 font_name_table_size = 16;
5995 font_name_table = (char **)
5996 xmalloc (font_name_table_size * sizeof (char *));
5997 }
5998 else if (font_name_count + 1 >= font_name_table_size)
5999 {
6000 font_name_table_size += 16;
6001 font_name_table = (char **)
6002 xrealloc (font_name_table,
6003 font_name_table_size * sizeof (char *));
6004 }
6005
6006 font_name_table[font_name_count++] = font_name;
6007}
6008
6009/* Sets up the table font_name_table to contain the list of all fonts
6010 in the system the first time the table is used so that the Resource
6011 Manager need not be accessed every time this information is
6012 needed. */
1a578e9b
AC
6013
6014static void
6015init_font_name_table ()
6016{
e0f712ba
AC
6017#if TARGET_API_MAC_CARBON
6018 SInt32 sv;
177c0ea7 6019
e0f712ba
AC
6020 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
6021 {
6022 FMFontFamilyIterator ffi;
6023 FMFontFamilyInstanceIterator ffii;
6024 FMFontFamily ff;
1a578e9b 6025
e0f712ba
AC
6026 /* Create a dummy instance iterator here to avoid creating and
6027 destroying it in the loop. */
6028 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6029 return;
6030 /* Create an iterator to enumerate the font families. */
6031 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6032 != noErr)
6033 {
6034 FMDisposeFontFamilyInstanceIterator (&ffii);
6035 return;
6036 }
1a578e9b 6037
e0f712ba
AC
6038 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6039 {
6040 Str255 name;
6041 FMFont font;
6042 FMFontStyle style;
6043 FMFontSize size;
fc7a70cc
ST
6044 TextEncoding encoding;
6045 TextEncodingBase sc;
177c0ea7 6046
e0f712ba
AC
6047 if (FMGetFontFamilyName (ff, name) != noErr)
6048 break;
6049 p2cstr (name);
e3564461
ST
6050 if (*name == '.')
6051 continue;
177c0ea7 6052
fc7a70cc
ST
6053 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6054 break;
6055 sc = GetTextEncodingBase (encoding);
e3564461 6056 decode_mac_font_name (name, sizeof (name), sc);
b15325b2 6057
e0f712ba 6058 /* Point the instance iterator at the current font family. */
e3564461 6059 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
e0f712ba 6060 break;
177c0ea7 6061
e0f712ba
AC
6062 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6063 == noErr)
e3564461
ST
6064 {
6065 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6066 contained in Apple Japanese (SJIS) font. */
6067 again:
6068 if (size == 0)
6069 {
6070 add_font_name_table_entry (mac_to_x_fontname (name, size,
6071 style, sc));
6072 add_font_name_table_entry (mac_to_x_fontname (name, size,
6073 italic, sc));
6074 add_font_name_table_entry (mac_to_x_fontname (name, size,
6075 bold, sc));
6076 add_font_name_table_entry (mac_to_x_fontname (name, size,
6077 italic | bold,
6078 sc));
6079 }
6080 else
a0f593ff
AC
6081 add_font_name_table_entry (mac_to_x_fontname (name, size,
6082 style, sc));
e3564461
ST
6083 if (sc == smJapanese)
6084 {
6085 sc = -smJapanese;
6086 goto again;
6087 }
6088 else if (sc == -smJapanese)
6089 sc = smJapanese;
6090 }
e0f712ba 6091 }
177c0ea7 6092
e0f712ba
AC
6093 /* Dispose of the iterators. */
6094 FMDisposeFontFamilyIterator (&ffi);
6095 FMDisposeFontFamilyInstanceIterator (&ffii);
6096 }
6097 else
1a578e9b 6098 {
e0f712ba
AC
6099#endif /* TARGET_API_MAC_CARBON */
6100 GrafPtr port;
6101 SInt16 fontnum, old_fontnum;
6102 int num_mac_fonts = CountResources('FOND');
6103 int i, j;
6104 Handle font_handle, font_handle_2;
6105 short id, scriptcode;
6106 ResType type;
6107 Str32 name;
6108 struct FontAssoc *fat;
6109 struct AsscEntry *assc_entry;
177c0ea7 6110
e0f712ba
AC
6111 GetPort (&port); /* save the current font number used */
6112#if TARGET_API_MAC_CARBON
6113 old_fontnum = GetPortTextFont (port);
6114#else
6115 old_fontnum = port->txFont;
6116#endif
6117
6118 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6119 {
6120 font_handle = GetIndResource ('FOND', i);
6121 if (!font_handle)
6122 continue;
177c0ea7 6123
e0f712ba
AC
6124 GetResInfo (font_handle, &id, &type, name);
6125 GetFNum (name, &fontnum);
6126 p2cstr (name);
6127 if (fontnum == 0)
6128 continue;
177c0ea7 6129
e0f712ba
AC
6130 TextFont (fontnum);
6131 scriptcode = FontToScript (fontnum);
e3564461 6132 decode_mac_font_name (name, sizeof (name), scriptcode);
e0f712ba
AC
6133 do
6134 {
6135 HLock (font_handle);
177c0ea7 6136
e0f712ba
AC
6137 if (GetResourceSizeOnDisk (font_handle)
6138 >= sizeof (struct FamRec))
6139 {
6140 fat = (struct FontAssoc *) (*font_handle
6141 + sizeof (struct FamRec));
6142 assc_entry
6143 = (struct AsscEntry *) (*font_handle
6144 + sizeof (struct FamRec)
6145 + sizeof (struct FontAssoc));
177c0ea7 6146
e0f712ba 6147 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
199f9270 6148 {
e0f712ba
AC
6149 if (font_name_table_size == 0)
6150 {
6151 font_name_table_size = 16;
6152 font_name_table = (char **)
6153 xmalloc (font_name_table_size * sizeof (char *));
6154 }
6155 else if (font_name_count >= font_name_table_size)
6156 {
6157 font_name_table_size += 16;
6158 font_name_table = (char **)
6159 xrealloc (font_name_table,
6160 font_name_table_size * sizeof (char *));
6161 }
199f9270 6162 font_name_table[font_name_count++]
e0f712ba 6163 = mac_to_x_fontname (name,
199f9270
AC
6164 assc_entry->fontSize,
6165 assc_entry->fontStyle,
e0f712ba 6166 scriptcode);
e3564461
ST
6167 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6168 parts are contained in Apple Japanese (SJIS)
6169 font. */
e0f712ba
AC
6170 if (smJapanese == scriptcode)
6171 {
6172 font_name_table[font_name_count++]
6173 = mac_to_x_fontname (name,
6174 assc_entry->fontSize,
6175 assc_entry->fontStyle,
a0f593ff 6176 -smJapanese);
e0f712ba 6177 }
199f9270 6178 }
e0f712ba 6179 }
177c0ea7 6180
e0f712ba
AC
6181 HUnlock (font_handle);
6182 font_handle_2 = GetNextFOND (font_handle);
6183 ReleaseResource (font_handle);
6184 font_handle = font_handle_2;
6185 }
6186 while (ResError () == noErr && font_handle);
6187 }
177c0ea7 6188
e0f712ba
AC
6189 TextFont (old_fontnum);
6190#if TARGET_API_MAC_CARBON
1a578e9b 6191 }
e0f712ba 6192#endif /* TARGET_API_MAC_CARBON */
1a578e9b
AC
6193}
6194
6195
b15325b2
ST
6196void
6197mac_clear_font_name_table ()
6198{
6199 int i;
6200
6201 for (i = 0; i < font_name_count; i++)
6202 xfree (font_name_table[i]);
6203 xfree (font_name_table);
6204 font_name_table = NULL;
6205 font_name_table_size = font_name_count = 0;
6206}
6207
6208
e3564461
ST
6209enum xlfd_scalable_field_index
6210 {
6211 XLFD_SCL_PIXEL_SIZE,
6212 XLFD_SCL_POINT_SIZE,
6213 XLFD_SCL_AVGWIDTH,
6214 XLFD_SCL_LAST
6215 };
6216
6217static int xlfd_scalable_fields[] =
6218 {
6219 6, /* PIXEL_SIZE */
6220 7, /* POINT_SIZE */
6221 11, /* AVGWIDTH */
6222 -1
6223 };
6224
fbe6152f
ST
6225static Lisp_Object
6226mac_c_string_match (regexp, string, nonspecial, exact)
6227 Lisp_Object regexp;
6228 const char *string, *nonspecial;
6229 int exact;
6230{
6231 if (exact)
6232 {
6233 if (strcmp (string, nonspecial) == 0)
6234 return build_string (string);
6235 }
6236 else if (strstr (string, nonspecial))
6237 {
6238 Lisp_Object str = build_string (string);
6239
6240 if (fast_string_match (regexp, str) >= 0)
6241 return str;
6242 }
6243
6244 return Qnil;
6245}
6246
e3564461
ST
6247static Lisp_Object
6248mac_do_list_fonts (pattern, maxnames)
6249 char *pattern;
6250 int maxnames;
6251{
6252 int i, n_fonts = 0;
6253 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6254 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6255 char scaled[256];
6256 char *ptr;
6257 int scl_val[XLFD_SCL_LAST], *field, *val;
fbe6152f
ST
6258 char *longest_start, *cur_start, *nonspecial;
6259 int longest_len, cur_len, exact;
e3564461 6260
b15325b2
ST
6261 if (font_name_table == NULL) /* Initialize when first used. */
6262 init_font_name_table ();
6263
e3564461
ST
6264 for (i = 0; i < XLFD_SCL_LAST; i++)
6265 scl_val[i] = -1;
6266
6267 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6268 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6269 fonts are scaled according to the specified size. */
6270 ptr = pattern;
6271 i = 0;
6272 field = xlfd_scalable_fields;
6273 val = scl_val;
6274 if (*ptr == '-')
6275 do
6276 {
6277 ptr++;
6278 if (i == *field)
6279 {
6280 if ('1' <= *ptr && *ptr <= '9')
6281 {
6282 *val = *ptr++ - '0';
6283 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6284 *val = *val * 10 + *ptr++ - '0';
6285 if (*ptr != '-')
6286 *val = -1;
6287 }
6288 field++;
6289 val++;
6290 }
6291 ptr = strchr (ptr, '-');
6292 i++;
6293 }
6294 while (ptr && i < 14);
6295
6296 if (i == 14 && ptr == NULL)
6297 {
6298 if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
6299 {
6300 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
6301 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
6302 }
6303 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
6304 {
6305 scl_val[XLFD_SCL_POINT_SIZE] =
6306 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
6307 }
6308 else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
6309 {
6310 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
6311 scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
6312 }
6313 }
6314 else
6315 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6316
6317 ptr = regex;
6318 *ptr++ = '^';
6319
fbe6152f
ST
6320 longest_start = cur_start = ptr;
6321 longest_len = cur_len = 0;
6322 exact = 1;
6323
6324 /* Turn pattern into a regexp and do a regexp match. Also find the
6325 longest substring containing no special characters. */
e3564461
ST
6326 for (; *pattern; pattern++)
6327 {
fbe6152f
ST
6328 if (*pattern == '?' || *pattern == '*')
6329 {
6330 if (cur_len > longest_len)
6331 {
6332 longest_start = cur_start;
6333 longest_len = cur_len;
6334 }
6335 cur_len = 0;
6336 exact = 0;
6337
6338 if (*pattern == '?')
6339 *ptr++ = '.';
6340 else /* if (*pattern == '*') */
6341 {
6342 *ptr++ = '.';
6343 *ptr++ = '*';
6344 }
6345 }
e3564461 6346 else
fbe6152f
ST
6347 {
6348 if (cur_len == 0)
6349 cur_start = ptr;
6350 cur_len++;
6351
6352 *ptr++ = tolower (*pattern);
6353 }
e3564461 6354 }
fbe6152f
ST
6355
6356 if (cur_len > longest_len)
6357 {
6358 longest_start = cur_start;
6359 longest_len = cur_len;
6360 }
6361
e3564461
ST
6362 *ptr = '$';
6363 *(ptr + 1) = '\0';
6364
fbe6152f
ST
6365 nonspecial = xmalloc (longest_len + 1);
6366 strncpy (nonspecial, longest_start, longest_len);
6367 nonspecial[longest_len] = '\0';
6368
e3564461
ST
6369 pattern_regex = build_string (regex);
6370
6371 for (i = 0; i < font_name_count; i++)
6372 {
fbe6152f
ST
6373 fontname = mac_c_string_match (pattern_regex, font_name_table[i],
6374 nonspecial, exact);
6375 if (!NILP (fontname))
e3564461
ST
6376 {
6377 font_list = Fcons (fontname, font_list);
fbe6152f 6378 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
68c69027 6379 break;
e3564461
ST
6380 }
6381 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6382 && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
6383 {
6384 int former_len = ptr - font_name_table[i];
6385
6386 memcpy (scaled, font_name_table[i], former_len);
6387 sprintf (scaled + former_len,
6388 "-%d-%d-75-75-m-%d-%s",
6389 scl_val[XLFD_SCL_PIXEL_SIZE],
6390 scl_val[XLFD_SCL_POINT_SIZE],
6391 scl_val[XLFD_SCL_AVGWIDTH],
6392 ptr + sizeof ("-0-0-75-75-m-0-") - 1);
fbe6152f
ST
6393 fontname = mac_c_string_match (pattern_regex, scaled,
6394 nonspecial, exact);
6395 if (!NILP (fontname))
e3564461
ST
6396 {
6397 font_list = Fcons (fontname, font_list);
fbe6152f 6398 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
68c69027 6399 break;
e3564461
ST
6400 }
6401 }
6402 }
fbe6152f
ST
6403
6404 xfree (nonspecial);
6405
e3564461
ST
6406 return font_list;
6407}
6408
1a578e9b 6409/* Return a list of at most MAXNAMES font specs matching the one in
10ba2aec
AC
6410 PATTERN. Cache matching fonts for patterns in
6411 dpyinfo->name_list_element to avoid looking them up again by
0b325c12
AC
6412 calling mac_font_pattern_match (slow). Return as many matching
6413 fonts as possible if MAXNAMES = -1. */
1a578e9b
AC
6414
6415Lisp_Object
6416x_list_fonts (struct frame *f,
6417 Lisp_Object pattern,
6418 int size,
6419 int maxnames)
6420{
10ba2aec 6421 Lisp_Object newlist = Qnil, tem, key;
10ba2aec 6422 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
1a578e9b 6423
10ba2aec
AC
6424 if (dpyinfo)
6425 {
6426 tem = XCDR (dpyinfo->name_list_element);
6427 key = Fcons (pattern, make_number (maxnames));
6428
6429 newlist = Fassoc (key, tem);
6430 if (!NILP (newlist))
6431 {
6432 newlist = Fcdr_safe (newlist);
6433 goto label_cached;
6434 }
6435 }
6436
b15325b2 6437 BLOCK_INPUT;
e3564461 6438 newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
b15325b2 6439 UNBLOCK_INPUT;
177c0ea7 6440
1a578e9b
AC
6441 /* MAC_TODO: add code for matching outline fonts here */
6442
10ba2aec
AC
6443 if (dpyinfo)
6444 {
6445 XSETCDR (dpyinfo->name_list_element,
6446 Fcons (Fcons (key, newlist),
6447 XCDR (dpyinfo->name_list_element)));
6448 }
6449 label_cached:
177c0ea7 6450
1a578e9b
AC
6451 return newlist;
6452}
6453
6454
6455#if GLYPH_DEBUG
6456
e0f712ba
AC
6457/* Check that FONT is valid on frame F. It is if it can be found in F's
6458 font table. */
1a578e9b
AC
6459
6460static void
6461x_check_font (f, font)
6462 struct frame *f;
6463 XFontStruct *font;
6464{
6465 int i;
6466 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6467
6468 xassert (font != NULL);
6469
6470 for (i = 0; i < dpyinfo->n_fonts; i++)
177c0ea7 6471 if (dpyinfo->font_table[i].name
1a578e9b
AC
6472 && font == dpyinfo->font_table[i].font)
6473 break;
6474
6475 xassert (i < dpyinfo->n_fonts);
6476}
6477
6478#endif /* GLYPH_DEBUG != 0 */
6479
1a578e9b
AC
6480/* Set *W to the minimum width, *H to the minimum font height of FONT.
6481 Note: There are (broken) X fonts out there with invalid XFontStruct
6482 min_bounds contents. For example, handa@etl.go.jp reports that
6483 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6484 have font->min_bounds.width == 0. */
6485
6486static INLINE void
6487x_font_min_bounds (font, w, h)
6488 MacFontStruct *font;
6489 int *w, *h;
6490{
e0f712ba
AC
6491 /*
6492 * TODO: Windows does not appear to offer min bound, only
6493 * average and maximum width, and maximum height.
6494 */
1a578e9b 6495 *h = FONT_HEIGHT (font);
e0f712ba 6496 *w = FONT_WIDTH (font);
1a578e9b
AC
6497}
6498
6499
6500/* Compute the smallest character width and smallest font height over
6501 all fonts available on frame F. Set the members smallest_char_width
6502 and smallest_font_height in F's x_display_info structure to
6503 the values computed. Value is non-zero if smallest_font_height or
6504 smallest_char_width become smaller than they were before. */
6505
e0f712ba 6506int
1a578e9b
AC
6507x_compute_min_glyph_bounds (f)
6508 struct frame *f;
6509{
6510 int i;
6511 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6512 MacFontStruct *font;
6513 int old_width = dpyinfo->smallest_char_width;
6514 int old_height = dpyinfo->smallest_font_height;
177c0ea7 6515
1a578e9b
AC
6516 dpyinfo->smallest_font_height = 100000;
6517 dpyinfo->smallest_char_width = 100000;
177c0ea7 6518
1a578e9b
AC
6519 for (i = 0; i < dpyinfo->n_fonts; ++i)
6520 if (dpyinfo->font_table[i].name)
6521 {
6522 struct font_info *fontp = dpyinfo->font_table + i;
6523 int w, h;
177c0ea7 6524
1a578e9b
AC
6525 font = (MacFontStruct *) fontp->font;
6526 xassert (font != (MacFontStruct *) ~0);
6527 x_font_min_bounds (font, &w, &h);
177c0ea7 6528
1a578e9b
AC
6529 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6530 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6531 }
6532
6533 xassert (dpyinfo->smallest_char_width > 0
6534 && dpyinfo->smallest_font_height > 0);
6535
6536 return (dpyinfo->n_fonts == 1
6537 || dpyinfo->smallest_char_width < old_width
6538 || dpyinfo->smallest_font_height < old_height);
6539}
6540
6541
6542/* Determine whether given string is a fully-specified XLFD: all 14
6543 fields are present, none is '*'. */
6544
6545static int
6546is_fully_specified_xlfd (char *p)
6547{
6548 int i;
6549 char *q;
6550
6551 if (*p != '-')
6552 return 0;
177c0ea7 6553
1a578e9b
AC
6554 for (i = 0; i < 13; i++)
6555 {
6556 q = strchr (p + 1, '-');
6557 if (q == NULL)
6558 return 0;
6559 if (q - p == 2 && *(p + 1) == '*')
6560 return 0;
6561 p = q;
6562 }
6563
6564 if (strchr (p + 1, '-') != NULL)
6565 return 0;
177c0ea7 6566
1a578e9b
AC
6567 if (*(p + 1) == '*' && *(p + 2) == '\0')
6568 return 0;
6569
6570 return 1;
6571}
6572
6573
6574const int kDefaultFontSize = 9;
6575
6576
e0f712ba
AC
6577/* XLoadQueryFont creates and returns an internal representation for a
6578 font in a MacFontStruct struct. There is really no concept
6579 corresponding to "loading" a font on the Mac. But we check its
6580 existence and find the font number and all other information for it
6581 and store them in the returned MacFontStruct. */
1a578e9b
AC
6582
6583static MacFontStruct *
6584XLoadQueryFont (Display *dpy, char *fontname)
6585{
6586 int i, size, is_two_byte_font, char_width;
6587 char *name;
6588 GrafPtr port;
6589 SInt16 old_fontnum, old_fontsize;
6590 Style old_fontface;
6591 Str32 mfontname;
6592 SInt16 fontnum;
6593 Style fontface = normal;
6594 MacFontStruct *font;
6595 FontInfo the_fontinfo;
6596 char s_weight[7], c_slant;
6597
6598 if (is_fully_specified_xlfd (fontname))
6599 name = fontname;
6600 else
6601 {
e3564461 6602 Lisp_Object matched_fonts;
1a578e9b 6603
e3564461
ST
6604 matched_fonts = mac_do_list_fonts (fontname, 1);
6605 if (NILP (matched_fonts))
6606 return NULL;
6607 name = SDATA (XCAR (matched_fonts));
1a578e9b
AC
6608 }
6609
6610 GetPort (&port); /* save the current font number used */
e0f712ba
AC
6611#if TARGET_API_MAC_CARBON
6612 old_fontnum = GetPortTextFont (port);
6613 old_fontsize = GetPortTextSize (port);
6614 old_fontface = GetPortTextFace (port);
6615#else
1a578e9b
AC
6616 old_fontnum = port->txFont;
6617 old_fontsize = port->txSize;
6618 old_fontface = port->txFace;
e0f712ba 6619#endif
1a578e9b
AC
6620
6621 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6622 size = kDefaultFontSize;
6623
6624 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6625 if (strcmp (s_weight, "bold") == 0)
6626 fontface |= bold;
6627
6628 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6629 if (c_slant == 'i')
6630 fontface |= italic;
6631
6632 x_font_name_to_mac_font_name (name, mfontname);
6633 c2pstr (mfontname);
6634 GetFNum (mfontname, &fontnum);
6635 if (fontnum == 0)
6636 return NULL;
177c0ea7 6637
1a578e9b 6638 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
177c0ea7 6639
1a578e9b
AC
6640 font->fontname = (char *) xmalloc (strlen (name) + 1);
6641 bcopy (name, font->fontname, strlen (name) + 1);
6642
6643 font->mac_fontnum = fontnum;
6644 font->mac_fontsize = size;
6645 font->mac_fontface = fontface;
6646 font->mac_scriptcode = FontToScript (fontnum);
6647
199f9270 6648 /* Apple Japanese (SJIS) font is listed as both
2f64cf3a 6649 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
e0f712ba 6650 (Roman script) in init_font_name_table (). The latter should be
2f64cf3a 6651 treated as a one-byte font. */
199f9270
AC
6652 {
6653 char cs[32];
6654
177c0ea7 6655 if (sscanf (name,
199f9270
AC
6656 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6657 cs) == 1
177c0ea7 6658 && 0 == strcmp (cs, "jisx0201.1976-0"))
199f9270
AC
6659 font->mac_scriptcode = smRoman;
6660 }
177c0ea7 6661
1a578e9b
AC
6662 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6663 font->mac_scriptcode == smTradChinese ||
6664 font->mac_scriptcode == smSimpChinese ||
6665 font->mac_scriptcode == smKorean;
6666
6667 TextFont (fontnum);
6668 TextSize (size);
6669 TextFace (fontface);
177c0ea7 6670
1a578e9b
AC
6671 GetFontInfo (&the_fontinfo);
6672
6673 font->ascent = the_fontinfo.ascent;
6674 font->descent = the_fontinfo.descent;
6675
6676 font->min_byte1 = 0;
6677 if (is_two_byte_font)
6678 font->max_byte1 = 1;
6679 else
6680 font->max_byte1 = 0;
6681 font->min_char_or_byte2 = 0x20;
6682 font->max_char_or_byte2 = 0xff;
177c0ea7 6683
1a578e9b
AC
6684 if (is_two_byte_font)
6685 {
6686 /* Use the width of an "ideographic space" of that font because
6687 the_fontinfo.widMax returns the wrong width for some fonts. */
6688 switch (font->mac_scriptcode)
6689 {
6690 case smJapanese:
6691 char_width = StringWidth("\p\x81\x40");
6692 break;
6693 case smTradChinese:
6694 char_width = StringWidth("\p\xa1\x40");
6695 break;
6696 case smSimpChinese:
6697 char_width = StringWidth("\p\xa1\xa1");
6698 break;
6699 case smKorean:
6700 char_width = StringWidth("\p\xa1\xa1");
6701 break;
6702 }
6703 }
6704 else
6705 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6706 returns 15 for 12-point Monaco! */
6707 char_width = CharWidth ('m');
6708
6709 font->max_bounds.rbearing = char_width;
6710 font->max_bounds.lbearing = 0;
6711 font->max_bounds.width = char_width;
6712 font->max_bounds.ascent = the_fontinfo.ascent;
6713 font->max_bounds.descent = the_fontinfo.descent;
6714
6715 font->min_bounds = font->max_bounds;
6716
6717 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6718 font->per_char = NULL;
6719 else
6720 {
6721 font->per_char = (XCharStruct *)
6722 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6723 {
6724 int c;
177c0ea7 6725
1a578e9b
AC
6726 for (c = 0x20; c <= 0xff; c++)
6727 {
6728 font->per_char[c - 0x20] = font->max_bounds;
e3564461
ST
6729 font->per_char[c - 0x20].width =
6730 font->per_char[c - 0x20].rbearing = CharWidth (c);
1a578e9b
AC
6731 }
6732 }
6733 }
177c0ea7 6734
1a578e9b
AC
6735 TextFont (old_fontnum); /* restore previous font number, size and face */
6736 TextSize (old_fontsize);
6737 TextFace (old_fontface);
177c0ea7 6738
1a578e9b
AC
6739 return font;
6740}
6741
6742
b15325b2
ST
6743void
6744mac_unload_font (dpyinfo, font)
6745 struct mac_display_info *dpyinfo;
6746 XFontStruct *font;
6747{
6748 xfree (font->fontname);
6749 if (font->per_char)
6750 xfree (font->per_char);
6751 xfree (font);
6752}
6753
6754
1a578e9b
AC
6755/* Load font named FONTNAME of the size SIZE for frame F, and return a
6756 pointer to the structure font_info while allocating it dynamically.
6757 If SIZE is 0, load any size of font.
6758 If loading is failed, return NULL. */
6759
6760struct font_info *
6761x_load_font (f, fontname, size)
6762 struct frame *f;
6763 register char *fontname;
6764 int size;
6765{
6766 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6767 Lisp_Object font_names;
6768
6769 /* Get a list of all the fonts that match this name. Once we
6770 have a list of matching fonts, we compare them against the fonts
6771 we already have by comparing names. */
6772 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6773
6774 if (!NILP (font_names))
6775 {
6776 Lisp_Object tail;
6777 int i;
6778
6779 for (i = 0; i < dpyinfo->n_fonts; i++)
6780 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6781 if (dpyinfo->font_table[i].name
6782 && (!strcmp (dpyinfo->font_table[i].name,
d5db4077 6783 SDATA (XCAR (tail)))
1a578e9b 6784 || !strcmp (dpyinfo->font_table[i].full_name,
d5db4077 6785 SDATA (XCAR (tail)))))
1a578e9b
AC
6786 return (dpyinfo->font_table + i);
6787 }
6788
6789 /* Load the font and add it to the table. */
6790 {
6791 char *full_name;
6792 struct MacFontStruct *font;
6793 struct font_info *fontp;
6794 unsigned long value;
6795 int i;
6796
6797 /* If we have found fonts by x_list_font, load one of them. If
6798 not, we still try to load a font by the name given as FONTNAME
6799 because XListFonts (called in x_list_font) of some X server has
6800 a bug of not finding a font even if the font surely exists and
6801 is loadable by XLoadQueryFont. */
6802 if (size > 0 && !NILP (font_names))
d5db4077 6803 fontname = (char *) SDATA (XCAR (font_names));
1a578e9b 6804
b15325b2 6805 BLOCK_INPUT;
1a578e9b 6806 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
b15325b2 6807 UNBLOCK_INPUT;
1a578e9b
AC
6808 if (!font)
6809 return NULL;
6810
6811 /* Find a free slot in the font table. */
6812 for (i = 0; i < dpyinfo->n_fonts; ++i)
6813 if (dpyinfo->font_table[i].name == NULL)
6814 break;
6815
6816 /* If no free slot found, maybe enlarge the font table. */
6817 if (i == dpyinfo->n_fonts
6818 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6819 {
6820 int sz;
6821 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6822 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6823 dpyinfo->font_table
6824 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6825 }
6826
6827 fontp = dpyinfo->font_table + i;
6828 if (i == dpyinfo->n_fonts)
6829 ++dpyinfo->n_fonts;
6830
6831 /* Now fill in the slots of *FONTP. */
6832 BLOCK_INPUT;
be2fdba9 6833 bzero (fontp, sizeof (*fontp));
1a578e9b
AC
6834 fontp->font = font;
6835 fontp->font_idx = i;
6836 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6837 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6838
6839 fontp->full_name = fontp->name;
6840
6841 fontp->size = font->max_bounds.width;
6842 fontp->height = FONT_HEIGHT (font);
6843 {
6844 /* For some font, ascent and descent in max_bounds field is
6845 larger than the above value. */
6846 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6847 if (max_height > fontp->height)
6848 fontp->height = max_height;
6849 }
6850
6851 /* The slot `encoding' specifies how to map a character
6852 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6853 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6854 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6855 2:0xA020..0xFF7F). For the moment, we don't know which charset
6856 uses this font. So, we set information in fontp->encoding[1]
6857 which is never used by any charset. If mapping can't be
6858 decided, set FONT_ENCODING_NOT_DECIDED. */
6859 if (font->mac_scriptcode == smJapanese)
6860 fontp->encoding[1] = 4;
6861 else
6862 {
6863 fontp->encoding[1]
6864 = (font->max_byte1 == 0
6865 /* 1-byte font */
6866 ? (font->min_char_or_byte2 < 0x80
6867 ? (font->max_char_or_byte2 < 0x80
6868 ? 0 /* 0x20..0x7F */
6869 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6870 : 1) /* 0xA0..0xFF */
6871 /* 2-byte font */
6872 : (font->min_byte1 < 0x80
6873 ? (font->max_byte1 < 0x80
6874 ? (font->min_char_or_byte2 < 0x80
6875 ? (font->max_char_or_byte2 < 0x80
6876 ? 0 /* 0x2020..0x7F7F */
6877 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6878 : 3) /* 0x20A0..0x7FFF */
6879 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6880 : (font->min_char_or_byte2 < 0x80
6881 ? (font->max_char_or_byte2 < 0x80
6882 ? 2 /* 0xA020..0xFF7F */
6883 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6884 : 1))); /* 0xA0A0..0xFFFF */
6885 }
6886
6887#if 0 /* MAC_TODO: fill these out with more reasonably values */
6888 fontp->baseline_offset
6889 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6890 ? (long) value : 0);
6891 fontp->relative_compose
6892 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6893 ? (long) value : 0);
6894 fontp->default_ascent
6895 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6896 ? (long) value : 0);
6897#else
6898 fontp->baseline_offset = 0;
6899 fontp->relative_compose = 0;
6900 fontp->default_ascent = 0;
6901#endif
6902
6903 /* Set global flag fonts_changed_p to non-zero if the font loaded
6904 has a character with a smaller width than any other character
6905 before, or if the font loaded has a smalle>r height than any
6906 other font loaded before. If this happens, it will make a
6907 glyph matrix reallocation necessary. */
6908 fonts_changed_p = x_compute_min_glyph_bounds (f);
6909 UNBLOCK_INPUT;
6910 return fontp;
6911 }
6912}
6913
6914
6915/* Return a pointer to struct font_info of a font named FONTNAME for
6916 frame F. If no such font is loaded, return NULL. */
6917
6918struct font_info *
6919x_query_font (f, fontname)
6920 struct frame *f;
6921 register char *fontname;
6922{
6923 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6924 int i;
6925
6926 for (i = 0; i < dpyinfo->n_fonts; i++)
6927 if (dpyinfo->font_table[i].name
6928 && (!strcmp (dpyinfo->font_table[i].name, fontname)
6929 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
6930 return (dpyinfo->font_table + i);
6931 return NULL;
6932}
6933
6934
6935/* Find a CCL program for a font specified by FONTP, and set the member
6936 `encoder' of the structure. */
6937
6938void
6939x_find_ccl_program (fontp)
6940 struct font_info *fontp;
6941{
6942 Lisp_Object list, elt;
6943
6944 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
6945 {
6946 elt = XCAR (list);
6947 if (CONSP (elt)
6948 && STRINGP (XCAR (elt))
6949 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
6950 >= 0))
6951 break;
6952 }
6953 if (! NILP (list))
6954 {
6955 struct ccl_program *ccl
6956 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
6957
6958 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
6959 xfree (ccl);
6960 else
6961 fontp->font_encoder = ccl;
6962 }
6963}
6964
6965
6966\f
1a578e9b
AC
6967/* The Mac Event loop code */
6968
e0f712ba 6969#ifndef MAC_OSX
1a578e9b
AC
6970#include <Events.h>
6971#include <Quickdraw.h>
6972#include <Balloons.h>
6973#include <Devices.h>
6974#include <Fonts.h>
6975#include <Gestalt.h>
6976#include <Menus.h>
6977#include <Processes.h>
6978#include <Sound.h>
6979#include <ToolUtils.h>
6980#include <TextUtils.h>
6981#include <Dialogs.h>
6982#include <Script.h>
1a578e9b
AC
6983#include <Types.h>
6984#include <TextEncodingConverter.h>
6985#include <Resources.h>
6986
6987#if __MWERKS__
6988#include <unix.h>
6989#endif
e0f712ba 6990#endif /* ! MAC_OSX */
1a578e9b
AC
6991
6992#define M_APPLE 128
6993#define I_ABOUT 1
6994
6995#define WINDOW_RESOURCE 128
6996#define TERM_WINDOW_RESOURCE 129
6997
6998#define DEFAULT_NUM_COLS 80
6999
7000#define MIN_DOC_SIZE 64
7001#define MAX_DOC_SIZE 32767
7002
7003/* sleep time for WaitNextEvent */
7004#define WNE_SLEEP_AT_SUSPEND 10
7005#define WNE_SLEEP_AT_RESUME 1
7006
7007/* true when cannot handle any Mac OS events */
7008static int handling_window_update = 0;
7009
bf06c82f 7010#if 0
1a578e9b
AC
7011/* the flag appl_is_suspended is used both for determining the sleep
7012 time to be passed to WaitNextEvent and whether the cursor should be
7013 drawn when updating the display. The cursor is turned off when
7014 Emacs is suspended. Redrawing it is unnecessary and what needs to
7015 be done depends on whether the cursor lies inside or outside the
7016 redraw region. So we might as well skip drawing it when Emacs is
7017 suspended. */
7018static Boolean app_is_suspended = false;
7019static long app_sleep_time = WNE_SLEEP_AT_RESUME;
bf06c82f 7020#endif
1a578e9b
AC
7021
7022#define EXTRA_STACK_ALLOC (256 * 1024)
7023
7024#define ARGV_STRING_LIST_ID 129
7025#define ABOUT_ALERT_ID 128
2e875e36 7026#define RAM_TOO_LARGE_ALERT_ID 129
1a578e9b
AC
7027
7028Boolean terminate_flag = false;
7029
dd4497dc
ST
7030/* Contains the string "reverse", which is a constant for mouse button emu.*/
7031Lisp_Object Qreverse;
7032
742fbed7 7033/* True if using command key as meta key. */
1a578e9b
AC
7034Lisp_Object Vmac_command_key_is_meta;
7035
a36f1680
JW
7036/* Modifier associated with the option key, or nil for normal behavior. */
7037Lisp_Object Vmac_option_modifier;
7038
742fbed7
AC
7039/* True if the ctrl and meta keys should be reversed. */
7040Lisp_Object Vmac_reverse_ctrl_meta;
7041
dd4497dc
ST
7042/* True if the option and command modifiers should be used to emulate
7043 a three button mouse */
7044Lisp_Object Vmac_emulate_three_button_mouse;
7045
742fbed7
AC
7046#if USE_CARBON_EVENTS
7047/* True if the mouse wheel button (i.e. button 4) should map to
7048 mouse-2, instead of mouse-3. */
7049Lisp_Object Vmac_wheel_button_is_mouse_2;
5883787c
AC
7050
7051/* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7052 for processing before Emacs sees it. */
7053Lisp_Object Vmac_pass_command_to_system;
7054
7055/* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7056 for processing before Emacs sees it. */
7057Lisp_Object Vmac_pass_control_to_system;
742fbed7
AC
7058#endif
7059
1a578e9b
AC
7060/* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7061 to this text encoding */
7062int mac_keyboard_text_encoding;
7063int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
7064
7065/* Set in term/mac-win.el to indicate that event loop can now generate
7066 drag and drop events. */
8f47302e 7067Lisp_Object Qmac_ready_for_drag_n_drop;
1a578e9b
AC
7068
7069Lisp_Object drag_and_drop_file_list;
7070
7071Point saved_menu_event_location;
7072
50bf7673
ST
7073#if !TARGET_API_MAC_CARBON
7074/* Place holder for the default arrow cursor. */
7075CursPtr arrow_cursor;
7076#endif
7077
1a578e9b 7078/* Apple Events */
742fbed7 7079static void init_required_apple_events (void);
e0f712ba 7080static pascal OSErr
742fbed7 7081do_ae_open_application (const AppleEvent *, AppleEvent *, long);
e0f712ba 7082static pascal OSErr
742fbed7
AC
7083do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7084static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7085static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7086
b15325b2 7087#if TARGET_API_MAC_CARBON
742fbed7
AC
7088/* Drag and Drop */
7089static OSErr init_mac_drag_n_drop ();
177c0ea7 7090static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
b15325b2 7091#endif
742fbed7
AC
7092
7093#if USE_CARBON_EVENTS
7094/* Preliminary Support for the OSX Services Menu */
7095static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
7096static void init_service_handler ();
b15325b2
ST
7097/* Window Event Handler */
7098static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
7099 EventRef, void *);
742fbed7 7100#endif
b15325b2 7101void install_window_handler (WindowPtr);
1a578e9b
AC
7102
7103extern void init_emacs_passwd_dir ();
7104extern int emacs_main (int, char **, char **);
7105extern void check_alarm ();
7106
7107extern void initialize_applescript();
7108extern void terminate_applescript();
7109
177c0ea7 7110static unsigned int
742fbed7
AC
7111#if USE_CARBON_EVENTS
7112mac_to_emacs_modifiers (UInt32 mods)
7113#else
7114mac_to_emacs_modifiers (EventModifiers mods)
7115#endif
7116{
7117 unsigned int result = 0;
7118 if (mods & macShiftKey)
7119 result |= shift_modifier;
7120 if (mods & macCtrlKey)
7121 result |= ctrl_modifier;
7122 if (mods & macMetaKey)
7123 result |= meta_modifier;
7124 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7125 result |= alt_modifier;
a36f1680
JW
7126 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7127 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7128 if (!NILP(val))
7129 result |= XUINT(val);
7130 }
7131
742fbed7
AC
7132 return result;
7133}
7134
dd4497dc
ST
7135static int
7136mac_get_emulated_btn ( UInt32 modifiers )
7137{
7138 int result = 0;
a433994a
ST
7139 if (!NILP (Vmac_emulate_three_button_mouse)) {
7140 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
c61278bb 7141 if (modifiers & cmdKey)
dd4497dc
ST
7142 result = cmdIs3 ? 2 : 1;
7143 else if (modifiers & optionKey)
ffe8b3f4 7144 result = cmdIs3 ? 1 : 2;
dd4497dc
ST
7145 }
7146 return result;
7147}
7148
742fbed7
AC
7149#if USE_CARBON_EVENTS
7150/* Obtains the event modifiers from the event ref and then calls
7151 mac_to_emacs_modifiers. */
177c0ea7
JB
7152static int
7153mac_event_to_emacs_modifiers (EventRef eventRef)
742fbed7
AC
7154{
7155 UInt32 mods = 0;
7156 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7157 sizeof (UInt32), NULL, &mods);
a433994a 7158 if (!NILP (Vmac_emulate_three_button_mouse) &&
dd4497dc
ST
7159 GetEventClass(eventRef) == kEventClassMouse)
7160 {
c61278bb 7161 mods &= ~(optionKey | cmdKey);
dd4497dc 7162 }
742fbed7
AC
7163 return mac_to_emacs_modifiers (mods);
7164}
7165
7166/* Given an event ref, return the code to use for the mouse button
7167 code in the emacs input_event. */
7168static int
177c0ea7 7169mac_get_mouse_btn (EventRef ref)
742fbed7
AC
7170{
7171 EventMouseButton result = kEventMouseButtonPrimary;
7172 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7173 sizeof (EventMouseButton), NULL, &result);
177c0ea7 7174 switch (result)
742fbed7
AC
7175 {
7176 case kEventMouseButtonPrimary:
a433994a 7177 if (NILP (Vmac_emulate_three_button_mouse))
dd4497dc
ST
7178 return 0;
7179 else {
7180 UInt32 mods = 0;
7181 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7182 sizeof (UInt32), NULL, &mods);
7183 return mac_get_emulated_btn(mods);
7184 }
742fbed7 7185 case kEventMouseButtonSecondary:
177c0ea7 7186 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
742fbed7
AC
7187 case kEventMouseButtonTertiary:
7188 case 4: /* 4 is the number for the mouse wheel button */
177c0ea7 7189 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
742fbed7
AC
7190 default:
7191 return 0;
7192 }
7193}
7194
7195/* Normally, ConvertEventRefToEventRecord will correctly handle all
7196 events. However the click of the mouse wheel is not converted to a
7197 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7198 checks to see if it is a mouse up or down carbon event that has not
7199 been converted, and if so, converts it by hand (to be picked up in
7200 the XTread_socket loop). */
177c0ea7 7201static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
742fbed7
AC
7202{
7203 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7204 /* Do special case for mouse wheel button. */
177c0ea7
JB
7205 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7206 {
742fbed7 7207 UInt32 kind = GetEventKind (eventRef);
177c0ea7 7208 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
742fbed7
AC
7209 {
7210 eventRec->what = mouseDown;
7211 result=1;
7212 }
177c0ea7 7213 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
742fbed7
AC
7214 {
7215 eventRec->what = mouseUp;
7216 result=1;
7217 }
177c0ea7 7218 if (result)
742fbed7
AC
7219 {
7220 /* Need where and when. */
7221 UInt32 mods;
7222 GetEventParameter (eventRef, kEventParamMouseLocation,
7223 typeQDPoint, NULL, sizeof (Point),
7224 NULL, &eventRec->where);
7225 /* Use two step process because new event modifiers are
7226 32-bit and old are 16-bit. Currently, only loss is
7227 NumLock & Fn. */
7228 GetEventParameter (eventRef, kEventParamKeyModifiers,
7229 typeUInt32, NULL, sizeof (UInt32),
7230 NULL, &mods);
7231 eventRec->modifiers = mods;
177c0ea7 7232
742fbed7
AC
7233 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7234 }
7235 }
7236 return result;
7237}
7238
7239#endif
1a578e9b
AC
7240
7241static void
7242do_get_menus (void)
7243{
7244 Handle menubar_handle;
7245 MenuHandle menu_handle;
177c0ea7 7246
1a578e9b
AC
7247 menubar_handle = GetNewMBar (128);
7248 if(menubar_handle == NULL)
7249 abort ();
7250 SetMenuBar (menubar_handle);
7251 DrawMenuBar ();
7252
7253 menu_handle = GetMenuHandle (M_APPLE);
7254 if(menu_handle != NULL)
7255 AppendResMenu (menu_handle,'DRVR');
7256 else
7257 abort ();
7258}
7259
7260
7261static void
7262do_init_managers (void)
7263{
e0f712ba 7264#if !TARGET_API_MAC_CARBON
1a578e9b
AC
7265 InitGraf (&qd.thePort);
7266 InitFonts ();
7267 FlushEvents (everyEvent, 0);
7268 InitWindows ();
7269 InitMenus ();
7270 TEInit ();
7271 InitDialogs (NULL);
e0f712ba
AC
7272#endif /* !TARGET_API_MAC_CARBON */
7273 InitCursor ();
177c0ea7 7274
e0f712ba 7275#if !TARGET_API_MAC_CARBON
50bf7673
ST
7276 arrow_cursor = &qd.arrow;
7277
1a578e9b
AC
7278 /* set up some extra stack space for use by emacs */
7279 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7280
7281 /* MaxApplZone must be called for AppleScript to execute more
7282 complicated scripts */
7283 MaxApplZone ();
7284 MoreMasters ();
e0f712ba 7285#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
7286}
7287
2e875e36
AC
7288static void
7289do_check_ram_size (void)
7290{
7291 SInt32 physical_ram_size, logical_ram_size;
177c0ea7 7292
2e875e36
AC
7293 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7294 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
eccab144
SM
7295 || physical_ram_size > (1 << VALBITS)
7296 || logical_ram_size > (1 << VALBITS))
2e875e36
AC
7297 {
7298 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7299 exit (1);
7300 }
7301}
7302
1a578e9b
AC
7303static void
7304do_window_update (WindowPtr win)
7305{
50bf7673
ST
7306 struct frame *f = mac_window_to_frame (win);
7307
b15325b2 7308 BeginUpdate (win);
1a578e9b 7309
b15325b2
ST
7310 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7311 below. */
7312 if (win != tip_window)
1a578e9b
AC
7313 {
7314 if (f->async_visible == 0)
7315 {
7316 f->async_visible = 1;
7317 f->async_iconified = 0;
7318 SET_FRAME_GARBAGED (f);
177c0ea7 7319
1a578e9b
AC
7320 /* An update event is equivalent to MapNotify on X, so report
7321 visibility changes properly. */
7322 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7323 /* Force a redisplay sooner or later to update the
7324 frame titles in case this is the second frame. */
7325 record_asynch_buffer_change ();
7326 }
7327 else
7328 {
b15325b2
ST
7329 Rect r;
7330
1a578e9b
AC
7331 handling_window_update = 1;
7332
b15325b2
ST
7333#if TARGET_API_MAC_CARBON
7334 {
7335 RgnHandle region = NewRgn ();
2d97ff8c 7336
b15325b2
ST
7337 GetPortVisibleRegion (GetWindowPort (win), region);
7338 UpdateControls (win, region);
7339 GetRegionBounds (region, &r);
7340 DisposeRgn (region);
7341 }
7342#else
7343 UpdateControls (win, win->visRgn);
7344 r = (*win->visRgn)->rgnBBox;
7345#endif
7346 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
1a578e9b
AC
7347
7348 handling_window_update = 0;
1a578e9b
AC
7349 }
7350 }
b15325b2
ST
7351
7352 EndUpdate (win);
1a578e9b
AC
7353}
7354
e0f712ba
AC
7355static int
7356is_emacs_window (WindowPtr win)
7357{
7358 Lisp_Object tail, frame;
7359
7360 if (!win)
7361 return 0;
7362
7363 FOR_EACH_FRAME (tail, frame)
7364 if (FRAME_MAC_P (XFRAME (frame)))
7365 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7366 return 1;
7367
7368 return 0;
7369}
7370
1a578e9b
AC
7371static void
7372do_app_resume ()
7373{
bf06c82f
ST
7374 /* Window-activate events will do the job. */
7375#if 0
e0f712ba 7376 WindowPtr wp;
e0f712ba 7377 struct frame *f;
fa0b4c14 7378
bf06c82f
ST
7379 wp = front_emacs_window ();
7380 if (wp)
1a578e9b 7381 {
50bf7673 7382 f = mac_window_to_frame (wp);
e0f712ba
AC
7383
7384 if (f)
7385 {
7386 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
7387 activate_scroll_bars (f);
7388 }
1a578e9b
AC
7389 }
7390
7391 app_is_suspended = false;
7392 app_sleep_time = WNE_SLEEP_AT_RESUME;
bf06c82f 7393#endif
1a578e9b
AC
7394}
7395
7396static void
7397do_app_suspend ()
7398{
bf06c82f
ST
7399 /* Window-deactivate events will do the job. */
7400#if 0
e0f712ba 7401 WindowPtr wp;
e0f712ba 7402 struct frame *f;
1a578e9b 7403
bf06c82f
ST
7404 wp = front_emacs_window ();
7405 if (wp)
1a578e9b 7406 {
50bf7673 7407 f = mac_window_to_frame (wp);
e0f712ba
AC
7408
7409 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
7410 {
7411 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
7412 deactivate_scroll_bars (f);
7413 }
1a578e9b
AC
7414 }
7415
7416 app_is_suspended = true;
7417 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
bf06c82f 7418#endif
1a578e9b
AC
7419}
7420
7421
7422static void
50bf7673
ST
7423do_mouse_moved (mouse_pos, f)
7424 Point mouse_pos;
7425 FRAME_PTR *f;
1a578e9b 7426{
bf06c82f 7427 WindowPtr wp = front_emacs_window ();
50bf7673 7428 struct x_display_info *dpyinfo;
1a578e9b 7429
bf06c82f 7430 if (wp)
5883787c 7431 {
50bf7673
ST
7432 *f = mac_window_to_frame (wp);
7433 dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
177c0ea7 7434
50bf7673
ST
7435 if (dpyinfo->mouse_face_hidden)
7436 {
7437 dpyinfo->mouse_face_hidden = 0;
7438 clear_mouse_face (dpyinfo);
7439 }
177c0ea7 7440
50bf7673 7441 SetPortWindowPort (wp);
1a578e9b 7442
50bf7673 7443 GlobalToLocal (&mouse_pos);
1a578e9b 7444
50bf7673
ST
7445 if (dpyinfo->grabbed && tracked_scroll_bar)
7446 x_scroll_bar_note_movement (tracked_scroll_bar,
7447 mouse_pos.v
7448 - XINT (tracked_scroll_bar->top),
7449 TickCount() * (1000 / 60));
1a578e9b 7450 else
50bf7673 7451 note_mouse_movement (*f, &mouse_pos);
1a578e9b
AC
7452 }
7453}
7454
1a578e9b
AC
7455
7456static void
7457do_apple_menu (SInt16 menu_item)
7458{
e0f712ba 7459#if !TARGET_API_MAC_CARBON
1a578e9b
AC
7460 Str255 item_name;
7461 SInt16 da_driver_refnum;
177c0ea7 7462
1a578e9b
AC
7463 if (menu_item == I_ABOUT)
7464 NoteAlert (ABOUT_ALERT_ID, NULL);
7465 else
7466 {
7467 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7468 da_driver_refnum = OpenDeskAcc (item_name);
7469 }
e0f712ba 7470#endif /* !TARGET_API_MAC_CARBON */
1a578e9b
AC
7471}
7472
7473void
7474do_menu_choice (SInt32 menu_choice)
7475{
7476 SInt16 menu_id, menu_item;
177c0ea7 7477
1a578e9b
AC
7478 menu_id = HiWord (menu_choice);
7479 menu_item = LoWord (menu_choice);
177c0ea7 7480
1a578e9b
AC
7481 if (menu_id == 0)
7482 return;
177c0ea7 7483
1a578e9b
AC
7484 switch (menu_id)
7485 {
7486 case M_APPLE:
7487 do_apple_menu (menu_item);
7488 break;
7489
7490 default:
7491 {
bf06c82f 7492 struct frame *f = mac_window_to_frame (front_emacs_window ());
1a578e9b
AC
7493 MenuHandle menu = GetMenuHandle (menu_id);
7494 if (menu)
7495 {
7496 UInt32 refcon;
177c0ea7 7497
1a578e9b
AC
7498 GetMenuItemRefCon (menu, menu_item, &refcon);
7499 menubar_selection_callback (f, refcon);
7500 }
7501 }
7502 }
177c0ea7 7503
1a578e9b
AC
7504 HiliteMenu (0);
7505}
7506
7507
7508/* Handle drags in size box. Based on code contributed by Ben
7509 Mesander and IM - Window Manager A. */
7510
7511static void
7512do_grow_window (WindowPtr w, EventRecord *e)
7513{
1a578e9b 7514 Rect limit_rect;
b15325b2 7515 int rows, columns, width, height;
50bf7673 7516 struct frame *f = mac_window_to_frame (w);
b15325b2
ST
7517 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
7518 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
7519#if TARGET_API_MAC_CARBON
7520 Rect new_rect;
7521#else
7522 long grow_size;
7523#endif
177c0ea7 7524
b15325b2
ST
7525 if (size_hints->flags & PMinSize)
7526 {
7527 min_width = size_hints->min_width;
7528 min_height = size_hints->min_height;
7529 }
7530 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
177c0ea7 7531
b15325b2
ST
7532#if TARGET_API_MAC_CARBON
7533 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
7534 return;
7535 height = new_rect.bottom - new_rect.top;
7536 width = new_rect.right - new_rect.left;
7537#else
1a578e9b 7538 grow_size = GrowWindow (w, e->where, &limit_rect);
1a578e9b 7539 /* see if it really changed size */
b15325b2
ST
7540 if (grow_size == 0)
7541 return;
7542 height = HiWord (grow_size);
7543 width = LoWord (grow_size);
7544#endif
7545
7546 if (width != FRAME_PIXEL_WIDTH (f)
7547 || height != FRAME_PIXEL_HEIGHT (f))
1a578e9b 7548 {
b15325b2
ST
7549 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7550 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
177c0ea7 7551
1a578e9b
AC
7552 x_set_window_size (f, 0, columns, rows);
7553 }
7554}
7555
7556
7557/* Handle clicks in zoom box. Calculation of "standard state" based
7558 on code in IM - Window Manager A and code contributed by Ben
7559 Mesander. The standard state of an Emacs window is 80-characters
7560 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7561
7562static void
7563do_zoom_window (WindowPtr w, int zoom_in_or_out)
7564{
7565 GrafPtr save_port;
7566 Rect zoom_rect, port_rect;
7567 Point top_left;
b15325b2 7568 int w_title_height, columns, rows, width, height;
50bf7673 7569 struct frame *f = mac_window_to_frame (w);
177c0ea7 7570
e0f712ba
AC
7571#if TARGET_API_MAC_CARBON
7572 {
bf06c82f 7573 Point standard_size;
177c0ea7 7574
bf06c82f
ST
7575 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7576 standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
e0f712ba 7577
bf06c82f
ST
7578 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7579 zoom_in_or_out = inZoomIn;
7580 else
e0f712ba 7581 {
bf06c82f
ST
7582 /* Adjust the standard size according to character boundaries. */
7583
7584 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7585 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7586 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7587 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7588 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7589 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7590 && port_rect.left == zoom_rect.left
7591 && port_rect.top == zoom_rect.top)
7592 zoom_in_or_out = inZoomIn;
7593 else
7594 zoom_in_or_out = inZoomOut;
e0f712ba 7595 }
bf06c82f
ST
7596
7597 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
e0f712ba
AC
7598 }
7599#else /* not TARGET_API_MAC_CARBON */
bf06c82f
ST
7600 GetPort (&save_port);
7601
7602 SetPortWindowPort (w);
7603
7604 /* Clear window to avoid flicker. */
e0f712ba 7605 EraseRect (&(w->portRect));
1a578e9b
AC
7606 if (zoom_in_or_out == inZoomOut)
7607 {
e0f712ba 7608 SetPt (&top_left, w->portRect.left, w->portRect.top);
1a578e9b
AC
7609 LocalToGlobal (&top_left);
7610
7611 /* calculate height of window's title bar */
7612 w_title_height = top_left.v - 1
e0f712ba 7613 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
1a578e9b
AC
7614
7615 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7616 zoom_rect = qd.screenBits.bounds;
7617 zoom_rect.top += w_title_height;
7618 InsetRect (&zoom_rect, 8, 4); /* not too tight */
177c0ea7 7619
1a578e9b 7620 zoom_rect.right = zoom_rect.left
f1a83aab 7621 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
1a578e9b 7622
bf06c82f
ST
7623 /* Adjust the standard size according to character boundaries. */
7624 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7625 zoom_rect.bottom =
7626 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7627
e0f712ba
AC
7628 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7629 = zoom_rect;
1a578e9b
AC
7630 }
7631
bf06c82f
ST
7632 ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
7633
7634 SetPort (save_port);
7635#endif /* not TARGET_API_MAC_CARBON */
1a578e9b
AC
7636
7637 /* retrieve window size and update application values */
e0f712ba
AC
7638#if TARGET_API_MAC_CARBON
7639 GetWindowPortBounds (w, &port_rect);
7640#else
1a578e9b 7641 port_rect = w->portRect;
e0f712ba 7642#endif
b15325b2
ST
7643 height = port_rect.bottom - port_rect.top;
7644 width = port_rect.right - port_rect.left;
7645
7646 if (width != FRAME_PIXEL_WIDTH (f)
7647 || height != FRAME_PIXEL_HEIGHT (f))
7648 {
7649 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7650 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7651
7652 change_frame_size (f, rows, columns, 0, 1, 0);
7653 SET_FRAME_GARBAGED (f);
7654 cancel_mouse_face (f);
7655
7656 FRAME_PIXEL_WIDTH (f) = width;
7657 FRAME_PIXEL_HEIGHT (f) = height;
7658 }
bf06c82f 7659 x_real_positions (f, &f->left_pos, &f->top_pos);
1a578e9b
AC
7660}
7661
b15325b2 7662#if TARGET_API_MAC_CARBON
742fbed7
AC
7663/* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
7664static OSErr
7665init_mac_drag_n_drop ()
7666{
7667 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
7668 return result;
7669}
b15325b2 7670#endif
1a578e9b
AC
7671
7672/* Intialize AppleEvent dispatcher table for the required events. */
7673void
7674init_required_apple_events ()
7675{
7676 OSErr err;
7677 long result;
7678
7679 /* Make sure we have apple events before starting. */
7680 err = Gestalt (gestaltAppleEventsAttr, &result);
7681 if (err != noErr)
7682 abort ();
7683
7684 if (!(result & (1 << gestaltAppleEventsPresent)))
7685 abort ();
177c0ea7 7686
e0f712ba 7687#if TARGET_API_MAC_CARBON
1a578e9b 7688 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
e0f712ba
AC
7689 NewAEEventHandlerUPP
7690 ((AEEventHandlerProcPtr) do_ae_open_application),
1a578e9b 7691 0L, false);
e0f712ba
AC
7692#else
7693 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7694 NewAEEventHandlerProc
7695 ((AEEventHandlerProcPtr) do_ae_open_application),
7696 0L, false);
7697#endif
1a578e9b
AC
7698 if (err != noErr)
7699 abort ();
e0f712ba
AC
7700
7701#if TARGET_API_MAC_CARBON
7702 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7703 NewAEEventHandlerUPP
7704 ((AEEventHandlerProcPtr) do_ae_open_documents),
7705 0L, false);
7706#else
1a578e9b 7707 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
e0f712ba
AC
7708 NewAEEventHandlerProc
7709 ((AEEventHandlerProcPtr) do_ae_open_documents),
1a578e9b 7710 0L, false);
e0f712ba 7711#endif
1a578e9b
AC
7712 if (err != noErr)
7713 abort ();
7714
e0f712ba
AC
7715#if TARGET_API_MAC_CARBON
7716 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7717 NewAEEventHandlerUPP
7718 ((AEEventHandlerProcPtr) do_ae_print_documents),
7719 0L, false);
7720#else
1a578e9b 7721 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
e0f712ba
AC
7722 NewAEEventHandlerProc
7723 ((AEEventHandlerProcPtr) do_ae_print_documents),
1a578e9b 7724 0L, false);
e0f712ba 7725#endif
1a578e9b
AC
7726 if (err != noErr)
7727 abort ();
7728
e0f712ba
AC
7729#if TARGET_API_MAC_CARBON
7730 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7731 NewAEEventHandlerUPP
7732 ((AEEventHandlerProcPtr) do_ae_quit_application),
7733 0L, false);
7734#else
1a578e9b 7735 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
e0f712ba
AC
7736 NewAEEventHandlerProc
7737 ((AEEventHandlerProcPtr) do_ae_quit_application),
1a578e9b 7738 0L, false);
e0f712ba 7739#endif
1a578e9b
AC
7740 if (err != noErr)
7741 abort ();
7742}
7743
742fbed7
AC
7744#if USE_CARBON_EVENTS
7745
770136ad
RS
7746void
7747init_service_handler ()
742fbed7
AC
7748{
7749 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7750 {kEventClassService, kEventServiceCopy},
7751 {kEventClassService, kEventServicePaste}};
7752 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7753 3, specs, NULL, NULL);
7754}
7755
7756/*
7757 MAC_TODO: Check to see if this is called by AEProcessDesc...
7758 */
770136ad
RS
7759OSStatus
7760mac_handle_service_event (EventHandlerCallRef callRef,
7761 EventRef event, void *data)
742fbed7 7762{
177c0ea7 7763 OSStatus err = noErr;
742fbed7
AC
7764 switch (GetEventKind (event))
7765 {
177c0ea7 7766 case kEventServiceGetTypes:
742fbed7
AC
7767 {
7768 CFMutableArrayRef copyTypes, pasteTypes;
7769 CFStringRef type;
7770 Boolean selection = true;
7771 /*
7772 GetEventParameter(event, kEventParamServicePasteTypes,
7773 typeCFMutableArrayRef, NULL,
7774 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7775 */
7776 GetEventParameter(event, kEventParamServiceCopyTypes,
7777 typeCFMutableArrayRef, NULL,
7778 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7779 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7780 if (type) {
7781 CFArrayAppendValue (copyTypes, type);
7782 //CFArrayAppendValue (pasteTypes, type);
7783 CFRelease (type);
7784 }
7785 }
7786 case kEventServiceCopy:
7787 {
7788 ScrapRef currentScrap, specificScrap;
7789 char * buf = "";
7790 Size byteCount = 0;
7791
7792 GetCurrentScrap (&currentScrap);
7793
7794 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7795 if (err == noErr)
7796 {
7797 void *buffer = xmalloc (byteCount);
7798 if (buffer != NULL)
7799 {
7800 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7801 sizeof (ScrapRef), NULL, &specificScrap);
177c0ea7 7802
742fbed7
AC
7803 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7804 &byteCount, buffer);
7805 if (err == noErr)
7806 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7807 kScrapFlavorMaskNone, byteCount, buffer);
7808 xfree (buffer);
177c0ea7 7809 }
742fbed7
AC
7810 }
7811 err = noErr;
7812 }
7813 case kEventServicePaste:
7814 {
7815 /*
7816 // Get the current location
7817 Size byteCount;
7818 ScrapRef specificScrap;
7819 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7820 sizeof(ScrapRef), NULL, &specificScrap);
7821 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7822 if (err == noErr) {
7823 void * buffer = xmalloc(byteCount);
7824 if (buffer != NULL ) {
177c0ea7 7825 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
742fbed7
AC
7826 &byteCount, buffer);
7827 if (err == noErr) {
7828 // Actually place in the buffer
7829 BLOCK_INPUT;
7830 // Get the current "selection" string here
7831 UNBLOCK_INPUT;
7832 }
7833 }
7834 xfree(buffer);
7835 }
7836 */
177c0ea7 7837 }
742fbed7
AC
7838 }
7839 return err;
7840}
b15325b2
ST
7841
7842
7843static pascal OSStatus
7844mac_handle_window_event (next_handler, event, data)
7845 EventHandlerCallRef next_handler;
7846 EventRef event;
7847 void *data;
7848{
7849 extern Lisp_Object Qcontrol;
7850
7851 WindowPtr wp;
7852 OSStatus result;
7853 UInt32 attributes;
7854 XSizeHints *size_hints;
7855
7856 GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
7857 NULL, sizeof (WindowPtr), NULL, &wp);
7858
7859 switch (GetEventKind (event))
7860 {
7861 case kEventWindowBoundsChanging:
7862 result = CallNextEventHandler (next_handler, event);
7863 if (result != eventNotHandledErr)
7864 return result;
7865
7866 GetEventParameter (event, kEventParamAttributes, typeUInt32,
7867 NULL, sizeof (UInt32), NULL, &attributes);
7868 size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
7869 if ((attributes & kWindowBoundsChangeUserResize)
7870 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
7871 == (PResizeInc | PBaseSize | PMinSize)))
7872 {
7873 Rect bounds;
7874 int width, height;
7875
7876 GetEventParameter (event, kEventParamCurrentBounds,
7877 typeQDRectangle,
7878 NULL, sizeof (Rect), NULL, &bounds);
7879 width = bounds.right - bounds.left;
7880 height = bounds.bottom - bounds.top;
7881
7882 if (width < size_hints->min_width)
7883 width = size_hints->min_width;
7884 else
7885 width = size_hints->base_width
7886 + (int) ((width - size_hints->base_width)
7887 / (float) size_hints->width_inc + .5)
7888 * size_hints->width_inc;
7889
7890 if (height < size_hints->min_height)
7891 height = size_hints->min_height;
7892 else
7893 height = size_hints->base_height
7894 + (int) ((height - size_hints->base_height)
7895 / (float) size_hints->height_inc + .5)
7896 * size_hints->height_inc;
7897
7898 bounds.right = bounds.left + width;
7899 bounds.bottom = bounds.top + height;
7900 SetEventParameter (event, kEventParamCurrentBounds,
7901 typeQDRectangle, sizeof (Rect), &bounds);
7902 return noErr;
7903 }
7904 break;
7905 }
7906
7907 return eventNotHandledErr;
7908}
7909#endif /* USE_CARBON_EVENTS */
7910
7911
7912void
7913install_window_handler (window)
7914 WindowPtr window;
7915{
7916#if USE_CARBON_EVENTS
7917 EventTypeSpec specs[] = {{kEventClassWindow, kEventWindowBoundsChanging}};
7918 static EventHandlerUPP handle_window_event_UPP = NULL;
7919
7920 if (handle_window_event_UPP == NULL)
7921 handle_window_event_UPP = NewEventHandlerUPP (mac_handle_window_event);
7922
7923 InstallWindowEventHandler (window, handle_window_event_UPP,
7924 GetEventTypeCount (specs), specs, NULL, NULL);
742fbed7 7925#endif
b15325b2
ST
7926}
7927
1a578e9b
AC
7928
7929/* Open Application Apple Event */
7930static pascal OSErr
7931do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
7932{
7933 return noErr;
7934}
7935
7936
7937/* Defined in mac.c. */
7938extern int
7939path_from_vol_dir_name (char *, int, short, long, char *);
7940
7941
7942/* Called when we receive an AppleEvent with an ID of
7943 "kAEOpenDocuments". This routine gets the direct parameter,
7944 extracts the FSSpecs in it, and puts their names on a list. */
177c0ea7 7945static pascal OSErr
1a578e9b
AC
7946do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
7947{
7948 OSErr err, err2;
7949 AEDesc the_desc;
7950 AEKeyword keyword;
7951 DescType actual_type;
7952 Size actual_size;
7953
7954 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
7955 if (err != noErr)
7956 goto descriptor_error_exit;
7957
7958 /* Check to see that we got all of the required parameters from the
7959 event descriptor. For an 'odoc' event this should just be the
7960 file list. */
177c0ea7 7961 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
1a578e9b
AC
7962 &actual_type, (Ptr) &keyword,
7963 sizeof (keyword), &actual_size);
7964 /* No error means that we found some unused parameters.
7965 errAEDescNotFound means that there are no more parameters. If we
7966 get an error code other than that, flag it. */
7967 if ((err == noErr) || (err != errAEDescNotFound))
7968 {
7969 err = errAEEventNotHandled;
7970 goto error_exit;
7971 }
7972 err = noErr;
7973
7974 /* Got all the parameters we need. Now, go through the direct
7975 object list and parse it up. */
7976 {
7977 long num_files_to_open;
7978
7979 err = AECountItems (&the_desc, &num_files_to_open);
7980 if (err == noErr)
7981 {
7982 int i;
177c0ea7 7983
1a578e9b 7984 /* AE file list is one based so just use that for indexing here. */
bc21bf11
AC
7985 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
7986 {
7987 FSSpec fs;
7988 Str255 path_name, unix_path_name;
7989#ifdef MAC_OSX
7990 FSRef fref;
7991#endif
7992
7993 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
7994 (Ptr) &fs, sizeof (fs), &actual_size);
7995 if (err != noErr) break;
7996
7997#ifdef MAC_OSX
7998 err = FSpMakeFSRef (&fs, &fref);
7999 if (err != noErr) break;
8000
8001 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
8002#else
8003 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
8004 fs.name) &&
8005 mac_to_posix_pathname (path_name, unix_path_name, 255))
8006#endif
8007 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
8008 drag_and_drop_file_list);
8009 }
1a578e9b
AC
8010 }
8011 }
8012
8013error_exit:
8014 /* Nuke the coerced file list in any case */
8015 err2 = AEDisposeDesc(&the_desc);
8016
8017descriptor_error_exit:
8018 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8019 return err;
8020}
8021
8022
b15325b2 8023#if TARGET_API_MAC_CARBON
770136ad
RS
8024static pascal OSErr
8025mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
8026 DragReference theDrag)
742fbed7
AC
8027{
8028 short items;
8029 short index;
8030 FlavorFlags theFlags;
8031 Point mouse;
8032 OSErr result;
8033 ItemReference theItem;
8034 HFSFlavor data;
8035 FSRef fref;
8036 Size size = sizeof (HFSFlavor);
8037
8038 drag_and_drop_file_list = Qnil;
8039 GetDragMouse (theDrag, &mouse, 0L);
8040 CountDragItems (theDrag, &items);
177c0ea7 8041 for (index = 1; index <= items; index++)
742fbed7
AC
8042 {
8043 /* Only handle file references. */
8044 GetDragItemReferenceNumber (theDrag, index, &theItem);
8045 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8046 if (result == noErr)
8047 {
8048#ifdef MAC_OSX
8049 FSRef frref;
8050#else
8051 Str255 path_name;
8052#endif
8053 Str255 unix_path_name;
8054 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
8055#ifdef MAC_OSX
8056 /* Use Carbon routines, otherwise it converts the file name
8057 to /Macintosh HD/..., which is not correct. */
8058 FSpMakeFSRef (&data.fileSpec, &fref);
8059 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
8060#else
8061 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
8062 data.fileSpec.parID, data.fileSpec.name) &&
8063 mac_to_posix_pathname (path_name, unix_path_name, 255))
8064#endif
8065 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
8066 drag_and_drop_file_list);
8067 }
8068 else
8069 return;
8070 }
8071 /* If there are items in the list, construct an event and post it to
8072 the queue like an interrupt using kbd_buffer_store_event. */
177c0ea7 8073 if (!NILP (drag_and_drop_file_list))
742fbed7
AC
8074 {
8075 struct input_event event;
8076 Lisp_Object frame;
50bf7673
ST
8077 struct frame *f = mac_window_to_frame (window);
8078 SetPortWindowPort (window);
742fbed7
AC
8079 GlobalToLocal (&mouse);
8080
8081 event.kind = DRAG_N_DROP_EVENT;
8082 event.code = 0;
8083 event.modifiers = 0;
8084 event.timestamp = TickCount () * (1000 / 60);
8085 XSETINT (event.x, mouse.h);
8086 XSETINT (event.y, mouse.v);
8087 XSETFRAME (frame, f);
8088 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8089 event.arg = Qnil;
8090 /* Post to the interrupt queue */
8091 kbd_buffer_store_event (&event);
8092 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8093 {
8094 ProcessSerialNumber psn;
8095 GetCurrentProcess (&psn);
8096 SetFrontProcess (&psn);
8097 }
8098 }
8099}
b15325b2 8100#endif
742fbed7
AC
8101
8102
1a578e9b
AC
8103/* Print Document Apple Event */
8104static pascal OSErr
8105do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
8106{
8107 return errAEEventNotHandled;
8108}
8109
8110
8111static pascal OSErr
8112do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
8113{
8114 /* FixMe: Do we need an unwind-protect or something here? And what
8115 do we do about unsaved files. Currently just forces quit rather
8116 than doing recursive callback to get user input. */
8117
8118 terminate_flag = true;
8119
8120 /* Fkill_emacs doesn't return. We have to return. (TI) */
8121 return noErr;
8122}
8123
8124
8125#if __profile__
8126void
8127profiler_exit_proc ()
8128{
8129 ProfilerDump ("\pEmacs.prof");
8130 ProfilerTerm ();
8131}
8132#endif
8133
8134/* These few functions implement Emacs as a normal Mac application
8c1cc9e8 8135 (almost): set up the heap and the Toolbox, handle necessary
1a578e9b
AC
8136 system events plus a few simple menu events. They also set up
8137 Emacs's access to functions defined in the rest of this file.
8138 Emacs uses function hooks to perform all its terminal I/O. A
8139 complete list of these functions appear in termhooks.h. For what
8140 they do, read the comments there and see also w32term.c and
8141 xterm.c. What's noticeably missing here is the event loop, which
8142 is normally present in most Mac application. After performing the
8143 necessary Mac initializations, main passes off control to
8144 emacs_main (corresponding to main in emacs.c). Emacs_main calls
8145 mac_read_socket (defined further below) to read input. This is
8146 where WaitNextEvent is called to process Mac events. This is also
8147 where check_alarm in sysdep.c is called to simulate alarm signals.
8148 This makes the cursor jump back to its correct position after
8149 briefly jumping to that of the matching parenthesis, print useful
8150 hints and prompts in the minibuffer after the user stops typing for
8151 a wait, etc. */
8152
e0f712ba 8153#if !TARGET_API_MAC_CARBON
1a578e9b 8154#undef main
177c0ea7 8155int
1a578e9b
AC
8156main (void)
8157{
8158#if __profile__ /* is the profiler on? */
8159 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
8160 exit(1);
8161#endif
8162
8163#if __MWERKS__
8164 /* set creator and type for files created by MSL */
8165 _fcreator = 'EMAx';
8166 _ftype = 'TEXT';
8167#endif
8168
8169 do_init_managers ();
177c0ea7 8170
1a578e9b 8171 do_get_menus ();
177c0ea7 8172
6839cd15 8173#ifndef USE_LSB_TAG
2e875e36 8174 do_check_ram_size ();
6839cd15 8175#endif
2e875e36 8176
1a578e9b
AC
8177 init_emacs_passwd_dir ();
8178
8179 init_environ ();
8180
8181 initialize_applescript ();
8182
8183 init_required_apple_events ();
177c0ea7 8184
1a578e9b
AC
8185 {
8186 char **argv;
8187 int argc = 0;
8188
8189 /* set up argv array from STR# resource */
8190 get_string_list (&argv, ARGV_STRING_LIST_ID);
8191 while (argv[argc])
8192 argc++;
8193
8194 /* free up AppleScript resources on exit */
8195 atexit (terminate_applescript);
8196
8197#if __profile__ /* is the profiler on? */
8198 atexit (profiler_exit_proc);
8199#endif
8200
8201 /* 3rd param "envp" never used in emacs_main */
8202 (void) emacs_main (argc, argv, 0);
8203 }
8204
8205 /* Never reached - real exit in Fkill_emacs */
8206 return 0;
8207}
e0f712ba 8208#endif
1a578e9b
AC
8209
8210/* Table for translating Mac keycode to X keysym values. Contributed
8211 by Sudhir Shenoy. */
8212static unsigned char keycode_to_xkeysym_table[] = {
058c18c7
AC
8213 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8214 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8215 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8216
8217 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8218 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8219 /*0x38*/ 0, 0, 0, 0,
8220 /*0x3C*/ 0, 0, 0, 0,
8221
177c0ea7 8222 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
058c18c7
AC
8223 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8224 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8225 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8226
8227 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8228 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8229 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8230 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8231
8232 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
177c0ea7
JB
8233 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8234 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
058c18c7
AC
8235 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8236
8237 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8238 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8239 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8240 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
1a578e9b
AC
8241};
8242
8243static int
8244keycode_to_xkeysym (int keyCode, int *xKeySym)
8245{
8246 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8247 return *xKeySym != 0;
8248}
8249
b15325b2
ST
8250#if !USE_CARBON_EVENTS
8251static RgnHandle mouse_region = NULL;
8252
8253Boolean
8254mac_wait_next_event (er, sleep_time, dequeue)
8255 EventRecord *er;
8256 UInt32 sleep_time;
8257 Boolean dequeue;
8258{
8259 static EventRecord er_buf = {nullEvent};
8260 UInt32 target_tick, current_tick;
8261 EventMask event_mask;
8262
8263 if (mouse_region == NULL)
8264 mouse_region = NewRgn ();
8265
8266 event_mask = everyEvent;
8267 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8268 event_mask -= highLevelEventMask;
8269
8270 current_tick = TickCount ();
8271 target_tick = current_tick + sleep_time;
8272
8273 if (er_buf.what == nullEvent)
8274 while (!WaitNextEvent (event_mask, &er_buf,
8275 target_tick - current_tick, mouse_region))
8276 {
8277 current_tick = TickCount ();
8278 if (target_tick <= current_tick)
8279 return false;
8280 }
8281
8282 *er = er_buf;
8283 if (dequeue)
8284 er_buf.what = nullEvent;
8285 return true;
8286}
8287#endif /* not USE_CARBON_EVENTS */
8288
1a578e9b
AC
8289/* Emacs calls this whenever it wants to read an input event from the
8290 user. */
8291int
50bf7673
ST
8292XTread_socket (sd, expected, hold_quit)
8293 int sd, expected;
8294 struct input_event *hold_quit;
1a578e9b 8295{
ff158530 8296 struct input_event inev;
177c0ea7 8297 int count = 0;
742fbed7 8298#if USE_CARBON_EVENTS
742fbed7 8299 EventRef eventRef;
b15325b2 8300 EventTargetRef toolbox_dispatcher;
742fbed7 8301#endif
1a578e9b 8302 EventRecord er;
50bf7673 8303 struct mac_display_info *dpyinfo = &one_mac_display_info;
1a578e9b
AC
8304
8305 if (interrupt_input_blocked)
8306 {
8307 interrupt_input_pending = 1;
8308 return -1;
8309 }
8310
8311 interrupt_input_pending = 0;
8312 BLOCK_INPUT;
8313
8314 /* So people can tell when we have read the available input. */
8315 input_signal_count++;
8316
1a578e9b
AC
8317 /* Don't poll for events to process (specifically updateEvt) if
8318 window update currently already in progress. A call to redisplay
8319 (in do_window_update) can be preempted by another call to
8320 redisplay, causing blank regions to be left on the screen and the
8321 cursor to be left at strange places. */
8322 if (handling_window_update)
8323 {
8324 UNBLOCK_INPUT;
8325 return 0;
8326 }
8327
8328 if (terminate_flag)
8329 Fkill_emacs (make_number (1));
8330
b15325b2
ST
8331#if USE_CARBON_EVENTS
8332 toolbox_dispatcher = GetEventDispatcherTarget ();
1a578e9b 8333
bf06c82f 8334 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
50bf7673 8335 kEventRemoveFromQueue, &eventRef))
b15325b2
ST
8336#else /* !USE_CARBON_EVENTS */
8337 while (mac_wait_next_event (&er, 0, true))
8338#endif /* !USE_CARBON_EVENTS */
742fbed7 8339 {
50bf7673
ST
8340 int do_help = 0;
8341 struct frame *f;
8342
50bf7673
ST
8343 /* It is necessary to set this (additional) argument slot of an
8344 event to nil because keyboard.c protects incompletely
8345 processed event from being garbage collected by placing them
8346 in the kbd_buffer_gcpro vector. */
8347 EVENT_INIT (inev);
8348 inev.kind = NO_EVENT;
8349 inev.arg = Qnil;
8350
8351#if USE_CARBON_EVENTS
742fbed7 8352 /* Handle new events */
177c0ea7
JB
8353 if (!mac_convert_event_ref (eventRef, &er))
8354 switch (GetEventClass (eventRef))
742fbed7 8355 {
e439b925 8356 case kEventClassWindow:
f94a2622 8357 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
e439b925
ST
8358 {
8359 WindowPtr window_ptr;
8360 GetEventParameter(eventRef, kEventParamDirectObject,
8361 typeWindowRef, NULL, sizeof(WindowPtr),
8362 NULL, &window_ptr);
8363 f = mac_window_to_frame (window_ptr);
8364 if (f && !f->async_iconified)
bf06c82f 8365 x_real_positions (f, &f->left_pos, &f->top_pos);
e439b925
ST
8366 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8367 }
8368 break;
742fbed7 8369 case kEventClassMouse:
177c0ea7 8370 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
742fbed7
AC
8371 {
8372 SInt32 delta;
8373 Point point;
bf06c82f 8374 WindowPtr window_ptr = front_emacs_window ();
50bf7673 8375
539e69a9
ST
8376 if (!IsValidWindowPtr (window_ptr))
8377 {
8378 SysBeep(1);
50bf7673 8379 break;
539e69a9
ST
8380 }
8381
742fbed7
AC
8382 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8383 typeSInt32, NULL, sizeof (SInt32),
8384 NULL, &delta);
8385 GetEventParameter(eventRef, kEventParamMouseLocation,
8386 typeQDPoint, NULL, sizeof (Point),
8387 NULL, &point);
ff158530
KS
8388 inev.kind = WHEEL_EVENT;
8389 inev.code = 0;
50bf7673 8390 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
ff158530
KS
8391 | ((delta < 0) ? down_modifier
8392 : up_modifier));
50bf7673 8393 SetPortWindowPort (window_ptr);
742fbed7 8394 GlobalToLocal (&point);
ff158530
KS
8395 XSETINT (inev.x, point.h);
8396 XSETINT (inev.y, point.v);
50bf7673
ST
8397 XSETFRAME (inev.frame_or_window,
8398 mac_window_to_frame (window_ptr));
ff158530 8399 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
742fbed7 8400 }
177c0ea7 8401 else
50bf7673 8402 SendEventToEventTarget (eventRef, toolbox_dispatcher);
742fbed7
AC
8403
8404 break;
b15325b2 8405
742fbed7
AC
8406 default:
8407 /* Send the event to the appropriate receiver. */
50bf7673 8408 SendEventToEventTarget (eventRef, toolbox_dispatcher);
742fbed7
AC
8409 }
8410 else
742fbed7 8411#endif /* USE_CARBON_EVENTS */
50bf7673 8412 switch (er.what)
1a578e9b 8413 {
50bf7673
ST
8414 case mouseDown:
8415 case mouseUp:
8416 {
8417 WindowPtr window_ptr;
8418 SInt16 part_code;
8419 int tool_bar_p = 0;
8420
59feca74
ST
8421#if USE_CARBON_EVENTS
8422 /* This is needed to send mouse events like aqua window
8423 buttons to the correct handler. */
8424 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8425 != eventNotHandledErr)
8426 break;
8427#endif
8428
50bf7673
ST
8429 if (dpyinfo->grabbed && last_mouse_frame
8430 && FRAME_LIVE_P (last_mouse_frame))
8431 {
8432 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8433 part_code = inContent;
8434 }
8435 else
8436 {
bf06c82f 8437 part_code = FindWindow (er.where, &window_ptr);
50bf7673
ST
8438 if (tip_window && window_ptr == tip_window)
8439 {
8440 HideWindow (tip_window);
bf06c82f 8441 part_code = FindWindow (er.where, &window_ptr);
50bf7673 8442 }
50bf7673
ST
8443 }
8444
bf06c82f
ST
8445 if (er.what != mouseDown && part_code != inContent)
8446 break;
8447
50bf7673
ST
8448 switch (part_code)
8449 {
8450 case inMenuBar:
bf06c82f
ST
8451 f = mac_window_to_frame (front_emacs_window ());
8452 saved_menu_event_location = er.where;
8453 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8454 XSETFRAME (inev.frame_or_window, f);
50bf7673 8455 break;
742fbed7 8456
50bf7673 8457 case inContent:
bf06c82f 8458 if (window_ptr != front_emacs_window ())
50bf7673
ST
8459 SelectWindow (window_ptr);
8460 else
8461 {
8462 SInt16 control_part_code;
8463 ControlHandle ch;
8464 Point mouse_loc = er.where;
8465
8466 f = mac_window_to_frame (window_ptr);
8467 /* convert to local coordinates of new window */
8468 SetPortWindowPort (window_ptr);
177c0ea7 8469
50bf7673 8470 GlobalToLocal (&mouse_loc);
e0f712ba 8471#if TARGET_API_MAC_CARBON
50bf7673
ST
8472 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8473 &control_part_code);
e0f712ba 8474#else
50bf7673
ST
8475 control_part_code = FindControl (mouse_loc, window_ptr,
8476 &ch);
e0f712ba
AC
8477#endif
8478
742fbed7 8479#if USE_CARBON_EVENTS
50bf7673
ST
8480 inev.code = mac_get_mouse_btn (eventRef);
8481 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
742fbed7 8482#else
50bf7673
ST
8483 inev.code = mac_get_emulated_btn (er.modifiers);
8484 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
742fbed7 8485#endif
50bf7673
ST
8486 XSETINT (inev.x, mouse_loc.h);
8487 XSETINT (inev.y, mouse_loc.v);
8488 inev.timestamp = er.when * (1000 / 60);
8489 /* ticks to milliseconds */
8490
8491 if (dpyinfo->grabbed && tracked_scroll_bar
8492#if TARGET_API_MAC_CARBON
8493 || ch != 0
742fbed7 8494#else
50bf7673 8495 || control_part_code != 0
742fbed7 8496#endif
50bf7673
ST
8497 )
8498 {
8499 struct scroll_bar *bar;
8500
8501 if (dpyinfo->grabbed && tracked_scroll_bar)
8502 {
8503 bar = tracked_scroll_bar;
8504 control_part_code = kControlIndicatorPart;
8505 }
8506 else
8507 bar = (struct scroll_bar *) GetControlReference (ch);
8508 x_scroll_bar_handle_click (bar, control_part_code,
8509 &er, &inev);
8510 if (er.what == mouseDown
8511 && control_part_code == kControlIndicatorPart)
8512 tracked_scroll_bar = bar;
8513 else
8514 tracked_scroll_bar = NULL;
8515 }
8516 else
8517 {
8518 Lisp_Object window;
8519 int x = mouse_loc.h;
8520 int y = mouse_loc.v;
8521
8522 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
8523 if (EQ (window, f->tool_bar_window))
8524 {
8525 if (er.what == mouseDown)
8526 handle_tool_bar_click (f, x, y, 1, 0);
8527 else
8528 handle_tool_bar_click (f, x, y, 0,
8529 inev.modifiers);
8530 tool_bar_p = 1;
8531 }
8532 else
8533 {
8534 XSETFRAME (inev.frame_or_window, f);
8535 inev.kind = MOUSE_CLICK_EVENT;
8536 }
8537 }
8538
8539 if (er.what == mouseDown)
8540 {
8541 dpyinfo->grabbed |= (1 << inev.code);
8542 last_mouse_frame = f;
8543 /* Ignore any mouse motion that happened
8544 before this event; any subsequent
8545 mouse-movement Emacs events should reflect
8546 only motion after the ButtonPress. */
8547 if (f != 0)
8548 f->mouse_moved = 0;
8549
8550 if (!tool_bar_p)
8551 last_tool_bar_item = -1;
8552 }
8553 else
8554 {
bf06c82f 8555 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
50bf7673
ST
8556 /* If a button is released though it was not
8557 previously pressed, that would be because
8558 of multi-button emulation. */
8559 dpyinfo->grabbed = 0;
8560 else
8561 dpyinfo->grabbed &= ~(1 << inev.code);
8562 }
8563
8564 switch (er.what)
8565 {
8566 case mouseDown:
8567 inev.modifiers |= down_modifier;
8568 break;
8569 case mouseUp:
8570 inev.modifiers |= up_modifier;
8571 break;
8572 }
8573 }
8574 break;
1a578e9b 8575
50bf7673
ST
8576 case inDrag:
8577#if TARGET_API_MAC_CARBON
bf06c82f 8578 DragWindow (window_ptr, er.where, NULL);
50bf7673
ST
8579#else /* not TARGET_API_MAC_CARBON */
8580 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
8581#endif /* not TARGET_API_MAC_CARBON */
e439b925
ST
8582 /* Update the frame parameters. */
8583 {
8584 struct frame *f = mac_window_to_frame (window_ptr);
bf06c82f 8585
e439b925 8586 if (f && !f->async_iconified)
bf06c82f 8587 x_real_positions (f, &f->left_pos, &f->top_pos);
e439b925 8588 }
50bf7673 8589 break;
177c0ea7 8590
50bf7673
ST
8591 case inGoAway:
8592 if (TrackGoAway (window_ptr, er.where))
8593 {
8594 inev.kind = DELETE_WINDOW_EVENT;
8595 XSETFRAME (inev.frame_or_window,
8596 mac_window_to_frame (window_ptr));
8597 }
8598 break;
1a578e9b 8599
50bf7673
ST
8600 /* window resize handling added --ben */
8601 case inGrow:
bf06c82f
ST
8602 do_grow_window (window_ptr, &er);
8603 break;
e0f712ba 8604
50bf7673
ST
8605 /* window zoom handling added --ben */
8606 case inZoomIn:
8607 case inZoomOut:
8608 if (TrackBox (window_ptr, er.where, part_code))
8609 do_zoom_window (window_ptr, part_code);
8610 break;
742fbed7 8611
50bf7673
ST
8612 default:
8613 break;
8614 }
8615 }
8616 break;
e0f712ba 8617
50bf7673 8618 case updateEvt:
e3564461 8619#if USE_CARBON_EVENTS
50bf7673
ST
8620 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8621 != eventNotHandledErr)
8622 break;
e3564461 8623#endif
50bf7673
ST
8624 do_window_update ((WindowPtr) er.message);
8625 break;
177c0ea7 8626
50bf7673 8627 case osEvt:
742fbed7 8628#if USE_CARBON_EVENTS
50bf7673
ST
8629 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8630 != eventNotHandledErr)
8631 break;
742fbed7 8632#endif
50bf7673
ST
8633 switch ((er.message >> 24) & 0x000000FF)
8634 {
8635 case suspendResumeMessage:
8636 if ((er.message & resumeFlag) == 1)
8637 do_app_resume ();
8638 else
8639 do_app_suspend ();
1a578e9b
AC
8640 break;
8641
50bf7673 8642 case mouseMovedMessage:
b15325b2
ST
8643#if !USE_CARBON_EVENTS
8644 SetRectRgn (mouse_region, er.where.h, er.where.v,
8645 er.where.h + 1, er.where.v + 1);
8646#endif
50bf7673
ST
8647 previous_help_echo_string = help_echo_string;
8648 help_echo_string = help_echo_object = help_echo_window = Qnil;
8649 help_echo_pos = -1;
ffe8b3f4 8650
50bf7673 8651 do_mouse_moved (er.where, &f);
1a578e9b 8652
50bf7673
ST
8653 /* If the contents of the global variable
8654 help_echo_string has changed, generate a
8655 HELP_EVENT. */
8656 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
8657 do_help = 1;
1a578e9b
AC
8658 break;
8659 }
50bf7673
ST
8660 break;
8661
8662 case activateEvt:
8663 {
8664 WindowPtr window_ptr = (WindowPtr) er.message;
177c0ea7 8665
742fbed7 8666#if USE_CARBON_EVENTS
50bf7673
ST
8667 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8668 != eventNotHandledErr)
8669 break;
177c0ea7 8670#endif
50bf7673
ST
8671 if (window_ptr == tip_window)
8672 {
8673 HideWindow (tip_window);
8674 break;
8675 }
177c0ea7 8676
59feca74
ST
8677 if (!is_emacs_window (window_ptr))
8678 break;
f94a2622 8679
59feca74
ST
8680 f = mac_window_to_frame (window_ptr);
8681
50bf7673
ST
8682 if ((er.modifiers & activeFlag) != 0)
8683 {
59feca74 8684 /* A window has been activated */
50bf7673 8685 Point mouse_loc = er.where;
177c0ea7 8686
59feca74
ST
8687 x_new_focus_frame (dpyinfo, f);
8688 activate_scroll_bars (f);
177c0ea7 8689
50bf7673
ST
8690 SetPortWindowPort (window_ptr);
8691 GlobalToLocal (&mouse_loc);
59feca74 8692 /* Window-activated event counts as mouse movement,
50bf7673
ST
8693 so update things that depend on mouse position. */
8694 note_mouse_movement (mac_window_to_frame (window_ptr),
8695 &mouse_loc);
8696 }
8697 else
8698 {
59feca74
ST
8699 /* A window has been deactivated */
8700 dpyinfo->grabbed = 0;
8701
8702 if (f == dpyinfo->x_focus_frame)
8703 {
8704 x_new_focus_frame (dpyinfo, 0);
8705 deactivate_scroll_bars (f);
8706 }
8707
177c0ea7 8708
50bf7673
ST
8709 if (f == dpyinfo->mouse_face_mouse_frame)
8710 {
8711 /* If we move outside the frame, then we're
8712 certainly no longer on any text in the
8713 frame. */
8714 clear_mouse_face (dpyinfo);
8715 dpyinfo->mouse_face_mouse_frame = 0;
8716 }
177c0ea7 8717
50bf7673
ST
8718 /* Generate a nil HELP_EVENT to cancel a help-echo.
8719 Do it only if there's something to cancel.
8720 Otherwise, the startup message is cleared when the
8721 mouse leaves the frame. */
8722 if (any_help_event_p)
8723 do_help = -1;
8724 }
8725 }
8726 break;
177c0ea7 8727
50bf7673
ST
8728 case keyDown:
8729 case autoKey:
1a578e9b 8730 {
50bf7673
ST
8731 int keycode = (er.message & keyCodeMask) >> 8;
8732 int xkeysym;
177c0ea7 8733
50bf7673
ST
8734#if USE_CARBON_EVENTS
8735 /* When using Carbon Events, we need to pass raw keyboard
8736 events to the TSM ourselves. If TSM handles it, it
8737 will pass back noErr, otherwise it will pass back
8738 "eventNotHandledErr" and we can process it
8739 normally. */
8740 if ((!NILP (Vmac_pass_command_to_system)
8741 || !(er.modifiers & cmdKey))
8742 && (!NILP (Vmac_pass_control_to_system)
8743 || !(er.modifiers & controlKey)))
8744 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8745 != eventNotHandledErr)
8746 break;
8747#endif
8748
8749#if TARGET_API_MAC_CARBON
bf06c82f 8750 if (!IsValidWindowPtr (front_emacs_window ()))
6ef0a87e 8751 {
50bf7673
ST
8752 SysBeep (1);
8753 break;
6ef0a87e 8754 }
50bf7673
ST
8755#endif
8756
8757 ObscureCursor ();
8758
8759 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
6ef0a87e 8760 {
50bf7673
ST
8761 clear_mouse_face (dpyinfo);
8762 dpyinfo->mouse_face_hidden = 1;
177c0ea7
JB
8763 }
8764
50bf7673 8765 if (keycode_to_xkeysym (keycode, &xkeysym))
6ef0a87e 8766 {
50bf7673
ST
8767 inev.code = 0xff00 | xkeysym;
8768 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
8769 }
8770 else
8771 {
8772 if (er.modifiers & (controlKey |
8773 (NILP (Vmac_command_key_is_meta) ? optionKey
8774 : cmdKey)))
8775 {
8776 /* This code comes from Keyboard Resource,
8777 Appendix C of IM - Text. This is necessary
8778 since shift is ignored in KCHR table
8779 translation when option or command is pressed.
8780 It also does not translate correctly
8781 control-shift chars like C-% so mask off shift
8782 here also */
8783 int new_modifiers = er.modifiers & 0xe600;
8784 /* mask off option and command */
8785 int new_keycode = keycode | new_modifiers;
8786 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8787 unsigned long some_state = 0;
8788 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8789 &some_state) & 0xff;
a36f1680
JW
8790 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
8791 {
8792 /* When using the option key as an emacs modifier, convert
8793 the pressed key code back to one without the Mac option
8794 modifier applied. */
8795 int new_modifiers = er.modifiers & ~optionKey;
8796 int new_keycode = keycode | new_modifiers;
8797 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8798 unsigned long some_state = 0;
8799 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8800 &some_state) & 0xff;
8801 }
50bf7673
ST
8802 else
8803 inev.code = er.message & charCodeMask;
8804 inev.kind = ASCII_KEYSTROKE_EVENT;
6ef0a87e 8805 }
1a578e9b 8806 }
177c0ea7 8807
50bf7673
ST
8808 /* If variable mac-convert-keyboard-input-to-latin-1 is
8809 non-nil, convert non-ASCII characters typed at the Mac
8810 keyboard (presumed to be in the Mac Roman encoding) to
8811 iso-latin-1 encoding before they are passed to Emacs.
8812 This enables the Mac keyboard to be used to enter
8813 non-ASCII iso-latin-1 characters directly. */
8814 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
8815 && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
8816 {
8817 static TECObjectRef converter = NULL;
8818 OSStatus the_err = noErr;
8819 OSStatus convert_status = noErr;
8820
8821 if (converter == NULL)
8822 {
8823 the_err = TECCreateConverter (&converter,
8824 kTextEncodingMacRoman,
8825 mac_keyboard_text_encoding);
8826 current_mac_keyboard_text_encoding
8827 = mac_keyboard_text_encoding;
8828 }
8829 else if (mac_keyboard_text_encoding
8830 != current_mac_keyboard_text_encoding)
8831 {
8832 /* Free the converter for the current encoding
8833 before creating a new one. */
8834 TECDisposeConverter (converter);
8835 the_err = TECCreateConverter (&converter,
8836 kTextEncodingMacRoman,
8837 mac_keyboard_text_encoding);
8838 current_mac_keyboard_text_encoding
8839 = mac_keyboard_text_encoding;
8840 }
8841
8842 if (the_err == noErr)
8843 {
8844 unsigned char ch = inev.code;
8845 ByteCount actual_input_length, actual_output_length;
fc7a70cc 8846 unsigned char outbuf[32];
b15325b2
ST
8847
8848 convert_status = TECConvertText (converter, &ch, 1,
8849 &actual_input_length,
fc7a70cc 8850 outbuf, 1,
b15325b2
ST
8851 &actual_output_length);
8852 if (convert_status == noErr
8853 && actual_input_length == 1
8854 && actual_output_length == 1)
fc7a70cc 8855 inev.code = *outbuf;
b15325b2 8856
fc7a70cc 8857 /* Reset internal states of the converter object.
b15325b2 8858 If it fails, create another one. */
fc7a70cc
ST
8859 convert_status = TECFlushText (converter, outbuf,
8860 sizeof (outbuf),
b15325b2 8861 &actual_output_length);
fc7a70cc
ST
8862 if (convert_status != noErr)
8863 {
8864 TECDisposeConverter (converter);
8865 TECCreateConverter (&converter,
8866 kTextEncodingMacRoman,
8867 mac_keyboard_text_encoding);
8868 }
b15325b2 8869 }
50bf7673
ST
8870 }
8871
742fbed7 8872#if USE_CARBON_EVENTS
50bf7673 8873 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
742fbed7 8874#else
50bf7673 8875 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
742fbed7 8876#endif
50bf7673 8877 XSETFRAME (inev.frame_or_window,
bf06c82f 8878 mac_window_to_frame (front_emacs_window ()));
50bf7673
ST
8879 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
8880 break;
177c0ea7 8881
50bf7673
ST
8882 case kHighLevelEvent:
8883 drag_and_drop_file_list = Qnil;
8f47302e 8884
50bf7673 8885 AEProcessAppleEvent(&er);
177c0ea7 8886
50bf7673
ST
8887 /* Build a DRAG_N_DROP_EVENT type event as is done in
8888 constuct_drag_n_drop in w32term.c. */
8889 if (!NILP (drag_and_drop_file_list))
8890 {
8891 struct frame *f = NULL;
8892 WindowPtr wp;
8893 Lisp_Object frame;
1a578e9b 8894
bf06c82f 8895 wp = front_emacs_window ();
177c0ea7 8896
50bf7673
ST
8897 if (!wp)
8898 {
8899 struct frame *f = XFRAME (XCAR (Vframe_list));
8900 CollapseWindow (FRAME_MAC_WINDOW (f), false);
bf06c82f 8901 wp = front_emacs_window ();
50bf7673 8902 }
72742a99 8903
bf06c82f 8904 if (wp)
50bf7673 8905 f = mac_window_to_frame (wp);
5883787c 8906
50bf7673
ST
8907 inev.kind = DRAG_N_DROP_EVENT;
8908 inev.code = 0;
8909 inev.timestamp = er.when * (1000 / 60);
1a578e9b 8910 /* ticks to milliseconds */
742fbed7 8911#if USE_CARBON_EVENTS
50bf7673 8912 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
742fbed7 8913#else
50bf7673 8914 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
742fbed7 8915#endif
1a578e9b 8916
50bf7673
ST
8917 XSETINT (inev.x, 0);
8918 XSETINT (inev.y, 0);
1a578e9b 8919
50bf7673
ST
8920 XSETFRAME (frame, f);
8921 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
1a578e9b 8922
50bf7673
ST
8923 /* Regardless of whether Emacs was suspended or in the
8924 foreground, ask it to redraw its entire screen.
8925 Otherwise parts of the screen can be left in an
8926 inconsistent state. */
8927 if (wp)
e0f712ba 8928#if TARGET_API_MAC_CARBON
50bf7673
ST
8929 {
8930 Rect r;
177c0ea7 8931
50bf7673
ST
8932 GetWindowPortBounds (wp, &r);
8933 InvalWindowRect (wp, &r);
8934 }
e0f712ba 8935#else /* not TARGET_API_MAC_CARBON */
50bf7673 8936 InvalRect (&(wp->portRect));
e0f712ba 8937#endif /* not TARGET_API_MAC_CARBON */
50bf7673
ST
8938 }
8939 default:
8940 break;
8941 }
742fbed7
AC
8942#if USE_CARBON_EVENTS
8943 ReleaseEvent (eventRef);
742fbed7 8944#endif
1a578e9b 8945
50bf7673
ST
8946 if (inev.kind != NO_EVENT)
8947 {
8948 kbd_buffer_store_event_hold (&inev, hold_quit);
8949 count++;
8950 }
8951
8952 if (do_help
8953 && !(hold_quit && hold_quit->kind != NO_EVENT))
8954 {
8955 Lisp_Object frame;
8956
8957 if (f)
8958 XSETFRAME (frame, f);
8959 else
8960 frame = Qnil;
8961
8962 if (do_help > 0)
8963 {
8964 any_help_event_p = 1;
8965 gen_help_event (help_echo_string, frame, help_echo_window,
8966 help_echo_object, help_echo_pos);
8967 }
8968 else
8969 {
8970 help_echo_string = Qnil;
8971 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
8972 }
8973 count++;
8974 }
8975
8976 }
8977
1a578e9b
AC
8978 /* If the focus was just given to an autoraising frame,
8979 raise it now. */
8980 /* ??? This ought to be able to handle more than one such frame. */
8981 if (pending_autoraise_frame)
8982 {
8983 x_raise_frame (pending_autoraise_frame);
8984 pending_autoraise_frame = 0;
8985 }
8986
e0f712ba 8987#if !TARGET_API_MAC_CARBON
1a578e9b 8988 check_alarm (); /* simulate the handling of a SIGALRM */
e0f712ba 8989#endif
1a578e9b 8990
ff158530 8991 UNBLOCK_INPUT;
1a578e9b
AC
8992 return count;
8993}
8994
8995
8996/* Need to override CodeWarrior's input function so no conversion is
8997 done on newlines Otherwise compiled functions in .elc files will be
8998 read incorrectly. Defined in ...:MSL C:MSL
8999 Common:Source:buffer_io.c. */
9000#ifdef __MWERKS__
9001void
9002__convert_to_newlines (unsigned char * p, size_t * n)
9003{
9004#pragma unused(p,n)
9005}
9006
9007void
9008__convert_from_newlines (unsigned char * p, size_t * n)
9009{
9010#pragma unused(p,n)
9011}
9012#endif
9013
b15325b2 9014#ifdef MAC_OS8
770136ad 9015void
50bf7673 9016make_mac_terminal_frame (struct frame *f)
1a578e9b 9017{
50bf7673 9018 Lisp_Object frame;
b15325b2 9019 Rect r;
50bf7673
ST
9020
9021 XSETFRAME (frame, f);
9022
9023 f->output_method = output_mac;
9024 f->output_data.mac = (struct mac_output *)
9025 xmalloc (sizeof (struct mac_output));
9026 bzero (f->output_data.mac, sizeof (struct mac_output));
9027
9028 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
177c0ea7 9029
50bf7673
ST
9030 FRAME_COLS (f) = 96;
9031 FRAME_LINES (f) = 4;
9032
9033 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9034 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9035
9036 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
1a578e9b
AC
9037
9038 f->output_data.mac->cursor_pixel = 0;
9039 f->output_data.mac->border_pixel = 0x00ff00;
9040 f->output_data.mac->mouse_pixel = 0xff00ff;
9041 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9042
b15325b2
ST
9043 f->output_data.mac->text_cursor = GetCursor (iBeamCursor);
9044 f->output_data.mac->nontext_cursor = &arrow_cursor;
9045 f->output_data.mac->modeline_cursor = &arrow_cursor;
9046 f->output_data.mac->hand_cursor = &arrow_cursor;
9047 f->output_data.mac->hourglass_cursor = GetCursor (watchCursor);
9048 f->output_data.mac->horizontal_drag_cursor = &arrow_cursor;
9049
f1a83aab 9050 FRAME_FONTSET (f) = -1;
1a578e9b 9051 f->output_data.mac->explicit_parent = 0;
b15325b2
ST
9052 f->left_pos = 8;
9053 f->top_pos = 32;
f1a83aab 9054 f->border_width = 0;
177c0ea7 9055
f1a83aab 9056 f->internal_border_width = 0;
1a578e9b 9057
1a578e9b
AC
9058 f->auto_raise = 1;
9059 f->auto_lower = 1;
177c0ea7 9060
f1a83aab
KS
9061 f->new_text_cols = 0;
9062 f->new_text_lines = 0;
21a3e657 9063
b15325b2
ST
9064 SetRect (&r, f->left_pos, f->top_pos,
9065 f->left_pos + FRAME_PIXEL_WIDTH (f),
9066 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9067
9068 BLOCK_INPUT;
9069
9070 if (!(FRAME_MAC_WINDOW (f) =
9071 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9072 (WindowPtr) -1, 1, (long) f->output_data.mac)))
9073 abort ();
9074 /* so that update events can find this mac_output struct */
9075 f->output_data.mac->mFP = f; /* point back to emacs frame */
9076
9077 UNBLOCK_INPUT;
e0f712ba
AC
9078
9079 x_make_gc (f);
177c0ea7 9080
e0f712ba
AC
9081 /* Need to be initialized for unshow_buffer in window.c. */
9082 selected_window = f->selected_window;
9083
1a578e9b
AC
9084 Fmodify_frame_parameters (frame,
9085 Fcons (Fcons (Qfont,
9086 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9087 Fmodify_frame_parameters (frame,
9088 Fcons (Fcons (Qforeground_color,
9089 build_string ("black")), Qnil));
9090 Fmodify_frame_parameters (frame,
9091 Fcons (Fcons (Qbackground_color,
9092 build_string ("white")), Qnil));
9093}
b15325b2 9094#endif
1a578e9b 9095
e0f712ba
AC
9096\f
9097/***********************************************************************
9098 Initialization
9099 ***********************************************************************/
9100
e0f712ba
AC
9101int mac_initialized = 0;
9102
1a578e9b
AC
9103void
9104mac_initialize_display_info ()
9105{
9106 struct mac_display_info *dpyinfo = &one_mac_display_info;
9107 GDHandle main_device_handle;
9108
9109 bzero (dpyinfo, sizeof (*dpyinfo));
9110
b15325b2 9111#ifdef MAC_OSX
e0f712ba 9112 dpyinfo->mac_id_name
d5db4077
KR
9113 = (char *) xmalloc (SCHARS (Vinvocation_name)
9114 + SCHARS (Vsystem_name)
e0f712ba
AC
9115 + 2);
9116 sprintf (dpyinfo->mac_id_name, "%s@%s",
d5db4077 9117 SDATA (Vinvocation_name), SDATA (Vsystem_name));
e0f712ba
AC
9118#else
9119 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9120 strcpy (dpyinfo->mac_id_name, "Mac Display");
9121#endif
9122
1a578e9b
AC
9123 main_device_handle = LMGetMainDevice();
9124
9125 dpyinfo->reference_count = 0;
9126 dpyinfo->resx = 75.0;
9127 dpyinfo->resy = 75.0;
e3564461 9128 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
f303762d
JD
9129#ifdef MAC_OSX
9130 /* HasDepth returns true if it is possible to have a 32 bit display,
2bac9bb1
JD
9131 but this may not be what is actually used. Mac OSX can do better.
9132 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9133 header for CGGetActiveDisplayList says that the first display returned
9134 is the active one, so we use that. */
9135 {
9136 CGDirectDisplayID disp_id[1];
9137 CGDisplayCount disp_count;
9138 CGDisplayErr error_code;
9139
9140 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
9141 if (error_code != 0)
9142 error ("No display found, CGGetActiveDisplayList error %d", error_code);
9143
9144 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
9145 }
f303762d 9146#else
e3564461
ST
9147 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9148 if (HasDepth (main_device_handle, dpyinfo->n_planes,
9149 gdDevType, dpyinfo->color_p))
9150 break;
f303762d 9151#endif
1a578e9b
AC
9152 dpyinfo->height = (**main_device_handle).gdRect.bottom;
9153 dpyinfo->width = (**main_device_handle).gdRect.right;
9154 dpyinfo->grabbed = 0;
9155 dpyinfo->root_window = NULL;
e3564461 9156 dpyinfo->image_cache = make_image_cache ();
1a578e9b
AC
9157
9158 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9159 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9160 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9161 dpyinfo->mouse_face_window = Qnil;
50bf7673
ST
9162 dpyinfo->mouse_face_overlay = Qnil;
9163 dpyinfo->mouse_face_hidden = 0;
e0f712ba
AC
9164}
9165
b15325b2
ST
9166/* Create an xrdb-style database of resources to supercede registry settings.
9167 The database is just a concatenation of C strings, finished by an additional
9168 \0. The string are submitted to some basic normalization, so
9169
9170 [ *]option[ *]:[ *]value...
9171
9172 becomes
9173
9174 option:value...
9175
9176 but any whitespace following value is not removed. */
9177
9178static char *
9179mac_make_rdb (xrm_option)
9180 char *xrm_option;
9181{
9182 char *buffer = xmalloc (strlen (xrm_option) + 2);
9183 char *current = buffer;
9184 char ch;
9185 int in_option = 1;
9186 int before_value = 0;
9187
9188 do {
9189 ch = *xrm_option++;
9190
9191 if (ch == '\n')
9192 {
9193 *current++ = '\0';
9194 in_option = 1;
9195 before_value = 0;
9196 }
9197 else if (ch != ' ')
9198 {
9199 *current++ = ch;
9200 if (in_option && (ch == ':'))
9201 {
9202 in_option = 0;
9203 before_value = 1;
9204 }
9205 else if (before_value)
9206 {
9207 before_value = 0;
9208 }
9209 }
9210 else if (!(in_option || before_value))
9211 {
9212 *current++ = ch;
9213 }
9214 } while (ch);
9215
9216 *current = '\0';
9217
9218 return buffer;
9219}
9220
e0f712ba
AC
9221struct mac_display_info *
9222mac_term_init (display_name, xrm_option, resource_name)
9223 Lisp_Object display_name;
9224 char *xrm_option;
9225 char *resource_name;
9226{
9227 struct mac_display_info *dpyinfo;
b15325b2
ST
9228
9229 BLOCK_INPUT;
e0f712ba
AC
9230
9231 if (!mac_initialized)
9232 {
9233 mac_initialize ();
9234 mac_initialized = 1;
9235 }
9236
b15325b2
ST
9237 if (x_display_list)
9238 error ("Sorry, this version can only handle one display");
9239
9240 mac_initialize_display_info ();
e0f712ba
AC
9241
9242 dpyinfo = &one_mac_display_info;
9243
b15325b2 9244 dpyinfo->xrdb = xrm_option ? mac_make_rdb (xrm_option) : NULL;
e0f712ba 9245
b15325b2
ST
9246 /* Put this display on the chain. */
9247 dpyinfo->next = x_display_list;
9248 x_display_list = dpyinfo;
9249
9250 /* Put it on x_display_name_list. */
9251 x_display_name_list = Fcons (Fcons (display_name, Qnil),
9252 x_display_name_list);
9253 dpyinfo->name_list_element = XCAR (x_display_name_list);
9254
9255 UNBLOCK_INPUT;
1a578e9b 9256
e0f712ba 9257 return dpyinfo;
1a578e9b 9258}
b15325b2
ST
9259/* Get rid of display DPYINFO, assuming all frames are already gone. */
9260
9261void
9262x_delete_display (dpyinfo)
9263 struct mac_display_info *dpyinfo;
9264{
9265 int i;
9266
9267 /* Discard this display from x_display_name_list and x_display_list.
9268 We can't use Fdelq because that can quit. */
9269 if (! NILP (x_display_name_list)
9270 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9271 x_display_name_list = XCDR (x_display_name_list);
9272 else
9273 {
9274 Lisp_Object tail;
9275
9276 tail = x_display_name_list;
9277 while (CONSP (tail) && CONSP (XCDR (tail)))
9278 {
9279 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9280 {
9281 XSETCDR (tail, XCDR (XCDR (tail)));
9282 break;
9283 }
9284 tail = XCDR (tail);
9285 }
9286 }
9287
9288 if (x_display_list == dpyinfo)
9289 x_display_list = dpyinfo->next;
9290 else
9291 {
9292 struct x_display_info *tail;
9293
9294 for (tail = x_display_list; tail; tail = tail->next)
9295 if (tail->next == dpyinfo)
9296 tail->next = tail->next->next;
9297 }
9298
9299 /* Free the font names in the font table. */
9300 for (i = 0; i < dpyinfo->n_fonts; i++)
9301 if (dpyinfo->font_table[i].name)
9302 {
9303 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9304 xfree (dpyinfo->font_table[i].full_name);
9305 xfree (dpyinfo->font_table[i].name);
9306 }
9307
9308 if (dpyinfo->font_table->font_encoder)
9309 xfree (dpyinfo->font_table->font_encoder);
9310
9311 xfree (dpyinfo->font_table);
9312 xfree (dpyinfo->mac_id_name);
9313
9314 if (x_display_list == 0)
9315 {
9316 mac_clear_font_name_table ();
9317 bzero (dpyinfo, sizeof (*dpyinfo));
9318 }
9319}
9320
e0f712ba 9321\f
8030369c 9322#ifdef MAC_OSX
6ef0a87e
ST
9323void
9324mac_check_bundle()
9325{
9326 extern int inhibit_window_system;
9327 extern int noninteractive;
9328 CFBundleRef appsBundle;
9329 pid_t child;
9330
9331 /* No need to test if already -nw*/
9332 if (inhibit_window_system || noninteractive)
9333 return;
9334
9335 appsBundle = CFBundleGetMainBundle();
9336 if (appsBundle != NULL)
9337 {
9338 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9339 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9340 /* We found the bundle identifier, now we know we are valid. */
9341 if (res != NULL)
9342 {
9343 CFRelease(res);
9344 return;
9345 }
9346 }
9347 /* MAC_TODO: Have this start the bundled executable */
9348
9349 /* For now, prevent the fatal error by bringing it up in the terminal */
9350 inhibit_window_system = 1;
9351}
9352
770136ad
RS
9353void
9354MakeMeTheFrontProcess ()
8030369c
AC
9355{
9356 ProcessSerialNumber psn;
9357 OSErr err;
177c0ea7 9358
8030369c
AC
9359 err = GetCurrentProcess (&psn);
9360 if (err == noErr)
9361 (void) SetFrontProcess (&psn);
9362}
6ef0a87e
ST
9363
9364/***** Code to handle C-g testing *****/
9365
9366/* Contains the Mac modifier formed from quit_char */
9367static mac_quit_char_modifiers = 0;
9368static mac_quit_char_keycode;
9369extern int quit_char;
9370
9371static void
9372mac_determine_quit_char_modifiers()
9373{
9374 /* Todo: Determine modifiers from quit_char. */
9375 UInt32 qc_modifiers = ctrl_modifier;
9376
9377 /* Map modifiers */
9378 mac_quit_char_modifiers = 0;
9379 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9380 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9381 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9382 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9383}
9384
9385static void
9386init_quit_char_handler ()
9387{
9388 /* TODO: Let this support keys other the 'g' */
9389 mac_quit_char_keycode = 5;
9390 /* Look at <architecture/adb_kb_map.h> for details */
9391 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
177c0ea7 9392
6ef0a87e
ST
9393 mac_determine_quit_char_modifiers();
9394}
9395
9396static Boolean
9397quit_char_comp (EventRef inEvent, void *inCompData)
9398{
9399 if (GetEventClass(inEvent) != kEventClassKeyboard)
9400 return false;
9401 if (GetEventKind(inEvent) != kEventRawKeyDown)
9402 return false;
9403 {
9404 UInt32 keyCode;
9405 UInt32 keyModifiers;
177c0ea7 9406 GetEventParameter(inEvent, kEventParamKeyCode,
6ef0a87e
ST
9407 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9408 if (keyCode != mac_quit_char_keycode)
9409 return false;
177c0ea7 9410 GetEventParameter(inEvent, kEventParamKeyModifiers,
6ef0a87e
ST
9411 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9412 if (keyModifiers != mac_quit_char_modifiers)
9413 return false;
9414 }
9415 return true;
9416}
9417
9418void
d243e605 9419mac_check_for_quit_char ()
6ef0a87e
ST
9420{
9421 EventRef event;
d243e605
AC
9422 static EMACS_TIME last_check_time = { 0, 0 };
9423 static EMACS_TIME one_second = { 1, 0 };
9424 EMACS_TIME now, t;
9425
9426 /* If windows are not initialized, return immediately (keep it bouncin'). */
6ef0a87e
ST
9427 if (!mac_quit_char_modifiers)
9428 return;
9429
d243e605
AC
9430 /* Don't check if last check is less than a second ago. */
9431 EMACS_GET_TIME (now);
9432 EMACS_SUB_TIME (t, now, last_check_time);
9433 if (EMACS_TIME_LT (t, one_second))
9434 return;
9435 last_check_time = now;
9436
6ef0a87e 9437 /* Redetermine modifiers because they are based on lisp variables */
d243e605 9438 mac_determine_quit_char_modifiers ();
6ef0a87e
ST
9439
9440 /* Fill the queue with events */
2a316a84 9441 BLOCK_INPUT;
6ef0a87e 9442 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
d243e605
AC
9443 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9444 NULL);
2a316a84 9445 UNBLOCK_INPUT;
177c0ea7 9446 if (event)
6ef0a87e
ST
9447 {
9448 struct input_event e;
50bf7673 9449
6ef0a87e 9450 /* Use an input_event to emulate what the interrupt handler does. */
c61ab2a0 9451 EVENT_INIT (e);
6ef0a87e
ST
9452 e.kind = ASCII_KEYSTROKE_EVENT;
9453 e.code = quit_char;
a433994a 9454 e.arg = Qnil;
96720f09 9455 e.modifiers = NULL;
d243e605 9456 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
bf06c82f 9457 XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
6ef0a87e 9458 /* Remove event from queue to prevent looping. */
d243e605
AC
9459 RemoveEventFromQueue (GetMainEventQueue (), event);
9460 ReleaseEvent (event);
9461 kbd_buffer_store_event (&e);
6ef0a87e
ST
9462 }
9463}
9464
8030369c
AC
9465#endif /* MAC_OSX */
9466
e0f712ba
AC
9467/* Set up use of X before we make the first connection. */
9468
88cd462d
KS
9469extern frame_parm_handler mac_frame_parm_handlers[];
9470
e0f712ba
AC
9471static struct redisplay_interface x_redisplay_interface =
9472{
88cd462d 9473 mac_frame_parm_handlers,
e0f712ba
AC
9474 x_produce_glyphs,
9475 x_write_glyphs,
9476 x_insert_glyphs,
9477 x_clear_end_of_line,
9478 x_scroll_run,
9479 x_after_update_window_line,
9480 x_update_window_begin,
9481 x_update_window_end,
f9e65eb3
KS
9482 x_cursor_to,
9483 x_flush,
fc7a70cc 9484 0, /* flush_display_optional */
f9e65eb3 9485 x_clear_window_mouse_face,
e0f712ba 9486 x_get_glyph_overhangs,
5958f265 9487 x_fix_overlapping_area,
750fc673 9488 x_draw_fringe_bitmap,
288670f5
KS
9489 0, /* define_fringe_bitmap */
9490 0, /* destroy_fringe_bitmap */
750fc673
KS
9491 mac_per_char_metric,
9492 mac_encode_char,
9493 NULL, /* mac_compute_glyph_string_overhangs */
f9e65eb3
KS
9494 x_draw_glyph_string,
9495 mac_define_frame_cursor,
9496 mac_clear_frame_area,
9497 mac_draw_window_cursor,
efcf4234 9498 mac_draw_vertical_window_border,
f9e65eb3 9499 mac_shift_glyphs_for_insert
e0f712ba 9500};
1a578e9b
AC
9501
9502void
e0f712ba 9503mac_initialize ()
1a578e9b
AC
9504{
9505 rif = &x_redisplay_interface;
9506
9507 clear_frame_hook = x_clear_frame;
9508 ins_del_lines_hook = x_ins_del_lines;
1a578e9b
AC
9509 delete_glyphs_hook = x_delete_glyphs;
9510 ring_bell_hook = XTring_bell;
9511 reset_terminal_modes_hook = XTreset_terminal_modes;
9512 set_terminal_modes_hook = XTset_terminal_modes;
9513 update_begin_hook = x_update_begin;
9514 update_end_hook = x_update_end;
9515 set_terminal_window_hook = XTset_terminal_window;
9516 read_socket_hook = XTread_socket;
9517 frame_up_to_date_hook = XTframe_up_to_date;
1a578e9b
AC
9518 mouse_position_hook = XTmouse_position;
9519 frame_rehighlight_hook = XTframe_rehighlight;
9520 frame_raise_lower_hook = XTframe_raise_lower;
9521
9522 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9523 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9524 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9525 judge_scroll_bars_hook = XTjudge_scroll_bars;
9526
e0f712ba
AC
9527 scroll_region_ok = 1; /* we'll scroll partial frames */
9528 char_ins_del_ok = 1;
9529 line_ins_del_ok = 1; /* we'll just blt 'em */
9530 fast_clear_end_of_line = 1; /* X does this well */
9531 memory_below_frame = 0; /* we don't remember what scrolls
1a578e9b
AC
9532 off the bottom */
9533 baud_rate = 19200;
9534
9535 x_noop_count = 0;
9536 last_tool_bar_item = -1;
9537 any_help_event_p = 0;
177c0ea7 9538
1a578e9b
AC
9539 /* Try to use interrupt input; if we can't, then start polling. */
9540 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9541
9542#ifdef USE_X_TOOLKIT
9543 XtToolkitInitialize ();
9544 Xt_app_con = XtCreateApplicationContext ();
9545 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
9546
9547 /* Install an asynchronous timer that processes Xt timeout events
9548 every 0.1s. This is necessary because some widget sets use
9549 timeouts internally, for example the LessTif menu bar, or the
9550 Xaw3d scroll bar. When Xt timouts aren't processed, these
9551 widgets don't behave normally. */
9552 {
9553 EMACS_TIME interval;
9554 EMACS_SET_SECS_USECS (interval, 0, 100000);
9555 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
9556 }
9557#endif
177c0ea7 9558
1a578e9b
AC
9559#if USE_TOOLKIT_SCROLL_BARS
9560 xaw3d_arrow_scroll = False;
9561 xaw3d_pick_top = True;
9562#endif
9563
9564#if 0
9565 /* Note that there is no real way portable across R3/R4 to get the
9566 original error handler. */
9567 XSetErrorHandler (x_error_handler);
9568 XSetIOErrorHandler (x_io_error_quitter);
9569
9570 /* Disable Window Change signals; they are handled by X events. */
9571#ifdef SIGWINCH
9572 signal (SIGWINCH, SIG_DFL);
9573#endif /* ! defined (SIGWINCH) */
9574
9575 signal (SIGPIPE, x_connection_signal);
9576#endif
9577
c3f4c690 9578 BLOCK_INPUT;
bc21bf11
AC
9579
9580#if TARGET_API_MAC_CARBON
9581 init_required_apple_events ();
9582
742fbed7
AC
9583 init_mac_drag_n_drop ();
9584
9585#if USE_CARBON_EVENTS
9586 init_service_handler ();
6ef0a87e
ST
9587
9588 init_quit_char_handler ();
742fbed7
AC
9589#endif
9590
bc21bf11 9591 DisableMenuCommand (NULL, kHICommandQuit);
8030369c
AC
9592
9593 if (!inhibit_window_system)
9594 MakeMeTheFrontProcess ();
bc21bf11 9595#endif
c3f4c690 9596 UNBLOCK_INPUT;
1a578e9b
AC
9597}
9598
9599
9600void
9601syms_of_macterm ()
9602{
9603#if 0
9604 staticpro (&x_error_message_string);
9605 x_error_message_string = Qnil;
9606#endif
9607
a36f1680
JW
9608 Qmodifier_value = intern ("modifier-value");
9609 Qalt = intern ("alt");
9610 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9611 Qhyper = intern ("hyper");
9612 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9613 Qsuper = intern ("super");
9614 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9615
b15325b2 9616#ifdef MAC_OSX
8c609cff 9617 Fprovide (intern ("mac-carbon"), Qnil);
b15325b2 9618#endif
8c609cff 9619
dd4497dc
ST
9620 staticpro (&Qreverse);
9621 Qreverse = intern ("reverse");
9622
1a578e9b
AC
9623 staticpro (&x_display_name_list);
9624 x_display_name_list = Qnil;
9625
9626 staticpro (&last_mouse_scroll_bar);
9627 last_mouse_scroll_bar = Qnil;
9628
9629 staticpro (&Qvendor_specific_keysyms);
9630 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9631
9632 staticpro (&last_mouse_press_frame);
9633 last_mouse_press_frame = Qnil;
9634
8f47302e
AC
9635 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
9636 staticpro (&Qmac_ready_for_drag_n_drop);
9637
e3564461
ST
9638 Qbig5 = intern ("big5");
9639 staticpro (&Qbig5);
9640
9641 Qcn_gb = intern ("cn-gb");
9642 staticpro (&Qcn_gb);
9643
9644 Qsjis = intern ("sjis");
9645 staticpro (&Qsjis);
9646
9647 Qeuc_kr = intern ("euc-kr");
9648 staticpro (&Qeuc_kr);
9649
e0f712ba
AC
9650 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
9651 doc: /* *Non-nil means autoselect window with mouse pointer. */);
9652 x_autoselect_window_p = 0;
9653
e0f712ba
AC
9654 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9655 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9656 Vx_toolkit_scroll_bars = Qt;
9657
d243e605
AC
9658 DEFVAR_BOOL ("x-use-underline-position-properties",
9659 &x_use_underline_position_properties,
9660 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9661nil means ignore them. If you encounter fonts with bogus
9662UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9663to 4.1, set this to nil. */);
9664 x_use_underline_position_properties = 0;
9665
1a578e9b
AC
9666 staticpro (&last_mouse_motion_frame);
9667 last_mouse_motion_frame = Qnil;
177c0ea7 9668
1a578e9b 9669 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
e0f712ba
AC
9670 doc: /* Non-nil means that the command key is used as the Emacs meta key.
9671Otherwise the option key is used. */);
1a578e9b
AC
9672 Vmac_command_key_is_meta = Qt;
9673
a36f1680
JW
9674 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9675 doc: /* Modifier to use for the Mac alt/option key. The value can
9676be alt, hyper, or super for the respective modifier. If the value is
9677nil then the key will act as the normal Mac option modifier. */);
9678 Vmac_option_modifier = Qnil;
9679
742fbed7
AC
9680 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
9681 doc: /* Non-nil means that the control and meta keys are reversed. This is
9682 useful for non-standard keyboard layouts. */);
9683 Vmac_reverse_ctrl_meta = Qnil;
9684
ffe8b3f4 9685 DEFVAR_LISP ("mac-emulate-three-button-mouse",
dd4497dc
ST
9686 &Vmac_emulate_three_button_mouse,
9687 doc: /* t means that when the option-key is held down while pressing the
ffe8b3f4 9688 mouse button, the click will register as mouse-2 and while the
dd4497dc
ST
9689 command-key is held down, the click will register as mouse-3.
9690 'reverse means that the the option-key will register for mouse-3
9691 and the command-key will register for mouse-2. nil means that
9692 not emulation should be done and the modifiers should be placed
9693 on the mouse-1 event. */);
9694 Vmac_emulate_three_button_mouse = Qnil;
9695
742fbed7
AC
9696#if USE_CARBON_EVENTS
9697 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
9698 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
9699the right click will be mouse-3.
9700Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
b37113a1 9701 Vmac_wheel_button_is_mouse_2 = Qt;
5883787c
AC
9702
9703 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
9704 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9705Toolbox for processing before Emacs sees it. */);
9706 Vmac_pass_command_to_system = Qt;
9707
9708 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9709 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9710Toolbox for processing before Emacs sees it. */);
9711 Vmac_pass_control_to_system = Qt;
742fbed7
AC
9712#endif
9713
1a578e9b 9714 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
e0f712ba
AC
9715 doc: /* One of the Text Encoding Base constant values defined in the
9716Basic Text Constants section of Inside Macintosh - Text Encoding
9717Conversion Manager. Its value determines the encoding characters
9718typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9719will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9720its default value, no conversion takes place. If it is set to
9721kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9722characters typed on Mac keyboard are first converted into the
9723ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9724passed to Emacs. Together with Emacs's set-keyboard-coding-system
9725command, this enables the Mac keyboard to be used to enter non-ASCII
9726characters directly. */);
1a578e9b
AC
9727 mac_keyboard_text_encoding = kTextEncodingMacRoman;
9728}
ab5796a9
MB
9729
9730/* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9731 (do not change this comment) */