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