summaryrefslogtreecommitdiff
path: root/src/macterm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/macterm.c')
-rw-r--r--src/macterm.c13451
1 files changed, 0 insertions, 13451 deletions
diff --git a/src/macterm.c b/src/macterm.c
deleted file mode 100644
index 4deaa91dc5e..00000000000
--- a/src/macterm.c
+++ /dev/null
@@ -1,13451 +0,0 @@
-/* Implementation of GUI terminal on the Mac OS.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
-
-/* Contributed by Andrew Choi (akochoi@mac.com). */
-
-#include <config.h>
-#include <signal.h>
-
-#include <stdio.h>
-
-#include "lisp.h"
-#include "blockinput.h"
-
-#include "macterm.h"
-
-#ifndef MAC_OSX
-#include <alloca.h>
-#endif
-
-#if !TARGET_API_MAC_CARBON
-#include <Quickdraw.h>
-#include <ToolUtils.h>
-#include <Sound.h>
-#include <Events.h>
-#include <Script.h>
-#include <Resources.h>
-#include <Fonts.h>
-#include <TextUtils.h>
-#include <LowMem.h>
-#include <Controls.h>
-#include <Windows.h>
-#include <Displays.h>
-#if defined (__MRC__) || (__MSL__ >= 0x6000)
-#include <ControlDefinitions.h>
-#endif
-
-#if __profile__
-#include <profiler.h>
-#endif
-#endif /* not TARGET_API_MAC_CARBON */
-
-#include "systty.h"
-#include "systime.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <setjmp.h>
-#include <sys/stat.h>
-
-#include "charset.h"
-#include "coding.h"
-#include "frame.h"
-#include "dispextern.h"
-#include "fontset.h"
-#include "termhooks.h"
-#include "termopts.h"
-#include "termchar.h"
-#include "disptab.h"
-#include "buffer.h"
-#include "window.h"
-#include "keyboard.h"
-#include "intervals.h"
-#include "atimer.h"
-#include "keymap.h"
-#include "character.h"
-#include "ccl.h"
-
-
-
-/* Non-nil means Emacs uses toolkit scroll bars. */
-
-Lisp_Object Vx_toolkit_scroll_bars;
-
-/* If non-zero, the text will be rendered using Core Graphics text
- rendering which may anti-alias the text. */
-int mac_use_core_graphics;
-
-
-/* Non-zero means that a HELP_EVENT has been generated since Emacs
- start. */
-
-static int any_help_event_p;
-
-/* Last window where we saw the mouse. Used by mouse-autoselect-window. */
-static Lisp_Object last_window;
-
-/* Non-zero means make use of UNDERLINE_POSITION font properties.
- (Not yet supported.) */
-int x_use_underline_position_properties;
-
-/* Non-zero means to draw the underline at the same place as the descent line. */
-
-int x_underline_at_descent_line;
-
-/* This is a chain of structures for all the X displays currently in
- use. */
-
-struct x_display_info *x_display_list;
-
-/* This is a list of cons cells, each of the form (NAME
- FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
- x_display_list and in the same order. NAME is the name of the
- frame. FONT-LIST-CACHE records previous values returned by
- x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
- equivalent, which is implemented with a Lisp object, for the
- display. */
-
-Lisp_Object x_display_name_list;
-
-/* This is display since Mac does not support multiple ones. */
-struct mac_display_info one_mac_display_info;
-
-/* Frame being updated by update_frame. This is declared in term.c.
- This is set by update_begin and looked at by all the XT functions.
- It is zero while not inside an update. In that case, the XT
- functions assume that `selected_frame' is the frame to apply to. */
-
-extern struct frame *updating_frame;
-
-/* This is a frame waiting to be auto-raised, within XTread_socket. */
-
-struct frame *pending_autoraise_frame;
-
-/* Mouse movement.
-
- Formerly, we used PointerMotionHintMask (in standard_event_mask)
- so that we would have to call XQueryPointer after each MotionNotify
- event to ask for another such event. However, this made mouse tracking
- slow, and there was a bug that made it eventually stop.
-
- Simply asking for MotionNotify all the time seems to work better.
-
- In order to avoid asking for motion events and then throwing most
- of them away or busy-polling the server for mouse positions, we ask
- the server for pointer motion hints. This means that we get only
- one event per group of mouse movements. "Groups" are delimited by
- other kinds of events (focus changes and button clicks, for
- example), or by XQueryPointer calls; when one of these happens, we
- get another MotionNotify event the next time the mouse moves. This
- is at least as efficient as getting motion events when mouse
- tracking is on, and I suspect only negligibly worse when tracking
- is off. */
-
-/* Where the mouse was last time we reported a mouse event. */
-
-static Rect last_mouse_glyph;
-static FRAME_PTR last_mouse_glyph_frame;
-
-/* The scroll bar in which the last X motion event occurred.
-
- If the last X motion event occurred in a scroll bar, we set this so
- XTmouse_position can know whether to report a scroll bar motion or
- an ordinary motion.
-
- If the last X motion event didn't occur in a scroll bar, we set
- this to Qnil, to tell XTmouse_position to return an ordinary motion
- event. */
-
-static Lisp_Object last_mouse_scroll_bar;
-
-/* This is a hack. We would really prefer that XTmouse_position would
- return the time associated with the position it returns, but there
- doesn't seem to be any way to wrest the time-stamp from the server
- along with the position query. So, we just keep track of the time
- of the last movement we received, and return that in hopes that
- it's somewhat accurate. */
-
-static Time last_mouse_movement_time;
-
-struct scroll_bar *tracked_scroll_bar = NULL;
-
-/* Incremented by XTread_socket whenever it really tries to read
- events. */
-
-#ifdef __STDC__
-static int volatile input_signal_count;
-#else
-static int input_signal_count;
-#endif
-
-extern Lisp_Object Vsystem_name;
-
-extern Lisp_Object Qeql;
-
-/* A mask of extra modifier bits to put into every keyboard char. */
-
-extern EMACS_INT extra_keyboard_modifiers;
-
-/* The keysyms to use for the various modifiers. */
-
-static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
-
-extern int inhibit_window_system;
-
-#if __MRC__ && !TARGET_API_MAC_CARBON
-QDGlobals qd; /* QuickDraw global information structure. */
-#endif
-
-#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
-
-struct mac_display_info *mac_display_info_for_display (Display *);
-static void x_update_window_end P_ ((struct window *, int, int));
-int x_catch_errors P_ ((Display *));
-void x_uncatch_errors P_ ((Display *, int));
-void x_lower_frame P_ ((struct frame *));
-void x_scroll_bar_clear P_ ((struct frame *));
-int x_had_errors_p P_ ((Display *));
-void x_wm_set_size_hint P_ ((struct frame *, long, int));
-void x_raise_frame P_ ((struct frame *));
-void x_set_window_size P_ ((struct frame *, int, int, int));
-void x_wm_set_window_state P_ ((struct frame *, int));
-void x_wm_set_icon_pixmap P_ ((struct frame *, int));
-static void mac_initialize P_ ((void));
-static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
-static int x_compute_min_glyph_bounds P_ ((struct frame *));
-static void x_update_end P_ ((struct frame *));
-static void XTframe_up_to_date P_ ((struct frame *));
-static void XTset_terminal_modes P_ ((struct terminal *));
-static void XTreset_terminal_modes P_ ((struct terminal *));
-static void x_clear_frame P_ ((struct frame *));
-static void frame_highlight P_ ((struct frame *));
-static void frame_unhighlight P_ ((struct frame *));
-static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
-static void mac_focus_changed P_ ((int, struct mac_display_info *,
- struct frame *, struct input_event *));
-static void x_detect_focus_change P_ ((struct mac_display_info *,
- const EventRecord *,
- struct input_event *));
-static void XTframe_rehighlight P_ ((struct frame *));
-static void x_frame_rehighlight P_ ((struct x_display_info *));
-static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
-static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
- enum text_cursor_kinds));
-
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
-static void x_flush P_ ((struct frame *f));
-static void x_update_begin P_ ((struct frame *));
-static void x_update_window_begin P_ ((struct window *));
-static void x_after_update_window_line P_ ((struct glyph_row *));
-static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
- enum scroll_bar_part *,
- Lisp_Object *, Lisp_Object *,
- unsigned long *));
-
-static int is_emacs_window P_ ((WindowRef));
-static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
-static void XSetFont P_ ((Display *, GC, XFontStruct *));
-static struct terminal *mac_create_terminal P_ ((struct mac_display_info *dpyinfo));
-
-
-#define GC_FORE_COLOR(gc) (&(gc)->fore_color)
-#define GC_BACK_COLOR(gc) (&(gc)->back_color)
-#define GC_FONT(gc) ((gc)->xgcv.font)
-#define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
-
-#define CG_SET_FILL_COLOR(context, color) \
- CGContextSetRGBFillColor (context, \
- RED_FROM_ULONG (color) / 255.0f, \
- GREEN_FROM_ULONG (color) / 255.0f, \
- BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
-#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
-#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
- do { \
- if (CGColorGetTypeID != NULL) \
- CGContextSetFillColorWithColor (context, cg_color); \
- else \
- CG_SET_FILL_COLOR (context, color); \
- } while (0)
-#else
-#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
- CGContextSetFillColorWithColor (context, cg_color)
-#endif
-#else
-#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
- CG_SET_FILL_COLOR (context, color)
-#endif
-#define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
- CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
- (gc)->cg_fore_color)
-#define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
- CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
- (gc)->cg_back_color)
-
-
-#define CG_SET_STROKE_COLOR(context, color) \
- CGContextSetRGBStrokeColor (context, \
- RED_FROM_ULONG (color) / 255.0f, \
- GREEN_FROM_ULONG (color) / 255.0f, \
- BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
-#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
-#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
- do { \
- if (CGColorGetTypeID != NULL) \
- CGContextSetStrokeColorWithColor (context, cg_color); \
- else \
- CG_SET_STROKE_COLOR (context, color); \
- } while (0)
-#else
-#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
- CGContextSetStrokeColorWithColor (context, cg_color)
-#endif
-#else
-#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
- CG_SET_STROKE_COLOR (context, color)
-#endif
-#define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
- CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
- (gc)->cg_fore_color)
-
-#if USE_CG_DRAWING
-#define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
-
-/* Fringe bitmaps. */
-
-static int max_fringe_bmp = 0;
-static CGImageRef *fringe_bmp = 0;
-
-CGColorSpaceRef mac_cg_color_space_rgb;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-static CGColorRef mac_cg_color_black;
-#endif
-
-static void
-init_cg_color ()
-{
- mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB ();
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- /* Don't check the availability of CGColorCreate; this symbol is
- defined even in Mac OS X 10.1. */
- if (CGColorGetTypeID != NULL)
-#endif
- {
- CGFloat rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
-
- mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
- }
-#endif
-}
-
-static CGContextRef
-mac_begin_cg_clip (f, gc)
- struct frame *f;
- GC gc;
-{
- CGContextRef context = FRAME_CG_CONTEXT (f);
-
- if (!context)
- {
- QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
- FRAME_CG_CONTEXT (f) = context;
- }
-
- CGContextSaveGState (context);
- CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
- CGContextScaleCTM (context, 1, -1);
- if (gc && gc->n_clip_rects)
- CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
-
- return context;
-}
-
-static void
-mac_end_cg_clip (f)
- struct frame *f;
-{
- CGContextRestoreGState (FRAME_CG_CONTEXT (f));
-}
-
-void
-mac_prepare_for_quickdraw (f)
- struct frame *f;
-{
- if (f == NULL)
- {
- Lisp_Object rest, frame;
- FOR_EACH_FRAME (rest, frame)
- if (FRAME_MAC_P (XFRAME (frame)))
- mac_prepare_for_quickdraw (XFRAME (frame));
- }
- else
- {
- CGContextRef context = FRAME_CG_CONTEXT (f);
-
- if (context)
- {
- CGContextSynchronize (context);
- QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
- &FRAME_CG_CONTEXT (f));
- }
- }
-}
-#endif
-
-static RgnHandle saved_port_clip_region = NULL;
-
-static void
-mac_begin_clip (f, gc)
- struct frame *f;
- GC gc;
-{
- static RgnHandle new_region = NULL;
-
- if (saved_port_clip_region == NULL)
- saved_port_clip_region = NewRgn ();
- if (new_region == NULL)
- new_region = NewRgn ();
-
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
- if (gc->n_clip_rects)
- {
- GetClip (saved_port_clip_region);
- SectRgn (saved_port_clip_region, gc->clip_region, new_region);
- SetClip (new_region);
- }
-}
-
-static void
-mac_end_clip (gc)
- GC gc;
-{
- if (gc->n_clip_rects)
- SetClip (saved_port_clip_region);
-}
-
-
-/* X display function emulation */
-
-/* Mac version of XDrawLine. */
-
-static void
-mac_draw_line (f, gc, x1, y1, x2, y2)
- struct frame *f;
- GC gc;
- int x1, y1, x2, y2;
-{
-#if USE_CG_DRAWING
- CGContextRef context;
- CGFloat gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
-
- if (y1 != y2)
- gx1 += 0.5f, gx2 += 0.5f;
- if (x1 != x2)
- gy1 += 0.5f, gy2 += 0.5f;
-
- context = mac_begin_cg_clip (f, gc);
- CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
- CGContextBeginPath (context);
- CGContextMoveToPoint (context, gx1, gy1);
- CGContextAddLineToPoint (context, gx2, gy2);
- CGContextClosePath (context);
- CGContextStrokePath (context);
- mac_end_cg_clip (f);
-#else
- if (x1 == x2)
- {
- if (y1 > y2)
- y1--;
- else if (y2 > y1)
- y2--;
- }
- else if (y1 == y2)
- {
- if (x1 > x2)
- x1--;
- else
- x2--;
- }
-
- mac_begin_clip (f, gc);
- RGBForeColor (GC_FORE_COLOR (gc));
- MoveTo (x1, y1);
- LineTo (x2, y2);
- mac_end_clip (gc);
-#endif
-}
-
-/* Mac version of XDrawLine (to Pixmap). */
-
-void
-XDrawLine (display, p, gc, x1, y1, x2, y2)
- Display *display;
- Pixmap p;
- GC gc;
- int x1, y1, x2, y2;
-{
-#if USE_MAC_IMAGE_IO
- CGContextRef context;
- XImagePtr ximg = p;
- CGColorSpaceRef color_space;
- CGImageAlphaInfo alpha_info;
- CGFloat gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
-
- if (y1 != y2)
- gx1 += 0.5f, gx2 += 0.5f;
- if (x1 != x2)
- gy1 += 0.5f, gy2 += 0.5f;
-
- if (ximg->bits_per_pixel == 32)
- {
- color_space = mac_cg_color_space_rgb;
- alpha_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
- }
- else
- {
- color_space = NULL;
- alpha_info = kCGImageAlphaOnly;
- }
- context = CGBitmapContextCreate (ximg->data, ximg->width, ximg->height, 8,
- ximg->bytes_per_line, color_space,
- alpha_info);
- if (ximg->bits_per_pixel == 32)
- CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
- else
- CGContextSetGrayStrokeColor (context, gc->xgcv.foreground / 255.0f, 1.0);
- CGContextMoveToPoint (context, gx1, gy1);
- CGContextAddLineToPoint (context, gx2, gy2);
- CGContextClosePath (context);
- CGContextStrokePath (context);
- CGContextRelease (context);
-#else
- CGrafPtr old_port;
- GDHandle old_gdh;
-
- if (x1 == x2)
- {
- if (y1 > y2)
- y1--;
- else if (y2 > y1)
- y2--;
- }
- else if (y1 == y2)
- {
- if (x1 > x2)
- x1--;
- else
- x2--;
- }
-
- GetGWorld (&old_port, &old_gdh);
- SetGWorld (p, NULL);
-
- RGBForeColor (GC_FORE_COLOR (gc));
-
- LockPixels (GetGWorldPixMap (p));
- MoveTo (x1, y1);
- LineTo (x2, y2);
- UnlockPixels (GetGWorldPixMap (p));
-
- SetGWorld (old_port, old_gdh);
-#endif
-}
-
-
-static void
-mac_erase_rectangle (f, gc, x, y, width, height)
- struct frame *f;
- GC gc;
- int x, y;
- unsigned int width, height;
-{
-#if USE_CG_DRAWING
- {
- CGContextRef context;
-
- context = mac_begin_cg_clip (f, gc);
- CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
- CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
- mac_end_cg_clip (f);
- }
-#else
- {
- Rect r;
-
- mac_begin_clip (f, gc);
- RGBBackColor (GC_BACK_COLOR (gc));
- SetRect (&r, x, y, x + width, y + height);
- EraseRect (&r);
- RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
- mac_end_clip (gc);
- }
-#endif
-}
-
-
-/* Mac version of XClearArea. */
-
-void
-mac_clear_area (f, x, y, width, height)
- struct frame *f;
- int x, y;
- unsigned int width, height;
-{
- mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
-}
-
-/* Mac version of XClearWindow. */
-
-static void
-mac_clear_window (f)
- struct frame *f;
-{
-#if USE_CG_DRAWING
- {
- CGContextRef context;
- GC gc = FRAME_NORMAL_GC (f);
-
- context = mac_begin_cg_clip (f, NULL);
- CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
- CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
- FRAME_PIXEL_HEIGHT (f)));
- mac_end_cg_clip (f);
- }
-#else /* !USE_CG_DRAWING */
- SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
- RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
-
-#if TARGET_API_MAC_CARBON
- {
- Rect r;
-
- GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
- EraseRect (&r);
- }
-#else /* not TARGET_API_MAC_CARBON */
- EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
-#endif /* not TARGET_API_MAC_CARBON */
-#endif
-}
-
-
-/* Mac replacement for XCopyArea. */
-
-#if USE_CG_DRAWING
-static void
-mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
- dest_x, dest_y, overlay_p)
- CGImageRef image;
- struct frame *f;
- GC gc;
- int src_x, src_y;
- unsigned int width, height;
- int dest_x, dest_y, overlay_p;
-{
- CGContextRef context;
- CGFloat port_height = FRAME_PIXEL_HEIGHT (f);
- CGRect dest_rect = mac_rect_make (f, dest_x, dest_y, width, height);
-
- context = mac_begin_cg_clip (f, gc);
- if (!overlay_p)
- {
- CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
- CGContextFillRect (context, dest_rect);
- }
- CGContextClipToRect (context, dest_rect);
- CGContextScaleCTM (context, 1, -1);
- CGContextTranslateCTM (context, 0, -port_height);
- if (CGImageIsMask (image))
- CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
- CGContextDrawImage (context,
- mac_rect_make (f, dest_x - src_x,
- port_height - (dest_y - src_y
- + CGImageGetHeight (image)),
- CGImageGetWidth (image),
- CGImageGetHeight (image)),
- image);
- mac_end_cg_clip (f);
-}
-
-#else /* !USE_CG_DRAWING */
-
-static void
-mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
- struct frame *f;
- GC gc;
- int x, y, width, height;
- unsigned short *bits;
- int overlay_p;
-{
- BitMap bitmap;
- Rect r;
-
- bitmap.rowBytes = sizeof(unsigned short);
- bitmap.baseAddr = (char *)bits;
- SetRect (&(bitmap.bounds), 0, 0, width, height);
-
- mac_begin_clip (f, gc);
- RGBForeColor (GC_FORE_COLOR (gc));
- RGBBackColor (GC_BACK_COLOR (gc));
- SetRect (&r, x, y, x + width, y + height);
-#if TARGET_API_MAC_CARBON
- {
- CGrafPtr port;
-
- GetPort (&port);
- LockPortBits (port);
- CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
- &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
- UnlockPortBits (port);
- }
-#else /* not TARGET_API_MAC_CARBON */
- CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
- overlay_p ? srcOr : srcCopy, 0);
-#endif /* not TARGET_API_MAC_CARBON */
- RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
- mac_end_clip (gc);
-}
-#endif /* !USE_CG_DRAWING */
-
-
-/* Mac replacement for XCreateBitmapFromBitmapData. */
-
-static void
-mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
- BitMap *bitmap;
- char *bits;
- int w, h;
-{
- static const unsigned char swap_nibble[16]
- = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
- 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
- 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
- 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
- int i, j, w1;
- char *p;
-
- w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
- bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
- bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
- bzero (bitmap->baseAddr, bitmap->rowBytes * h);
- for (i = 0; i < h; i++)
- {
- p = bitmap->baseAddr + i * bitmap->rowBytes;
- for (j = 0; j < w1; j++)
- {
- /* Bitswap XBM bytes to match how Mac does things. */
- unsigned char c = *bits++;
- *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
- | (swap_nibble[(c>>4) & 0xf]));
- }
- }
-
- SetRect (&(bitmap->bounds), 0, 0, w, h);
-}
-
-
-static void
-mac_free_bitmap (bitmap)
- BitMap *bitmap;
-{
- xfree (bitmap->baseAddr);
-}
-
-
-Pixmap
-XCreatePixmap (display, w, width, height, depth)
- Display *display;
- Window w;
- unsigned int width, height;
- unsigned int depth;
-{
-#if USE_MAC_IMAGE_IO
- XImagePtr ximg;
-
- ximg = xmalloc (sizeof (*ximg));
- ximg->width = width;
- ximg->height = height;
- ximg->bits_per_pixel = depth == 1 ? 8 : 32;
- ximg->bytes_per_line = width * (ximg->bits_per_pixel / 8);
- ximg->data = xmalloc (ximg->bytes_per_line * height);
- return ximg;
-#else
- Pixmap pixmap;
- Rect r;
- QDErr err;
-
-#ifdef MAC_OS8
- SetPortWindowPort (w);
-#endif
- SetRect (&r, 0, 0, width, height);
-#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
- if (depth == 1)
-#endif
- err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
-#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
- else
- /* CreateCGImageFromPixMaps requires ARGB format. */
- err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
-#endif
- if (err != noErr)
- return NULL;
- return pixmap;
-#endif
-}
-
-
-Pixmap
-XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
- Display *display;
- Window w;
- char *data;
- unsigned int width, height;
- unsigned long fg, bg;
- unsigned int depth;
-{
- Pixmap pixmap;
- BitMap bitmap;
-#if USE_MAC_IMAGE_IO
- CGDataProviderRef provider;
- CGImageRef image_mask;
- CGContextRef context;
-
- pixmap = XCreatePixmap (display, w, width, height, depth);
- if (pixmap == NULL)
- return NULL;
-
- mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
- provider = CGDataProviderCreateWithData (NULL, bitmap.baseAddr,
- bitmap.rowBytes * height, NULL);
- image_mask = CGImageMaskCreate (width, height, 1, 1, bitmap.rowBytes,
- provider, NULL, 0);
- CGDataProviderRelease (provider);
-
- context = CGBitmapContextCreate (pixmap->data, width, height, 8,
- pixmap->bytes_per_line,
- mac_cg_color_space_rgb,
- kCGImageAlphaNoneSkipFirst
- | kCGBitmapByteOrder32Host);
-
- CG_SET_FILL_COLOR (context, fg);
- CGContextFillRect (context, CGRectMake (0, 0, width, height));
- CG_SET_FILL_COLOR (context, bg);
- CGContextDrawImage (context, CGRectMake (0, 0, width, height), image_mask);
- CGContextRelease (context);
- CGImageRelease (image_mask);
-#else
- CGrafPtr old_port;
- GDHandle old_gdh;
- static GC gc = NULL;
-
- if (gc == NULL)
- gc = XCreateGC (display, w, 0, NULL);
-
- pixmap = XCreatePixmap (display, w, width, height, depth);
- if (pixmap == NULL)
- return NULL;
-
- GetGWorld (&old_port, &old_gdh);
- SetGWorld (pixmap, NULL);
- mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
- XSetForeground (display, gc, fg);
- XSetBackground (display, gc, bg);
- RGBForeColor (GC_FORE_COLOR (gc));
- RGBBackColor (GC_BACK_COLOR (gc));
- LockPixels (GetGWorldPixMap (pixmap));
-#if TARGET_API_MAC_CARBON
- CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
- &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
-#else /* not TARGET_API_MAC_CARBON */
- CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
- &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
-#endif /* not TARGET_API_MAC_CARBON */
- UnlockPixels (GetGWorldPixMap (pixmap));
- SetGWorld (old_port, old_gdh);
-#endif
- mac_free_bitmap (&bitmap);
-
- return pixmap;
-}
-
-
-void
-XFreePixmap (display, pixmap)
- Display *display;
- Pixmap pixmap;
-{
-#if USE_MAC_IMAGE_IO
- if (pixmap)
- {
- xfree (pixmap->data);
- xfree (pixmap);
- }
-#else
- DisposeGWorld (pixmap);
-#endif
-}
-
-
-/* Mac replacement for XFillRectangle. */
-
-static void
-mac_fill_rectangle (f, gc, x, y, width, height)
- struct frame *f;
- GC gc;
- int x, y;
- unsigned int width, height;
-{
-#if USE_CG_DRAWING
- CGContextRef context;
-
- context = mac_begin_cg_clip (f, gc);
- CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
- CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
- mac_end_cg_clip (f);
-#else
- Rect r;
-
- mac_begin_clip (f, gc);
- RGBForeColor (GC_FORE_COLOR (gc));
- SetRect (&r, x, y, x + width, y + height);
- PaintRect (&r); /* using foreground color of gc */
- mac_end_clip (gc);
-#endif
-}
-
-
-/* Mac replacement for XDrawRectangle: dest is a window. */
-
-static void
-mac_draw_rectangle (f, gc, x, y, width, height)
- struct frame *f;
- GC gc;
- int x, y;
- unsigned int width, height;
-{
-#if USE_CG_DRAWING
- CGContextRef context;
-
- context = mac_begin_cg_clip (f, gc);
- CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
- CGContextStrokeRect (context,
- CGRectMake (x + 0.5f, y + 0.5f, width, height));
- mac_end_cg_clip (f);
-#else
- Rect r;
-
- mac_begin_clip (f, gc);
- RGBForeColor (GC_FORE_COLOR (gc));
- SetRect (&r, x, y, x + width + 1, y + height + 1);
- FrameRect (&r); /* using foreground color of gc */
- mac_end_clip (gc);
-#endif
-}
-
-
-static void
-mac_invert_rectangle (f, x, y, width, height)
- struct frame *f;
- int x, y;
- unsigned int width, height;
-{
-#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
- if (CGContextSetBlendMode != NULL)
-#endif
- {
- CGContextRef context;
-
- context = mac_begin_cg_clip (f, NULL);
- CGContextSetRGBFillColor (context, 1.0f, 1.0f, 1.0f, 1.0f);
- CGContextSetBlendMode (context, kCGBlendModeDifference);
- CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
- mac_end_cg_clip (f);
- }
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
- else /* CGContextSetBlendMode == NULL */
-#endif
-#endif /* USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */
-#if !USE_CG_DRAWING || MAC_OS_X_VERSION_MAX_ALLOWED < 1040 || (MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020)
- {
- Rect r;
-
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
- SetRect (&r, x, y, x + width, y + height);
-
- InvertRect (&r);
-}
-
-
-#if USE_ATSUI
-static OSStatus
-atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
- ConstUniCharArrayPtr text;
- UniCharCount text_length;
- ATSUStyle style;
- ATSUTextLayout *text_layout;
-{
- OSStatus err;
- static ATSUTextLayout saved_text_layout = NULL;
-
- if (saved_text_layout == NULL)
- {
- static const UniCharCount lengths[] = {kATSUToTextEnd};
- static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
- static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
- static ATSLineLayoutOptions line_layout =
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
- | kATSLineUseQDRendering
-#else
- kATSLineIsDisplayOnly | kATSLineFractDisable
-#endif
- ;
- static const ATSUAttributeValuePtr values[] = {&line_layout};
-
- err = ATSUCreateTextLayoutWithTextPtr (text,
- kATSUFromTextBeginning,
- kATSUToTextEnd,
- text_length,
- 1, lengths, &style,
- &saved_text_layout);
- if (err == noErr)
- err = ATSUSetLayoutControls (saved_text_layout,
- sizeof (tags) / sizeof (tags[0]),
- tags, sizes, values);
- if (err == noErr)
- err = ATSUSetTransientFontMatching (saved_text_layout, true);
- }
- else
- {
- err = ATSUSetRunStyle (saved_text_layout, style,
- kATSUFromTextBeginning, kATSUToTextEnd);
- if (err == noErr)
- err = ATSUSetTextPointerLocation (saved_text_layout, text,
- kATSUFromTextBeginning,
- kATSUToTextEnd,
- text_length);
- }
-
- if (err == noErr)
- *text_layout = saved_text_layout;
- return err;
-}
-
-
-static void
-mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
- overstrike_p, bytes_per_char)
- struct frame *f;
- GC gc;
- int x, y;
- char *buf;
- int nchars, bg_width, overstrike_p, bytes_per_char;
-{
- OSStatus err;
- ATSUTextLayout text_layout;
-
- xassert (bytes_per_char == 2);
-
-#ifndef WORDS_BIG_ENDIAN
- {
- int i;
- UniChar *text = (UniChar *)buf;
-
- for (i = 0; i < nchars; i++)
- text[i] = EndianU16_BtoN (text[i]);
- }
-#endif
- err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
- nchars,
- GC_FONT (gc)->mac_style,
- &text_layout);
- if (err != noErr)
- return;
-#ifdef MAC_OSX
- if (!mac_use_core_graphics)
- {
-#endif
- mac_begin_clip (f, gc);
- RGBForeColor (GC_FORE_COLOR (gc));
- if (bg_width)
- {
- Rect r;
-
- SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
- x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
- RGBBackColor (GC_BACK_COLOR (gc));
- EraseRect (&r);
- RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
- }
- MoveTo (x, y);
- ATSUDrawText (text_layout,
- kATSUFromTextBeginning, kATSUToTextEnd,
- kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
- if (overstrike_p)
- {
- MoveTo (x + 1, y);
- ATSUDrawText (text_layout,
- kATSUFromTextBeginning, kATSUToTextEnd,
- kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
- }
- mac_end_clip (gc);
-#ifdef MAC_OSX
- }
- else
- {
- static CGContextRef context;
- CGFloat port_height = FRAME_PIXEL_HEIGHT (f);
- static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
- static const ByteCount sizes[] = {sizeof (CGContextRef)};
- static const ATSUAttributeValuePtr values[] = {&context};
-
-#if USE_CG_DRAWING
- context = mac_begin_cg_clip (f, gc);
-#else
- CGrafPtr port;
-
- GetPort (&port);
- QDBeginCGContext (port, &context);
- if (gc->n_clip_rects || bg_width)
- {
- CGContextTranslateCTM (context, 0, port_height);
- CGContextScaleCTM (context, 1, -1);
- if (gc->n_clip_rects)
- CGContextClipToRects (context, gc->clip_rects,
- gc->n_clip_rects);
-#endif
- if (bg_width)
- {
- CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
- CGContextFillRect (context,
- mac_rect_make (f,
- x, y - FONT_BASE (GC_FONT (gc)),
- bg_width,
- FONT_HEIGHT (GC_FONT (gc))));
- }
- CGContextScaleCTM (context, 1, -1);
- CGContextTranslateCTM (context, 0, -port_height);
-#if !USE_CG_DRAWING
- }
-#endif
- CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
- err = ATSUSetLayoutControls (text_layout,
- sizeof (tags) / sizeof (tags[0]),
- tags, sizes, values);
- if (err == noErr)
- {
- ATSUDrawText (text_layout,
- kATSUFromTextBeginning, kATSUToTextEnd,
- Long2Fix (x), Long2Fix (port_height - y));
- if (overstrike_p)
- ATSUDrawText (text_layout,
- kATSUFromTextBeginning, kATSUToTextEnd,
- Long2Fix (x + 1), Long2Fix (port_height - y));
- }
-#if USE_CG_DRAWING
- mac_end_cg_clip (f);
- context = NULL;
-#else
- CGContextSynchronize (context);
- QDEndCGContext (port, &context);
-#endif
-#if 0
- /* This doesn't work on Mac OS X 10.1. */
- ATSUClearLayoutControls (text_layout,
- sizeof (tags) / sizeof (tags[0]), tags);
-#else
- ATSUSetLayoutControls (text_layout,
- sizeof (tags) / sizeof (tags[0]),
- tags, sizes, values);
-#endif
- }
-#endif /* MAC_OSX */
-}
-#endif /* USE_ATSUI */
-
-
-static void
-mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
- overstrike_p, bytes_per_char)
- struct frame *f;
- GC gc;
- int x, y;
- char *buf;
- int nchars, bg_width, overstrike_p, bytes_per_char;
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- UInt32 savedFlags;
-#endif
-
- mac_begin_clip (f, gc);
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- if (mac_use_core_graphics)
- savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
-#endif
- RGBForeColor (GC_FORE_COLOR (gc));
-#ifdef MAC_OS8
- if (bg_width)
- {
- RGBBackColor (GC_BACK_COLOR (gc));
- TextMode (srcCopy);
- }
- else
- TextMode (srcOr);
-#else
- /* We prefer not to use srcCopy text transfer mode on Mac OS X
- because:
- - Screen is double-buffered. (In srcCopy mode, a text is drawn
- into an offscreen graphics world first. So performance gain
- cannot be expected.)
- - It lowers rendering quality.
- - Some fonts leave garbage on cursor movement. */
- if (bg_width)
- {
- Rect r;
-
- RGBBackColor (GC_BACK_COLOR (gc));
- SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
- x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
- EraseRect (&r);
- }
- TextMode (srcOr);
-#endif
- TextFont (GC_FONT (gc)->mac_fontnum);
- TextSize (GC_FONT (gc)->mac_fontsize);
- TextFace (GC_FONT (gc)->mac_fontface);
- MoveTo (x, y);
- DrawText (buf, 0, nchars * bytes_per_char);
- if (overstrike_p)
- {
- TextMode (srcOr);
- MoveTo (x + 1, y);
- DrawText (buf, 0, nchars * bytes_per_char);
- }
- if (bg_width)
- RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
- mac_end_clip (gc);
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- if (mac_use_core_graphics)
- SwapQDTextFlags(savedFlags);
-#endif
-}
-
-
-static INLINE void
-mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
- overstrike_p, bytes_per_char)
- struct frame *f;
- GC gc;
- int x, y;
- char *buf;
- int nchars, bg_width, overstrike_p, bytes_per_char;
-{
-#if USE_ATSUI
- if (GC_FONT (gc)->mac_style)
- mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
- overstrike_p, bytes_per_char);
- else
-#endif /* USE_ATSUI */
- mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
- overstrike_p, bytes_per_char);
-}
-
-
-/* Mac replacement for XDrawImageString. */
-
-static void
-mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
- struct frame *f;
- GC gc;
- int x, y;
- char *buf;
- int nchars, bg_width, overstrike_p;
-{
- mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
- overstrike_p, 1);
-}
-
-
-/* Mac replacement for XDrawImageString16. */
-
-static void
-mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
- struct frame *f;
- GC gc;
- int x, y;
- XChar2b *buf;
- int nchars, bg_width, overstrike_p;
-{
- mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
- overstrike_p, 2);
-}
-
-
-/* Mac replacement for XQueryTextExtents, but takes a character. If
- STYLE is NULL, measurement is done by QuickDraw Text routines for
- the font of the current graphics port. If CG_GLYPH is not NULL,
- *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
-
-static OSStatus
-mac_query_char_extents (style, c,
- font_ascent_return, font_descent_return,
- overall_return, cg_glyph)
-#if USE_ATSUI
- ATSUStyle style;
-#else
- void *style;
-#endif
- int c;
- int *font_ascent_return, *font_descent_return;
- XCharStruct *overall_return;
-#if USE_CG_TEXT_DRAWING
- CGGlyph *cg_glyph;
-#else
- void *cg_glyph;
-#endif
-{
- OSStatus err = noErr;
- int width;
- Rect char_bounds;
-
-#if USE_ATSUI
- if (style)
- {
- ATSUTextLayout text_layout;
- UniChar ch = c;
-
- err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
- if (err == noErr
- && (font_ascent_return || font_descent_return || overall_return))
- {
- ATSTrapezoid glyph_bounds;
-
- err = ATSUGetGlyphBounds (text_layout, 0, 0,
- kATSUFromTextBeginning, kATSUToTextEnd,
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- kATSUseFractionalOrigins,
-#else
- kATSUseDeviceOrigins,
-#endif
- 1, &glyph_bounds, NULL);
- if (err == noErr)
- {
- xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
- == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
-
- width = Fix2Long (glyph_bounds.upperRight.x
- - glyph_bounds.upperLeft.x);
- if (font_ascent_return)
- *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
- if (font_descent_return)
- *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
- }
- }
- if (err == noErr && overall_return)
- {
- err = ATSUMeasureTextImage (text_layout,
- kATSUFromTextBeginning, kATSUToTextEnd,
- 0, 0, &char_bounds);
- if (err == noErr)
- STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
-#if USE_CG_TEXT_DRAWING
- if (err == noErr && cg_glyph)
- {
- OSStatus err1;
- ATSUGlyphInfoArray glyph_info_array;
- ByteCount count = sizeof (ATSUGlyphInfoArray);
-
- err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
- kATSUToTextEnd, NULL, NULL, NULL);
- if (err1 == noErr)
- err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
- kATSUToTextEnd, &count,
- &glyph_info_array);
- if (err1 == noErr
- /* Make sure that we don't have to make layout
- adjustments. */
- && glyph_info_array.glyphs[0].deltaY == 0.0f
- && glyph_info_array.glyphs[0].idealX == 0.0f
- && glyph_info_array.glyphs[0].screenX == 0)
- {
- xassert (glyph_info_array.glyphs[0].glyphID);
- *cg_glyph = glyph_info_array.glyphs[0].glyphID;
- }
- else
- *cg_glyph = 0;
- }
-#endif
- }
- }
- else
-#endif
- {
- if (font_ascent_return || font_descent_return)
- {
- FontInfo font_info;
-
- GetFontInfo (&font_info);
- if (font_ascent_return)
- *font_ascent_return = font_info.ascent;
- if (font_descent_return)
- *font_descent_return = font_info.descent;
- }
- if (overall_return)
- {
- char ch = c;
-
- width = CharWidth (ch);
- QDTextBounds (1, &ch, &char_bounds);
- STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
- }
- }
-
- return err;
-}
-
-
-/* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
-
-static int
-mac_text_extents_16 (font_struct, string, nchars, overall_return)
- XFontStruct *font_struct;
- XChar2b *string;
- int nchars;
- XCharStruct *overall_return;
-{
- int i;
- short width = 0, lbearing = 0, rbearing = 0;
- XCharStruct *pcm;
-
- for (i = 0; i < nchars; i++)
- {
- pcm = mac_per_char_metric (font_struct, string, 0);
- if (pcm == NULL)
- width += FONT_WIDTH (font_struct);
- else
- {
- lbearing = min (lbearing, width + pcm->lbearing);
- rbearing = max (rbearing, width + pcm->rbearing);
- width += pcm->width;
- }
- string++;
- }
-
- overall_return->lbearing = lbearing;
- overall_return->rbearing = rbearing;
- overall_return->width = width;
-
- /* What's the meaning of the return value of XTextExtents16? */
-}
-
-
-#if USE_CG_TEXT_DRAWING
-static int cg_text_anti_aliasing_threshold = 8;
-
-static void
-init_cg_text_anti_aliasing_threshold ()
-{
- int threshold;
- Boolean valid_p;
-
- threshold =
- CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
- kCFPreferencesCurrentApplication,
- &valid_p);
- if (valid_p)
- cg_text_anti_aliasing_threshold = threshold;
-}
-
-static int
-mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
- struct frame *f;
- GC gc;
- int x, y;
- XChar2b *buf;
- int nchars, bg_width, overstrike_p;
-{
- CGFloat port_height, gx, gy;
- int i;
- CGContextRef context;
- CGGlyph *glyphs;
- CGSize *advances;
-
- if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
- return 0;
-
- port_height = FRAME_PIXEL_HEIGHT (f);
- gx = x;
- gy = port_height - y;
- glyphs = (CGGlyph *)buf;
- advances = alloca (sizeof (CGSize) * nchars);
- if (advances == NULL)
- return 0;
- for (i = 0; i < nchars; i++)
- {
- XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
-
- advances[i].width = pcm->width;
- advances[i].height = 0;
- glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
- buf++;
- }
-
-#if USE_CG_DRAWING
- context = mac_begin_cg_clip (f, gc);
-#else
- QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
- if (gc->n_clip_rects || bg_width)
- {
- CGContextTranslateCTM (context, 0, port_height);
- CGContextScaleCTM (context, 1, -1);
- if (gc->n_clip_rects)
- CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
-#endif
- if (bg_width)
- {
- CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
- CGContextFillRect
- (context,
- mac_rect_make (f, gx, y - FONT_BASE (GC_FONT (gc)),
- bg_width, FONT_HEIGHT (GC_FONT (gc))));
- }
- CGContextScaleCTM (context, 1, -1);
- CGContextTranslateCTM (context, 0, -port_height);
-#if !USE_CG_DRAWING
- }
-#endif
- CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
- CGContextSetFont (context, GC_FONT (gc)->cg_font);
- CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
- if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
- CGContextSetShouldAntialias (context, false);
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- if (CGContextShowGlyphsWithAdvances != NULL)
-#endif
- {
- CGContextSetTextPosition (context, gx, gy);
- CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
- if (overstrike_p)
- {
- CGContextSetTextPosition (context, gx + 1.0f, gy);
- CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
- }
- }
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- else /* CGContextShowGlyphsWithAdvances == NULL */
-#endif
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- {
- for (i = 0; i < nchars; i++)
- {
- CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
- if (overstrike_p)
- CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
- gx += advances[i].width;
- }
- }
-#endif
-#if USE_CG_DRAWING
- mac_end_cg_clip (f);
-#else
- CGContextSynchronize (context);
- QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
-#endif
-
- return 1;
-}
-#endif
-
-
-#if !USE_CG_DRAWING
-/* Mac replacement for XCopyArea: dest must be window. */
-
-static void
-mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
- Pixmap src;
- struct frame *f;
- GC gc;
- int src_x, src_y;
- unsigned int width, height;
- int dest_x, dest_y;
-{
- Rect src_r, dest_r;
-
- mac_begin_clip (f, gc);
-
- SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
- SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
- ForeColor (blackColor);
- BackColor (whiteColor);
-
- LockPixels (GetGWorldPixMap (src));
-#if TARGET_API_MAC_CARBON
- {
- CGrafPtr port;
-
- GetPort (&port);
- LockPortBits (port);
- CopyBits (GetPortBitMapForCopyBits (src),
- GetPortBitMapForCopyBits (port),
- &src_r, &dest_r, srcCopy, 0);
- UnlockPortBits (port);
- }
-#else /* not TARGET_API_MAC_CARBON */
- CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
- &src_r, &dest_r, srcCopy, 0);
-#endif /* not TARGET_API_MAC_CARBON */
- UnlockPixels (GetGWorldPixMap (src));
-
- RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
-
- mac_end_clip (gc);
-}
-
-
-static void
-mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
- width, height, dest_x, dest_y)
- Pixmap src, mask;
- struct frame *f;
- GC gc;
- int src_x, src_y;
- unsigned int width, height;
- int dest_x, dest_y;
-{
- Rect src_r, dest_r;
-
- mac_begin_clip (f, gc);
-
- SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
- SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
- ForeColor (blackColor);
- BackColor (whiteColor);
-
- LockPixels (GetGWorldPixMap (src));
- LockPixels (GetGWorldPixMap (mask));
-#if TARGET_API_MAC_CARBON
- {
- CGrafPtr port;
-
- GetPort (&port);
- LockPortBits (port);
- CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
- GetPortBitMapForCopyBits (port),
- &src_r, &src_r, &dest_r);
- UnlockPortBits (port);
- }
-#else /* not TARGET_API_MAC_CARBON */
- CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
- &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
-#endif /* not TARGET_API_MAC_CARBON */
- UnlockPixels (GetGWorldPixMap (mask));
- UnlockPixels (GetGWorldPixMap (src));
-
- RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
-
- mac_end_clip (gc);
-}
-#endif /* !USE_CG_DRAWING */
-
-
-/* Mac replacement for XCopyArea: used only for scrolling. */
-
-static void
-mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
- struct frame *f;
- GC gc;
- int src_x, src_y;
- unsigned int width, height;
- int dest_x, dest_y;
-{
-#if TARGET_API_MAC_CARBON
- Rect src_r;
- RgnHandle dummy = NewRgn (); /* For avoiding update events. */
-
- SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- ScrollWindowRect (FRAME_MAC_WINDOW (f),
- &src_r, dest_x - src_x, dest_y - src_y,
- kScrollWindowNoOptions, dummy);
- DisposeRgn (dummy);
-#else /* not TARGET_API_MAC_CARBON */
- Rect src_r, dest_r;
- WindowRef w = FRAME_MAC_WINDOW (f);
-
- mac_begin_clip (f, gc);
-
- SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
- SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
- /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
- color mapping in CopyBits. Otherwise, it will be slow. */
- ForeColor (blackColor);
- BackColor (whiteColor);
- CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
-
- RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
-
- mac_end_clip (gc);
-#endif /* not TARGET_API_MAC_CARBON */
-}
-
-
-/* Mac replacement for XChangeGC. */
-
-static void
-XChangeGC (display, gc, mask, xgcv)
- Display *display;
- GC gc;
- unsigned long mask;
- XGCValues *xgcv;
-{
- if (mask & GCForeground)
- XSetForeground (display, gc, xgcv->foreground);
- if (mask & GCBackground)
- XSetBackground (display, gc, xgcv->background);
- if (mask & GCFont)
- XSetFont (display, gc, xgcv->font);
-}
-
-
-/* Mac replacement for XCreateGC. */
-
-GC
-XCreateGC (display, d, mask, xgcv)
- Display *display;
- void *d;
- unsigned long mask;
- XGCValues *xgcv;
-{
- GC gc = xmalloc (sizeof (*gc));
-
- bzero (gc, sizeof (*gc));
-#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- if (CGColorGetTypeID != NULL)
-#endif
- {
- gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
- CGColorRetain (gc->cg_fore_color);
- CGColorRetain (gc->cg_back_color);
- }
-#endif
- XChangeGC (display, gc, mask, xgcv);
-
- return gc;
-}
-
-
-/* Used in xfaces.c. */
-
-void
-XFreeGC (display, gc)
- Display *display;
- GC gc;
-{
- if (gc->clip_region)
- DisposeRgn (gc->clip_region);
-#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- if (CGColorGetTypeID != NULL)
-#endif
- {
- CGColorRelease (gc->cg_fore_color);
- CGColorRelease (gc->cg_back_color);
- }
-#endif
- xfree (gc);
-}
-
-
-/* Mac replacement for XGetGCValues. */
-
-static void
-XGetGCValues (display, gc, mask, xgcv)
- Display *display;
- GC gc;
- unsigned long mask;
- XGCValues *xgcv;
-{
- if (mask & GCForeground)
- xgcv->foreground = gc->xgcv.foreground;
- if (mask & GCBackground)
- xgcv->background = gc->xgcv.background;
- if (mask & GCFont)
- xgcv->font = gc->xgcv.font;
-}
-
-
-/* Mac replacement for XSetForeground. */
-
-void
-XSetForeground (display, gc, color)
- Display *display;
- GC gc;
- unsigned long color;
-{
- if (gc->xgcv.foreground != color)
- {
- gc->xgcv.foreground = color;
- gc->fore_color.red = RED16_FROM_ULONG (color);
- gc->fore_color.green = GREEN16_FROM_ULONG (color);
- gc->fore_color.blue = BLUE16_FROM_ULONG (color);
-#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- if (CGColorGetTypeID != NULL)
-#endif
- {
- CGColorRelease (gc->cg_fore_color);
- if (color == 0)
- {
- gc->cg_fore_color = mac_cg_color_black;
- CGColorRetain (gc->cg_fore_color);
- }
- else
- {
- CGFloat rgba[4];
-
- rgba[0] = gc->fore_color.red / 65535.0f;
- rgba[1] = gc->fore_color.green / 65535.0f;
- rgba[2] = gc->fore_color.blue / 65535.0f;
- rgba[3] = 1.0f;
- gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
- }
- }
-#endif
- }
-}
-
-
-/* Mac replacement for XSetBackground. */
-
-void
-XSetBackground (display, gc, color)
- Display *display;
- GC gc;
- unsigned long color;
-{
- if (gc->xgcv.background != color)
- {
- gc->xgcv.background = color;
- gc->back_color.red = RED16_FROM_ULONG (color);
- gc->back_color.green = GREEN16_FROM_ULONG (color);
- gc->back_color.blue = BLUE16_FROM_ULONG (color);
-#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- if (CGColorGetTypeID != NULL)
-#endif
- {
- CGColorRelease (gc->cg_back_color);
- if (color == 0)
- {
- gc->cg_back_color = mac_cg_color_black;
- CGColorRetain (gc->cg_back_color);
- }
- else
- {
- CGFloat rgba[4];
-
- rgba[0] = gc->back_color.red / 65535.0f;
- rgba[1] = gc->back_color.green / 65535.0f;
- rgba[2] = gc->back_color.blue / 65535.0f;
- rgba[3] = 1.0f;
- gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
- }
- }
-#endif
- }
-}
-
-
-/* Mac replacement for XSetFont. */
-
-static void
-XSetFont (display, gc, font)
- Display *display;
- GC gc;
- XFontStruct *font;
-{
- gc->xgcv.font = font;
-}
-
-
-/* Mac replacement for XSetClipRectangles. */
-
-static void
-mac_set_clip_rectangles (f, gc, rectangles, n)
- struct frame *f;
- GC gc;
- Rect *rectangles;
- int n;
-{
- int i;
-
- xassert (n >= 0 && n <= MAX_CLIP_RECTS);
-
- gc->n_clip_rects = n;
- if (n > 0)
- {
- if (gc->clip_region == NULL)
- gc->clip_region = NewRgn ();
- RectRgn (gc->clip_region, rectangles);
- if (n > 1)
- {
- RgnHandle region = NewRgn ();
-
- for (i = 1; i < n; i++)
- {
- RectRgn (region, rectangles + i);
- UnionRgn (gc->clip_region, region, gc->clip_region);
- }
- DisposeRgn (region);
- }
- }
-#if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
- for (i = 0; i < n; i++)
- {
- Rect *rect = rectangles + i;
-
- gc->clip_rects[i] = mac_rect_make (f, rect->left, rect->top,
- rect->right - rect->left,
- rect->bottom - rect->top);
- }
-#endif
-}
-
-
-/* Mac replacement for XSetClipMask. */
-
-static INLINE void
-mac_reset_clip_rectangles (f, gc)
- struct frame *f;
- GC gc;
-{
- gc->n_clip_rects = 0;
-}
-
-
-/* Mac replacement for XSetWindowBackground. */
-
-void
-XSetWindowBackground (display, w, color)
- Display *display;
- WindowRef w;
- unsigned long color;
-{
-#if !TARGET_API_MAC_CARBON
- AuxWinHandle aw_handle;
- CTabHandle ctab_handle;
- ColorSpecPtr ct_table;
- short ct_size;
-#endif
- RGBColor bg_color;
-
- bg_color.red = RED16_FROM_ULONG (color);
- bg_color.green = GREEN16_FROM_ULONG (color);
- bg_color.blue = BLUE16_FROM_ULONG (color);
-
-#if TARGET_API_MAC_CARBON
- SetWindowContentColor (w, &bg_color);
-#else
- if (GetAuxWin (w, &aw_handle))
- {
- ctab_handle = (*aw_handle)->awCTable;
- HandToHand ((Handle *) &ctab_handle);
- ct_table = (*ctab_handle)->ctTable;
- ct_size = (*ctab_handle)->ctSize;
- while (ct_size > -1)
- {
- if (ct_table->value == 0)
- {
- ct_table->rgb = bg_color;
- CTabChanged (ctab_handle);
- SetWinColor (w, (WCTabHandle) ctab_handle);
- }
- ct_size--;
- }
- }
-#endif
-}
-
-/* Flush display of frame F, or of all frames if F is null. */
-
-static void
-x_flush (f)
- struct frame *f;
-{
-#if TARGET_API_MAC_CARBON
- BLOCK_INPUT;
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- if (f)
- QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
- else
- QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
- UNBLOCK_INPUT;
-#endif
-}
-
-
-/* Remove calls to XFlush by defining XFlush to an empty replacement.
- Calls to XFlush should be unnecessary because the X output buffer
- is flushed automatically as needed by calls to XPending,
- XNextEvent, or XWindowEvent according to the XFlush man page.
- XTread_socket calls XPending. Removing XFlush improves
- performance. */
-
-#define XFlush(DISPLAY) (void) 0
-
-#if USE_CG_DRAWING
-static void
-mac_flush_display_optional (f)
- struct frame *f;
-{
- BLOCK_INPUT;
- mac_prepare_for_quickdraw (f);
- UNBLOCK_INPUT;
-}
-#endif
-
-/***********************************************************************
- Starting and ending an update
- ***********************************************************************/
-
-/* Start an update of frame F. This function is installed as a hook
- for update_begin, i.e. it is called when update_begin is called.
- This function is called prior to calls to x_update_window_begin for
- each window being updated. */
-
-static void
-x_update_begin (f)
- struct frame *f;
-{
-#if TARGET_API_MAC_CARBON
- /* During update of a frame, availability of input events is
- periodically checked with ReceiveNextEvent if
- redisplay-dont-pause is nil. That normally flushes window buffer
- changes for every check, and thus screen update looks waving even
- if no input is available. So we disable screen updates during
- update of a frame. */
- BLOCK_INPUT;
- DisableScreenUpdates ();
- UNBLOCK_INPUT;
-#endif
-}
-
-
-/* Start update of window W. Set the global variable updated_window
- to the window being updated and set output_cursor to the cursor
- position of W. */
-
-static void
-x_update_window_begin (w)
- struct window *w;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
-
- updated_window = w;
- set_output_cursor (&w->cursor);
-
- BLOCK_INPUT;
-
- if (f == display_info->mouse_face_mouse_frame)
- {
- /* Don't do highlighting for mouse motion during the update. */
- display_info->mouse_face_defer = 1;
-
- /* If F needs to be redrawn, simply forget about any prior mouse
- highlighting. */
- if (FRAME_GARBAGED_P (f))
- display_info->mouse_face_window = Qnil;
-
-#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
- their mouse_face_p flag set, which means that they are always
- unequal to rows in a desired matrix which never have that
- flag set. So, rows containing mouse-face glyphs are never
- scrolled, and we don't have to switch the mouse highlight off
- here to prevent it from being scrolled. */
-
- /* Can we tell that this update does not affect the window
- where the mouse highlight is? If so, no need to turn off.
- Likewise, don't do anything if the frame is garbaged;
- in that case, the frame's current matrix that we would use
- is all wrong, and we will redisplay that line anyway. */
- if (!NILP (display_info->mouse_face_window)
- && w == XWINDOW (display_info->mouse_face_window))
- {
- int i;
-
- for (i = 0; i < w->desired_matrix->nrows; ++i)
- if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
- break;
-
- if (i < w->desired_matrix->nrows)
- clear_mouse_face (display_info);
- }
-#endif /* 0 */
- }
-
- UNBLOCK_INPUT;
-}
-
-
-/* Draw a vertical window border from (x,y0) to (x,y1) */
-
-static void
-mac_draw_vertical_window_border (w, x, y0, y1)
- struct window *w;
- int x, y0, y1;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- struct face *face;
-
- face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
- if (face)
- XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
- face->foreground);
-
- mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
-}
-
-/* End update of window W (which is equal to updated_window).
-
- Draw vertical borders between horizontally adjacent windows, and
- display W's cursor if CURSOR_ON_P is non-zero.
-
- MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
- glyphs in mouse-face were overwritten. In that case we have to
- make sure that the mouse-highlight is properly redrawn.
-
- W may be a menu bar pseudo-window in case we don't have X toolkit
- support. Such windows don't have a cursor, so don't display it
- here. */
-
-static void
-x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
- struct window *w;
- int cursor_on_p, mouse_face_overwritten_p;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
-
- if (!w->pseudo_window_p)
- {
- BLOCK_INPUT;
-
- if (cursor_on_p)
- display_and_set_cursor (w, 1, output_cursor.hpos,
- output_cursor.vpos,
- output_cursor.x, output_cursor.y);
-
- if (draw_window_fringes (w, 1))
- x_draw_vertical_border (w);
-
- UNBLOCK_INPUT;
- }
-
- /* If a row with mouse-face was overwritten, arrange for
- XTframe_up_to_date to redisplay the mouse highlight. */
- if (mouse_face_overwritten_p)
- {
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- }
-
- updated_window = NULL;
-}
-
-
-/* End update of frame F. This function is installed as a hook in
- update_end. */
-
-static void
-x_update_end (f)
- struct frame *f;
-{
- /* Mouse highlight may be displayed again. */
- FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
-
- BLOCK_INPUT;
-#if TARGET_API_MAC_CARBON
- EnableScreenUpdates ();
-#endif
- XFlush (FRAME_MAC_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-
-
-/* This function is called from various places in xdisp.c whenever a
- complete update has been performed. The global variable
- updated_window is not available here. */
-
-static void
-XTframe_up_to_date (f)
- struct frame *f;
-{
- if (FRAME_MAC_P (f))
- {
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- if (dpyinfo->mouse_face_deferred_gc
- || f == dpyinfo->mouse_face_mouse_frame)
- {
- BLOCK_INPUT;
- if (dpyinfo->mouse_face_mouse_frame)
- note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
- dpyinfo->mouse_face_mouse_x,
- dpyinfo->mouse_face_mouse_y);
- dpyinfo->mouse_face_deferred_gc = 0;
- UNBLOCK_INPUT;
- }
- }
-}
-
-
-/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
- arrow bitmaps, or clear the fringes if no bitmaps are required
- before DESIRED_ROW is made current. The window being updated is
- found in updated_window. This function is called from
- update_window_line only if it is known that there are differences
- between bitmaps to be drawn between current row and DESIRED_ROW. */
-
-static void
-x_after_update_window_line (desired_row)
- struct glyph_row *desired_row;
-{
- struct window *w = updated_window;
- struct frame *f;
- int width, height;
-
- xassert (w);
-
- if (!desired_row->mode_line_p && !w->pseudo_window_p)
- desired_row->redraw_fringe_bitmaps_p = 1;
-
- /* When a window has disappeared, make sure that no rest of
- full-width rows stays visible in the internal border. Could
- check here if updated_window is the leftmost/rightmost window,
- but I guess it's not worth doing since vertically split windows
- are almost never used, internal border is rarely set, and the
- overhead is very small. */
- if (windows_or_buffers_changed
- && desired_row->full_width_p
- && (f = XFRAME (w->frame),
- width = FRAME_INTERNAL_BORDER_WIDTH (f),
- width != 0)
- && (height = desired_row->visible_height,
- height > 0))
- {
- int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
-
- /* Internal border is drawn below the tool bar. */
- if (WINDOWP (f->tool_bar_window)
- && w == XWINDOW (f->tool_bar_window))
- y -= width;
-
- BLOCK_INPUT;
- mac_clear_area (f, 0, y, width, height);
- mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
- UNBLOCK_INPUT;
- }
-}
-
-
-/* Draw the bitmap WHICH in one of the left or right fringes of
- window W. ROW is the glyph row for which to display the bitmap; it
- determines the vertical position at which the bitmap has to be
- drawn. */
-
-static void
-x_draw_fringe_bitmap (w, row, p)
- struct window *w;
- struct glyph_row *row;
- struct draw_fringe_bitmap_params *p;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- Display *display = FRAME_MAC_DISPLAY (f);
- struct face *face = p->face;
- int rowY;
- int overlay_p = p->overlay_p;
-
-#ifdef MAC_OSX
- if (!overlay_p)
- {
- int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
-
-#if 0 /* MAC_TODO: stipple */
- /* In case the same realized face is used for fringes and
- for something displayed in the text (e.g. face `region' on
- mono-displays, the fill style may have been changed to
- FillSolid in x_draw_glyph_string_background. */
- if (face->stipple)
- XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
- else
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
-#endif
-
- /* If the fringe is adjacent to the left (right) scroll bar of a
- leftmost (rightmost, respectively) window, then extend its
- background to the gap between the fringe and the bar. */
- if ((WINDOW_LEFTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
- || (WINDOW_RIGHTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
- {
- int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
- if (sb_width > 0)
- {
- int left = WINDOW_SCROLL_BAR_AREA_X (w);
- int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
- * FRAME_COLUMN_WIDTH (f));
-
- if (bx < 0
- && (left + width == p->x
- || p->x + p->wd == left))
- {
- /* Bitmap fills the fringe and we need background
- extension. */
- int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
-
- bx = p->x;
- nx = p->wd;
- by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
- row->y));
- ny = row->visible_height;
- }
-
- if (bx >= 0)
- {
- if (left + width == bx)
- {
- bx = left + sb_width;
- nx += width - sb_width;
- }
- else if (bx + nx == left)
- nx += width - sb_width;
- }
- }
- }
-
- if (bx >= 0)
- {
- mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
- /* The fringe background has already been filled. */
- overlay_p = 1;
- }
-
-#if 0 /* MAC_TODO: stipple */
- if (!face->stipple)
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
-#endif
- }
-#endif /* MAC_OSX */
-
- /* Must clip because of partially visible lines. */
- rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
- if (p->y < rowY)
- {
- /* Adjust position of "bottom aligned" bitmap on partially
- visible last row. */
- int oldY = row->y;
- int oldVH = row->visible_height;
- row->visible_height = p->h;
- row->y -= rowY - p->y;
- x_clip_to_row (w, row, -1, face->gc);
- row->y = oldY;
- row->visible_height = oldVH;
- }
- else
- x_clip_to_row (w, row, -1, face->gc);
-
-#ifndef MAC_OSX
- if (p->bx >= 0 && !p->overlay_p)
- {
-#if 0 /* MAC_TODO: stipple */
- /* In case the same realized face is used for fringes and
- for something displayed in the text (e.g. face `region' on
- mono-displays, the fill style may have been changed to
- FillSolid in x_draw_glyph_string_background. */
- if (face->stipple)
- XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
- else
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
-#endif
-
- mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
-
-#if 0 /* MAC_TODO: stipple */
- if (!face->stipple)
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
-#endif
- }
-#endif /* !MAC_OSX */
-
- if (p->which
-#if USE_CG_DRAWING
- && p->which < max_fringe_bmp
-#endif
- )
- {
- XGCValues gcv;
-
- XGetGCValues (display, face->gc, GCForeground, &gcv);
- XSetForeground (display, face->gc,
- (p->cursor_p
- ? (p->overlay_p ? face->background
- : f->output_data.mac->cursor_pixel)
- : face->foreground));
-#if USE_CG_DRAWING
- mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
- p->wd, p->h, p->x, p->y, overlay_p);
-#else
- mac_draw_bitmap (f, face->gc, p->x, p->y,
- p->wd, p->h, p->bits + p->dh, overlay_p);
-#endif
- XSetForeground (display, face->gc, gcv.foreground);
- }
-
- mac_reset_clip_rectangles (f, face->gc);
-}
-
-#if USE_CG_DRAWING
-static void
-mac_define_fringe_bitmap (which, bits, h, wd)
- int which;
- unsigned short *bits;
- int h, wd;
-{
- int i;
- CGDataProviderRef provider;
-
- if (which >= max_fringe_bmp)
- {
- i = max_fringe_bmp;
- max_fringe_bmp = which + 20;
- fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
- while (i < max_fringe_bmp)
- fringe_bmp[i++] = 0;
- }
-
- for (i = 0; i < h; i++)
- bits[i] = ~bits[i];
-
- BLOCK_INPUT;
-
- provider = CGDataProviderCreateWithData (NULL, bits,
- sizeof (unsigned short) * h, NULL);
- if (provider)
- {
- fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
- sizeof (unsigned short),
- provider, NULL, 0);
- CGDataProviderRelease (provider);
- }
-
- UNBLOCK_INPUT;
-}
-
-static void
-mac_destroy_fringe_bitmap (which)
- int which;
-{
- if (which >= max_fringe_bmp)
- return;
-
- if (fringe_bmp[which])
- {
- BLOCK_INPUT;
- CGImageRelease (fringe_bmp[which]);
- UNBLOCK_INPUT;
- }
- fringe_bmp[which] = 0;
-}
-#endif
-
-
-/* This is called when starting Emacs and when restarting after
- suspend. When starting Emacs, no window is mapped. And nothing
- must be done to Emacs's own window if it is suspended (though that
- rarely happens). */
-
-static void
-XTset_terminal_modes (struct terminal *t)
-{
-}
-
-/* This is called when exiting or suspending Emacs. Exiting will make
- the windows go away, and suspending requires no action. */
-
-static void
-XTreset_terminal_modes (struct terminal *t)
-{
-}
-
-
-
-/***********************************************************************
- Display Iterator
- ***********************************************************************/
-
-/* Function prototypes of this page. */
-
-static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
-static int mac_encode_char P_ ((int, XChar2b *, struct font_info *,
- struct charset *, int *));
-
-
-static void
-pcm_init (pcm, count)
- XCharStruct *pcm;
- int count;
-{
- bzero (pcm, sizeof (XCharStruct) * count);
- while (--count >= 0)
- {
- pcm->descent = PCM_INVALID;
- pcm++;
- }
-}
-
-static enum pcm_status
-pcm_get_status (pcm)
- const XCharStruct *pcm;
-{
- int height = pcm->ascent + pcm->descent;
-
- /* Negative height means some special status. */
- return height >= 0 ? PCM_VALID : height;
-}
-
-/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
- is not contained in the font. */
-
-static INLINE XCharStruct *
-x_per_char_metric (font, char2b)
- XFontStruct *font;
- XChar2b *char2b;
-{
- /* The result metric information. */
- XCharStruct *pcm = NULL;
-
- xassert (font && char2b);
-
-#if USE_ATSUI
- if (font->mac_style)
- {
- XCharStruct **row = font->bounds.rows + char2b->byte1;
-
- if (*row == NULL)
- {
- *row = xmalloc (sizeof (XCharStruct) * 0x100);
- pcm_init (*row, 0x100);
- }
- pcm = *row + char2b->byte2;
- if (pcm_get_status (pcm) != PCM_VALID)
- {
- BLOCK_INPUT;
- mac_query_char_extents (font->mac_style,
- (char2b->byte1 << 8) + char2b->byte2,
- NULL, NULL, pcm, NULL);
- UNBLOCK_INPUT;
- }
- }
- else
- {
-#endif
- if (font->bounds.per_char != NULL)
- {
- if (font->min_byte1 == 0 && font->max_byte1 == 0)
- {
- /* min_char_or_byte2 specifies the linear character index
- corresponding to the first element of the per_char array,
- max_char_or_byte2 is the index of the last character. A
- character with non-zero CHAR2B->byte1 is not in the font.
- A character with byte2 less than min_char_or_byte2 or
- greater max_char_or_byte2 is not in the font. */
- if (char2b->byte1 == 0
- && char2b->byte2 >= font->min_char_or_byte2
- && char2b->byte2 <= font->max_char_or_byte2)
- pcm = font->bounds.per_char
- + (char2b->byte2 - font->min_char_or_byte2);
- }
- else
- {
- /* If either min_byte1 or max_byte1 are nonzero, both
- min_char_or_byte2 and max_char_or_byte2 are less than
- 256, and the 2-byte character index values corresponding
- to the per_char array element N (counting from 0) are:
-
- byte1 = N/D + min_byte1
- byte2 = N\D + min_char_or_byte2
-
- where:
-
- D = max_char_or_byte2 - min_char_or_byte2 + 1
- / = integer division
- \ = integer modulus */
- if (char2b->byte1 >= font->min_byte1
- && char2b->byte1 <= font->max_byte1
- && char2b->byte2 >= font->min_char_or_byte2
- && char2b->byte2 <= font->max_char_or_byte2)
- {
- pcm = (font->bounds.per_char
- + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
- * (char2b->byte1 - font->min_byte1))
- + (char2b->byte2 - font->min_char_or_byte2));
- }
- }
- }
- else
- {
- /* If the per_char pointer is null, all glyphs between the first
- and last character indexes inclusive have the same
- information, as given by both min_bounds and max_bounds. */
- if (char2b->byte2 >= font->min_char_or_byte2
- && char2b->byte2 <= font->max_char_or_byte2)
- pcm = &font->max_bounds;
- }
-#if USE_ATSUI
- }
-#endif
-
- return ((pcm == NULL
- || (pcm->width == 0
-#if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
- && (pcm->rbearing - pcm->lbearing) == 0
-#endif
- ))
- ? NULL : pcm);
-}
-
-/* RIF:
- */
-
-static XCharStruct *
-mac_per_char_metric (font, char2b, font_type)
- XFontStruct *font;
- XChar2b *char2b;
- int font_type;
-{
- return x_per_char_metric (font, char2b);
-}
-
-/* RIF:
- Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
- the two-byte form of C. Encoding is returned in *CHAR2B. */
-
-static int
-mac_encode_char (c, char2b, font_info, charset, two_byte_p)
- int c;
- XChar2b *char2b;
- struct font_info *font_info;
- struct charset *charset;
- int *two_byte_p;
-{
- XFontStruct *font = font_info->font;
-
- /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
- This may be either a program in a special encoder language or a
- fixed encoding. */
- if (font_info->font_encoder)
- {
- /* It's a program. */
- struct ccl_program *ccl = font_info->font_encoder;
-
- check_ccl_update (ccl);
- if (CHARSET_DIMENSION (charset) == 1)
- {
- ccl->reg[0] = CHARSET_ID (charset);
- ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
- ccl->reg[2] = -1;
- }
- else
- {
- ccl->reg[0] = CHARSET_ID (charset);
- ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
- ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
- }
-
- ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
-
- /* We assume that MSBs are appropriately set/reset by CCL
- program. */
- if (font->max_byte1 == 0) /* 1-byte font */
- STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
- else
- STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
- }
- else if (font_info->encoding_type)
- {
- /* Fixed encoding scheme. See fontset.h for the meaning of the
- encoding numbers. */
- unsigned char enc = font_info->encoding_type;
-
- if ((enc == 1 || enc == 2)
- && CHARSET_DIMENSION (charset) == 2)
- char2b->byte1 |= 0x80;
-
- if (enc == 1 || enc == 3)
- char2b->byte2 |= 0x80;
-
- if (enc == 4)
- {
- int code = (char2b->byte1 << 8) | char2b->byte2;
-
- JIS_TO_SJIS (code);
- STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
- }
- }
-
- if (two_byte_p)
- *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
-
- return FONT_TYPE_UNKNOWN;
-}
-
-
-
-/***********************************************************************
- Glyph display
- ***********************************************************************/
-
-
-
-static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
-static void x_set_glyph_string_gc P_ ((struct glyph_string *));
-static void x_draw_glyph_string_background P_ ((struct glyph_string *,
- int));
-static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
-static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
-static void x_draw_glyph_string_box P_ ((struct glyph_string *));
-static void x_draw_glyph_string P_ ((struct glyph_string *));
-static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
-static void x_set_cursor_gc P_ ((struct glyph_string *));
-static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
-static void x_set_mouse_face_gc P_ ((struct glyph_string *));
-/*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
- unsigned long *, double, int));*/
-static void x_setup_relief_color P_ ((struct frame *, struct relief *,
- double, int, unsigned long));
-static void x_setup_relief_colors P_ ((struct glyph_string *));
-static void x_draw_image_glyph_string P_ ((struct glyph_string *));
-static void x_draw_image_relief P_ ((struct glyph_string *));
-static void x_draw_image_foreground P_ ((struct glyph_string *));
-static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
- int, int, int));
-static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
- int, int, int, int, int, int,
- Rect *));
-static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
- int, int, int, Rect *));
-
-#if GLYPH_DEBUG
-static void x_check_font P_ ((struct frame *, XFontStruct *));
-#endif
-
-
-/* Set S->gc to a suitable GC for drawing glyph string S in cursor
- face. */
-
-static void
-x_set_cursor_gc (s)
- struct glyph_string *s;
-{
- if (s->font == FRAME_FONT (s->f)
- && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
- && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
- && !s->cmp)
- s->gc = s->f->output_data.mac->cursor_gc;
- else
- {
- /* Cursor on non-default face: must merge. */
- XGCValues xgcv;
- unsigned long mask;
-
- xgcv.background = s->f->output_data.mac->cursor_pixel;
- xgcv.foreground = s->face->background;
-
- /* If the glyph would be invisible, try a different foreground. */
- if (xgcv.foreground == xgcv.background)
- xgcv.foreground = s->face->foreground;
- if (xgcv.foreground == xgcv.background)
- xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
- if (xgcv.foreground == xgcv.background)
- xgcv.foreground = s->face->foreground;
-
- /* Make sure the cursor is distinct from text in this face. */
- if (xgcv.background == s->face->background
- && xgcv.foreground == s->face->foreground)
- {
- xgcv.background = s->face->foreground;
- xgcv.foreground = s->face->background;
- }
-
- IF_DEBUG (x_check_font (s->f, s->font));
- xgcv.font = s->font;
- mask = GCForeground | GCBackground | GCFont;
-
- if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
- XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
- mask, &xgcv);
- else
- FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
- = XCreateGC (s->display, s->window, mask, &xgcv);
-
- s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
- }
-}
-
-
-/* Set up S->gc of glyph string S for drawing text in mouse face. */
-
-static void
-x_set_mouse_face_gc (s)
- struct glyph_string *s;
-{
- int face_id;
- struct face *face;
-
- /* What face has to be used last for the mouse face? */
- face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
- face = FACE_FROM_ID (s->f, face_id);
- if (face == NULL)
- face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
-
- if (s->first_glyph->type == CHAR_GLYPH)
- face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
- else
- face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
- s->face = FACE_FROM_ID (s->f, face_id);
- PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
-
- /* If font in this face is same as S->font, use it. */
- if (s->font == s->face->font)
- s->gc = s->face->gc;
- else
- {
- /* Otherwise construct scratch_cursor_gc with values from FACE
- but font FONT. */
- XGCValues xgcv;
- unsigned long mask;
-
- xgcv.background = s->face->background;
- xgcv.foreground = s->face->foreground;
- IF_DEBUG (x_check_font (s->f, s->font));
- xgcv.font = s->font;
- mask = GCForeground | GCBackground | GCFont;
-
- if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
- XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
- mask, &xgcv);
- else
- FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
- = XCreateGC (s->display, s->window, mask, &xgcv);
-
- s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
- }
-
- xassert (s->gc != 0);
-}
-
-
-/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
- Faces to use in the mode line have already been computed when the
- matrix was built, so there isn't much to do, here. */
-
-static INLINE void
-x_set_mode_line_face_gc (s)
- struct glyph_string *s;
-{
- s->gc = s->face->gc;
-}
-
-
-/* Set S->gc of glyph string S for drawing that glyph string. Set
- S->stippled_p to a non-zero value if the face of S has a stipple
- pattern. */
-
-static INLINE void
-x_set_glyph_string_gc (s)
- struct glyph_string *s;
-{
- PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
-
- if (s->hl == DRAW_NORMAL_TEXT)
- {
- s->gc = s->face->gc;
- s->stippled_p = s->face->stipple != 0;
- }
- else if (s->hl == DRAW_INVERSE_VIDEO)
- {
- x_set_mode_line_face_gc (s);
- s->stippled_p = s->face->stipple != 0;
- }
- else if (s->hl == DRAW_CURSOR)
- {
- x_set_cursor_gc (s);
- s->stippled_p = 0;
- }
- else if (s->hl == DRAW_MOUSE_FACE)
- {
- x_set_mouse_face_gc (s);
- s->stippled_p = s->face->stipple != 0;
- }
- else if (s->hl == DRAW_IMAGE_RAISED
- || s->hl == DRAW_IMAGE_SUNKEN)
- {
- s->gc = s->face->gc;
- s->stippled_p = s->face->stipple != 0;
- }
- else
- {
- s->gc = s->face->gc;
- s->stippled_p = s->face->stipple != 0;
- }
-
- /* GC must have been set. */
- xassert (s->gc != 0);
-}
-
-
-/* Set clipping for output of glyph string S. S may be part of a mode
- line or menu if we don't have X toolkit support. */
-
-static INLINE void
-x_set_glyph_string_clipping (s)
- struct glyph_string *s;
-{
- Rect rects[MAX_CLIP_RECTS];
- int n;
-
- n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
- mac_set_clip_rectangles (s->f, s->gc, rects, n);
-}
-
-
-/* RIF:
- Compute left and right overhang of glyph string S. If S is a glyph
- string for a composition, assume overhangs don't exist. */
-
-static void
-mac_compute_glyph_string_overhangs (s)
- struct glyph_string *s;
-{
- if (!(s->cmp == NULL
- && s->first_glyph->type == CHAR_GLYPH))
- return;
-
- if (!s->two_byte_p
-#if USE_ATSUI
- || s->font->mac_style
-#endif
- )
- {
- XCharStruct cs;
-
- mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
- s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
- s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
- }
- else
- {
- Rect r;
- MacFontStruct *font = s->font;
-
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (s->f);
-#endif
- SetPortWindowPort (FRAME_MAC_WINDOW (s->f));
-
- TextFont (font->mac_fontnum);
- TextSize (font->mac_fontsize);
- TextFace (font->mac_fontface);
-
- QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
-
- s->right_overhang = r.right > s->width ? r.right - s->width : 0;
- s->left_overhang = r.left < 0 ? -r.left : 0;
- }
-}
-
-
-/* Fill rectangle X, Y, W, H with background color of glyph string S. */
-
-static INLINE void
-x_clear_glyph_string_rect (s, x, y, w, h)
- struct glyph_string *s;
- int x, y, w, h;
-{
- mac_erase_rectangle (s->f, s->gc, x, y, w, h);
-}
-
-
-/* Draw the background of glyph_string S. If S->background_filled_p
- is non-zero don't draw it. FORCE_P non-zero means draw the
- background even if it wouldn't be drawn normally. This is used
- when a string preceding S draws into the background of S, or S
- contains the first component of a composition. */
-
-static void
-x_draw_glyph_string_background (s, force_p)
- struct glyph_string *s;
- int force_p;
-{
- /* Nothing to do if background has already been drawn or if it
- shouldn't be drawn in the first place. */
- if (!s->background_filled_p)
- {
- int box_line_width = max (s->face->box_line_width, 0);
-
-#if 0 /* MAC_TODO: stipple */
- if (s->stippled_p)
- {
- /* Fill background with a stipple pattern. */
- XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
- XFillRectangle (s->display, s->window, s->gc, s->x,
- s->y + box_line_width,
- s->background_width,
- s->height - 2 * box_line_width);
- XSetFillStyle (s->display, s->gc, FillSolid);
- s->background_filled_p = 1;
- }
- else
-#endif
- if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
- || s->font_not_found_p
- || s->extends_to_end_of_line_p
- || force_p)
- {
- x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
- s->background_width,
- s->height - 2 * box_line_width);
- s->background_filled_p = 1;
- }
- }
-}
-
-
-/* Draw the foreground of glyph string S. */
-
-static void
-x_draw_glyph_string_foreground (s)
- struct glyph_string *s;
-{
- int i, x, bg_width;
-
- /* If first glyph of S has a left box line, start drawing the text
- of S to the right of that box line. */
- if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + eabs (s->face->box_line_width);
- else
- x = s->x;
-
- /* Draw characters of S as rectangles if S's font could not be
- loaded. */
- if (s->font_not_found_p)
- {
- for (i = 0; i < s->nchars; ++i)
- {
- struct glyph *g = s->first_glyph + i;
- mac_draw_rectangle (s->f, s->gc, x, s->y,
- g->pixel_width - 1, s->height - 1);
- x += g->pixel_width;
- }
- }
- else
- {
- char *char1b = (char *) s->char2b;
- int boff = s->font_info->baseline_offset;
-
- if (s->font_info->vertical_centering)
- boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
-
- /* If we can use 8-bit functions, condense S->char2b. */
- if (!s->two_byte_p
-#if USE_ATSUI
- && GC_FONT (s->gc)->mac_style == NULL
-#endif
- )
- for (i = 0; i < s->nchars; ++i)
- char1b[i] = s->char2b[i].byte2;
-
- /* Draw text with XDrawString if background has already been
- filled. Otherwise, use XDrawImageString. (Note that
- XDrawImageString is usually faster than XDrawString.) Always
- use XDrawImageString when drawing the cursor so that there is
- no chance that characters under a box cursor are invisible. */
- if (s->for_overlaps
- || (s->background_filled_p && s->hl != DRAW_CURSOR))
- bg_width = 0; /* Corresponds to XDrawString. */
- else
- bg_width = s->background_width; /* Corresponds to XDrawImageString. */
-
- if (s->two_byte_p
-#if USE_ATSUI
- || GC_FONT (s->gc)->mac_style
-#endif
- )
-#if USE_CG_TEXT_DRAWING
- if (!s->two_byte_p
- && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
- s->char2b, s->nchars, bg_width,
- s->face->overstrike))
- ;
- else
-#endif
- mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
- s->char2b, s->nchars, bg_width,
- s->face->overstrike);
- else
- mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
- char1b, s->nchars, bg_width,
- s->face->overstrike);
- }
-}
-
-/* Draw the foreground of composite glyph string S. */
-
-static void
-x_draw_composite_glyph_string_foreground (s)
- struct glyph_string *s;
-{
- int i, x;
-
- /* If first glyph of S has a left box line, start drawing the text
- of S to the right of that box line. */
- if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + eabs (s->face->box_line_width);
- else
- x = s->x;
-
- /* S is a glyph string for a composition. S->gidx is the index of
- the first character drawn for glyphs of this composition.
- S->gidx == 0 means we are drawing the very first character of
- this composition. */
-
- /* Draw a rectangle for the composition if the font for the very
- first character of the composition could not be loaded. */
- if (s->font_not_found_p)
- {
- if (s->gidx == 0)
- mac_draw_rectangle (s->f, s->gc, x, s->y,
- s->width - 1, s->height - 1);
- }
- else
- {
- for (i = 0; i < s->nchars; i++, ++s->gidx)
- if (mac_per_char_metric (GC_FONT (s->gc), s->char2b + i, 0) == NULL)
- /* This is a nonexistent or zero-width glyph such as a
- combining diacritic. Draw a rectangle. */
- mac_draw_rectangle (s->f, s->gc,
- x + s->cmp->offsets[s->gidx * 2], s->y,
- FONT_WIDTH (GC_FONT (s->gc)) - 1, s->height - 1);
- else
- mac_draw_image_string_16 (s->f, s->gc,
- x + s->cmp->offsets[s->gidx * 2],
- s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
- s->char2b + i, 1, 0, s->face->overstrike);
- }
-}
-
-
-#ifdef USE_X_TOOLKIT
-
-static struct frame *x_frame_of_widget P_ ((Widget));
-
-
-/* Return the frame on which widget WIDGET is used.. Abort if frame
- cannot be determined. */
-
-static struct frame *
-x_frame_of_widget (widget)
- Widget widget;
-{
- struct x_display_info *dpyinfo;
- Lisp_Object tail;
- struct frame *f;
-
- dpyinfo = x_display_info_for_display (XtDisplay (widget));
-
- /* Find the top-level shell of the widget. Note that this function
- can be called when the widget is not yet realized, so XtWindow
- (widget) == 0. That's the reason we can't simply use
- x_any_window_to_frame. */
- while (!XtIsTopLevelShell (widget))
- widget = XtParent (widget);
-
- /* Look for a frame with that top-level widget. Allocate the color
- on that frame to get the right gamma correction value. */
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- if (FRAMEP (XCAR (tail))
- && (f = XFRAME (XCAR (tail)),
- (f->output_data.nothing != 1
- && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
- && f->output_data.x->widget == widget)
- return f;
-
- abort ();
-}
-
-
-/* Allocate the color COLOR->pixel on the screen and display of
- widget WIDGET in colormap CMAP. If an exact match cannot be
- allocated, try the nearest color available. Value is non-zero
- if successful. This is called from lwlib. */
-
-int
-x_alloc_nearest_color_for_widget (widget, cmap, color)
- Widget widget;
- Colormap cmap;
- XColor *color;
-{
- struct frame *f = x_frame_of_widget (widget);
- return x_alloc_nearest_color (f, cmap, color);
-}
-
-
-#endif /* USE_X_TOOLKIT */
-
-#if 0 /* MAC_TODO */
-
-/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
- CMAP. If an exact match can't be allocated, try the nearest color
- available. Value is non-zero if successful. Set *COLOR to the
- color allocated. */
-
-int
-x_alloc_nearest_color (f, cmap, color)
- struct frame *f;
- Colormap cmap;
- XColor *color;
-{
- Display *display = FRAME_X_DISPLAY (f);
- Screen *screen = FRAME_X_SCREEN (f);
- int rc;
-
- gamma_correct (f, color);
- rc = XAllocColor (display, cmap, color);
- if (rc == 0)
- {
- /* If we got to this point, the colormap is full, so we're going
- to try to get the next closest color. The algorithm used is
- a least-squares matching, which is what X uses for closest
- color matching with StaticColor visuals. */
- int nearest, i;
- unsigned long nearest_delta = ~0;
- int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
- XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
-
- for (i = 0; i < ncells; ++i)
- cells[i].pixel = i;
- XQueryColors (display, cmap, cells, ncells);
-
- for (nearest = i = 0; i < ncells; ++i)
- {
- long dred = (color->red >> 8) - (cells[i].red >> 8);
- long dgreen = (color->green >> 8) - (cells[i].green >> 8);
- long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
- unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
-
- if (delta < nearest_delta)
- {
- nearest = i;
- nearest_delta = delta;
- }
- }
-
- color->red = cells[nearest].red;
- color->green = cells[nearest].green;
- color->blue = cells[nearest].blue;
- rc = XAllocColor (display, cmap, color);
- }
-
-#ifdef DEBUG_X_COLORS
- if (rc)
- register_color (color->pixel);
-#endif /* DEBUG_X_COLORS */
-
- return rc;
-}
-
-
-/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
- It's necessary to do this instead of just using PIXEL directly to
- get color reference counts right. */
-
-unsigned long
-x_copy_color (f, pixel)
- struct frame *f;
- unsigned long pixel;
-{
- XColor color;
-
- color.pixel = pixel;
- BLOCK_INPUT;
- XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
- XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
- UNBLOCK_INPUT;
-#ifdef DEBUG_X_COLORS
- register_color (pixel);
-#endif
- return color.pixel;
-}
-
-
-/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
- It's necessary to do this instead of just using PIXEL directly to
- get color reference counts right. */
-
-unsigned long
-x_copy_dpy_color (dpy, cmap, pixel)
- Display *dpy;
- Colormap cmap;
- unsigned long pixel;
-{
- XColor color;
-
- color.pixel = pixel;
- BLOCK_INPUT;
- XQueryColor (dpy, cmap, &color);
- XAllocColor (dpy, cmap, &color);
- UNBLOCK_INPUT;
-#ifdef DEBUG_X_COLORS
- register_color (pixel);
-#endif
- return color.pixel;
-}
-
-#endif /* MAC_TODO */
-
-
-/* Brightness beyond which a color won't have its highlight brightness
- boosted.
-
- Nominally, highlight colors for `3d' faces are calculated by
- brightening an object's color by a constant scale factor, but this
- doesn't yield good results for dark colors, so for colors who's
- brightness is less than this value (on a scale of 0-255) have to
- use an additional additive factor.
-
- The value here is set so that the default menu-bar/mode-line color
- (grey75) will not have its highlights changed at all. */
-#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
-
-
-/* Allocate a color which is lighter or darker than *COLOR by FACTOR
- or DELTA. Try a color with RGB values multiplied by FACTOR first.
- If this produces the same color as COLOR, try a color where all RGB
- values have DELTA added. Return the allocated color in *COLOR.
- DISPLAY is the X display, CMAP is the colormap to operate on.
- Value is non-zero if successful. */
-
-static int
-mac_alloc_lighter_color (f, color, factor, delta)
- struct frame *f;
- unsigned long *color;
- double factor;
- int delta;
-{
- unsigned long new;
- long bright;
-
- /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
- delta /= 256;
-
- /* Change RGB values by specified FACTOR. Avoid overflow! */
- xassert (factor >= 0);
- new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
- min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
- min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
-
- /* Calculate brightness of COLOR. */
- bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
- + BLUE_FROM_ULONG (*color)) / 6;
-
- /* We only boost colors that are darker than
- HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
- if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
- /* Make an additive adjustment to NEW, because it's dark enough so
- that scaling by FACTOR alone isn't enough. */
- {
- /* How far below the limit this color is (0 - 1, 1 being darker). */
- double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
- /* The additive adjustment. */
- int min_delta = delta * dimness * factor / 2;
-
- if (factor < 1)
- new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
- max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
- max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
- else
- new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
- max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
- max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
- }
-
- if (new == *color)
- new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
- max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
- max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
-
- /* MAC_TODO: Map to palette and retry with delta if same? */
- /* MAC_TODO: Free colors (if using palette)? */
-
- if (new == *color)
- return 0;
-
- *color = new;
-
- return 1;
-}
-
-
-/* Set up the foreground color for drawing relief lines of glyph
- string S. RELIEF is a pointer to a struct relief containing the GC
- with which lines will be drawn. Use a color that is FACTOR or
- DELTA lighter or darker than the relief's background which is found
- in S->f->output_data.x->relief_background. If such a color cannot
- be allocated, use DEFAULT_PIXEL, instead. */
-
-static void
-x_setup_relief_color (f, relief, factor, delta, default_pixel)
- struct frame *f;
- struct relief *relief;
- double factor;
- int delta;
- unsigned long default_pixel;
-{
- XGCValues xgcv;
- struct mac_output *di = f->output_data.mac;
- unsigned long mask = GCForeground;
- unsigned long pixel;
- unsigned long background = di->relief_background;
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- /* MAC_TODO: Free colors (if using palette)? */
-
- /* Allocate new color. */
- xgcv.foreground = default_pixel;
- pixel = background;
- if (dpyinfo->n_planes != 1
- && mac_alloc_lighter_color (f, &pixel, factor, delta))
- {
- relief->allocated_p = 1;
- xgcv.foreground = relief->pixel = pixel;
- }
-
- if (relief->gc == 0)
- {
-#if 0 /* MAC_TODO: stipple */
- xgcv.stipple = dpyinfo->gray;
- mask |= GCStipple;
-#endif
- relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
- }
- else
- XChangeGC (NULL, relief->gc, mask, &xgcv);
-}
-
-
-/* Set up colors for the relief lines around glyph string S. */
-
-static void
-x_setup_relief_colors (s)
- struct glyph_string *s;
-{
- struct mac_output *di = s->f->output_data.mac;
- unsigned long color;
-
- if (s->face->use_box_color_for_shadows_p)
- color = s->face->box_color;
- else if (s->first_glyph->type == IMAGE_GLYPH
- && s->img->pixmap
- && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
- color = IMAGE_BACKGROUND (s->img, s->f, 0);
- else
- {
- XGCValues xgcv;
-
- /* Get the background color of the face. */
- XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
- color = xgcv.background;
- }
-
- if (di->white_relief.gc == 0
- || color != di->relief_background)
- {
- di->relief_background = color;
- x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
- WHITE_PIX_DEFAULT (s->f));
- x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
- BLACK_PIX_DEFAULT (s->f));
- }
-}
-
-
-/* Draw a relief on frame F inside the rectangle given by LEFT_X,
- TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
- to draw, it must be >= 0. RAISED_P non-zero means draw a raised
- relief. LEFT_P non-zero means draw a relief on the left side of
- the rectangle. RIGHT_P non-zero means draw a relief on the right
- side of the rectangle. CLIP_RECT is the clipping rectangle to use
- when drawing. */
-
-static void
-x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
- raised_p, top_p, bot_p, left_p, right_p, clip_rect)
- struct frame *f;
- int left_x, top_y, right_x, bottom_y, width;
- int top_p, bot_p, left_p, right_p, raised_p;
- Rect *clip_rect;
-{
- int i;
- GC gc;
-
- if (raised_p)
- gc = f->output_data.mac->white_relief.gc;
- else
- gc = f->output_data.mac->black_relief.gc;
- mac_set_clip_rectangles (f, gc, clip_rect, 1);
-
- /* Top. */
- if (top_p)
- for (i = 0; i < width; ++i)
- mac_draw_line (f, gc,
- left_x + i * left_p, top_y + i,
- right_x + 1 - i * right_p, top_y + i);
-
- /* Left. */
- if (left_p)
- for (i = 0; i < width; ++i)
- mac_draw_line (f, gc,
- left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
-
- mac_reset_clip_rectangles (f, gc);
- if (raised_p)
- gc = f->output_data.mac->black_relief.gc;
- else
- gc = f->output_data.mac->white_relief.gc;
- mac_set_clip_rectangles (f, gc, clip_rect, 1);
-
- /* Bottom. */
- if (bot_p)
- for (i = 0; i < width; ++i)
- mac_draw_line (f, gc,
- left_x + i * left_p, bottom_y - i,
- right_x + 1 - i * right_p, bottom_y - i);
-
- /* Right. */
- if (right_p)
- for (i = 0; i < width; ++i)
- mac_draw_line (f, gc,
- right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
-
- mac_reset_clip_rectangles (f, gc);
-}
-
-
-/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
- RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
- draw, it must be >= 0. LEFT_P non-zero means draw a line on the
- left side of the rectangle. RIGHT_P non-zero means draw a line
- on the right side of the rectangle. CLIP_RECT is the clipping
- rectangle to use when drawing. */
-
-static void
-x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
- left_p, right_p, clip_rect)
- struct glyph_string *s;
- int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
- Rect *clip_rect;
-{
- XGCValues xgcv;
-
- XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
- XSetForeground (s->display, s->gc, s->face->box_color);
- mac_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
-
- /* Top. */
- mac_fill_rectangle (s->f, s->gc, left_x, top_y,
- right_x - left_x + 1, width);
-
- /* Left. */
- if (left_p)
- mac_fill_rectangle (s->f, s->gc, left_x, top_y,
- width, bottom_y - top_y + 1);
-
- /* Bottom. */
- mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
- right_x - left_x + 1, width);
-
- /* Right. */
- if (right_p)
- mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
- top_y, width, bottom_y - top_y + 1);
-
- XSetForeground (s->display, s->gc, xgcv.foreground);
- mac_reset_clip_rectangles (s->f, s->gc);
-}
-
-
-/* Draw a box around glyph string S. */
-
-static void
-x_draw_glyph_string_box (s)
- struct glyph_string *s;
-{
- int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
- int left_p, right_p;
- struct glyph *last_glyph;
- Rect clip_rect;
-
- last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
- ? WINDOW_RIGHT_EDGE_X (s->w)
- : window_box_right (s->w, s->area));
-
- /* The glyph that may have a right box line. */
- last_glyph = (s->cmp || s->img
- ? s->first_glyph
- : s->first_glyph + s->nchars - 1);
-
- width = eabs (s->face->box_line_width);
- raised_p = s->face->box == FACE_RAISED_BOX;
- left_x = s->x;
- right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
- ? last_x - 1
- : min (last_x, s->x + s->background_width) - 1);
- top_y = s->y;
- bottom_y = top_y + s->height - 1;
-
- left_p = (s->first_glyph->left_box_line_p
- || (s->hl == DRAW_MOUSE_FACE
- && (s->prev == NULL
- || s->prev->hl != s->hl)));
- right_p = (last_glyph->right_box_line_p
- || (s->hl == DRAW_MOUSE_FACE
- && (s->next == NULL
- || s->next->hl != s->hl)));
-
- get_glyph_string_clip_rect (s, &clip_rect);
-
- if (s->face->box == FACE_SIMPLE_BOX)
- x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
- left_p, right_p, &clip_rect);
- else
- {
- x_setup_relief_colors (s);
- x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
- width, raised_p, 1, 1, left_p, right_p, &clip_rect);
- }
-}
-
-
-/* Draw foreground of image glyph string S. */
-
-static void
-x_draw_image_foreground (s)
- struct glyph_string *s;
-{
- int x = s->x;
- int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
-
- /* If first glyph of S has a left box line, start drawing it to the
- right of that line. */
- if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p
- && s->slice.x == 0)
- x += eabs (s->face->box_line_width);
-
- /* If there is a margin around the image, adjust x- and y-position
- by that margin. */
- if (s->slice.x == 0)
- x += s->img->hmargin;
- if (s->slice.y == 0)
- y += s->img->vmargin;
-
- if (s->img->pixmap)
- {
- x_set_glyph_string_clipping (s);
-
-#if USE_CG_DRAWING
- mac_draw_cg_image (s->img->data.ptr_val,
- s->f, s->gc, s->slice.x, s->slice.y,
- s->slice.width, s->slice.height, x, y, 1);
-#endif
- if (s->img->mask)
-#if !USE_CG_DRAWING
- mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
- s->f, s->gc, s->slice.x, s->slice.y,
- s->slice.width, s->slice.height, x, y);
-#else
- ;
-#endif
- else
- {
-#if !USE_CG_DRAWING
- mac_copy_area (s->img->pixmap,
- s->f, s->gc, s->slice.x, s->slice.y,
- s->slice.width, s->slice.height, x, y);
-#endif
-
- /* When the image has a mask, we can expect that at
- least part of a mouse highlight or a block cursor will
- be visible. If the image doesn't have a mask, make
- a block cursor visible by drawing a rectangle around
- the image. I believe it's looking better if we do
- nothing here for mouse-face. */
- if (s->hl == DRAW_CURSOR)
- {
- int r = s->img->relief;
- if (r < 0) r = -r;
- mac_draw_rectangle (s->f, s->gc, x - r, y - r,
- s->slice.width + r*2 - 1,
- s->slice.height + r*2 - 1);
- }
- }
- }
- else
- /* Draw a rectangle if image could not be loaded. */
- mac_draw_rectangle (s->f, s->gc, x, y,
- s->slice.width - 1, s->slice.height - 1);
-}
-
-
-/* Draw a relief around the image glyph string S. */
-
-static void
-x_draw_image_relief (s)
- struct glyph_string *s;
-{
- int x0, y0, x1, y1, thick, raised_p;
- Rect r;
- int x = s->x;
- int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
-
- /* If first glyph of S has a left box line, start drawing it to the
- right of that line. */
- if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p
- && s->slice.x == 0)
- x += eabs (s->face->box_line_width);
-
- /* If there is a margin around the image, adjust x- and y-position
- by that margin. */
- if (s->slice.x == 0)
- x += s->img->hmargin;
- if (s->slice.y == 0)
- y += s->img->vmargin;
-
- if (s->hl == DRAW_IMAGE_SUNKEN
- || s->hl == DRAW_IMAGE_RAISED)
- {
- thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
- raised_p = s->hl == DRAW_IMAGE_RAISED;
- }
- else
- {
- thick = eabs (s->img->relief);
- raised_p = s->img->relief > 0;
- }
-
- x0 = x - thick;
- y0 = y - thick;
- x1 = x + s->slice.width + thick - 1;
- y1 = y + s->slice.height + thick - 1;
-
- x_setup_relief_colors (s);
- get_glyph_string_clip_rect (s, &r);
- x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
- s->slice.y == 0,
- s->slice.y + s->slice.height == s->img->height,
- s->slice.x == 0,
- s->slice.x + s->slice.width == s->img->width,
- &r);
-}
-
-
-/* Draw part of the background of glyph string S. X, Y, W, and H
- give the rectangle to draw. */
-
-static void
-x_draw_glyph_string_bg_rect (s, x, y, w, h)
- struct glyph_string *s;
- int x, y, w, h;
-{
-#if 0 /* MAC_TODO: stipple */
- if (s->stippled_p)
- {
- /* Fill background with a stipple pattern. */
- XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
- XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
- XSetFillStyle (s->display, s->gc, FillSolid);
- }
- else
-#endif /* MAC_TODO */
- x_clear_glyph_string_rect (s, x, y, w, h);
-}
-
-
-/* Draw image glyph string S.
-
- s->y
- s->x +-------------------------
- | s->face->box
- |
- | +-------------------------
- | | s->img->margin
- | |
- | | +-------------------
- | | | the image
-
- */
-
-static void
-x_draw_image_glyph_string (s)
- struct glyph_string *s;
-{
- int x, y;
- int box_line_hwidth = eabs (s->face->box_line_width);
- int box_line_vwidth = max (s->face->box_line_width, 0);
- int height;
-
- height = s->height - 2 * box_line_vwidth;
-
-
- /* Fill background with face under the image. Do it only if row is
- taller than image or if image has a clip mask to reduce
- flickering. */
- s->stippled_p = s->face->stipple != 0;
- if (height > s->slice.height
- || s->img->hmargin
- || s->img->vmargin
- || s->img->mask
- || s->img->pixmap == 0
- || s->width != s->background_width)
- {
- x = s->x;
- if (s->first_glyph->left_box_line_p
- && s->slice.x == 0)
- x += box_line_hwidth;
-
- y = s->y;
- if (s->slice.y == 0)
- y += box_line_vwidth;
-
- x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
-
- s->background_filled_p = 1;
- }
-
- /* Draw the foreground. */
- x_draw_image_foreground (s);
-
- /* If we must draw a relief around the image, do it. */
- if (s->img->relief
- || s->hl == DRAW_IMAGE_RAISED
- || s->hl == DRAW_IMAGE_SUNKEN)
- x_draw_image_relief (s);
-}
-
-
-/* Draw stretch glyph string S. */
-
-static void
-x_draw_stretch_glyph_string (s)
- struct glyph_string *s;
-{
- xassert (s->first_glyph->type == STRETCH_GLYPH);
-
- if (s->hl == DRAW_CURSOR
- && !x_stretch_cursor_p)
- {
- /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
- as wide as the stretch glyph. */
- int width, background_width = s->background_width;
- int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
-
- if (x < left_x)
- {
- background_width -= left_x - x;
- x = left_x;
- }
- width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
-
- /* Draw cursor. */
- x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
-
- /* Clear rest using the GC of the original non-cursor face. */
- if (width < background_width)
- {
- int y = s->y;
- int w = background_width - width, h = s->height;
- Rect r;
- GC gc;
-
- x += width;
- if (s->row->mouse_face_p
- && cursor_in_mouse_face_p (s->w))
- {
- x_set_mouse_face_gc (s);
- gc = s->gc;
- }
- else
- gc = s->face->gc;
-
- get_glyph_string_clip_rect (s, &r);
- mac_set_clip_rectangles (s->f, gc, &r, 1);
-
-#if 0 /* MAC_TODO: stipple */
- if (s->face->stipple)
- {
- /* Fill background with a stipple pattern. */
- XSetFillStyle (s->display, gc, FillOpaqueStippled);
- XFillRectangle (s->display, s->window, gc, x, y, w, h);
- XSetFillStyle (s->display, gc, FillSolid);
- }
- else
-#endif /* MAC_TODO */
- mac_erase_rectangle (s->f, gc, x, y, w, h);
- }
- }
- else if (!s->background_filled_p)
- {
- int background_width = s->background_width;
- int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
-
- /* Don't draw into left margin, fringe or scrollbar area
- except for header line and mode line. */
- if (x < left_x && !s->row->mode_line_p)
- {
- background_width -= left_x - x;
- x = left_x;
- }
- if (background_width > 0)
- x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
- }
-
- s->background_filled_p = 1;
-}
-
-
-/* Draw glyph string S. */
-
-static void
-x_draw_glyph_string (s)
- struct glyph_string *s;
-{
- int relief_drawn_p = 0;
-
- /* If S draws into the background of its successor that does not
- draw a cursor, draw the background of the successor first so that
- S can draw into it. This makes S->next use XDrawString instead
- of XDrawImageString. */
- if (s->next && s->right_overhang && !s->for_overlaps
- && s->next->hl != DRAW_CURSOR)
- {
- xassert (s->next->img == NULL);
- x_set_glyph_string_gc (s->next);
- x_set_glyph_string_clipping (s->next);
- x_draw_glyph_string_background (s->next, 1);
- }
-
- /* Set up S->gc, set clipping and draw S. */
- x_set_glyph_string_gc (s);
-
- /* Draw relief (if any) in advance for char/composition so that the
- glyph string can be drawn over it. */
- if (!s->for_overlaps
- && s->face->box != FACE_NO_BOX
- && (s->first_glyph->type == CHAR_GLYPH
- || s->first_glyph->type == COMPOSITE_GLYPH))
-
- {
- x_set_glyph_string_clipping (s);
- x_draw_glyph_string_background (s, 1);
- x_draw_glyph_string_box (s);
- x_set_glyph_string_clipping (s);
- relief_drawn_p = 1;
- }
- else
- x_set_glyph_string_clipping (s);
-
- switch (s->first_glyph->type)
- {
- case IMAGE_GLYPH:
- x_draw_image_glyph_string (s);
- break;
-
- case STRETCH_GLYPH:
- x_draw_stretch_glyph_string (s);
- break;
-
- case CHAR_GLYPH:
- if (s->for_overlaps)
- s->background_filled_p = 1;
- else
- x_draw_glyph_string_background (s, 0);
- x_draw_glyph_string_foreground (s);
- break;
-
- case COMPOSITE_GLYPH:
- if (s->for_overlaps || s->gidx > 0)
- s->background_filled_p = 1;
- else
- x_draw_glyph_string_background (s, 1);
- x_draw_composite_glyph_string_foreground (s);
- break;
-
- default:
- abort ();
- }
-
- if (!s->for_overlaps)
- {
- /* Draw underline. */
- if (s->face->underline_p)
- {
- unsigned long tem, h;
- int y;
-
-#if 0
- /* Get the underline thickness. Default is 1 pixel. */
- if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
-#endif
- h = 1;
-
- y = s->y + s->height - h;
- if (!x_underline_at_descent_line)
- {
- /* Get the underline position. This is the recommended
- vertical offset in pixels from the baseline to the top of
- the underline. This is a signed value according to the
- specs, and its default is
-
- ROUND ((maximum descent) / 2), with
- ROUND(x) = floor (x + 0.5) */
-
-#if 0
- if (x_use_underline_position_properties
- && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
- y = s->ybase + (long) tem;
- else
-#endif
- if (s->face->font)
- y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
- }
- /* FIXME: Obey underline_minimum_offset. */
- if (s->face->underline_defaulted_p)
- mac_fill_rectangle (s->f, s->gc, s->x, y,
- s->background_width, h);
- else
- {
- XGCValues xgcv;
- XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
- XSetForeground (s->display, s->gc, s->face->underline_color);
- mac_fill_rectangle (s->f, s->gc, s->x, y,
- s->background_width, h);
- XSetForeground (s->display, s->gc, xgcv.foreground);
- }
- }
-
- /* Draw overline. */
- if (s->face->overline_p)
- {
- unsigned long dy = 0, h = 1;
-
- if (s->face->overline_color_defaulted_p)
- mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
- s->background_width, h);
- else
- {
- XGCValues xgcv;
- XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
- XSetForeground (s->display, s->gc, s->face->overline_color);
- mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
- s->background_width, h);
- XSetForeground (s->display, s->gc, xgcv.foreground);
- }
- }
-
- /* Draw strike-through. */
- if (s->face->strike_through_p)
- {
- unsigned long h = 1;
- unsigned long dy = (s->height - h) / 2;
-
- if (s->face->strike_through_color_defaulted_p)
- mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
- s->width, h);
- else
- {
- XGCValues xgcv;
- XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
- XSetForeground (s->display, s->gc, s->face->strike_through_color);
- mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
- s->width, h);
- XSetForeground (s->display, s->gc, xgcv.foreground);
- }
- }
-
- /* Draw relief if not yet drawn. */
- if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
- x_draw_glyph_string_box (s);
- }
-
- /* Reset clipping. */
- mac_reset_clip_rectangles (s->f, s->gc);
-}
-
-/* Shift display to make room for inserted glyphs. */
-
-void
-mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
- struct frame *f;
- int x, y, width, height, shift_by;
-{
- mac_scroll_area (f, f->output_data.mac->normal_gc,
- x, y, width, height,
- x + shift_by, y);
-}
-
-/* Delete N glyphs at the nominal cursor position. Not implemented
- for X frames. */
-
-static void
-x_delete_glyphs (n)
- register int n;
-{
- abort ();
-}
-
-
-/* Clear entire frame. If updating_frame is non-null, clear that
- frame. Otherwise clear the selected frame. */
-
-static void
-x_clear_frame (struct frame *f)
-{
- /* Clearing the frame will erase any cursor, so mark them all as no
- longer visible. */
- mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
- output_cursor.hpos = output_cursor.vpos = 0;
- output_cursor.x = -1;
-
- /* We don't set the output cursor here because there will always
- follow an explicit cursor_to. */
- BLOCK_INPUT;
- mac_clear_window (f);
-
- /* We have to clear the scroll bars, too. If we have changed
- colors or something like that, then they should be notified. */
- x_scroll_bar_clear (f);
-
- XFlush (FRAME_MAC_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-
-
-
-/* Invert the middle quarter of the frame for .15 sec. */
-
-/* We use the select system call to do the waiting, so we have to make
- sure it's available. If it isn't, we just won't do visual bells. */
-
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
-
-
-/* Subtract the `struct timeval' values X and Y, storing the result in
- *RESULT. Return 1 if the difference is negative, otherwise 0. */
-
-static int
-timeval_subtract (result, x, y)
- struct timeval *result, x, y;
-{
- /* Perform the carry for the later subtraction by updating y. This
- is safer because on some systems the tv_sec member is unsigned. */
- if (x.tv_usec < y.tv_usec)
- {
- int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
- y.tv_usec -= 1000000 * nsec;
- y.tv_sec += nsec;
- }
-
- if (x.tv_usec - y.tv_usec > 1000000)
- {
- int nsec = (y.tv_usec - x.tv_usec) / 1000000;
- y.tv_usec += 1000000 * nsec;
- y.tv_sec -= nsec;
- }
-
- /* Compute the time remaining to wait. tv_usec is certainly
- positive. */
- result->tv_sec = x.tv_sec - y.tv_sec;
- result->tv_usec = x.tv_usec - y.tv_usec;
-
- /* Return indication of whether the result should be considered
- negative. */
- return x.tv_sec < y.tv_sec;
-}
-
-void
-XTflash (f)
- struct frame *f;
-{
- /* Get the height not including a menu bar widget. */
- int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
- /* Height of each line to flash. */
- int flash_height = FRAME_LINE_HEIGHT (f);
- /* These will be the left and right margins of the rectangles. */
- int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
- int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
-
- int width;
-
- /* Don't flash the area between a scroll bar and the frame
- edge it is next to. */
- switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
- {
- case vertical_scroll_bar_left:
- flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
- break;
-
- case vertical_scroll_bar_right:
- flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
- break;
-
- default:
- break;
- }
-
- width = flash_right - flash_left;
-
- BLOCK_INPUT;
-
- /* If window is tall, flash top and bottom line. */
- if (height > 3 * FRAME_LINE_HEIGHT (f))
- {
- mac_invert_rectangle (f, flash_left,
- (FRAME_INTERNAL_BORDER_WIDTH (f)
- + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
- width, flash_height);
- mac_invert_rectangle (f, flash_left,
- (height - flash_height
- - FRAME_INTERNAL_BORDER_WIDTH (f)),
- width, flash_height);
- }
- else
- /* If it is short, flash it all. */
- mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
- width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
-
- x_flush (f);
-
- {
- struct timeval wakeup;
-
- EMACS_GET_TIME (wakeup);
-
- /* Compute time to wait until, propagating carry from usecs. */
- wakeup.tv_usec += 150000;
- wakeup.tv_sec += (wakeup.tv_usec / 1000000);
- wakeup.tv_usec %= 1000000;
-
- /* Keep waiting until past the time wakeup or any input gets
- available. */
- while (! detect_input_pending ())
- {
- struct timeval current;
- struct timeval timeout;
-
- EMACS_GET_TIME (current);
-
- /* Break if result would be negative. */
- if (timeval_subtract (&current, wakeup, current))
- break;
-
- /* How long `select' should wait. */
- timeout.tv_sec = 0;
- timeout.tv_usec = 10000;
-
- /* Try to wait that long--but we might wake up sooner. */
- select (0, NULL, NULL, NULL, &timeout);
- }
- }
-
- /* If window is tall, flash top and bottom line. */
- if (height > 3 * FRAME_LINE_HEIGHT (f))
- {
- mac_invert_rectangle (f, flash_left,
- (FRAME_INTERNAL_BORDER_WIDTH (f)
- + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
- width, flash_height);
- mac_invert_rectangle (f, flash_left,
- (height - flash_height
- - FRAME_INTERNAL_BORDER_WIDTH (f)),
- width, flash_height);
- }
- else
- /* If it is short, flash it all. */
- mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
- width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
-
- x_flush (f);
-
- UNBLOCK_INPUT;
-}
-
-#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
-
-
-/* Make audible bell. */
-
-void
-XTring_bell ()
-{
- struct frame *f = SELECTED_FRAME ();
-
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
- if (visible_bell)
- XTflash (f);
- else
-#endif
- {
- BLOCK_INPUT;
- SysBeep (1);
- XFlush (FRAME_MAC_DISPLAY (f));
- UNBLOCK_INPUT;
- }
-}
-
-
-/* Specify how many text lines, from the top of the window,
- should be affected by insert-lines and delete-lines operations.
- This, and those operations, are used only within an update
- that is bounded by calls to x_update_begin and x_update_end. */
-
-static void
-XTset_terminal_window (n)
- register int n;
-{
- /* This function intentionally left blank. */
-}
-
-
-
-/***********************************************************************
- Line Dance
- ***********************************************************************/
-
-/* Perform an insert-lines or delete-lines operation, inserting N
- lines or deleting -N lines at vertical position VPOS. */
-
-static void
-x_ins_del_lines (vpos, n)
- int vpos, n;
-{
- abort ();
-}
-
-
-/* Scroll part of the display as described by RUN. */
-
-static void
-x_scroll_run (w, run)
- struct window *w;
- struct run *run;
-{
- struct frame *f = XFRAME (w->frame);
- int x, y, width, height, from_y, to_y, bottom_y;
-
- /* Get frame-relative bounding box of the text display area of W,
- without mode lines. Include in this box the left and right
- fringe of W. */
- window_box (w, -1, &x, &y, &width, &height);
-
- from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
- to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
- bottom_y = y + height;
-
- if (to_y < from_y)
- {
- /* Scrolling up. Make sure we don't copy part of the mode
- line at the bottom. */
- if (from_y + run->height > bottom_y)
- height = bottom_y - from_y;
- else
- height = run->height;
- }
- else
- {
- /* Scolling down. Make sure we don't copy over the mode line.
- at the bottom. */
- if (to_y + run->height > bottom_y)
- height = bottom_y - to_y;
- else
- height = run->height;
- }
-
- BLOCK_INPUT;
-
- /* Cursor off. Will be switched on again in x_update_window_end. */
- updated_window = w;
- x_clear_cursor (w);
-
- mac_scroll_area (f, f->output_data.mac->normal_gc,
- x, from_y,
- width, height,
- x, to_y);
-
- UNBLOCK_INPUT;
-}
-
-
-
-/***********************************************************************
- Exposure Events
- ***********************************************************************/
-
-
-static void
-frame_highlight (f)
- struct frame *f;
-{
- x_update_cursor (f, 1);
-}
-
-static void
-frame_unhighlight (f)
- struct frame *f;
-{
- x_update_cursor (f, 1);
-}
-
-/* The focus has changed. Update the frames as necessary to reflect
- the new situation. Note that we can't change the selected frame
- here, because the Lisp code we are interrupting might become confused.
- Each event gets marked with the frame in which it occurred, so the
- Lisp code can tell when the switch took place by examining the events. */
-
-static void
-x_new_focus_frame (dpyinfo, frame)
- struct x_display_info *dpyinfo;
- struct frame *frame;
-{
- struct frame *old_focus = dpyinfo->x_focus_frame;
-
- if (frame != dpyinfo->x_focus_frame)
- {
- /* Set this before calling other routines, so that they see
- the correct value of x_focus_frame. */
- dpyinfo->x_focus_frame = frame;
-
- if (old_focus && old_focus->auto_lower)
- x_lower_frame (old_focus);
-
-#if 0
- selected_frame = frame;
- XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
- selected_frame);
- Fselect_window (selected_frame->selected_window, Qnil);
- choose_minibuf_frame ();
-#endif /* ! 0 */
-
- if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
- pending_autoraise_frame = dpyinfo->x_focus_frame;
- else
- pending_autoraise_frame = 0;
-
-#if USE_MAC_FONT_PANEL
- if (frame)
- mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
-#endif
- }
-
- x_frame_rehighlight (dpyinfo);
-}
-
-/* Handle FocusIn and FocusOut state changes for FRAME.
- If FRAME has focus and there exists more than one frame, puts
- a FOCUS_IN_EVENT into *BUFP. */
-
-static void
-mac_focus_changed (type, dpyinfo, frame, bufp)
- int type;
- struct mac_display_info *dpyinfo;
- struct frame *frame;
- struct input_event *bufp;
-{
- if (type == activeFlag)
- {
- if (dpyinfo->x_focus_event_frame != frame)
- {
- x_new_focus_frame (dpyinfo, frame);
- dpyinfo->x_focus_event_frame = frame;
-
- /* Don't stop displaying the initial startup message
- for a switch-frame event we don't need. */
- if (NILP (Vterminal_frame)
- && CONSP (Vframe_list)
- && !NILP (XCDR (Vframe_list)))
- {
- bufp->kind = FOCUS_IN_EVENT;
- XSETFRAME (bufp->frame_or_window, frame);
- }
- }
- }
- else
- {
- if (dpyinfo->x_focus_event_frame == frame)
- {
- dpyinfo->x_focus_event_frame = 0;
- x_new_focus_frame (dpyinfo, 0);
- }
- }
-}
-
-/* The focus may have changed. Figure out if it is a real focus change,
- by checking both FocusIn/Out and Enter/LeaveNotify events.
-
- Returns FOCUS_IN_EVENT event in *BUFP. */
-
-static void
-x_detect_focus_change (dpyinfo, event, bufp)
- struct mac_display_info *dpyinfo;
- const EventRecord *event;
- struct input_event *bufp;
-{
- struct frame *frame;
-
- frame = mac_window_to_frame ((WindowRef) event->message);
- if (! frame)
- return;
-
- /* On Mac, this is only called from focus events, so no switch needed. */
- mac_focus_changed ((event->modifiers & activeFlag),
- dpyinfo, frame, bufp);
-}
-
-
-/* Handle an event saying the mouse has moved out of an Emacs frame. */
-
-void
-x_mouse_leave (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
-}
-
-/* The focus has changed, or we have redirected a frame's focus to
- another frame (this happens when a frame uses a surrogate
- mini-buffer frame). Shift the highlight as appropriate.
-
- The FRAME argument doesn't necessarily have anything to do with which
- frame is being highlighted or un-highlighted; we only use it to find
- the appropriate X display info. */
-
-static void
-XTframe_rehighlight (frame)
- struct frame *frame;
-{
- x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
-}
-
-static void
-x_frame_rehighlight (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- struct frame *old_highlight = dpyinfo->x_highlight_frame;
-
- if (dpyinfo->x_focus_frame)
- {
- dpyinfo->x_highlight_frame
- = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
- ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
- : dpyinfo->x_focus_frame);
- if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
- {
- FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
- dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
- }
- }
- else
- dpyinfo->x_highlight_frame = 0;
-
- if (dpyinfo->x_highlight_frame != old_highlight)
- {
- if (old_highlight)
- frame_unhighlight (old_highlight);
- if (dpyinfo->x_highlight_frame)
- frame_highlight (dpyinfo->x_highlight_frame);
- }
-}
-
-
-
-/* Convert a keysym to its name. */
-
-char *
-x_get_keysym_name (keysym)
- int keysym;
-{
- char *value;
-
- BLOCK_INPUT;
-#if 0
- value = XKeysymToString (keysym);
-#else
- value = 0;
-#endif
- UNBLOCK_INPUT;
-
- return value;
-}
-
-
-
-/* Function to report a mouse movement to the mainstream Emacs code.
- The input handler calls this.
-
- We have received a mouse movement event, which is given in *event.
- If the mouse is over a different glyph than it was last time, tell
- the mainstream emacs code by setting mouse_moved. If not, ask for
- another motion event, so we can check again the next time it moves. */
-
-static Point last_mouse_motion_position;
-static Lisp_Object last_mouse_motion_frame;
-
-static int
-note_mouse_movement (frame, pos)
- FRAME_PTR frame;
- Point *pos;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
-#if TARGET_API_MAC_CARBON
- Rect r;
-#endif
-
- last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
- last_mouse_motion_position = *pos;
- XSETFRAME (last_mouse_motion_frame, frame);
-
- if (frame == dpyinfo->mouse_face_mouse_frame
-#if TARGET_API_MAC_CARBON
- && !PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r))
-#else
- && !PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect)
-#endif
- )
- {
- /* This case corresponds to LeaveNotify in X11. If we move
- outside the frame, then we're certainly no longer on any text
- in the frame. */
- clear_mouse_face (dpyinfo);
- dpyinfo->mouse_face_mouse_frame = 0;
- if (!dpyinfo->grabbed)
- FRAME_RIF (frame)->define_frame_cursor (frame,
- frame->output_data.mac->nontext_cursor);
- }
-
- /* Has the mouse moved off the glyph it was on at the last sighting? */
- if (frame != last_mouse_glyph_frame
- || !PtInRect (*pos, &last_mouse_glyph))
- {
- frame->mouse_moved = 1;
- last_mouse_scroll_bar = Qnil;
- note_mouse_highlight (frame, pos->h, pos->v);
- /* Remember which glyph we're now on. */
- remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
- last_mouse_glyph_frame = frame;
- return 1;
- }
-
- return 0;
-}
-
-
-/************************************************************************
- Mouse Face
- ************************************************************************/
-
-/* MAC TODO: This should be called from somewhere (or removed) ++KFS */
-
-static void
-redo_mouse_highlight ()
-{
- if (!NILP (last_mouse_motion_frame)
- && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
- note_mouse_highlight (XFRAME (last_mouse_motion_frame),
- last_mouse_motion_position.h,
- last_mouse_motion_position.v);
-}
-
-
-static struct frame *
-mac_focus_frame (dpyinfo)
- struct mac_display_info *dpyinfo;
-{
- if (dpyinfo->x_focus_frame)
- return dpyinfo->x_focus_frame;
- else
- /* Mac version may get events, such as a menu bar click, even when
- all the frames are invisible. In this case, we regard the
- event came to the selected frame. */
- return SELECTED_FRAME ();
-}
-
-
-/* Return the current position of the mouse.
- *FP should be a frame which indicates which display to ask about.
-
- If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
- and *PART to the frame, window, and scroll bar part that the mouse
- is over. Set *X and *Y to the portion and whole of the mouse's
- position on the scroll bar.
-
- If the mouse movement started elsewhere, set *FP to the frame the
- mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
- the mouse is over.
-
- Set *TIME to the server time-stamp for the time at which the mouse
- was at this position.
-
- Don't store anything if we don't have a valid set of values to report.
-
- This clears the mouse_moved flag, so we can wait for the next mouse
- movement. */
-
-static void
-XTmouse_position (fp, insist, bar_window, part, x, y, time)
- FRAME_PTR *fp;
- int insist;
- Lisp_Object *bar_window;
- enum scroll_bar_part *part;
- Lisp_Object *x, *y;
- unsigned long *time;
-{
- FRAME_PTR f1;
-
- BLOCK_INPUT;
-
- if (! NILP (last_mouse_scroll_bar) && insist == 0)
- x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
- else
- {
- Lisp_Object frame, tail;
-
- /* Clear the mouse-moved flag for every frame on this display. */
- FOR_EACH_FRAME (tail, frame)
- XFRAME (frame)->mouse_moved = 0;
-
- last_mouse_scroll_bar = Qnil;
-
- if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- f1 = last_mouse_frame;
- else
- f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
-
- if (f1)
- {
- /* Ok, we found a frame. Store all the values.
- last_mouse_glyph is a rectangle used to reduce the
- generation of mouse events. To not miss any motion
- events, we must divide the frame into rectangles of the
- size of the smallest character that could be displayed
- on it, i.e. into the same rectangles that matrices on
- the frame are divided into. */
- Point mouse_pos;
-
-#if TARGET_API_MAC_CARBON
- GetGlobalMouse (&mouse_pos);
- mouse_pos.h -= f1->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f1);
- mouse_pos.v -= f1->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f1);
-#else
- SetPortWindowPort (FRAME_MAC_WINDOW (f1));
- GetMouse (&mouse_pos);
-#endif
- remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
- &last_mouse_glyph);
- last_mouse_glyph_frame = f1;
-
- *bar_window = Qnil;
- *part = 0;
- *fp = f1;
- XSETINT (*x, mouse_pos.h);
- XSETINT (*y, mouse_pos.v);
- *time = last_mouse_movement_time;
- }
- }
-
- UNBLOCK_INPUT;
-}
-
-
-/************************************************************************
- Toolkit scroll bars
- ************************************************************************/
-
-#ifdef USE_TOOLKIT_SCROLL_BARS
-
-static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
-static OSStatus install_scroll_bar_timer P_ ((void));
-static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
-static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
-static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
- struct input_event *));
-static OSStatus get_control_part_bounds P_ ((ControlRef, ControlPartCode,
- Rect *));
-static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
- ControlPartCode, Point,
- struct input_event *));
-static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
- struct input_event *));
-static void x_scroll_bar_handle_drag P_ ((WindowRef, struct scroll_bar *,
- Point, struct input_event *));
-static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
- int, int, int));
-
-/* Last scroll bar part sent in x_scroll_bar_handle_*. */
-
-static int last_scroll_bar_part;
-
-static EventLoopTimerRef scroll_bar_timer;
-
-static int scroll_bar_timer_event_posted_p;
-
-#define SCROLL_BAR_FIRST_DELAY 0.5
-#define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
-
-static pascal void
-scroll_bar_timer_callback (timer, data)
- EventLoopTimerRef timer;
- void *data;
-{
- OSStatus err;
-
- err = mac_post_mouse_moved_event ();
- if (err == noErr)
- scroll_bar_timer_event_posted_p = 1;
-}
-
-static OSStatus
-install_scroll_bar_timer ()
-{
- static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
-
- if (scroll_bar_timer_callbackUPP == NULL)
- scroll_bar_timer_callbackUPP =
- NewEventLoopTimerUPP (scroll_bar_timer_callback);
-
- if (scroll_bar_timer == NULL)
- /* Mac OS X and CarbonLib 1.5 and later allow us to specify
- kEventDurationForever as delays. */
- return
- InstallEventLoopTimer (GetCurrentEventLoop (),
- kEventDurationForever, kEventDurationForever,
- scroll_bar_timer_callbackUPP, NULL,
- &scroll_bar_timer);
-}
-
-static OSStatus
-set_scroll_bar_timer (delay)
- EventTimerInterval delay;
-{
- if (scroll_bar_timer == NULL)
- install_scroll_bar_timer ();
-
- scroll_bar_timer_event_posted_p = 0;
-
- return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
-}
-
-static int
-control_part_code_to_scroll_bar_part (part_code)
- ControlPartCode part_code;
-{
- switch (part_code)
- {
- case kControlUpButtonPart: return scroll_bar_up_arrow;
- case kControlDownButtonPart: return scroll_bar_down_arrow;
- case kControlPageUpPart: return scroll_bar_above_handle;
- case kControlPageDownPart: return scroll_bar_below_handle;
- case kControlIndicatorPart: return scroll_bar_handle;
- }
-
- return -1;
-}
-
-static void
-construct_scroll_bar_click (bar, part, bufp)
- struct scroll_bar *bar;
- int part;
- struct input_event *bufp;
-{
- bufp->kind = SCROLL_BAR_CLICK_EVENT;
- bufp->frame_or_window = bar->window;
- bufp->arg = Qnil;
- bufp->part = part;
- bufp->code = 0;
- XSETINT (bufp->x, 0);
- XSETINT (bufp->y, 0);
- bufp->modifiers = 0;
-}
-
-static OSStatus
-get_control_part_bounds (ch, part_code, rect)
- ControlRef ch;
- ControlPartCode part_code;
- Rect *rect;
-{
- RgnHandle region = NewRgn ();
- OSStatus err;
-
- err = GetControlRegion (ch, part_code, region);
- if (err == noErr)
- GetRegionBounds (region, rect);
- DisposeRgn (region);
-
- return err;
-}
-
-static void
-x_scroll_bar_handle_press (bar, part_code, mouse_pos, bufp)
- struct scroll_bar *bar;
- ControlPartCode part_code;
- Point mouse_pos;
- struct input_event *bufp;
-{
- int part = control_part_code_to_scroll_bar_part (part_code);
-
- if (part < 0)
- return;
-
- if (part != scroll_bar_handle)
- {
- construct_scroll_bar_click (bar, part, bufp);
- HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
- set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
- bar->dragging = Qnil;
- }
- else
- {
- Rect r;
-
- get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
- kControlIndicatorPart, &r);
- XSETINT (bar->dragging, - (mouse_pos.v - r.top) - 1);
- }
-
- last_scroll_bar_part = part;
- tracked_scroll_bar = bar;
-}
-
-static void
-x_scroll_bar_handle_release (bar, bufp)
- struct scroll_bar *bar;
- struct input_event *bufp;
-{
- if (last_scroll_bar_part != scroll_bar_handle
- || (INTEGERP (bar->dragging) && XINT (bar->dragging) >= 0))
- construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
-
- HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
- set_scroll_bar_timer (kEventDurationForever);
-
- last_scroll_bar_part = -1;
- bar->dragging = Qnil;
- tracked_scroll_bar = NULL;
-}
-
-static void
-x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
- WindowRef win;
- struct scroll_bar *bar;
- Point mouse_pos;
- struct input_event *bufp;
-{
- ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
-
- if (last_scroll_bar_part == scroll_bar_handle)
- {
- int top, top_range;
- Rect r;
-
- get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
- kControlIndicatorPart, &r);
-
- if (INTEGERP (bar->dragging) && XINT (bar->dragging) < 0)
- XSETINT (bar->dragging, - (XINT (bar->dragging) + 1));
-
- top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
- top_range = XINT (bar->track_height) - XINT (bar->min_handle);
-
- if (top < 0)
- top = 0;
- if (top > top_range)
- top = top_range;
-
- construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
- XSETINT (bufp->x, top);
- XSETINT (bufp->y, top_range);
- }
- else
- {
- ControlPartCode part_code;
- int unhilite_p = 0, part;
-
- if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
- unhilite_p = 1;
- else
- {
- part = control_part_code_to_scroll_bar_part (part_code);
-
- switch (last_scroll_bar_part)
- {
- case scroll_bar_above_handle:
- case scroll_bar_below_handle:
- if (part != scroll_bar_above_handle
- && part != scroll_bar_below_handle)
- unhilite_p = 1;
- break;
-
- case scroll_bar_up_arrow:
- case scroll_bar_down_arrow:
- if (part != scroll_bar_up_arrow
- && part != scroll_bar_down_arrow)
- unhilite_p = 1;
- break;
- }
- }
-
- if (unhilite_p)
- HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
- else if (part != last_scroll_bar_part
- || scroll_bar_timer_event_posted_p)
- {
- construct_scroll_bar_click (bar, part, bufp);
- last_scroll_bar_part = part;
- HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
- set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
- }
- }
-}
-
-/* Set the thumb size and position of scroll bar BAR. We are currently
- displaying PORTION out of a whole WHOLE, and our position POSITION. */
-
-static void
-x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
- struct scroll_bar *bar;
- int portion, position, whole;
-{
- ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
- int value, viewsize, maximum;
-
- if (XINT (bar->track_height) == 0)
- return;
-
- if (whole <= portion)
- value = 0, viewsize = 1, maximum = 0;
- else
- {
- float scale;
-
- maximum = XINT (bar->track_height) - XINT (bar->min_handle);
- scale = (float) maximum / (whole - portion);
- value = position * scale + 0.5f;
- viewsize = (int) (portion * scale + 0.5f) + XINT (bar->min_handle);
- }
-
- BLOCK_INPUT;
-
- if (GetControlViewSize (ch) != viewsize
- || GetControl32BitValue (ch) != value
- || GetControl32BitMaximum (ch) != maximum)
- {
- /* Temporarily hide the scroll bar to avoid multiple redraws. */
- SetControlVisibility (ch, false, false);
-
- SetControl32BitMaximum (ch, maximum);
- SetControl32BitValue (ch, value);
- SetControlViewSize (ch, viewsize);
-
- SetControlVisibility (ch, true, true);
- }
-
- UNBLOCK_INPUT;
-}
-
-#endif /* USE_TOOLKIT_SCROLL_BARS */
-
-
-
-/************************************************************************
- Scroll bars, general
- ************************************************************************/
-
-/* Create a scroll bar and return the scroll bar vector for it. W is
- the Emacs window on which to create the scroll bar. TOP, LEFT,
- WIDTH and HEIGHT are the pixel coordinates and dimensions of the
- scroll bar. */
-
-static struct scroll_bar *
-x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
- struct window *w;
- int top, left, width, height, disp_top, disp_height;
-{
- struct frame *f = XFRAME (w->frame);
- struct scroll_bar *bar
- = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
- Rect r;
- ControlRef ch;
-
- BLOCK_INPUT;
-
- r.left = left;
- r.top = disp_top;
- r.right = left + width;
- r.bottom = disp_top + disp_height;
-
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
-#if TARGET_API_MAC_CARBON
- ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
-#ifdef USE_TOOLKIT_SCROLL_BARS
- false,
-#else
- width < disp_height,
-#endif
- 0, 0, 0, kControlScrollBarProc, (long) bar);
-#else
- ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
- 0, 0, 0, scrollBarProc, (long) bar);
-#endif
- SET_SCROLL_BAR_CONTROL_REF (bar, ch);
-
- XSETWINDOW (bar->window, w);
- XSETINT (bar->top, top);
- XSETINT (bar->left, left);
- XSETINT (bar->width, width);
- XSETINT (bar->height, height);
- XSETINT (bar->start, 0);
- XSETINT (bar->end, 0);
- bar->dragging = Qnil;
-#ifdef MAC_OSX
- bar->fringe_extended_p = Qnil;
-#endif
- bar->redraw_needed_p = Qnil;
-#ifdef USE_TOOLKIT_SCROLL_BARS
- bar->track_top = Qnil;
- bar->track_height = Qnil;
- bar->min_handle = Qnil;
-#endif
-
- /* Add bar to its frame's list of scroll bars. */
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
- if (!NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
-
- UNBLOCK_INPUT;
- return bar;
-}
-
-
-/* Draw BAR's handle in the proper position.
-
- If the handle is already drawn from START to END, don't bother
- redrawing it, unless REBUILD is non-zero; in that case, always
- redraw it. (REBUILD is handy for drawing the handle after expose
- events.)
-
- Normally, we want to constrain the start and end of the handle to
- fit inside its rectangle, but if the user is dragging the scroll
- bar handle, we want to let them drag it down all the way, so that
- the bar's top is as far down as it goes; otherwise, there's no way
- to move to the very end of the buffer. */
-
-#ifndef USE_TOOLKIT_SCROLL_BARS
-
-static void
-x_scroll_bar_set_handle (bar, start, end, rebuild)
- struct scroll_bar *bar;
- int start, end;
- int rebuild;
-{
- int dragging = ! NILP (bar->dragging);
- ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
- int length = end - start;
-
- /* If the display is already accurate, do nothing. */
- if (! rebuild
- && start == XINT (bar->start)
- && end == XINT (bar->end))
- return;
-
- BLOCK_INPUT;
-
- /* Make sure the values are reasonable, and try to preserve the
- distance between start and end. */
- if (start < 0)
- start = 0;
- else if (start > top_range)
- start = top_range;
- end = start + length;
-
- if (end < start)
- end = start;
- else if (end > top_range && ! dragging)
- end = top_range;
-
- /* Store the adjusted setting in the scroll bar. */
- XSETINT (bar->start, start);
- XSETINT (bar->end, end);
-
- /* Clip the end position, just for display. */
- if (end > top_range)
- end = top_range;
-
- /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
- top positions, to make sure the handle is always at least that
- many pixels tall. */
- end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
-
- SetControlMinimum (ch, 0);
- /* Don't inadvertently activate deactivated scroll bars */
- if (GetControlMaximum (ch) != -1)
- SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
- - (end - start));
- SetControlValue (ch, start);
-#if TARGET_API_MAC_CARBON
- SetControlViewSize (ch, end - start);
-#endif
-
- UNBLOCK_INPUT;
-}
-
-#endif /* !USE_TOOLKIT_SCROLL_BARS */
-
-/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
- nil. */
-
-static void
-x_scroll_bar_remove (bar)
- struct scroll_bar *bar;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-
- BLOCK_INPUT;
-
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- /* Destroy the Mac scroll bar control */
- DisposeControl (SCROLL_BAR_CONTROL_REF (bar));
-
- /* Disassociate this scroll bar from its window. */
- XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
-
- UNBLOCK_INPUT;
-}
-
-
-/* Set the handle of the vertical scroll bar for WINDOW to indicate
- that we are displaying PORTION characters out of a total of WHOLE
- characters, starting at POSITION. If WINDOW has no scroll bar,
- create one. */
-
-static void
-XTset_vertical_scroll_bar (w, portion, whole, position)
- struct window *w;
- int portion, whole, position;
-{
- struct frame *f = XFRAME (w->frame);
- struct scroll_bar *bar;
- int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
- int window_y, window_height;
-#ifdef MAC_OSX
- int fringe_extended_p;
-#endif
-
- /* Get window dimensions. */
- window_box (w, -1, 0, &window_y, 0, &window_height);
- top = window_y;
- width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
- height = window_height;
-
- /* Compute the left edge of the scroll bar area. */
- left = WINDOW_SCROLL_BAR_AREA_X (w);
-
- /* Compute the width of the scroll bar which might be less than
- the width of the area reserved for the scroll bar. */
- if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
- sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
- else
- sb_width = width;
-
- /* Compute the left edge of the scroll bar. */
- if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
- sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
- else
- sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
-
- /* Adjustments according to Inside Macintosh to make it look nice */
- disp_top = top;
- disp_height = height;
-#ifdef MAC_OS8
- if (disp_top == 0)
- {
- disp_top = -1;
- disp_height++;
- }
- else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
- {
- disp_top++;
- disp_height--;
- }
-
- if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
- sb_left++;
-#endif
-
-#ifdef MAC_OSX
- if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
- fringe_extended_p = (WINDOW_LEFTMOST_P (w)
- && WINDOW_LEFT_FRINGE_WIDTH (w)
- && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
- || WINDOW_LEFT_MARGIN_COLS (w) == 0));
- else
- fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
- && WINDOW_RIGHT_FRINGE_WIDTH (w)
- && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
- || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
-#endif
-
- /* Does the scroll bar exist yet? */
- if (NILP (w->vertical_scroll_bar))
- {
- BLOCK_INPUT;
-#ifdef MAC_OSX
- if (fringe_extended_p)
- mac_clear_area (f, sb_left, top, sb_width, height);
- else
-#endif
- mac_clear_area (f, left, top, width, height);
- UNBLOCK_INPUT;
- bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
- disp_height);
- XSETVECTOR (w->vertical_scroll_bar, bar);
- }
- else
- {
- /* It may just need to be moved and resized. */
- ControlRef ch;
-
- bar = XSCROLL_BAR (w->vertical_scroll_bar);
- ch = SCROLL_BAR_CONTROL_REF (bar);
-
- BLOCK_INPUT;
-
- /* If already correctly positioned, do nothing. */
- if (XINT (bar->left) == sb_left
- && XINT (bar->top) == top
- && XINT (bar->width) == sb_width
- && XINT (bar->height) == height
-#ifdef MAC_OSX
- && !NILP (bar->fringe_extended_p) == fringe_extended_p
-#endif
- )
- {
- if (!NILP (bar->redraw_needed_p))
- {
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- Draw1Control (SCROLL_BAR_CONTROL_REF (bar));
- }
- }
- else
- {
- /* Since toolkit scroll bars are smaller than the space reserved
- for them on the frame, we have to clear "under" them. */
-#ifdef MAC_OSX
- if (fringe_extended_p)
- mac_clear_area (f, sb_left, top, sb_width, height);
- else
-#endif
- mac_clear_area (f, left, top, width, height);
-
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- HideControl (ch);
- MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
- SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
- disp_height);
-#ifndef USE_TOOLKIT_SCROLL_BARS
- if (sb_width < disp_height)
- ShowControl (ch);
-#endif
-
- /* Remember new settings. */
- XSETINT (bar->left, sb_left);
- XSETINT (bar->top, top);
- XSETINT (bar->width, sb_width);
- XSETINT (bar->height, height);
-#ifdef USE_TOOLKIT_SCROLL_BARS
- bar->track_top = Qnil;
- bar->track_height = Qnil;
- bar->min_handle = Qnil;
-#endif
- }
-
- UNBLOCK_INPUT;
- }
-
-#ifdef MAC_OSX
- bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
-#endif
-
- bar->redraw_needed_p = Qnil;
-
-#ifdef USE_TOOLKIT_SCROLL_BARS
- if (NILP (bar->track_top))
- {
- if (sb_width >= disp_height
-#ifdef MAC_OSX
- || sb_width < MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
-#endif
- )
- {
- XSETINT (bar->track_top, 0);
- XSETINT (bar->track_height, 0);
- XSETINT (bar->min_handle, 0);
- }
- else
- {
- ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
- Rect r0, r1;
-
- BLOCK_INPUT;
-
- SetControl32BitMinimum (ch, 0);
- SetControl32BitMaximum (ch, 1 << 30);
- SetControlViewSize (ch, 1);
-
- /* Move the scroll bar thumb to the top. */
- SetControl32BitValue (ch, 0);
- get_control_part_bounds (ch, kControlIndicatorPart, &r0);
-
- /* Move the scroll bar thumb to the bottom. */
- SetControl32BitValue (ch, 1 << 30);
- get_control_part_bounds (ch, kControlIndicatorPart, &r1);
-
- UnionRect (&r0, &r1, &r0);
- XSETINT (bar->track_top, r0.top);
- XSETINT (bar->track_height, r0.bottom - r0.top);
- XSETINT (bar->min_handle, r1.bottom - r1.top);
-
- /* Don't show the scroll bar if its height is not enough to
- display the scroll bar thumb. */
- if (r0.bottom - r0.top > 0)
- ShowControl (ch);
-
- UNBLOCK_INPUT;
- }
- }
-
- x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
-#else /* not USE_TOOLKIT_SCROLL_BARS */
- /* Set the scroll bar's current state, unless we're currently being
- dragged. */
- if (NILP (bar->dragging))
- {
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
-
- if (whole == 0)
- x_scroll_bar_set_handle (bar, 0, top_range, 0);
- else
- {
- int start = ((double) position * top_range) / whole;
- int end = ((double) (position + portion) * top_range) / whole;
- x_scroll_bar_set_handle (bar, start, end, 0);
- }
- }
-#endif /* not USE_TOOLKIT_SCROLL_BARS */
-}
-
-
-/* The following three hooks are used when we're doing a thorough
- redisplay of the frame. We don't explicitly know which scroll bars
- are going to be deleted, because keeping track of when windows go
- away is a real pain - "Can you say set-window-configuration, boys
- and girls?" Instead, we just assert at the beginning of redisplay
- that *all* scroll bars are to be removed, and then save a scroll bar
- from the fiery pit when we actually redisplay its window. */
-
-/* Arrange for all scroll bars on FRAME to be removed at the next call
- to `*judge_scroll_bars_hook'. A scroll bar may be spared if
- `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
-
-static void
-XTcondemn_scroll_bars (frame)
- FRAME_PTR frame;
-{
- /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
- while (! NILP (FRAME_SCROLL_BARS (frame)))
- {
- Lisp_Object bar;
- bar = FRAME_SCROLL_BARS (frame);
- FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
- XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
- XSCROLL_BAR (bar)->prev = Qnil;
- if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
- XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
- FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
- }
-}
-
-
-/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
- Note that WINDOW isn't necessarily condemned at all. */
-
-static void
-XTredeem_scroll_bar (window)
- struct window *window;
-{
- struct scroll_bar *bar;
- struct frame *f;
-
- /* We can't redeem this window's scroll bar if it doesn't have one. */
- if (NILP (window->vertical_scroll_bar))
- abort ();
-
- bar = XSCROLL_BAR (window->vertical_scroll_bar);
-
- /* Unlink it from the condemned list. */
- f = XFRAME (WINDOW_FRAME (window));
- if (NILP (bar->prev))
- {
- /* If the prev pointer is nil, it must be the first in one of
- the lists. */
- if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
- /* It's not condemned. Everything's fine. */
- return;
- else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
- window->vertical_scroll_bar))
- FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
- else
- /* If its prev pointer is nil, it must be at the front of
- one or the other! */
- abort ();
- }
- else
- XSCROLL_BAR (bar->prev)->next = bar->next;
-
- if (! NILP (bar->next))
- XSCROLL_BAR (bar->next)->prev = bar->prev;
-
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
-}
-
-/* Remove all scroll bars on FRAME that haven't been saved since the
- last call to `*condemn_scroll_bars_hook'. */
-
-static void
-XTjudge_scroll_bars (f)
- FRAME_PTR f;
-{
- Lisp_Object bar, next;
-
- bar = FRAME_CONDEMNED_SCROLL_BARS (f);
-
- /* Clear out the condemned list now so we won't try to process any
- more events on the hapless scroll bars. */
- FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
-
- for (; ! NILP (bar); bar = next)
- {
- struct scroll_bar *b = XSCROLL_BAR (bar);
-
- x_scroll_bar_remove (b);
-
- next = b->next;
- b->next = b->prev = Qnil;
- }
-
- /* Now there should be no references to the condemned scroll bars,
- and they should get garbage-collected. */
-}
-
-
-/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
- is set to something other than NO_EVENT, it is enqueued.
-
- This may be called from a signal handler, so we have to ignore GC
- mark bits. */
-
-static void
-x_scroll_bar_handle_click (bar, part_code, er, bufp)
- struct scroll_bar *bar;
- ControlPartCode part_code;
- const EventRecord *er;
- struct input_event *bufp;
-{
- int win_y, top_range;
-
- if (! WINDOWP (bar->window))
- abort ();
-
- bufp->kind = SCROLL_BAR_CLICK_EVENT;
- bufp->frame_or_window = bar->window;
- bufp->arg = Qnil;
-
- bar->dragging = Qnil;
-
- switch (part_code)
- {
- case kControlUpButtonPart:
- bufp->part = scroll_bar_up_arrow;
- break;
- case kControlDownButtonPart:
- bufp->part = scroll_bar_down_arrow;
- break;
- case kControlPageUpPart:
- bufp->part = scroll_bar_above_handle;
- break;
- case kControlPageDownPart:
- bufp->part = scroll_bar_below_handle;
- break;
-#if TARGET_API_MAC_CARBON
- default:
-#else
- case kControlIndicatorPart:
-#endif
- if (er->what == mouseDown)
- bar->dragging = make_number (0);
- XSETVECTOR (last_mouse_scroll_bar, bar);
- bufp->part = scroll_bar_handle;
- break;
- }
-
- win_y = XINT (bufp->y) - XINT (bar->top);
- top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
-
- win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
-
- win_y -= 24;
-
- if (! NILP (bar->dragging))
- win_y -= XINT (bar->dragging);
-
- if (win_y < 0)
- win_y = 0;
- if (win_y > top_range)
- win_y = top_range;
-
- XSETINT (bufp->x, win_y);
- XSETINT (bufp->y, top_range);
-}
-
-#ifndef USE_TOOLKIT_SCROLL_BARS
-
-/* Handle some mouse motion while someone is dragging the scroll bar.
-
- This may be called from a signal handler, so we have to ignore GC
- mark bits. */
-
-static void
-x_scroll_bar_note_movement (bar, y_pos, t)
- struct scroll_bar *bar;
- int y_pos;
- Time t;
-{
- FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
-
- last_mouse_movement_time = t;
-
- f->mouse_moved = 1;
- XSETVECTOR (last_mouse_scroll_bar, bar);
-
- /* If we're dragging the bar, display it. */
- if (! NILP (bar->dragging))
- {
- /* Where should the handle be now? */
- int new_start = y_pos - 24;
-
- if (new_start != XINT (bar->start))
- {
- int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
-
- x_scroll_bar_set_handle (bar, new_start, new_end, 0);
- }
- }
-}
-
-#endif /* !USE_TOOLKIT_SCROLL_BARS */
-
-/* Return information to the user about the current position of the mouse
- on the scroll bar. */
-
-static void
-x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
- FRAME_PTR *fp;
- Lisp_Object *bar_window;
- enum scroll_bar_part *part;
- Lisp_Object *x, *y;
- unsigned long *time;
-{
- struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
- ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
-#if TARGET_API_MAC_CARBON
- WindowRef wp = GetControlOwner (ch);
-#else
- WindowRef wp = (*ch)->contrlOwner;
-#endif
- Point mouse_pos;
- struct frame *f = mac_window_to_frame (wp);
- int win_y, top_range;
-
-#if TARGET_API_MAC_CARBON
- GetGlobalMouse (&mouse_pos);
- mouse_pos.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
- mouse_pos.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
-#else
- SetPortWindowPort (wp);
- GetMouse (&mouse_pos);
-#endif
-
- win_y = mouse_pos.v - XINT (bar->top);
- top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
-
- win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
-
- win_y -= 24;
-
- if (! NILP (bar->dragging))
- win_y -= XINT (bar->dragging);
-
- if (win_y < 0)
- win_y = 0;
- if (win_y > top_range)
- win_y = top_range;
-
- *fp = f;
- *bar_window = bar->window;
-
- if (! NILP (bar->dragging))
- *part = scroll_bar_handle;
- else if (win_y < XINT (bar->start))
- *part = scroll_bar_above_handle;
- else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
- *part = scroll_bar_handle;
- else
- *part = scroll_bar_below_handle;
-
- XSETINT (*x, win_y);
- XSETINT (*y, top_range);
-
- f->mouse_moved = 0;
- last_mouse_scroll_bar = Qnil;
-
- *time = last_mouse_movement_time;
-}
-
-
-/* The screen has been cleared so we may have changed foreground or
- background colors, and the scroll bars may need to be redrawn.
- Clear out the scroll bars, and ask for expose events, so we can
- redraw them. */
-
-void
-x_scroll_bar_clear (f)
- FRAME_PTR f;
-{
- Lisp_Object bar;
-
- /* We can have scroll bars even if this is 0,
- if we just turned off scroll bar mode.
- But in that case we should not clear them. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
- bar = XSCROLL_BAR (bar)->next)
- XSCROLL_BAR (bar)->redraw_needed_p = Qt;
-}
-
-
-/***********************************************************************
- Tool-bars
- ***********************************************************************/
-#if USE_MAC_TOOLBAR
-
-/* In identifiers such as function/variable names, Emacs tool bar is
- referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
-
-#define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
-#define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
-
-#define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
-#define TOOLBAR_ITEM_COMMAND_ID_P(id) \
- (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
-#define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
- ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
-#define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
- ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
-
-static int mac_event_to_emacs_modifiers P_ ((EventRef));
-static void mac_handle_origin_change P_ ((struct frame *));
-static OSStatus mac_handle_toolbar_command_event P_ ((EventHandlerCallRef,
- EventRef, void *));
-
-static void
-mac_move_window_with_gravity (f, win_gravity, left, top)
- struct frame *f;
- int win_gravity;
- short left, top;
-{
- Rect inner, outer;
-
- mac_get_window_bounds (f, &inner, &outer);
-
- switch (win_gravity)
- {
- case NorthWestGravity:
- case WestGravity:
- case SouthWestGravity:
- left += inner.left - outer.left;
- break;
-
- case NorthGravity:
- case CenterGravity:
- case SouthGravity:
- left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
- break;
-
- case NorthEastGravity:
- case EastGravity:
- case SouthEastGravity:
- left += inner.right - outer.right;
- break;
- }
-
- switch (win_gravity)
- {
- case NorthWestGravity:
- case NorthGravity:
- case NorthEastGravity:
- top += inner.top - outer.top;
- break;
-
- case WestGravity:
- case CenterGravity:
- case EastGravity:
- top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
- break;
-
- case SouthWestGravity:
- case SouthGravity:
- case SouthEastGravity:
- top += inner.bottom - outer.bottom;
- break;
- }
-
- MoveWindow (FRAME_MAC_WINDOW (f), left, top, false);
-}
-
-static void
-mac_get_window_origin_with_gravity (f, win_gravity, left, top)
- struct frame *f;
- int win_gravity;
- short *left, *top;
-{
- Rect inner, outer;
-
- mac_get_window_bounds (f, &inner, &outer);
-
- switch (win_gravity)
- {
- case NorthWestGravity:
- case WestGravity:
- case SouthWestGravity:
- *left = outer.left;
- break;
-
- case NorthGravity:
- case CenterGravity:
- case SouthGravity:
- *left = outer.left + ((outer.right - outer.left)
- - (inner.right - inner.left)) / 2;
- break;
-
- case NorthEastGravity:
- case EastGravity:
- case SouthEastGravity:
- *left = outer.right - (inner.right - inner.left);
- break;
- }
-
- switch (win_gravity)
- {
- case NorthWestGravity:
- case NorthGravity:
- case NorthEastGravity:
- *top = outer.top;
- break;
-
- case WestGravity:
- case CenterGravity:
- case EastGravity:
- *top = outer.top + ((outer.bottom - outer.top)
- - (inner.bottom - inner.top)) / 2;
- break;
-
- case SouthWestGravity:
- case SouthGravity:
- case SouthEastGravity:
- *top = outer.bottom - (inner.bottom - inner.top);
- break;
- }
-}
-
-static OSStatus
-mac_handle_toolbar_event (next_handler, event, data)
- EventHandlerCallRef next_handler;
- EventRef event;
- void *data;
-{
- OSStatus err, result = eventNotHandledErr;
-
- switch (GetEventKind (event))
- {
- case kEventToolbarGetDefaultIdentifiers:
- result = noErr;
- break;
-
- case kEventToolbarGetAllowedIdentifiers:
- {
- CFMutableArrayRef array;
-
- GetEventParameter (event, kEventParamMutableArray,
- typeCFMutableArrayRef, NULL,
- sizeof (CFMutableArrayRef), NULL, &array);
- CFArrayAppendValue (array, TOOLBAR_ICON_ITEM_IDENTIFIER);
- result = noErr;
- }
- break;
-
- case kEventToolbarCreateItemWithIdentifier:
- {
- CFStringRef identifier;
- HIToolbarItemRef item = NULL;
-
- GetEventParameter (event, kEventParamToolbarItemIdentifier,
- typeCFStringRef, NULL,
- sizeof (CFStringRef), NULL, &identifier);
-
- if (CFStringCompare (identifier, TOOLBAR_ICON_ITEM_IDENTIFIER, 0)
- == kCFCompareEqualTo)
- HIToolbarItemCreate (identifier,
- kHIToolbarItemAllowDuplicates
- | kHIToolbarItemCantBeRemoved, &item);
-
- if (item)
- {
- SetEventParameter (event, kEventParamToolbarItem,
- typeHIToolbarItemRef,
- sizeof (HIToolbarItemRef), &item);
- result = noErr;
- }
- }
- break;
-
- default:
- abort ();
- }
-
- return result;
-}
-
-static CGImageRef
-mac_image_spec_to_cg_image (f, image)
- struct frame *f;
- Lisp_Object image;
-{
- if (!valid_image_p (image))
- return NULL;
- else
- {
- int img_id = lookup_image (f, image);
- struct image *img = IMAGE_FROM_ID (f, img_id);
-
- prepare_image_for_display (f, img);
-
- return img->data.ptr_val;
- }
-}
-
-/* Create a tool bar for frame F. */
-
-static OSStatus
-mac_create_frame_tool_bar (f)
- FRAME_PTR f;
-{
- OSStatus err;
- HIToolbarRef toolbar;
-
- err = HIToolbarCreate (TOOLBAR_IDENTIFIER, kHIToolbarNoAttributes,
- &toolbar);
- if (err == noErr)
- {
- static const EventTypeSpec specs[] =
- {{kEventClassToolbar, kEventToolbarGetDefaultIdentifiers},
- {kEventClassToolbar, kEventToolbarGetAllowedIdentifiers},
- {kEventClassToolbar, kEventToolbarCreateItemWithIdentifier}};
-
- err = InstallEventHandler (HIObjectGetEventTarget (toolbar),
- mac_handle_toolbar_event,
- GetEventTypeCount (specs), specs,
- f, NULL);
- }
-
- if (err == noErr)
- err = HIToolbarSetDisplayMode (toolbar, kHIToolbarDisplayModeIconOnly);
- if (err == noErr)
- {
- static const EventTypeSpec specs[] =
- {{kEventClassCommand, kEventCommandProcess}};
-
- err = InstallWindowEventHandler (FRAME_MAC_WINDOW (f),
- mac_handle_toolbar_command_event,
- GetEventTypeCount (specs),
- specs, f, NULL);
- }
- if (err == noErr)
- err = SetWindowToolbar (FRAME_MAC_WINDOW (f), toolbar);
-
- if (toolbar)
- CFRelease (toolbar);
-
- return err;
-}
-
-/* Update the tool bar for frame F. Add new buttons and remove old. */
-
-void
-update_frame_tool_bar (f)
- FRAME_PTR f;
-{
- HIToolbarRef toolbar = NULL;
- short left, top;
- CFArrayRef old_items = NULL;
- CFIndex old_count;
- int i, pos, win_gravity = f->output_data.mac->toolbar_win_gravity;
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- BLOCK_INPUT;
-
- GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
- if (toolbar == NULL)
- {
- mac_create_frame_tool_bar (f);
- GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
- if (toolbar == NULL)
- goto out;
- if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
- mac_get_window_origin_with_gravity (f, win_gravity, &left, &top);
- }
-
- HIToolbarCopyItems (toolbar, &old_items);
- if (old_items == NULL)
- goto out;
-
- old_count = CFArrayGetCount (old_items);
- pos = 0;
- for (i = 0; i < f->n_tool_bar_items; ++i)
- {
-#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
-
- int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
- int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
- int idx;
- Lisp_Object image;
- CGImageRef cg_image;
- CFStringRef label;
- HIToolbarItemRef item;
-
- /* If image is a vector, choose the image according to the
- button state. */
- image = PROP (TOOL_BAR_ITEM_IMAGES);
- if (VECTORP (image))
- {
- if (enabled_p)
- idx = (selected_p
- ? TOOL_BAR_IMAGE_ENABLED_SELECTED
- : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
- else
- idx = (selected_p
- ? TOOL_BAR_IMAGE_DISABLED_SELECTED
- : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
-
- xassert (ASIZE (image) >= idx);
- image = AREF (image, idx);
- }
- else
- idx = -1;
-
- cg_image = mac_image_spec_to_cg_image (f, image);
- /* Ignore invalid image specifications. */
- if (cg_image == NULL)
- continue;
-
- label = cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION));
- if (label == NULL)
- label = CFSTR ("");
-
- if (pos < old_count)
- {
- CGImageRef old_cg_image = NULL;
- CFStringRef old_label = NULL;
- Boolean old_enabled_p;
-
- item = (HIToolbarItemRef) CFArrayGetValueAtIndex (old_items, pos);
-
- HIToolbarItemCopyImage (item, &old_cg_image);
- if (cg_image != old_cg_image)
- HIToolbarItemSetImage (item, cg_image);
- CGImageRelease (old_cg_image);
-
- HIToolbarItemCopyLabel (item, &old_label);
- if (CFStringCompare (label, old_label, 0) != kCFCompareEqualTo)
- HIToolbarItemSetLabel (item, label);
- CFRelease (old_label);
-
- old_enabled_p = HIToolbarItemIsEnabled (item);
- if ((enabled_p || idx >= 0) != old_enabled_p)
- HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
- }
- else
- {
- item = NULL;
- HIToolbarCreateItemWithIdentifier (toolbar,
- TOOLBAR_ICON_ITEM_IDENTIFIER,
- NULL, &item);
- if (item)
- {
- HIToolbarItemSetImage (item, cg_image);
- HIToolbarItemSetLabel (item, label);
- HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
- HIToolbarAppendItem (toolbar, item);
- CFRelease (item);
- }
- }
-
- CFRelease (label);
- if (item)
- {
- HIToolbarItemSetCommandID (item, TOOLBAR_ITEM_MAKE_COMMAND_ID (i));
- pos++;
- }
- }
-
- CFRelease (old_items);
-
- while (pos < old_count)
- HIToolbarRemoveItemAtIndex (toolbar, --old_count);
-
- ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), true,
- !win_gravity && f == mac_focus_frame (dpyinfo));
- /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
- toolbar visibility change. */
- mac_handle_origin_change (f);
- if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
- {
- mac_move_window_with_gravity (f, win_gravity, left, top);
- /* If the title bar is completely outside the screen, adjust the
- position. */
- ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
- kWindowConstrainMoveRegardlessOfFit
- | kWindowConstrainAllowPartial, NULL, NULL);
- f->output_data.mac->toolbar_win_gravity = 0;
- }
-
- out:
- UNBLOCK_INPUT;
-}
-
-/* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
- doesn't deallocate the resources. */
-
-void
-free_frame_tool_bar (f)
- FRAME_PTR f;
-{
- if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f)))
- {
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- BLOCK_INPUT;
- ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), false,
- (NILP (Fsymbol_value
- (intern ("frame-notice-user-settings")))
- && f == mac_focus_frame (dpyinfo)));
- /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
- on toolbar visibility change. */
- mac_handle_origin_change (f);
- UNBLOCK_INPUT;
- }
-}
-
-static void
-mac_tool_bar_note_mouse_movement (f, event)
- struct frame *f;
- EventRef event;
-{
- OSStatus err;
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- int mouse_down_p;
- HIViewRef item_view;
- UInt32 command_id;
-
- mouse_down_p = (dpyinfo->grabbed
- && f == last_mouse_frame
- && FRAME_LIVE_P (f));
- if (mouse_down_p)
- return;
-
- err = HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
- event, &item_view);
- /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
- toolbar item view seems to have the same command ID with that of
- the toolbar item. */
- if (err == noErr)
- err = GetControlCommandID (item_view, &command_id);
- if (err == noErr && TOOLBAR_ITEM_COMMAND_ID_P (command_id))
- {
- int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id);
-
- if (i < f->n_tool_bar_items)
- {
- HIRect bounds;
- HIViewRef content_view;
-
- err = HIViewGetBounds (item_view, &bounds);
- if (err == noErr)
- err = HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
- kHIViewWindowContentID, &content_view);
- if (err == noErr)
- err = HIViewConvertRect (&bounds, item_view, content_view);
- if (err == noErr)
- SetRect (&last_mouse_glyph,
- CGRectGetMinX (bounds), CGRectGetMinY (bounds),
- CGRectGetMaxX (bounds), CGRectGetMaxY (bounds));
-
- help_echo_object = help_echo_window = Qnil;
- help_echo_pos = -1;
- help_echo_string = PROP (TOOL_BAR_ITEM_HELP);
- if (NILP (help_echo_string))
- help_echo_string = PROP (TOOL_BAR_ITEM_CAPTION);
- }
- }
-}
-
-static OSStatus
-mac_handle_toolbar_command_event (next_handler, event, data)
- EventHandlerCallRef next_handler;
- EventRef event;
- void *data;
-{
- OSStatus err, result = eventNotHandledErr;
- struct frame *f = (struct frame *) data;
- HICommand command;
-
- err = GetEventParameter (event, kEventParamDirectObject,
- typeHICommand, NULL,
- sizeof (HICommand), NULL, &command);
- if (err != noErr)
- return result;
-
- switch (GetEventKind (event))
- {
- case kEventCommandProcess:
- if (!TOOLBAR_ITEM_COMMAND_ID_P (command.commandID))
- result = CallNextEventHandler (next_handler, event);
- else
- {
- int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command.commandID);
-
- if (i < f->n_tool_bar_items
- && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)))
- {
- Lisp_Object frame;
- struct input_event buf;
-
- EVENT_INIT (buf);
-
- XSETFRAME (frame, f);
- buf.kind = TOOL_BAR_EVENT;
- buf.frame_or_window = frame;
- buf.arg = frame;
- kbd_buffer_store_event (&buf);
-
- buf.kind = TOOL_BAR_EVENT;
- buf.frame_or_window = frame;
- buf.arg = PROP (TOOL_BAR_ITEM_KEY);
- buf.modifiers = mac_event_to_emacs_modifiers (event);
- kbd_buffer_store_event (&buf);
-
- result = noErr;
- }
- }
- break;
-
- default:
- abort ();
- }
-#undef PROP
-
- return result;
-}
-#endif /* USE_MAC_TOOLBAR */
-
-
-/***********************************************************************
- Text Cursor
- ***********************************************************************/
-
-/* Set clipping for output in glyph row ROW. W is the window in which
- we operate. GC is the graphics context to set clipping in.
-
- ROW may be a text row or, e.g., a mode line. Text rows must be
- clipped to the interior of the window dedicated to text display,
- mode lines must be clipped to the whole window. */
-
-static void
-x_clip_to_row (w, row, area, gc)
- struct window *w;
- struct glyph_row *row;
- int area;
- GC gc;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- Rect clip_rect;
- int window_x, window_y, window_width;
-
- window_box (w, area, &window_x, &window_y, &window_width, 0);
-
- clip_rect.left = window_x;
- clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
- clip_rect.top = max (clip_rect.top, window_y);
- clip_rect.right = clip_rect.left + window_width;
- clip_rect.bottom = clip_rect.top + row->visible_height;
-
- mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
-}
-
-
-/* Draw a hollow box cursor on window W in glyph row ROW. */
-
-static void
-x_draw_hollow_cursor (w, row)
- struct window *w;
- struct glyph_row *row;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- Display *dpy = FRAME_MAC_DISPLAY (f);
- int x, y, wd, h;
- XGCValues xgcv;
- struct glyph *cursor_glyph;
- GC gc;
-
- /* Get the glyph the cursor is on. If we can't tell because
- the current matrix is invalid or such, give up. */
- cursor_glyph = get_phys_cursor_glyph (w);
- if (cursor_glyph == NULL)
- return;
-
- /* Compute frame-relative coordinates for phys cursor. */
- get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
- wd = w->phys_cursor_width;
-
- /* The foreground of cursor_gc is typically the same as the normal
- background color, which can cause the cursor box to be invisible. */
- xgcv.foreground = f->output_data.mac->cursor_pixel;
- if (dpyinfo->scratch_cursor_gc)
- XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
- else
- dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
- GCForeground, &xgcv);
- gc = dpyinfo->scratch_cursor_gc;
-
- /* Set clipping, draw the rectangle, and reset clipping again. */
- x_clip_to_row (w, row, TEXT_AREA, gc);
- mac_draw_rectangle (f, gc, x, y, wd, h - 1);
- mac_reset_clip_rectangles (dpy, gc);
-}
-
-
-/* Draw a bar cursor on window W in glyph row ROW.
-
- Implementation note: One would like to draw a bar cursor with an
- angle equal to the one given by the font property XA_ITALIC_ANGLE.
- Unfortunately, I didn't find a font yet that has this property set.
- --gerd. */
-
-static void
-x_draw_bar_cursor (w, row, width, kind)
- struct window *w;
- struct glyph_row *row;
- int width;
- enum text_cursor_kinds kind;
-{
- struct frame *f = XFRAME (w->frame);
- struct glyph *cursor_glyph;
-
- /* If cursor is out of bounds, don't draw garbage. This can happen
- in mini-buffer windows when switching between echo area glyphs
- and mini-buffer. */
- cursor_glyph = get_phys_cursor_glyph (w);
- if (cursor_glyph == NULL)
- return;
-
- /* If on an image, draw like a normal cursor. That's usually better
- visible than drawing a bar, esp. if the image is large so that
- the bar might not be in the window. */
- if (cursor_glyph->type == IMAGE_GLYPH)
- {
- struct glyph_row *row;
- row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
- draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
- }
- else
- {
- Display *dpy = FRAME_MAC_DISPLAY (f);
- Window window = FRAME_MAC_WINDOW (f);
- GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
- unsigned long mask = GCForeground | GCBackground;
- struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
- XGCValues xgcv;
-
- /* If the glyph's background equals the color we normally draw
- the bar cursor in, the bar cursor in its normal color is
- invisible. Use the glyph's foreground color instead in this
- case, on the assumption that the glyph's colors are chosen so
- that the glyph is legible. */
- if (face->background == f->output_data.mac->cursor_pixel)
- xgcv.background = xgcv.foreground = face->foreground;
- else
- xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
-
- if (gc)
- XChangeGC (dpy, gc, mask, &xgcv);
- else
- {
- gc = XCreateGC (dpy, window, mask, &xgcv);
- FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
- }
-
- if (width < 0)
- width = FRAME_CURSOR_WIDTH (f);
- width = min (cursor_glyph->pixel_width, width);
-
- w->phys_cursor_width = width;
- x_clip_to_row (w, row, TEXT_AREA, gc);
-
- if (kind == BAR_CURSOR)
- mac_fill_rectangle (f, gc,
- WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
- WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
- width, row->height);
- else
- mac_fill_rectangle (f, gc,
- WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
- WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
- row->height - width),
- cursor_glyph->pixel_width,
- width);
-
- mac_reset_clip_rectangles (f, gc);
- }
-}
-
-
-/* RIF: Define cursor CURSOR on frame F. */
-
-static void
-mac_define_frame_cursor (f, cursor)
- struct frame *f;
- Cursor cursor;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- if (dpyinfo->x_focus_frame == f)
- SetThemeCursor (cursor);
-}
-
-
-/* RIF: Clear area on frame F. */
-
-static void
-mac_clear_frame_area (f, x, y, width, height)
- struct frame *f;
- int x, y, width, height;
-{
- mac_clear_area (f, x, y, width, height);
-}
-
-
-/* RIF: Draw cursor on window W. */
-
-static void
-mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
- struct window *w;
- struct glyph_row *glyph_row;
- int x, y;
- int cursor_type, cursor_width;
- int on_p, active_p;
-{
- if (on_p)
- {
- w->phys_cursor_type = cursor_type;
- w->phys_cursor_on_p = 1;
-
- if (glyph_row->exact_window_width_line_p
- && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
- {
- glyph_row->cursor_in_fringe_p = 1;
- draw_fringe_bitmap (w, glyph_row, 0);
- }
- else
- switch (cursor_type)
- {
- case HOLLOW_BOX_CURSOR:
- x_draw_hollow_cursor (w, glyph_row);
- break;
-
- case FILLED_BOX_CURSOR:
- draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
- break;
-
- case BAR_CURSOR:
- x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
- break;
-
- case HBAR_CURSOR:
- x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
- break;
-
- case NO_CURSOR:
- w->phys_cursor_width = 0;
- break;
-
- default:
- abort ();
- }
- }
-}
-
-
-/* Icons. */
-
-#if 0 /* MAC_TODO: no icon support yet. */
-int
-x_bitmap_icon (f, icon)
- struct frame *f;
- Lisp_Object icon;
-{
- HANDLE hicon;
-
- if (FRAME_W32_WINDOW (f) == 0)
- return 1;
-
- if (NILP (icon))
- hicon = LoadIcon (hinst, EMACS_CLASS);
- else if (STRINGP (icon))
- hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
- LR_DEFAULTSIZE | LR_LOADFROMFILE);
- else if (SYMBOLP (icon))
- {
- LPCTSTR name;
-
- if (EQ (icon, intern ("application")))
- name = (LPCTSTR) IDI_APPLICATION;
- else if (EQ (icon, intern ("hand")))
- name = (LPCTSTR) IDI_HAND;
- else if (EQ (icon, intern ("question")))
- name = (LPCTSTR) IDI_QUESTION;
- else if (EQ (icon, intern ("exclamation")))
- name = (LPCTSTR) IDI_EXCLAMATION;
- else if (EQ (icon, intern ("asterisk")))
- name = (LPCTSTR) IDI_ASTERISK;
- else if (EQ (icon, intern ("winlogo")))
- name = (LPCTSTR) IDI_WINLOGO;
- else
- return 1;
-
- hicon = LoadIcon (NULL, name);
- }
- else
- return 1;
-
- if (hicon == NULL)
- return 1;
-
- PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
- (LPARAM) hicon);
-
- return 0;
-}
-#endif /* MAC_TODO */
-
-/************************************************************************
- Handling X errors
- ************************************************************************/
-
-/* Display Error Handling functions not used on W32. Listing them here
- helps diff stay in step when comparing w32term.c with xterm.c.
-
-x_error_catcher (display, error)
-x_catch_errors (dpy)
-x_catch_errors_unwind (old_val)
-x_check_errors (dpy, format)
-x_had_errors_p (dpy)
-x_clear_errors (dpy)
-x_uncatch_errors (dpy, count)
-x_trace_wire ()
-x_connection_signal (signalnum)
-x_connection_closed (dpy, error_message)
-x_error_quitter (display, error)
-x_error_handler (display, error)
-x_io_error_quitter (display)
-
- */
-
-
-/* Changing the font of the frame. */
-
-/* Give frame F the font named FONTNAME as its default font, and
- return the full name of that font. FONTNAME may be a wildcard
- pattern; in that case, we choose some font that fits the pattern.
- The return value shows which font we chose. */
-
-Lisp_Object
-x_new_font (f, fontname)
- struct frame *f;
- register char *fontname;
-{
- struct font_info *fontp
- = FS_LOAD_FONT (f, fontname);
-
- if (!fontp)
- return Qnil;
-
- if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
- /* This font is already set in frame F. There's nothing more to
- do. */
- return build_string (fontp->full_name);
-
- FRAME_FONT (f) = (XFontStruct *) (fontp->font);
- FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
- FRAME_FONTSET (f) = -1;
-
- FRAME_COLUMN_WIDTH (f) = fontp->average_width;
- FRAME_SPACE_WIDTH (f) = fontp->space_width;
- FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
-
- compute_fringe_widths (f, 1);
-
- /* Compute the scroll bar width in character columns. */
- if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
- {
- int wid = FRAME_COLUMN_WIDTH (f);
- FRAME_CONFIG_SCROLL_BAR_COLS (f)
- = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
- }
- else
- {
- int wid = FRAME_COLUMN_WIDTH (f);
- FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
- }
-
- /* Now make the frame display the given font. */
- if (FRAME_MAC_WINDOW (f) != 0)
- {
- XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
- FRAME_FONT (f));
- XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
- FRAME_FONT (f));
- XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
- FRAME_FONT (f));
-
- /* Don't change the size of a tip frame; there's no point in
- doing it because it's done in Fx_show_tip, and it leads to
- problems because the tip frame has no widget. */
- if (NILP (tip_frame) || XFRAME (tip_frame) != f)
- x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
- }
-
- return build_string (fontp->full_name);
-}
-
-/* Give frame F the fontset named FONTSETNAME as its default fontset,
- and return the full name of that fontset. FONTSETNAME may be a
- wildcard pattern; in that case, we choose some fontset that fits
- the pattern. FONTSETNAME may be a font name for ASCII characters;
- in that case, we create a fontset from that font name.
-
- The return value shows which fontset we chose.
- If FONTSETNAME specifies the default fontset, return Qt.
- If an ASCII font in the specified fontset can't be loaded, return
- Qnil. */
-
-Lisp_Object
-x_new_fontset (f, fontsetname)
- struct frame *f;
- Lisp_Object fontsetname;
-{
- int fontset = fs_query_fontset (fontsetname, 0);
- Lisp_Object result;
-
- if (fontset > 0 && FRAME_FONTSET(f) == fontset)
- /* This fontset is already set in frame F. There's nothing more
- to do. */
- return fontset_name (fontset);
- else if (fontset == 0)
- /* The default fontset can't be the default font. */
- return Qt;
-
- if (fontset > 0)
- result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
- else
- result = x_new_font (f, SDATA (fontsetname));
-
- if (!STRINGP (result))
- /* Can't load ASCII font. */
- return Qnil;
-
- if (fontset < 0)
- fontset = new_fontset_from_font_name (result);
-
- /* Since x_new_font doesn't update any fontset information, do it now. */
- FRAME_FONTSET (f) = fontset;
-
- return fontset_name (fontset);
-}
-
-
-/***********************************************************************
- TODO: W32 Input Methods
- ***********************************************************************/
-/* Listing missing functions from xterm.c helps diff stay in step.
-
-xim_destroy_callback (xim, client_data, call_data)
-xim_open_dpy (dpyinfo, resource_name)
-struct xim_inst_t
-xim_instantiate_callback (display, client_data, call_data)
-xim_initialize (dpyinfo, resource_name)
-xim_close_dpy (dpyinfo)
-
- */
-
-
-void
-mac_get_window_bounds (f, inner, outer)
- struct frame *f;
- Rect *inner, *outer;
-{
-#if TARGET_API_MAC_CARBON
- GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
- GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
-#else /* not TARGET_API_MAC_CARBON */
- RgnHandle region = NewRgn ();
-
- GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
- *inner = (*region)->rgnBBox;
- GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
- *outer = (*region)->rgnBBox;
- DisposeRgn (region);
-#endif /* not TARGET_API_MAC_CARBON */
-}
-
-static void
-mac_handle_origin_change (f)
- struct frame *f;
-{
- x_real_positions (f, &f->left_pos, &f->top_pos);
-}
-
-static void
-mac_handle_size_change (f, pixelwidth, pixelheight)
- struct frame *f;
- int pixelwidth, pixelheight;
-{
- int cols, rows;
-
- cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
- rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
-
- if (cols != FRAME_COLS (f)
- || rows != FRAME_LINES (f)
- || pixelwidth != FRAME_PIXEL_WIDTH (f)
- || pixelheight != FRAME_PIXEL_HEIGHT (f))
- {
- /* We pass 1 for DELAY since we can't run Lisp code inside of
- a BLOCK_INPUT. */
- change_frame_size (f, rows, cols, 0, 1, 0);
- FRAME_PIXEL_WIDTH (f) = pixelwidth;
- FRAME_PIXEL_HEIGHT (f) = pixelheight;
-
- /* If cursor was outside the new size, mark it as off. */
- mark_window_cursors_off (XWINDOW (f->root_window));
-
- /* Clear out any recollection of where the mouse highlighting
- was, since it might be in a place that's outside the new
- frame size. Actually checking whether it is outside is a
- pain in the neck, so don't try--just let the highlighting be
- done afresh with new size. */
- cancel_mouse_face (f);
-
-#if TARGET_API_MAC_CARBON
- if (f->output_data.mac->hourglass_control)
- {
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- MoveControl (f->output_data.mac->hourglass_control,
- pixelwidth - HOURGLASS_WIDTH, 0);
- }
-#endif
- }
-}
-
-
-/* Calculate the absolute position in frame F
- from its current recorded position values and gravity. */
-
-void
-x_calc_absolute_position (f)
- struct frame *f;
-{
- int flags = f->size_hint_flags;
- Rect inner, outer;
-
- /* We have nothing to do if the current position
- is already for the top-left corner. */
- if (! ((flags & XNegative) || (flags & YNegative)))
- return;
-
- /* Find the offsets of the outside upper-left corner of
- the inner window, with respect to the outer window. */
- BLOCK_INPUT;
- mac_get_window_bounds (f, &inner, &outer);
- UNBLOCK_INPUT;
-
- /* Treat negative positions as relative to the leftmost bottommost
- position that fits on the screen. */
- if (flags & XNegative)
- f->left_pos += (FRAME_MAC_DISPLAY_INFO (f)->width
- - (outer.right - outer.left));
-
- if (flags & YNegative)
- f->top_pos += (FRAME_MAC_DISPLAY_INFO (f)->height
- - (outer.bottom - outer.top));
-
- /* The left_pos and top_pos
- are now relative to the top and left screen edges,
- so the flags should correspond. */
- f->size_hint_flags &= ~ (XNegative | YNegative);
-}
-
-/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
- to really change the position, and 0 when calling from
- x_make_frame_visible (in that case, XOFF and YOFF are the current
- position values). It is -1 when calling from x_set_frame_parameters,
- which means, do adjust for borders but don't change the gravity. */
-
-void
-x_set_offset (f, xoff, yoff, change_gravity)
- struct frame *f;
- register int xoff, yoff;
- int change_gravity;
-{
- if (change_gravity > 0)
- {
- f->top_pos = yoff;
- f->left_pos = xoff;
- f->size_hint_flags &= ~ (XNegative | YNegative);
- if (xoff < 0)
- f->size_hint_flags |= XNegative;
- if (yoff < 0)
- f->size_hint_flags |= YNegative;
- f->win_gravity = NorthWestGravity;
- }
- x_calc_absolute_position (f);
-
- BLOCK_INPUT;
- x_wm_set_size_hint (f, (long) 0, 0);
-
-#if TARGET_API_MAC_CARBON
- MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
- /* If the title bar is completely outside the screen, adjust the
- position. */
- ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
- kWindowConstrainMoveRegardlessOfFit
- | kWindowConstrainAllowPartial, NULL, NULL);
- if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
- mac_handle_origin_change (f);
-#else
- {
- Rect inner, outer, screen_rect, dummy;
- RgnHandle region = NewRgn ();
-
- mac_get_window_bounds (f, &inner, &outer);
- f->x_pixels_diff = inner.left - outer.left;
- f->y_pixels_diff = inner.top - outer.top;
- MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
- f->top_pos + f->y_pixels_diff, false);
-
- /* If the title bar is completely outside the screen, adjust the
- position. The variable `outer' holds the title bar rectangle.
- The variable `inner' holds slightly smaller one than `outer',
- so that the calculation of overlapping may not become too
- strict. */
- GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
- outer = (*region)->rgnBBox;
- DisposeRgn (region);
- inner = outer;
- InsetRect (&inner, 8, 8);
- screen_rect = qd.screenBits.bounds;
- screen_rect.top += GetMBarHeight ();
-
- if (!SectRect (&inner, &screen_rect, &dummy))
- {
- if (inner.right <= screen_rect.left)
- f->left_pos = screen_rect.left;
- else if (inner.left >= screen_rect.right)
- f->left_pos = screen_rect.right - (outer.right - outer.left);
-
- if (inner.bottom <= screen_rect.top)
- f->top_pos = screen_rect.top;
- else if (inner.top >= screen_rect.bottom)
- f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
-
- MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
- f->top_pos + f->y_pixels_diff, false);
- }
- }
-#endif
-
- UNBLOCK_INPUT;
-}
-
-/* Call this to change the size of frame F's x-window.
- If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
- for this size change and subsequent size changes.
- Otherwise we leave the window gravity unchanged. */
-
-void
-x_set_window_size (f, change_gravity, cols, rows)
- struct frame *f;
- int change_gravity;
- int cols, rows;
-{
- int pixelwidth, pixelheight;
-
- BLOCK_INPUT;
-
- check_frame_size (f, &rows, &cols);
- f->scroll_bar_actual_width
- = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
-
- compute_fringe_widths (f, 0);
-
- pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
- pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
-
- f->win_gravity = NorthWestGravity;
- x_wm_set_size_hint (f, (long) 0, 0);
-
- SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
-
-#if TARGET_API_MAC_CARBON
- if (!NILP (tip_frame) && f == XFRAME (tip_frame))
-#endif
- mac_handle_size_change (f, pixelwidth, pixelheight);
-
- if (f->output_data.mac->internal_border_width
- != FRAME_INTERNAL_BORDER_WIDTH (f))
- {
- mac_clear_window (f);
- f->output_data.mac->internal_border_width
- = FRAME_INTERNAL_BORDER_WIDTH (f);
- }
-
- SET_FRAME_GARBAGED (f);
-
- UNBLOCK_INPUT;
-}
-
-/* Mouse warping. */
-
-void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
-
-void
-x_set_mouse_position (f, x, y)
- struct frame *f;
- int x, y;
-{
- int pix_x, pix_y;
-
- pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
- pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
-
- if (pix_x < 0) pix_x = 0;
- if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
-
- if (pix_y < 0) pix_y = 0;
- if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
-
- x_set_mouse_pixel_position (f, pix_x, pix_y);
-}
-
-void
-x_set_mouse_pixel_position (f, pix_x, pix_y)
- struct frame *f;
- int pix_x, pix_y;
-{
-#ifdef MAC_OSX
- pix_x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
- pix_y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
-
- BLOCK_INPUT;
- CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
- UNBLOCK_INPUT;
-#else
-#if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
- BLOCK_INPUT;
-
- XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
- 0, 0, 0, 0, pix_x, pix_y);
- UNBLOCK_INPUT;
-#endif
-#endif
-}
-
-/* focus shifting, raising and lowering. */
-
-void
-x_focus_on_frame (f)
- struct frame *f;
-{
-#if 0 /* This proves to be unpleasant. */
- x_raise_frame (f);
-#endif
-#if 0
- /* I don't think that the ICCCM allows programs to do things like this
- without the interaction of the window manager. Whatever you end up
- doing with this code, do it to x_unfocus_frame too. */
- XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- RevertToPointerRoot, CurrentTime);
-#endif /* ! 0 */
-}
-
-void
-x_unfocus_frame (f)
- struct frame *f;
-{
-}
-
-/* Raise frame F. */
-
-void
-x_raise_frame (f)
- struct frame *f;
-{
- if (f->async_visible)
- {
- BLOCK_INPUT;
- BringToFront (FRAME_MAC_WINDOW (f));
- UNBLOCK_INPUT;
- }
-}
-
-/* Lower frame F. */
-
-void
-x_lower_frame (f)
- struct frame *f;
-{
- if (f->async_visible)
- {
- BLOCK_INPUT;
- SendBehind (FRAME_MAC_WINDOW (f), NULL);
- UNBLOCK_INPUT;
- }
-}
-
-static void
-XTframe_raise_lower (f, raise_flag)
- FRAME_PTR f;
- int raise_flag;
-{
- if (raise_flag)
- x_raise_frame (f);
- else
- x_lower_frame (f);
-}
-
-/* Change of visibility. */
-
-static void
-mac_handle_visibility_change (f)
- struct frame *f;
-{
- WindowRef wp = FRAME_MAC_WINDOW (f);
- int visible = 0, iconified = 0;
- struct input_event buf;
-
- if (IsWindowVisible (wp))
- {
- if (IsWindowCollapsed (wp))
- iconified = 1;
- else
- visible = 1;
- }
-
- if (!f->async_visible && visible)
- {
- if (f->iconified)
- {
- /* wait_reading_process_output will notice this and update
- the frame's display structures. If we were made
- invisible, we should not set garbaged, because that stops
- redrawing on Update events. */
- SET_FRAME_GARBAGED (f);
-
- EVENT_INIT (buf);
- buf.kind = DEICONIFY_EVENT;
- XSETFRAME (buf.frame_or_window, f);
- buf.arg = Qnil;
- kbd_buffer_store_event (&buf);
- }
- else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
- /* Force a redisplay sooner or later to update the
- frame titles in case this is the second frame. */
- record_asynch_buffer_change ();
- }
- else if (f->async_visible && !visible)
- if (iconified)
- {
- EVENT_INIT (buf);
- buf.kind = ICONIFY_EVENT;
- XSETFRAME (buf.frame_or_window, f);
- buf.arg = Qnil;
- kbd_buffer_store_event (&buf);
- }
-
- f->async_visible = visible;
- f->async_iconified = iconified;
-}
-
-/* This tries to wait until the frame is really visible.
- However, if the window manager asks the user where to position
- the frame, this will return before the user finishes doing that.
- The frame will not actually be visible at that time,
- but it will become visible later when the window manager
- finishes with it. */
-
-void
-x_make_frame_visible (f)
- struct frame *f;
-{
- BLOCK_INPUT;
-
- if (! FRAME_VISIBLE_P (f))
- {
- /* We test FRAME_GARBAGED_P here to make sure we don't
- call x_set_offset a second time
- if we get to x_make_frame_visible a second time
- before the window gets really visible. */
- if (! FRAME_ICONIFIED_P (f)
- && ! f->output_data.mac->asked_for_visible)
- x_set_offset (f, f->left_pos, f->top_pos, 0);
-
- f->output_data.mac->asked_for_visible = 1;
-
- CollapseWindow (FRAME_MAC_WINDOW (f), false);
- ShowWindow (FRAME_MAC_WINDOW (f));
- }
-
- XFlush (FRAME_MAC_DISPLAY (f));
-
- /* Synchronize to ensure Emacs knows the frame is visible
- before we do anything else. We do this loop with input not blocked
- so that incoming events are handled. */
- {
- Lisp_Object frame;
- int count;
-
- /* This must come after we set COUNT. */
- UNBLOCK_INPUT;
-
- XSETFRAME (frame, f);
-
- /* Wait until the frame is visible. Process X events until a
- MapNotify event has been seen, or until we think we won't get a
- MapNotify at all.. */
- for (count = input_signal_count + 10;
- input_signal_count < count && !FRAME_VISIBLE_P (f);)
- {
- /* Force processing of queued events. */
- x_sync (f);
-
- /* Machines that do polling rather than SIGIO have been
- observed to go into a busy-wait here. So we'll fake an
- alarm signal to let the handler know that there's something
- to be read. We used to raise a real alarm, but it seems
- that the handler isn't always enabled here. This is
- probably a bug. */
- if (input_polling_used ())
- {
- /* It could be confusing if a real alarm arrives while
- processing the fake one. Turn it off and let the
- handler reset it. */
- extern void poll_for_input_1 P_ ((void));
- int old_poll_suppress_count = poll_suppress_count;
- poll_suppress_count = 1;
- poll_for_input_1 ();
- poll_suppress_count = old_poll_suppress_count;
- }
-
- /* See if a MapNotify event has been processed. */
- FRAME_SAMPLE_VISIBILITY (f);
- }
- }
-}
-
-/* Change from mapped state to withdrawn state. */
-
-/* Make the frame visible (mapped and not iconified). */
-
-void
-x_make_frame_invisible (f)
- struct frame *f;
-{
- /* A deactivate event does not occur when the last visible frame is
- made invisible. So if we clear the highlight here, it will not
- be rehighlighted when it is made visible. */
-#if 0
- /* Don't keep the highlight on an invisible frame. */
- if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
- FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
-#endif
-
- BLOCK_INPUT;
-
-#if !TARGET_API_MAC_CARBON
- /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
- that the current position of the window is user-specified, rather than
- program-specified, so that when the window is mapped again, it will be
- placed at the same location, without forcing the user to position it
- by hand again (they have already done that once for this window.) */
- x_wm_set_size_hint (f, (long) 0, 1);
-#endif
-
- HideWindow (FRAME_MAC_WINDOW (f));
-
- UNBLOCK_INPUT;
-
-#if !TARGET_API_MAC_CARBON
- mac_handle_visibility_change (f);
-#endif
-}
-
-/* Change window state from mapped to iconified. */
-
-void
-x_iconify_frame (f)
- struct frame *f;
-{
- OSStatus err;
-
- /* A deactivate event does not occur when the last visible frame is
- iconified. So if we clear the highlight here, it will not be
- rehighlighted when it is deiconified. */
-#if 0
- /* Don't keep the highlight on an invisible frame. */
- if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
- FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
-#endif
-
- if (f->async_iconified)
- return;
-
- BLOCK_INPUT;
-
- FRAME_SAMPLE_VISIBILITY (f);
-
- if (! FRAME_VISIBLE_P (f))
- ShowWindow (FRAME_MAC_WINDOW (f));
-
- err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
-
- UNBLOCK_INPUT;
-
- if (err != noErr)
- error ("Can't notify window manager of iconification");
-
-#if !TARGET_API_MAC_CARBON
- mac_handle_visibility_change (f);
-#endif
-}
-
-
-/* Free X resources of frame F. */
-
-void
-x_free_frame_resources (f)
- struct frame *f;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- WindowRef wp = FRAME_MAC_WINDOW (f);
-
- BLOCK_INPUT;
-
- if (wp != tip_window)
- remove_window_handler (wp);
-
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- DisposeWindow (wp);
- if (wp == tip_window)
- /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
- closed' event. So we reset tip_window here. */
- tip_window = NULL;
-
- free_frame_menubar (f);
-
- if (FRAME_FACE_CACHE (f))
- free_frame_faces (f);
-
- x_free_gcs (f);
-
- xfree (FRAME_SIZE_HINTS (f));
-
- xfree (f->output_data.mac);
- f->output_data.mac = NULL;
-
- if (f == dpyinfo->x_focus_frame)
- {
- dpyinfo->x_focus_frame = 0;
-#if USE_MAC_FONT_PANEL
- mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
-#endif
- }
- if (f == dpyinfo->x_focus_event_frame)
- dpyinfo->x_focus_event_frame = 0;
- if (f == dpyinfo->x_highlight_frame)
- dpyinfo->x_highlight_frame = 0;
-
- if (f == dpyinfo->mouse_face_mouse_frame)
- {
- dpyinfo->mouse_face_beg_row
- = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row
- = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- dpyinfo->mouse_face_deferred_gc = 0;
- dpyinfo->mouse_face_mouse_frame = 0;
- }
-
- UNBLOCK_INPUT;
-}
-
-
-/* Destroy the X window of frame F. */
-
-void
-x_destroy_window (f)
- struct frame *f;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- x_free_frame_resources (f);
-
- dpyinfo->reference_count--;
-}
-
-
-/* Setting window manager hints. */
-
-/* Set the normal size hints for the window manager, for frame F.
- FLAGS is the flags word to use--or 0 meaning preserve the flags
- that the window now has.
- If USER_POSITION is nonzero, we set the USPosition
- flag (this is useful when FLAGS is 0). */
-void
-x_wm_set_size_hint (f, flags, user_position)
- struct frame *f;
- long flags;
- int user_position;
-{
- int base_width, base_height, width_inc, height_inc;
- int min_rows = 0, min_cols = 0;
- XSizeHints *size_hints;
-
- base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
- base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
- width_inc = FRAME_COLUMN_WIDTH (f);
- height_inc = FRAME_LINE_HEIGHT (f);
-
- check_frame_size (f, &min_rows, &min_cols);
-
- size_hints = FRAME_SIZE_HINTS (f);
- if (size_hints == NULL)
- {
- size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
- bzero (size_hints, sizeof (XSizeHints));
- }
-
- size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
- size_hints->width_inc = width_inc;
- size_hints->height_inc = height_inc;
- size_hints->min_width = base_width + min_cols * width_inc;
- size_hints->min_height = base_height + min_rows * height_inc;
- size_hints->base_width = base_width;
- size_hints->base_height = base_height;
-
- if (flags)
- size_hints->flags = flags;
- else if (user_position)
- {
- size_hints->flags &= ~ PPosition;
- size_hints->flags |= USPosition;
- }
-}
-
-#if 0 /* MAC_TODO: hide application instead of iconify? */
-/* Used for IconicState or NormalState */
-
-void
-x_wm_set_window_state (f, state)
- struct frame *f;
- int state;
-{
-#ifdef USE_X_TOOLKIT
- Arg al[1];
-
- XtSetArg (al[0], XtNinitialState, state);
- XtSetValues (f->output_data.x->widget, al, 1);
-#else /* not USE_X_TOOLKIT */
- Window window = FRAME_X_WINDOW (f);
-
- f->output_data.x->wm_hints.flags |= StateHint;
- f->output_data.x->wm_hints.initial_state = state;
-
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-#endif /* not USE_X_TOOLKIT */
-}
-
-void
-x_wm_set_icon_pixmap (f, pixmap_id)
- struct frame *f;
- int pixmap_id;
-{
- Pixmap icon_pixmap;
-
-#ifndef USE_X_TOOLKIT
- Window window = FRAME_X_WINDOW (f);
-#endif
-
- if (pixmap_id > 0)
- {
- icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
- f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
- }
- else
- {
- /* It seems there is no way to turn off use of an icon pixmap.
- The following line does it, only if no icon has yet been created,
- for some window managers. But with mwm it crashes.
- Some people say it should clear the IconPixmapHint bit in this case,
- but that doesn't work, and the X consortium said it isn't the
- right thing at all. Since there is no way to win,
- best to explicitly give up. */
-#if 0
- f->output_data.x->wm_hints.icon_pixmap = None;
-#else
- return;
-#endif
- }
-
-#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
-
- {
- Arg al[1];
- XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
- XtSetValues (f->output_data.x->widget, al, 1);
- }
-
-#else /* not USE_X_TOOLKIT */
-
- f->output_data.x->wm_hints.flags |= IconPixmapHint;
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-
-#endif /* not USE_X_TOOLKIT */
-}
-
-#endif /* MAC_TODO */
-
-void
-x_wm_set_icon_position (f, icon_x, icon_y)
- struct frame *f;
- int icon_x, icon_y;
-{
-#if 0 /* MAC_TODO: no icons on Mac */
-#ifdef USE_X_TOOLKIT
- Window window = XtWindow (f->output_data.x->widget);
-#else
- Window window = FRAME_X_WINDOW (f);
-#endif
-
- f->output_data.x->wm_hints.flags |= IconPositionHint;
- f->output_data.x->wm_hints.icon_x = icon_x;
- f->output_data.x->wm_hints.icon_y = icon_y;
-
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-#endif /* MAC_TODO */
-}
-
-
-/***********************************************************************
- XLFD Pattern Match
- ***********************************************************************/
-
-/* An XLFD pattern is divided into blocks delimited by '*'. This
- structure holds information for each block. */
-struct xlfdpat_block
-{
- /* Length of the pattern string in this block. Non-zero except for
- the first and the last blocks. */
- int len;
-
- /* Pattern string except the last character in this block. The last
- character is replaced with NUL in order to use it as a
- sentinel. */
- unsigned char *pattern;
-
- /* Last character of the pattern string. Must not be '?'. */
- unsigned char last_char;
-
- /* One of the tables for the Boyer-Moore string search. It
- specifies the number of positions to proceed for each character
- with which the match fails. */
- int skip[256];
-
- /* The skip value for the last character in the above `skip' is
- assigned to `infinity' in order to simplify a loop condition.
- The original value is saved here. */
- int last_char_skip;
-};
-
-struct xlfdpat
-{
- /* Normalized pattern string. "Normalized" means that capital
- letters are lowered, blocks are not empty except the first and
- the last ones, and trailing '?'s in a block that is not the last
- one are moved to the next one. The last character in each block
- is replaced with NUL. */
- unsigned char *buf;
-
- /* Number of characters except '*'s and trailing '?'s in the
- normalized pattern string. */
- int nchars;
-
- /* Number of trailing '?'s in the normalized pattern string. */
- int trailing_anychars;
-
- /* Number of blocks and information for each block. The latter is
- NULL if the pattern is exact (no '*' or '?' in it). */
- int nblocks;
- struct xlfdpat_block *blocks;
-};
-
-static void
-xlfdpat_destroy (pat)
- struct xlfdpat *pat;
-{
- if (pat)
- {
- if (pat->buf)
- {
- xfree (pat->blocks);
- xfree (pat->buf);
- }
- xfree (pat);
- }
-}
-
-static struct xlfdpat *
-xlfdpat_create (pattern)
- const char *pattern;
-{
- struct xlfdpat *pat;
- int nblocks, i, skip;
- unsigned char last_char, *p, *q, *anychar_head;
- const unsigned char *ptr;
- struct xlfdpat_block *blk;
-
- pat = xmalloc (sizeof (struct xlfdpat));
- pat->buf = xmalloc (strlen (pattern) + 1);
-
- /* Normalize the pattern string and store it to `pat->buf'. */
- nblocks = 0;
- anychar_head = NULL;
- q = pat->buf;
- last_char = '\0';
- for (ptr = pattern; *ptr; ptr++)
- {
- unsigned char c = *ptr;
-
- if (c == '*')
- if (last_char == '*')
- /* ...a** -> ...a* */
- continue;
- else
- {
- if (last_char == '?')
- {
- if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
- /* ...*??* -> ...*?? */
- continue;
- else
- /* ...a??* -> ...a*?? */
- {
- *anychar_head++ = '*';
- c = '?';
- }
- }
- nblocks++;
- }
- else if (c == '?')
- {
- if (last_char != '?')
- anychar_head = q;
- }
- else
- /* On Mac OS X 10.3, tolower also converts non-ASCII
- characters for some locales. */
- if (isascii (c))
- c = tolower (c);
-
- *q++ = last_char = c;
- }
- *q = '\0';
- nblocks++;
- pat->nblocks = nblocks;
- if (last_char != '?')
- pat->trailing_anychars = 0;
- else
- {
- pat->trailing_anychars = q - anychar_head;
- q = anychar_head;
- }
- pat->nchars = q - pat->buf - (nblocks - 1);
-
- if (anychar_head == NULL && nblocks == 1)
- {
- /* The pattern is exact. */
- pat->blocks = NULL;
- return pat;
- }
-
- pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
-
- /* Divide the normalized pattern into blocks. */
- p = pat->buf;
- for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
- {
- blk->pattern = p;
- while (*p != '*')
- p++;
- blk->len = p - blk->pattern;
- p++;
- }
- blk->pattern = p;
- blk->len = q - blk->pattern;
-
- /* Setup a table for the Boyer-Moore string search. */
- for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
- if (blk->len != 0)
- {
- blk->last_char = blk->pattern[blk->len - 1];
- blk->pattern[blk->len - 1] = '\0';
-
- for (skip = 1; skip < blk->len; skip++)
- if (blk->pattern[blk->len - skip - 1] == '?')
- break;
-
- for (i = 0; i < 256; i++)
- blk->skip[i] = skip;
-
- p = blk->pattern + (blk->len - skip);
- while (--skip > 0)
- blk->skip[*p++] = skip;
-
- blk->last_char_skip = blk->skip[blk->last_char];
- }
-
- return pat;
-}
-
-static INLINE int
-xlfdpat_exact_p (pat)
- struct xlfdpat *pat;
-{
- return pat->blocks == NULL;
-}
-
-/* Return the first string in STRING + 0, ..., STRING + START_MAX such
- that the pattern in *BLK matches with its prefix. Return NULL
- there is no such strings. STRING must be lowered in advance. */
-
-static const char *
-xlfdpat_block_match_1 (blk, string, start_max)
- struct xlfdpat_block *blk;
- const unsigned char *string;
- int start_max;
-{
- int start, infinity;
- unsigned char *p;
- const unsigned char *s;
-
- xassert (blk->len > 0);
- xassert (start_max + blk->len <= strlen (string));
- xassert (blk->last_char != '?');
-
- /* See the comments in the function `boyer_moore' (search.c) for the
- use of `infinity'. */
- infinity = start_max + blk->len + 1;
- blk->skip[blk->last_char] = infinity;
-
- start = 0;
- do
- {
- /* Check the last character of the pattern. */
- s = string + blk->len - 1;
- do
- {
- start += blk->skip[*(s + start)];
- }
- while (start <= start_max);
-
- if (start < infinity)
- /* Couldn't find the last character. */
- return NULL;
-
- /* No less than `infinity' means we could find the last
- character at `s[start - infinity]'. */
- start -= infinity;
-
- /* Check the remaining characters. We prefer making no-'?'
- cases faster because the use of '?' is really rare. */
- p = blk->pattern;
- s = string + start;
- do
- {
- while (*p++ == *s++)
- ;
- }
- while (*(p - 1) == '?');
-
- if (*(p - 1) == '\0')
- /* Matched. */
- return string + start;
-
- /* Didn't match. */
- start += blk->last_char_skip;
- }
- while (start <= start_max);
-
- return NULL;
-}
-
-#define xlfdpat_block_match(b, s, m) \
- ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
- : xlfdpat_block_match_1 (b, s, m))
-
-/* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
- matches with STRING. STRING must be lowered in advance. */
-
-static int
-xlfdpat_match (pat, string)
- struct xlfdpat *pat;
- const unsigned char *string;
-{
- int str_len, nblocks, i, start_max;
- struct xlfdpat_block *blk;
- const unsigned char *s;
-
- xassert (pat->nblocks > 0);
-
- if (xlfdpat_exact_p (pat))
- return strcmp (pat->buf, string) == 0;
-
- /* The number of the characters in the string must not be smaller
- than that in the pattern. */
- str_len = strlen (string);
- if (str_len < pat->nchars + pat->trailing_anychars)
- return 0;
-
- /* Chop off the trailing '?'s. */
- str_len -= pat->trailing_anychars;
-
- /* The last block. When it is non-empty, it must match at the end
- of the string. */
- nblocks = pat->nblocks;
- blk = pat->blocks + (nblocks - 1);
- if (nblocks == 1)
- /* The last block is also the first one. */
- return (str_len == blk->len
- && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
- else if (blk->len != 0)
- if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
- return 0;
-
- /* The first block. When it is non-empty, it must match at the
- beginning of the string. */
- blk = pat->blocks;
- if (blk->len != 0)
- {
- s = xlfdpat_block_match (blk, string, 0);
- if (s == NULL)
- return 0;
- string = s + blk->len;
- }
-
- /* The rest of the blocks. */
- start_max = str_len - pat->nchars;
- for (i = 1, blk++; i < nblocks - 1; i++, blk++)
- {
- s = xlfdpat_block_match (blk, string, start_max);
- if (s == NULL)
- return 0;
- start_max -= s - string;
- string = s + blk->len;
- }
-
- return 1;
-}
-
-
-/***********************************************************************
- Fonts
- ***********************************************************************/
-
-/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
-
-struct font_info *
-x_get_font_info (f, font_idx)
- FRAME_PTR f;
- int font_idx;
-{
- return (FRAME_MAC_FONT_TABLE (f) + font_idx);
-}
-
-/* the global font name table */
-static char **font_name_table = NULL;
-static int font_name_table_size = 0;
-static int font_name_count = 0;
-
-/* Alist linking font family names to Font Manager font family
- references (which can also be used as QuickDraw font IDs). We use
- an alist because hash tables are not ready when the terminal frame
- for Mac OS Classic is created. */
-static Lisp_Object fm_font_family_alist;
-#if USE_ATSUI
-/* Hash table linking font family names to ATSU font IDs. */
-static Lisp_Object atsu_font_id_hash;
-/* Alist linking Font Manager style to face attributes. */
-static Lisp_Object fm_style_face_attributes_alist;
-extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
-#endif
-
-/* Alist linking character set strings to Mac text encoding and Emacs
- coding system. */
-static Lisp_Object Vmac_charset_info_alist;
-
-static Lisp_Object
-create_text_encoding_info_alist ()
-{
- Lisp_Object result = Qnil, rest;
-
- for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
- {
- Lisp_Object charset_info = XCAR (rest);
- Lisp_Object charset, coding_system, text_encoding;
- Lisp_Object existing_info;
-
- if (!(CONSP (charset_info)
- && (charset = XCAR (charset_info),
- STRINGP (charset))
- && CONSP (XCDR (charset_info))
- && (text_encoding = XCAR (XCDR (charset_info)),
- INTEGERP (text_encoding))
- && CONSP (XCDR (XCDR (charset_info)))
- && (coding_system = XCAR (XCDR (XCDR (charset_info))),
- SYMBOLP (coding_system))))
- continue;
-
- existing_info = assq_no_quit (text_encoding, result);
- if (NILP (existing_info))
- result = Fcons (list3 (text_encoding, coding_system, charset),
- result);
- else
- if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
- XSETCDR (XCDR (existing_info),
- Fcons (charset, XCDR (XCDR (existing_info))));
- }
-
- return result;
-}
-
-
-static void
-decode_mac_font_name (name, size, coding_system)
- char *name;
- int size;
- Lisp_Object coding_system;
-{
- struct coding_system coding;
- char *buf, *p;
-
- if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
- {
- for (p = name; *p; p++)
- if (!isascii (*p) || iscntrl (*p))
- break;
-
- if (*p)
- {
- setup_coding_system (coding_system, &coding);
- coding.src_multibyte = 0;
- coding.dst_multibyte = 1;
- coding.mode |= CODING_MODE_LAST_BLOCK;
- coding.dst_bytes = size;
- coding.destination = (unsigned char *) alloca (coding.dst_bytes);
-
- decode_coding_c_string (&coding, name, strlen (name), Qnil);
- bcopy (coding.destination, name, min (coding.produced, size));
- name[min (coding.produced, size)] = '\0';
- }
- }
-
- /* If there's just one occurrence of '-' in the family name, it is
- replaced with '_'. (More than one occurrence of '-' means a
- "FOUNDRY-FAMILY-CHARSET"-style name.) */
- p = strchr (name, '-');
- if (p && strchr (p + 1, '-') == NULL)
- *p = '_';
-
- for (p = name; *p; p++)
- /* On Mac OS X 10.3, tolower also converts non-ASCII characters
- for some locales. */
- if (isascii (*p))
- *p = tolower (*p);
-}
-
-
-static char *
-mac_to_x_fontname (name, size, style, charset)
- const char *name;
- int size;
- Style style;
- char *charset;
-{
- Str31 foundry, cs;
- Str255 family;
- char xf[256], *result;
- unsigned char *p;
-
- if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
- charset = cs;
- else
- {
- strcpy(foundry, "Apple");
- strcpy(family, name);
- }
-
- sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
- style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
- size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
-
- result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
- sprintf (result, "-%s-%s-%s", foundry, family, xf);
- for (p = result; *p; p++)
- /* On Mac OS X 10.3, tolower also converts non-ASCII characters
- for some locales. */
- if (isascii (*p))
- *p = tolower (*p);
- return result;
-}
-
-
-/* Parse fully-specified and instantiated X11 font spec XF, and store
- the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
- parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
- caller must allocate at least 256 and 32 bytes respectively. For
- ordinary Mac fonts, the value stored to FAMILY should just be their
- names, like "monaco", "Taipei", etc. Fonts converted from the GNU
- intlfonts collection contain their charset designation in their
- names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
- types of font names are handled accordingly. */
-
-const int kDefaultFontSize = 12;
-
-static int
-parse_x_font_name (xf, family, size, style, charset)
- const char *xf;
- char *family;
- int *size;
- Style *style;
- char *charset;
-{
- Str31 foundry, weight;
- int point_size, avgwidth;
- char slant[2], *p;
-
- if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
- foundry, family, weight, slant, size,
- &point_size, &avgwidth, charset) != 8
- && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
- foundry, family, weight, slant, size,
- &point_size, &avgwidth, charset) != 8)
- return 0;
-
- if (*size == 0)
- {
- if (point_size > 0)
- *size = point_size / 10;
- else if (avgwidth > 0)
- *size = avgwidth / 10;
- }
- if (*size == 0)
- *size = kDefaultFontSize;
-
- *style = normal;
- if (strcmp (weight, "bold") == 0)
- *style |= bold;
- if (*slant == 'i')
- *style |= italic;
-
- if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
- {
- int foundry_len = strlen (foundry), family_len = strlen (family);
-
- if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
- {
- /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
- but take overlap into account. */
- memmove (family + foundry_len + 1, family, family_len);
- memcpy (family, foundry, foundry_len);
- family[foundry_len] = '-';
- family[foundry_len + 1 + family_len] = '-';
- strcpy (family + foundry_len + 1 + family_len + 1, charset);
- }
- else
- return 0;
- }
-
- for (p = family; *p; p++)
- /* On Mac OS X 10.3, tolower also converts non-ASCII characters
- for some locales. */
- if (isascii (*p))
- *p = tolower (*p);
-
- return 1;
-}
-
-
-static void
-add_font_name_table_entry (char *font_name)
-{
- if (font_name_table_size == 0)
- {
- font_name_table_size = 256;
- font_name_table = (char **)
- xmalloc (font_name_table_size * sizeof (char *));
- }
- else if (font_name_count + 1 >= font_name_table_size)
- {
- font_name_table_size *= 2;
- font_name_table = (char **)
- xrealloc (font_name_table,
- font_name_table_size * sizeof (char *));
- }
-
- font_name_table[font_name_count++] = font_name;
-}
-
-static void
-add_mac_font_name (name, size, style, charset)
- const char *name;
- int size;
- Style style;
- const char *charset;
-{
- if (size > 0)
- add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
- else
- {
- add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
- add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
- add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
- add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
- charset));
- }
-}
-
-#if USE_ATSUI
-static FMFontStyle
-fm_get_style_from_font (font)
- FMFont font;
-{
- OSStatus err;
- FMFontStyle style = normal;
- ByteCount len;
- UInt16 mac_style;
- FMFontFamily font_family;
-#define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
-
- /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
- some font (e.g., Optima) even if it is `bold'. */
- err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
- sizeof (mac_style), &mac_style, &len);
- if (err == noErr
- && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
- style = EndianU16_BtoN (mac_style);
- else
- FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
-
- return style;
-}
-
-static ATSUFontID
-atsu_find_font_from_family_name (family)
- const char *family;
-{
- struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
- unsigned hash_code;
- int i;
- Lisp_Object rest, best;
- FMFontStyle min_style, style;
-
- i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
- &hash_code);
- if (i < 0)
- return kATSUInvalidFontID;
-
- rest = HASH_VALUE (h, i);
- if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
- return cons_to_long (rest);
-
- rest = Fnreverse (rest);
- best = XCAR (rest);
- rest = XCDR (rest);
- if (!NILP (rest)
- && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
- do
- {
- style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
- if (style < min_style)
- {
- best = XCAR (rest);
- if (style == normal)
- break;
- else
- min_style = style;
- }
- rest = XCDR (rest);
- }
- while (!NILP (rest));
-
- HASH_VALUE (h, i) = best;
- return cons_to_long (best);
-}
-
-static Lisp_Object
-fm_style_to_face_attributes (fm_style)
- FMFontStyle fm_style;
-{
- Lisp_Object tem;
-
- fm_style &= (bold | italic);
- tem = assq_no_quit (make_number (fm_style),
- fm_style_face_attributes_alist);
- if (!NILP (tem))
- return XCDR (tem);
-
- tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
- QCslant, fm_style & italic ? Qitalic : Qnormal);
- fm_style_face_attributes_alist =
- Fcons (Fcons (make_number (fm_style), tem),
- fm_style_face_attributes_alist);
-
- return tem;
-}
-
-static Lisp_Object
-atsu_find_font_family_name (font_id)
- ATSUFontID font_id;
-{
- OSStatus err;
- ByteCount len;
- Lisp_Object family = Qnil;
-
- err = ATSUFindFontName (font_id, kFontFamilyName,
- kFontMacintoshPlatform, kFontNoScript,
- kFontNoLanguage, 0, NULL, &len, NULL);
- if (err == noErr)
- {
- family = make_uninit_string (len);
- err = ATSUFindFontName (font_id, kFontFamilyName,
- kFontMacintoshPlatform, kFontNoScript,
- kFontNoLanguage, len, SDATA (family),
- NULL, NULL);
- }
- if (err == noErr)
- decode_mac_font_name (SDATA (family), len + 1, Qnil);
-
- return family;
-}
-
-Lisp_Object
-mac_atsu_font_face_attributes (font_id)
- ATSUFontID font_id;
-{
- Lisp_Object family, style_attrs;
-
- family = atsu_find_font_family_name (font_id);
- if (NILP (family))
- return Qnil;
- style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
- return Fcons (QCfamily, Fcons (family, style_attrs));
-}
-#endif
-
-/* Sets up the table font_name_table to contain the list of all fonts
- in the system the first time the table is used so that the Resource
- Manager need not be accessed every time this information is
- needed. */
-
-static void
-init_font_name_table ()
-{
-#if TARGET_API_MAC_CARBON
- FMFontFamilyIterator ffi;
- FMFontFamilyInstanceIterator ffii;
- FMFontFamily ff;
- Lisp_Object text_encoding_info_alist;
- struct gcpro gcpro1;
-
- text_encoding_info_alist = create_text_encoding_info_alist ();
-
-#if USE_ATSUI
-#if USE_CG_TEXT_DRAWING
- init_cg_text_anti_aliasing_threshold ();
-#endif
- if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
- text_encoding_info_alist)))
- {
- OSStatus err;
- struct Lisp_Hash_Table *h;
- unsigned hash_code;
- ItemCount nfonts, i;
- ATSUFontID *font_ids = NULL;
- Lisp_Object prev_family = Qnil;
- int j;
-
- atsu_font_id_hash =
- make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
- make_float (DEFAULT_REHASH_SIZE),
- make_float (DEFAULT_REHASH_THRESHOLD),
- Qnil, Qnil, Qnil);
- h = XHASH_TABLE (atsu_font_id_hash);
-
- err = ATSUFontCount (&nfonts);
- if (err == noErr)
- {
- font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
- err = ATSUGetFontIDs (font_ids, nfonts, NULL);
- }
- if (err == noErr)
- for (i = 0; i < nfonts; i++)
- {
- Lisp_Object family;
-
- family = atsu_find_font_family_name (font_ids[i]);
- if (NILP (family) || SREF (family, 0) == '.')
- continue;
- if (!NILP (Fequal (prev_family, family)))
- family = prev_family;
- else
- j = hash_lookup (h, family, &hash_code);
- if (j < 0)
- {
- add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
- j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
- Qnil), hash_code);
- }
- else if (EQ (prev_family, family))
- HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
- HASH_VALUE (h, j));
- prev_family = family;
- }
- xfree (font_ids);
- }
-#endif
-
- /* Create a dummy instance iterator here to avoid creating and
- destroying it in the loop. */
- if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
- return;
- /* Create an iterator to enumerate the font families. */
- if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
- != noErr)
- {
- FMDisposeFontFamilyInstanceIterator (&ffii);
- return;
- }
-
- GCPRO1 (text_encoding_info_alist);
-
- while (FMGetNextFontFamily (&ffi, &ff) == noErr)
- {
- Str255 name;
- FMFont font;
- FMFontStyle style;
- FMFontSize size;
- TextEncoding encoding;
- TextEncodingBase sc;
- Lisp_Object text_encoding_info, family;
-
- if (FMGetFontFamilyName (ff, name) != noErr)
- continue;
- p2cstr (name);
- if (*name == '.')
- continue;
-
- if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
- continue;
- sc = GetTextEncodingBase (encoding);
- text_encoding_info = assq_no_quit (make_number (sc),
- text_encoding_info_alist);
- if (NILP (text_encoding_info))
- text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
- text_encoding_info_alist);
- decode_mac_font_name (name, sizeof (name),
- XCAR (XCDR (text_encoding_info)));
- family = build_string (name);
- if (!NILP (Fassoc (family, fm_font_family_alist)))
- continue;
- fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
- fm_font_family_alist);
-
- /* Point the instance iterator at the current font family. */
- if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
- continue;
-
- while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
- == noErr)
- {
- Lisp_Object rest = XCDR (XCDR (text_encoding_info));
-
- if (size > 0 || style == normal)
- for (; CONSP (rest); rest = XCDR (rest))
- add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
- }
- }
-
- UNGCPRO;
-
- /* Dispose of the iterators. */
- FMDisposeFontFamilyIterator (&ffi);
- FMDisposeFontFamilyInstanceIterator (&ffii);
-#else /* !TARGET_API_MAC_CARBON */
- GrafPtr port;
- SInt16 fontnum, old_fontnum;
- int num_mac_fonts = CountResources('FOND');
- int i, j;
- Handle font_handle, font_handle_2;
- short id, scriptcode;
- ResType type;
- Str255 name;
- struct FontAssoc *fat;
- struct AsscEntry *assc_entry;
- Lisp_Object text_encoding_info_alist, text_encoding_info, family;
- struct gcpro gcpro1;
-
- GetPort (&port); /* save the current font number used */
- old_fontnum = port->txFont;
-
- text_encoding_info_alist = create_text_encoding_info_alist ();
-
- GCPRO1 (text_encoding_info_alist);
-
- for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
- {
- font_handle = GetIndResource ('FOND', i);
- if (!font_handle)
- continue;
-
- GetResInfo (font_handle, &id, &type, name);
- GetFNum (name, &fontnum);
- p2cstr (name);
- if (fontnum == 0 || *name == '.')
- continue;
-
- TextFont (fontnum);
- scriptcode = FontToScript (fontnum);
- text_encoding_info = assq_no_quit (make_number (scriptcode),
- text_encoding_info_alist);
- if (NILP (text_encoding_info))
- text_encoding_info = assq_no_quit (make_number (smRoman),
- text_encoding_info_alist);
- decode_mac_font_name (name, sizeof (name),
- XCAR (XCDR (text_encoding_info)));
- family = build_string (name);
- if (!NILP (Fassoc (family, fm_font_family_alist)))
- continue;
- fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
- fm_font_family_alist);
- do
- {
- HLock (font_handle);
-
- if (GetResourceSizeOnDisk (font_handle)
- >= sizeof (struct FamRec))
- {
- fat = (struct FontAssoc *) (*font_handle
- + sizeof (struct FamRec));
- assc_entry
- = (struct AsscEntry *) (*font_handle
- + sizeof (struct FamRec)
- + sizeof (struct FontAssoc));
-
- for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
- {
- Lisp_Object rest = XCDR (XCDR (text_encoding_info));
-
- for (; CONSP (rest); rest = XCDR (rest))
- add_mac_font_name (name, assc_entry->fontSize,
- assc_entry->fontStyle,
- SDATA (XCAR (rest)));
- }
- }
-
- HUnlock (font_handle);
- font_handle_2 = GetNextFOND (font_handle);
- ReleaseResource (font_handle);
- font_handle = font_handle_2;
- }
- while (ResError () == noErr && font_handle);
- }
-
- UNGCPRO;
-
- TextFont (old_fontnum);
-#endif /* !TARGET_API_MAC_CARBON */
-}
-
-
-void
-mac_clear_font_name_table ()
-{
- int i;
-
- for (i = 0; i < font_name_count; i++)
- xfree (font_name_table[i]);
- xfree (font_name_table);
- font_name_table = NULL;
- font_name_table_size = font_name_count = 0;
- fm_font_family_alist = Qnil;
-}
-
-
-enum xlfd_scalable_field_index
- {
- XLFD_SCL_PIXEL_SIZE,
- XLFD_SCL_POINT_SIZE,
- XLFD_SCL_AVGWIDTH,
- XLFD_SCL_LAST
- };
-
-static const int xlfd_scalable_fields[] =
- {
- 6, /* PIXEL_SIZE */
- 7, /* POINT_SIZE */
- 11, /* AVGWIDTH */
- -1
- };
-
-static Lisp_Object
-mac_do_list_fonts (pattern, maxnames)
- const char *pattern;
- int maxnames;
-{
- int i, n_fonts = 0;
- Lisp_Object font_list = Qnil;
- struct xlfdpat *pat;
- char *scaled;
- const char *ptr;
- int scl_val[XLFD_SCL_LAST], *val;
- const int *field;
- int exact;
-
- if (font_name_table == NULL) /* Initialize when first used. */
- init_font_name_table ();
-
- for (i = 0; i < XLFD_SCL_LAST; i++)
- scl_val[i] = -1;
-
- /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
- POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
- fonts are scaled according to the specified size. */
- ptr = pattern;
- i = 0;
- field = xlfd_scalable_fields;
- val = scl_val;
- if (*ptr == '-')
- do
- {
- ptr++;
- if (i == *field)
- {
- if ('0' <= *ptr && *ptr <= '9')
- {
- *val = *ptr++ - '0';
- while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
- *val = *val * 10 + *ptr++ - '0';
- if (*ptr != '-')
- *val = -1;
- }
- field++;
- val++;
- }
- ptr = strchr (ptr, '-');
- i++;
- }
- while (ptr && i < 14);
-
- if (i == 14 && ptr == NULL)
- {
- if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
- scl_val[XLFD_SCL_PIXEL_SIZE] =
- (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
- : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
- : -1));
- if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
- scl_val[XLFD_SCL_POINT_SIZE] =
- (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
- : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
- : -1));
- if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
- scl_val[XLFD_SCL_AVGWIDTH] =
- (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
- : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
- : -1));
- }
- else
- scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
-
- pat = xlfdpat_create (pattern);
- if (pat == NULL)
- return Qnil;
-
- exact = xlfdpat_exact_p (pat);
-
- for (i = 0; i < font_name_count; i++)
- {
- if (xlfdpat_match (pat, font_name_table[i]))
- {
- font_list = Fcons (build_string (font_name_table[i]), font_list);
- if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
- break;
- }
- else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
- && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
- {
- int former_len = ptr - font_name_table[i];
-
- scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
- memcpy (scaled, font_name_table[i], former_len);
- sprintf (scaled + former_len,
- "-%d-%d-72-72-m-%d-%s",
- scl_val[XLFD_SCL_PIXEL_SIZE],
- scl_val[XLFD_SCL_POINT_SIZE],
- scl_val[XLFD_SCL_AVGWIDTH],
- ptr + sizeof ("-0-0-0-0-m-0-") - 1);
-
- if (xlfdpat_match (pat, scaled))
- {
- font_list = Fcons (build_string (scaled), font_list);
- xfree (scaled);
- if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
- break;
- }
- else
- xfree (scaled);
- }
- }
-
- xlfdpat_destroy (pat);
-
- return font_list;
-}
-
-/* Return a list of names of available fonts matching PATTERN on frame F.
-
- Frame F null means we have not yet created any frame on Mac, and
- consult the first display in x_display_list. MAXNAMES sets a limit
- on how many fonts to match. */
-
-Lisp_Object
-x_list_fonts (f, pattern, size, maxnames)
- struct frame *f;
- Lisp_Object pattern;
- int size, maxnames;
-{
- Lisp_Object list = Qnil, patterns, tem, key;
- struct mac_display_info *dpyinfo
- = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
-
- xassert (size <= 0);
-
- patterns = Fassoc (pattern, Valternate_fontname_alist);
- if (NILP (patterns))
- patterns = Fcons (pattern, Qnil);
-
- for (; CONSP (patterns); patterns = XCDR (patterns))
- {
- pattern = XCAR (patterns);
-
- if (!STRINGP (pattern))
- continue;
-
- tem = XCAR (XCDR (dpyinfo->name_list_element));
- key = Fcons (pattern, make_number (maxnames));
-
- list = Fassoc (key, tem);
- if (!NILP (list))
- {
- list = Fcdr_safe (list);
- /* We have a cashed list. Don't have to get the list again. */
- goto label_cached;
- }
-
- BLOCK_INPUT;
- list = mac_do_list_fonts (SDATA (pattern), maxnames);
- UNBLOCK_INPUT;
-
- /* MAC_TODO: add code for matching outline fonts here */
-
- /* Now store the result in the cache. */
- XSETCAR (XCDR (dpyinfo->name_list_element),
- Fcons (Fcons (key, list),
- XCAR (XCDR (dpyinfo->name_list_element))));
-
- label_cached:
- if (NILP (list)) continue; /* Try the remaining alternatives. */
- }
-
- return list;
-}
-
-
-#if GLYPH_DEBUG
-
-/* Check that FONT is valid on frame F. It is if it can be found in F's
- font table. */
-
-static void
-x_check_font (f, font)
- struct frame *f;
- XFontStruct *font;
-{
- int i;
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-
- xassert (font != NULL);
-
- for (i = 0; i < dpyinfo->n_fonts; i++)
- if (dpyinfo->font_table[i].name
- && font == dpyinfo->font_table[i].font)
- break;
-
- xassert (i < dpyinfo->n_fonts);
-}
-
-#endif /* GLYPH_DEBUG != 0 */
-
-/* Set *W to the minimum width, *H to the minimum font height of FONT.
- Note: There are (broken) X fonts out there with invalid XFontStruct
- min_bounds contents. For example, handa@etl.go.jp reports that
- "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
- have font->min_bounds.width == 0. */
-
-static INLINE void
-x_font_min_bounds (font, w, h)
- MacFontStruct *font;
- int *w, *h;
-{
- *h = FONT_HEIGHT (font);
- *w = font->min_bounds.width;
-}
-
-
-/* Compute the smallest character width and smallest font height over
- all fonts available on frame F. Set the members smallest_char_width
- and smallest_font_height in F's x_display_info structure to
- the values computed. Value is non-zero if smallest_font_height or
- smallest_char_width become smaller than they were before. */
-
-static int
-x_compute_min_glyph_bounds (f)
- struct frame *f;
-{
- int i;
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- MacFontStruct *font;
- int old_width = dpyinfo->smallest_char_width;
- int old_height = dpyinfo->smallest_font_height;
-
- dpyinfo->smallest_font_height = 100000;
- dpyinfo->smallest_char_width = 100000;
-
- for (i = 0; i < dpyinfo->n_fonts; ++i)
- if (dpyinfo->font_table[i].name)
- {
- struct font_info *fontp = dpyinfo->font_table + i;
- int w, h;
-
- font = (MacFontStruct *) fontp->font;
- xassert (font != (MacFontStruct *) ~0);
- x_font_min_bounds (font, &w, &h);
-
- dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
- dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
- }
-
- xassert (dpyinfo->smallest_char_width > 0
- && dpyinfo->smallest_font_height > 0);
-
- return (dpyinfo->n_fonts == 1
- || dpyinfo->smallest_char_width < old_width
- || dpyinfo->smallest_font_height < old_height);
-}
-
-
-/* Determine whether given string is a fully-specified XLFD: all 14
- fields are present, none is '*'. */
-
-static int
-is_fully_specified_xlfd (p)
- const char *p;
-{
- int i;
- char *q;
-
- if (*p != '-')
- return 0;
-
- for (i = 0; i < 13; i++)
- {
- q = strchr (p + 1, '-');
- if (q == NULL)
- return 0;
- if (q - p == 2 && *(p + 1) == '*')
- return 0;
- p = q;
- }
-
- if (strchr (p + 1, '-') != NULL)
- return 0;
-
- if (*(p + 1) == '*' && *(p + 2) == '\0')
- return 0;
-
- return 1;
-}
-
-
-/* mac_load_query_font creates and returns an internal representation
- for a font in a MacFontStruct struct. There is really no concept
- corresponding to "loading" a font on the Mac. But we check its
- existence and find the font number and all other information for it
- and store them in the returned MacFontStruct. */
-
-static MacFontStruct *
-mac_load_query_font (f, fontname)
- struct frame *f;
- char *fontname;
-{
- int size;
- char *name;
- Str255 family;
- Str31 charset;
- SInt16 fontnum;
-#if USE_ATSUI
- static ATSUFontID font_id;
- ATSUStyle mac_style = NULL;
-#endif
- Style fontface;
-#if TARGET_API_MAC_CARBON
- TextEncoding encoding;
- int scriptcode;
-#else
- short scriptcode;
-#endif
- MacFontStruct *font;
- XCharStruct *space_bounds = NULL, *pcm;
-
- if (is_fully_specified_xlfd (fontname))
- name = fontname;
- else
- {
- Lisp_Object matched_fonts;
-
- matched_fonts = mac_do_list_fonts (fontname, 1);
- if (NILP (matched_fonts))
- return NULL;
- name = SDATA (XCAR (matched_fonts));
- }
-
- if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
- return NULL;
-
-#if USE_ATSUI
- if (strcmp (charset, "iso10646-1") == 0) /* XXX */
- {
- OSStatus err;
- static const ATSUAttributeTag tags[] =
- {kATSUFontTag, kATSUSizeTag,
- kATSUQDBoldfaceTag, kATSUQDItalicTag};
- static const ByteCount sizes[] =
- {sizeof (ATSUFontID), sizeof (Fixed),
- sizeof (Boolean), sizeof (Boolean)};
- static Fixed size_fixed;
- static Boolean bold_p, italic_p;
- static const ATSUAttributeValuePtr values[] =
- {&font_id, &size_fixed,
- &bold_p, &italic_p};
- static const ATSUFontFeatureType types[] =
- {kAllTypographicFeaturesType, kDiacriticsType};
- static const ATSUFontFeatureSelector selectors[] =
- {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
- FMFontStyle style;
-
- font_id = atsu_find_font_from_family_name (family);
- if (font_id == kATSUInvalidFontID)
- return NULL;
- size_fixed = Long2Fix (size);
- bold_p = (fontface & bold) != 0;
- italic_p = (fontface & italic) != 0;
- err = ATSUCreateStyle (&mac_style);
- if (err != noErr)
- return NULL;
- err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
- types, selectors);
- if (err != noErr)
- return NULL;
- err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
- tags, sizes, values);
- if (err != noErr)
- return NULL;
- err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
- if (err != noErr)
- fontnum = -1;
- scriptcode = kTextEncodingMacUnicode;
- }
- else
-#endif
- {
- Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
-
- if (NILP (tmp))
- return NULL;
- fontnum = XINT (XCDR (tmp));
-#if TARGET_API_MAC_CARBON
- if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
- return NULL;
- scriptcode = GetTextEncodingBase (encoding);
-#else
- scriptcode = FontToScript (fontnum);
-#endif
- }
-
- font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
-
- font->mac_fontnum = fontnum;
- font->mac_fontsize = size;
- font->mac_fontface = fontface;
- font->mac_scriptcode = scriptcode;
-#if USE_ATSUI
- font->mac_style = mac_style;
-#if USE_CG_TEXT_DRAWING
- font->cg_font = NULL;
- font->cg_glyphs = NULL;
-#endif
-#endif
-
- /* Apple Japanese (SJIS) font is listed as both
- "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
- (Roman script) in init_font_name_table (). The latter should be
- treated as a one-byte font. */
- if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
- font->mac_scriptcode = smRoman;
-
- font->full_name = mac_to_x_fontname (family, size, fontface, charset);
-
-#if USE_ATSUI
- if (font->mac_style)
- {
- OSStatus err;
- UniChar c;
-
- font->min_byte1 = 0;
- font->max_byte1 = 0xff;
- font->min_char_or_byte2 = 0;
- font->max_char_or_byte2 = 0xff;
-
- font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
- bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
- font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
- pcm_init (font->bounds.rows[0], 0x100);
-
-#if USE_CG_TEXT_DRAWING
- if (fontnum != -1)
- {
- FMFontStyle style;
- ATSFontRef ats_font;
-
- err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
- &font_id, &style);
- /* Use CG text drawing if italic/bold is not synthesized. */
- if (err == noErr && style == fontface)
- {
- ats_font = FMGetATSFontRefFromFont (font_id);
- font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
- }
- }
-
- if (font->cg_font)
- {
- font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
- bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
- }
-#endif
- space_bounds = font->bounds.rows[0] + 0x20;
- err = mac_query_char_extents (font->mac_style, 0x20,
- &font->ascent, &font->descent,
- space_bounds,
-#if USE_CG_TEXT_DRAWING
- (font->cg_glyphs ? font->cg_glyphs + 0x20
- : NULL)
-#else
- NULL
-#endif
- );
- if (err != noErr
- || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
- {
- mac_unload_font (&one_mac_display_info, font);
- return NULL;
- }
-
- pcm = font->bounds.rows[0];
- for (c = 0x21; c <= 0xff; c++)
- {
- if (c == 0xad)
- /* Soft hyphen is not supported in ATSUI. */
- continue;
- else if (c == 0x7f)
- {
-#if USE_CG_TEXT_DRAWING
- if (font->cg_glyphs)
- {
- c = 0x9f;
- pcm = NULL;
- continue;
- }
-#endif
- break;
- }
-
- mac_query_char_extents (font->mac_style, c, NULL, NULL,
- pcm ? pcm + c : NULL,
-#if USE_CG_TEXT_DRAWING
- (font->cg_glyphs ? font->cg_glyphs + c
- : NULL)
-#else
- NULL
-#endif
- );
-
-#if USE_CG_TEXT_DRAWING
- if (font->cg_glyphs && font->cg_glyphs[c] == 0)
- {
- /* Don't use CG text drawing if font substitution occurs in
- ASCII or Latin-1 characters. */
- CGFontRelease (font->cg_font);
- font->cg_font = NULL;
- xfree (font->cg_glyphs);
- font->cg_glyphs = NULL;
- if (pcm == NULL)
- break;
- }
-#endif
- }
- }
- else
-#endif
- {
- OSStatus err;
- FontInfo the_fontinfo;
- int is_two_byte_font;
-
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
- TextFont (fontnum);
- TextSize (size);
- TextFace (fontface);
-
- GetFontInfo (&the_fontinfo);
-
- font->ascent = the_fontinfo.ascent;
- font->descent = the_fontinfo.descent;
-
- is_two_byte_font = (font->mac_scriptcode == smJapanese
- || font->mac_scriptcode == smTradChinese
- || font->mac_scriptcode == smSimpChinese
- || font->mac_scriptcode == smKorean);
-
- if (is_two_byte_font)
- {
- int char_width;
-
- font->min_byte1 = 0xa1;
- font->max_byte1 = 0xfe;
- font->min_char_or_byte2 = 0xa1;
- font->max_char_or_byte2 = 0xfe;
-
- /* Use the width of an "ideographic space" of that font
- because the_fontinfo.widMax returns the wrong width for
- some fonts. */
- switch (font->mac_scriptcode)
- {
- case smJapanese:
- font->min_byte1 = 0x81;
- font->max_byte1 = 0xfc;
- font->min_char_or_byte2 = 0x40;
- font->max_char_or_byte2 = 0xfc;
- char_width = StringWidth("\p\x81\x40");
- break;
- case smTradChinese:
- font->min_char_or_byte2 = 0x40;
- char_width = StringWidth("\p\xa1\x40");
- break;
- case smSimpChinese:
- char_width = StringWidth("\p\xa1\xa1");
- break;
- case smKorean:
- char_width = StringWidth("\p\xa1\xa1");
- break;
- }
-
- font->bounds.per_char = NULL;
-
- if (fontface & italic)
- font->max_bounds.rbearing = char_width + 1;
- else
- font->max_bounds.rbearing = char_width;
- font->max_bounds.lbearing = 0;
- font->max_bounds.width = char_width;
- font->max_bounds.ascent = the_fontinfo.ascent;
- font->max_bounds.descent = the_fontinfo.descent;
-
- font->min_bounds = font->max_bounds;
- }
- else
- {
- int c;
-
- font->min_byte1 = font->max_byte1 = 0;
- font->min_char_or_byte2 = 0x20;
- font->max_char_or_byte2 = 0xff;
-
- font->bounds.per_char =
- xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
- bzero (font->bounds.per_char,
- sizeof (XCharStruct) * (0xff - 0x20 + 1));
-
- space_bounds = font->bounds.per_char;
- err = mac_query_char_extents (NULL, 0x20, &font->ascent,
- &font->descent, space_bounds, NULL);
- if (err != noErr || space_bounds->width <= 0)
- {
- mac_unload_font (&one_mac_display_info, font);
- return NULL;
- }
-
- for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
- mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
- }
- }
-
- if (space_bounds)
- {
- int c;
-
- font->min_bounds = font->max_bounds = *space_bounds;
- for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
- if (pcm->width > 0)
- {
- font->min_bounds.lbearing = min (font->min_bounds.lbearing,
- pcm->lbearing);
- font->min_bounds.rbearing = min (font->min_bounds.rbearing,
- pcm->rbearing);
- font->min_bounds.width = min (font->min_bounds.width,
- pcm->width);
- font->min_bounds.ascent = min (font->min_bounds.ascent,
- pcm->ascent);
- font->min_bounds.descent = min (font->min_bounds.descent,
- pcm->descent);
-
- font->max_bounds.lbearing = max (font->max_bounds.lbearing,
- pcm->lbearing);
- font->max_bounds.rbearing = max (font->max_bounds.rbearing,
- pcm->rbearing);
- font->max_bounds.width = max (font->max_bounds.width,
- pcm->width);
- font->max_bounds.ascent = max (font->max_bounds.ascent,
- pcm->ascent);
- font->max_bounds.descent = max (font->max_bounds.descent,
- pcm->descent);
- }
- if (
-#if USE_ATSUI
- font->mac_style == NULL &&
-#endif
- font->max_bounds.width == font->min_bounds.width
- && font->min_bounds.lbearing >= 0
- && font->max_bounds.rbearing <= font->max_bounds.width)
- {
- /* Fixed width and no overhangs. */
- xfree (font->bounds.per_char);
- font->bounds.per_char = NULL;
- }
- }
-
-#if !defined (MAC_OS8) || USE_ATSUI
- /* AppKit and WebKit do some adjustment to the heights of Courier,
- Helvetica, and Times. This only works on the environments where
- srcCopy text transfer mode is never used. */
- if (
-#ifdef MAC_OS8 /* implies USE_ATSUI */
- font->mac_style &&
-#endif
- (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
- || strcmp (family, "times") == 0))
- font->ascent += (font->ascent + font->descent) * .15 + 0.5;
-#endif
-
- return font;
-}
-
-
-void
-mac_unload_font (dpyinfo, font)
- struct mac_display_info *dpyinfo;
- XFontStruct *font;
-{
- xfree (font->full_name);
-#if USE_ATSUI
- if (font->mac_style)
- {
- int i;
-
- for (i = font->min_byte1; i <= font->max_byte1; i++)
- xfree (font->bounds.rows[i]);
- xfree (font->bounds.rows);
- ATSUDisposeStyle (font->mac_style);
- }
- else
-#endif
- xfree (font->bounds.per_char);
-#if USE_CG_TEXT_DRAWING
- if (font->cg_font)
- CGFontRelease (font->cg_font);
- xfree (font->cg_glyphs);
-#endif
- xfree (font);
-}
-
-
-/* Load font named FONTNAME of the size SIZE for frame F, and return a
- pointer to the structure font_info while allocating it dynamically.
- If SIZE is 0, load any size of font.
- If loading is failed, return NULL. */
-
-struct font_info *
-x_load_font (f, fontname, size)
- struct frame *f;
- register char *fontname;
- int size;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- Lisp_Object font_names;
-
- /* Get a list of all the fonts that match this name. Once we
- have a list of matching fonts, we compare them against the fonts
- we already have by comparing names. */
- font_names = x_list_fonts (f, build_string (fontname), size, 1);
-
- if (!NILP (font_names))
- {
- Lisp_Object tail;
- int i;
-
- for (i = 0; i < dpyinfo->n_fonts; i++)
- for (tail = font_names; CONSP (tail); tail = XCDR (tail))
- if (dpyinfo->font_table[i].name
- && (!strcmp (dpyinfo->font_table[i].name,
- SDATA (XCAR (tail)))
- || !strcmp (dpyinfo->font_table[i].full_name,
- SDATA (XCAR (tail)))))
- return (dpyinfo->font_table + i);
- }
- else
- return NULL;
-
- /* Load the font and add it to the table. */
- {
- struct MacFontStruct *font;
- struct font_info *fontp;
- int i;
-
- fontname = (char *) SDATA (XCAR (font_names));
-
- BLOCK_INPUT;
- font = mac_load_query_font (f, fontname);
- UNBLOCK_INPUT;
- if (!font)
- return NULL;
-
- /* Find a free slot in the font table. */
- for (i = 0; i < dpyinfo->n_fonts; ++i)
- if (dpyinfo->font_table[i].name == NULL)
- break;
-
- /* If no free slot found, maybe enlarge the font table. */
- if (i == dpyinfo->n_fonts
- && dpyinfo->n_fonts == dpyinfo->font_table_size)
- {
- int sz;
- dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
- sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
- dpyinfo->font_table
- = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
- }
-
- fontp = dpyinfo->font_table + i;
- if (i == dpyinfo->n_fonts)
- ++dpyinfo->n_fonts;
-
- /* Now fill in the slots of *FONTP. */
- BLOCK_INPUT;
- bzero (fontp, sizeof (*fontp));
- fontp->font = font;
- fontp->font_idx = i;
- fontp->charset = -1; /* fs_load_font sets it. */
- fontp->name = (char *) xmalloc (strlen (fontname) + 1);
- bcopy (fontname, fontp->name, strlen (fontname) + 1);
-
- if (font->min_bounds.width == font->max_bounds.width)
- {
- /* Fixed width font. */
- fontp->average_width = fontp->space_width = font->min_bounds.width;
- }
- else
- {
- XChar2b char2b;
- XCharStruct *pcm;
-
- char2b.byte1 = 0x00, char2b.byte2 = 0x20;
- pcm = mac_per_char_metric (font, &char2b, 0);
- if (pcm)
- fontp->space_width = pcm->width;
- else
- fontp->space_width = FONT_WIDTH (font);
-
- if (pcm)
- {
- int width = pcm->width;
- for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
- if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
- width += pcm->width;
- fontp->average_width = width / 95;
- }
- else
- fontp->average_width = FONT_WIDTH (font);
- }
-
- fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
- bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
-
- fontp->size = font->max_bounds.width;
- fontp->height = FONT_HEIGHT (font);
- {
- /* For some font, ascent and descent in max_bounds field is
- larger than the above value. */
- int max_height = font->max_bounds.ascent + font->max_bounds.descent;
- if (max_height > fontp->height)
- fontp->height = max_height;
- }
-
- /* MAC_TODO: The script encoding is irrelevant in unicode? */
- /* The slot `encoding' specifies how to map a character
- code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
- the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
- (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
- 2:0xA020..0xFF7F). For the moment, we don't know which charset
- uses this font. So, we set information in fontp->encoding_type
- which is never used by any charset. If mapping can't be
- decided, set FONT_ENCODING_NOT_DECIDED. */
- if (font->mac_scriptcode == smJapanese)
- fontp->encoding_type = 4;
- else
- {
- fontp->encoding_type
- = (font->max_byte1 == 0
- /* 1-byte font */
- ? (font->min_char_or_byte2 < 0x80
- ? (font->max_char_or_byte2 < 0x80
- ? 0 /* 0x20..0x7F */
- : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
- : 1) /* 0xA0..0xFF */
- /* 2-byte font */
- : (font->min_byte1 < 0x80
- ? (font->max_byte1 < 0x80
- ? (font->min_char_or_byte2 < 0x80
- ? (font->max_char_or_byte2 < 0x80
- ? 0 /* 0x2020..0x7F7F */
- : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
- : 3) /* 0x20A0..0x7FFF */
- : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
- : (font->min_char_or_byte2 < 0x80
- ? (font->max_char_or_byte2 < 0x80
- ? 2 /* 0xA020..0xFF7F */
- : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
- : 1))); /* 0xA0A0..0xFFFF */
- }
-
-#if 0 /* MAC_TODO: fill these out with more reasonably values */
- fontp->baseline_offset
- = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
- ? (long) value : 0);
- fontp->relative_compose
- = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
- ? (long) value : 0);
- fontp->default_ascent
- = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
- ? (long) value : 0);
-#else
- fontp->baseline_offset = 0;
- fontp->relative_compose = 0;
- fontp->default_ascent = 0;
-#endif
-
- /* Set global flag fonts_changed_p to non-zero if the font loaded
- has a character with a smaller width than any other character
- before, or if the font loaded has a smaller height than any
- other font loaded before. If this happens, it will make a
- glyph matrix reallocation necessary. */
- fonts_changed_p |= x_compute_min_glyph_bounds (f);
- UNBLOCK_INPUT;
- return fontp;
- }
-}
-
-
-/* Return a pointer to struct font_info of a font named FONTNAME for
- frame F. If no such font is loaded, return NULL. */
-
-struct font_info *
-x_query_font (f, fontname)
- struct frame *f;
- register char *fontname;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- int i;
-
- for (i = 0; i < dpyinfo->n_fonts; i++)
- if (dpyinfo->font_table[i].name
- && (!xstrcasecmp (dpyinfo->font_table[i].name, fontname)
- || !xstrcasecmp (dpyinfo->font_table[i].full_name, fontname)))
- return (dpyinfo->font_table + i);
- return NULL;
-}
-
-
-/* Find a CCL program for a font specified by FONTP, and set the member
- `encoder' of the structure. */
-
-void
-x_find_ccl_program (fontp)
- struct font_info *fontp;
-{
- Lisp_Object list, elt;
-
- for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
- {
- elt = XCAR (list);
- if (CONSP (elt)
- && STRINGP (XCAR (elt))
- && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
- >= 0))
- break;
- }
- if (! NILP (list))
- {
- struct ccl_program *ccl
- = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
-
- if (setup_ccl_program (ccl, XCDR (elt)) < 0)
- xfree (ccl);
- else
- fontp->font_encoder = ccl;
- }
-}
-
-#if USE_MAC_FONT_PANEL
-/* Whether Font Panel has been shown before. The first call to font
- panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
- slow. This variable is used for deferring such a call as much as
- possible. */
-static int font_panel_shown_p = 0;
-
-extern Lisp_Object Qfont;
-static Lisp_Object Qpanel_closed, Qselection;
-
-static OSStatus mac_store_event_ref_as_apple_event P_ ((AEEventClass, AEEventID,
- Lisp_Object,
- Lisp_Object,
- EventRef, UInt32,
- const EventParamName *,
- const EventParamType *));
-
-int
-mac_font_panel_visible_p ()
-{
- return font_panel_shown_p && FPIsFontPanelVisible ();
-}
-
-static pascal OSStatus
-mac_handle_font_event (next_handler, event, data)
- EventHandlerCallRef next_handler;
- EventRef event;
- void *data;
-{
- OSStatus result, err;
- Lisp_Object id_key;
- int num_params;
- const EventParamName *names;
- const EventParamType *types;
- static const EventParamName names_sel[] = {kEventParamATSUFontID,
- kEventParamATSUFontSize,
- kEventParamFMFontFamily,
- kEventParamFMFontStyle,
- kEventParamFMFontSize,
- kEventParamFontColor};
- static const EventParamType types_sel[] = {typeATSUFontID,
- typeATSUSize,
- typeFMFontFamily,
- typeFMFontStyle,
- typeFMFontSize,
- typeFontColor};
-
- result = CallNextEventHandler (next_handler, event);
- if (result != eventNotHandledErr)
- return result;
-
- switch (GetEventKind (event))
- {
- case kEventFontPanelClosed:
- id_key = Qpanel_closed;
- num_params = 0;
- names = NULL;
- types = NULL;
- break;
-
- case kEventFontSelection:
- id_key = Qselection;
- num_params = sizeof (names_sel) / sizeof (names_sel[0]);
- names = names_sel;
- types = types_sel;
- break;
- }
-
- err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
- event, num_params,
- names, types);
- if (err == noErr)
- result = noErr;
-
- return result;
-}
-
-OSStatus
-mac_show_hide_font_panel ()
-{
- if (!font_panel_shown_p)
- {
- OSStatus err;
-
- static const EventTypeSpec specs[] =
- {{kEventClassFont, kEventFontPanelClosed},
- {kEventClassFont, kEventFontSelection}};
-
- err = InstallApplicationEventHandler (mac_handle_font_event,
- GetEventTypeCount (specs),
- specs, NULL, NULL);
- if (err != noErr)
- return err;
-
- font_panel_shown_p = 1;
- }
-
- return FPShowHideFontPanel ();
-}
-
-OSStatus
-mac_set_font_info_for_selection (f, face_id, c)
- struct frame *f;
- int face_id, c;
-{
- OSStatus err;
- EventTargetRef target = NULL;
- XFontStruct *font = NULL;
-
- if (!mac_font_panel_visible_p ())
- return noErr;
-
- if (f)
- {
- target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
-
- if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
- {
- struct face *face;
-
- face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
- face = FACE_FROM_ID (f, face_id);
- font = face->font;
- }
- }
-
- if (font == NULL)
- err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
- else
- {
- if (font->mac_fontnum != -1)
- {
- FontSelectionQDStyle qd_style;
-
- qd_style.version = kFontSelectionQDStyleVersionZero;
- qd_style.instance.fontFamily = font->mac_fontnum;
- qd_style.instance.fontStyle = font->mac_fontface;
- qd_style.size = font->mac_fontsize;
- qd_style.hasColor = false;
-
- err = SetFontInfoForSelection (kFontSelectionQDType,
- 1, &qd_style, target);
- }
- else
- err = SetFontInfoForSelection (kFontSelectionATSUIType,
- 1, &font->mac_style, target);
- }
-
- return err;
-}
-#endif
-
-
-/* The Mac Event loop code */
-
-#if !TARGET_API_MAC_CARBON
-#include <Events.h>
-#include <Quickdraw.h>
-#include <Balloons.h>
-#include <Devices.h>
-#include <Fonts.h>
-#include <Gestalt.h>
-#include <Menus.h>
-#include <Processes.h>
-#include <Sound.h>
-#include <ToolUtils.h>
-#include <TextUtils.h>
-#include <Dialogs.h>
-#include <Script.h>
-#include <Types.h>
-#include <Resources.h>
-
-#if __MWERKS__
-#include <unix.h>
-#endif
-#endif /* ! TARGET_API_MAC_CARBON */
-
-#define M_APPLE 234
-#define I_ABOUT 1
-
-#define DEFAULT_NUM_COLS 80
-
-#define MIN_DOC_SIZE 64
-#define MAX_DOC_SIZE 32767
-
-#define EXTRA_STACK_ALLOC (256 * 1024)
-
-#define ARGV_STRING_LIST_ID 129
-#define ABOUT_ALERT_ID 128
-#define RAM_TOO_LARGE_ALERT_ID 129
-
-/* Contains the string "reverse", which is a constant for mouse button emu.*/
-Lisp_Object Qreverse;
-
-
-/* Modifier associated with the control key, or nil to ignore. */
-Lisp_Object Vmac_control_modifier;
-
-/* Modifier associated with the option key, or nil to ignore. */
-Lisp_Object Vmac_option_modifier;
-
-/* Modifier associated with the command key, or nil to ignore. */
-Lisp_Object Vmac_command_modifier;
-
-/* Modifier associated with the function key, or nil to ignore. */
-Lisp_Object Vmac_function_modifier;
-
-/* True if the option and command modifiers should be used to emulate
- a three button mouse */
-Lisp_Object Vmac_emulate_three_button_mouse;
-
-#if TARGET_API_MAC_CARBON
-/* Non-zero if the mouse wheel button (i.e. button 4) should map to
- mouse-2, instead of mouse-3. */
-int mac_wheel_button_is_mouse_2;
-
-/* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
- for processing before Emacs sees it. */
-int mac_pass_command_to_system;
-
-/* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
- for processing before Emacs sees it. */
-int mac_pass_control_to_system;
-#endif
-
-/* Points to the variable `inev' in the function XTread_socket. It is
- used for passing an input event to the function back from
- Carbon/Apple event handlers. */
-static struct input_event *read_socket_inev = NULL;
-
-/* Whether or not the screen configuration has changed. */
-static int mac_screen_config_changed = 0;
-
-Point saved_menu_event_location;
-
-/* Apple Events */
-#if TARGET_API_MAC_CARBON
-static Lisp_Object Qhi_command;
-#ifdef MAC_OSX
-extern Lisp_Object Qwindow;
-static Lisp_Object Qtoolbar_switch_mode;
-#endif
-#if USE_MAC_TSM
-static TSMDocumentID tsm_document_id;
-Lisp_Object Qtext_input;
-Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
-Lisp_Object Vmac_ts_active_input_overlay, Vmac_ts_active_input_buf;
-extern Lisp_Object Qbefore_string;
-static Lisp_Object Vmac_ts_script_language_on_focus;
-static Lisp_Object saved_ts_script_language_on_focus;
-static ScriptLanguageRecord saved_ts_language;
-static Component saved_ts_component;
-#endif
-#endif /* TARGET_API_MAC_CARBON */
-extern int mac_ready_for_apple_events;
-extern Lisp_Object Qundefined;
-extern void init_apple_event_handler P_ ((void));
-extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
- Lisp_Object *, Lisp_Object *,
- Lisp_Object *));
-extern OSErr init_coercion_handler P_ ((void));
-
-/* Drag and Drop */
-extern OSErr install_drag_handler P_ ((WindowRef));
-extern void remove_drag_handler P_ ((WindowRef));
-
-#if TARGET_API_MAC_CARBON
-/* Showing help echo string during menu tracking */
-extern OSStatus install_menu_target_item_handler P_ ((void));
-
-#ifdef MAC_OSX
-extern OSStatus install_service_handler ();
-Lisp_Object Qservice, Qpaste, Qperform;
-Lisp_Object Qmouse_drag_overlay;
-#endif
-#endif
-
-extern void init_emacs_passwd_dir ();
-extern int emacs_main (int, char **, char **);
-
-extern void initialize_applescript();
-extern void terminate_applescript();
-
-/* Table for translating Mac keycode to X keysym values. Contributed
- by Sudhir Shenoy.
- Mapping for special keys is now identical to that in Apple X11
- except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
- on the right of the Cmd key on laptops, and fn + `enter' (->
- <linefeed>). */
-static const unsigned char keycode_to_xkeysym_table[] = {
- /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
- /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
- /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
- /*0x38*/ 0, 0, 0, 0,
- /*0x3C*/ 0, 0, 0, 0,
-
- /*0x40*/ 0xce /*f17*/, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
- /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
- /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
- /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0xcf /*f18*/,
-
- /*0x50*/ 0xd0 /*f19*/, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
- /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
- /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
- /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
-
- /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
- /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
- /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
- /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
-
- /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
- /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
- /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
- /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
-};
-
-#ifdef MAC_OSX
-/* Table for translating Mac keycode with the laptop `fn' key to that
- without it. Destination symbols in comments are keys on US
- keyboard, and they may not be the same on other types of keyboards.
- If the destination is identical to the source (f1 ... f12), it
- doesn't map `fn' key to a modifier. */
-static const unsigned char fn_keycode_to_keycode_table[] = {
- /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
- /*0x30*/ 0, 0, 0, 0,
- /*0x34*/ 0, 0, 0, 0,
- /*0x38*/ 0, 0, 0, 0,
- /*0x3C*/ 0, 0, 0, 0,
-
- /*0x40*/ 0x40 /*f17 = f17*/, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
- /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
- /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
- /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0x4f /*f18 = f18*/,
-
- /*0x50*/ 0x50 /*f19 = f19*/, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
- /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
- /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
- /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
-
- /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
- /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
- /*0x68*/ 0, 0, 0, 0,
- /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
-
- /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
- /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
- /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
- /*0x7C*/ 0, 0, 0, 0
-};
-#endif /* MAC_OSX */
-
-static int
-#if TARGET_API_MAC_CARBON
-mac_to_emacs_modifiers (UInt32 mods)
-#else
-mac_to_emacs_modifiers (EventModifiers mods)
-#endif
-{
- unsigned int result = 0;
- if (mods & shiftKey)
- result |= shift_modifier;
-
- /* Deactivated to simplify configuration:
- if Vmac_option_modifier is non-NIL, we fully process the Option
- key. Otherwise, we only process it if an additional Ctrl or Command
- is pressed. That way the system may convert the character to a
- composed one.
- if ((mods & optionKey) &&
- (( !NILP(Vmac_option_modifier) ||
- ((mods & cmdKey) || (mods & controlKey))))) */
-
- if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
- Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
- if (INTEGERP(val))
- result |= XUINT(val);
- }
- if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
- Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
- if (INTEGERP(val))
- result |= XUINT(val);
- }
- if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
- Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
- if (INTEGERP(val))
- result |= XUINT(val);
- }
-
-#ifdef MAC_OSX
- if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
- Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
- if (INTEGERP(val))
- result |= XUINT(val);
- }
-#endif
-
- return result;
-}
-
-static UInt32
-mac_mapped_modifiers (modifiers)
- UInt32 modifiers;
-{
- UInt32 mapped_modifiers_all =
- (NILP (Vmac_control_modifier) ? 0 : controlKey)
- | (NILP (Vmac_option_modifier) ? 0 : optionKey)
- | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
-
-#ifdef MAC_OSX
- mapped_modifiers_all |=
- (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
-#endif
-
- return mapped_modifiers_all & modifiers;
-}
-
-static int
-mac_get_emulated_btn ( UInt32 modifiers )
-{
- int result = 0;
- if (!NILP (Vmac_emulate_three_button_mouse)) {
- int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
- if (modifiers & cmdKey)
- result = cmdIs3 ? 2 : 1;
- else if (modifiers & optionKey)
- result = cmdIs3 ? 1 : 2;
- }
- return result;
-}
-
-#ifdef MAC_OSX
-void
-mac_get_selected_range (w, range)
- struct window *w;
- CFRange *range;
-{
- Lisp_Object overlay = find_symbol_value (Qmouse_drag_overlay);
- struct buffer *b = XBUFFER (w->buffer);
- int begv = BUF_BEGV (b), zv = BUF_ZV (b);
- int start, end;
-
- if (OVERLAYP (overlay)
- && EQ (Foverlay_buffer (overlay), w->buffer)
- && (start = XINT (Foverlay_start (overlay)),
- end = XINT (Foverlay_end (overlay)),
- start != end))
- ;
- else
- {
- if (w == XWINDOW (selected_window) && b == current_buffer)
- start = PT;
- else
- start = marker_position (w->pointm);
-
- if (NILP (Vtransient_mark_mode) || NILP (b->mark_active))
- end = start;
- else
- {
- int mark_pos = marker_position (b->mark);
-
- if (start <= mark_pos)
- end = mark_pos;
- else
- {
- end = start;
- start = mark_pos;
- }
- }
- }
-
- if (start != end)
- {
- if (start < begv)
- start = begv;
- else if (start > zv)
- start = zv;
-
- if (end < begv)
- end = begv;
- else if (end > zv)
- end = zv;
- }
-
- range->location = start - begv;
- range->length = end - start;
-}
-
-/* Store the text of the buffer BUF from START to END as Unicode
- characters in CHARACTERS. Return non-zero if successful. */
-
-int
-mac_store_buffer_text_to_unicode_chars (buf, start, end, characters)
- struct buffer *buf;
- int start, end;
- UniChar *characters;
-{
- int start_byte, end_byte, char_count, byte_count;
- struct coding_system coding;
- unsigned char *dst = (unsigned char *) characters;
-
- start_byte = buf_charpos_to_bytepos (buf, start);
- end_byte = buf_charpos_to_bytepos (buf, end);
- char_count = end - start;
- byte_count = end_byte - start_byte;
-
- if (setup_coding_system (
-#ifdef WORDS_BIG_ENDIAN
- intern ("utf-16be")
-#else
- intern ("utf-16le")
-#endif
- , &coding) < 0)
- return 0;
-
- coding.src_multibyte = !NILP (buf->enable_multibyte_characters);
- coding.dst_multibyte = 0;
- coding.mode |= CODING_MODE_LAST_BLOCK;
- coding.composing = COMPOSITION_DISABLED;
-
- if (BUF_GPT_BYTE (buf) <= start_byte || end_byte <= BUF_GPT_BYTE (buf))
- encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
- byte_count, char_count * sizeof (UniChar));
- else
- {
- int first_byte_count = BUF_GPT_BYTE (buf) - start_byte;
-
- encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
- first_byte_count, char_count * sizeof (UniChar));
- if (coding.result == CODING_FINISH_NORMAL)
- encode_coding (&coding,
- BUF_BYTE_ADDRESS (buf, start_byte + first_byte_count),
- dst + coding.produced,
- byte_count - first_byte_count,
- char_count * sizeof (UniChar) - coding.produced);
- }
-
- if (coding.result != CODING_FINISH_NORMAL)
- return 0;
-
- return 1;
-}
-
-void
-mac_ax_selected_text_range (f, range)
- struct frame *f;
- CFRange *range;
-{
- mac_get_selected_range (XWINDOW (f->selected_window), range);
-}
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-unsigned int
-mac_ax_number_of_characters (f)
- struct frame *f;
-{
- struct buffer *b = XBUFFER (XWINDOW (f->selected_window)->buffer);
-
- return BUF_ZV (b) - BUF_BEGV (b);
-}
-#endif
-#endif
-
-#if USE_MAC_TSM
-OSStatus
-mac_restore_keyboard_input_source ()
-{
- OSStatus err = noErr;
- ScriptLanguageRecord slrec, *slptr = NULL;
-
- if (EQ (Vmac_ts_script_language_on_focus, Qt)
- && EQ (saved_ts_script_language_on_focus, Qt))
- slptr = &saved_ts_language;
- else if (CONSP (Vmac_ts_script_language_on_focus)
- && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
- && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
- && CONSP (saved_ts_script_language_on_focus)
- && EQ (XCAR (saved_ts_script_language_on_focus),
- XCAR (Vmac_ts_script_language_on_focus))
- && EQ (XCDR (saved_ts_script_language_on_focus),
- XCDR (Vmac_ts_script_language_on_focus)))
- {
- slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
- slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
- slptr = &slrec;
- }
-
- if (slptr)
- {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
- kKeyboardInputMethodClass);
-#else
- err = SetDefaultInputMethod (saved_ts_component, slptr);
-#endif
- if (err == noErr)
- err = SetTextServiceLanguage (slptr);
-
- /* Seems to be needed on Mac OS X 10.2. */
- if (err == noErr)
- KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
- }
-
- return err;
-}
-
-void
-mac_save_keyboard_input_source ()
-{
- OSStatus err;
- ScriptLanguageRecord slrec, *slptr = NULL;
-
- saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
-
- if (EQ (Vmac_ts_script_language_on_focus, Qt))
- {
- err = GetTextServiceLanguage (&saved_ts_language);
- if (err == noErr)
- slptr = &saved_ts_language;
- }
- else if (CONSP (Vmac_ts_script_language_on_focus)
- && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
- && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
- {
- slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
- slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
- slptr = &slrec;
- }
-
- if (slptr)
- {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
- kKeyboardInputMethodClass);
-#else
- GetDefaultInputMethod (&saved_ts_component, slptr);
-#endif
- }
-}
-#endif
-
-#if TARGET_API_MAC_CARBON
-/***** Code to handle C-g testing *****/
-extern int quit_char;
-extern int make_ctrl_char P_ ((int));
-
-int
-mac_quit_char_key_p (modifiers, key_code)
- UInt32 modifiers, key_code;
-{
- UInt32 char_code;
- unsigned long some_state = 0;
- Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
- int c, emacs_modifiers;
-
- /* Mask off modifier keys that are mapped to some Emacs modifiers. */
- key_code |= (modifiers & ~(mac_mapped_modifiers (modifiers)));
- char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
- if (char_code & ~0xff)
- return 0;
-
- emacs_modifiers = mac_to_emacs_modifiers (modifiers);
- if (emacs_modifiers & ctrl_modifier)
- c = make_ctrl_char (char_code);
-
- c |= (emacs_modifiers
- & (meta_modifier | alt_modifier
- | hyper_modifier | super_modifier));
-
- return c == quit_char;
-}
-#endif
-
-#if TARGET_API_MAC_CARBON
-/* Obtains the event modifiers from the event ref and then calls
- mac_to_emacs_modifiers. */
-static int
-mac_event_to_emacs_modifiers (EventRef eventRef)
-{
- UInt32 mods = 0, class;
-
- GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
- sizeof (UInt32), NULL, &mods);
- class = GetEventClass (eventRef);
- if (!NILP (Vmac_emulate_three_button_mouse) &&
- (class == kEventClassMouse || class == kEventClassCommand))
- {
- mods &= ~(optionKey | cmdKey);
- }
- return mac_to_emacs_modifiers (mods);
-}
-
-/* Given an event ref, return the code to use for the mouse button
- code in the emacs input_event. */
-static int
-mac_get_mouse_btn (EventRef ref)
-{
- EventMouseButton result = kEventMouseButtonPrimary;
- GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
- sizeof (EventMouseButton), NULL, &result);
- switch (result)
- {
- case kEventMouseButtonPrimary:
- if (NILP (Vmac_emulate_three_button_mouse))
- return 0;
- else {
- UInt32 mods = 0;
- GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
- sizeof (UInt32), NULL, &mods);
- return mac_get_emulated_btn(mods);
- }
- case kEventMouseButtonSecondary:
- return mac_wheel_button_is_mouse_2 ? 2 : 1;
- case kEventMouseButtonTertiary:
- case 4: /* 4 is the number for the mouse wheel button */
- return mac_wheel_button_is_mouse_2 ? 1 : 2;
- default:
- return 0;
- }
-}
-
-/* Normally, ConvertEventRefToEventRecord will correctly handle all
- events. However the click of the mouse wheel is not converted to a
- mouseDown or mouseUp event. Likewise for dead key events. This
- calls ConvertEventRefToEventRecord, but then checks to see if it is
- a mouse up/down, or a dead key Carbon event that has not been
- converted, and if so, converts it by hand (to be picked up in the
- XTread_socket loop). */
-static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
-{
- OSStatus err;
- Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
- EventKind action;
-
- if (result)
- return result;
-
- switch (GetEventClass (eventRef))
- {
- case kEventClassMouse:
- switch (GetEventKind (eventRef))
- {
- case kEventMouseDown:
- eventRec->what = mouseDown;
- result = 1;
- break;
-
- case kEventMouseUp:
- eventRec->what = mouseUp;
- result = 1;
- break;
-
- default:
- break;
- }
- break;
-
- case kEventClassKeyboard:
- switch (GetEventKind (eventRef))
- {
- case kEventRawKeyDown:
- action = keyDown;
- goto keystroke_common;
- case kEventRawKeyRepeat:
- action = autoKey;
- goto keystroke_common;
- case kEventRawKeyUp:
- action = keyUp;
- keystroke_common:
- {
- unsigned char char_codes;
- UInt32 key_code;
-
- err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
- typeChar, NULL, sizeof (char),
- NULL, &char_codes);
- if (err == noErr)
- err = GetEventParameter (eventRef, kEventParamKeyCode,
- typeUInt32, NULL, sizeof (UInt32),
- NULL, &key_code);
- if (err == noErr)
- {
- eventRec->what = action;
- eventRec->message = char_codes | ((key_code & 0xff) << 8);
- result = 1;
- }
- }
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- if (result)
- {
- /* Need where and when. */
- UInt32 mods = 0;
-
- GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
- NULL, sizeof (Point), NULL, &eventRec->where);
- /* Use two step process because new event modifiers are 32-bit
- and old are 16-bit. Currently, only loss is NumLock & Fn. */
- GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
- NULL, sizeof (UInt32), NULL, &mods);
- eventRec->modifiers = mods;
-
- eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
- }
-
- return result;
-}
-
-#endif
-
-#ifdef MAC_OS8
-static void
-do_get_menus (void)
-{
- Handle menubar_handle;
- MenuRef menu;
-
- menubar_handle = GetNewMBar (128);
- if(menubar_handle == NULL)
- abort ();
- SetMenuBar (menubar_handle);
- DrawMenuBar ();
-
-#if !TARGET_API_MAC_CARBON
- menu = GetMenuRef (M_APPLE);
- if (menu != NULL)
- AppendResMenu (menu, 'DRVR');
- else
- abort ();
-#endif
-}
-
-
-static void
-do_init_managers (void)
-{
-#if !TARGET_API_MAC_CARBON
- InitGraf (&qd.thePort);
- InitFonts ();
- FlushEvents (everyEvent, 0);
- InitWindows ();
- InitMenus ();
- TEInit ();
- InitDialogs (NULL);
-#endif /* !TARGET_API_MAC_CARBON */
- InitCursor ();
-
-#if !TARGET_API_MAC_CARBON
- /* set up some extra stack space for use by emacs */
- SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
-
- /* MaxApplZone must be called for AppleScript to execute more
- complicated scripts */
- MaxApplZone ();
- MoreMasters ();
-#endif /* !TARGET_API_MAC_CARBON */
-}
-
-static void
-do_check_ram_size (void)
-{
- SInt32 physical_ram_size, logical_ram_size;
-
- if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
- || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
- || physical_ram_size > (1 << VALBITS)
- || logical_ram_size > (1 << VALBITS))
- {
- StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
- exit (1);
- }
-}
-#endif /* MAC_OS8 */
-
-static void
-do_window_update (WindowRef win)
-{
- struct frame *f = mac_window_to_frame (win);
-
- BeginUpdate (win);
-
- /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
- below. */
- if (win != tip_window)
- {
- if (f->async_visible == 0)
- {
- /* Update events may occur when a frame gets iconified. */
-#if 0
- f->async_visible = 1;
- f->async_iconified = 0;
- SET_FRAME_GARBAGED (f);
-#endif
- }
- else
- {
- Rect r;
-#if TARGET_API_MAC_CARBON
- RgnHandle region = NewRgn ();
-
- GetPortVisibleRegion (GetWindowPort (win), region);
- GetRegionBounds (region, &r);
- expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (f);
-#endif
- UpdateControls (win, region);
- DisposeRgn (region);
-#else
- r = (*win->visRgn)->rgnBBox;
- expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
- UpdateControls (win, win->visRgn);
-#endif
- }
- }
-
- EndUpdate (win);
-}
-
-static int
-is_emacs_window (WindowRef win)
-{
- Lisp_Object tail, frame;
-
- if (!win)
- return 0;
-
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_MAC_P (XFRAME (frame)))
- if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
- return 1;
-
- return 0;
-}
-
-#if USE_MAC_TSM
-static OSStatus
-mac_tsm_resume ()
-{
- OSStatus err;
- ScriptLanguageRecord slrec, *slptr = NULL;
-
- err = ActivateTSMDocument (tsm_document_id);
-
- if (err == noErr)
- {
- if (EQ (Vmac_ts_script_language_on_focus, Qt)
- && EQ (saved_ts_script_language_on_focus, Qt))
- slptr = &saved_ts_language;
- else if (CONSP (Vmac_ts_script_language_on_focus)
- && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
- && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
- && CONSP (saved_ts_script_language_on_focus)
- && EQ (XCAR (saved_ts_script_language_on_focus),
- XCAR (Vmac_ts_script_language_on_focus))
- && EQ (XCDR (saved_ts_script_language_on_focus),
- XCDR (Vmac_ts_script_language_on_focus)))
- {
- slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
- slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
- slptr = &slrec;
- }
- }
-
- if (slptr)
- {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
- kKeyboardInputMethodClass);
-#else
- err = SetDefaultInputMethod (saved_ts_component, slptr);
-#endif
- if (err == noErr)
- err = SetTextServiceLanguage (slptr);
-
- /* Seems to be needed on Mac OS X 10.2. */
- if (err == noErr)
- KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
- }
-
- return err;
-}
-
-static OSStatus
-mac_tsm_suspend ()
-{
- OSStatus err;
- ScriptLanguageRecord slrec, *slptr = NULL;
-
- saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
-
- if (EQ (Vmac_ts_script_language_on_focus, Qt))
- {
- err = GetTextServiceLanguage (&saved_ts_language);
- if (err == noErr)
- slptr = &saved_ts_language;
- }
- else if (CONSP (Vmac_ts_script_language_on_focus)
- && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
- && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
- {
- slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
- slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
- slptr = &slrec;
- }
-
- if (slptr)
- {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
- kKeyboardInputMethodClass);
-#else
- GetDefaultInputMethod (&saved_ts_component, slptr);
-#endif
- }
-
- err = DeactivateTSMDocument (tsm_document_id);
-
- return err;
-}
-#endif
-
-#if !TARGET_API_MAC_CARBON
-void
-do_apple_menu (SInt16 menu_item)
-{
- Str255 item_name;
- SInt16 da_driver_refnum;
-
- if (menu_item == I_ABOUT)
- NoteAlert (ABOUT_ALERT_ID, NULL);
- else
- {
- GetMenuItemText (GetMenuRef (M_APPLE), menu_item, item_name);
- da_driver_refnum = OpenDeskAcc (item_name);
- }
-}
-#endif /* !TARGET_API_MAC_CARBON */
-
-/* Handle drags in size box. Based on code contributed by Ben
- Mesander and IM - Window Manager A. */
-
-static void
-do_grow_window (w, e)
- WindowRef w;
- const EventRecord *e;
-{
- Rect limit_rect;
- int rows, columns, width, height;
- struct frame *f = mac_window_to_frame (w);
- XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
- int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
-#if TARGET_API_MAC_CARBON
- Rect new_rect;
-#else
- long grow_size;
-#endif
-
- if (size_hints->flags & PMinSize)
- {
- min_width = size_hints->min_width;
- min_height = size_hints->min_height;
- }
- SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
-
-#if TARGET_API_MAC_CARBON
- if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
- return;
- height = new_rect.bottom - new_rect.top;
- width = new_rect.right - new_rect.left;
-#else
- grow_size = GrowWindow (w, e->where, &limit_rect);
- /* see if it really changed size */
- if (grow_size == 0)
- return;
- height = HiWord (grow_size);
- width = LoWord (grow_size);
-#endif
-
- if (width != FRAME_PIXEL_WIDTH (f)
- || height != FRAME_PIXEL_HEIGHT (f))
- {
- rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
- columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
-
- x_set_window_size (f, 0, columns, rows);
- }
-}
-
-
-#if TARGET_API_MAC_CARBON
-static Point
-mac_get_ideal_size (f)
- struct frame *f;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- WindowRef w = FRAME_MAC_WINDOW (f);
- Point ideal_size;
- Rect standard_rect;
- int height, width, columns, rows;
-
- ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
- ideal_size.v = dpyinfo->height;
- IsWindowInStandardState (w, &ideal_size, &standard_rect);
- /* Adjust the standard size according to character boundaries. */
- width = standard_rect.right - standard_rect.left;
- height = standard_rect.bottom - standard_rect.top;
- columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
- rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
- ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
- ideal_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
-
- return ideal_size;
-}
-#endif
-
-/* Handle clicks in zoom box. Calculation of "standard state" based
- on code in IM - Window Manager A and code contributed by Ben
- Mesander. The standard state of an Emacs window is 80-characters
- wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
-
-static void
-do_zoom_window (WindowRef w, int zoom_in_or_out)
-{
- Rect zoom_rect, port_rect;
- int width, height;
- struct frame *f = mac_window_to_frame (w);
-#if TARGET_API_MAC_CARBON
- Point ideal_size = mac_get_ideal_size (f);
-
- GetWindowBounds (w, kWindowContentRgn, &port_rect);
- if (IsWindowInStandardState (w, &ideal_size, &zoom_rect)
- && port_rect.left == zoom_rect.left
- && port_rect.top == zoom_rect.top)
- zoom_in_or_out = inZoomIn;
- else
- zoom_in_or_out = inZoomOut;
-
-#ifdef MAC_OS8
- mac_clear_window (f);
-#endif
- ZoomWindowIdeal (w, zoom_in_or_out, &ideal_size);
-#else /* not TARGET_API_MAC_CARBON */
- GrafPtr save_port;
- Point top_left;
- int w_title_height, rows;
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- GetPort (&save_port);
-
- SetPortWindowPort (w);
-
- /* Clear window to avoid flicker. */
- EraseRect (&(w->portRect));
- if (zoom_in_or_out == inZoomOut)
- {
- SetPt (&top_left, w->portRect.left, w->portRect.top);
- LocalToGlobal (&top_left);
-
- /* calculate height of window's title bar */
- w_title_height = top_left.v - 1
- - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
-
- /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
- zoom_rect = qd.screenBits.bounds;
- zoom_rect.top += w_title_height;
- InsetRect (&zoom_rect, 8, 4); /* not too tight */
-
- zoom_rect.right = zoom_rect.left
- + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-
- /* Adjust the standard size according to character boundaries. */
- rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
- zoom_rect.bottom =
- zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
-
- (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
- = zoom_rect;
- }
-
- ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
-
- SetPort (save_port);
-#endif /* not TARGET_API_MAC_CARBON */
-
-#if !TARGET_API_MAC_CARBON
- /* retrieve window size and update application values */
- port_rect = w->portRect;
- height = port_rect.bottom - port_rect.top;
- width = port_rect.right - port_rect.left;
-
- mac_handle_size_change (f, width, height);
- mac_handle_origin_change (f);
-#endif
-}
-
-static void
-mac_set_unicode_keystroke_event (code, buf)
- UniChar code;
- struct input_event *buf;
-{
- int charset_id, c1, c2;
-
- if (code < 0x80)
- {
- buf->kind = ASCII_KEYSTROKE_EVENT;
- buf->code = code;
- }
- else if (code < 0x100)
- {
- if (code < 0xA0)
- charset_id = CHARSET_8_BIT_CONTROL;
- else
- charset_id = charset_latin_iso8859_1;
- buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
- buf->code = MAKE_CHAR (charset_id, code, 0);
- }
- else
- {
- if (code < 0x2500)
- charset_id = charset_mule_unicode_0100_24ff,
- code -= 0x100;
- else if (code < 0x33FF)
- charset_id = charset_mule_unicode_2500_33ff,
- code -= 0x2500;
- else if (code >= 0xE000)
- charset_id = charset_mule_unicode_e000_ffff,
- code -= 0xE000;
- c1 = (code / 96) + 32, c2 = (code % 96) + 32;
- buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
- buf->code = MAKE_CHAR (charset_id, c1, c2);
- }
-}
-
-static void
-do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
- EventKind action;
- unsigned char char_code;
- UInt32 key_code, modifiers;
- unsigned long timestamp;
- struct input_event *buf;
-{
- static SInt16 last_key_script = -1;
- SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
- UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers);
-
-#ifdef MAC_OSX
- if (mapped_modifiers & kEventKeyModifierFnMask
- && key_code <= 0x7f
- && fn_keycode_to_keycode_table[key_code])
- key_code = fn_keycode_to_keycode_table[key_code];
-#endif
-
- if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
- {
- buf->kind = NON_ASCII_KEYSTROKE_EVENT;
- buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
-#ifdef MAC_OSX
- if (modifiers & kEventKeyModifierFnMask
- && key_code <= 0x7f
- && fn_keycode_to_keycode_table[key_code] == key_code)
- modifiers &= ~kEventKeyModifierFnMask;
-#endif
- }
- else if (mapped_modifiers)
- {
- /* translate the keycode back to determine the original key */
-#ifdef MAC_OSX
- UCKeyboardLayout *uchr_ptr = NULL;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- OSStatus err;
- KeyboardLayoutRef layout;
-
- err = KLGetCurrentKeyboardLayout (&layout);
- if (err == noErr)
- err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
- (const void **) &uchr_ptr);
-#else
- static SInt16 last_key_layout_id = 0;
- static Handle uchr_handle = (Handle)-1;
- SInt16 current_key_layout_id =
- GetScriptVariable (current_key_script, smScriptKeys);
-
- if (uchr_handle == (Handle)-1
- || last_key_layout_id != current_key_layout_id)
- {
- uchr_handle = GetResource ('uchr', current_key_layout_id);
- last_key_layout_id = current_key_layout_id;
- }
- if (uchr_handle)
- uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
-#endif
-
- if (uchr_ptr)
- {
- OSStatus status;
- UInt16 key_action = action - keyDown;
- UInt32 modifier_key_state = (modifiers & ~mapped_modifiers) >> 8;
- UInt32 keyboard_type = LMGetKbdType ();
- SInt32 dead_key_state = 0;
- UniChar code;
- UniCharCount actual_length;
-
- status = UCKeyTranslate (uchr_ptr, key_code, key_action,
- modifier_key_state, keyboard_type,
- kUCKeyTranslateNoDeadKeysMask,
- &dead_key_state,
- 1, &actual_length, &code);
- if (status == noErr && actual_length == 1)
- mac_set_unicode_keystroke_event (code, buf);
- }
-#endif /* MAC_OSX */
-
- if (buf->kind == NO_EVENT)
- {
- /* This code comes from Keyboard Resource, Appendix C of IM
- - Text. This is necessary since shift is ignored in KCHR
- table translation when option or command is pressed. It
- also does not translate correctly control-shift chars
- like C-% so mask off shift here also. */
- /* Mask off modifier keys that are mapped to some Emacs
- modifiers. */
- int new_modifiers = modifiers & ~mapped_modifiers;
- /* set high byte of keycode to modifier high byte*/
- int new_key_code = key_code | new_modifiers;
- Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
- unsigned long some_state = 0;
- UInt32 new_char_code;
-
- new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
- if (new_char_code == 0)
- /* Seems like a dead key. Append up-stroke. */
- new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
- &some_state);
- if (new_char_code)
- {
- buf->kind = ASCII_KEYSTROKE_EVENT;
- buf->code = new_char_code & 0xff;
- }
- }
- }
-
- if (buf->kind == NO_EVENT)
- {
- buf->kind = ASCII_KEYSTROKE_EVENT;
- buf->code = char_code;
- }
-
- buf->modifiers = mac_to_emacs_modifiers (modifiers);
- buf->modifiers |= (extra_keyboard_modifiers
- & (meta_modifier | alt_modifier
- | hyper_modifier | super_modifier));
-
-#if TARGET_API_MAC_CARBON
- if (buf->kind == ASCII_KEYSTROKE_EVENT
- && buf->code >= 0x80 && buf->modifiers)
- {
- OSStatus err;
- TextEncoding encoding = kTextEncodingMacRoman;
- TextToUnicodeInfo ttu_info;
-
- UpgradeScriptInfoToTextEncoding (current_key_script,
- kTextLanguageDontCare,
- kTextRegionDontCare,
- NULL, &encoding);
- err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
- if (err == noErr)
- {
- UniChar code;
- Str255 pstr;
- ByteCount unicode_len;
-
- pstr[0] = 1;
- pstr[1] = buf->code;
- err = ConvertFromPStringToUnicode (ttu_info, pstr,
- sizeof (UniChar),
- &unicode_len, &code);
- if (err == noErr && unicode_len == sizeof (UniChar))
- mac_set_unicode_keystroke_event (code, buf);
- DisposeTextToUnicodeInfo (&ttu_info);
- }
- }
-#endif
-
- if (buf->kind == ASCII_KEYSTROKE_EVENT
- && buf->code >= 0x80
- && last_key_script != current_key_script)
- {
- struct input_event event;
-
- EVENT_INIT (event);
- event.kind = LANGUAGE_CHANGE_EVENT;
- event.arg = Qnil;
- event.code = current_key_script;
- event.timestamp = timestamp;
- kbd_buffer_store_event (&event);
- last_key_script = current_key_script;
- }
-}
-
-void
-mac_store_apple_event (class, id, desc)
- Lisp_Object class, id;
- const AEDesc *desc;
-{
- struct input_event buf;
-
- EVENT_INIT (buf);
-
- buf.kind = MAC_APPLE_EVENT;
- buf.x = class;
- buf.y = id;
- XSETFRAME (buf.frame_or_window,
- mac_focus_frame (&one_mac_display_info));
- /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
- is safe to use them during read_socket_hook. */
- buf.arg = mac_aedesc_to_lisp (desc);
- kbd_buffer_store_event (&buf);
-}
-
-#if TARGET_API_MAC_CARBON
-static OSStatus
-mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
- event, num_params, names, types)
- AEEventClass class;
- AEEventID id;
- Lisp_Object class_key, id_key;
- EventRef event;
- UInt32 num_params;
- const EventParamName *names;
- const EventParamType *types;
-{
- OSStatus err = eventNotHandledErr;
- Lisp_Object binding;
-
- mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
- if (!NILP (binding) && !EQ (binding, Qundefined))
- {
- if (INTEGERP (binding))
- err = XINT (binding);
- else
- {
- AppleEvent apple_event;
- err = create_apple_event_from_event_ref (event, num_params,
- names, types,
- &apple_event);
- if (err == noErr)
- {
- mac_store_apple_event (class_key, id_key, &apple_event);
- AEDisposeDesc (&apple_event);
- mac_wakeup_from_rne ();
- }
- }
- }
-
- return err;
-}
-
-void
-mac_store_drag_event (window, mouse_pos, modifiers, desc)
- WindowRef window;
- Point mouse_pos;
- SInt16 modifiers;
- const AEDesc *desc;
-{
- struct input_event buf;
-
- EVENT_INIT (buf);
-
- buf.kind = DRAG_N_DROP_EVENT;
- buf.modifiers = mac_to_emacs_modifiers (modifiers);
- buf.timestamp = TickCount () * (1000 / 60);
- XSETINT (buf.x, mouse_pos.h);
- XSETINT (buf.y, mouse_pos.v);
- XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
- buf.arg = mac_aedesc_to_lisp (desc);
- kbd_buffer_store_event (&buf);
-}
-
-#ifdef MAC_OSX
-OSStatus
-mac_store_service_event (event)
- EventRef event;
-{
- OSStatus err;
- Lisp_Object id_key;
- int num_params;
- const EventParamName *names;
- const EventParamType *types;
- static const EventParamName names_pfm[] =
- {kEventParamServiceMessageName, kEventParamServiceUserData};
- static const EventParamType types_pfm[] =
- {typeCFStringRef, typeCFStringRef};
-
- switch (GetEventKind (event))
- {
- case kEventServicePaste:
- id_key = Qpaste;
- num_params = 0;
- names = NULL;
- types = NULL;
- break;
-
- case kEventServicePerform:
- id_key = Qperform;
- num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
- names = names_pfm;
- types = types_pfm;
- break;
-
- default:
- abort ();
- }
-
- err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
- event, num_params,
- names, types);
-
- return err;
-}
-#endif /* MAC_OSX */
-
-static pascal OSStatus
-mac_handle_window_event (next_handler, event, data)
- EventHandlerCallRef next_handler;
- EventRef event;
- void *data;
-{
- WindowRef wp;
- OSStatus err, result = eventNotHandledErr;
- struct frame *f;
- UInt32 attributes;
- XSizeHints *size_hints;
-
- err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
- NULL, sizeof (WindowRef), NULL, &wp);
- if (err != noErr)
- return eventNotHandledErr;
-
- f = mac_window_to_frame (wp);
- switch (GetEventKind (event))
- {
- /* -- window refresh events -- */
-
- case kEventWindowUpdate:
- result = CallNextEventHandler (next_handler, event);
- if (result != eventNotHandledErr)
- break;
-
- do_window_update (wp);
- result = noErr;
- break;
-
- /* -- window state change events -- */
-
- case kEventWindowShowing:
- size_hints = FRAME_SIZE_HINTS (f);
- if (!(size_hints->flags & (USPosition | PPosition)))
- {
- struct frame *sf = SELECTED_FRAME ();
-
- if (!(FRAME_MAC_P (sf) && sf->async_visible))
- RepositionWindow (wp, NULL, kWindowCenterOnMainScreen);
- else
- {
- RepositionWindow (wp, FRAME_MAC_WINDOW (sf),
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- kWindowCascadeStartAtParentWindowScreen
-#else
- kWindowCascadeOnParentWindowScreen
-#endif
- );
-#if USE_MAC_TOOLBAR
- /* This is a workaround. RepositionWindow fails to put
- a window at the cascading position when its parent
- window has a Carbon HIToolbar. */
- if ((f->left_pos == sf->left_pos
- && f->top_pos == sf->top_pos)
- || (f->left_pos == sf->left_pos + 10 * 2
- && f->top_pos == sf->top_pos + 32 * 2))
- MoveWindowStructure (wp, sf->left_pos + 10, sf->top_pos + 32);
-#endif
- }
- result = noErr;
- }
- break;
-
- case kEventWindowHiding:
- /* Before unmapping the window, update the WM_SIZE_HINTS
- property to claim that the current position of the window is
- user-specified, rather than program-specified, so that when
- the window is mapped again, it will be placed at the same
- location, without forcing the user to position it by hand
- again (they have already done that once for this window.) */
- x_wm_set_size_hint (f, (long) 0, 1);
- result = noErr;
- break;
-
- case kEventWindowShown:
- case kEventWindowHidden:
- case kEventWindowCollapsed:
- case kEventWindowExpanded:
- mac_handle_visibility_change (f);
- result = noErr;
- break;
-
- case kEventWindowBoundsChanging:
- result = CallNextEventHandler (next_handler, event);
- if (result != eventNotHandledErr)
- break;
-
- err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
- NULL, sizeof (UInt32), NULL, &attributes);
- if (err != noErr)
- break;
-
- size_hints = FRAME_SIZE_HINTS (f);
- if ((attributes & kWindowBoundsChangeUserResize)
- && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
- == (PResizeInc | PBaseSize | PMinSize)))
- {
- Rect bounds;
- int width, height;
-
- err = GetEventParameter (event, kEventParamCurrentBounds,
- typeQDRectangle, NULL, sizeof (Rect),
- NULL, &bounds);
- if (err != noErr)
- break;
-
- width = bounds.right - bounds.left;
- height = bounds.bottom - bounds.top;
-
- if (width < size_hints->min_width)
- width = size_hints->min_width;
- else
- width = size_hints->base_width
- + (int) ((width - size_hints->base_width)
- / (float) size_hints->width_inc + .5)
- * size_hints->width_inc;
-
- if (height < size_hints->min_height)
- height = size_hints->min_height;
- else
- height = size_hints->base_height
- + (int) ((height - size_hints->base_height)
- / (float) size_hints->height_inc + .5)
- * size_hints->height_inc;
-
- bounds.right = bounds.left + width;
- bounds.bottom = bounds.top + height;
- SetEventParameter (event, kEventParamCurrentBounds,
- typeQDRectangle, sizeof (Rect), &bounds);
- result = noErr;
- }
- break;
-
- case kEventWindowBoundsChanged:
- err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
- NULL, sizeof (UInt32), NULL, &attributes);
- if (err != noErr)
- break;
-
- if (attributes & kWindowBoundsChangeSizeChanged)
- {
- Rect bounds;
-
- err = GetEventParameter (event, kEventParamCurrentBounds,
- typeQDRectangle, NULL, sizeof (Rect),
- NULL, &bounds);
- if (err == noErr)
- {
- int width, height;
-
- width = bounds.right - bounds.left;
- height = bounds.bottom - bounds.top;
- mac_handle_size_change (f, width, height);
- mac_wakeup_from_rne ();
- }
- }
-
- if (attributes & kWindowBoundsChangeOriginChanged)
- mac_handle_origin_change (f);
-
- result = noErr;
- break;
-
- /* -- window action events -- */
-
- case kEventWindowClose:
- {
- struct input_event buf;
-
- EVENT_INIT (buf);
- buf.kind = DELETE_WINDOW_EVENT;
- XSETFRAME (buf.frame_or_window, f);
- buf.arg = Qnil;
- kbd_buffer_store_event (&buf);
- }
- result = noErr;
- break;
-
- case kEventWindowGetIdealSize:
- result = CallNextEventHandler (next_handler, event);
- if (result != eventNotHandledErr)
- break;
-
- {
- Point ideal_size = mac_get_ideal_size (f);
-
- err = SetEventParameter (event, kEventParamDimensions,
- typeQDPoint, sizeof (Point), &ideal_size);
- if (err == noErr)
- result = noErr;
- }
- break;
-
-#ifdef MAC_OSX
- case kEventWindowToolbarSwitchMode:
- {
- static const EventParamName names[] = {kEventParamDirectObject,
- kEventParamWindowMouseLocation,
- kEventParamKeyModifiers,
- kEventParamMouseButton,
- kEventParamClickCount,
- kEventParamMouseChord};
- static const EventParamType types[] = {typeWindowRef,
- typeQDPoint,
- typeUInt32,
- typeMouseButton,
- typeUInt32,
- typeUInt32};
- int num_params = sizeof (names) / sizeof (names[0]);
-
- err = mac_store_event_ref_as_apple_event (0, 0,
- Qwindow,
- Qtoolbar_switch_mode,
- event, num_params,
- names, types);
- }
- if (err == noErr)
- result = noErr;
- break;
-#endif
-
-#if USE_MAC_TSM
- /* -- window focus events -- */
-
- case kEventWindowFocusAcquired:
- err = mac_tsm_resume ();
- if (err == noErr)
- result = noErr;
- break;
-
- case kEventWindowFocusRelinquish:
- err = mac_tsm_suspend ();
- if (err == noErr)
- result = noErr;
- break;
-#endif
-
- default:
- abort ();
- }
-
- return result;
-}
-
-static pascal OSStatus
-mac_handle_application_event (next_handler, event, data)
- EventHandlerCallRef next_handler;
- EventRef event;
- void *data;
-{
- OSStatus err, result = eventNotHandledErr;
-
- switch (GetEventKind (event))
- {
-#if USE_MAC_TSM
- case kEventAppActivated:
- err = mac_tsm_resume ();
- break;
-
- case kEventAppDeactivated:
- err = mac_tsm_suspend ();
- break;
-#endif
-
- default:
- abort ();
- }
-
- if (err == noErr)
- result = noErr;
-
- return result;
-}
-
-static pascal OSStatus
-mac_handle_keyboard_event (next_handler, event, data)
- EventHandlerCallRef next_handler;
- EventRef event;
- void *data;
-{
- OSStatus err, result = eventNotHandledErr;
- UInt32 event_kind, key_code, modifiers;
- unsigned char char_code;
-
- event_kind = GetEventKind (event);
- switch (event_kind)
- {
- case kEventRawKeyDown:
- case kEventRawKeyRepeat:
- case kEventRawKeyUp:
- /* When using Carbon Events, we need to pass raw keyboard events
- to the TSM ourselves. If TSM handles it, it will pass back
- noErr, otherwise it will pass back "eventNotHandledErr" and
- we can process it normally. */
- result = CallNextEventHandler (next_handler, event);
- if (result != eventNotHandledErr)
- break;
-
- if (read_socket_inev == NULL)
- break;
-
-#if USE_MAC_TSM
- if (read_socket_inev->kind != NO_EVENT)
- {
- result = noErr;
- break;
- }
-#endif
-
- if (event_kind == kEventRawKeyUp)
- break;
-
- err = GetEventParameter (event, kEventParamKeyMacCharCodes,
- typeChar, NULL,
- sizeof (char), NULL, &char_code);
- if (err != noErr)
- break;
-
- err = GetEventParameter (event, kEventParamKeyCode,
- typeUInt32, NULL,
- sizeof (UInt32), NULL, &key_code);
- if (err != noErr)
- break;
-
- err = GetEventParameter (event, kEventParamKeyModifiers,
- typeUInt32, NULL,
- sizeof (UInt32), NULL, &modifiers);
- if (err != noErr)
- break;
-
- do_keystroke ((event_kind == kEventRawKeyDown ? keyDown : autoKey),
- char_code, key_code, modifiers,
- ((unsigned long)
- (GetEventTime (event) / kEventDurationMillisecond)),
- read_socket_inev);
- result = noErr;
- break;
-
- default:
- abort ();
- }
-
- return result;
-}
-
-static pascal OSStatus
-mac_handle_command_event (next_handler, event, data)
- EventHandlerCallRef next_handler;
- EventRef event;
- void *data;
-{
- OSStatus err, result = eventNotHandledErr;
- HICommand command;
- static const EventParamName names[] =
- {kEventParamDirectObject, kEventParamKeyModifiers};
- static const EventParamType types[] =
- {typeHICommand, typeUInt32};
- int num_params = sizeof (names) / sizeof (names[0]);
-
- err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
- NULL, sizeof (HICommand), NULL, &command);
- if (err != noErr)
- return eventNotHandledErr;
-
- switch (GetEventKind (event))
- {
- case kEventCommandProcess:
- result = CallNextEventHandler (next_handler, event);
- if (result != eventNotHandledErr)
- break;
-
- err = GetEventParameter (event, kEventParamDirectObject,
- typeHICommand, NULL,
- sizeof (HICommand), NULL, &command);
-
- if (err != noErr || command.commandID == 0)
- break;
-
- /* A HI command event is mapped to an Apple event whose event
- class symbol is `hi-command' and event ID is its command
- ID. */
- err = mac_store_event_ref_as_apple_event (0, command.commandID,
- Qhi_command, Qnil,
- event, num_params,
- names, types);
- if (err == noErr)
- result = noErr;
- break;
-
- default:
- abort ();
- }
-
- return result;
-}
-
-static pascal OSStatus
-mac_handle_mouse_event (next_handler, event, data)
- EventHandlerCallRef next_handler;
- EventRef event;
- void *data;
-{
- OSStatus err, result = eventNotHandledErr;
-
- switch (GetEventKind (event))
- {
- case kEventMouseWheelMoved:
- {
- WindowRef wp;
- struct frame *f;
- EventMouseWheelAxis axis;
- SInt32 delta;
- Point point;
-
- result = CallNextEventHandler (next_handler, event);
- if (result != eventNotHandledErr || read_socket_inev == NULL)
- break;
-
- f = mac_focus_frame (&one_mac_display_info);
-
- err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
- NULL, sizeof (WindowRef), NULL, &wp);
- if (err != noErr
- || wp != FRAME_MAC_WINDOW (f))
- break;
-
- err = GetEventParameter (event, kEventParamMouseWheelAxis,
- typeMouseWheelAxis, NULL,
- sizeof (EventMouseWheelAxis), NULL, &axis);
- if (err != noErr || axis != kEventMouseWheelAxisY)
- break;
-
- err = GetEventParameter (event, kEventParamMouseLocation,
- typeQDPoint, NULL, sizeof (Point),
- NULL, &point);
- if (err != noErr)
- break;
-
- point.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
- point.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
- if (point.h < 0 || point.v < 0
- || EQ (window_from_coordinates (f, point.h, point.v, 0, 0, 0, 1),
- f->tool_bar_window))
- break;
-
- err = GetEventParameter (event, kEventParamMouseWheelDelta,
- typeSInt32, NULL, sizeof (SInt32),
- NULL, &delta);
- if (err != noErr)
- break;
-
- read_socket_inev->kind = WHEEL_EVENT;
- read_socket_inev->code = 0;
- read_socket_inev->modifiers =
- (mac_event_to_emacs_modifiers (event)
- | ((delta < 0) ? down_modifier : up_modifier));
- XSETINT (read_socket_inev->x, point.h);
- XSETINT (read_socket_inev->y, point.v);
- XSETFRAME (read_socket_inev->frame_or_window, f);
-
- result = noErr;
- }
- break;
-
- default:
- abort ();
- }
-
- return result;
-}
-
-#if USE_MAC_TSM
-static pascal OSStatus
-mac_handle_text_input_event (next_handler, event, data)
- EventHandlerCallRef next_handler;
- EventRef event;
- void *data;
-{
- OSStatus err, result;
- Lisp_Object id_key = Qnil;
- int num_params;
- const EventParamName *names;
- const EventParamType *types;
- static UInt32 seqno_uaia = 0;
- static const EventParamName names_uaia[] =
- {kEventParamTextInputSendComponentInstance,
- kEventParamTextInputSendRefCon,
- kEventParamTextInputSendSLRec,
- kEventParamTextInputSendFixLen,
- kEventParamTextInputSendText,
- kEventParamTextInputSendUpdateRng,
- kEventParamTextInputSendHiliteRng,
- kEventParamTextInputSendClauseRng,
- kEventParamTextInputSendPinRng,
- kEventParamTextInputSendTextServiceEncoding,
- kEventParamTextInputSendTextServiceMacEncoding,
- EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
- static const EventParamType types_uaia[] =
- {typeComponentInstance,
- typeLongInteger,
- typeIntlWritingCode,
- typeLongInteger,
-#ifdef MAC_OSX
- typeUnicodeText,
-#else
- typeChar,
-#endif
- typeTextRangeArray,
- typeTextRangeArray,
- typeOffsetArray,
- typeTextRange,
- typeUInt32,
- typeUInt32,
- typeUInt32};
- static const EventParamName names_ufke[] =
- {kEventParamTextInputSendComponentInstance,
- kEventParamTextInputSendRefCon,
- kEventParamTextInputSendSLRec,
- kEventParamTextInputSendText};
- static const EventParamType types_ufke[] =
- {typeComponentInstance,
- typeLongInteger,
- typeIntlWritingCode,
- typeUnicodeText};
-
- result = CallNextEventHandler (next_handler, event);
- if (result != eventNotHandledErr)
- return result;
-
- switch (GetEventKind (event))
- {
- case kEventTextInputUpdateActiveInputArea:
- id_key = Qupdate_active_input_area;
- num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
- names = names_uaia;
- types = types_uaia;
- SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
- typeUInt32, sizeof (UInt32), &seqno_uaia);
- seqno_uaia++;
- result = noErr;
- break;
-
- case kEventTextInputUnicodeForKeyEvent:
- {
- EventRef kbd_event;
- UInt32 actual_size, modifiers;
-
- err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
- typeEventRef, NULL, sizeof (EventRef), NULL,
- &kbd_event);
- if (err == noErr)
- err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
- typeUInt32, NULL,
- sizeof (UInt32), NULL, &modifiers);
- if (err == noErr && mac_mapped_modifiers (modifiers))
- /* There're mapped modifier keys. Process it in
- do_keystroke. */
- break;
- if (err == noErr)
- err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
- typeUnicodeText, NULL, 0, &actual_size,
- NULL);
- if (err == noErr && actual_size == sizeof (UniChar))
- {
- UniChar code;
-
- err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
- typeUnicodeText, NULL,
- sizeof (UniChar), NULL, &code);
- if (err == noErr && code < 0x80)
- {
- /* ASCII character. Process it in do_keystroke. */
- if (read_socket_inev && code >= 0x20 && code <= 0x7e)
- {
- UInt32 key_code;
-
- err = GetEventParameter (kbd_event, kEventParamKeyCode,
- typeUInt32, NULL, sizeof (UInt32),
- NULL, &key_code);
- if (!(err == noErr && key_code <= 0x7f
- && keycode_to_xkeysym_table [key_code]))
- {
- struct frame *f =
- mac_focus_frame (&one_mac_display_info);
-
- read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
- read_socket_inev->code = code;
- read_socket_inev->modifiers =
- mac_to_emacs_modifiers (modifiers);
- read_socket_inev->modifiers |=
- (extra_keyboard_modifiers
- & (meta_modifier | alt_modifier
- | hyper_modifier | super_modifier));
- XSETFRAME (read_socket_inev->frame_or_window, f);
- }
- }
- break;
- }
- }
- if (err == noErr)
- {
- /* Non-ASCII keystrokes without mapped modifiers are
- processed at the Lisp level. */
- id_key = Qunicode_for_key_event;
- num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
- names = names_ufke;
- types = types_ufke;
- result = noErr;
- }
- }
- break;
-
- case kEventTextInputOffsetToPos:
- {
- struct frame *f;
- struct window *w;
- Point p;
-
- if (!OVERLAYP (Vmac_ts_active_input_overlay))
- break;
-
- /* Strictly speaking, this is not always correct because
- previous events may change some states about display. */
- if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
- {
- /* Active input area is displayed around the current point. */
- f = SELECTED_FRAME ();
- w = XWINDOW (f->selected_window);
- }
- else if (WINDOWP (echo_area_window))
- {
- /* Active input area is displayed in the echo area. */
- w = XWINDOW (echo_area_window);
- f = WINDOW_XFRAME (w);
- }
- else
- break;
-
- p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
- + WINDOW_LEFT_FRINGE_WIDTH (w)
- + f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f));
- p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
- + FONT_BASE (FRAME_FONT (f))
- + f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
- err = SetEventParameter (event, kEventParamTextInputReplyPoint,
- typeQDPoint, sizeof (typeQDPoint), &p);
- if (err == noErr)
- result = noErr;
- }
- break;
-
- default:
- abort ();
- }
-
- if (!NILP (id_key))
- err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
- event, num_params,
- names, types);
- return result;
-}
-#endif
-#endif /* TARGET_API_MAC_CARBON */
-
-
-OSStatus
-install_window_handler (window)
- WindowRef window;
-{
- OSStatus err = noErr;
-
-#if TARGET_API_MAC_CARBON
- if (err == noErr)
- {
- static const EventTypeSpec specs[] =
- {
- /* -- window refresh events -- */
- {kEventClassWindow, kEventWindowUpdate},
- /* -- window state change events -- */
- {kEventClassWindow, kEventWindowShowing},
- {kEventClassWindow, kEventWindowHiding},
- {kEventClassWindow, kEventWindowShown},
- {kEventClassWindow, kEventWindowHidden},
- {kEventClassWindow, kEventWindowCollapsed},
- {kEventClassWindow, kEventWindowExpanded},
- {kEventClassWindow, kEventWindowBoundsChanging},
- {kEventClassWindow, kEventWindowBoundsChanged},
- /* -- window action events -- */
- {kEventClassWindow, kEventWindowClose},
- {kEventClassWindow, kEventWindowGetIdealSize},
-#ifdef MAC_OSX
- {kEventClassWindow, kEventWindowToolbarSwitchMode},
-#endif
-#if USE_MAC_TSM
- /* -- window focus events -- */
- {kEventClassWindow, kEventWindowFocusAcquired},
- {kEventClassWindow, kEventWindowFocusRelinquish},
-#endif
- };
- static EventHandlerUPP handle_window_eventUPP = NULL;
-
- if (handle_window_eventUPP == NULL)
- handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
-
- err = InstallWindowEventHandler (window, handle_window_eventUPP,
- GetEventTypeCount (specs),
- specs, NULL, NULL);
- }
-#endif
-
- if (err == noErr)
- err = install_drag_handler (window);
-
- return err;
-}
-
-void
-remove_window_handler (window)
- WindowRef window;
-{
- remove_drag_handler (window);
-}
-
-#if TARGET_API_MAC_CARBON
-static OSStatus
-install_application_handler ()
-{
- OSStatus err = noErr;
-
- if (err == noErr)
- {
- static const EventTypeSpec specs[] = {
-#if USE_MAC_TSM
- {kEventClassApplication, kEventAppActivated},
- {kEventClassApplication, kEventAppDeactivated},
-#endif
- };
-
- err = InstallApplicationEventHandler (NewEventHandlerUPP
- (mac_handle_application_event),
- GetEventTypeCount (specs),
- specs, NULL, NULL);
- }
-
- if (err == noErr)
- {
- static const EventTypeSpec specs[] =
- {{kEventClassKeyboard, kEventRawKeyDown},
- {kEventClassKeyboard, kEventRawKeyRepeat},
- {kEventClassKeyboard, kEventRawKeyUp}};
-
- err = InstallApplicationEventHandler (NewEventHandlerUPP
- (mac_handle_keyboard_event),
- GetEventTypeCount (specs),
- specs, NULL, NULL);
- }
-
- if (err == noErr)
- {
- static const EventTypeSpec specs[] =
- {{kEventClassCommand, kEventCommandProcess}};
-
- err = InstallApplicationEventHandler (NewEventHandlerUPP
- (mac_handle_command_event),
- GetEventTypeCount (specs),
- specs, NULL, NULL);
- }
-
- if (err == noErr)
- {
- static const EventTypeSpec specs[] =
- {{kEventClassMouse, kEventMouseWheelMoved}};
-
- err = InstallApplicationEventHandler (NewEventHandlerUPP
- (mac_handle_mouse_event),
- GetEventTypeCount (specs),
- specs, NULL, NULL);
- }
-
-#if USE_MAC_TSM
- if (err == noErr)
- {
- static const EventTypeSpec spec[] =
- {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
- {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
- {kEventClassTextInput, kEventTextInputOffsetToPos}};
-
- err = InstallApplicationEventHandler (NewEventHandlerUPP
- (mac_handle_text_input_event),
- GetEventTypeCount (spec),
- spec, NULL, NULL);
- }
-#endif
-
- if (err == noErr)
- err = install_menu_target_item_handler ();
-
-#ifdef MAC_OSX
- if (err == noErr)
- err = install_service_handler ();
-#endif
-
- return err;
-}
-#endif
-
-static pascal void
-mac_handle_dm_notification (event)
- AppleEvent *event;
-{
- mac_screen_config_changed = 1;
-}
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-static void
-mac_handle_cg_display_reconfig (display, flags, user_info)
- CGDirectDisplayID display;
- CGDisplayChangeSummaryFlags flags;
- void *user_info;
-{
- mac_screen_config_changed = 1;
-}
-#endif
-
-static OSErr
-init_dm_notification_handler ()
-{
- OSErr err = noErr;
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- if (CGDisplayRegisterReconfigurationCallback != NULL)
-#endif
- {
- CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
- NULL);
- }
-#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- else /* CGDisplayRegisterReconfigurationCallback == NULL */
-#endif
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
- {
- static DMNotificationUPP handle_dm_notificationUPP = NULL;
- ProcessSerialNumber psn;
-
- if (handle_dm_notificationUPP == NULL)
- handle_dm_notificationUPP =
- NewDMNotificationUPP (mac_handle_dm_notification);
-
- err = GetCurrentProcess (&psn);
- if (err == noErr)
- err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
- }
-#endif
-
- return err;
-}
-
-static void
-mac_get_screen_info (dpyinfo)
- struct mac_display_info *dpyinfo;
-{
-#ifdef MAC_OSX
- /* HasDepth returns true if it is possible to have a 32 bit display,
- but this may not be what is actually used. Mac OSX can do better. */
- dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
- dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
- {
- CGDisplayErr err;
- CGDisplayCount ndisps;
- CGDirectDisplayID *displays;
-
- err = CGGetActiveDisplayList (0, NULL, &ndisps);
- if (err == noErr)
- {
- displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
- err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
- }
- if (err == noErr)
- {
- CGRect bounds = CGRectZero;
-
- while (ndisps-- > 0)
- bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
- dpyinfo->height = CGRectGetHeight (bounds);
- dpyinfo->width = CGRectGetWidth (bounds);
- }
- else
- {
- dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
- dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
- }
- }
-#else /* !MAC_OSX */
- {
- GDHandle gdh = GetMainDevice ();
- Rect rect = (**gdh).gdRect;
-
- dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
- for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
- if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
- break;
-
- for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
- gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
- UnionRect (&rect, &(**gdh).gdRect, &rect);
-
- dpyinfo->height = rect.bottom - rect.top;
- dpyinfo->width = rect.right - rect.left;
- }
-#endif /* !MAC_OSX */
-}
-
-
-#if __profile__
-void
-profiler_exit_proc ()
-{
- ProfilerDump ("\pEmacs.prof");
- ProfilerTerm ();
-}
-#endif
-
-/* These few functions implement Emacs as a normal Mac application
- (almost): set up the heap and the Toolbox, handle necessary system
- events plus a few simple menu events. They also set up Emacs's
- access to functions defined in the rest of this file. Emacs uses
- function hooks to perform all its terminal I/O. A complete list of
- these functions appear in termhooks.h. For what they do, read the
- comments there and see also w32term.c and xterm.c. What's
- noticeably missing here is the event loop, which is normally
- present in most Mac application. After performing the necessary
- Mac initializations, main passes off control to emacs_main
- (corresponding to main in emacs.c). Emacs_main calls XTread_socket
- (defined further below) to read input. This is where
- WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
-
-#ifdef MAC_OS8
-#undef main
-int
-main (void)
-{
-#if __profile__ /* is the profiler on? */
- if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
- exit(1);
-#endif
-
-#if __MWERKS__
- /* set creator and type for files created by MSL */
- _fcreator = MAC_EMACS_CREATOR_CODE;
- _ftype = 'TEXT';
-#endif
-
- do_init_managers ();
-
- do_get_menus ();
-
-#ifndef USE_LSB_TAG
- do_check_ram_size ();
-#endif
-
- init_emacs_passwd_dir ();
-
- init_environ ();
-
- init_coercion_handler ();
-
- initialize_applescript ();
-
- init_apple_event_handler ();
-
- init_dm_notification_handler ();
-
- {
- char **argv;
- int argc = 0;
-
- /* set up argv array from STR# resource */
- get_string_list (&argv, ARGV_STRING_LIST_ID);
- while (argv[argc])
- argc++;
-
- /* free up AppleScript resources on exit */
- atexit (terminate_applescript);
-
-#if __profile__ /* is the profiler on? */
- atexit (profiler_exit_proc);
-#endif
-
- /* 3rd param "envp" never used in emacs_main */
- (void) emacs_main (argc, argv, 0);
- }
-
- /* Never reached - real exit in Fkill_emacs */
- return 0;
-}
-#endif
-
-#if !TARGET_API_MAC_CARBON
-static RgnHandle mouse_region = NULL;
-
-Boolean
-mac_wait_next_event (er, sleep_time, dequeue)
- EventRecord *er;
- UInt32 sleep_time;
- Boolean dequeue;
-{
- static EventRecord er_buf = {nullEvent};
- UInt32 target_tick, current_tick;
- EventMask event_mask;
-
- if (mouse_region == NULL)
- mouse_region = NewRgn ();
-
- event_mask = everyEvent;
- if (!mac_ready_for_apple_events)
- event_mask -= highLevelEventMask;
-
- current_tick = TickCount ();
- target_tick = current_tick + sleep_time;
-
- if (er_buf.what == nullEvent)
- while (!WaitNextEvent (event_mask, &er_buf,
- target_tick - current_tick, mouse_region))
- {
- current_tick = TickCount ();
- if (target_tick <= current_tick)
- return false;
- }
-
- *er = er_buf;
- if (dequeue)
- er_buf.what = nullEvent;
- return true;
-}
-#endif /* not TARGET_API_MAC_CARBON */
-
-#if TARGET_API_MAC_CARBON
-OSStatus
-mac_post_mouse_moved_event ()
-{
- EventRef event = NULL;
- OSStatus err;
-
- err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
- kEventAttributeNone, &event);
- if (err == noErr)
- {
- Point mouse_pos;
-
- GetGlobalMouse (&mouse_pos);
- err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
- sizeof (Point), &mouse_pos);
- }
- if (err == noErr)
- {
- UInt32 modifiers = GetCurrentKeyModifiers ();
-
- err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
- sizeof (UInt32), &modifiers);
- }
- if (err == noErr)
- err = PostEventToQueue (GetCurrentEventQueue (), event,
- kEventPriorityStandard);
- if (event)
- ReleaseEvent (event);
-
- return err;
-}
-#endif
-
-/* Emacs calls this whenever it wants to read an input event from the
- user. */
-int
-XTread_socket (sd, expected, hold_quit)
- int sd, expected;
- struct input_event *hold_quit;
-{
- struct input_event inev;
- int count = 0;
-#if TARGET_API_MAC_CARBON
- EventRef eventRef;
- EventTargetRef toolbox_dispatcher;
-#endif
- EventRecord er;
- struct mac_display_info *dpyinfo = &one_mac_display_info;
-
- if (interrupt_input_blocked)
- {
- interrupt_input_pending = 1;
- return -1;
- }
-
- interrupt_input_pending = 0;
- BLOCK_INPUT;
-
- /* So people can tell when we have read the available input. */
- input_signal_count++;
-
- ++handling_signal;
-
-#if TARGET_API_MAC_CARBON
- toolbox_dispatcher = GetEventDispatcherTarget ();
-
- while (
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (NULL),
-#endif
- !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
- kEventRemoveFromQueue, &eventRef))
-#else /* !TARGET_API_MAC_CARBON */
- while (mac_wait_next_event (&er, 0, true))
-#endif /* !TARGET_API_MAC_CARBON */
- {
- int do_help = 0;
- struct frame *f;
- unsigned long timestamp;
-
- EVENT_INIT (inev);
- inev.kind = NO_EVENT;
- inev.arg = Qnil;
-
-#if TARGET_API_MAC_CARBON
- timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
-
- if (!mac_convert_event_ref (eventRef, &er))
- goto OTHER;
-#else /* !TARGET_API_MAC_CARBON */
- timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
-#endif /* !TARGET_API_MAC_CARBON */
-
- switch (er.what)
- {
- case mouseDown:
- case mouseUp:
- {
- WindowRef window_ptr;
- ControlPartCode part_code;
- int tool_bar_p = 0;
-
-#if TARGET_API_MAC_CARBON
- OSStatus err;
-
- /* This is needed to send mouse events like aqua window
- buttons to the correct handler. */
- read_socket_inev = &inev;
- err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
- read_socket_inev = NULL;
- if (err != eventNotHandledErr)
- break;
-#endif
- last_mouse_glyph_frame = 0;
-
- if (dpyinfo->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- {
- window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
- part_code = inContent;
- }
- else
- {
- part_code = FindWindow (er.where, &window_ptr);
- if (tip_window && window_ptr == tip_window)
- {
- HideWindow (tip_window);
- part_code = FindWindow (er.where, &window_ptr);
- }
- }
-
- if (er.what != mouseDown &&
- (part_code != inContent || dpyinfo->grabbed == 0))
- break;
-
- switch (part_code)
- {
- case inMenuBar:
- f = mac_focus_frame (dpyinfo);
- saved_menu_event_location = er.where;
- inev.kind = MENU_BAR_ACTIVATE_EVENT;
- XSETFRAME (inev.frame_or_window, f);
- break;
-
- case inContent:
- if (
-#if TARGET_API_MAC_CARBON
- FrontNonFloatingWindow ()
-#else
- FrontWindow ()
-#endif
- != window_ptr
- || (mac_window_to_frame (window_ptr)
- != dpyinfo->x_focus_frame))
- SelectWindow (window_ptr);
- else
- {
- ControlPartCode control_part_code;
- ControlRef ch;
- Point mouse_loc;
-#ifdef MAC_OSX
- ControlKind control_kind;
-#endif
-
- f = mac_window_to_frame (window_ptr);
- /* convert to local coordinates of new window */
- mouse_loc.h = (er.where.h
- - (f->left_pos
- + FRAME_OUTER_TO_INNER_DIFF_X (f)));
- mouse_loc.v = (er.where.v
- - (f->top_pos
- + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
-#if TARGET_API_MAC_CARBON
- ch = FindControlUnderMouse (mouse_loc, window_ptr,
- &control_part_code);
-#ifdef MAC_OSX
- if (ch)
- GetControlKind (ch, &control_kind);
-#endif
-#else
- control_part_code = FindControl (mouse_loc, window_ptr,
- &ch);
-#endif
-
-#if TARGET_API_MAC_CARBON
- inev.code = mac_get_mouse_btn (eventRef);
- inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
- inev.code = mac_get_emulated_btn (er.modifiers);
- inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
-#endif
- XSETINT (inev.x, mouse_loc.h);
- XSETINT (inev.y, mouse_loc.v);
-
- if ((dpyinfo->grabbed && tracked_scroll_bar)
- || (ch != 0
-#ifndef USE_TOOLKIT_SCROLL_BARS
- /* control_part_code becomes kControlNoPart if
- a progress indicator is clicked. */
- && control_part_code != kControlNoPart
-#else /* USE_TOOLKIT_SCROLL_BARS */
-#ifdef MAC_OSX
- && control_kind.kind == kControlKindScrollBar
-#endif /* MAC_OSX */
-#endif /* USE_TOOLKIT_SCROLL_BARS */
- ))
- {
- struct scroll_bar *bar;
-
- if (dpyinfo->grabbed && tracked_scroll_bar)
- {
- bar = tracked_scroll_bar;
-#ifndef USE_TOOLKIT_SCROLL_BARS
- control_part_code = kControlIndicatorPart;
-#endif
- }
- else
- bar = (struct scroll_bar *) GetControlReference (ch);
-#ifdef USE_TOOLKIT_SCROLL_BARS
- /* Make the "Ctrl-Mouse-2 splits window" work
- for toolkit scroll bars. */
- if (inev.modifiers & ctrl_modifier)
- x_scroll_bar_handle_click (bar, control_part_code,
- &er, &inev);
- else if (er.what == mouseDown)
- x_scroll_bar_handle_press (bar, control_part_code,
- mouse_loc, &inev);
- else
- x_scroll_bar_handle_release (bar, &inev);
-#else /* not USE_TOOLKIT_SCROLL_BARS */
- x_scroll_bar_handle_click (bar, control_part_code,
- &er, &inev);
- if (er.what == mouseDown
- && control_part_code == kControlIndicatorPart)
- tracked_scroll_bar = bar;
- else
- tracked_scroll_bar = NULL;
-#endif /* not USE_TOOLKIT_SCROLL_BARS */
- }
- else
- {
- Lisp_Object window;
- int x = mouse_loc.h;
- int y = mouse_loc.v;
-
- window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
- if (EQ (window, f->tool_bar_window))
- {
- if (er.what == mouseDown)
- handle_tool_bar_click (f, x, y, 1, 0);
- else
- handle_tool_bar_click (f, x, y, 0,
- inev.modifiers);
- tool_bar_p = 1;
- }
- else
- {
- XSETFRAME (inev.frame_or_window, f);
- inev.kind = MOUSE_CLICK_EVENT;
- }
- }
-
- if (er.what == mouseDown)
- {
- dpyinfo->grabbed |= (1 << inev.code);
- last_mouse_frame = f;
-
- if (!tool_bar_p)
- last_tool_bar_item = -1;
- }
- else
- {
- if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
- /* If a button is released though it was not
- previously pressed, that would be because
- of multi-button emulation. */
- dpyinfo->grabbed = 0;
- else
- dpyinfo->grabbed &= ~(1 << inev.code);
- }
-
- /* Ignore any mouse motion that happened before
- this event; any subsequent mouse-movement Emacs
- events should reflect only motion after the
- ButtonPress. */
- if (f != 0)
- f->mouse_moved = 0;
-
-#ifdef USE_TOOLKIT_SCROLL_BARS
- if (inev.kind == MOUSE_CLICK_EVENT
- || (inev.kind == SCROLL_BAR_CLICK_EVENT
- && (inev.modifiers & ctrl_modifier)))
-#endif
- switch (er.what)
- {
- case mouseDown:
- inev.modifiers |= down_modifier;
- break;
- case mouseUp:
- inev.modifiers |= up_modifier;
- break;
- }
- }
- break;
-
- case inDrag:
-#if TARGET_API_MAC_CARBON
- case inProxyIcon:
- if (IsWindowPathSelectClick (window_ptr, &er))
- {
- WindowPathSelect (window_ptr, NULL, NULL);
- break;
- }
- if (part_code == inProxyIcon
- && (TrackWindowProxyDrag (window_ptr, er.where)
- != errUserWantsToDragWindow))
- break;
- DragWindow (window_ptr, er.where, NULL);
-#else /* not TARGET_API_MAC_CARBON */
- DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
- /* Update the frame parameters. */
- {
- struct frame *f = mac_window_to_frame (window_ptr);
-
- if (f && !f->async_iconified)
- mac_handle_origin_change (f);
- }
-#endif /* not TARGET_API_MAC_CARBON */
- break;
-
- case inGoAway:
- if (TrackGoAway (window_ptr, er.where))
- {
- inev.kind = DELETE_WINDOW_EVENT;
- XSETFRAME (inev.frame_or_window,
- mac_window_to_frame (window_ptr));
- }
- break;
-
- /* window resize handling added --ben */
- case inGrow:
- do_grow_window (window_ptr, &er);
- break;
-
- /* window zoom handling added --ben */
- case inZoomIn:
- case inZoomOut:
- if (TrackBox (window_ptr, er.where, part_code))
- do_zoom_window (window_ptr, part_code);
- break;
-
-#if USE_MAC_TOOLBAR
- case inStructure:
- {
- OSStatus err;
- HIViewRef ch;
-
- err = HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr),
- eventRef, &ch);
- /* This doesn't work on Mac OS X 10.2. */
- if (err == noErr)
- HIViewClick (ch, eventRef);
- }
- break;
-#endif /* USE_MAC_TOOLBAR */
-
- default:
- break;
- }
- }
- break;
-
-#if !TARGET_API_MAC_CARBON
- case updateEvt:
- do_window_update ((WindowRef) er.message);
- break;
-#endif
-
- case osEvt:
- switch ((er.message >> 24) & 0x000000FF)
- {
- case mouseMovedMessage:
-#if !TARGET_API_MAC_CARBON
- SetRectRgn (mouse_region, er.where.h, er.where.v,
- er.where.h + 1, er.where.v + 1);
-#endif
- previous_help_echo_string = help_echo_string;
- help_echo_string = Qnil;
-
- if (dpyinfo->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- f = last_mouse_frame;
- else
- f = dpyinfo->x_focus_frame;
-
- if (dpyinfo->mouse_face_hidden)
- {
- dpyinfo->mouse_face_hidden = 0;
- clear_mouse_face (dpyinfo);
- }
-
- if (f)
- {
- WindowRef wp = FRAME_MAC_WINDOW (f);
- Point mouse_pos;
-
- mouse_pos.h = (er.where.h
- - (f->left_pos
- + FRAME_OUTER_TO_INNER_DIFF_X (f)));
- mouse_pos.v = (er.where.v
- - (f->top_pos
- + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
- if (dpyinfo->grabbed && tracked_scroll_bar)
-#ifdef USE_TOOLKIT_SCROLL_BARS
- x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
- mouse_pos, &inev);
-#else /* not USE_TOOLKIT_SCROLL_BARS */
- x_scroll_bar_note_movement (tracked_scroll_bar,
- mouse_pos.v
- - XINT (tracked_scroll_bar->top),
- er.when * (1000 / 60));
-#endif /* not USE_TOOLKIT_SCROLL_BARS */
- else
- {
- /* Generate SELECT_WINDOW_EVENTs when needed. */
- if (!NILP (Vmouse_autoselect_window))
- {
- Lisp_Object window;
-
- window = window_from_coordinates (f,
- mouse_pos.h,
- mouse_pos.v,
- 0, 0, 0, 0);
-
- /* Window will be selected only when it is
- not selected now and last mouse movement
- event was not in it. Minibuffer window
- will be selected only when it is active. */
- if (WINDOWP (window)
- && !EQ (window, last_window)
- && !EQ (window, selected_window)
- /* For click-to-focus window managers
- create event iff we don't leave the
- selected frame. */
- && (focus_follows_mouse
- || (EQ (XWINDOW (window)->frame,
- XWINDOW (selected_window)->frame))))
- {
- inev.kind = SELECT_WINDOW_EVENT;
- inev.frame_or_window = window;
- }
-
- last_window=window;
- }
- if (!note_mouse_movement (f, &mouse_pos))
- help_echo_string = previous_help_echo_string;
-#if USE_MAC_TOOLBAR
- else
- mac_tool_bar_note_mouse_movement (f, eventRef);
-#endif
- }
- }
-
- /* If the contents of the global variable
- help_echo_string has changed, generate a
- HELP_EVENT. */
- if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
- do_help = 1;
- break;
-
- default:
- goto OTHER;
- }
- break;
-
- case activateEvt:
- {
- WindowRef window_ptr = (WindowRef) er.message;
- OSErr err;
- ControlRef root_control;
-
- if (window_ptr == tip_window)
- {
- HideWindow (tip_window);
- break;
- }
-
- if (!is_emacs_window (window_ptr))
- goto OTHER;
-
- f = mac_window_to_frame (window_ptr);
-
- if ((er.modifiers & activeFlag) != 0)
- {
- /* A window has been activated */
- Point mouse_loc;
-
- err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
- if (err == noErr)
- ActivateControl (root_control);
-
- x_detect_focus_change (dpyinfo, &er, &inev);
-
- mouse_loc.h = (er.where.h
- - (f->left_pos
- + FRAME_OUTER_TO_INNER_DIFF_X (f)));
- mouse_loc.v = (er.where.v
- - (f->top_pos
- + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
- /* Window-activated event counts as mouse movement,
- so update things that depend on mouse position. */
- note_mouse_movement (f, &mouse_loc);
- }
- else
- {
- /* A window has been deactivated */
- err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
- if (err == noErr)
- DeactivateControl (root_control);
-
-#ifdef USE_TOOLKIT_SCROLL_BARS
- if (dpyinfo->grabbed && tracked_scroll_bar)
- {
- struct input_event event;
-
- EVENT_INIT (event);
- event.kind = NO_EVENT;
- x_scroll_bar_handle_release (tracked_scroll_bar, &event);
- if (event.kind != NO_EVENT)
- {
- event.timestamp = timestamp;
- kbd_buffer_store_event_hold (&event, hold_quit);
- count++;
- }
- }
-#endif
- dpyinfo->grabbed = 0;
-
- x_detect_focus_change (dpyinfo, &er, &inev);
-
- if (f == dpyinfo->mouse_face_mouse_frame)
- {
- /* If we move outside the frame, then we're
- certainly no longer on any text in the
- frame. */
- clear_mouse_face (dpyinfo);
- dpyinfo->mouse_face_mouse_frame = 0;
- }
-
- /* Generate a nil HELP_EVENT to cancel a help-echo.
- Do it only if there's something to cancel.
- Otherwise, the startup message is cleared when the
- mouse leaves the frame. */
- if (any_help_event_p)
- do_help = -1;
- }
- }
- break;
-
- case keyDown:
- case keyUp:
- case autoKey:
- ObscureCursor ();
-
- f = mac_focus_frame (dpyinfo);
- XSETFRAME (inev.frame_or_window, f);
-
- /* If mouse-highlight is an integer, input clears out mouse
- highlighting. */
- if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
- && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
- {
- clear_mouse_face (dpyinfo);
- dpyinfo->mouse_face_hidden = 1;
- }
-
- {
- UInt32 modifiers = er.modifiers, mapped_modifiers;
-
-#ifdef MAC_OSX
- GetEventParameter (eventRef, kEventParamKeyModifiers,
- typeUInt32, NULL,
- sizeof (UInt32), NULL, &modifiers);
-#endif
- mapped_modifiers = mac_mapped_modifiers (modifiers);
-
-#if TARGET_API_MAC_CARBON
- if (!(mapped_modifiers
- & ~(mac_pass_command_to_system ? cmdKey : 0)
- & ~(mac_pass_control_to_system ? controlKey : 0)))
- goto OTHER;
- else
-#endif
- if (er.what != keyUp)
- do_keystroke (er.what, er.message & charCodeMask,
- (er.message & keyCodeMask) >> 8,
- modifiers, timestamp, &inev);
- }
- break;
-
- case kHighLevelEvent:
- AEProcessAppleEvent (&er);
- break;
-
- default:
- OTHER:
-#if TARGET_API_MAC_CARBON
- {
- OSStatus err;
-
- read_socket_inev = &inev;
- err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
- read_socket_inev = NULL;
- }
-#endif
- break;
- }
-#if TARGET_API_MAC_CARBON
- ReleaseEvent (eventRef);
-#endif
-
- if (inev.kind != NO_EVENT)
- {
- inev.timestamp = timestamp;
- kbd_buffer_store_event_hold (&inev, hold_quit);
- count++;
- }
-
- if (do_help
- && !(hold_quit && hold_quit->kind != NO_EVENT))
- {
- Lisp_Object frame;
-
- if (f)
- XSETFRAME (frame, f);
- else
- frame = Qnil;
-
- if (do_help > 0)
- {
- any_help_event_p = 1;
- gen_help_event (help_echo_string, frame, help_echo_window,
- help_echo_object, help_echo_pos);
- }
- else
- {
- help_echo_string = Qnil;
- gen_help_event (Qnil, frame, Qnil, Qnil, 0);
- }
- count++;
- }
- }
-
- /* If the focus was just given to an autoraising frame,
- raise it now. */
- /* ??? This ought to be able to handle more than one such frame. */
- if (pending_autoraise_frame)
- {
- x_raise_frame (pending_autoraise_frame);
- pending_autoraise_frame = 0;
- }
-
- if (mac_screen_config_changed)
- {
- mac_get_screen_info (dpyinfo);
- mac_screen_config_changed = 0;
- }
-
-#if !TARGET_API_MAC_CARBON
- /* Check which frames are still visible. We do this here because
- there doesn't seem to be any direct notification from the Window
- Manager that the visibility of a window has changed (at least,
- not in all cases). */
- {
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
-
- /* The tooltip has been drawn already. Avoid the
- SET_FRAME_GARBAGED in mac_handle_visibility_change. */
- if (EQ (frame, tip_frame))
- continue;
-
- if (FRAME_MAC_P (f))
- mac_handle_visibility_change (f);
- }
- }
-#endif
-
- --handling_signal;
- UNBLOCK_INPUT;
- return count;
-}
-
-
-/* Need to override CodeWarrior's input function so no conversion is
- done on newlines Otherwise compiled functions in .elc files will be
- read incorrectly. Defined in ...:MSL C:MSL
- Common:Source:buffer_io.c. */
-#ifdef __MWERKS__
-void
-__convert_to_newlines (unsigned char * p, size_t * n)
-{
-#pragma unused(p,n)
-}
-
-void
-__convert_from_newlines (unsigned char * p, size_t * n)
-{
-#pragma unused(p,n)
-}
-#endif
-
-#ifdef MAC_OS8
-void
-make_mac_terminal_frame (struct frame *f)
-{
- Lisp_Object frame;
- Rect r;
-
- XSETFRAME (frame, f);
-
- f->output_method = output_mac;
- f->output_data.mac = (struct mac_output *)
- xmalloc (sizeof (struct mac_output));
- bzero (f->output_data.mac, sizeof (struct mac_output));
-
- XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
-
- FRAME_COLS (f) = 96;
- FRAME_LINES (f) = 4;
-
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
-
- FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
-
- f->output_data.mac->cursor_pixel = 0;
- f->output_data.mac->border_pixel = 0x00ff00;
- f->output_data.mac->mouse_pixel = 0xff00ff;
- f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
-
- f->output_data.mac->text_cursor = kThemeIBeamCursor;
- f->output_data.mac->nontext_cursor = kThemeArrowCursor;
- f->output_data.mac->modeline_cursor = kThemeArrowCursor;
- f->output_data.mac->hand_cursor = kThemePointingHandCursor;
- f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
- f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
-
- FRAME_FONTSET (f) = -1;
- f->output_data.mac->explicit_parent = 0;
- f->left_pos = 8;
- f->top_pos = 32;
- f->border_width = 0;
-
- f->internal_border_width = 0;
-
- f->auto_raise = 1;
- f->auto_lower = 1;
-
- f->new_text_cols = 0;
- f->new_text_lines = 0;
-
- SetRect (&r, f->left_pos, f->top_pos,
- f->left_pos + FRAME_PIXEL_WIDTH (f),
- f->top_pos + FRAME_PIXEL_HEIGHT (f));
-
- BLOCK_INPUT;
-
- if (!(FRAME_MAC_WINDOW (f) =
- NewCWindow (NULL, &r, "\p", true, dBoxProc,
- (WindowRef) -1, 1, (long) f->output_data.mac)))
- abort ();
- /* so that update events can find this mac_output struct */
- f->output_data.mac->mFP = f; /* point back to emacs frame */
-
- UNBLOCK_INPUT;
-
- x_make_gc (f);
-
- /* Need to be initialized for unshow_buffer in window.c. */
- selected_window = f->selected_window;
-
- Fmodify_frame_parameters (frame,
- Fcons (Fcons (Qfont,
- build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
- Fmodify_frame_parameters (frame,
- Fcons (Fcons (Qforeground_color,
- build_string ("black")), Qnil));
- Fmodify_frame_parameters (frame,
- Fcons (Fcons (Qbackground_color,
- build_string ("white")), Qnil));
-}
-#endif
-
-
-/***********************************************************************
- Initialization
- ***********************************************************************/
-
-static int mac_initialized = 0;
-
-static XrmDatabase
-mac_make_rdb (xrm_option)
- const char *xrm_option;
-{
- XrmDatabase database;
-
- database = xrm_get_preference_database (NULL);
- if (xrm_option)
- xrm_merge_string_database (database, xrm_option);
-
- return database;
-}
-
-struct mac_display_info *
-mac_term_init (display_name, xrm_option, resource_name)
- Lisp_Object display_name;
- char *xrm_option;
- char *resource_name;
-{
- struct mac_display_info *dpyinfo;
- struct terminal *terminal;
-
- BLOCK_INPUT;
-
- if (!mac_initialized)
- {
- mac_initialize ();
- mac_initialized = 1;
- }
-
- if (x_display_list)
- error ("Sorry, this version can only handle one display");
-
- dpyinfo = &one_mac_display_info;
- bzero (dpyinfo, sizeof (*dpyinfo));
-
- terminal = mac_create_terminal (dpyinfo);
-
- /* Set the name of the terminal. */
- terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
- strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
- terminal->name[SBYTES (display_name)] = 0;
-
-#ifdef MAC_OSX
- dpyinfo->mac_id_name
- = (char *) xmalloc (SCHARS (Vinvocation_name)
- + SCHARS (Vsystem_name)
- + 2);
- sprintf (dpyinfo->mac_id_name, "%s@%s",
- SDATA (Vinvocation_name), SDATA (Vsystem_name));
-#else
- dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
- strcpy (dpyinfo->mac_id_name, "Mac Display");
-#endif
-
- dpyinfo->reference_count = 0;
- dpyinfo->resx = 72.0;
- dpyinfo->resy = 72.0;
-
- mac_get_screen_info (dpyinfo);
-
- dpyinfo->grabbed = 0;
- dpyinfo->root_window = NULL;
- dpyinfo->terminal->image_cache = make_image_cache ();
-
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
- dpyinfo->mouse_face_window = Qnil;
- dpyinfo->mouse_face_overlay = Qnil;
- dpyinfo->mouse_face_hidden = 0;
-
- dpyinfo->xrdb = mac_make_rdb (xrm_option);
-
- /* Put this display on the chain. */
- dpyinfo->next = x_display_list;
- x_display_list = dpyinfo;
-
- /* Put it on x_display_name_list. */
- x_display_name_list = Fcons (Fcons (display_name,
- Fcons (Qnil, dpyinfo->xrdb)),
- x_display_name_list);
- dpyinfo->name_list_element = XCAR (x_display_name_list);
-
- /* FIXME: Untested.
- Add the default keyboard. */
- add_keyboard_wait_descriptor (0);
-
-#if USE_CG_DRAWING
- mac_init_fringe (terminal->rif);
-#endif
-
- UNBLOCK_INPUT;
-
- return dpyinfo;
-}
-
-/* Get rid of display DPYINFO, assuming all frames are already gone. */
-
-void
-x_delete_display (dpyinfo)
- struct mac_display_info *dpyinfo;
-{
- int i;
-
- /* Discard this display from x_display_name_list and x_display_list.
- We can't use Fdelq because that can quit. */
- if (! NILP (x_display_name_list)
- && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
- x_display_name_list = XCDR (x_display_name_list);
- else
- {
- Lisp_Object tail;
-
- tail = x_display_name_list;
- while (CONSP (tail) && CONSP (XCDR (tail)))
- {
- if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
- {
- XSETCDR (tail, XCDR (XCDR (tail)));
- break;
- }
- tail = XCDR (tail);
- }
- }
-
- if (x_display_list == dpyinfo)
- x_display_list = dpyinfo->next;
- else
- {
- struct x_display_info *tail;
-
- for (tail = x_display_list; tail; tail = tail->next)
- if (tail->next == dpyinfo)
- tail->next = tail->next->next;
- }
-
- /* Free the font names in the font table. */
- for (i = 0; i < dpyinfo->n_fonts; i++)
- if (dpyinfo->font_table[i].name)
- {
- if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
- xfree (dpyinfo->font_table[i].full_name);
- xfree (dpyinfo->font_table[i].name);
- }
-
- if (dpyinfo->font_table)
- {
- xfree (dpyinfo->font_table->font_encoder);
- xfree (dpyinfo->font_table);
- }
- xfree (dpyinfo->mac_id_name);
-
- if (x_display_list == 0)
- {
- mac_clear_font_name_table ();
- bzero (dpyinfo, sizeof (*dpyinfo));
- }
-}
-
-
-static void
-init_menu_bar ()
-{
-#ifdef MAC_OSX
- OSStatus err;
- MenuRef menu;
- MenuItemIndex menu_index;
-
- err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
- &menu, &menu_index);
- if (err == noErr)
- SetMenuItemCommandKey (menu, menu_index, false, 0);
- EnableMenuCommand (NULL, kHICommandPreferences);
- err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
- &menu, &menu_index);
- if (err == noErr)
- {
- SetMenuItemCommandKey (menu, menu_index, false, 0);
- InsertMenuItemTextWithCFString (menu, NULL,
- 0, kMenuItemAttrSeparator, 0);
- InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
- 0, 0, kHICommandAbout);
- }
-#else /* !MAC_OSX */
-#if TARGET_API_MAC_CARBON
- SetMenuItemCommandID (GetMenuRef (M_APPLE), I_ABOUT, kHICommandAbout);
-#endif
-#endif
-}
-
-#if USE_MAC_TSM
-static void
-init_tsm ()
-{
-#ifdef MAC_OSX
- static InterfaceTypeList types = {kUnicodeDocument};
-#else
- static InterfaceTypeList types = {kTextService};
-#endif
-
- NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
- &tsm_document_id, 0);
-}
-#endif
-
-/* Set up use of X before we make the first connection. */
-
-extern frame_parm_handler mac_frame_parm_handlers[];
-
-static struct redisplay_interface x_redisplay_interface =
-{
- mac_frame_parm_handlers,
- x_produce_glyphs,
- x_write_glyphs,
- x_insert_glyphs,
- x_clear_end_of_line,
- x_scroll_run,
- x_after_update_window_line,
- x_update_window_begin,
- x_update_window_end,
- x_cursor_to,
- x_flush,
-#if USE_CG_DRAWING
- mac_flush_display_optional,
-#else
- 0, /* flush_display_optional */
-#endif
- x_clear_window_mouse_face,
- x_get_glyph_overhangs,
- x_fix_overlapping_area,
- x_draw_fringe_bitmap,
-#if USE_CG_DRAWING
- mac_define_fringe_bitmap,
- mac_destroy_fringe_bitmap,
-#else
- 0, /* define_fringe_bitmap */
- 0, /* destroy_fringe_bitmap */
-#endif
- mac_per_char_metric,
- mac_encode_char,
- mac_compute_glyph_string_overhangs,
- x_draw_glyph_string,
- mac_define_frame_cursor,
- mac_clear_frame_area,
- mac_draw_window_cursor,
- mac_draw_vertical_window_border,
- mac_shift_glyphs_for_insert
-};
-
-static struct terminal *
-mac_create_terminal (struct mac_display_info *dpyinfo)
-{
- struct terminal *terminal;
-
- terminal = create_terminal ();
-
- terminal->type = output_mac;
- terminal->display_info.mac = dpyinfo;
- dpyinfo->terminal = terminal;
-
- terminal->clear_frame_hook = x_clear_frame;
- terminal->ins_del_lines_hook = x_ins_del_lines;
- terminal->delete_glyphs_hook = x_delete_glyphs;
- terminal->ring_bell_hook = XTring_bell;
- terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
- terminal->set_terminal_modes_hook = XTset_terminal_modes;
- terminal->update_begin_hook = x_update_begin;
- terminal->update_end_hook = x_update_end;
- terminal->set_terminal_window_hook = XTset_terminal_window;
- terminal->read_socket_hook = XTread_socket;
- terminal->frame_up_to_date_hook = XTframe_up_to_date;
- terminal->mouse_position_hook = XTmouse_position;
- terminal->frame_rehighlight_hook = XTframe_rehighlight;
- terminal->frame_raise_lower_hook = XTframe_raise_lower;
- /* terminal->fullscreen_hook = XTfullscreen_hook; */
- terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
- terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
- terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
- terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
- terminal->delete_frame_hook = x_destroy_window;
- /* terminal->delete_terminal_hook = x_delete_terminal; */
-
- terminal->rif = &x_redisplay_interface;
-#if 0
- TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
- TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
- TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
- TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
- TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
- scrolls off the
- bottom */
-#else
- terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
- terminal->char_ins_del_ok = 1;
- terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
- terminal->fast_clear_end_of_line = 1; /* X does this well. */
- terminal->memory_below_frame = 0; /* We don't remember what scrolls
- off the bottom. */
-
-#endif
-
- /* FIXME: This keyboard setup is 100% untested, just copied from
- w32_create_terminal in order to set window-system now that it's
- a keyboard object. */
- /* We don't yet support separate terminals on Mac, so don't try to share
- keyboards between virtual terminals that are on the same physical
- terminal like X does. */
- terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
- init_kboard (terminal->kboard);
- terminal->kboard->Vwindow_system = intern ("mac");
- terminal->kboard->next_kboard = all_kboards;
- all_kboards = terminal->kboard;
- /* Don't let the initial kboard remain current longer than necessary.
- That would cause problems if a file loaded on startup tries to
- prompt in the mini-buffer. */
- if (current_kboard == initial_kboard)
- current_kboard = terminal->kboard;
- terminal->kboard->reference_count++;
-
- return terminal;
-}
-
-static void
-mac_initialize ()
-{
-
- baud_rate = 19200;
-
- last_tool_bar_item = -1;
- any_help_event_p = 0;
-
- /* Try to use interrupt input; if we can't, then start polling. */
- Fset_input_interrupt_mode (Qt);
-
- BLOCK_INPUT;
-
-#if TARGET_API_MAC_CARBON
-
- install_application_handler ();
-
- init_menu_bar ();
-
-#if USE_MAC_TSM
- init_tsm ();
-#endif
-
-#ifdef MAC_OSX
- init_coercion_handler ();
-
- init_apple_event_handler ();
-
- init_dm_notification_handler ();
-
- if (!inhibit_window_system)
- {
- static const ProcessSerialNumber psn = {0, kCurrentProcess};
-
- SetFrontProcess (&psn);
- }
-#endif
-#endif
-
-#if USE_CG_DRAWING
- init_cg_color ();
-#endif
-
- UNBLOCK_INPUT;
-
-}
-
-
-void
-syms_of_macterm ()
-{
-#if 0
- staticpro (&x_error_message_string);
- x_error_message_string = Qnil;
-#endif
-
- Qcontrol = intern ("control"); staticpro (&Qcontrol);
- Qmeta = intern ("meta"); staticpro (&Qmeta);
- Qalt = intern ("alt"); staticpro (&Qalt);
- Qhyper = intern ("hyper"); staticpro (&Qhyper);
- Qsuper = intern ("super"); staticpro (&Qsuper);
- Qmodifier_value = intern ("modifier-value");
- staticpro (&Qmodifier_value);
-
- Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
- Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
- Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
- Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
- Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
-
-#if TARGET_API_MAC_CARBON
- Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
-#ifdef MAC_OSX
- Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
- staticpro (&Qtoolbar_switch_mode);
-#if USE_MAC_FONT_PANEL
- Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
- Qselection = intern ("selection"); staticpro (&Qselection);
-#endif
-
- Qservice = intern ("service"); staticpro (&Qservice);
- Qpaste = intern ("paste"); staticpro (&Qpaste);
- Qperform = intern ("perform"); staticpro (&Qperform);
-
- Qmouse_drag_overlay = intern ("mouse-drag-overlay");
- staticpro (&Qmouse_drag_overlay);
-#endif
-#if USE_MAC_TSM
- Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
- Qupdate_active_input_area = intern ("update-active-input-area");
- staticpro (&Qupdate_active_input_area);
- Qunicode_for_key_event = intern ("unicode-for-key-event");
- staticpro (&Qunicode_for_key_event);
-#endif
-#endif
-
-#ifdef MAC_OSX
- Fprovide (intern ("mac-carbon"), Qnil);
-#endif
-
- staticpro (&Qreverse);
- Qreverse = intern ("reverse");
-
- staticpro (&x_display_name_list);
- x_display_name_list = Qnil;
-
- staticpro (&last_mouse_scroll_bar);
- last_mouse_scroll_bar = Qnil;
-
- staticpro (&fm_font_family_alist);
- fm_font_family_alist = Qnil;
-
-#if USE_ATSUI
- staticpro (&atsu_font_id_hash);
- atsu_font_id_hash = Qnil;
-
- staticpro (&fm_style_face_attributes_alist);
- fm_style_face_attributes_alist = Qnil;
-#endif
-
-#if USE_MAC_TSM
- staticpro (&saved_ts_script_language_on_focus);
- saved_ts_script_language_on_focus = Qnil;
-#endif
-
- /* We don't yet support this, but defining this here avoids whining
- from cus-start.el and other places, like "M-x set-variable". */
- DEFVAR_BOOL ("x-use-underline-position-properties",
- &x_use_underline_position_properties,
- doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
-A value of nil means ignore them. If you encounter fonts with bogus
-UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
-to 4.1, set this to nil.
-
-NOTE: Not supported on Mac yet. */);
- x_use_underline_position_properties = 0;
-
- DEFVAR_BOOL ("x-underline-at-descent-line",
- &x_underline_at_descent_line,
- doc: /* *Non-nil means to draw the underline at the same place as the descent line.
-A value of nil means to draw the underline according to the value of the
-variable `x-use-underline-position-properties', which is usually at the
-baseline level. The default value is nil. */);
- x_underline_at_descent_line = 0;
-
- DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
- doc: /* If not nil, Emacs uses toolkit scroll bars. */);
-#ifdef USE_TOOLKIT_SCROLL_BARS
- Vx_toolkit_scroll_bars = Qt;
-#else
- Vx_toolkit_scroll_bars = Qnil;
-#endif
-
- staticpro (&last_mouse_motion_frame);
- last_mouse_motion_frame = Qnil;
-
-/* Variables to configure modifier key assignment. */
-
- DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
- doc: /* *Modifier key assumed when the Mac control key is pressed.
-The value can be `control', `meta', `alt', `hyper', or `super' for the
-respective modifier. The default is `control'. */);
- Vmac_control_modifier = Qcontrol;
-
- DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
- doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
-The value can be `control', `meta', `alt', `hyper', or `super' for the
-respective modifier. If the value is nil then the key will act as the
-normal Mac control modifier, and the option key can be used to compose
-characters depending on the chosen Mac keyboard setting. */);
- Vmac_option_modifier = Qnil;
-
- DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
- doc: /* *Modifier key assumed when the Mac command key is pressed.
-The value can be `control', `meta', `alt', `hyper', or `super' for the
-respective modifier. The default is `meta'. */);
- Vmac_command_modifier = Qmeta;
-
- DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
- doc: /* *Modifier key assumed when the Mac function key is pressed.
-The value can be `control', `meta', `alt', `hyper', or `super' for the
-respective modifier. Note that remapping the function key may lead to
-unexpected results for some keys on non-US/GB keyboards. */);
- Vmac_function_modifier = Qnil;
-
- DEFVAR_LISP ("mac-emulate-three-button-mouse",
- &Vmac_emulate_three_button_mouse,
- doc: /* *Specify a way of three button mouse emulation.
-The value can be nil, t, or the symbol `reverse'.
-A value of nil means that no emulation should be done and the modifiers
-should be placed on the mouse-1 event.
-t means that when the option-key is held down while pressing the mouse
-button, the click will register as mouse-2 and while the command-key
-is held down, the click will register as mouse-3.
-The symbol `reverse' means that the option-key will register for
-mouse-3 and the command-key will register for mouse-2. */);
- Vmac_emulate_three_button_mouse = Qnil;
-
-#if TARGET_API_MAC_CARBON
- DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
- doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
-Otherwise, the right click will be treated as mouse-2 and the wheel
-button will be mouse-3. */);
- mac_wheel_button_is_mouse_2 = 1;
-
- DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
- doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
- mac_pass_command_to_system = 1;
-
- DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
- doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
- mac_pass_control_to_system = 1;
-
-#endif
-
- DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
- doc: /* *If non-nil, allow anti-aliasing.
-The text will be rendered using Core Graphics text rendering which
-may anti-alias the text. */);
-#if USE_CG_DRAWING
- mac_use_core_graphics = 1;
-#else
- mac_use_core_graphics = 0;
-#endif
-
- /* Register an entry for `mac-roman' so that it can be used when
- creating the terminal frame on Mac OS 9 before loading
- term/mac-win.elc. */
- DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
- doc: /* Alist of Emacs character sets vs text encodings and coding systems.
-Each entry should be of the form:
-
- (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
-
-where CHARSET-NAME is a string used in font names to identify the
-charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
-CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
- Vmac_charset_info_alist =
- Fcons (list3 (build_string ("mac-roman"),
- make_number (smRoman), Qnil), Qnil);
-
-#if USE_MAC_TSM
- DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
- doc: /* Overlay used to display Mac TSM active input area. */);
- Vmac_ts_active_input_overlay = Qnil;
-
- DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf,
- doc: /* Byte sequence of the current Mac TSM active input area. */);
- /* `empty_string' is not ready yet on Mac OS Classic. */
- Vmac_ts_active_input_buf = build_string ("");
-
- DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
- doc: /* *How to change Mac TSM script/language when a frame gets focus.
-If the value is t, the input script and language are restored to those
-used in the last focus frame. If the value is a pair of integers, the
-input script and language codes, which are defined in the Script
-Manager, are set to its car and cdr parts, respectively. Otherwise,
-Emacs doesn't set them and thus follows the system default behavior. */);
- Vmac_ts_script_language_on_focus = Qnil;
-#endif
-}
-
-/* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
- (do not change this comment) */