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