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