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