X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/70ed951a16197310141ff44a36390354f4c504fe..daf9e22086135d98f34bf25f32a3405192a8a0d9:/src/macterm.c diff --git a/src/macterm.c b/src/macterm.c index 5fd80b7387..b78c01e129 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" @@ -259,7 +258,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. */ @@ -268,14 +267,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 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; @@ -284,19 +353,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); } @@ -320,14 +389,27 @@ mac_draw_line (f, gc, x1, y1, x2, y2) GC gc; int x1, y1, x2, y2; { +#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 @@ -361,6 +443,14 @@ mac_erase_rectangle (f, gc, x, y, width, height) 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 (FRAME_MAC_WINDOW (f)); @@ -368,11 +458,12 @@ mac_erase_rectangle (f, gc, x, y, width, height) 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 (FRAME_NORMAL_GC (f))); +#endif } @@ -393,6 +484,16 @@ static void mac_clear_window (f) struct frame *f; { +#if USE_CG_DRAWING + CGContextRef context; + GC gc = FRAME_NORMAL_GC (f); + + context = mac_begin_cg_clip (f, NULL); + CG_SET_FILL_COLOR (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))); @@ -407,11 +508,50 @@ mac_clear_window (f) #else /* not TARGET_API_MAC_CARBON */ EraseRect (&(FRAME_MAC_WINDOW (f)->portRect)); #endif /* not TARGET_API_MAC_CARBON */ +#endif } /* Mac replacement for XCopyArea. */ +#if USE_CG_DRAWING +static void +mac_draw_cg_image (image, f, gc, src_x, src_y, width, height, + dest_x, dest_y, overlay_p) + CGImageRef image; + struct frame *f; + GC gc; + int src_x, src_y; + unsigned int width, height; + int dest_x, dest_y, overlay_p; +{ + CGContextRef context; + 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; @@ -433,7 +573,7 @@ mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p) 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 { CGrafPtr port; @@ -448,10 +588,11 @@ mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p) 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 (FRAME_NORMAL_GC (f))); } +#endif /* !USE_CG_DRAWING */ /* Mac replacement for XCreateBitmapFromBitmapData. */ @@ -512,7 +653,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; @@ -573,6 +722,14 @@ mac_fill_rectangle (f, gc, x, y, width, height) 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.foreground); + CGContextFillRect (context, CGRectMake (x, y, width, height)); + mac_end_cg_clip (f); +#else Rect r; SetPortWindowPort (FRAME_MAC_WINDOW (f)); @@ -580,9 +737,10 @@ mac_fill_rectangle (f, gc, x, y, width, height) RGBForeColor (GC_FORE_COLOR (gc)); SetRect (&r, x, y, x + width, y + height); - mac_begin_clip (GC_CLIP_REGION (gc)); + mac_begin_clip (gc); PaintRect (&r); /* using foreground color of gc */ - mac_end_clip (GC_CLIP_REGION (gc)); + mac_end_clip (gc); +#endif } @@ -595,6 +753,15 @@ mac_draw_rectangle (f, gc, x, y, width, height) int x, y; unsigned int width, height; { +#if USE_CG_DRAWING + CGContextRef context; + + 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; SetPortWindowPort (FRAME_MAC_WINDOW (f)); @@ -602,9 +769,10 @@ mac_draw_rectangle (f, gc, x, y, width, height) RGBForeColor (GC_FORE_COLOR (gc)); SetRect (&r, x, y, x + width + 1, y + height + 1); - mac_begin_clip (GC_CLIP_REGION (gc)); + mac_begin_clip (gc); FrameRect (&r); /* using foreground color of gc */ - mac_end_clip (GC_CLIP_REGION (gc)); + mac_end_clip (gc); +#endif } @@ -627,6 +795,7 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout) static ATSLineLayoutOptions line_layout = #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics + | kATSLineUseQDRendering #else kATSLineIsDisplayOnly | kATSLineFractDisable #endif @@ -673,6 +842,9 @@ mac_invert_rectangle (f, x, y, width, height) { Rect r; +#if USE_CG_DRAWING + mac_prepare_for_quickdraw (f); +#endif SetPortWindowPort (FRAME_MAC_WINDOW (f)); SetRect (&r, x, y, x + width, y + height); @@ -682,27 +854,15 @@ mac_invert_rectangle (f, x, y, width, height) static void -mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char) +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 (mac_use_core_graphics) { - textFlags = kQDUseCGTextRendering; - savedFlags = SwapQDTextFlags(textFlags); - } -#endif - SetPortWindowPort (FRAME_MAC_WINDOW (f)); - RGBForeColor (GC_FORE_COLOR (gc)); - if (mode != srcOr) - RGBBackColor (GC_BACK_COLOR (gc)); - #if USE_ATSUI if (GC_FONT (gc)->mac_style) { @@ -724,91 +884,151 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char) nchars, GC_FONT (gc)->mac_style, &text_layout); - if (err == noErr) - { + if (err != noErr) + return; #ifdef MAC_OSX - if (!mac_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; - float port_height = FRAME_PIXEL_HEIGHT (f); - ATSUAttributeTag tags[] = {kATSUCGContextTag}; - ByteCount sizes[] = {sizeof (CGContextRef)}; - ATSUAttributeValuePtr values[] = {&context}; - - GetPort (&port); - QDBeginCGContext (port, &context); + 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)); - CGContextSynchronize (context); - QDEndCGContext (port, &context); -#if 0 - /* This doesn't work on Mac OS X 10.1. */ - ATSUClearLayoutControls (text_layout, + 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); + 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 - ATSUSetLayoutControls (text_layout, - sizeof (tags) / sizeof (tags[0]), - tags, sizes, values); + 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 (FRAME_NORMAL_GC (f))); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 - if (mac_use_core_graphics) - SwapQDTextFlags(savedFlags); + if (mac_use_core_graphics) + SwapQDTextFlags(savedFlags); #endif + } } @@ -822,7 +1042,7 @@ mac_draw_string (f, gc, x, y, buf, nchars) char *buf; int nchars; { - mac_draw_string_common (f, gc, x, y, buf, nchars, srcOr, 1); + mac_draw_string_common (f, gc, x, y, buf, nchars, 0, 1); } @@ -836,61 +1056,214 @@ mac_draw_string_16 (f, gc, x, y, buf, nchars) XChar2b *buf; int nchars; { - mac_draw_string_common (f, 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 -mac_draw_image_string (f, gc, x, y, buf, nchars) +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 (f, 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 -mac_draw_image_string_16 (f, gc, x, y, buf, nchars) +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; + int nchars, bg_width; { - mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, srcCopy, 2); + 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 -static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *)); + 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 () { - Lisp_Object val = - Fmac_get_preference (build_string ("AppleAntiAliasingThreshold"), - Qnil, Qnil, Qnil); + int threshold; + Boolean valid_p; - if (INTEGERP (val)) - cg_text_anti_aliasing_threshold = XINT (val); + threshold = + CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"), + kCFPreferencesCurrentApplication, + &valid_p); + if (valid_p) + cg_text_anti_aliasing_threshold = threshold; } static int -mac_draw_string_cg (f, gc, x, y, buf, nchars) +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; + int nchars, bg_width; { CGrafPtr port; float port_height, gx, gy; @@ -907,29 +1280,44 @@ mac_draw_string_cg (f, gc, x, y, buf, nchars) gx = x; gy = port_height - y; glyphs = (CGGlyph *)buf; - advances = xmalloc (sizeof (CGSize) * nchars); + advances = alloca (sizeof (CGSize) * nchars); + if (advances == NULL) + return 0; for (i = 0; i < nchars; i++) { - advances[i].width = x_per_char_metric (GC_FONT (gc), buf)->width; + 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) + if (gc->n_clip_rects || bg_width) { CGContextTranslateCTM (context, 0, port_height); CGContextScaleCTM (context, 1, -1); - CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects); + 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 } - 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); +#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) @@ -944,16 +1332,19 @@ mac_draw_string_cg (f, gc, x, y, buf, nchars) gx += advances[i].width; } #endif +#if USE_CG_DRAWING + mac_end_cg_clip (f); +#else CGContextSynchronize (context); QDEndCGContext (port, &context); - - xfree (advances); +#endif return 1; } #endif +#if !USE_CG_DRAWING /* Mac replacement for XCopyArea: dest must be window. */ static void @@ -975,7 +1366,7 @@ mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y) ForeColor (blackColor); BackColor (whiteColor); - mac_begin_clip (GC_CLIP_REGION (gc)); + mac_begin_clip (gc); LockPixels (GetGWorldPixMap (src)); #if TARGET_API_MAC_CARBON { @@ -993,7 +1384,7 @@ mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y) &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 (FRAME_NORMAL_GC (f))); } @@ -1019,7 +1410,7 @@ mac_copy_area_with_mask (src, mask, f, 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 @@ -1039,10 +1430,11 @@ mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y, #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 (FRAME_NORMAL_GC (f))); } +#endif /* !USE_CG_DRAWING */ /* Mac replacement for XCopyArea: used only for scrolling. */ @@ -1060,6 +1452,9 @@ mac_scroll_area (f, 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); +#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); @@ -1077,9 +1472,9 @@ mac_scroll_area (f, 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)); + mac_end_clip (gc); RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); #endif /* not TARGET_API_MAC_CARBON */ @@ -1215,17 +1610,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 (); @@ -1243,8 +1631,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; @@ -1264,7 +1650,7 @@ mac_reset_clip_rectangles (display, gc) Display *display; GC gc; { - mac_set_clip_rectangles (display, gc, NULL, 0); + gc->n_clip_rects = 0; } @@ -1327,6 +1713,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 @@ -1657,9 +2046,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); @@ -1668,14 +2060,64 @@ x_draw_fringe_bitmap (w, row, p) ? (p->overlay_p ? face->background : f->output_data.mac->cursor_pixel) : face->foreground)); +#if USE_CG_DRAWING + mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh, + p->wd, p->h, p->x, p->y, p->overlay_p); +#else mac_draw_bitmap (f, face->gc, p->x, p->y, - p->wd, p->h, bits, p->overlay_p); + p->wd, p->h, p->bits + p->dh, p->overlay_p); +#endif XSetForeground (display, face->gc, gcv.foreground); } 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; +{ + unsigned short *mask_bits; + 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 @@ -1724,63 +2166,32 @@ 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)); + if (*row) + bzero (*row, sizeof (XCharStructRow)); } - - if (pcm && !pcm->valid_p) + if (*row) { - 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, -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 - kATSUseFractionalOrigins, -#else - kATSUseDeviceOrigins, -#endif - 1, &glyph_bounds, NULL); - UNBLOCK_INPUT; - if (err != noErr) - pcm = NULL; - else + pcm = (*row)->per_char + char2b->byte2; + if (!XCHARSTRUCTROW_CHAR_VALID_P (*row, char2b->byte2)) { - 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); + BLOCK_INPUT; + mac_query_char_extents (font->mac_style, + (char2b->byte1 << 8) + char2b->byte2, + NULL, NULL, pcm, NULL); + UNBLOCK_INPUT; + 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) { @@ -1793,7 +2204,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 { @@ -1815,7 +2227,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)); @@ -2157,67 +2569,32 @@ mac_compute_glyph_string_overhangs (s) { if (s->cmp == NULL && s->first_glyph->type == CHAR_GLYPH) - { - Rect r; - MacFontStruct *font = s->font; - + 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); + 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 - s->right_overhang = r.right > s->width ? r.right - s->width : 0; - s->left_overhang = r.left < 0 ? -r.left : 0; - } + s->right_overhang = r.right > s->width ? r.right - s->width : 0; + s->left_overhang = r.left < 0 ? -r.left : 0; + } } @@ -2232,14 +2609,6 @@ x_clear_glyph_string_rect (s, 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 @@ -2271,12 +2640,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, @@ -2293,7 +2660,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. */ @@ -2332,7 +2699,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 @@ -2340,38 +2706,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 - ) + ) #if USE_CG_TEXT_DRAWING - if (!s->two_byte_p - && mac_draw_string_cg (s->f, s->gc, x, s->ybase - boff, - s->char2b, s->nchars)) - ; - else + 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_string_16 (s->f, s->gc, x, s->ybase - boff, - s->char2b, s->nchars); - else - mac_draw_string (s->f, s->gc, x, s->ybase - boff, - char1b, s->nchars); - } -#if defined (MAC_OS8) && !USE_ATSUI + mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff, + s->char2b, s->nchars, bg_width); else - { - if (s->two_byte_p) - mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff, - s->char2b, s->nchars); - else - mac_draw_image_string (s->f, s->gc, x, s->ybase - boff, - char1b, s->nchars); - } -#endif + mac_draw_image_string (s->f, s->gc, x, s->ybase - boff, + char1b, s->nchars, bg_width); } } @@ -2934,15 +3289,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) +#if !USE_CG_DRAWING mac_copy_area_with_mask (s->img->pixmap, s->img->mask, s->f, s->gc, s->slice.x, s->slice.y, s->slice.width, s->slice.height, x, y); +#else + ; +#endif else { +#if !USE_CG_DRAWING mac_copy_area (s->img->pixmap, s->f, s->gc, s->slice.x, s->slice.y, s->slice.width, s->slice.height, x, y); +#endif /* When the image has a mask, we can expect that at least part of a mouse highlight or a block cursor will @@ -4152,8 +4518,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 *)); @@ -4274,7 +4640,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; @@ -4416,10 +4782,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 { @@ -4430,10 +4798,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; } @@ -4469,8 +4846,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, @@ -4590,6 +4975,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)); @@ -4640,6 +5028,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; @@ -4653,6 +5042,7 @@ 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)) @@ -4684,12 +5074,17 @@ XTset_vertical_scroll_bar (w, portion, whole, position) for them on the frame, we have to clear "under" them. */ mac_clear_area (f, left, top, width, height); +#if USE_CG_DRAWING + mac_prepare_for_quickdraw (f); +#endif HideControl (ch); MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top); SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, disp_height); +#ifndef USE_TOOLKIT_SCROLL_BARS if (sb_width < disp_height) ShowControl (ch); +#endif /* Remember new settings. */ XSETINT (bar->left, sb_left); @@ -4707,30 +5102,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); #else /* not USE_TOOLKIT_SCROLL_BARS */ @@ -5115,7 +5521,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 (f, gc, x, y, wd, h); + mac_draw_rectangle (f, gc, x, y, wd, h - 1); mac_reset_clip_rectangles (dpy, gc); } @@ -5212,7 +5618,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); } @@ -5639,8 +6048,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, @@ -5750,7 +6164,7 @@ x_raise_frame (f) if (f->async_visible) { BLOCK_INPUT; - SelectWindow (FRAME_MAC_WINDOW (f)); + BringToFront (FRAME_MAC_WINDOW (f)); UNBLOCK_INPUT; } } @@ -5764,7 +6178,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; } } @@ -5877,7 +6291,6 @@ x_make_frame_visible (f) f->output_data.mac->asked_for_visible = 1; - SelectWindow (FRAME_MAC_WINDOW (f)); CollapseWindow (FRAME_MAC_WINDOW (f), false); ShowWindow (FRAME_MAC_WINDOW (f)); } @@ -7375,7 +7788,7 @@ 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; @@ -7392,6 +7805,7 @@ XLoadQueryFont (Display *dpy, char *fontname) short scriptcode; #endif MacFontStruct *font; + XCharStruct *space_bounds = NULL, *pcm; if (is_fully_specified_xlfd (fontname)) name = fontname; @@ -7420,8 +7834,10 @@ XLoadQueryFont (Display *dpy, char *fontname) 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)), @@ -7488,19 +7904,27 @@ 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->per_char = xmalloc (sizeof (XCharStruct) * 0x10000); - if (font->per_char == NULL) + 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); + if (font->bounds.rows == NULL) { mac_unload_font (&one_mac_display_info, font); return NULL; } - bzero (font->per_char, sizeof (XCharStruct) * 0x10000); + bzero (font->bounds.rows, sizeof (XCharStructRow *) * 0x100); + font->bounds.rows[0] = xmalloc (sizeof (XCharStructRow)); + if (font->bounds.rows[0] == NULL) + { + mac_unload_font (&one_mac_display_info, font); + return NULL; + } + bzero (font->bounds.rows[0], sizeof (XCharStructRow)); #if USE_CG_TEXT_DRAWING { @@ -7525,108 +7949,58 @@ XLoadQueryFont (Display *dpy, char *fontname) if (font->cg_glyphs) bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100); #endif - - err = atsu_get_text_layout_with_text_ptr (&c, 1, - font->mac_style, - &text_layout); + 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 <= 0xff; c++) + pcm = font->bounds.rows[0]->per_char; + for (c = 0x21; c <= 0xff; c++) { if (c == 0xad) /* Soft hyphen is not supported in ATSUI. */ continue; else if (c == 0x7f) { - STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); - STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); c = 0x9f; continue; } - 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, -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 - kATSUseFractionalOrigins, + 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 - kATSUseDeviceOrigins, + NULL #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); + ); + XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], c); - 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); - } - } - } #if USE_CG_TEXT_DRAWING - if (err == noErr && char_width > 0 && font->cg_font) + if (font->cg_glyphs && font->cg_glyphs[c] == 0) { - ATSUGlyphInfoArray glyph_info_array; - ByteCount count = sizeof (ATSUGlyphInfoArray); - - err = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning, - kATSUToTextEnd, NULL, NULL, NULL); - if (err == noErr) - err = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning, - kATSUToTextEnd, &count, - &glyph_info_array); - if (err == noErr) - font->cg_glyphs[c] = glyph_info_array.glyphs[0].glyphID; - else - { - /* 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; - } + /* 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 } - - font->min_byte1 = 0; - font->max_byte1 = 0xff; - font->min_char_or_byte2 = 0; - font->max_char_or_byte2 = 0xff; } else #endif @@ -7665,6 +8039,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; @@ -7693,21 +8069,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; @@ -7722,54 +8085,28 @@ XLoadQueryFont (Display *dpy, char *fontname) } else { - int c, min_width, max_width; - Rect char_bounds, min_bounds, max_bounds; - char ch; + int c; - font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); - bzero (font->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++) - { - if (c == 0x7f) - { - STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); - STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); - continue; - } + font->min_byte1 = font->max_byte1 = 0; + font->min_char_or_byte2 = 0x20; + font->max_char_or_byte2 = 0xff; - 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); - } - } - if (min_width == max_width - && max_bounds.left >= 0 && max_bounds.right <= max_width) + font->bounds.per_char = + xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); + if (font->bounds.per_char == NULL) { - /* Fixed width and no overhangs. */ - xfree (font->per_char); - font->per_char = NULL; + mac_unload_font (&one_mac_display_info, font); + return NULL; } + bzero (font->bounds.per_char, + sizeof (XCharStruct) * (0xff - 0x20 + 1)); + + 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. */ @@ -7778,12 +8115,56 @@ 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 - the XDrawImageString counterpart is never used. */ - if (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0 - || strcmp (family, "times") == 0) + 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 @@ -7797,17 +8178,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 #endif xfree (font); } @@ -8143,6 +8533,7 @@ 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 */ @@ -8285,6 +8676,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) @@ -8318,13 +8710,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; @@ -8340,7 +8738,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); @@ -8750,8 +9148,7 @@ mac_handle_command_event (next_handler, event, data) EventRef event; void *data; { - OSStatus result; - OSErr err; + OSStatus result, err; HICommand command; Lisp_Object class_key, id_key, binding; @@ -8759,10 +9156,10 @@ mac_handle_command_event (next_handler, event, data) if (result != eventNotHandledErr) return result; - GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL, - sizeof (HICommand), NULL, &command); + err = GetEventParameter (event, kEventParamDirectObject, typeHICommand, + NULL, sizeof (HICommand), NULL, &command); - if (command.commandID == 0) + if (err != noErr || command.commandID == 0) return eventNotHandledErr; /* A HICommand event is mapped to an Apple event whose event class @@ -8816,12 +9213,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)) { @@ -8838,8 +9237,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)) @@ -8848,9 +9250,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; @@ -8899,7 +9304,7 @@ mac_handle_mouse_event (next_handler, event, data) EventRef event; void *data; { - OSStatus result; + OSStatus result, err; switch (GetEventKind (event)) { @@ -8915,22 +9320,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 = @@ -9149,25 +9563,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 @@ -9259,6 +9673,8 @@ main (void) init_environ (); + init_coercion_handler (); + initialize_applescript (); init_apple_event_handler (); @@ -9390,13 +9806,13 @@ convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode) Fn modifier. That's why we need the table. */ - + OSStatus err; UInt32 mods = 0; if (!NILP(Vmac_function_modifier)) { - GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL, - sizeof (UInt32), NULL, &mods); - if (mods & kEventKeyModifierFnMask) + 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); @@ -9518,10 +9934,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)) @@ -10158,6 +10580,7 @@ XTread_socket (sd, expected, hold_quit) } #endif + --handling_signal; UNBLOCK_INPUT; return count; } @@ -10578,8 +11001,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, @@ -10647,12 +11075,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; } @@ -10795,7 +11230,7 @@ button will be mouse-3. */); doc: /* *If non-nil, allow anti-aliasing. The text will be rendered using Core Graphics text rendering which may anti-alias the text. */); - mac_use_core_graphics = 1; + 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