/* Implementation of GUI terminal on the Mac OS.
Copyright (C) 2000, 2001, 2002, 2003, 2004,
- 2005 Free Software Foundation, Inc.
+ 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <errno.h>
#include <setjmp.h>
#include <sys/stat.h>
-#include <sys/param.h>
#include "charset.h"
#include "coding.h"
#include "termhooks.h"
#include "termopts.h"
#include "termchar.h"
-#include "gnu.h"
#include "disptab.h"
#include "buffer.h"
#include "window.h"
#include "atimer.h"
#include "keymap.h"
-/* Set of macros that handle mapping of Mac modifier keys to emacs. */
-#define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
- (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
-#define macShiftKey (shiftKey)
-#define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
- (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
- : controlKey)
-#define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
\f
/* Non-nil means Emacs uses toolkit scroll bars. */
Lisp_Object Vx_toolkit_scroll_bars;
-/* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
-Lisp_Object Vmac_use_core_graphics;
+/* 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
/* 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;
+
/* This is a chain of structures for all the X displays currently in
use. */
/* 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.
/* The keysyms to use for the various modifiers. */
-static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
+static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
extern int inhibit_window_system;
struct mac_display_info *mac_display_info_for_display (Display *);
static void x_update_window_end P_ ((struct window *, int, int));
-static int x_io_error_quitter P_ ((Display *));
int x_catch_errors P_ ((Display *));
void x_uncatch_errors P_ ((Display *, int));
void x_lower_frame P_ ((struct frame *));
unsigned long *));
static int is_emacs_window P_ ((WindowPtr));
-
+static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
static void XSetFont P_ ((Display *, GC, XFontStruct *));
/* Defined in macmenu.h. */
#define GC_FORE_COLOR(gc) (&(gc)->fore_color)
#define GC_BACK_COLOR(gc) (&(gc)->back_color)
#define GC_FONT(gc) ((gc)->xgcv.font)
-#define GC_CLIP_REGION(gc) ((gc)->clip_region)
-#define MAC_WINDOW_NORMAL_GC(w) (((mac_output *) GetWRefCon (w))->normal_gc)
+#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)
+#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
+#define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
+
+/* Fringe bitmaps. */
+
+static int max_fringe_bmp = 0;
+static CGImageRef *fringe_bmp = 0;
+
+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 (region)
- RgnHandle region;
+mac_begin_clip (gc)
+ GC gc;
{
static RgnHandle new_region = NULL;
if (new_region == NULL)
new_region = NewRgn ();
- if (region)
+ if (gc->n_clip_rects)
{
GetClip (saved_port_clip_region);
- SectRgn (saved_port_clip_region, region, new_region);
+ SectRgn (saved_port_clip_region, gc->clip_region, new_region);
SetClip (new_region);
}
}
static void
-mac_end_clip (region)
- RgnHandle region;
+mac_end_clip (gc)
+ GC gc;
{
- if (region)
+ if (gc->n_clip_rects)
SetClip (saved_port_clip_region);
}
/* Mac version of XDrawLine. */
static void
-XDrawLine (display, w, gc, x1, y1, x2, y2)
- Display *display;
- WindowPtr w;
+mac_draw_line (f, gc, x1, y1, x2, y2)
+ struct frame *f;
GC gc;
int x1, y1, x2, y2;
{
- SetPortWindowPort (w);
+#if USE_CG_DRAWING
+ CGContextRef context;
+
+ context = mac_begin_cg_clip (f, gc);
+ CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+ CGContextBeginPath (context);
+ CGContextMoveToPoint (context, x1 + 0.5f, y1 + 0.5f);
+ CGContextAddLineToPoint (context, x2 + 0.5f, y2 + 0.5f);
+ CGContextClosePath (context);
+ CGContextStrokePath (context);
+ mac_end_cg_clip (f);
+#else
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
RGBForeColor (GC_FORE_COLOR (gc));
- mac_begin_clip (GC_CLIP_REGION (gc));
+ mac_begin_clip (gc);
MoveTo (x1, y1);
LineTo (x2, y2);
- mac_end_clip (GC_CLIP_REGION (gc));
+ mac_end_clip (gc);
+#endif
}
void
static void
-mac_erase_rectangle (w, gc, x, y, width, height)
- WindowPtr w;
+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 (context, gc->xgcv.background);
+ CGContextFillRect (context, CGRectMake (x, y, width, height));
+ mac_end_cg_clip (f);
+#else
Rect r;
- SetPortWindowPort (w);
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
RGBBackColor (GC_BACK_COLOR (gc));
SetRect (&r, x, y, x + width, y + height);
- mac_begin_clip (GC_CLIP_REGION (gc));
+ mac_begin_clip (gc);
EraseRect (&r);
- mac_end_clip (GC_CLIP_REGION (gc));
+ mac_end_clip (gc);
- RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
+ RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+#endif
}
/* Mac version of XClearArea. */
void
-XClearArea (display, w, x, y, width, height, exposures)
- Display *display;
- WindowPtr w;
+mac_clear_area (f, x, y, width, height)
+ struct frame *f;
int x, y;
unsigned int width, height;
- int exposures;
{
- mac_erase_rectangle (w, MAC_WINDOW_NORMAL_GC (w), x, y, width, height);
+ mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
}
/* Mac version of XClearWindow. */
static void
-XClearWindow (display, w)
- Display *display;
- WindowPtr w;
+mac_clear_window (f)
+ struct frame *f;
{
- SetPortWindowPort (w);
+#if USE_CG_DRAWING
+ CGContextRef context;
+ GC gc = FRAME_NORMAL_GC (f);
- RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
+ context = mac_begin_cg_clip (f, NULL);
+ CG_SET_FILL_COLOR (context, gc->xgcv.background);
+ CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f)));
+ mac_end_cg_clip (f);
+#else
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
+
+ RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
#if TARGET_API_MAC_CARBON
{
Rect r;
- GetWindowPortBounds (w, &r);
+ GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
EraseRect (&r);
}
#else /* not TARGET_API_MAC_CARBON */
- EraseRect (&(w->portRect));
+ 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_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
- Display *display;
- WindowPtr w;
+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;
+ float port_height = FRAME_PIXEL_HEIGHT (f);
+ CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
+
+ context = mac_begin_cg_clip (f, gc);
+ if (!overlay_p)
+ {
+ CG_SET_FILL_COLOR (context, gc->xgcv.background);
+ CGContextFillRect (context, dest_rect);
+ }
+ CGContextClipToRect (context, dest_rect);
+ CGContextScaleCTM (context, 1, -1);
+ CGContextTranslateCTM (context, 0, -port_height);
+ if (CGImageIsMask (image))
+ CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+ CGContextDrawImage (context,
+ CGRectMake (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;
bitmap.baseAddr = (char *)bits;
SetRect (&(bitmap.bounds), 0, 0, width, height);
- SetPortWindowPort (w);
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
RGBForeColor (GC_FORE_COLOR (gc));
RGBBackColor (GC_BACK_COLOR (gc));
SetRect (&r, x, y, x + width, y + height);
- mac_begin_clip (GC_CLIP_REGION (gc));
+ mac_begin_clip (gc);
#if TARGET_API_MAC_CARBON
- LockPortBits (GetWindowPort (w));
- CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
- &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
- UnlockPortBits (GetWindowPort (w));
+ {
+ 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, &(w->portBits), &(bitmap.bounds), &r,
+ CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
overlay_p ? srcOr : srcCopy, 0);
#endif /* not TARGET_API_MAC_CARBON */
- mac_end_clip (GC_CLIP_REGION (gc));
+ mac_end_clip (gc);
- RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
+ RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
}
+#endif /* !USE_CG_DRAWING */
/* Mac replacement for XCreateBitmapFromBitmapData. */
SetPortWindowPort (w);
SetRect (&r, 0, 0, width, height);
- err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
+#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;
/* Mac replacement for XFillRectangle. */
static void
-XFillRectangle (display, w, gc, x, y, width, height)
- Display *display;
- WindowPtr w;
+mac_fill_rectangle (f, gc, x, y, width, height)
+ struct frame *f;
GC gc;
int x, y;
unsigned int width, height;
{
- Rect r;
-
- SetPortWindowPort (w);
-
- RGBForeColor (GC_FORE_COLOR (gc));
- SetRect (&r, x, y, x + width, y + height);
+#if USE_CG_DRAWING
+ CGContextRef context;
- mac_begin_clip (GC_CLIP_REGION (gc));
- PaintRect (&r); /* using foreground color of gc */
- mac_end_clip (GC_CLIP_REGION (gc));
-}
-
-
-#if 0 /* TODO: figure out if we need to do this on Mac. */
-static void
-mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
- Display *display;
- Pixmap p;
- GC gc;
- int x, y;
- unsigned int width, height;
-{
- CGrafPtr old_port;
- GDHandle old_gdh;
+ context = mac_begin_cg_clip (f, gc);
+ CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+ CGContextFillRect (context, CGRectMake (x, y, width, height));
+ mac_end_cg_clip (f);
+#else
Rect r;
- GetGWorld (&old_port, &old_gdh);
- SetGWorld (p, NULL);
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
+
RGBForeColor (GC_FORE_COLOR (gc));
SetRect (&r, x, y, x + width, y + height);
- LockPixels (GetGWorldPixMap (p));
+ mac_begin_clip (gc);
PaintRect (&r); /* using foreground color of gc */
- UnlockPixels (GetGWorldPixMap (p));
-
- SetGWorld (old_port, old_gdh);
-}
+ mac_end_clip (gc);
#endif
+}
/* Mac replacement for XDrawRectangle: dest is a window. */
static void
-mac_draw_rectangle (display, w, gc, x, y, width, height)
- Display *display;
- WindowPtr w;
+mac_draw_rectangle (f, gc, x, y, width, height)
+ struct frame *f;
GC gc;
int x, y;
unsigned int width, height;
{
- Rect r;
+#if USE_CG_DRAWING
+ CGContextRef context;
- SetPortWindowPort (w);
-
- RGBForeColor (GC_FORE_COLOR (gc));
- SetRect (&r, x, y, x + width + 1, y + height + 1);
-
- mac_begin_clip (GC_CLIP_REGION (gc));
- FrameRect (&r); /* using foreground color of gc */
- mac_end_clip (GC_CLIP_REGION (gc));
-}
-
-
-#if 0 /* TODO: figure out if we need to do this on Mac. */
-/* Mac replacement for XDrawRectangle: dest is a Pixmap. */
-
-static void
-mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
- Display *display;
- Pixmap p;
- GC gc;
- int x, y;
- unsigned int width, height;
-{
- CGrafPtr old_port;
- GDHandle old_gdh;
+ context = mac_begin_cg_clip (f, gc);
+ CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+ CGContextStrokeRect (context,
+ CGRectMake (x + 0.5f, y + 0.5f, width, height));
+ mac_end_cg_clip (f);
+#else
Rect r;
- GetGWorld (&old_port, &old_gdh);
- SetGWorld (p, NULL);
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
+
RGBForeColor (GC_FORE_COLOR (gc));
SetRect (&r, x, y, x + width + 1, y + height + 1);
- LockPixels (GetGWorldPixMap (p));
+ mac_begin_clip (gc);
FrameRect (&r); /* using foreground color of gc */
- UnlockPixels (GetGWorldPixMap (p));
-
- SetGWorld (old_port, old_gdh);
-}
+ mac_end_clip (gc);
#endif
+}
#if USE_ATSUI
ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
static ATSLineLayoutOptions line_layout =
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
+ kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
+ | kATSLineUseQDRendering
#else
kATSLineIsDisplayOnly | kATSLineFractDisable
#endif
}
#endif
+
static void
-mac_invert_rectangle (display, w, x, y, width, height)
- Display *display;
- WindowPtr w;
+mac_invert_rectangle (f, x, y, width, height)
+ struct frame *f;
int x, y;
unsigned int width, height;
{
Rect r;
- SetPortWindowPort (w);
+#if USE_CG_DRAWING
+ mac_prepare_for_quickdraw (f);
+#endif
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
SetRect (&r, x, y, x + width, y + height);
static void
-mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
- bytes_per_char)
- Display *display;
- WindowPtr w;
+mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, bytes_per_char)
+ struct frame *f;
GC gc;
int x, y;
char *buf;
- int nchars, mode, bytes_per_char;
+ int nchars, bg_width, bytes_per_char;
{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- UInt32 textFlags, savedFlags;
- if (!NILP(Vmac_use_core_graphics)) {
- textFlags = kQDUseCGTextRendering;
- savedFlags = SwapQDTextFlags(textFlags);
- }
-#endif
-
- SetPortWindowPort (w);
-
- RGBForeColor (GC_FORE_COLOR (gc));
- if (mode != srcOr)
- RGBBackColor (GC_BACK_COLOR (gc));
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
#if USE_ATSUI
if (GC_FONT (gc)->mac_style)
#ifndef WORDS_BIG_ENDIAN
{
int i;
- Unichar *text = (Unichar *)buf;
+ UniChar *text = (UniChar *)buf;
for (i = 0; i < nchars; i++)
- text[i] = buf[2*i] << 8 | buf[2*i+1];
+ 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)
- {
+ if (err != noErr)
+ return;
#ifdef MAC_OSX
- if (NILP (Vmac_use_core_graphics))
- {
+ if (!mac_use_core_graphics)
+ {
#endif
- mac_begin_clip (GC_CLIP_REGION (gc));
- MoveTo (x, y);
- ATSUDrawText (text_layout,
- kATSUFromTextBeginning, kATSUToTextEnd,
- kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
- mac_end_clip (GC_CLIP_REGION (gc));
-#ifdef MAC_OSX
+#if USE_CG_DRAWING
+ mac_prepare_for_quickdraw (f);
+#endif
+ mac_begin_clip (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)));
}
- else
+ MoveTo (x, y);
+ ATSUDrawText (text_layout,
+ kATSUFromTextBeginning, kATSUToTextEnd,
+ kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
+ mac_end_clip (gc);
+#ifdef MAC_OSX
+ }
+ else
+ {
+ CGrafPtr port;
+ CGContextRef context;
+ float port_height = FRAME_PIXEL_HEIGHT (f);
+ ATSUAttributeTag tags[] = {kATSUCGContextTag};
+ ByteCount sizes[] = {sizeof (CGContextRef)};
+ ATSUAttributeValuePtr values[] = {&context};
+
+#if USE_CG_DRAWING
+ context = mac_begin_cg_clip (f, gc);
+#else
+ GetPort (&port);
+ QDBeginCGContext (port, &context);
+ if (gc->n_clip_rects || bg_width)
{
- CGrafPtr port;
- CGContextRef context;
- Rect rect;
- float port_height;
- ATSUAttributeTag tags[] = {kATSUCGContextTag};
- ByteCount sizes[] = {sizeof (CGContextRef)};
- ATSUAttributeValuePtr values[] = {&context};
-
- GetPort (&port);
- QDBeginCGContext (port, &context);
- GetPortBounds (port, &rect);
- port_height = rect.bottom - rect.top;
+ 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)
{
- CGContextTranslateCTM (context, 0, port_height);
- CGContextScaleCTM (context, 1, -1);
- CGContextClipToRects (context, gc->clip_rects,
- gc->n_clip_rects);
- CGContextScaleCTM (context, 1, -1);
- CGContextTranslateCTM (context, 0, -port_height);
+ CG_SET_FILL_COLOR (context, gc->xgcv.background);
+ CGContextFillRect
+ (context,
+ CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
+ bg_width, FONT_HEIGHT (GC_FONT (gc))));
}
- CGContextSetRGBFillColor
- (context,
- RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
- GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
- BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
- 1.0);
- 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));
- ATSUClearLayoutControls (text_layout,
- sizeof (tags) / sizeof (tags[0]),
- tags);
- CGContextSynchronize (context);
- QDEndCGContext (port, &context);
+ CGContextScaleCTM (context, 1, -1);
+ CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
}
+#endif
+ CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+ 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 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 */
}
else
+#endif /* USE_ATSUI */
{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+ UInt32 savedFlags;
+
+ if (mac_use_core_graphics)
+ savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
+#endif
+#if USE_CG_DRAWING
+ mac_prepare_for_quickdraw (f);
#endif
- TextFont (GC_FONT (gc)->mac_fontnum);
- TextSize (GC_FONT (gc)->mac_fontsize);
- TextFace (GC_FONT (gc)->mac_fontface);
- TextMode (mode);
+ mac_begin_clip (gc);
+ 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;
- mac_begin_clip (GC_CLIP_REGION (gc));
- MoveTo (x, y);
- DrawText (buf, 0, nchars * bytes_per_char);
- mac_end_clip (GC_CLIP_REGION (gc));
-#if USE_ATSUI
- }
+ 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 (bg_width)
+ RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+ mac_end_clip (gc);
- if (mode != srcOr)
- RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- if (!NILP(Vmac_use_core_graphics))
- SwapQDTextFlags(savedFlags);
+ if (mac_use_core_graphics)
+ SwapQDTextFlags(savedFlags);
#endif
+ }
}
/* Mac replacement for XDrawString. */
static void
-XDrawString (display, w, gc, x, y, buf, nchars)
- Display *display;
- WindowPtr w;
+mac_draw_string (f, gc, x, y, buf, nchars)
+ struct frame *f;
GC gc;
int x, y;
char *buf;
int nchars;
{
- mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
+ mac_draw_string_common (f, gc, x, y, buf, nchars, 0, 1);
}
/* Mac replacement for XDrawString16. */
static void
-XDrawString16 (display, w, gc, x, y, buf, nchars)
- Display *display;
- WindowPtr w;
+mac_draw_string_16 (f, gc, x, y, buf, nchars)
+ struct frame *f;
GC gc;
int x, y;
XChar2b *buf;
int nchars;
{
- mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
- 2);
+ mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, 0, 2);
}
/* Mac replacement for XDrawImageString. */
static void
-XDrawImageString (display, w, gc, x, y, buf, nchars)
- Display *display;
- WindowPtr w;
+mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width)
+ struct frame *f;
GC gc;
int x, y;
char *buf;
- int nchars;
+ int nchars, bg_width;
{
- mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
+ mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, 1);
}
/* Mac replacement for XDrawString16. */
static void
-XDrawImageString16 (display, w, gc, x, y, buf, nchars)
- Display *display;
- WindowPtr w;
+mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width)
+ struct frame *f;
GC gc;
int x, y;
XChar2b *buf;
+ int nchars, bg_width;
+{
+ mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width, 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 OSErr
+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
+{
+ OSErr 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)
+ {
+ 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)
+ {
+ OSErr 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)
+ {
+ 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 ()
{
- mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
- 2);
+ 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)
+ struct frame *f;
+ GC gc;
+ int x, y;
+ XChar2b *buf;
+ int nchars, bg_width;
+{
+ CGrafPtr port;
+ float 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 = GetWindowPort (FRAME_MAC_WINDOW (f));
+ 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 (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 (context, gc->xgcv.background);
+ CGContextFillRect
+ (context,
+ CGRectMake (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 (context, gc->xgcv.foreground);
+ 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
+ CGContextSetTextPosition (context, gx, gy);
+ CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
+#else
+ for (i = 0; i < nchars; i++)
+ {
+ CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
+ gx += advances[i].width;
+ }
+#endif
+#if USE_CG_DRAWING
+ mac_end_cg_clip (f);
+#else
+ CGContextSynchronize (context);
+ QDEndCGContext (port, &context);
+#endif
+
+ return 1;
}
+#endif
+#if !USE_CG_DRAWING
/* Mac replacement for XCopyArea: dest must be window. */
static void
-mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
- dest_y)
- Display *display;
+mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
Pixmap src;
- WindowPtr dest;
+ struct frame *f;
GC gc;
int src_x, src_y;
unsigned int width, height;
{
Rect src_r, dest_r;
- SetPortWindowPort (dest);
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
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);
- mac_begin_clip (GC_CLIP_REGION (gc));
+ mac_begin_clip (gc);
LockPixels (GetGWorldPixMap (src));
#if TARGET_API_MAC_CARBON
- LockPortBits (GetWindowPort (dest));
- CopyBits (GetPortBitMapForCopyBits (src),
- GetPortBitMapForCopyBits (GetWindowPort (dest)),
- &src_r, &dest_r, srcCopy, 0);
- UnlockPortBits (GetWindowPort (dest));
+ {
+ 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), &(dest->portBits),
+ CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
&src_r, &dest_r, srcCopy, 0);
#endif /* not TARGET_API_MAC_CARBON */
UnlockPixels (GetGWorldPixMap (src));
- mac_end_clip (GC_CLIP_REGION (gc));
+ mac_end_clip (gc);
- RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (dest)));
+ RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
}
static void
-mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
+mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
width, height, dest_x, dest_y)
- Display *display;
Pixmap src, mask;
- WindowPtr dest;
+ struct frame *f;
GC gc;
int src_x, src_y;
unsigned int width, height;
{
Rect src_r, dest_r;
- SetPortWindowPort (dest);
+ SetPortWindowPort (FRAME_MAC_WINDOW (f));
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);
- mac_begin_clip (GC_CLIP_REGION (gc));
+ mac_begin_clip (gc);
LockPixels (GetGWorldPixMap (src));
LockPixels (GetGWorldPixMap (mask));
#if TARGET_API_MAC_CARBON
- LockPortBits (GetWindowPort (dest));
- CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
- GetPortBitMapForCopyBits (GetWindowPort (dest)),
- &src_r, &src_r, &dest_r);
- UnlockPortBits (GetWindowPort (dest));
+ {
+ 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),
- &(dest->portBits), &src_r, &src_r, &dest_r);
+ &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
#endif /* not TARGET_API_MAC_CARBON */
UnlockPixels (GetGWorldPixMap (mask));
UnlockPixels (GetGWorldPixMap (src));
- mac_end_clip (GC_CLIP_REGION (gc));
+ mac_end_clip (gc);
- RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (dest)));
+ RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
}
+#endif /* !USE_CG_DRAWING */
/* Mac replacement for XCopyArea: used only for scrolling. */
static void
-mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
- Display *display;
- WindowPtr w;
+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;
RgnHandle dummy = NewRgn (); /* For avoiding update events. */
SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
- ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
+#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;
+ WindowPtr w = FRAME_MAC_WINDOW (f);
SetPort (w);
color mapping in CopyBits. Otherwise, it will be slow. */
ForeColor (blackColor);
BackColor (whiteColor);
- mac_begin_clip (GC_CLIP_REGION (gc));
+ mac_begin_clip (gc);
CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
- mac_end_clip (GC_CLIP_REGION (gc));
-
- RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
-#endif /* not TARGET_API_MAC_CARBON */
-}
-
-
-#if 0 /* TODO: figure out if we need to do this on Mac. */
-/* Mac replacement for XCopyArea: dest must be Pixmap. */
-
-static void
-mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
- dest_x, dest_y)
- Display *display;
- Pixmap src, dest;
- GC gc;
- int src_x, src_y;
- unsigned int width, height;
- int dest_x, dest_y;
-{
- CGrafPtr old_port;
- GDHandle old_gdh;
- Rect src_r, dest_r;
-
- GetGWorld (&old_port, &old_gdh);
- SetGWorld (dest, NULL);
- ForeColor (blackColor);
- BackColor (whiteColor);
-
- 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);
-
- LockPixels (GetGWorldPixMap (src));
- LockPixels (GetGWorldPixMap (dest));
-#if TARGET_API_MAC_CARBON
- CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
- &src_r, &dest_r, srcCopy, 0);
-#else /* not TARGET_API_MAC_CARBON */
- CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
- &src_r, &dest_r, srcCopy, 0);
-#endif /* not TARGET_API_MAC_CARBON */
- UnlockPixels (GetGWorldPixMap (dest));
- UnlockPixels (GetGWorldPixMap (src));
-
- SetGWorld (old_port, old_gdh);
-}
-
-
-static void
-mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
- width, height, dest_x, dest_y)
- Display *display;
- Pixmap src, mask, dest;
- GC gc;
- int src_x, src_y;
- unsigned int width, height;
- int dest_x, dest_y;
-{
- CGrafPtr old_port;
- GDHandle old_gdh;
- Rect src_r, dest_r;
-
- GetGWorld (&old_port, &old_gdh);
- SetGWorld (dest, NULL);
- ForeColor (blackColor);
- BackColor (whiteColor);
-
- 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);
+ mac_end_clip (gc);
- LockPixels (GetGWorldPixMap (src));
- LockPixels (GetGWorldPixMap (mask));
- LockPixels (GetGWorldPixMap (dest));
-#if TARGET_API_MAC_CARBON
- CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
- GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
-#else /* not TARGET_API_MAC_CARBON */
- CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
- &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
+ RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
#endif /* not TARGET_API_MAC_CARBON */
- UnlockPixels (GetGWorldPixMap (dest));
- UnlockPixels (GetGWorldPixMap (mask));
- UnlockPixels (GetGWorldPixMap (src));
-
- SetGWorld (old_port, old_gdh);
}
-#endif
/* Mac replacement for XChangeGC. */
{
GC gc = xmalloc (sizeof (*gc));
- if (gc)
- {
- bzero (gc, sizeof (*gc));
- XChangeGC (display, gc, mask, xgcv);
- }
+ bzero (gc, sizeof (*gc));
+ XChangeGC (display, gc, mask, xgcv);
return gc;
}
{
int i;
- if (n < 0 || n > MAX_CLIP_RECTS)
- abort ();
- if (n == 0)
- {
- if (gc->clip_region)
- {
- DisposeRgn (gc->clip_region);
- gc->clip_region = NULL;
- }
- }
- else
+ xassert (n >= 0 && n <= MAX_CLIP_RECTS);
+
+ gc->n_clip_rects = n;
+ if (n > 0)
{
if (gc->clip_region == NULL)
gc->clip_region = NewRgn ();
}
}
#if defined (MAC_OSX) && USE_ATSUI
- gc->n_clip_rects = n;
-
for (i = 0; i < n; i++)
{
Rect *rect = rectangles + i;
Display *display;
GC gc;
{
- mac_set_clip_rectangles (display, gc, NULL, 0);
+ gc->n_clip_rects = 0;
}
#endif
}
-/* x_sync is a no-op on Mac. */
-void
-x_sync (f)
- void *f;
-{
-}
-
-
/* Flush display of frame F, or of all frames if F is null. */
static void
{
#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
XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
face->foreground);
- XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- f->output_data.mac->normal_gc, x, y0, x, y1);
+ 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).
y -= width;
BLOCK_INPUT;
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- 0, y, width, height, 0);
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- FRAME_PIXEL_WIDTH (f) - width, y,
- width, height, 0);
+ mac_clear_area (f, 0, y, width, height);
+ mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
UNBLOCK_INPUT;
}
}
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
Display *display = FRAME_MAC_DISPLAY (f);
- WindowPtr window = FRAME_MAC_WINDOW (f);
- GC gc = f->output_data.mac->normal_gc;
struct face *face = p->face;
int rowY;
int oldVH = row->visible_height;
row->visible_height = p->h;
row->y -= rowY - p->y;
- x_clip_to_row (w, row, -1, gc);
+ x_clip_to_row (w, row, -1, face->gc);
row->y = oldY;
row->visible_height = oldVH;
}
else
- x_clip_to_row (w, row, -1, gc);
+ x_clip_to_row (w, row, -1, face->gc);
if (p->bx >= 0 && !p->overlay_p)
{
XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
#endif
- mac_erase_rectangle (window, face->gc, p->bx, p->by, p->nx, p->ny);
+ mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
#if 0 /* MAC_TODO: stipple */
if (!face->stipple)
#endif
}
- if (p->which)
+ if (p->which
+#if USE_CG_DRAWING
+ && p->which < max_fringe_bmp
+#endif
+ )
{
- unsigned short *bits = p->bits + p->dh;
XGCValues gcv;
XGetGCValues (display, face->gc, GCForeground, &gcv);
? (p->overlay_p ? face->background
: f->output_data.mac->cursor_pixel)
: face->foreground));
- mac_draw_bitmap (display, window, face->gc, p->x, p->y,
- p->wd, p->h, bits, p->overlay_p);
+#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, p->overlay_p);
+#else
+ mac_draw_bitmap (f, face->gc, p->x, p->y,
+ p->wd, p->h, p->bits + p->dh, p->overlay_p);
+#endif
XSetForeground (display, face->gc, gcv.foreground);
}
- mac_reset_clip_rectangles (display, gc);
+ mac_reset_clip_rectangles (display, 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];
+ 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);
+ }
+}
+
+static void
+mac_destroy_fringe_bitmap (which)
+ int which;
+{
+ if (which >= max_fringe_bmp)
+ return;
+
+ if (fringe_bmp[which])
+ CGImageRelease (fringe_bmp[which]);
+ fringe_bmp[which] = 0;
+}
+#endif
\f
/* This is called when starting Emacs and when restarting after
#if USE_ATSUI
if (font->mac_style)
{
- 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)
+ XCharStructRow **row = font->bounds.rows + char2b->byte1;
+
+ if (*row == NULL)
{
- pcm = (font->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));
+ *row = xmalloc (sizeof (XCharStructRow));
+ bzero (*row, sizeof (XCharStructRow));
}
-
- if (pcm && !pcm->valid_p)
+ pcm = (*row)->per_char + char2b->byte2;
+ if (!XCHARSTRUCTROW_CHAR_VALID_P (*row, char2b->byte2))
{
- OSErr err;
- ATSUTextLayout text_layout;
- UniChar c;
- int char_width;
- ATSTrapezoid glyph_bounds;
- Rect char_bounds;
-
- c = (char2b->byte1 << 8) + char2b->byte2;
BLOCK_INPUT;
- err = atsu_get_text_layout_with_text_ptr (&c, 1,
- font->mac_style,
- &text_layout);
- if (err == noErr)
- err = ATSUMeasureTextImage (text_layout,
- kATSUFromTextBeginning, kATSUToTextEnd,
- 0, 0, &char_bounds);
-
- if (err == noErr)
- err = ATSUGetGlyphBounds (text_layout, 0, 0,
- kATSUFromTextBeginning, kATSUToTextEnd,
- kATSUseFractionalOrigins, 1,
- &glyph_bounds, NULL);
+ mac_query_char_extents (font->mac_style,
+ (char2b->byte1 << 8) + char2b->byte2,
+ NULL, NULL, pcm, NULL);
UNBLOCK_INPUT;
- if (err != noErr)
- pcm = NULL;
- else
- {
- xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
- == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
-
- char_width = Fix2Long (glyph_bounds.upperRight.x
- - glyph_bounds.upperLeft.x);
- STORE_XCHARSTRUCT (*pcm, char_width, char_bounds);
- }
+ XCHARSTRUCTROW_SET_CHAR_VALID (*row, char2b->byte2);
}
}
else
{
#endif
- if (font->per_char != NULL)
+ if (font->bounds.per_char != NULL)
{
if (font->min_byte1 == 0 && font->max_byte1 == 0)
{
if (char2b->byte1 == 0
&& char2b->byte2 >= font->min_char_or_byte2
&& char2b->byte2 <= font->max_char_or_byte2)
- pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
+ pcm = font->bounds.per_char
+ + (char2b->byte2 - font->min_char_or_byte2);
}
else
{
&& char2b->byte2 >= font->min_char_or_byte2
&& char2b->byte2 <= font->max_char_or_byte2)
{
- pcm = (font->per_char
+ 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));
#endif
return ((pcm == NULL
- || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
+ || (pcm->width == 0
+#if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
+ && (pcm->rbearing - pcm->lbearing) == 0
+#endif
+ ))
? NULL : pcm);
}
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_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
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,
mac_compute_glyph_string_overhangs (s)
struct glyph_string *s;
{
- if (s->cmp == NULL
- && s->first_glyph->type == CHAR_GLYPH)
- {
- Rect r;
- MacFontStruct *font = s->font;
+ if (!(s->cmp == NULL
+ && s->first_glyph->type == CHAR_GLYPH))
+ return;
+ if (!s->two_byte_p
#if USE_ATSUI
- if (font->mac_style)
- {
- OSErr err;
- ATSUTextLayout text_layout;
- UniChar *buf;
- int i;
+ || s->font->mac_style
+#endif
+ )
+ {
+ XCharStruct cs;
- SetRect (&r, 0, 0, 0, 0);
- buf = xmalloc (sizeof (UniChar) * s->nchars);
- if (buf)
- {
- for (i = 0; i < s->nchars; i++)
- buf[i] = (s->char2b[i].byte1 << 8) + s->char2b[i].byte2;
+ 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;
- err = atsu_get_text_layout_with_text_ptr (buf, s->nchars,
- font->mac_style,
- &text_layout);
- if (err == noErr)
- err = ATSUMeasureTextImage (text_layout,
- kATSUFromTextBeginning,
- kATSUToTextEnd,
- 0, 0, &r);
- xfree (buf);
- }
- }
- else
- {
-#endif
TextFont (font->mac_fontnum);
TextSize (font->mac_fontsize);
TextFace (font->mac_fontface);
- if (s->two_byte_p)
- QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
- else
- {
- int i;
- char *buf = xmalloc (s->nchars);
-
- if (buf == NULL)
- SetRect (&r, 0, 0, 0, 0);
- else
- {
- for (i = 0; i < s->nchars; ++i)
- buf[i] = s->char2b[i].byte2;
- QDTextBounds (s->nchars, buf, &r);
- xfree (buf);
- }
- }
-#if USE_ATSUI
- }
-#endif
+ 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;
struct glyph_string *s;
int x, y, w, h;
{
- mac_erase_rectangle (s->window, s->gc, x, y, w, h);
+ mac_erase_rectangle (s->f, s->gc, x, y, w, h);
}
-/* We prefer not to use XDrawImageString (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. */
-
/* 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
}
else
#endif
-#if defined (MAC_OS8) && !USE_ATSUI
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)
-#endif
{
x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
s->background_width,
x_draw_glyph_string_foreground (s)
struct glyph_string *s;
{
- int i, x;
+ 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. */
for (i = 0; i < s->nchars; ++i)
{
struct glyph *g = s->first_glyph + i;
- mac_draw_rectangle (s->display, s->window,
- s->gc, x, s->y, g->pixel_width - 1,
- s->height - 1);
+ mac_draw_rectangle (s->f, s->gc, x, s->y,
+ g->pixel_width - 1, s->height - 1);
x += g->pixel_width;
}
}
for (i = 0; i < s->nchars; ++i)
char1b[i] = s->char2b[i].byte2;
-#if defined (MAC_OS8) && !USE_ATSUI
/* Draw text with XDrawString if background has already been
filled. Otherwise, use XDrawImageString. (Note that
XDrawImageString is usually faster than XDrawString.) Always
no chance that characters under a box cursor are invisible. */
if (s->for_overlaps
|| (s->background_filled_p && s->hl != DRAW_CURSOR))
-#endif
- {
- /* Draw characters with 16-bit or 8-bit functions. */
- if (s->two_byte_p
+ 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
+ || GC_FONT (s->gc)->mac_style
#endif
- )
- XDrawString16 (s->display, s->window, s->gc, x,
- s->ybase - boff, s->char2b, s->nchars);
- else
- XDrawString (s->display, s->window, s->gc, x,
- s->ybase - boff, char1b, s->nchars);
- }
-#if defined (MAC_OS8) && !USE_ATSUI
- else
- {
- if (s->two_byte_p)
- XDrawImageString16 (s->display, s->window, s->gc, x,
- s->ybase - boff, s->char2b, s->nchars);
- else
- XDrawImageString (s->display, s->window, s->gc, x,
- s->ybase - boff, char1b, s->nchars);
- }
+ )
+#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))
+ ;
+ else
#endif
+ mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
+ s->char2b, s->nchars, bg_width);
+ else
+ mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
+ char1b, s->nchars, bg_width);
}
}
if (s->font_not_found_p)
{
if (s->gidx == 0)
- mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
- s->width - 1, s->height - 1);
+ 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)
- XDrawString16 (s->display, s->window, s->gc,
- x + s->cmp->offsets[s->gidx * 2],
- s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
- s->char2b + i, 1);
+ mac_draw_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);
}
}
Rect *clip_rect;
{
Display *dpy = FRAME_MAC_DISPLAY (f);
- Window window = FRAME_MAC_WINDOW (f);
int i;
GC gc;
/* Top. */
if (top_p)
for (i = 0; i < width; ++i)
- XDrawLine (dpy, window, gc,
- left_x + i * left_p, top_y + i,
- right_x - i * right_p, top_y + i);
+ mac_draw_line (f, gc,
+ left_x + i * left_p, top_y + i,
+ right_x - i * right_p, top_y + i);
/* Left. */
if (left_p)
for (i = 0; i < width; ++i)
- XDrawLine (dpy, window, gc,
- left_x + i, top_y + i, left_x + i, bottom_y - i);
+ mac_draw_line (f, gc,
+ left_x + i, top_y + i, left_x + i, bottom_y - i);
mac_reset_clip_rectangles (dpy, gc);
if (raised_p)
/* Bottom. */
if (bot_p)
for (i = 0; i < width; ++i)
- XDrawLine (dpy, window, gc,
- left_x + i * left_p, bottom_y - i,
- right_x - i * right_p, bottom_y - i);
+ mac_draw_line (f, gc,
+ left_x + i * left_p, bottom_y - i,
+ right_x - i * right_p, bottom_y - i);
/* Right. */
if (right_p)
for (i = 0; i < width; ++i)
- XDrawLine (dpy, window, gc,
- right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
+ mac_draw_line (f, gc,
+ right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
mac_reset_clip_rectangles (dpy, gc);
}
mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
/* Top. */
- XFillRectangle (s->display, s->window, s->gc,
- left_x, top_y, right_x - left_x + 1, width);
+ mac_fill_rectangle (s->f, s->gc, left_x, top_y,
+ right_x - left_x + 1, width);
/* Left. */
if (left_p)
- XFillRectangle (s->display, s->window, s->gc,
- left_x, top_y, width, bottom_y - top_y + 1);
+ mac_fill_rectangle (s->f, s->gc, left_x, top_y,
+ width, bottom_y - top_y + 1);
/* Bottom. */
- XFillRectangle (s->display, s->window, s->gc,
- left_x, bottom_y - width + 1, right_x - left_x + 1, width);
+ mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
+ right_x - left_x + 1, width);
/* Right. */
if (right_p)
- XFillRectangle (s->display, s->window, s->gc,
- right_x - width + 1, top_y, width, bottom_y - top_y + 1);
+ 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->display, s->gc);
{
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)
- mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
- s->window, s->gc, s->slice.x, s->slice.y,
+#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
{
- mac_copy_area (s->display, s->img->pixmap,
- s->window, s->gc, s->slice.x, s->slice.y,
+#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
{
int r = s->img->relief;
if (r < 0) r = -r;
- mac_draw_rectangle (s->display, s->window, s->gc,
- x - r, y - 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->display, s->window, s->gc, x, y,
+ mac_draw_rectangle (s->f, s->gc, x, y,
s->slice.width - 1, s->slice.height - 1);
}
}
-#if 0 /* TODO: figure out if we need to do this on Mac. */
-/* Draw the foreground of image glyph string S to PIXMAP. */
-
-static void
-x_draw_image_foreground_1 (s, pixmap)
- struct glyph_string *s;
- Pixmap pixmap;
-{
- int x = 0;
- int y = s->ybase - s->y - 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 += abs (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)
- {
- if (s->img->mask)
- mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
- s->img->mask, pixmap, s->gc,
- s->slice.x, s->slice.y,
- s->slice.width, s->slice.height,
- x, y);
- else
- {
- mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
- s->slice.x, s->slice.y,
- s->slice.width, s->slice.height,
- x, y);
-
- /* 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->display, s->window, 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_to_pixmap (s->display, pixmap, s->gc, x, y,
- s->slice.width - 1, s->slice.height - 1);
-}
-#endif
-
-
/* Draw part of the background of glyph string S. X, Y, W, and H
give the rectangle to draw. */
int box_line_hwidth = abs (s->face->box_line_width);
int box_line_vwidth = max (s->face->box_line_width, 0);
int height;
- Pixmap pixmap = 0;
height = s->height - 2 * box_line_vwidth;
if (s->slice.y == 0)
y += box_line_vwidth;
-#if 0 /* TODO: figure out if we need to do this on Mac. */
- if (s->img->mask)
- {
- /* Create a pixmap as large as the glyph string. Fill it
- with the background color. Copy the image to it, using
- its mask. Copy the temporary pixmap to the display. */
- int depth = one_mac_display_info.n_planes;
-
- /* Create a pixmap as large as the glyph string. */
- pixmap = XCreatePixmap (s->display, s->window,
- s->background_width,
- s->height, depth);
-
- /* Fill the pixmap with the background color/stipple. */
-#if 0 /* TODO: stipple */
- if (s->stippled_p)
- {
- /* Fill background with a stipple pattern. */
- XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
- XFillRectangle (s->display, pixmap, s->gc,
- 0, 0, s->background_width, s->height);
- XSetFillStyle (s->display, s->gc, FillSolid);
- }
- else
-#endif
- {
- XGCValues xgcv;
- XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
- &xgcv);
- XSetForeground (s->display, s->gc, xgcv.background);
- mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
- 0, 0, s->background_width,
- s->height);
- XSetForeground (s->display, s->gc, xgcv.foreground);
- }
- }
- else
-#endif
- x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+ x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
s->background_filled_p = 1;
}
/* Draw the foreground. */
-#if 0 /* TODO: figure out if we need to do this on Mac. */
- if (pixmap != 0)
- {
- x_draw_image_foreground_1 (s, pixmap);
- x_set_glyph_string_clipping (s);
- mac_copy_area (s->display, pixmap, s->window, s->gc,
- 0, 0, s->background_width, s->height, s->x, s->y);
- XFreePixmap (s->display, pixmap);
- }
- else
-#endif
- x_draw_image_foreground (s);
+ x_draw_image_foreground (s);
/* If we must draw a relief around the image, do it. */
if (s->img->relief
}
else
#endif /* MAC_TODO */
- mac_erase_rectangle (s->window, gc, x, y, w, h);
+ mac_erase_rectangle (s->f, gc, x, y, w, h);
}
}
else if (!s->background_filled_p)
unsigned long dy = s->height - h;
if (s->face->underline_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
+ 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->underline_color);
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
+ mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+ s->width, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
}
unsigned long dy = 0, h = 1;
if (s->face->overline_color_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
+ 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->overline_color);
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
+ mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+ s->width, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
}
unsigned long dy = (s->height - h) / 2;
if (s->face->strike_through_color_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
+ 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);
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
+ mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+ s->width, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
}
struct frame *f;
int x, y, width, height, shift_by;
{
- mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- f->output_data.mac->normal_gc,
+ mac_scroll_area (f, f->output_data.mac->normal_gc,
x, y, width, height,
x + shift_by, y);
}
/* We don't set the output cursor here because there will always
follow an explicit cursor_to. */
BLOCK_INPUT;
- XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+ 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. */
/* If window is tall, flash top and bottom line. */
if (height > 3 * FRAME_LINE_HEIGHT (f))
{
- mac_invert_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- flash_left,
+ 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 (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- flash_left,
+ 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 (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+ mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
x_flush (f);
/* If window is tall, flash top and bottom line. */
if (height > 3 * FRAME_LINE_HEIGHT (f))
{
- mac_invert_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- flash_left,
+ 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 (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- flash_left,
+ 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 (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+ mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
x_flush (f);
updated_window = w;
x_clear_cursor (w);
- mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- f->output_data.mac->normal_gc,
- x, from_y,
- width, height,
- x, to_y);
+ mac_scroll_area (f, f->output_data.mac->normal_gc,
+ x, from_y,
+ width, height,
+ x, to_y);
UNBLOCK_INPUT;
}
\f
-/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
-
-#if 0 /* MAC_TODO */
-/* Initialize mode_switch_bit and modifier_meaning. */
-static void
-x_find_modifier_meanings (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- int min_code, max_code;
- KeySym *syms;
- int syms_per_code;
- XModifierKeymap *mods;
-
- dpyinfo->meta_mod_mask = 0;
- dpyinfo->shift_lock_mask = 0;
- dpyinfo->alt_mod_mask = 0;
- dpyinfo->super_mod_mask = 0;
- dpyinfo->hyper_mod_mask = 0;
-
-#ifdef HAVE_X11R4
- XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
-#else
- min_code = dpyinfo->display->min_keycode;
- max_code = dpyinfo->display->max_keycode;
-#endif
-
- syms = XGetKeyboardMapping (dpyinfo->display,
- min_code, max_code - min_code + 1,
- &syms_per_code);
- mods = XGetModifierMapping (dpyinfo->display);
-
- /* Scan the modifier table to see which modifier bits the Meta and
- Alt keysyms are on. */
- {
- int row, col; /* The row and column in the modifier table. */
-
- for (row = 3; row < 8; row++)
- for (col = 0; col < mods->max_keypermod; col++)
- {
- KeyCode code
- = mods->modifiermap[(row * mods->max_keypermod) + col];
-
- /* Zeroes are used for filler. Skip them. */
- if (code == 0)
- continue;
-
- /* Are any of this keycode's keysyms a meta key? */
- {
- int code_col;
-
- for (code_col = 0; code_col < syms_per_code; code_col++)
- {
- int sym = syms[((code - min_code) * syms_per_code) + code_col];
-
- switch (sym)
- {
- case XK_Meta_L:
- case XK_Meta_R:
- dpyinfo->meta_mod_mask |= (1 << row);
- break;
-
- case XK_Alt_L:
- case XK_Alt_R:
- dpyinfo->alt_mod_mask |= (1 << row);
- break;
-
- case XK_Hyper_L:
- case XK_Hyper_R:
- dpyinfo->hyper_mod_mask |= (1 << row);
- break;
-
- case XK_Super_L:
- case XK_Super_R:
- dpyinfo->super_mod_mask |= (1 << row);
- break;
-
- case XK_Shift_Lock:
- /* Ignore this if it's not on the lock modifier. */
- if ((1 << row) == LockMask)
- dpyinfo->shift_lock_mask = LockMask;
- break;
- }
- }
- }
- }
- }
-
- /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
- if (! dpyinfo->meta_mod_mask)
- {
- dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
- dpyinfo->alt_mod_mask = 0;
- }
-
- /* If some keys are both alt and meta,
- make them just meta, not alt. */
- if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
- {
- dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
- }
-
- XFree ((char *) syms);
- XFreeModifiermap (mods);
-}
-
-#endif /* MAC_TODO */
-
-/* Convert between the modifier bits X uses and the modifier bits
- Emacs uses. */
-
-static unsigned int
-x_mac_to_emacs_modifiers (dpyinfo, state)
- struct x_display_info *dpyinfo;
- unsigned short state;
-{
- return (((state & shiftKey) ? shift_modifier : 0)
- | ((state & controlKey) ? ctrl_modifier : 0)
- | ((state & cmdKey) ? meta_modifier : 0)
- | ((state & optionKey) ? alt_modifier : 0));
-}
-
-#if 0 /* MAC_TODO */
-static unsigned short
-x_emacs_to_x_modifiers (dpyinfo, state)
- struct x_display_info *dpyinfo;
- unsigned int state;
-{
- return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
- | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
- | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
- | ((state & shift_modifier) ? ShiftMask : 0)
- | ((state & ctrl_modifier) ? ControlMask : 0)
- | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
-}
-#endif /* MAC_TODO */
-
/* Convert a keysym to its name. */
char *
static Point last_mouse_motion_position;
static Lisp_Object last_mouse_motion_frame;
-static void
+static int
note_mouse_movement (frame, pos)
FRAME_PTR frame;
Point *pos;
rif->define_frame_cursor (frame,
frame->output_data.mac->nontext_cursor);
}
+ return 1;
}
/* Has the mouse moved off the glyph it was on at the last sighting? */
- else if (pos->h < last_mouse_glyph.left
- || pos->h >= last_mouse_glyph.right
- || pos->v < last_mouse_glyph.top
- || pos->v >= last_mouse_glyph.bottom)
+ 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;
}
\f
Mouse Face
************************************************************************/
-static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
-
-
/* MAC TODO: This should be called from somewhere (or removed) ++KFS */
static void
}
-/* Try to determine frame pixel position and size of the glyph under
- frame pixel coordinates X/Y on frame F . Return the position and
- size in *RECT. Value is non-zero if we could compute these
- values. */
-
-static int
-glyph_rect (f, x, y, rect)
- struct frame *f;
- int x, y;
- Rect *rect;
-{
- Lisp_Object window;
-
- window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
-
- if (!NILP (window))
- {
- struct window *w = XWINDOW (window);
- struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
- struct glyph_row *end = r + w->current_matrix->nrows - 1;
-
- for (; r < end && r->enabled_p; ++r)
- if (r->y <= y && r->y + r->height > y)
- {
- /* Found the row at y. */
- struct glyph *g = r->glyphs[TEXT_AREA];
- struct glyph *end = g + r->used[TEXT_AREA];
- int gx;
-
- rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
- rect->bottom = rect->top + r->height;
-
- if (x < r->x)
- {
- /* x is to the left of the first glyph in the row. */
- /* Shouldn't this be a pixel value?
- WINDOW_LEFT_EDGE_X (w) seems to be the right value.
- ++KFS */
- rect->left = WINDOW_LEFT_EDGE_COL (w);
- rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
- return 1;
- }
-
- for (gx = r->x; g < end; gx += g->pixel_width, ++g)
- if (gx <= x && gx + g->pixel_width > x)
- {
- /* x is on a glyph. */
- rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
- rect->right = rect->left + g->pixel_width;
- return 1;
- }
-
- /* x is to the right of the last glyph in the row. */
- rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
- /* Shouldn't this be a pixel value?
- WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
- ++KFS */
- rect->right = WINDOW_RIGHT_EDGE_COL (w);
- return 1;
- }
- }
-
- /* The y is not on any row. */
- return 0;
-}
-
-/* MAC TODO: This should be called from somewhere (or removed) ++KFS */
-
-/* Record the position of the mouse in last_mouse_glyph. */
-static void
-remember_mouse_glyph (f1, gx, gy)
- struct frame * f1;
- int gx, gy;
-{
- if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
- {
- int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
- int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
-
- /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
- round down even for negative values. */
- if (gx < 0)
- gx -= width - 1;
- if (gy < 0)
- gy -= height - 1;
-#if 0
- /* This was the original code from XTmouse_position, but it seems
- to give the position of the glyph diagonally next to the one
- the mouse is over. */
- gx = (gx + width - 1) / width * width;
- gy = (gy + height - 1) / height * height;
-#else
- gx = gx / width * width;
- gy = gy / height * height;
-#endif
-
- last_mouse_glyph.left = gx;
- last_mouse_glyph.top = gy;
- last_mouse_glyph.right = gx + width;
- last_mouse_glyph.bottom = gy + height;
- }
-}
-
-
static struct frame *
mac_focus_frame (dpyinfo)
struct mac_display_info *dpyinfo;
/* Return the current position of the mouse.
- *fp should be a frame which indicates which display to ask about.
+ *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
+ 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
+ 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
+ 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.
Lisp_Object *x, *y;
unsigned long *time;
{
- Point mouse_pos;
- int ignore1, ignore2;
- struct frame *f = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
- WindowPtr wp = FRAME_MAC_WINDOW (f);
- Lisp_Object frame, tail;
+ FRAME_PTR f1;
BLOCK_INPUT;
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;
+ XFRAME (frame)->mouse_moved = 0;
last_mouse_scroll_bar = Qnil;
- SetPortWindowPort (wp);
-
- GetMouse (&mouse_pos);
-
- pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
- &last_mouse_glyph, insist);
+ 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));
- *bar_window = Qnil;
- *part = scroll_bar_handle;
- *fp = f;
- XSETINT (*x, mouse_pos.h);
- XSETINT (*y, mouse_pos.v);
- *time = last_mouse_movement_time;
+ 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;
+
+ SetPortWindowPort (FRAME_MAC_WINDOW (f1));
+ GetMouse (&mouse_pos);
+ 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;
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 OSErr get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
- Rect *));
+static OSStatus get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
+ Rect *));
static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
ControlPartCode,
struct input_event *));
bufp->modifiers = 0;
}
-static OSErr
+static OSStatus
get_control_part_bounds (ch, part_code, rect)
ControlHandle ch;
ControlPartCode part_code;
int portion, position, whole;
{
ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
-
int value, viewsize, maximum;
- if (whole == 0 || XINT (bar->track_height) == 0)
+ if (XINT (bar->track_height) == 0)
+ return;
+
+ if (whole == 0)
value = 0, viewsize = 1, maximum = 0;
else
{
BLOCK_INPUT;
- SetControl32BitMinimum (ch, 0);
- SetControl32BitMaximum (ch, maximum);
- SetControl32BitValue (ch, value);
- SetControlViewSize (ch, viewsize);
+ 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;
}
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", width < disp_height,
+ ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
+#if 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,
BLOCK_INPUT;
+#if USE_CG_DRAWING
+ mac_prepare_for_quickdraw (f);
+#endif
/* Destroy the Mac scroll bar control */
DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
/* 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;
if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
sb_left++;
+#endif
/* Does the scroll bar exist yet? */
if (NILP (w->vertical_scroll_bar))
{
BLOCK_INPUT;
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- left, top, width, height, 0);
+ 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);
{
/* Since toolkit scroll bars are smaller than the space reserved
for them on the frame, we have to clear "under" them. */
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- left, top, width, height, 0);
+ mac_clear_area (f, left, top, width, height);
-#if 0
- if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- sb_left - 1, top, 1, height, 0);
+#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);
#ifdef USE_TOOLKIT_SCROLL_BARS
if (NILP (bar->track_top))
{
- ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
- Rect r0, r1;
+ if (sb_width >= disp_height)
+ {
+ XSETINT (bar->track_top, 0);
+ XSETINT (bar->track_height, 0);
+ }
+ else
+ {
+ ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+ Rect r0, r1;
- BLOCK_INPUT;
+ BLOCK_INPUT;
- SetControl32BitMinimum (ch, 0);
- SetControl32BitMaximum (ch, 1);
- SetControlViewSize (ch, 1);
+ SetControl32BitMinimum (ch, 0);
+ SetControl32BitMaximum (ch, 1);
+ 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 top. */
+ SetControl32BitValue (ch, 0);
+ get_control_part_bounds (ch, kControlIndicatorPart, &r0);
- /* Move the scroll bar thumb to the bottom. */
- SetControl32BitValue (ch, 1);
- get_control_part_bounds (ch, kControlIndicatorPart, &r1);
+ /* Move the scroll bar thumb to the bottom. */
+ SetControl32BitValue (ch, 1);
+ 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);
+ UnionRect (&r0, &r1, &r0);
+ XSETINT (bar->track_top, r0.top);
+ XSETINT (bar->track_height, r0.bottom - r0.top);
- UNBLOCK_INPUT;
+ /* 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);
/* Set clipping, draw the rectangle, and reset clipping again. */
x_clip_to_row (w, row, TEXT_AREA, gc);
- mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
+ mac_draw_rectangle (f, gc, x, y, wd, h - 1);
mac_reset_clip_rectangles (dpy, gc);
}
x_clip_to_row (w, row, TEXT_AREA, gc);
if (kind == BAR_CURSOR)
- XFillRectangle (dpy, window, 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);
+ 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
- XFillRectangle (dpy, window, 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_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 (dpy, gc);
}
struct frame *f;
Cursor cursor;
{
- SetThemeCursor (cursor);
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+ if (dpyinfo->x_focus_frame == f)
+ SetThemeCursor (cursor);
}
struct frame *f;
int x, y, width, height;
{
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- x, y, width, height, 0);
+ mac_clear_area (f, x, y, width, height);
}
SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
#if TARGET_API_MAC_CARBON
if (f->output_data.mac->hourglass_control)
- MoveControl (f->output_data.mac->hourglass_control,
- pixelwidth - HOURGLASS_WIDTH, 0);
+ {
+#if USE_CG_DRAWING
+ mac_prepare_for_quickdraw (f);
+#endif
+ MoveControl (f->output_data.mac->hourglass_control,
+ pixelwidth - HOURGLASS_WIDTH, 0);
+ }
#endif
/* Now, strictly speaking, we can't be sure that this is accurate,
if (f->async_visible)
{
BLOCK_INPUT;
- SelectWindow (FRAME_MAC_WINDOW (f));
+ BringToFront (FRAME_MAC_WINDOW (f));
UNBLOCK_INPUT;
}
}
if (f->async_visible)
{
BLOCK_INPUT;
- SendBehind (FRAME_MAC_WINDOW (f), nil);
+ SendBehind (FRAME_MAC_WINDOW (f), NULL);
UNBLOCK_INPUT;
}
}
struct input_event buf;
if (IsWindowVisible (wp))
- if (IsWindowCollapsed (wp))
- iconified = 1;
- else
- visible = 1;
+ {
+ if (IsWindowCollapsed (wp))
+ iconified = 1;
+ else
+ visible = 1;
+ }
if (!f->async_visible && visible)
{
x_make_frame_visible (f)
struct frame *f;
{
- Lisp_Object type;
- int original_top, original_left;
-
BLOCK_INPUT;
if (! FRAME_VISIBLE_P (f))
before the window gets really visible. */
if (! FRAME_ICONIFIED_P (f)
&& ! f->output_data.mac->asked_for_visible)
+ {
#if TARGET_API_MAC_CARBON
- if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
- {
- struct frame *sf = SELECTED_FRAME ();
- if (!FRAME_MAC_P (sf))
- RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
- kWindowCenterOnMainScreen);
- else
- RepositionWindow (FRAME_MAC_WINDOW (f),
- FRAME_MAC_WINDOW (sf),
+ if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
+ {
+ struct frame *sf = SELECTED_FRAME ();
+ if (!FRAME_MAC_P (sf))
+ RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
+ kWindowCenterOnMainScreen);
+ else
+ RepositionWindow (FRAME_MAC_WINDOW (f),
+ FRAME_MAC_WINDOW (sf),
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- kWindowCascadeStartAtParentWindowScreen
+ kWindowCascadeStartAtParentWindowScreen
#else
- kWindowCascadeOnParentWindowScreen
+ kWindowCascadeOnParentWindowScreen
#endif
- );
- x_real_positions (f, &f->left_pos, &f->top_pos);
- }
- else
+ );
+ x_real_positions (f, &f->left_pos, &f->top_pos);
+ }
+ else
#endif
- x_set_offset (f, f->left_pos, f->top_pos, 0);
+ x_set_offset (f, f->left_pos, f->top_pos, 0);
+ }
f->output_data.mac->asked_for_visible = 1;
- SelectWindow (FRAME_MAC_WINDOW (f));
CollapseWindow (FRAME_MAC_WINDOW (f), false);
ShowWindow (FRAME_MAC_WINDOW (f));
}
struct xlfdpat_block *blk;
pat = xmalloc (sizeof (struct xlfdpat));
- if (pat == NULL)
- goto error;
-
pat->buf = xmalloc (strlen (pattern) + 1);
- if (pat->buf == NULL)
- goto error;
/* Normalize the pattern string and store it to `pat->buf'. */
nblocks = 0;
else
{
if (last_char == '?')
- if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
- /* ...*??* -> ...*?? */
- continue;
- else
- /* ...a??* -> ...a*?? */
- {
- *anychar_head++ = '*';
- c = '?';
- }
+ {
+ if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
+ /* ...*??* -> ...*?? */
+ continue;
+ else
+ /* ...a??* -> ...a*?? */
+ {
+ *anychar_head++ = '*';
+ c = '?';
+ }
+ }
nblocks++;
}
else if (c == '?')
}
pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
- if (pat->blocks == NULL)
- goto error;
/* Divide the normalized pattern into blocks. */
p = pat->buf;
sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
- size, size * 10, size ? 75 : 0, size ? 75 : 0, size * 10, charset);
+ 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);
xrealloc (font_name_table,
font_name_table_size * sizeof (char *));
}
-
- font_name_table[font_name_count++] = font_name;
+
+ font_name_table[font_name_count++] = font_name;
+}
+
+static void
+add_mac_font_name (name, size, style, charset)
+ char *name;
+ int size;
+ Style style;
+ 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));
+ }
}
/* Sets up the table font_name_table to contain the list of all fonts
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)))
{
OSErr err;
+ struct Lisp_Hash_Table *h;
+ unsigned hash_code;
ItemCount nfonts, i;
ATSUFontID *font_ids = NULL;
- Ptr name, prev_name = NULL;
+ Ptr name;
ByteCount name_len;
+ Lisp_Object family;
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);
- if (font_ids)
- err = ATSUGetFontIDs (font_ids, nfonts, NULL);
+ {
+ font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
+ err = ATSUGetFontIDs (font_ids, nfonts, NULL);
+ }
if (err == noErr)
for (i = 0; i < nfonts; i++)
{
if (err != noErr)
continue;
name = xmalloc (name_len + 1);
- if (name == NULL)
- continue;
name[name_len] = '\0';
err = ATSUFindFontName (font_ids[i], kFontFamilyName,
kFontMacintoshPlatform, kFontNoScript,
kFontNoLanguage, name_len, name,
NULL, NULL);
if (err == noErr)
- decode_mac_font_name (name, name_len + 1, Qnil);
- if (err == noErr
- && *name != '.'
- && (prev_name == NULL
- || strcmp (name, prev_name) != 0))
{
- static char *cs = "iso10646-1";
-
- add_font_name_table_entry (mac_to_x_fontname (name, 0,
- normal, cs));
- add_font_name_table_entry (mac_to_x_fontname (name, 0,
- italic, cs));
- add_font_name_table_entry (mac_to_x_fontname (name, 0,
- bold, cs));
- add_font_name_table_entry (mac_to_x_fontname (name, 0,
- italic | bold, cs));
- Fputhash (make_unibyte_string (name, name_len),
- long_to_cons (font_ids[i]), atsu_font_id_hash);
- xfree (prev_name);
- prev_name = name;
+ decode_mac_font_name (name, name_len + 1, Qnil);
+ family = make_unibyte_string (name, name_len);
+ if (*name != '.'
+ && hash_lookup (h, family, &hash_code) < 0)
+ {
+ add_mac_font_name (name, 0, normal, "iso10646-1");
+ hash_put (h, family, long_to_cons (font_ids[i]),
+ hash_code);
+ }
}
- else
- xfree (name);
+ xfree (name);
}
- if (prev_name)
- xfree (prev_name);
if (font_ids)
xfree (font_ids);
}
FMFontSize size;
TextEncoding encoding;
TextEncodingBase sc;
- Lisp_Object text_encoding_info;
+ Lisp_Object text_encoding_info, family;
if (FMGetFontFamilyName (ff, name) != noErr)
- break;
+ continue;
p2cstr (name);
if (*name == '.')
continue;
if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
- break;
+ continue;
sc = GetTextEncodingBase (encoding);
text_encoding_info = assq_no_quit (make_number (sc),
text_encoding_info_alist);
text_encoding_info_alist);
decode_mac_font_name (name, sizeof (name),
XCAR (XCDR (text_encoding_info)));
- fm_font_family_alist = Fcons (Fcons (build_string (name),
- make_number (ff)),
+ 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)
- break;
+ continue;
while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
== noErr)
if (size > 0 || style == normal)
for (; !NILP (rest); rest = XCDR (rest))
- {
- char *cs = SDATA (XCAR (rest));
-
- if (size == 0)
- {
- add_font_name_table_entry (mac_to_x_fontname (name, size,
- style, cs));
- add_font_name_table_entry (mac_to_x_fontname (name, size,
- italic, cs));
- add_font_name_table_entry (mac_to_x_fontname (name, size,
- bold, cs));
- add_font_name_table_entry (mac_to_x_fontname (name, size,
- italic | bold,
- cs));
- }
- else
- {
- add_font_name_table_entry (mac_to_x_fontname (name, size,
- style, cs));
- }
- }
+ add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
}
}
Str255 name;
struct FontAssoc *fat;
struct AsscEntry *assc_entry;
- Lisp_Object text_encoding_info_alist, text_encoding_info;
+ Lisp_Object text_encoding_info_alist, text_encoding_info, family;
struct gcpro gcpro1;
GetPort (&port); /* save the current font number used */
GetResInfo (font_handle, &id, &type, name);
GetFNum (name, &fontnum);
p2cstr (name);
- if (fontnum == 0)
+ if (fontnum == 0 || *name == '.')
continue;
TextFont (fontnum);
text_encoding_info_alist);
decode_mac_font_name (name, sizeof (name),
XCAR (XCDR (text_encoding_info)));
- fm_font_family_alist = Fcons (Fcons (build_string (name),
- make_number (fontnum)),
+ 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
{
Lisp_Object rest = XCDR (XCDR (text_encoding_info));
for (; !NILP (rest); rest = XCDR (rest))
- {
- char *cs = SDATA (XCAR (rest));
-
- add_font_name_table_entry (mac_to_x_fontname (name,
- assc_entry->fontSize,
- assc_entry->fontStyle,
- cs));
- }
+ add_mac_font_name (name, assc_entry->fontSize,
+ assc_entry->fontStyle,
+ SDATA (XCAR (rest)));
}
}
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)
+ if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
break;
}
else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
int former_len = ptr - font_name_table[i];
scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
- if (scaled == NULL)
- continue;
memcpy (scaled, font_name_table[i], former_len);
sprintf (scaled + former_len,
- "-%d-%d-75-75-m-%d-%s",
+ "-%d-%d-72-72-m-%d-%s",
scl_val[XLFD_SCL_PIXEL_SIZE],
scl_val[XLFD_SCL_POINT_SIZE],
scl_val[XLFD_SCL_AVGWIDTH],
{
font_list = Fcons (build_string (scaled), font_list);
xfree (scaled);
- if (exact || maxnames > 0 && ++n_fonts >= maxnames)
+ if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
break;
}
else
static MacFontStruct *
XLoadQueryFont (Display *dpy, char *fontname)
{
- int i, size, char_width;
+ int size;
char *name;
Str255 family;
Str31 charset;
SInt16 fontnum;
#if USE_ATSUI
+ static ATSUFontID font_id;
ATSUStyle mac_style = NULL;
#endif
Style fontface;
short scriptcode;
#endif
MacFontStruct *font;
+ XCharStruct *space_bounds = NULL, *pcm;
if (is_fully_specified_xlfd (fontname))
name = fontname;
kATSUQDBoldfaceTag, kATSUQDItalicTag};
ByteCount sizes[] = {sizeof (ATSUFontID), sizeof (Fixed),
sizeof (Boolean), sizeof (Boolean)};
- static ATSUFontID font_id;
static Fixed size_fixed;
static Boolean bold_p, italic_p;
ATSUAttributeValuePtr values[] = {&font_id, &size_fixed,
&bold_p, &italic_p};
- ATSUFontFeatureType types[] = {kAllTypographicFeaturesType};
- ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector};
+ ATSUFontFeatureType types[] = {kAllTypographicFeaturesType,
+ kDiacriticsType};
+ ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector,
+ kDecomposeDiacriticsSelector};
Lisp_Object font_id_cons;
font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
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
if (font->mac_style)
{
OSErr err;
- ATSUTextLayout text_layout;
- UniChar c = 0x20;
- Rect char_bounds, min_bounds, max_bounds;
- int min_width, max_width;
- ATSTrapezoid glyph_bounds;
+ 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 (XCharStructRow *) * 0x100);
+ bzero (font->bounds.rows, sizeof (XCharStructRow *) * 0x100);
+ font->bounds.rows[0] = xmalloc (sizeof (XCharStructRow));
+ bzero (font->bounds.rows[0], sizeof (XCharStructRow));
+
+#if USE_CG_TEXT_DRAWING
+ {
+ FMFontFamily font_family;
+ FMFontStyle style;
+ ATSFontRef ats_font;
+
+ err = FMGetFontFamilyInstanceFromFont (font_id, &font_family, &style);
+ if (err == noErr)
+ err = FMGetFontFromFontFamilyInstance (font_family, 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);
+ }
+ }
- font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000);
- if (font->per_char == NULL)
+ if (font->cg_font)
{
- mac_unload_font (&one_mac_display_info, font);
- return NULL;
+ font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
+ bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
}
- bzero (font->per_char, sizeof (XCharStruct) * 0x10000);
-
- err = atsu_get_text_layout_with_text_ptr (&c, 1,
- font->mac_style,
- &text_layout);
+#endif
+ space_bounds = font->bounds.rows[0]->per_char + 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)
{
mac_unload_font (&one_mac_display_info, font);
return NULL;
}
+ XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], 0x20);
- for (c = 0x20; c <= 0x7e; c++)
+ pcm = font->bounds.rows[0]->per_char;
+ for (c = 0x21; c <= 0xff; c++)
{
- err = ATSUClearLayoutCache (text_layout, kATSUFromTextBeginning);
- if (err == noErr)
- err = ATSUMeasureTextImage (text_layout,
- kATSUFromTextBeginning, kATSUToTextEnd,
- 0, 0, &char_bounds);
- if (err == noErr)
- err = ATSUGetGlyphBounds (text_layout, 0, 0,
- kATSUFromTextBeginning, kATSUToTextEnd,
- kATSUseFractionalOrigins, 1,
- &glyph_bounds, NULL);
- if (err == noErr)
+ if (c == 0xad)
+ /* Soft hyphen is not supported in ATSUI. */
+ continue;
+ else if (c == 0x7f)
{
- xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
- == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
+ c = 0x9f;
+ continue;
+ }
- char_width = Fix2Long (glyph_bounds.upperRight.x
- - glyph_bounds.upperLeft.x);
- STORE_XCHARSTRUCT (font->per_char[c],
- char_width, char_bounds);
- if (c == 0x20)
- {
- min_width = max_width = char_width;
- min_bounds = max_bounds = char_bounds;
- font->ascent = -Fix2Long (glyph_bounds.upperLeft.y);
- font->descent = Fix2Long (glyph_bounds.lowerLeft.y);
- }
- else
- {
- if (char_width > 0)
- {
- min_width = min (min_width, char_width);
- max_width = max (max_width, char_width);
- }
- if (!EmptyRect (&char_bounds))
- {
- SetRect (&min_bounds,
- max (min_bounds.left, char_bounds.left),
- max (min_bounds.top, char_bounds.top),
- min (min_bounds.right, char_bounds.right),
- min (min_bounds.bottom, char_bounds.bottom));
- UnionRect (&max_bounds, &char_bounds, &max_bounds);
- }
- }
+ mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c,
+#if USE_CG_TEXT_DRAWING
+ (font->cg_glyphs ? font->cg_glyphs + c
+ : NULL)
+#else
+ NULL
+#endif
+ );
+ XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], c);
+
+#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;
}
+#endif
}
- STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
- STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
-
- font->min_byte1 = 0;
- font->max_byte1 = 0xff;
- font->min_char_or_byte2 = 0;
- font->max_char_or_byte2 = 0xff;
}
else
#endif
if (is_two_byte_font)
{
+ int char_width;
+
font->min_byte1 = 0xa1;
font->max_byte1 = 0xfe;
font->min_char_or_byte2 = 0xa1;
char_width = StringWidth("\p\xa1\xa1");
break;
}
- }
- else
- {
- font->min_byte1 = font->max_byte1 = 0;
- font->min_char_or_byte2 = 0x20;
- font->max_char_or_byte2 = 0xff;
-
- /* Do this instead of use the_fontinfo.widMax, which
- incorrectly returns 15 for 12-point Monaco! */
- char_width = CharWidth ('m');
- }
- if (is_two_byte_font)
- {
- font->per_char = NULL;
+ font->bounds.per_char = NULL;
if (fontface & italic)
font->max_bounds.rbearing = char_width + 1;
}
else
{
- int c, min_width, max_width;
- Rect char_bounds, min_bounds, max_bounds;
- char ch;
+ int c;
+
+ font->min_byte1 = font->max_byte1 = 0;
+ font->min_char_or_byte2 = 0x20;
+ font->max_char_or_byte2 = 0xff;
- font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
- bzero (font->per_char, sizeof (XCharStruct) * (0xff - 0x20 + 1));
+ font->bounds.per_char =
+ xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
+ bzero (font->bounds.per_char,
+ sizeof (XCharStruct) * (0xff - 0x20 + 1));
- min_width = max_width = char_width;
- SetRect (&min_bounds, -32767, -32767, 32767, 32767);
- SetRect (&max_bounds, 0, 0, 0, 0);
- for (c = 0x20; c <= 0xff; c++)
- {
- ch = c;
- char_width = CharWidth (ch);
- QDTextBounds (1, &ch, &char_bounds);
- STORE_XCHARSTRUCT (font->per_char[c - 0x20],
- char_width, char_bounds);
- /* Some Japanese fonts (in SJIS encoding) return 0 as
- the character width of 0x7f. */
- if (char_width > 0)
- {
- min_width = min (min_width, char_width);
- max_width = max (max_width, char_width);
- }
- if (!EmptyRect (&char_bounds))
- {
- SetRect (&min_bounds,
- max (min_bounds.left, char_bounds.left),
- max (min_bounds.top, char_bounds.top),
- min (min_bounds.right, char_bounds.right),
- min (min_bounds.bottom, char_bounds.bottom));
- UnionRect (&max_bounds, &char_bounds, &max_bounds);
- }
- }
- STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
- STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
- if (min_width == max_width
- && max_bounds.left >= 0 && max_bounds.right <= max_width)
- {
- /* Fixed width and no overhangs. */
- xfree (font->per_char);
- font->per_char = NULL;
- }
+ space_bounds = font->bounds.per_char;
+ mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent,
+ space_bounds, NULL);
+
+ for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
+ mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
}
/* Restore previous font number, size and face. */
TextFace (old_fontface);
}
+ 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->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);
+ }
+ 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;
}
XFontStruct *font;
{
xfree (font->full_name);
- if (font->per_char)
- xfree (font->per_char);
#if USE_ATSUI
if (font->mac_style)
- ATSUDisposeStyle (font->mac_style);
+ {
+ int i;
+
+ for (i = font->min_byte1; i <= font->max_byte1; i++)
+ if (font->bounds.rows[i])
+ xfree (font->bounds.rows[i]);
+ xfree (font->bounds.rows);
+ ATSUDisposeStyle (font->mac_style);
+ }
+ else
+#endif
+ if (font->bounds.per_char)
+ xfree (font->bounds.per_char);
+#if USE_CG_TEXT_DRAWING
+ if (font->cg_font)
+ CGFontRelease (font->cg_font);
+ if (font->cg_glyphs)
+ xfree (font->cg_glyphs);
#endif
xfree (font);
}
/* Load the font and add it to the table. */
{
- char *full_name;
struct MacFontStruct *font;
struct font_info *fontp;
- unsigned long value;
int i;
fontname = (char *) SDATA (XCAR (font_names));
/* Contains the string "reverse", which is a constant for mouse button emu.*/
Lisp_Object Qreverse;
-/* True if using command key as meta key. */
-Lisp_Object Vmac_command_key_is_meta;
-/* Modifier associated with the option key, or nil for normal behavior. */
+/* 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;
-/* True if the ctrl and meta keys should be reversed. */
-Lisp_Object Vmac_reverse_ctrl_meta;
+/* 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 USE_CARBON_EVENTS
-/* True if the mouse wheel button (i.e. button 4) should map to
+/* Non-zero if the mouse wheel button (i.e. button 4) should map to
mouse-2, instead of mouse-3. */
-Lisp_Object Vmac_wheel_button_is_mouse_2;
+int mac_wheel_button_is_mouse_2;
-/* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
+/* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
for processing before Emacs sees it. */
-Lisp_Object Vmac_pass_command_to_system;
+int mac_pass_command_to_system;
-/* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
+/* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
for processing before Emacs sees it. */
-Lisp_Object Vmac_pass_control_to_system;
+int mac_pass_control_to_system;
#endif
/* Points to the variable `inev' in the function XTread_socket. It is
Carbon/Apple event handlers. */
static struct input_event *read_socket_inev = NULL;
-/* Set in term/mac-win.el to indicate that event loop can now generate
- drag and drop events. */
-Lisp_Object Qmac_ready_for_drag_n_drop;
-
Point saved_menu_event_location;
/* Apple Events */
-static void init_required_apple_events (void);
-static pascal OSErr
-do_ae_open_application (const AppleEvent *, AppleEvent *, long);
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
+#if USE_CARBON_EVENTS
+static Lisp_Object Qhicommand;
+#endif
+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));
#if TARGET_API_MAC_CARBON
/* Drag and Drop */
static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
#endif
-static Lisp_Object Qapplication, Qabout;
#if USE_CARBON_EVENTS
#ifdef MAC_OSX
extern void init_service_handler ();
-static Lisp_Object Qpreferences, Qservices, Qpaste, Qperform;
+static Lisp_Object Qservices, Qpaste, Qperform;
#endif
/* Window Event Handler */
static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
#endif
{
unsigned int result = 0;
- if (mods & macShiftKey)
+ if (mods & shiftKey)
result |= shift_modifier;
- if (mods & macCtrlKey)
- result |= ctrl_modifier;
- if (mods & macMetaKey)
- result |= meta_modifier;
- if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
- result |= alt_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 (!NILP(val))
- result |= XUINT(val);
+ 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;
}
#if USE_CARBON_EVENTS
/* Obtains the event modifiers from the event ref and then calls
mac_to_emacs_modifiers. */
-static int
+static UInt32
mac_event_to_emacs_modifiers (EventRef eventRef)
{
UInt32 mods = 0;
return mac_get_emulated_btn(mods);
}
case kEventMouseButtonSecondary:
- return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
+ return mac_wheel_button_is_mouse_2 ? 2 : 1;
case kEventMouseButtonTertiary:
case 4: /* 4 is the number for the mouse wheel button */
- return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
+ return mac_wheel_button_is_mouse_2 ? 1 : 2;
default:
return 0;
}
XTread_socket loop). */
static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
{
+ OSStatus err;
Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
if (result)
unsigned char char_codes;
UInt32 key_code;
- eventRec->what = keyDown;
- GetEventParameter (eventRef, kEventParamKeyMacCharCodes, typeChar,
- NULL, sizeof (char), NULL, &char_codes);
- GetEventParameter (eventRef, kEventParamKeyCode, typeUInt32,
- NULL, sizeof (UInt32), NULL, &key_code);
- eventRec->message = char_codes | ((key_code & 0xff) << 8);
- result = 1;
+ 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 = keyDown;
+ eventRec->message = char_codes | ((key_code & 0xff) << 8);
+ result = 1;
+ }
}
break;
if (result)
{
/* Need where and when. */
- UInt32 mods;
+ UInt32 mods = 0;
GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
NULL, sizeof (Point), NULL, &eventRec->where);
#endif
+#ifdef MAC_OS8
static void
do_get_menus (void)
{
exit (1);
}
}
+#endif /* MAC_OS8 */
static void
do_window_update (WindowPtr win)
static void
do_zoom_window (WindowPtr w, int zoom_in_or_out)
{
- GrafPtr save_port;
Rect zoom_rect, port_rect;
- Point top_left;
- int w_title_height, columns, rows, width, height;
+ int columns, rows, width, height;
struct frame *f = mac_window_to_frame (w);
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
#if TARGET_API_MAC_CARBON
- {
- Point standard_size;
+ Point standard_size;
- standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
- standard_size.v = dpyinfo->height;
+ standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+ standard_size.v = dpyinfo->height;
- if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
- zoom_in_or_out = inZoomIn;
- else
- {
- /* Adjust the standard size according to character boundaries. */
-
- columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
- rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
- standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
- standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
- GetWindowBounds (w, kWindowContentRgn, &port_rect);
- if (IsWindowInStandardState (w, &standard_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;
- }
+ if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
+ zoom_in_or_out = inZoomIn;
+ else
+ {
+ /* Adjust the standard size according to character boundaries. */
- ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
- }
+ columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
+ rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
+ standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
+ standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+ GetWindowBounds (w, kWindowContentRgn, &port_rect);
+ if (IsWindowInStandardState (w, &standard_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;
+ }
+
+ ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
#else /* not TARGET_API_MAC_CARBON */
+ GrafPtr save_port;
+ Point top_left;
+ int w_title_height;
+
GetPort (&save_port);
SetPortWindowPort (w);
height = port_rect.bottom - port_rect.top;
width = port_rect.right - port_rect.left;
- 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);
-
- change_frame_size (f, rows, columns, 0, 1, 0);
- SET_FRAME_GARBAGED (f);
- cancel_mouse_face (f);
-
- FRAME_PIXEL_WIDTH (f) = width;
- FRAME_PIXEL_HEIGHT (f) = height;
- }
- x_real_positions (f, &f->left_pos, &f->top_pos);
-}
-
-/* Intialize AppleEvent dispatcher table for the required events. */
-void
-init_required_apple_events ()
-{
- OSErr err;
- long result;
-
- /* Make sure we have apple events before starting. */
- err = Gestalt (gestaltAppleEventsAttr, &result);
- if (err != noErr)
- abort ();
-
- if (!(result & (1 << gestaltAppleEventsPresent)))
- abort ();
-
-#if TARGET_API_MAC_CARBON
- err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- NewAEEventHandlerUPP
- ((AEEventHandlerProcPtr) do_ae_open_application),
- 0L, false);
-#else
- err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- NewAEEventHandlerProc
- ((AEEventHandlerProcPtr) do_ae_open_application),
- 0L, false);
-#endif
- if (err != noErr)
- abort ();
-
-#if TARGET_API_MAC_CARBON
- err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
- NewAEEventHandlerUPP
- ((AEEventHandlerProcPtr) do_ae_open_documents),
- 0L, false);
-#else
- err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
- NewAEEventHandlerProc
- ((AEEventHandlerProcPtr) do_ae_open_documents),
- 0L, false);
-#endif
- if (err != noErr)
- abort ();
-
-#if TARGET_API_MAC_CARBON
- err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
- NewAEEventHandlerUPP
- ((AEEventHandlerProcPtr) do_ae_print_documents),
- 0L, false);
-#else
- err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
- NewAEEventHandlerProc
- ((AEEventHandlerProcPtr) do_ae_print_documents),
- 0L, false);
-#endif
- if (err != noErr)
- abort ();
-
-#if TARGET_API_MAC_CARBON
- err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- NewAEEventHandlerUPP
- ((AEEventHandlerProcPtr) do_ae_quit_application),
- 0L, false);
-#else
- err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- NewAEEventHandlerProc
- ((AEEventHandlerProcPtr) do_ae_quit_application),
- 0L, false);
-#endif
- if (err != noErr)
- abort ();
-}
-
-void
-mac_store_application_menu_event (event)
-#if USE_CARBON_EVENTS
- EventRef event;
-#else
- UInt32 event;
-#endif
-{
- struct input_event buf;
- Lisp_Object frame, entry;
-
- EVENT_INIT (buf);
-
- XSETFRAME (frame, mac_focus_frame (&one_mac_display_info));
- buf.kind = MENU_BAR_EVENT;
- buf.frame_or_window = frame;
- buf.arg = frame;
- kbd_buffer_store_event (&buf);
-
- buf.arg = Qapplication;
- kbd_buffer_store_event (&buf);
-
-#if USE_CARBON_EVENTS
- switch (GetEventClass (event))
- {
-#ifdef MAC_OSX
- case kEventClassService:
- buf.arg = Qservices;
- kbd_buffer_store_event (&buf);
- switch (GetEventKind (event))
- {
- case kEventServicePaste:
- entry = Qpaste;
- break;
-
- case kEventServicePerform:
- {
- OSErr err;
- CFStringRef message;
-
- err = GetEventParameter (event, kEventParamServiceMessageName,
- typeCFStringRef, NULL,
- sizeof (CFStringRef), NULL, &message);
- buf.arg = Qperform;
- kbd_buffer_store_event (&buf);
- if (err == noErr && message)
- entry = intern (SDATA (cfstring_to_lisp (message)));
- else
- entry = Qnil;
- }
- break;
-
- default:
- abort ();
- }
- break;
-#endif /* MAC_OSX */
- case kEventClassCommand:
- {
- HICommand command;
-
- GetEventParameter(event, kEventParamDirectObject, typeHICommand,
- NULL, sizeof (HICommand), NULL, &command);
- switch (command.commandID)
- {
- case kHICommandAbout:
- entry = Qabout;
- break;
-#ifdef MAC_OSX
- case kHICommandPreferences:
- entry = Qpreferences;
- break;
-#endif /* MAC_OSX */
- case kHICommandQuit:
- entry = Qquit;
- break;
- default:
- abort ();
- }
- }
- break;
-
- default:
- abort ();
+ 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);
+
+ change_frame_size (f, rows, columns, 0, 1, 0);
+ SET_FRAME_GARBAGED (f);
+ cancel_mouse_face (f);
+
+ FRAME_PIXEL_WIDTH (f) = width;
+ FRAME_PIXEL_HEIGHT (f) = height;
}
-#else /* USE_CARBON_EVENTS */
- switch (event)
+ x_real_positions (f, &f->left_pos, &f->top_pos);
+}
+
+OSErr
+mac_store_apple_event (class, id, desc)
+ Lisp_Object class, id;
+ const AEDesc *desc;
+{
+ OSErr err;
+ struct input_event buf;
+ AEDesc *desc_copy;
+
+ desc_copy = xmalloc (sizeof (AEDesc));
+ err = AEDuplicateDesc (desc, desc_copy);
+ if (err == noErr)
{
- case kHICommandAbout:
- entry = Qabout;
- break;
- case kHICommandQuit:
- entry = Qquit;
- break;
- default:
- abort ();
+ EVENT_INIT (buf);
+
+ buf.kind = MAC_APPLE_EVENT;
+ buf.x = class;
+ buf.y = id;
+ buf.code = (int)desc_copy;
+ XSETFRAME (buf.frame_or_window,
+ mac_focus_frame (&one_mac_display_info));
+ buf.arg = Qnil;
+ kbd_buffer_store_event (&buf);
}
-#endif
- buf.arg = entry;
- kbd_buffer_store_event (&buf);
+ return err;
+}
+
+Lisp_Object
+mac_make_lispy_event_code (code)
+ int code;
+{
+ AEDesc *desc = (AEDesc *)code;
+ Lisp_Object obj;
+
+ obj = mac_aedesc_to_lisp (desc);
+ AEDisposeDesc (desc);
+ xfree (desc);
+
+ return obj;
}
#if USE_CARBON_EVENTS
EventRef event;
void *data;
{
+ OSStatus result, err;
HICommand command;
- OSErr result;
+ Lisp_Object class_key, id_key, binding;
- GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL,
- sizeof (HICommand), NULL, &command);
+ result = CallNextEventHandler (next_handler, event);
+ if (result != eventNotHandledErr)
+ return result;
- switch (command.commandID)
- {
- case kHICommandAbout:
-#ifdef MAC_OSX
- case kHICommandPreferences:
-#endif /* MAC_OSX */
- result = CallNextEventHandler (next_handler, event);
- if (result != eventNotHandledErr)
- return result;
+ err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
+ NULL, sizeof (HICommand), NULL, &command);
- mac_store_application_menu_event (event);
- return noErr;
+ if (err != noErr || command.commandID == 0)
+ return eventNotHandledErr;
- default:
- break;
+ /* A HICommand event is mapped to an Apple event whose event class
+ symbol is `hicommand' and event ID is its command ID. */
+ class_key = Qhicommand;
+ mac_find_apple_event_spec (0, command.commandID,
+ &class_key, &id_key, &binding);
+ if (!NILP (binding) && !EQ (binding, Qundefined))
+ {
+ if (INTEGERP (binding))
+ return XINT (binding);
+ else
+ {
+ AppleEvent apple_event;
+ static EventParamName names[] = {kEventParamDirectObject,
+ kEventParamKeyModifiers};
+ static EventParamType types[] = {typeHICommand,
+ typeUInt32};
+ err = create_apple_event_from_event_ref (event, 2, names, types,
+ &apple_event);
+ if (err == noErr)
+ {
+ err = mac_store_apple_event (class_key, id_key, &apple_event);
+ AEDisposeDesc (&apple_event);
+ }
+ if (err == noErr)
+ return noErr;
+ }
}
return eventNotHandledErr;
static OSErr
init_command_handler ()
{
- OSErr err = noErr;
EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
static EventHandlerUPP handle_command_eventUPP = NULL;
void *data;
{
WindowPtr wp;
- OSStatus result;
+ OSStatus result, err;
UInt32 attributes;
XSizeHints *size_hints;
- GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
- NULL, sizeof (WindowPtr), NULL, &wp);
+ err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
+ NULL, sizeof (WindowPtr), NULL, &wp);
+ if (err != noErr)
+ return eventNotHandledErr;
switch (GetEventKind (event))
{
if (result != eventNotHandledErr)
return result;
- GetEventParameter (event, kEventParamAttributes, typeUInt32,
- NULL, sizeof (UInt32), NULL, &attributes);
+ err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
+ NULL, sizeof (UInt32), NULL, &attributes);
+ if (err != noErr)
+ break;
+
size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
if ((attributes & kWindowBoundsChangeUserResize)
&& ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
Rect bounds;
int width, height;
- GetEventParameter (event, kEventParamCurrentBounds,
- typeQDRectangle,
- NULL, sizeof (Rect), NULL, &bounds);
+ err = GetEventParameter (event, kEventParamCurrentBounds,
+ typeQDRectangle, NULL, sizeof (Rect),
+ NULL, &bounds);
+ if (err != noErr)
+ break;
+
width = bounds.right - bounds.left;
height = bounds.bottom - bounds.top;
EventRef event;
void *data;
{
- OSStatus result;
+ OSStatus result, err;
switch (GetEventKind (event))
{
if (result != eventNotHandledErr || read_socket_inev == NULL)
return result;
- GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
- NULL, sizeof (WindowRef), NULL, &wp);
+ err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
+ NULL, sizeof (WindowRef), NULL, &wp);
+ if (err != noErr)
+ break;
+
f = mac_window_to_frame (wp);
if (f != mac_focus_frame (&one_mac_display_info))
break;
- GetEventParameter (event, kEventParamMouseWheelAxis,
- typeMouseWheelAxis, NULL,
- sizeof (EventMouseWheelAxis), NULL, &axis);
- if (axis != kEventMouseWheelAxisY)
+ err = GetEventParameter (event, kEventParamMouseWheelAxis,
+ typeMouseWheelAxis, NULL,
+ sizeof (EventMouseWheelAxis), NULL, &axis);
+ if (err != noErr || axis != kEventMouseWheelAxisY)
break;
- GetEventParameter (event, kEventParamMouseWheelDelta, typeSInt32,
- NULL, sizeof (SInt32), NULL, &delta);
- GetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
- NULL, sizeof (Point), NULL, &point);
+ err = GetEventParameter (event, kEventParamMouseWheelDelta,
+ typeSInt32, NULL, sizeof (SInt32),
+ NULL, &delta);
+ if (err != noErr)
+ break;
+ err = GetEventParameter (event, kEventParamMouseLocation,
+ typeQDPoint, NULL, sizeof (Point),
+ NULL, &point);
+ if (err != noErr)
+ break;
read_socket_inev->kind = WHEEL_EVENT;
read_socket_inev->code = 0;
read_socket_inev->modifiers =
return eventNotHandledErr;
}
+
+#ifdef MAC_OSX
+OSErr
+mac_store_services_event (event)
+ EventRef event;
+{
+ OSErr err;
+ AppleEvent apple_event;
+ Lisp_Object id_key;
+
+ switch (GetEventKind (event))
+ {
+ case kEventServicePaste:
+ id_key = Qpaste;
+ err = create_apple_event_from_event_ref (event, 0, NULL, NULL,
+ &apple_event);
+ break;
+
+ case kEventServicePerform:
+ {
+ static EventParamName names[] = {kEventParamServiceMessageName,
+ kEventParamServiceUserData};
+ static EventParamType types[] = {typeCFStringRef,
+ typeCFStringRef};
+
+ id_key = Qperform;
+ err = create_apple_event_from_event_ref (event, 2, names, types,
+ &apple_event);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (err == noErr)
+ {
+ err = mac_store_apple_event (Qservices, id_key, &apple_event);
+ AEDisposeDesc (&apple_event);
+ }
+
+ return err;
+}
+#endif /* MAC_OSX */
#endif /* USE_CARBON_EVENTS */
#endif
}
-/* Open Application Apple Event */
-static pascal OSErr
-do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
-{
- return noErr;
-}
-
-
-/* Called when we receive an AppleEvent with an ID of
- "kAEOpenDocuments". This routine gets the direct parameter,
- extracts the FSSpecs in it, and puts their names on a list. */
-#pragma options align=mac68k
-typedef struct SelectionRange {
- short unused1; // 0 (not used)
- short lineNum; // line to select (<0 to specify range)
- long startRange; // start of selection range (if line < 0)
- long endRange; // end of selection range (if line < 0)
- long unused2; // 0 (not used)
- long theDate; // modification date/time
-} SelectionRange;
-#pragma options align=reset
-
-static pascal OSErr
-do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
-{
- OSErr err, err2;
- AEDesc the_desc;
- AEKeyword keyword;
- DescType actual_type;
- Size actual_size;
- SelectionRange position;
- Lisp_Object file_list = Qnil;
-
- xassert (read_socket_inev);
-
- err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
- if (err != noErr)
- goto descriptor_error_exit;
-
- err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
- if (err == noErr)
- file_list = Fcons (list3 (make_number (position.lineNum + 1),
- make_number (position.startRange + 1),
- make_number (position.endRange + 1)),
- file_list);
-
- /* Check to see that we got all of the required parameters from the
- event descriptor. For an 'odoc' event this should just be the
- file list. */
- err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
- &actual_type, (Ptr) &keyword,
- sizeof (keyword), &actual_size);
- /* No error means that we found some unused parameters.
- errAEDescNotFound means that there are no more parameters. If we
- get an error code other than that, flag it. */
- if ((err == noErr) || (err != errAEDescNotFound))
- {
- err = errAEEventNotHandled;
- goto error_exit;
- }
- err = noErr;
-
- /* Got all the parameters we need. Now, go through the direct
- object list and parse it up. */
- {
- long num_files_to_open;
-
- err = AECountItems (&the_desc, &num_files_to_open);
- if (err == noErr)
- {
- int i;
-
- /* AE file list is one based so just use that for indexing here. */
- for (i = 1; i <= num_files_to_open; i++)
- {
- char unix_path_name[MAXPATHLEN];
-#ifdef MAC_OSX
- FSRef fref;
-
- err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
- &actual_type, &fref, sizeof (FSRef),
- &actual_size);
- if (err != noErr || actual_type != typeFSRef)
- continue;
-
- if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
- == noErr)
-#else
- FSSpec fs;
-
- err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
- (Ptr) &fs, sizeof (fs), &actual_size);
- if (err != noErr) continue;
-
- if (fsspec_to_posix_pathname (&fs, unix_path_name,
- sizeof (unix_path_name) - 1) == noErr)
-#endif
- /* x-dnd functions expect undecoded filenames. */
- file_list = Fcons (make_unibyte_string (unix_path_name,
- strlen (unix_path_name)),
- file_list);
- }
- }
-
- /* Build a DRAG_N_DROP_EVENT type event as is done in
- constuct_drag_n_drop in w32term.c. */
- if (!NILP (file_list))
- {
- struct frame *f = mac_focus_frame (&one_mac_display_info);
- WindowPtr wp;
- Lisp_Object frame;
-
- read_socket_inev->kind = DRAG_N_DROP_EVENT;
- read_socket_inev->code = 0;
- read_socket_inev->modifiers = 0;
-
- XSETINT (read_socket_inev->x, 0);
- XSETINT (read_socket_inev->y, 0);
-
- XSETFRAME (frame, f);
- read_socket_inev->frame_or_window = Fcons (frame, file_list);
-
-#if 0
- /* Regardless of whether Emacs was suspended or in the
- foreground, ask it to redraw its entire screen. Otherwise
- parts of the screen can be left in an inconsistent
- state. */
- wp = FRAME_MAC_WINDOW (f);
- if (wp)
-#if TARGET_API_MAC_CARBON
- {
- Rect r;
-
- GetWindowPortBounds (wp, &r);
- InvalWindowRect (wp, &r);
- }
-#else /* not TARGET_API_MAC_CARBON */
- InvalRect (&(wp->portRect));
-#endif /* not TARGET_API_MAC_CARBON */
-#endif
- }
- }
-
-error_exit:
- /* Nuke the coerced file list in any case */
- err2 = AEDisposeDesc(&the_desc);
-
-descriptor_error_exit:
- /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
- return err;
-}
-
-
#if TARGET_API_MAC_CARBON
static pascal OSErr
mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
if (result == noErr)
{
-#ifdef MAC_OSX
- FSRef fref;
-#endif
- char unix_path_name[MAXPATHLEN];
+ OSErr err;
+ AEDesc desc;
- GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
-#ifdef MAC_OSX
- /* Use Carbon routines, otherwise it converts the file name
- to /Macintosh HD/..., which is not correct. */
- FSpMakeFSRef (&data.fileSpec, &fref);
- if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
-#else
- if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name,
- sizeof (unix_path_name) - 1) == noErr)
-#endif
- /* x-dnd functions expect undecoded filenames. */
- file_list = Fcons (make_unibyte_string (unix_path_name,
- strlen (unix_path_name)),
- file_list);
+ err = GetFlavorData (theDrag, theItem, flavorTypeHFS,
+ &data, &size, 0L);
+ if (err == noErr)
+ err = AECoercePtr (typeFSS, &data.fileSpec, sizeof (FSSpec),
+ TYPE_FILE_NAME, &desc);
+ if (err == noErr)
+ {
+ Lisp_Object file;
+
+ /* x-dnd functions expect undecoded filenames. */
+ file = make_uninit_string (AEGetDescDataSize (&desc));
+ err = AEGetDescData (&desc, SDATA (file), SBYTES (file));
+ if (err == noErr)
+ file_list = Fcons (file, file_list);
+ AEDisposeDesc (&desc);
+ }
}
}
/* If there are items in the list, construct an event and post it to
XSETINT (event.x, mouse.h);
XSETINT (event.y, mouse.v);
XSETFRAME (frame, f);
- event.frame_or_window = Fcons (frame, file_list);
- event.arg = Qnil;
+ event.frame_or_window = frame;
+ event.arg = file_list;
/* Post to the interrupt queue */
kbd_buffer_store_event (&event);
/* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
#endif
-/* Print Document Apple Event */
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
-{
- return errAEEventNotHandled;
-}
-
-
-static pascal OSErr
-do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
-{
-#if USE_CARBON_EVENTS
- OSErr err;
- EventRef event = NULL;
- static const HICommand quit_command = {kEventAttributeNone, kHICommandQuit};
-
- err = CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 0,
- kEventAttributeUserEvent, &event);
- if (err == noErr)
- err = SetEventParameter (event, kEventParamDirectObject, typeHICommand,
- sizeof (HICommand), &quit_command);
- if (err == noErr)
- mac_store_application_menu_event (event);
- if (event)
- ReleaseEvent (event);
-
- if (err == noErr)
- return noErr;
- else
- return errAEEventNotHandled;
-#else
- mac_store_application_menu_event (kHICommandQuit);
-
- return noErr;
-#endif
-}
-
-
#if __profile__
void
profiler_exit_proc ()
init_environ ();
+ init_coercion_handler ();
+
initialize_applescript ();
- init_required_apple_events ();
+ init_apple_event_handler ();
{
char **argv;
/*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
};
+
static int
keycode_to_xkeysym (int keyCode, int *xKeySym)
{
return *xKeySym != 0;
}
+static unsigned char fn_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, 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*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
+ /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
+ /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
+ /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
+
+ /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
+ /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
+ /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
+ /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
+
+ /*0x60*/ 0, 0, 0, 0,
+ /*0x64*/ 0, 0, 0, 0,
+ /*0x68*/ 0, 0, 0, 0,
+ /*0x6C*/ 0, 0, 0, 0,
+
+ /*0x70*/ 0, 0, 0, 0,
+ /*0x74*/ 0, 0, 0, 0,
+ /*0x78*/ 0, 0, 0, 0,
+ /*0x7C*/ 0, 0, 0, 0
+};
+static int
+convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
+{
+#ifdef MAC_OSX
+ /* Use the special map to translate keys when function modifier is
+ to be caught. KeyTranslate can't be used in that case.
+ We can't detect the function key using the input_event.modifiers,
+ because this uses the high word of an UInt32. Therefore,
+ we'll just read it out of the original eventRef.
+ */
+
+
+ /* TODO / known issues
+
+ - Fn-Shift-j is regonized as Fn-j and not Fn-J.
+ The above table always translates to lower characters. We need to use
+ the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
+
+ - The table is meant for English language keyboards, and it will work
+ for many others with the exception of key combinations like Fn-ö on
+ a German keyboard, which is currently mapped to Fn-;.
+ How to solve this without keeping separate tables for all keyboards
+ around? KeyTranslate isn't of much help here, as it only takes a 16-bit
+ value for keycode with the modifiers in he high byte, i.e. no room for the
+ Fn modifier. That's why we need the table.
+
+ */
+ OSStatus err;
+ UInt32 mods = 0;
+ if (!NILP(Vmac_function_modifier))
+ {
+ err = GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
+ NULL, sizeof (UInt32), NULL, &mods);
+ if (err != noErr && mods & kEventKeyModifierFnMask)
+ { *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
+
+ return (*newCode != 0);
+ }
+ }
+#endif
+ return false;
+}
+
+static int
+backtranslate_modified_keycode(int mods, int keycode, int def)
+{
+ EventModifiers mapped_modifiers =
+ (NILP (Vmac_control_modifier) ? 0 : controlKey)
+ | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+ | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+
+ if (mods & mapped_modifiers)
+ {
+ /* 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.
+
+ Not done for combinations with the option key (alt)
+ unless it is to be caught by Emacs: this is
+ to preserve key combinations translated by the OS
+ such as Alt-3.
+ */
+ /* Mask off modifier keys that are mapped to some Emacs
+ modifiers. */
+ int new_modifiers = mods & ~mapped_modifiers;
+ /* set high byte of keycode to modifier high byte*/
+ int new_keycode = keycode | new_modifiers;
+ Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+ unsigned long some_state = 0;
+ return (int) KeyTranslate (kchr_ptr, new_keycode,
+ &some_state) & 0xff;
+ /* TO DO: Recognize two separate resulting characters, "for
+ example, when the user presses Option-E followed by N, you
+ can map this through the KeyTranslate function using the
+ U.S. 'KCHR' resource to produce ´n, which KeyTranslate
+ returns as two characters in the bytes labeled Character code
+ 1 and Character code 2." (from Carbon API doc) */
+
+ }
+ else
+ return def;
+}
+
+
#if !USE_CARBON_EVENTS
static RgnHandle mouse_region = NULL;
mouse_region = NewRgn ();
event_mask = everyEvent;
- if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
+ if (!mac_ready_for_apple_events)
event_mask -= highLevelEventMask;
current_tick = TickCount ();
/* So people can tell when we have read the available input. */
input_signal_count++;
+ ++handling_signal;
+
#if USE_CARBON_EVENTS
toolbox_dispatcher = GetEventDispatcherTarget ();
- while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
+ while (
+#if USE_CG_DRAWING
+ mac_prepare_for_quickdraw (NULL),
+#endif
+ !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
kEventRemoveFromQueue, &eventRef))
#else /* !USE_CARBON_EVENTS */
while (mac_wait_next_event (&er, 0, true))
!= eventNotHandledErr)
break;
#endif
+ last_mouse_glyph_frame = 0;
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
}
}
- if (er.what != mouseDown && part_code != inContent)
+ if (er.what != mouseDown &&
+ (part_code != inContent || dpyinfo->grabbed == 0))
break;
switch (part_code)
XSETINT (inev.x, mouse_loc.h);
XSETINT (inev.y, mouse_loc.v);
- if (dpyinfo->grabbed && tracked_scroll_bar
- || ch != 0
+ 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
+ /* 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
+ && control_kind.kind == kControlKindScrollBar
#endif /* MAC_OSX */
#endif /* USE_TOOLKIT_SCROLL_BARS */
- )
+ ))
{
struct scroll_bar *bar;
{
dpyinfo->grabbed |= (1 << inev.code);
last_mouse_frame = f;
- /* 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;
if (!tool_bar_p)
last_tool_bar_item = -1;
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)
#endif
er.where.h + 1, er.where.v + 1);
#endif
previous_help_echo_string = help_echo_string;
- help_echo_string = help_echo_object = help_echo_window = Qnil;
- help_echo_pos = -1;
+ help_echo_string = Qnil;
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
last_window=window;
}
- note_mouse_movement (f, &mouse_pos);
+ if (!note_mouse_movement (f, &mouse_pos))
+ help_echo_string = previous_help_echo_string;
}
}
will pass back noErr, otherwise it will pass back
"eventNotHandledErr" and we can process it
normally. */
- if ((!NILP (Vmac_pass_command_to_system)
+ if ((mac_pass_command_to_system
|| !(er.modifiers & cmdKey))
- && (!NILP (Vmac_pass_control_to_system)
+ && (mac_pass_control_to_system
|| !(er.modifiers & controlKey))
- && (!NILP (Vmac_command_key_is_meta)
- && NILP (Vmac_option_modifier)
+ && (NILP (Vmac_option_modifier)
|| !(er.modifiers & optionKey)))
if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
!= eventNotHandledErr)
ObscureCursor ();
- if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+ f = mac_focus_frame (dpyinfo);
+
+ 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;
}
- if (keycode_to_xkeysym (keycode, &xkeysym))
- {
- inev.code = 0xff00 | xkeysym;
- inev.kind = NON_ASCII_KEYSTROKE_EVENT;
- }
- else
+ /* translate the keycode back to determine the original key */
+ /* Convert key code if function key is pressed.
+ Otherwise, if non-ASCII-event, take care of that
+ without re-translating the key code. */
+#if USE_CARBON_EVENTS
+ if (convert_fn_keycode (eventRef, keycode, &xkeysym))
{
- if (er.modifiers & (controlKey |
- (NILP (Vmac_command_key_is_meta) ? optionKey
- : cmdKey)))
- {
- /* 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 */
- int new_modifiers = er.modifiers & 0xe600;
- /* mask off option and command */
- int new_keycode = keycode | new_modifiers;
- Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
- unsigned long some_state = 0;
- inev.code = KeyTranslate (kchr_ptr, new_keycode,
- &some_state) & 0xff;
- }
- else if (!NILP (Vmac_option_modifier)
- && (er.modifiers & optionKey))
- {
- /* When using the option key as an emacs modifier,
- convert the pressed key code back to one
- without the Mac option modifier applied. */
- int new_modifiers = er.modifiers & ~optionKey;
- int new_keycode = keycode | new_modifiers;
- Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
- unsigned long some_state = 0;
- inev.code = KeyTranslate (kchr_ptr, new_keycode,
- &some_state) & 0xff;
- }
- else
- inev.code = er.message & charCodeMask;
+ inev.code = xkeysym;
+ /* this doesn't work - tried to add shift modifiers */
+ inev.code =
+ backtranslate_modified_keycode(er.modifiers & (~0x2200),
+ xkeysym | 0x80, xkeysym);
inev.kind = ASCII_KEYSTROKE_EVENT;
}
+ else
+#endif
+ if (keycode_to_xkeysym (keycode, &xkeysym))
+ {
+ inev.code = 0xff00 | xkeysym;
+ inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+ }
+ else
+ {
+ inev.code =
+ backtranslate_modified_keycode(er.modifiers, keycode,
+ er.message & charCodeMask);
+ inev.kind = ASCII_KEYSTROKE_EVENT;
+ }
}
#if USE_CARBON_EVENTS
inev.modifiers |= (extra_keyboard_modifiers
& (meta_modifier | alt_modifier
| hyper_modifier | super_modifier));
- XSETFRAME (inev.frame_or_window, mac_focus_frame (dpyinfo));
+ XSETFRAME (inev.frame_or_window, f);
break;
case kHighLevelEvent:
}
#endif
+ --handling_signal;
UNBLOCK_INPUT;
return count;
}
main_device_handle = LMGetMainDevice();
dpyinfo->reference_count = 0;
- dpyinfo->resx = 75.0;
- dpyinfo->resy = 75.0;
+ dpyinfo->resx = 72.0;
+ dpyinfo->resy = 72.0;
dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
#ifdef MAC_OSX
/* HasDepth returns true if it is possible to have a 32 bit display,
extern int inhibit_window_system;
extern int noninteractive;
CFBundleRef appsBundle;
- pid_t child;
/* No need to test if already -nw*/
if (inhibit_window_system || noninteractive)
/* Map modifiers */
mac_quit_char_modifiers = 0;
- if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
- if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
- if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
- if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
+ if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= controlKey;
+ if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey;
+ if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= optionKey;
}
static void
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,
BLOCK_INPUT;
#if TARGET_API_MAC_CARBON
- init_required_apple_events ();
#if USE_CARBON_EVENTS
#ifdef MAC_OSX
#endif /* USE_CARBON_EVENTS */
#ifdef MAC_OSX
+ init_coercion_handler ();
+
+ init_apple_event_handler ();
+
if (!inhibit_window_system)
MakeMeTheFrontProcess ();
#endif
#endif
+
+#if USE_CG_DRAWING
+ mac_init_fringe ();
+#endif
+
UNBLOCK_INPUT;
}
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");
- Qalt = intern ("alt");
- Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
- Qhyper = intern ("hyper");
- Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
- Qsuper = intern ("super");
- Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+ staticpro (&Qmodifier_value);
- Qapplication = intern ("application"); staticpro (&Qapplication);
- Qabout = intern ("about"); staticpro (&Qabout);
+ 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 USE_CARBON_EVENTS && defined (MAC_OSX)
- Qpreferences = intern ("preferences"); staticpro (&Qpreferences);
+#if USE_CARBON_EVENTS
+ Qhicommand = intern ("hicommand"); staticpro (&Qhicommand);
+#ifdef MAC_OSX
Qservices = intern ("services"); staticpro (&Qservices);
Qpaste = intern ("paste"); staticpro (&Qpaste);
Qperform = intern ("perform"); staticpro (&Qperform);
#endif
+#endif
#ifdef MAC_OSX
Fprovide (intern ("mac-carbon"), Qnil);
staticpro (&Qreverse);
Qreverse = intern ("reverse");
- staticpro (&Qmac_ready_for_drag_n_drop);
- Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
-
staticpro (&x_display_name_list);
x_display_name_list = Qnil;
atsu_font_id_hash = 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.
+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_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
doc: /* If not nil, Emacs uses toolkit scroll bars. */);
#ifdef USE_TOOLKIT_SCROLL_BARS
staticpro (&last_mouse_motion_frame);
last_mouse_motion_frame = Qnil;
- DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
- doc: /* Non-nil means that the command key is used as the Emacs meta key.
-Otherwise the option key is used. */);
- Vmac_command_key_is_meta = Qt;
+/* 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 to use for the Mac alt/option key. The value can
-be alt, hyper, or super for the respective modifier. If the value is
-nil then the key will act as the normal Mac 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-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
- doc: /* Non-nil means that the control and meta keys are reversed. This is
-useful for non-standard keyboard layouts. */);
- Vmac_reverse_ctrl_meta = 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: /* 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.
-'reverse means that the option-key will register for mouse-3
-and the command-key will register for mouse-2. nil means that
-no emulation should be done and the modifiers should be placed
-on the mouse-1 event. */);
+ doc: /* *Specify a way of three button mouse emulation.
+The value can be nil, t, or the symbol `reverse'.
+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 USE_CARBON_EVENTS
- DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
- doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
-the right click will be mouse-3.
-Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
- Vmac_wheel_button_is_mouse_2 = Qt;
+ 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_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
- doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
-Toolbox for processing before Emacs sees it. */);
- Vmac_pass_command_to_system = Qt;
+ 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_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
- doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
-Toolbox for processing before Emacs sees it. */);
- Vmac_pass_control_to_system = Qt;
+ 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_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
- doc: /* If non-nil, allow anti-aliasing.
+ 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. */);
- Vmac_use_core_graphics = Qnil;
+ mac_use_core_graphics = 0;
/* 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 linking Emacs character sets to Mac text encoding and Emacs coding system.
+ 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, and CODING_SYSTEM
-is a coding system corresponding to TEXT-ENCODING. */);
+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);