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