/* 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.
#define NSTRACE(x)
#endif
+extern NSString *NSMenuDidBeginTrackingNotification;
/* ==========================================================================
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;
/*NSLog (@"loadPath: '%@'\n", resourcePaths); */
}
+ /* 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. */
if (!getenv ("EMACSPATH"))
{
NSArray *paths = [binDir stringsByAppendingPaths:
- [NSArray arrayWithObjects: @"bin",
- @"lib-exec", nil]];
+ [NSArray arrayWithObjects: @"libexec",
+ @"bin", nil]];
NSEnumerator *pathEnum = [paths objectEnumerator];
resourcePaths = @"";
while (resourcePath = [pathEnum nextObject])
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. */
- }
-}
-
-
-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.
- -------------------------------------------------------------------------- */
-{
- /* Perform the carry for the later subtraction by updating y.
- This is safer because on some systems
- the tv_sec member is unsigned. */
- if (x.tv_usec < y.tv_usec)
- {
- int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
- y.tv_usec -= 1000000 * nsec;
- y.tv_sec += nsec;
- }
- if (x.tv_usec - y.tv_usec > 1000000)
- {
- int nsec = (y.tv_usec - x.tv_usec) / 1000000;
- y.tv_usec += 1000000 * nsec;
- y.tv_sec -= nsec;
- }
-
- /* Compute the time remaining to wait. tv_usec is certainly positive. */
- result->tv_sec = x.tv_sec - y.tv_sec;
- result->tv_usec = x.tv_usec - y.tv_usec;
-
- /* Return indication of whether the result should be considered negative. */
- return x.tv_sec < y.tv_sec;
}
static void
Blocking timer utility used by ns_ring_bell
-------------------------------------------------------------------------- */
{
- struct timeval wakeup;
+ EMACS_TIME wakeup, delay;
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_SET_SECS_USECS (delay, 0, usecs);
+ EMACS_ADD_TIME (wakeup, wakeup, delay);
/* Keep waiting until past the time wakeup. */
while (1)
{
- struct timeval timeout;
+ EMACS_TIME timeout;
EMACS_GET_TIME (timeout);
-
- /* In effect, timeout = wakeup - timeout.
- Break if result would be negative. */
- if (timeval_subtract (&timeout, wakeup, timeout))
+ if (EMACS_TIME_LE (wakeup, timeout))
break;
+ EMACS_SUB_TIME (timeout, wakeup, timeout);
/* Try to wait that long--but we might wake up sooner. */
- select (0, NULL, NULL, NULL, &timeout);
+ pselect (0, NULL, NULL, NULL, &timeout, NULL);
}
}
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;
}
{
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)
{
}
/* 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];
}
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);*/
}
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;
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)
/* 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 if (descent < position + thickness)
- thickness = 1;
- }
+ 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;
- s->underline_thickness = thickness;
- s->underline_position = position;
+ position = max (position, underline_minimum_offset);
- r = NSMakeRect (x, s->ybase + position, width, thickness);
+ /* Ensure underlining is not cropped. */
+ if (descent <= position)
+ {
+ position = descent - 1;
+ thickness = 1;
+ }
+ else if (descent < position + thickness)
+ thickness = 1;
+ }
- if (face->underline_defaulted_p)
- [defaultCol set];
- else
- [ns_lookup_indexed_color (face->underline_color, s->f) set];
- NSRectFill (r);
- }
+ s->underline_thickness = thickness;
+ s->underline_position = position;
+
+ 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);
+ }
+ }
/* Do overline. We follow other terms in using a thickness of 1
and ignoring overline_margin. */
if (face->overline_p)
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
-------------------------------------------------------------------------- */
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 */
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;
/* 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:)
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:)
}
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;
[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 */
-------------------------------------------------------------------------- */
{
int result;
+ struct timespec select_timeout;
/* NSTRACE (fd_handler); */
if (select_nfds == 0)
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));
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;
/* 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,