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