X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/ee7683ebb70c308e596103e379ef6b91d001eebc..d3d50620ed3a8066c15ae3d3701b83371ca5382a:/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m index b02561442e..4d3a138725 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1,6 +1,7 @@ /* NeXT/Open/GNUstep / MacOSX communication module. - Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2011 - Free Software Foundation, Inc. + +Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2012 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -35,6 +36,8 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include #include #include +#include +#include #include "lisp.h" #include "blockinput.h" @@ -52,7 +55,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include "window.h" #include "keyboard.h" - +#include "buffer.h" #include "font.h" /* call tracing */ @@ -64,6 +67,7 @@ int term_trace_num = 0; #define NSTRACE(x) #endif +extern NSString *NSMenuDidBeginTrackingNotification; /* ========================================================================== @@ -165,7 +169,9 @@ static EmacsScroller *last_mouse_scroll_bar = nil; static struct frame *ns_updating_frame; static NSView *focus_view = NULL; static int ns_window_num = 0; +#ifdef NS_IMPL_GNUSTEP static NSRect uRect; +#endif static BOOL gsaved = NO; BOOL ns_in_resize = NO; static BOOL ns_fake_keydown = NO; @@ -181,7 +187,6 @@ static NSTimer *timed_entry = 0; static NSTimer *fd_entry = nil; static NSTimer *scroll_repeat_entry = nil; static fd_set select_readfds, t_readfds; -static struct timeval select_timeout; static int select_nfds; static NSAutoreleasePool *outerpool; static struct input_event *emacs_event = NULL; @@ -190,6 +195,7 @@ static int n_emacs_events_pending = 0; static NSMutableArray *ns_pending_files, *ns_pending_service_names, *ns_pending_service_args; static BOOL inNsSelect = 0; +static BOOL ns_do_open_file = NO; /* Convert modifiers in a NeXTstep event to emacs style modifiers. */ #define NS_FUNCTION_KEY_MASK 0x800000 @@ -284,24 +290,51 @@ append2 (Lisp_Object list, Lisp_Object item) } -void -ns_init_paths (void) -/* -------------------------------------------------------------------------- - Used to allow emacs to find its resources under Emacs.app - Called from emacs.c at startup. - -------------------------------------------------------------------------- */ +const char * +ns_etc_directory (void) +/* If running as a self-contained app bundle, return as a string the + filename of the etc directory, if present; else nil. */ { NSBundle *bundle = [NSBundle mainBundle]; - NSString *binDir = [bundle bundlePath], *resourceDir = [bundle resourcePath]; + NSString *resourceDir = [bundle resourcePath]; + NSString *resourcePath; + NSFileManager *fileManager = [NSFileManager defaultManager]; + BOOL isDir; + + resourcePath = [resourceDir stringByAppendingPathComponent: @"etc"]; + if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) + { + if (isDir) return [resourcePath UTF8String]; + } + return NULL; +} + + +const char * +ns_exec_path (void) +/* If running as a self-contained app bundle, return as a path string + the filenames of the libexec and bin directories, ie libexec:bin. + Otherwise, return nil. + Normally, Emacs does not add its own bin/ directory to the PATH. + However, a self-contained NS build has a different layout, with + bin/ and libexec/ subdirectories in the directory that contains + Emacs.app itself. + We put libexec first, because init_callproc_1 uses the first + element to initialize exec-directory. An alternative would be + for init_callproc to check for invocation-directory/libexec. +*/ +{ + NSBundle *bundle = [NSBundle mainBundle]; + NSString *resourceDir = [bundle resourcePath]; + NSString *binDir = [bundle bundlePath]; NSString *resourcePath, *resourcePaths; NSRange range; - BOOL onWindows = NO; /* how do I determine this? */ - NSString *pathSeparator = onWindows ? @";" : @":"; + NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR]; NSFileManager *fileManager = [NSFileManager defaultManager]; + NSArray *paths; + NSEnumerator *pathEnum; BOOL isDir; -/*NSLog (@"ns_init_paths: '%@'\n%@\n", [[NSBundle mainBundle] bundlePath], [[NSBundle mainBundle] resourcePath]); */ - /* get bindir from base */ range = [resourceDir rangeOfString: @"Contents"]; if (range.location != NSNotFound) { @@ -311,107 +344,65 @@ ns_init_paths (void) #endif } - /* the following based on Andrew Choi's init_mac_osx_environment () */ - if (!getenv ("EMACSLOADPATH")) - { - NSArray *paths = [resourceDir stringsByAppendingPaths: - [NSArray arrayWithObjects: - @"site-lisp", @"lisp", @"leim", nil]]; - NSEnumerator *pathEnum = [paths objectEnumerator]; - resourcePaths = @""; - while (resourcePath = [pathEnum nextObject]) - { - if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) - if (isDir) - { - if ([resourcePaths length] > 0) - resourcePaths - = [resourcePaths stringByAppendingString: pathSeparator]; - resourcePaths - = [resourcePaths stringByAppendingString: resourcePath]; - } - } - if ([resourcePaths length] > 0) - setenv ("EMACSLOADPATH", [resourcePaths UTF8String], 1); -/*NSLog (@"loadPath: '%@'\n", resourcePaths); */ - } - - if (!getenv ("EMACSPATH")) - { - NSArray *paths = [binDir stringsByAppendingPaths: - [NSArray arrayWithObjects: @"bin", - @"lib-exec", nil]]; - NSEnumerator *pathEnum = [paths objectEnumerator]; - resourcePaths = @""; - while (resourcePath = [pathEnum nextObject]) - { - if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) - if (isDir) - { - if ([resourcePaths length] > 0) - resourcePaths - = [resourcePaths stringByAppendingString: pathSeparator]; - resourcePaths - = [resourcePaths stringByAppendingString: resourcePath]; - } - } - if ([resourcePaths length] > 0) - setenv ("EMACSPATH", [resourcePaths UTF8String], 1); - } + paths = [binDir stringsByAppendingPaths: + [NSArray arrayWithObjects: @"libexec", @"bin", nil]]; + pathEnum = [paths objectEnumerator]; + resourcePaths = @""; - resourcePath = [resourceDir stringByAppendingPathComponent: @"etc"]; - if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) + while ((resourcePath = [pathEnum nextObject])) { - if (isDir) - { - if (!getenv ("EMACSDATA")) - setenv ("EMACSDATA", [resourcePath UTF8String], 1); - if (!getenv ("EMACSDOC")) - setenv ("EMACSDOC", [resourcePath UTF8String], 1); - } - } - - if (!getenv ("INFOPATH")) - { - resourcePath = [resourceDir stringByAppendingPathComponent: @"info"]; if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) if (isDir) - setenv ("INFOPATH", [[resourcePath stringByAppendingString: @":"] - UTF8String], 1); - /* Note, extra colon needed to cause merge w/later user additions. */ + { + if ([resourcePaths length] > 0) + resourcePaths + = [resourcePaths stringByAppendingString: pathSeparator]; + resourcePaths + = [resourcePaths stringByAppendingString: resourcePath]; + } } + if ([resourcePaths length] > 0) return [resourcePaths UTF8String]; + + return NULL; } -static int -timeval_subtract (struct timeval *result, struct timeval x, struct timeval y) -/* -------------------------------------------------------------------------- - Subtract the `struct timeval' values X and Y, storing the result in RESULT. - Return 1 if the difference is negative, otherwise 0. - -------------------------------------------------------------------------- */ +const char * +ns_load_path (void) +/* If running as a self-contained app bundle, return as a path string + the filenames of the site-lisp, lisp and leim directories. + Ie, site-lisp:lisp:leim. Otherwise, return nil. */ { - /* Perform the carry for the later subtraction by updating y. - This is safer because on some systems - the tv_sec member is unsigned. */ - if (x.tv_usec < y.tv_usec) - { - int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; - y.tv_usec -= 1000000 * nsec; - y.tv_sec += nsec; - } - if (x.tv_usec - y.tv_usec > 1000000) + NSBundle *bundle = [NSBundle mainBundle]; + NSString *resourceDir = [bundle resourcePath]; + NSString *resourcePath, *resourcePaths; + NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + BOOL isDir; + NSArray *paths = [resourceDir stringsByAppendingPaths: + [NSArray arrayWithObjects: + @"site-lisp", @"lisp", @"leim", nil]]; + NSEnumerator *pathEnum = [paths objectEnumerator]; + resourcePaths = @""; + + /* Hack to skip site-lisp. */ + if (no_site_lisp) resourcePath = [pathEnum nextObject]; + + while ((resourcePath = [pathEnum nextObject])) { - int nsec = (y.tv_usec - x.tv_usec) / 1000000; - y.tv_usec += 1000000 * nsec; - y.tv_sec -= nsec; + if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) + if (isDir) + { + if ([resourcePaths length] > 0) + resourcePaths + = [resourcePaths stringByAppendingString: pathSeparator]; + resourcePaths + = [resourcePaths stringByAppendingString: resourcePath]; + } } + if ([resourcePaths length] > 0) return [resourcePaths UTF8String]; - /* Compute the time remaining to wait. tv_usec is certainly positive. */ - result->tv_sec = x.tv_sec - y.tv_sec; - result->tv_usec = x.tv_usec - y.tv_usec; - - /* Return indication of whether the result should be considered negative. */ - return x.tv_sec < y.tv_sec; + return NULL; } static void @@ -420,29 +411,19 @@ ns_timeout (int usecs) Blocking timer utility used by ns_ring_bell -------------------------------------------------------------------------- */ { - struct timeval wakeup; - - EMACS_GET_TIME (wakeup); - - /* Compute time to wait until, propagating carry from usecs. */ - wakeup.tv_usec += usecs; - wakeup.tv_sec += (wakeup.tv_usec / 1000000); - wakeup.tv_usec %= 1000000; + EMACS_TIME wakeup = add_emacs_time (current_emacs_time (), + make_emacs_time (0, usecs * 1000)); /* Keep waiting until past the time wakeup. */ while (1) { - struct timeval timeout; - - EMACS_GET_TIME (timeout); - - /* In effect, timeout = wakeup - timeout. - Break if result would be negative. */ - if (timeval_subtract (&timeout, wakeup, timeout)) + EMACS_TIME timeout, now = current_emacs_time (); + if (EMACS_TIME_LE (wakeup, now)) break; + timeout = sub_emacs_time (wakeup, now); /* Try to wait that long--but we might wake up sooner. */ - select (0, NULL, NULL, NULL, &timeout); + pselect (0, NULL, NULL, NULL, &timeout, NULL); } } @@ -559,7 +540,7 @@ ns_constrain_all_frames (void) { NSView *view = FRAME_NS_VIEW (f); /* This no-op will trigger the default window placing - * constriant system. */ + * constraint system. */ f->output_data.ns->dont_constrain = 0; [[view window] setFrameOrigin:[[view window] frame].origin]; } @@ -1037,7 +1018,7 @@ ns_frame_rehighlight (struct frame *frame) : dpyinfo->x_focus_frame); if (!FRAME_LIVE_P (dpyinfo->x_highlight_frame)) { - FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil; + FSET (dpyinfo->x_focus_frame, focus_frame, Qnil); dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame; } } @@ -1131,7 +1112,7 @@ x_free_frame_resources (struct frame *f) NSView *view = FRAME_NS_VIEW (f); struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f); Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - NSTRACE (x_destroy_window); + NSTRACE (x_free_frame_resources); check_ns (); [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */ @@ -1156,11 +1137,14 @@ x_free_frame_resources (struct frame *f) hlinfo->mouse_face_mouse_frame = 0; } - xfree (f->output_data.ns); + if (f->output_data.ns->miniimage != nil) + [f->output_data.ns->miniimage release]; [[view window] close]; [view release]; + xfree (f->output_data.ns); + UNBLOCK_INPUT; } @@ -1235,7 +1219,6 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) -------------------------------------------------------------------------- */ { EmacsView *view = FRAME_NS_VIEW (f); - EmacsToolbar *toolbar = [view toolbar]; NSWindow *window = [view window]; NSRect wr = [window frame]; int tb = FRAME_EXTERNAL_TOOL_BAR (f); @@ -1351,34 +1334,25 @@ ns_index_color (NSColor *color, struct frame *f) { struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table; ptrdiff_t idx; - NSNumber *index; + ptrdiff_t i; if (!color_table->colors) { color_table->size = NS_COLOR_CAPACITY; color_table->avail = 1; /* skip idx=0 as marker */ - color_table->colors - = (NSColor **)xmalloc (color_table->size * sizeof (NSColor *)); + color_table->colors = xmalloc (color_table->size * sizeof (NSColor *)); color_table->colors[0] = nil; color_table->empty_indices = [[NSMutableSet alloc] init]; } /* do we already have this color ? */ - { - ptrdiff_t i; - for (i = 1; i < color_table->avail; i++) - { - if (color_table->colors[i] && [color_table->colors[i] isEqual: color]) - { - [color_table->colors[i] retain]; - return i; - } - } - } + for (i = 1; i < color_table->avail; i++) + if (color_table->colors[i] && [color_table->colors[i] isEqual: color]) + return i; if ([color_table->empty_indices count] > 0) { - index = [color_table->empty_indices anyObject]; + NSNumber *index = [color_table->empty_indices anyObject]; [color_table->empty_indices removeObject: index]; idx = [index unsignedLongValue]; } @@ -1411,20 +1385,20 @@ ns_free_indexed_color (unsigned long idx, struct frame *f) color_table = FRAME_NS_DISPLAY_INFO (f)->color_table; if (idx <= 0 || idx >= color_table->size) { - message1("ns_free_indexed_color: Color index out of range.\n"); + message1 ("ns_free_indexed_color: Color index out of range.\n"); return; } index = [NSNumber numberWithUnsignedInt: idx]; if ([color_table->empty_indices containsObject: index]) { - message1("ns_free_indexed_color: attempt to free already freed color.\n"); + message1 ("ns_free_indexed_color: attempt to free already freed color.\n"); return; } color = color_table->colors[idx]; [color release]; color_table->colors[idx] = nil; - [color_table->empty_indices addObject: [NSNumber numberWithUnsignedInt: idx]]; + [color_table->empty_indices addObject: index]; /*fprintf(stderr, "color_table: FREED %d\n",idx);*/ } @@ -1464,21 +1438,16 @@ ns_get_color (const char *name, NSColor **col) [scanner scanFloat: &b]; } else if (!strncmp(name, "rgb:", 4)) /* A newer X11 format -- rgb:r/g/b */ - { - strncpy (hex, name + 4, 19); - hex[19] = '\0'; - scaling = (strlen(hex) - 2) / 3; - } + scaling = (snprintf (hex, sizeof hex, "%s", name + 4) - 2) / 3; else if (name[0] == '#') /* An old X11 format; convert to newer */ { int len = (strlen(name) - 1); int start = (len % 3 == 0) ? 1 : len / 4 + 1; int i; scaling = strlen(name+start) / 3; - for (i=0; i<3; i++) { - strncpy(hex + i * (scaling + 1), name + start + i * scaling, scaling); - hex[(i+1) * (scaling + 1) - 1] = '/'; - } + for (i = 0; i < 3; i++) + sprintf (hex + i * (scaling + 1), "%.*s/", scaling, + name + start + i * scaling); hex[3 * (scaling + 1) - 1] = '\0'; } @@ -1534,21 +1503,6 @@ ns_get_color (const char *name, NSColor **col) } -static NSColor * -ns_get_color_default (const char *name, NSColor *dflt) -/* -------------------------------------------------------------------------- - Parse a color or use a default value - -------------------------------------------------------------------------- */ -{ - NSColor * col; - - if (ns_get_color (name, &col)) - return dflt; - else - return col; -} - - int ns_lisp_to_color (Lisp_Object color, NSColor **col) /* -------------------------------------------------------------------------- @@ -1557,9 +1511,9 @@ ns_lisp_to_color (Lisp_Object color, NSColor **col) { NSTRACE (ns_lisp_to_color); if (STRINGP (color)) - return ns_get_color (SDATA (color), col); + return ns_get_color (SSDATA (color), col); else if (SYMBOLP (color)) - return ns_get_color (SDATA (SYMBOL_NAME (color)), col); + return ns_get_color (SSDATA (SYMBOL_NAME (color)), col); return 1; } @@ -1804,7 +1758,6 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, { id view; NSPoint position; - int xchar, ychar; Lisp_Object frame, tail; struct frame *f; struct ns_display_info *dpyinfo; @@ -1898,7 +1851,7 @@ ns_frame_up_to_date (struct frame *f) } -void +static void ns_define_frame_cursor (struct frame *f, Cursor cursor) /* -------------------------------------------------------------------------- External (RIF): set frame mouse pointer type. @@ -2023,7 +1976,7 @@ ns_clear_frame (struct frame *f) } -void +static void ns_clear_frame_area (struct frame *f, int x, int y, int width, int height) /* -------------------------------------------------------------------------- External (RIF): Clear section of frame @@ -2108,7 +2061,7 @@ ns_scroll_run (struct window *w, struct run *run) } else { - /* Scolling down. Make sure we don't copy over the mode line. + /* Scrolling down. Make sure we don't copy over the mode line. at the bottom. */ if (to_y + run->height > bottom_y) height = bottom_y - to_y; @@ -2152,7 +2105,7 @@ ns_after_update_window_line (struct glyph_row *desired_row) NSTRACE (ns_after_update_window_line); /* begin copy from other terms */ - xassert (w); + eassert (w); if (!desired_row->mode_line_p && !w->pseudo_window_p) desired_row->redraw_fringe_bitmaps_p = 1; @@ -2226,8 +2179,7 @@ ns_compute_glyph_string_overhangs (struct glyph_string *s) External (RIF); compute left/right overhang of whole string and set in s -------------------------------------------------------------------------- */ { - struct face *face = FACE_FROM_ID (s->f, s->first_glyph->face_id); - struct font *font = s->font; /*face->font; */ + struct font *font = s->font; if (s->char2b) { @@ -2287,17 +2239,9 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, /* grow bimgs if needed */ if (nBimgs < max_used_fringe_bitmap) { - EmacsImage **newBimgs - = xmalloc (max_used_fringe_bitmap * sizeof (EmacsImage *)); - memset (newBimgs, 0, max_used_fringe_bitmap * sizeof (EmacsImage *)); - - if (nBimgs) - { - memcpy (newBimgs, bimgs, nBimgs * sizeof (EmacsImage *)); - xfree (bimgs); - } - - bimgs = newBimgs; + bimgs = xrealloc (bimgs, max_used_fringe_bitmap * sizeof *bimgs); + memset (bimgs + nBimgs, 0, + (max_used_fringe_bitmap - nBimgs) * sizeof *bimgs); nBimgs = max_used_fringe_bitmap; } @@ -2321,7 +2265,6 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, if (p->which) { NSRect r = NSMakeRect (p->x+xAdjust, p->y, p->wd, p->h); - NSPoint pt = r.origin; EmacsImage *img = bimgs[p->which - 1]; if (!img) @@ -2344,15 +2287,19 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, to erase the whole background. */ [ns_lookup_indexed_color(face->background, f) set]; NSRectFill (r); - pt.y += p->h; [img setXBMColor: ns_lookup_indexed_color(face->foreground, f)]; - [img compositeToPoint: pt operation: NSCompositeSourceOver]; + [img drawInRect: r + fromRect: NSZeroRect + operation: NSCompositeSourceOver + fraction: 1.0 + respectFlipped: YES + hints: nil]; } ns_unfocus (f); } -void +static void ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int y, int cursor_type, int cursor_width, int on_p, int active_p) @@ -2601,6 +2548,60 @@ ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr) return n; } +/* -------------------------------------------------------------------- + Draw a wavy line under glyph string s. The wave fills wave_height + pixels from y. + + x wave_length = 3 + -- + y * * * * * + |* * * * * * * * * + wave_height = 3 | * * * * + --------------------------------------------------------------------- */ + +static void +ns_draw_underwave (struct glyph_string *s, CGFloat width, CGFloat x) +{ + int wave_height = 3, wave_length = 3; + int y, dx, dy, odd, xmax; + NSPoint a, b; + NSRect waveClip; + + dx = wave_length; + dy = wave_height - 1; + y = s->ybase + 1; + xmax = x + width; + + /* Find and set clipping rectangle */ + waveClip = NSMakeRect (x, y, width, wave_height); + [[NSGraphicsContext currentContext] saveGraphicsState]; + NSRectClip (waveClip); + + /* Draw the waves */ + a.x = x - ((int)(x) % dx); + b.x = a.x + dx; + odd = (int)(a.x/dx) % 2; + a.y = b.y = y; + + if (odd) + a.y += dy; + else + b.y += dy; + + while (a.x <= xmax) + { + [NSBezierPath strokeLineFromPoint:a toPoint:b]; + a.x = b.x, a.y = b.y; + b.x += dx, b.y = y + odd*dy; + odd = !odd; + } + + /* Restore previous clipping rectangle(s) */ + [[NSGraphicsContext currentContext] restoreGraphicsState]; +} + + + void ns_draw_text_decoration (struct glyph_string *s, struct face *face, NSColor *defaultCol, CGFloat width, CGFloat x) @@ -2614,63 +2615,75 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face, /* Do underline. */ if (face->underline_p) { - NSRect r; - unsigned long thickness, position; - - /* If the prev was underlined, match its appearance. */ - if (s->prev && s->prev->face->underline_p - && s->prev->underline_thickness > 0) + if (s->face->underline_type == FACE_UNDER_WAVE) { - thickness = s->prev->underline_thickness; - position = s->prev->underline_position; + if (face->underline_defaulted_p) + [defaultCol set]; + else + [ns_lookup_indexed_color (face->underline_color, s->f) set]; + + ns_draw_underwave (s, width, x); } - else + else if (s->face->underline_type == FACE_UNDER_LINE) { - struct font *font; - unsigned long descent; - - font=s->font; - descent = s->y + s->height - s->ybase; - - /* Use underline thickness of font, defaulting to 1. */ - thickness = (font && font->underline_thickness > 0) - ? font->underline_thickness : 1; - - /* Determine the offset of underlining from the baseline. */ - if (x_underline_at_descent_line) - position = descent - thickness; - else if (x_use_underline_position_properties - && font && font->underline_position >= 0) - position = font->underline_position; - else if (font) - position = lround (font->descent / 2); - else - position = underline_minimum_offset; - position = max (position, underline_minimum_offset); + NSRect r; + unsigned long thickness, position; - /* Ensure underlining is not cropped. */ - if (descent <= position) + /* If the prev was underlined, match its appearance. */ + if (s->prev && s->prev->face->underline_p + && s->prev->underline_thickness > 0) { - position = descent - 1; - thickness = 1; + thickness = s->prev->underline_thickness; + position = s->prev->underline_position; + } + else + { + struct font *font; + unsigned long descent; + + font=s->font; + descent = s->y + s->height - s->ybase; + + /* Use underline thickness of font, defaulting to 1. */ + thickness = (font && font->underline_thickness > 0) + ? font->underline_thickness : 1; + + /* Determine the offset of underlining from the baseline. */ + if (x_underline_at_descent_line) + position = descent - thickness; + else if (x_use_underline_position_properties + && font && font->underline_position >= 0) + position = font->underline_position; + else if (font) + position = lround (font->descent / 2); + else + position = underline_minimum_offset; + + position = max (position, underline_minimum_offset); + + /* Ensure underlining is not cropped. */ + if (descent <= position) + { + position = descent - 1; + thickness = 1; + } + else if (descent < position + thickness) + thickness = 1; } - else if (descent < position + thickness) - thickness = 1; - } - s->underline_thickness = thickness; - s->underline_position = position; + s->underline_thickness = thickness; + s->underline_position = position; - r = NSMakeRect (x, s->ybase + position, width, thickness); + r = NSMakeRect (x, s->ybase + position, width, thickness); - if (face->underline_defaulted_p) - [defaultCol set]; - else - [ns_lookup_indexed_color (face->underline_color, s->f) set]; - NSRectFill (r); + if (face->underline_defaulted_p) + [defaultCol set]; + else + [ns_lookup_indexed_color (face->underline_color, s->f) set]; + NSRectFill (r); + } } - /* Do overline. We follow other terms in using a thickness of 1 and ignoring overline_margin. */ if (face->overline_p) @@ -3023,8 +3036,12 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) /* Draw the image.. do we need to draw placeholder if img ==nil? */ if (img != nil) - [img compositeToPoint: NSMakePoint (x, y + s->slice.height) - operation: NSCompositeSourceOver]; + [img drawInRect: br + fromRect: NSZeroRect + operation: NSCompositeSourceOver + fraction: 1.0 + respectFlipped: YES + hints: nil]; if (s->hl == DRAW_CURSOR) { @@ -3400,6 +3417,9 @@ ns_read_socket (struct terminal *terminal, int expected, /* NSTRACE (ns_read_socket); */ + if ([NSApp modalWindow] != nil) + return -1; + if (interrupt_input_blocked) { interrupt_input_pending = 1; @@ -3477,7 +3497,7 @@ ns_read_socket (struct terminal *terminal, int expected, int ns_select (int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) + fd_set *exceptfds, EMACS_TIME *timeout, sigset_t *sigmask) /* -------------------------------------------------------------------------- Replacement for select, checking for events -------------------------------------------------------------------------- */ @@ -3485,12 +3505,14 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, int result; double time; NSEvent *ev; + struct timespec select_timeout; + /* NSTRACE (ns_select); */ if (NSApp == nil || inNsSelect == 1 /* || ([NSApp isActive] == NO && [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:NO] == nil) */) - return select (nfds, readfds, writefds, exceptfds, timeout); + return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask); /* Save file descriptor set, which gets overwritten in calls to select () Note, this is called from process.c, and only readfds is ever set */ @@ -3503,8 +3525,9 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, select_nfds = 0; /* Try an initial select for pending data on input files */ - select_timeout.tv_sec = select_timeout.tv_usec = 0; - result = select (nfds, readfds, writefds, exceptfds, &select_timeout); + select_timeout.tv_sec = select_timeout.tv_nsec = 0; + result = pselect (nfds, readfds, writefds, exceptfds, + &select_timeout, sigmask); if (result) return result; @@ -3513,7 +3536,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, /* set a timeout and run the main AppKit event loop while continuing to monitor the files */ - time = ((double) timeout->tv_sec) + ((double) timeout->tv_usec)/1000000.0; + time = EMACS_TIME_TO_DOUBLE (*timeout); timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time target: NSApp selector: @selector (timeout_handler:) @@ -3521,7 +3544,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, repeats: YES] /* for safe removal */ retain]; - /* set a periodic task to try the select () again */ + /* set a periodic task to try the pselect () again */ fd_entry = [[NSTimer scheduledTimerWithTimeInterval: 0.1 target: NSApp selector: @selector (fd_handler:) @@ -3563,7 +3586,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, } else { - /* Received back from select () in fd_handler; copy the results */ + /* Received back from pselect () in fd_handler; copy the results */ if (readfds) memcpy (readfds, &select_readfds, sizeof (fd_set)); return t; @@ -3597,7 +3620,6 @@ ns_set_vertical_scroll_bar (struct window *window, BOOL barOnVeryLeft, barOnVeryRight; int top, left, height, width, sb_width, sb_left; EmacsScroller *bar; -static int count = 0; /* optimization; display engine sends WAY too many of these.. */ if (!NILP (window->vertical_scroll_bar)) @@ -3654,7 +3676,7 @@ static int count = 0; { bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); [bar removeFromSuperview]; - window->vertical_scroll_bar = Qnil; + WSET (window, vertical_scroll_bar, Qnil); } ns_clear_frame_area (f, sb_left, top, width, height); UNBLOCK_INPUT; @@ -3665,7 +3687,7 @@ static int count = 0; { ns_clear_frame_area (f, sb_left, top, width, height); bar = [[EmacsScroller alloc] initFrame: r window: win]; - window->vertical_scroll_bar = make_save_value (bar, 0); + WSET (window, vertical_scroll_bar, make_save_value (bar, 0)); } else { @@ -3719,7 +3741,7 @@ ns_redeem_scroll_bar (struct window *window) NSTRACE (ns_redeem_scroll_bar); if (!NILP (window->vertical_scroll_bar)) { - bar =XNS_SCROLL_BAR (window->vertical_scroll_bar); + bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); [bar reprieve]; } } @@ -3779,43 +3801,23 @@ static Lisp_Object ns_string_to_lispmod (const char *s) Convert modifier name to lisp symbol -------------------------------------------------------------------------- */ { - if (!strncmp (SDATA (SYMBOL_NAME (Qmeta)), s, 10)) + if (!strncmp (SSDATA (SYMBOL_NAME (Qmeta)), s, 10)) return Qmeta; - else if (!strncmp (SDATA (SYMBOL_NAME (Qsuper)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qsuper)), s, 10)) return Qsuper; - else if (!strncmp (SDATA (SYMBOL_NAME (Qcontrol)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qcontrol)), s, 10)) return Qcontrol; - else if (!strncmp (SDATA (SYMBOL_NAME (Qalt)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qalt)), s, 10)) return Qalt; - else if (!strncmp (SDATA (SYMBOL_NAME (Qhyper)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qhyper)), s, 10)) return Qhyper; - else if (!strncmp (SDATA (SYMBOL_NAME (Qnone)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qnone)), s, 10)) return Qnone; else return Qnil; } -static Lisp_Object ns_mod_to_lisp (int m) -/* -------------------------------------------------------------------------- - Convert modifier code (see lisp.h) to lisp symbol - -------------------------------------------------------------------------- */ -{ - if (m == CHAR_META) - return Qmeta; - else if (m == CHAR_SUPER) - return Qsuper; - else if (m == CHAR_CTL) - return Qcontrol; - else if (m == CHAR_ALT) - return Qalt; - else if (m == CHAR_HYPER) - return Qhyper; - else /* if (m == 0) */ - return Qnone; -} - - static void ns_default (const char *parameter, Lisp_Object *result, Lisp_Object yesval, Lisp_Object noval, @@ -3824,17 +3826,15 @@ ns_default (const char *parameter, Lisp_Object *result, Check a parameter value in user's preferences -------------------------------------------------------------------------- */ { - const char *value; + const char *value = ns_get_defaults_value (parameter); - if ( (value =[[[NSUserDefaults standardUserDefaults] - stringForKey: [NSString stringWithUTF8String: parameter]] - UTF8String]) ) + if (value) { double f; char *pos; - if (strcasecmp (value, "YES") == 0) + if (c_strcasecmp (value, "YES") == 0) *result = yesval; - else if (strcasecmp (value, "NO") == 0) + else if (c_strcasecmp (value, "NO") == 0) *result = noval; else if (is_float && (f = strtod (value, &pos), pos != value)) *result = make_float (f); @@ -3846,7 +3846,7 @@ ns_default (const char *parameter, Lisp_Object *result, } -void +static void ns_initialize_display_info (struct ns_display_info *dpyinfo) /* -------------------------------------------------------------------------- Initialize global info and storage for display. @@ -3864,8 +3864,7 @@ ns_initialize_display_info (struct ns_display_info *dpyinfo) NSColorSpaceFromDepth (depth)]; dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth); dpyinfo->image_cache = make_image_cache (); - dpyinfo->color_table - = (struct ns_color_table *)xmalloc (sizeof (struct ns_color_table)); + dpyinfo->color_table = xmalloc (sizeof *dpyinfo->color_table); dpyinfo->color_table->colors = NULL; dpyinfo->root_window = 42; /* a placeholder.. */ @@ -3936,7 +3935,6 @@ static void ns_delete_terminal (struct terminal *terminal) { struct ns_display_info *dpyinfo = terminal->display_info.ns; - int i; /* Protect against recursive calls. delete_frame in delete_terminal calls us back when it deletes our last frame. */ @@ -4033,7 +4031,7 @@ ns_term_init (Lisp_Object display_name) ns_pending_service_names = [[NSMutableArray alloc] init]; ns_pending_service_args = [[NSMutableArray alloc] init]; - /* Start app and create the main menu, window, view. +/* Start app and create the main menu, window, view. Needs to be here because ns_initialize_display_info () uses AppKit classes. The view will then ask the NSApp to stop and return to Emacs. */ [EmacsApp sharedApplication]; @@ -4046,13 +4044,12 @@ ns_term_init (Lisp_Object display_name) selector: @selector (logNotification:) name: nil object: nil]; */ - dpyinfo = (struct ns_display_info *)xmalloc (sizeof (struct ns_display_info)); - memset (dpyinfo, 0, sizeof (struct ns_display_info)); + dpyinfo = xzalloc (sizeof *dpyinfo); ns_initialize_display_info (dpyinfo); terminal = ns_create_terminal (dpyinfo); - terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); + terminal->kboard = xmalloc (sizeof *terminal->kboard); init_kboard (terminal->kboard); KVAR (terminal->kboard, Vwindow_system) = Qns; terminal->kboard->next_kboard = all_kboards; @@ -4072,10 +4069,7 @@ ns_term_init (Lisp_Object display_name) ns_display_name_list); dpyinfo->name_list_element = XCAR (ns_display_name_list); - /* Set the name of the terminal. */ - terminal->name = (char *) xmalloc (SBYTES (display_name) + 1); - strncpy (terminal->name, SDATA (display_name), SBYTES (display_name)); - terminal->name[SBYTES (display_name)] = 0; + terminal->name = xstrdup (SSDATA (display_name)); UNBLOCK_INPUT; @@ -4101,7 +4095,6 @@ ns_term_init (Lisp_Object display_name) if ( cl == nil ) { Lisp_Object color_file, color_map, color; - int r,g,b; unsigned long c; char *name; @@ -4118,7 +4111,7 @@ ns_term_init (Lisp_Object display_name) for ( ; CONSP (color_map); color_map = XCDR (color_map)) { color = XCAR (color_map); - name = SDATA (XCAR (color)); + name = SSDATA (XCAR (color)); c = XINT (XCDR (color)); [cl setColor: [NSColor colorWithCalibratedRed: RED_FROM_ULONG (c) / 255.0 @@ -4132,14 +4125,14 @@ ns_term_init (Lisp_Object display_name) } { - char c[128]; #ifdef NS_IMPL_GNUSTEP - strncpy (c, gnustep_base_version, sizeof (c)); + Vwindow_system_version = build_string (gnustep_base_version); #else /*PSnextrelease (128, c); */ - snprintf (c, sizeof (c), "%g", NSAppKitVersionNumber); + char c[DBL_BUFSIZE_BOUND]; + int len = dtoastr (c, sizeof c, 0, 0, NSAppKitVersionNumber); + Vwindow_system_version = make_unibyte_string (c, len); #endif - Vwindow_system_version = build_string (c); } delete_keyboard_wait_descriptor (0); @@ -4205,11 +4198,20 @@ ns_term_init (Lisp_Object display_name) [NSApp setServicesMenu: svcsMenu]; /* Needed at least on Cocoa, to get dock menu to show windows */ [NSApp setWindowsMenu: [[NSMenu alloc] init]]; + + [[NSNotificationCenter defaultCenter] + addObserver: mainMenu + selector: @selector (trackingNotification:) + name: NSMenuDidBeginTrackingNotification object: mainMenu]; + [[NSNotificationCenter defaultCenter] + addObserver: mainMenu + selector: @selector (trackingNotification:) + name: NSMenuDidEndTrackingNotification object: mainMenu]; } #endif /* MAC OS X menu setup */ [NSApp run]; - + ns_do_open_file = YES; return dpyinfo; } @@ -4221,7 +4223,7 @@ ns_term_shutdown (int sig) /* code not reached in emacs.c after this is called by shut_down_emacs: */ if (STRINGP (Vauto_save_list_file_name)) - unlink (SDATA (Vauto_save_list_file_name)); + unlink (SSDATA (Vauto_save_list_file_name)); if (sig == 0 || sig == SIGTERM) { @@ -4436,7 +4438,7 @@ ns_term_shutdown (int sig) return NSTerminateNow; ret = NSRunAlertPanel(ns_app_name, - [NSString stringWithUTF8String:"Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?"], + @"Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?", @"Save Buffers and Exit", @"Cancel", nil); if (ret == NSAlertDefaultReturn) @@ -4450,7 +4452,8 @@ ns_term_shutdown (int sig) /* Notification from the Workspace to open a file */ - (BOOL)application: sender openFile: (NSString *)file { - [ns_pending_files addObject: file]; + if (ns_do_open_file) + [ns_pending_files addObject: file]; return YES; } @@ -4458,7 +4461,8 @@ ns_term_shutdown (int sig) /* Open a file as a temporary file */ - (BOOL)application: sender openTempFile: (NSString *)file { - [ns_pending_files addObject: file]; + if (ns_do_open_file) + [ns_pending_files addObject: file]; return YES; } @@ -4466,7 +4470,8 @@ ns_term_shutdown (int sig) /* Notification from the Workspace to open a file noninteractively (?) */ - (BOOL)application: sender openFileWithoutUI: (NSString *)file { - [ns_pending_files addObject: file]; + if (ns_do_open_file) + [ns_pending_files addObject: file]; return YES; } @@ -4474,11 +4479,17 @@ ns_term_shutdown (int sig) /* Notification from the Workspace to open multiple files */ - (void)application: sender openFiles: (NSArray *)fileList { - NSEnumerator *files = [fileList objectEnumerator]; - NSString *file; - while ((file = [files nextObject]) != nil) - [ns_pending_files addObject: file]; - + /* Don't open files from the command line, Cocoa parses the command line + wrong anyway, --option value tries to open value if --option is the last + option. */ + if (ns_do_open_file) + { + NSEnumerator *files = [fileList objectEnumerator]; + NSString *file; + while ((file = [files nextObject]) != nil) + [ns_pending_files addObject: file]; + } + [self replyToOpenOrPrint: NSApplicationDelegateReplySuccess]; } @@ -4536,6 +4547,7 @@ ns_term_shutdown (int sig) -------------------------------------------------------------------------- */ { int result; + struct timespec select_timeout; /* NSTRACE (fd_handler); */ if (select_nfds == 0) @@ -4543,9 +4555,8 @@ ns_term_shutdown (int sig) memcpy (&t_readfds, &select_readfds, sizeof (fd_set)); - select_timeout.tv_sec = select_timeout.tv_usec = 0; - result = select (select_nfds, &t_readfds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, - &select_timeout); + select_timeout.tv_sec = select_timeout.tv_nsec = 0; + result = pselect (select_nfds, &t_readfds, NULL, NULL, &select_timeout, NULL); if (result) { memcpy (&select_readfds, &t_readfds, sizeof (fd_set)); @@ -4568,7 +4579,7 @@ ns_term_shutdown (int sig) { [ns_pending_service_names addObject: userData]; [ns_pending_service_args addObject: [NSString stringWithUTF8String: - SDATA (ns_string_from_pasteboard (pboard))]]; + SSDATA (ns_string_from_pasteboard (pboard))]]; } @@ -4632,8 +4643,8 @@ ns_term_shutdown (int sig) if (!emacs_event) return; - if (newFont = [sender convertFont: - ((struct nsfont_info *)face->font)->nsfont]) + if ((newFont = [sender convertFont: + ((struct nsfont_info *)face->font)->nsfont])) { SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */ @@ -4727,8 +4738,13 @@ ns_term_shutdown (int sig) if (!processingCompose) { + /* When using screen sharing, no left or right information is sent, + so use Left key in those cases. */ + int is_left_key, is_right_key; + code = ([[theEvent charactersIgnoringModifiers] length] == 0) ? 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0]; + /* (Carbon way: [theEvent keyCode]) */ /* is it a "function key"? */ @@ -4753,13 +4769,17 @@ ns_term_shutdown (int sig) if (flags & NSShiftKeyMask) emacs_event->modifiers |= shift_modifier; - if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask) + is_right_key = (flags & NSRightCommandKeyMask) == NSRightCommandKeyMask; + is_left_key = (flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask + || (! is_right_key && (flags & NSCommandKeyMask) == NSCommandKeyMask); + + if (is_right_key) emacs_event->modifiers |= parse_solitary_modifier (EQ (ns_right_command_modifier, Qleft) ? ns_command_modifier : ns_right_command_modifier); - if ((flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask) + if (is_left_key) { emacs_event->modifiers |= parse_solitary_modifier (ns_command_modifier); @@ -4796,13 +4816,17 @@ ns_term_shutdown (int sig) } } - if ((flags & NSRightControlKeyMask) == NSRightControlKeyMask) + is_right_key = (flags & NSRightControlKeyMask) == NSRightControlKeyMask; + is_left_key = (flags & NSLeftControlKeyMask) == NSLeftControlKeyMask + || (! is_right_key && (flags & NSControlKeyMask) == NSControlKeyMask); + + if (is_right_key) emacs_event->modifiers |= parse_solitary_modifier (EQ (ns_right_control_modifier, Qleft) ? ns_control_modifier : ns_right_control_modifier); - if ((flags & NSLeftControlKeyMask) == NSLeftControlKeyMask) + if (is_left_key) emacs_event->modifiers |= parse_solitary_modifier (ns_control_modifier); @@ -4813,7 +4837,13 @@ ns_term_shutdown (int sig) left_is_none = NILP (ns_alternate_modifier) || EQ (ns_alternate_modifier, Qnone); - if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask) + is_right_key = (flags & NSRightAlternateKeyMask) + == NSRightAlternateKeyMask; + is_left_key = (flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask + || (! is_right_key + && (flags & NSAlternateKeyMask) == NSAlternateKeyMask); + + if (is_right_key) { if ((NILP (ns_right_alternate_modifier) || EQ (ns_right_alternate_modifier, Qnone) @@ -4833,7 +4863,7 @@ ns_term_shutdown (int sig) : ns_right_alternate_modifier); } - if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask) /* default = meta */ + if (is_left_key) /* default = meta */ { if (left_is_none && !fnKeysym) { /* accept pre-interp alt comb */ @@ -5047,9 +5077,9 @@ ns_term_shutdown (int sig) } -- (long)conversationIdentifier +- (NSInteger)conversationIdentifier { - return (long)self; + return (NSInteger)self; } @@ -5109,7 +5139,6 @@ ns_term_shutdown (int sig) - (void)mouseDown: (NSEvent *)theEvent { NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; - Lisp_Object window; NSTRACE (mouseDown); @@ -5321,8 +5350,7 @@ ns_term_shutdown (int sig) char *pos = strstr (t, " — "); if (pos) *pos = '\0'; - old_title = (char *) xmalloc (strlen (t) + 1); - strcpy (old_title, t); + old_title = xstrdup (t); } size_title = xmalloc (strlen (old_title) + 40); esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows); @@ -5340,9 +5368,9 @@ ns_term_shutdown (int sig) - (void)windowDidResize: (NSNotification *)notification { +#ifdef NS_IMPL_GNUSTEP NSWindow *theWindow = [notification object]; -#ifdef NS_IMPL_GNUSTEP /* in GNUstep, at least currently, it's possible to get a didResize without getting a willResize.. therefore we need to act as if we got the willResize now */ @@ -5462,7 +5490,6 @@ ns_term_shutdown (int sig) Lisp_Object tem; NSWindow *win; NSButton *toggleButton; - int vbextra = NS_SCROLL_BAR_WIDTH (f); NSSize sz; NSColor *col; NSString *name; @@ -5515,7 +5542,7 @@ ns_term_shutdown (int sig) tem = f->name; name = [NSString stringWithUTF8String: - NILP (tem) ? (unsigned char *)"Emacs" : SDATA (tem)]; + NILP (tem) ? "Emacs" : SSDATA (tem)]; [win setTitle: name]; /* toolbar support */ @@ -5534,7 +5561,7 @@ ns_term_shutdown (int sig) tem = f->icon_name; if (!NILP (tem)) [win setMiniwindowTitle: - [NSString stringWithUTF8String: SDATA (tem)]]; + [NSString stringWithUTF8String: SSDATA (tem)]]; { NSScreen *screen = [win screen]; @@ -5679,18 +5706,13 @@ ns_term_shutdown (int sig) - (void)mouseEntered: (NSEvent *)theEvent { - NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; - struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe); NSTRACE (mouseEntered); - last_mouse_movement_time = EV_TIMESTAMP (theEvent); } - (void)mouseExited: (NSEvent *)theEvent { - NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; - NSRect r; Mouse_HLInfo *hlinfo = emacsframe ? MOUSE_HL_INFO (emacsframe) : NULL; NSTRACE (mouseExited); @@ -5713,10 +5735,14 @@ ns_term_shutdown (int sig) NSTRACE (menuDown); if (context_menu_value == -1) context_menu_value = [sender tag]; - else - find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used, - emacsframe->menu_bar_vector, - (void *)[sender tag]); + else + { + NSInteger tag = [sender tag]; + find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used, + emacsframe->menu_bar_vector, + (void *)tag); + } + ns_send_appdefined (-1); return self; } @@ -5748,7 +5774,7 @@ ns_term_shutdown (int sig) emacs_event->kind = TOOL_BAR_EVENT; /* XSETINT (emacs_event->code, 0); */ emacs_event->arg = AREF (emacsframe->tool_bar_items, - idx + TOOL_BAR_ITEM_KEY); + idx + TOOL_BAR_ITEM_KEY); emacs_event->modifiers = EV_MODIFIERS (theEvent); EV_TRAILER (theEvent); return self; @@ -6030,15 +6056,76 @@ ns_term_shutdown (int sig) @implementation EmacsWindow +#ifdef NS_IMPL_COCOA +- (id)accessibilityAttributeValue:(NSString *)attribute +{ + Lisp_Object str = Qnil; + struct frame *f = SELECTED_FRAME (); + struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->buffer); + + if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) + return NSAccessibilityTextFieldRole; + + if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute] + && curbuf && ! NILP (BVAR (curbuf, mark_active))) + { + str = ns_get_local_selection (QPRIMARY, QUTF8_STRING); + } + else if (curbuf && [attribute isEqualToString:NSAccessibilityValueAttribute]) + { + if (! NILP (BVAR (curbuf, mark_active))) + str = ns_get_local_selection (QPRIMARY, QUTF8_STRING); + + if (NILP (str)) + { + ptrdiff_t start_byte = BUF_BEGV_BYTE (curbuf); + ptrdiff_t byte_range = BUF_ZV_BYTE (curbuf) - start_byte; + ptrdiff_t range = BUF_ZV (curbuf) - BUF_BEGV (curbuf); + + if (! NILP (BVAR (curbuf, enable_multibyte_characters))) + str = make_uninit_multibyte_string (range, byte_range); + else + str = make_uninit_string (range); + /* To check: This returns emacs-utf-8, which is a superset of utf-8. + Is this a problem? */ + memcpy (SDATA (str), BYTE_POS_ADDR (start_byte), byte_range); + } + } + + + if (! NILP (str)) + { + if (CONSP (str) && SYMBOLP (XCAR (str))) + { + str = XCDR (str); + if (CONSP (str) && NILP (XCDR (str))) + str = XCAR (str); + } + if (STRINGP (str)) + { + const char *utfStr = SSDATA (str); + NSString *nsStr = [NSString stringWithUTF8String: utfStr]; + return nsStr; + } + } + + return [super accessibilityAttributeValue:attribute]; +} +#endif /* NS_IMPL_COCOA */ + /* If we have multiple monitors, one above the other, we don't want to restrict the height to just one monitor. So we override this. */ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen { - /* When making the frame visible for the first time, we want to - constrain. Other times not. */ + /* When making the frame visible for the first time or if there is just + one screen, we want to constrain. Other times not. */ + NSUInteger nr_screens = [[NSScreen screens] count]; struct frame *f = ((EmacsView *)[self delegate])->emacsframe; NSTRACE (constrainFrameRect); + if (nr_screens == 1) + return [super constrainFrameRect:frameRect toScreen:screen]; + if (f->output_data.ns->dont_constrain || ns_menu_bar_should_be_hidden ()) return frameRect; @@ -6188,7 +6275,7 @@ ns_term_shutdown (int sig) { NSTRACE (EmacsScroller_dealloc); if (!NILP (win)) - XWINDOW (win)->vertical_scroll_bar = Qnil; + WSET (XWINDOW (win), vertical_scroll_bar, Qnil); [super dealloc]; } @@ -6733,12 +6820,12 @@ Only works on OSX 10.6 or later. */); /* TODO: move to common code */ DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, - doc: /* If not nil, Emacs uses toolkit scroll bars. */); -#ifdef USE_TOOLKIT_SCROLL_BARS + doc: /* Which toolkit scroll bars Emacs uses, if any. +A value of nil means Emacs doesn't use toolkit scroll bars. +With the X Window system, the value is a symbol describing the +X toolkit. Possible values are: gtk, motif, xaw, or xaw3d. +With MS Windows or Nextstep, the value is t. */); Vx_toolkit_scroll_bars = Qt; -#else - Vx_toolkit_scroll_bars = Qnil; -#endif DEFVAR_BOOL ("x-use-underline-position-properties", x_use_underline_position_properties,