#include <c-strcase.h>
#include <ftoastr.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
#include "lisp.h"
#include "blockinput.h"
#include "sysselect.h"
#include "window.h"
#include "keyboard.h"
-
+#include "buffer.h"
#include "font.h"
/* call tracing */
};
static Lisp_Object Qmodifier_value;
-Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper, Qnone;
+Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper;
extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft;
static Lisp_Object QUTF8_STRING;
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;
static BOOL send_appdefined = YES;
static NSEvent *last_appdefined_event = 0;
static NSTimer *timed_entry = 0;
-static NSTimer *fd_entry = nil;
static NSTimer *scroll_repeat_entry = nil;
-static fd_set select_readfds, t_readfds;
-static int select_nfds;
+static fd_set select_readfds, select_writefds;
+enum { SELECT_HAVE_READ = 1, SELECT_HAVE_WRITE = 2, SELECT_HAVE_TMO = 4 };
+static int select_nfds = 0, select_valid = 0;
+static EMACS_TIME select_timeout = { 0, 0 };
+static int selfds[2] = { -1, -1 };
+static pthread_mutex_t select_mutex;
+static int apploopnr = 0;
static NSAutoreleasePool *outerpool;
static struct input_event *emacs_event = NULL;
static struct input_event *q_event_ptr = NULL;
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
/* This is a piece of code which is common to all the event handling
methods. Maybe it should even be a function. */
-#define EV_TRAILER(e) \
- { \
- XSETFRAME (emacs_event->frame_or_window, emacsframe); \
- if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
- n_emacs_events_pending++; \
- kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
- EVENT_INIT (*emacs_event); \
- ns_send_appdefined (-1); \
- }
+#define EV_TRAILER(e) \
+ { \
+ XSETFRAME (emacs_event->frame_or_window, emacsframe); \
+ if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
+ if (q_event_ptr) \
+ { \
+ n_emacs_events_pending++; \
+ kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
+ } \
+ else \
+ kbd_buffer_store_event (emacs_event); \
+ EVENT_INIT (*emacs_event); \
+ ns_send_appdefined (-1); \
+ }
void x_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object);
NSString *binDir = [bundle bundlePath];
NSString *resourcePath, *resourcePaths;
NSRange range;
- BOOL onWindows = NO; /* FIXME determine this somehow */
- NSString *pathSeparator = onWindows ? @";" : @":";
+ NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths;
NSEnumerator *pathEnum;
pathEnum = [paths objectEnumerator];
resourcePaths = @"";
- while (resourcePath = [pathEnum nextObject])
+ while ((resourcePath = [pathEnum nextObject]))
{
if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
if (isDir)
NSBundle *bundle = [NSBundle mainBundle];
NSString *resourceDir = [bundle resourcePath];
NSString *resourcePath, *resourcePaths;
- BOOL onWindows = NO; /* FIXME determine this somehow */
- NSString *pathSeparator = onWindows ? @";" : @":";
+ NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDir;
NSArray *paths = [resourceDir stringsByAppendingPaths:
/* Hack to skip site-lisp. */
if (no_site_lisp) resourcePath = [pathEnum nextObject];
- while (resourcePath = [pathEnum nextObject])
+ while ((resourcePath = [pathEnum nextObject]))
{
if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
if (isDir)
: 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;
}
}
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 */
-------------------------------------------------------------------------- */
{
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);
}
-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)
/* --------------------------------------------------------------------------
{
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;
}
{
id view;
NSPoint position;
- int xchar, ychar;
Lisp_Object frame, tail;
struct frame *f;
struct ns_display_info *dpyinfo;
}
-void
+static void
ns_define_frame_cursor (struct frame *f, Cursor cursor)
/* --------------------------------------------------------------------------
External (RIF): set frame mouse pointer type.
}
-void
+static void
ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
/* --------------------------------------------------------------------------
External (RIF): Clear section of frame
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)
{
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)
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)
/* 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)
{
timed_entry = nil;
}
- /* Ditto for file descriptor poller */
- if (fd_entry)
- {
- [fd_entry invalidate];
- [fd_entry release];
- fd_entry = nil;
- }
-
nxev = [NSEvent otherEventWithType: NSApplicationDefined
location: NSMakePoint (0, 0)
modifierFlags: 0
}
}
-
static int
ns_read_socket (struct terminal *terminal, int expected,
struct input_event *hold_quit)
/* NSTRACE (ns_read_socket); */
+ if ([NSApp modalWindow] != nil)
+ return -1;
+
if (interrupt_input_blocked)
{
interrupt_input_pending = 1;
/* Run and wait for events. We must always send one NX_APPDEFINED event
to ourself, otherwise [NXApp run] will never exit. */
send_appdefined = YES;
+ ns_send_appdefined (-1);
- /* If called via ns_select, this is called once with expected=1,
- because we expect either the timeout or file descriptor activity.
- In this case the first event through will either be real input or
- one of these. read_avail_input() then calls once more with expected=0
- and in that case we need to return quickly if there is nothing.
- If we're being called outside of that, it's also OK to return quickly
- after one iteration through the event loop, since other terms do
- this and emacs expects it. */
- if (!(inNsSelect && expected))
+ if (++apploopnr != 1)
{
- /* Post an application defined event on the event queue. When this is
- received the [NXApp run] will return, thus having processed all
- events which are currently queued, if any. */
- ns_send_appdefined (-1);
+ abort ();
}
-
[NSApp run];
+ --apploopnr;
}
nevents = n_emacs_events_pending;
-------------------------------------------------------------------------- */
{
int result;
- double time;
NSEvent *ev;
- struct timespec select_timeout;
+ int k, nr = 0;
+ struct input_event event;
+ char c;
/* NSTRACE (ns_select); */
- if (NSApp == nil || inNsSelect == 1 /* || ([NSApp isActive] == NO &&
- [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil
- inMode:NSDefaultRunLoopMode dequeue:NO] == nil) */)
+ for (k = 0; readfds && k < nfds+1; k++)
+ if (FD_ISSET(k, readfds)) ++nr;
+
+ if (NSApp == nil
+ || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
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 */
- if (readfds)
+ [outerpool release];
+ outerpool = [[NSAutoreleasePool alloc] init];
+
+
+ send_appdefined = YES;
+ if (nr > 0)
{
- memcpy (&select_readfds, readfds, sizeof (fd_set));
+ pthread_mutex_lock (&select_mutex);
select_nfds = nfds;
+ select_valid = 0;
+ if (readfds)
+ {
+ select_readfds = *readfds;
+ select_valid += SELECT_HAVE_READ;
+ }
+ if (writefds)
+ {
+ select_writefds = *writefds;
+ select_valid += SELECT_HAVE_WRITE;
+ }
+
+ if (timeout)
+ {
+ select_timeout = *timeout;
+ select_valid += SELECT_HAVE_TMO;
+ }
+
+ pthread_mutex_unlock (&select_mutex);
+
+ /* Inform fd_handler that select should be called */
+ c = 'g';
+ write (selfds[1], &c, 1);
}
- else
- select_nfds = 0;
-
- /* Try an initial select for pending data on input files */
- select_timeout.tv_sec = select_timeout.tv_nsec = 0;
- result = pselect (nfds, readfds, writefds, exceptfds,
- &select_timeout, sigmask);
- if (result)
- return result;
-
- /* if (!timeout || timed_entry || fd_entry)
- fprintf (stderr, "assertion failed: timeout null or timed_entry/fd_entry non-null in ns_select\n"); */
-
- /* set a timeout and run the main AppKit event loop while continuing
- to monitor the files */
- time = EMACS_TIME_TO_DOUBLE (*timeout);
- timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
- target: NSApp
- selector: @selector (timeout_handler:)
- userInfo: 0
- repeats: YES] /* for safe removal */
- retain];
-
- /* set a periodic task to try the pselect () again */
- fd_entry = [[NSTimer scheduledTimerWithTimeInterval: 0.1
- target: NSApp
- selector: @selector (fd_handler:)
- userInfo: 0
- repeats: YES]
- retain];
-
- /* Let Application dispatch events until it receives an event of the type
- NX_APPDEFINED, which should only be sent by timeout_handler.
- We tell read_avail_input() that input is "expected" because we do expect
- either the timeout or fd handler to fire, and if they don't, the original
- call from process.c that got us here expects us to wait until some input
- comes. */
- inNsSelect = 1;
- gobble_input (1);
+ else if (nr == 0 && timeout)
+ {
+ /* No file descriptor, just a timeout, no need to wake fd_handler */
+ double time = EMACS_TIME_TO_DOUBLE (*timeout);
+ timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
+ target: NSApp
+ selector:
+ @selector (timeout_handler:)
+ userInfo: 0
+ repeats: NO]
+ retain];
+ }
+ else /* No timeout and no file descriptors, can this happen? */
+ {
+ /* Send appdefined so we exit from the loop */
+ ns_send_appdefined (-1);
+ }
+
+ EVENT_INIT (event);
+ BLOCK_INPUT;
+ emacs_event = &event;
+ if (++apploopnr != 1)
+ {
+ abort();
+ }
+ [NSApp run];
+ --apploopnr;
+ emacs_event = NULL;
+ if (nr > 0 && readfds)
+ {
+ c = 's';
+ write (selfds[1], &c, 1);
+ }
+ UNBLOCK_INPUT;
+
ev = last_appdefined_event;
- inNsSelect = 0;
if (ev)
{
if (t == -2)
{
/* The NX_APPDEFINED event we received was a timeout. */
- return 0;
+ result = 0;
}
else if (t == -1)
{
/* The NX_APPDEFINED event we received was the result of
at least one real input event arriving. */
errno = EINTR;
- return -1;
+ result = -1;
}
else
{
- /* Received back from pselect () in fd_handler; copy the results */
- if (readfds)
- memcpy (readfds, &select_readfds, sizeof (fd_set));
- return t;
+ /* Received back from select () in fd_handler; copy the results */
+ pthread_mutex_lock (&select_mutex);
+ if (readfds) *readfds = select_readfds;
+ if (writefds) *writefds = select_writefds;
+ if (timeout) *timeout = select_timeout;
+ pthread_mutex_unlock (&select_mutex);
+ result = t;
}
}
- /* never reached, shut compiler up */
- return 0;
+
+ return result;
}
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))
{
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;
{
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
{
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];
}
}
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,
}
-void
+static void
ns_initialize_display_info (struct ns_display_info *dpyinfo)
/* --------------------------------------------------------------------------
Initialize global info and storage for display.
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. */
{
baud_rate = 38400;
Fset_input_interrupt_mode (Qnil);
+
+ if (selfds[0] == -1)
+ {
+ if (pipe (selfds) == -1)
+ {
+ fprintf (stderr, "Failed to create pipe: %s\n",
+ emacs_strerror (errno));
+ abort ();
+ }
+
+ fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL));
+ FD_ZERO (&select_readfds);
+ FD_ZERO (&select_writefds);
+ pthread_mutex_init (&select_mutex, NULL);
+ }
ns_initialized = 1;
}
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];
return NULL;
[NSApp setDelegate: NSApp];
+ /* Start the select thread. */
+ [NSThread detachNewThreadSelector:@selector (fd_handler:)
+ toTarget:NSApp
+ withObject:nil];
+
/* debugging: log all notifications */
/* [[NSNotificationCenter defaultCenter] addObserver: NSApp
selector: @selector (logNotification:)
terminal->kboard = xmalloc (sizeof *terminal->kboard);
init_kboard (terminal->kboard);
- KVAR (terminal->kboard, Vwindow_system) = Qns;
+ KSET (terminal->kboard, Vwindow_system, Qns);
terminal->kboard->next_kboard = all_kboards;
all_kboards = terminal->kboard;
/* Don't let the initial kboard remain current longer than necessary.
if ( cl == nil )
{
Lisp_Object color_file, color_map, color;
- int r,g,b;
unsigned long c;
char *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
#endif /* MAC OS X menu setup */
[NSApp run];
-
+ ns_do_open_file = YES;
return dpyinfo;
}
/* 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)
{
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)
return NSTerminateNow; /* just in case */
}
+static int
+not_in_argv (NSString *arg)
+{
+ int k;
+ const char *a = [arg UTF8String];
+ for (k = 1; k < initial_argc; ++k)
+ if (strcmp (a, initial_argv[k]) == 0) return 0;
+ return 1;
+}
/* Notification from the Workspace to open a file */
- (BOOL)application: sender openFile: (NSString *)file
{
- [ns_pending_files addObject: file];
+ if (ns_do_open_file || not_in_argv (file))
+ [ns_pending_files addObject: file];
return YES;
}
/* Open a file as a temporary file */
- (BOOL)application: sender openTempFile: (NSString *)file
{
- [ns_pending_files addObject: file];
+ if (ns_do_open_file || not_in_argv (file))
+ [ns_pending_files addObject: file];
return YES;
}
/* 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 || not_in_argv (file))
+ [ns_pending_files addObject: file];
return YES;
}
-
/* 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 unconditionally,
+ Cocoa parses the command line wrong, --option value tries to open value
+ if --option is the last option. */
+ while ((file = [files nextObject]) != nil)
+ if (ns_do_open_file || not_in_argv (file))
+ [ns_pending_files addObject: file];
+
[self replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
}
ns_send_appdefined (-2);
}
-- (void)fd_handler: (NSTimer *) fdEntry
+- (void)fd_handler:(id)unused
/* --------------------------------------------------------------------------
Check data waiting on file descriptors and terminate if so
-------------------------------------------------------------------------- */
{
int result;
- struct timespec select_timeout;
- /* NSTRACE (fd_handler); */
+ int waiting = 1, nfds;
+ char c;
- if (select_nfds == 0)
- return;
+ SELECT_TYPE readfds, writefds, *wfds;
+ EMACS_TIME timeout, *tmo;
- memcpy (&t_readfds, &select_readfds, sizeof (fd_set));
+ /* NSTRACE (fd_handler); */
- select_timeout.tv_sec = select_timeout.tv_nsec = 0;
- result = pselect (select_nfds, &t_readfds, NULL, NULL, &select_timeout, NULL);
- if (result)
+ for (;;)
{
- memcpy (&select_readfds, &t_readfds, sizeof (fd_set));
- ns_send_appdefined (result);
+ if (waiting)
+ {
+ SELECT_TYPE fds;
+
+ FD_SET (selfds[0], &fds);
+ result = select (selfds[0]+1, &fds, NULL, NULL, NULL);
+ if (result > 0)
+ {
+ read (selfds[0], &c, 1);
+ if (c == 'g') waiting = 0;
+ }
+ }
+ else
+ {
+ pthread_mutex_lock (&select_mutex);
+ nfds = select_nfds;
+
+ if (select_valid & SELECT_HAVE_READ)
+ readfds = select_readfds;
+ else
+ FD_ZERO (&readfds);
+
+ if (select_valid & SELECT_HAVE_WRITE)
+ {
+ writefds = select_writefds;
+ wfds = &writefds;
+ }
+ else
+ wfds = NULL;
+ if (select_valid & SELECT_HAVE_TMO)
+ {
+ timeout = select_timeout;
+ tmo = &timeout;
+ }
+ else
+ tmo = NULL;
+
+ pthread_mutex_unlock (&select_mutex);
+
+ FD_SET (selfds[0], &readfds);
+ if (selfds[0] >= nfds) nfds = selfds[0]+1;
+
+ result = pselect (nfds, &readfds, wfds, NULL, tmo, NULL);
+
+ if (result == 0)
+ ns_send_appdefined (-2);
+ else if (result > 0)
+ {
+ if (FD_ISSET (selfds[0], &readfds))
+ {
+ read (selfds[0], &c, 1);
+ if (c == 's') waiting = 1;
+ }
+ else
+ {
+ pthread_mutex_lock (&select_mutex);
+ if (select_valid & SELECT_HAVE_READ)
+ select_readfds = readfds;
+ if (select_valid & SELECT_HAVE_WRITE)
+ select_writefds = writefds;
+ if (select_valid & SELECT_HAVE_TMO)
+ select_timeout = timeout;
+ pthread_mutex_unlock (&select_mutex);
+
+ ns_send_appdefined (result);
+ }
+ }
+ waiting = 1;
+ }
}
}
{
[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))]];
}
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 */
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"? */
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);
}
}
- 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);
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)
: 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 */
}
-- (long)conversationIdentifier
+- (NSInteger)conversationIdentifier
{
- return (long)self;
+ return (NSInteger)self;
}
- (void)mouseDown: (NSEvent *)theEvent
{
NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
- Lisp_Object window;
NSTRACE (mouseDown);
- (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 */
Lisp_Object tem;
NSWindow *win;
NSButton *toggleButton;
- int vbextra = NS_SCROLL_BAR_WIDTH (f);
NSSize sz;
NSColor *col;
NSString *name;
tem = f->name;
name = [NSString stringWithUTF8String:
- NILP (tem) ? (unsigned char *)"Emacs" : SDATA (tem)];
+ NILP (tem) ? "Emacs" : SSDATA (tem)];
[win setTitle: name];
/* toolbar support */
tem = f->icon_name;
if (!NILP (tem))
[win setMiniwindowTitle:
- [NSString stringWithUTF8String: SDATA (tem)]];
+ [NSString stringWithUTF8String: SSDATA (tem)]];
{
NSScreen *screen = [win screen];
- (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);
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;
}
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;
@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
{
NSTRACE (EmacsScroller_dealloc);
if (!NILP (win))
- XWINDOW (win)->vertical_scroll_bar = Qnil;
+ WSET (XWINDOW (win), vertical_scroll_bar, Qnil);
[super dealloc];
}
XSETINT (emacs_event->x, loc * pixel_height);
XSETINT (emacs_event->y, pixel_height-20);
- n_emacs_events_pending++;
- kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
+ if (q_event_ptr)
+ {
+ n_emacs_events_pending++;
+ kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
+ }
+ else
+ kbd_buffer_store_event (emacs_event);
EVENT_INIT (*emacs_event);
ns_send_appdefined (-1);
}
DEFSYM (Qmeta, "meta");
DEFSYM (Qsuper, "super");
DEFSYM (Qcontrol, "control");
- DEFSYM (Qnone, "none");
DEFSYM (QUTF8_STRING, "UTF8_STRING");
Fput (Qalt, Qmodifier_value, make_number (alt_modifier));