X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/71b7a47f7972000021bade3c1cab8e34a0ce9d0c..4ec9a7e215e94432892b0663be6c8b734be85c38:/src/macterm.c diff --git a/src/macterm.c b/src/macterm.c index 2142698bbf..cbef67c3be 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -1,6 +1,6 @@ /* 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. @@ -68,7 +68,6 @@ Boston, MA 02110-1301, USA. */ #include #include #include -#include #include "charset.h" #include "coding.h" @@ -78,7 +77,6 @@ Boston, MA 02110-1301, USA. */ #include "termhooks.h" #include "termopts.h" #include "termchar.h" -#include "gnu.h" #include "disptab.h" #include "buffer.h" #include "window.h" @@ -87,22 +85,15 @@ Boston, MA 02110-1301, USA. */ #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) /* 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 @@ -113,6 +104,10 @@ static int any_help_event_p; /* Last window where we saw the mouse. Used by mouse-autoselect-window. */ static Lisp_Object last_window; +/* Non-zero means make use of UNDERLINE_POSITION font properties. + (Not yet supported.) */ +int x_use_underline_position_properties; + /* This is a chain of structures for all the X displays currently in use. */ @@ -165,6 +160,7 @@ struct frame *pending_autoraise_frame; /* 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. @@ -206,7 +202,7 @@ extern EMACS_INT extra_keyboard_modifiers; /* 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; @@ -218,7 +214,6 @@ QDGlobals qd; /* QuickDraw global information structure. */ 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 *)); @@ -261,7 +256,7 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *, 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. */ @@ -270,14 +265,84 @@ extern void menubar_selection_callback (FRAME_PTR, int); #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; @@ -286,19 +351,19 @@ mac_begin_clip (region) 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); } @@ -317,20 +382,32 @@ XFreePixmap (display, pixmap) /* 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 @@ -358,70 +435,124 @@ mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2) 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; @@ -434,26 +565,32 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p) 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. */ @@ -514,7 +651,15 @@ XCreatePixmap (display, w, width, height, depth) 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; @@ -569,103 +714,64 @@ XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth) /* 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 @@ -686,7 +792,8 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout) 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 @@ -724,16 +831,19 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout) } #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); @@ -742,28 +852,14 @@ mac_invert_rectangle (display, w, x, y, width, 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) @@ -776,170 +872,483 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode, #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; @@ -947,7 +1356,7 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x, { 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); @@ -955,31 +1364,35 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x, 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; @@ -987,7 +1400,7 @@ mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y, { 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); @@ -995,33 +1408,38 @@ mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y, 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; @@ -1032,11 +1450,16 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y) 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); @@ -1047,95 +1470,13 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y) 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. */ @@ -1167,11 +1508,8 @@ XCreateGC (display, window, mask, xgcv) { 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; } @@ -1267,17 +1605,10 @@ mac_set_clip_rectangles (display, gc, rectangles, n) { 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 (); @@ -1295,8 +1626,6 @@ mac_set_clip_rectangles (display, gc, rectangles, n) } } #if defined (MAC_OSX) && USE_ATSUI - gc->n_clip_rects = n; - for (i = 0; i < n; i++) { Rect *rect = rectangles + i; @@ -1316,7 +1645,7 @@ mac_reset_clip_rectangles (display, gc) Display *display; GC gc; { - mac_set_clip_rectangles (display, gc, NULL, 0); + gc->n_clip_rects = 0; } @@ -1363,14 +1692,6 @@ XSetWindowBackground (display, w, color) #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 @@ -1379,6 +1700,9 @@ x_flush (f) { #if TARGET_API_MAC_CARBON BLOCK_INPUT; +#if USE_CG_DRAWING + mac_prepare_for_quickdraw (f); +#endif if (f) QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL); else @@ -1509,8 +1833,7 @@ mac_draw_vertical_window_border (w, x, y0, y1) 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). @@ -1649,11 +1972,8 @@ x_after_update_window_line (desired_row) 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; } } @@ -1672,8 +1992,6 @@ x_draw_fringe_bitmap (w, row, p) { 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; @@ -1687,12 +2005,12 @@ x_draw_fringe_bitmap (w, row, p) 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) { @@ -1707,7 +2025,7 @@ x_draw_fringe_bitmap (w, row, 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) @@ -1715,9 +2033,12 @@ x_draw_fringe_bitmap (w, row, p) #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); @@ -1726,14 +2047,63 @@ x_draw_fringe_bitmap (w, row, p) ? (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 /* This is called when starting Emacs and when restarting after @@ -1782,59 +2152,28 @@ x_per_char_metric (font, char2b) #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) { @@ -1847,7 +2186,8 @@ x_per_char_metric (font, char2b) 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 { @@ -1869,7 +2209,7 @@ x_per_char_metric (font, char2b) && 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)); @@ -1890,7 +2230,11 @@ x_per_char_metric (font, char2b) #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); } @@ -2008,7 +2352,6 @@ static void x_setup_relief_colors P_ ((struct glyph_string *)); static void x_draw_image_glyph_string P_ ((struct glyph_string *)); static void x_draw_image_relief P_ ((struct glyph_string *)); static void x_draw_image_foreground P_ ((struct glyph_string *)); -static void x_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, @@ -2209,65 +2552,32 @@ static void 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; @@ -2282,18 +2592,10 @@ x_clear_glyph_string_rect (s, x, y, w, h) 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 @@ -2325,12 +2627,10 @@ x_draw_glyph_string_background (s, force_p) } 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, @@ -2347,7 +2647,7 @@ static void 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. */ @@ -2364,9 +2664,8 @@ x_draw_glyph_string_foreground (s) 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; } } @@ -2387,7 +2686,6 @@ x_draw_glyph_string_foreground (s) 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 @@ -2395,31 +2693,27 @@ x_draw_glyph_string_foreground (s) 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); } } @@ -2449,16 +2743,16 @@ x_draw_composite_glyph_string_foreground (s) 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); } } @@ -2814,7 +3108,6 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, Rect *clip_rect; { Display *dpy = FRAME_MAC_DISPLAY (f); - Window window = FRAME_MAC_WINDOW (f); int i; GC gc; @@ -2827,15 +3120,15 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, /* 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) @@ -2847,15 +3140,15 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, /* 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); } @@ -2882,22 +3175,22 @@ x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, 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); @@ -2983,15 +3276,26 @@ x_draw_image_foreground (s) { 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 @@ -3003,8 +3307,7 @@ x_draw_image_foreground (s) { 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); } @@ -3012,7 +3315,7 @@ x_draw_image_foreground (s) } 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); } @@ -3070,70 +3373,6 @@ x_draw_image_relief (s) } -#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. */ @@ -3178,7 +3417,6 @@ x_draw_image_glyph_string (s) 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; @@ -3203,62 +3441,13 @@ x_draw_image_glyph_string (s) 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 @@ -3317,7 +3506,7 @@ x_draw_stretch_glyph_string (s) } 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) @@ -3408,15 +3597,15 @@ x_draw_glyph_string (s) 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); } } @@ -3427,15 +3616,15 @@ x_draw_glyph_string (s) 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); } } @@ -3447,15 +3636,15 @@ x_draw_glyph_string (s) 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); } } @@ -3476,8 +3665,7 @@ mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by) struct frame *f; int x, y, width, height, shift_by; { - mac_scroll_area (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); } @@ -3515,7 +3703,7 @@ x_clear_frame () /* 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. */ @@ -3605,21 +3793,18 @@ XTflash (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); @@ -3659,21 +3844,18 @@ XTflash (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); @@ -3778,11 +3960,10 @@ x_scroll_run (w, run) 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; } @@ -3981,142 +4162,6 @@ x_frame_rehighlight (dpyinfo) -/* 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 * @@ -4149,7 +4194,7 @@ x_get_keysym_name (keysym) 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; @@ -4180,17 +4225,22 @@ note_mouse_movement (frame, 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; } @@ -4198,9 +4248,6 @@ note_mouse_movement (frame, pos) 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 @@ -4214,110 +4261,6 @@ redo_mouse_highlight () } -/* 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; @@ -4333,18 +4276,18 @@ mac_focus_frame (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. @@ -4361,11 +4304,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) 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; @@ -4373,25 +4312,44 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) 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; @@ -4410,8 +4368,8 @@ static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval)); static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode)); static void construct_scroll_bar_click P_ ((struct scroll_bar *, int, struct input_event *)); -static 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 *)); @@ -4532,7 +4490,7 @@ construct_scroll_bar_click (bar, part, bufp) bufp->modifiers = 0; } -static OSErr +static OSStatus get_control_part_bounds (ch, part_code, rect) ControlHandle ch; ControlPartCode part_code; @@ -4674,10 +4632,12 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole) 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 { @@ -4688,10 +4648,19 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole) 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; } @@ -4727,8 +4696,16 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height) 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, @@ -4848,6 +4825,9 @@ x_scroll_bar_remove (bar) BLOCK_INPUT; +#if USE_CG_DRAWING + mac_prepare_for_quickdraw (f); +#endif /* Destroy the Mac scroll bar control */ DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar)); @@ -4898,6 +4878,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position) /* 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; @@ -4911,13 +4892,13 @@ XTset_vertical_scroll_bar (w, portion, whole, position) 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); @@ -4941,21 +4922,19 @@ XTset_vertical_scroll_bar (w, portion, whole, position) { /* 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); @@ -4974,28 +4953,41 @@ XTset_vertical_scroll_bar (w, portion, whole, position) #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); @@ -5381,7 +5373,7 @@ x_draw_hollow_cursor (w, row) /* 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); } @@ -5454,17 +5446,17 @@ x_draw_bar_cursor (w, row, width, kind) 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); } @@ -5478,7 +5470,10 @@ mac_define_frame_cursor (f, cursor) 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); } @@ -5489,8 +5484,7 @@ mac_clear_frame_area (f, x, y, width, height) 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); } @@ -5906,8 +5900,13 @@ x_set_window_size (f, change_gravity, cols, rows) 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, @@ -6017,7 +6016,7 @@ x_raise_frame (f) if (f->async_visible) { BLOCK_INPUT; - SelectWindow (FRAME_MAC_WINDOW (f)); + BringToFront (FRAME_MAC_WINDOW (f)); UNBLOCK_INPUT; } } @@ -6031,7 +6030,7 @@ x_lower_frame (f) if (f->async_visible) { BLOCK_INPUT; - SendBehind (FRAME_MAC_WINDOW (f), nil); + SendBehind (FRAME_MAC_WINDOW (f), NULL); UNBLOCK_INPUT; } } @@ -6058,10 +6057,12 @@ mac_handle_visibility_change (f) 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) { @@ -6107,9 +6108,6 @@ void x_make_frame_visible (f) struct frame *f; { - Lisp_Object type; - int original_top, original_left; - BLOCK_INPUT; if (! FRAME_VISIBLE_P (f)) @@ -6120,31 +6118,32 @@ x_make_frame_visible (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)); } @@ -6561,12 +6560,7 @@ xlfdpat_create (pattern) 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; @@ -6584,15 +6578,17 @@ xlfdpat_create (pattern) 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 == '?') @@ -6628,8 +6624,6 @@ xlfdpat_create (pattern) } pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks); - if (pat->blocks == NULL) - goto error; /* Divide the normalized pattern into blocks. */ p = pat->buf; @@ -6944,7 +6938,7 @@ mac_to_x_fontname (name, size, style, charset) 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); @@ -7048,8 +7042,27 @@ add_font_name_table_entry (char *font_name) 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 @@ -7070,25 +7083,34 @@ init_font_name_table () 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++) { @@ -7098,40 +7120,25 @@ init_font_name_table () 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); } @@ -7159,16 +7166,16 @@ init_font_name_table () 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); @@ -7177,13 +7184,15 @@ init_font_name_table () 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) @@ -7192,27 +7201,7 @@ init_font_name_table () 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))); } } @@ -7232,7 +7221,7 @@ init_font_name_table () 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 */ @@ -7251,7 +7240,7 @@ init_font_name_table () GetResInfo (font_handle, &id, &type, name); GetFNum (name, &fontnum); p2cstr (name); - if (fontnum == 0) + if (fontnum == 0 || *name == '.') continue; TextFont (fontnum); @@ -7263,8 +7252,10 @@ init_font_name_table () 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 { @@ -7285,14 +7276,9 @@ init_font_name_table () 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))); } } @@ -7420,7 +7406,7 @@ mac_do_list_fonts (pattern, maxnames) 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 @@ -7429,11 +7415,9 @@ mac_do_list_fonts (pattern, maxnames) 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], @@ -7443,7 +7427,7 @@ mac_do_list_fonts (pattern, maxnames) { 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 @@ -7639,12 +7623,13 @@ is_fully_specified_xlfd (char *p) 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; @@ -7655,6 +7640,7 @@ XLoadQueryFont (Display *dpy, char *fontname) short scriptcode; #endif MacFontStruct *font; + XCharStruct *space_bounds = NULL, *pcm; if (is_fully_specified_xlfd (fontname)) name = fontname; @@ -7679,13 +7665,14 @@ XLoadQueryFont (Display *dpy, char *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)), @@ -7733,6 +7720,10 @@ XLoadQueryFont (Display *dpy, char *fontname) 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 @@ -7748,83 +7739,94 @@ XLoadQueryFont (Display *dpy, char *fontname) 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 @@ -7863,6 +7865,8 @@ XLoadQueryFont (Display *dpy, char *fontname) if (is_two_byte_font) { + int char_width; + font->min_byte1 = 0xa1; font->max_byte1 = 0xfe; font->min_char_or_byte2 = 0xa1; @@ -7891,21 +7895,8 @@ XLoadQueryFont (Display *dpy, char *fontname) 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; @@ -7920,49 +7911,23 @@ XLoadQueryFont (Display *dpy, char *fontname) } 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. */ @@ -7971,6 +7936,59 @@ XLoadQueryFont (Display *dpy, char *fontname) 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; } @@ -7981,11 +7999,26 @@ mac_unload_font (dpyinfo, 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); } @@ -8029,10 +8062,8 @@ x_load_font (f, fontname, size) /* 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)); @@ -8273,31 +8304,35 @@ x_find_ccl_program (fontp) /* 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 @@ -8305,20 +8340,19 @@ Lisp_Object Vmac_pass_control_to_system; 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 */ @@ -8328,11 +8362,10 @@ static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL; 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, @@ -8354,19 +8387,41 @@ mac_to_emacs_modifiers (EventModifiers mods) #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; } @@ -8388,7 +8443,7 @@ mac_get_emulated_btn ( UInt32 modifiers ) #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; @@ -8422,10 +8477,10 @@ mac_get_mouse_btn (EventRef ref) 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; } @@ -8440,6 +8495,7 @@ mac_get_mouse_btn (EventRef ref) XTread_socket loop). */ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) { + OSStatus err; Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec); if (result) @@ -8473,13 +8529,19 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) 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; @@ -8495,7 +8557,7 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) if (result) { /* Need where and when. */ - UInt32 mods; + UInt32 mods = 0; GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint, NULL, sizeof (Point), NULL, &eventRec->where); @@ -8513,6 +8575,7 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) #endif +#ifdef MAC_OS8 static void do_get_menus (void) { @@ -8574,6 +8637,7 @@ do_check_ram_size (void) exit (1); } } +#endif /* MAC_OS8 */ static void do_window_update (WindowPtr win) @@ -8755,42 +8819,41 @@ do_grow_window (WindowPtr w, EventRecord *e) 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); @@ -8837,195 +8900,62 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out) 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 @@ -9035,27 +8965,46 @@ mac_handle_command_event (next_handler, event, data) 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; @@ -9064,7 +9013,6 @@ mac_handle_command_event (next_handler, event, data) static OSErr init_command_handler () { - OSErr err = noErr; EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}}; static EventHandlerUPP handle_command_eventUPP = NULL; @@ -9082,12 +9030,14 @@ mac_handle_window_event (next_handler, event, data) 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)) { @@ -9104,8 +9054,11 @@ mac_handle_window_event (next_handler, event, data) 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)) @@ -9114,9 +9067,12 @@ mac_handle_window_event (next_handler, event, data) 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; @@ -9165,7 +9121,7 @@ mac_handle_mouse_event (next_handler, event, data) EventRef event; void *data; { - OSStatus result; + OSStatus result, err; switch (GetEventKind (event)) { @@ -9181,22 +9137,31 @@ mac_handle_mouse_event (next_handler, event, data) 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 = @@ -9218,6 +9183,50 @@ mac_handle_mouse_event (next_handler, event, data) 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 */ @@ -9276,159 +9285,6 @@ remove_window_handler (window) #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, @@ -9524,25 +9380,25 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, 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 @@ -9564,8 +9420,8 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, 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 */ @@ -9583,44 +9439,6 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, #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 () @@ -9672,9 +9490,11 @@ main (void) init_environ (); + init_coercion_handler (); + initialize_applescript (); - init_required_apple_events (); + init_apple_event_handler (); { char **argv; @@ -9738,6 +9558,7 @@ static unsigned char keycode_to_xkeysym_table[] = { /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0 }; + static int keycode_to_xkeysym (int keyCode, int *xKeySym) { @@ -9745,6 +9566,124 @@ 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; @@ -9762,7 +9701,7 @@ mac_wait_next_event (er, sleep_time, dequeue) 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 (); @@ -9812,10 +9751,16 @@ XTread_socket (sd, expected, hold_quit) /* 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)) @@ -9873,6 +9818,7 @@ XTread_socket (sd, expected, hold_quit) != eventNotHandledErr) break; #endif + last_mouse_glyph_frame = 0; if (dpyinfo->grabbed && last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) @@ -9890,7 +9836,8 @@ XTread_socket (sd, expected, hold_quit) } } - if (er.what != mouseDown && part_code != inContent) + if (er.what != mouseDown && + (part_code != inContent || dpyinfo->grabbed == 0)) break; switch (part_code) @@ -9941,18 +9888,18 @@ XTread_socket (sd, expected, hold_quit) 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; @@ -10013,12 +9960,6 @@ XTread_socket (sd, expected, hold_quit) { 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; @@ -10034,6 +9975,13 @@ XTread_socket (sd, expected, hold_quit) 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 @@ -10122,8 +10070,7 @@ XTread_socket (sd, expected, hold_quit) 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)) @@ -10182,7 +10129,8 @@ XTread_socket (sd, expected, hold_quit) last_window=window; } - note_mouse_movement (f, &mouse_pos); + if (!note_mouse_movement (f, &mouse_pos)) + help_echo_string = previous_help_echo_string; } } @@ -10282,12 +10230,11 @@ XTread_socket (sd, expected, hold_quit) 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) @@ -10325,55 +10272,43 @@ XTread_socket (sd, expected, hold_quit) 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 @@ -10384,7 +10319,7 @@ XTread_socket (sd, expected, hold_quit) 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: @@ -10465,6 +10400,7 @@ XTread_socket (sd, expected, hold_quit) } #endif + --handling_signal; UNBLOCK_INPUT; return count; } @@ -10600,8 +10536,8 @@ mac_initialize_display_info () 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, @@ -10763,7 +10699,6 @@ mac_check_bundle() 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) @@ -10813,10 +10748,9 @@ mac_determine_quit_char_modifiers() /* 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 @@ -10886,8 +10820,13 @@ static struct redisplay_interface x_redisplay_interface = 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, @@ -10941,7 +10880,6 @@ mac_initialize () BLOCK_INPUT; #if TARGET_API_MAC_CARBON - init_required_apple_events (); #if USE_CARBON_EVENTS #ifdef MAC_OSX @@ -10956,10 +10894,19 @@ mac_initialize () #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; } @@ -10972,23 +10919,28 @@ syms_of_macterm () 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); @@ -10997,9 +10949,6 @@ syms_of_macterm () 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; @@ -11014,6 +10963,18 @@ syms_of_macterm () 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 @@ -11025,70 +10986,83 @@ syms_of_macterm () 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);