GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
*/
+/* This should be the first include, as it may set up #defines affecting
+ interpretation of even the system includes. */
+#include "config.h"
+
#include <math.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
-#include "config.h"
#include "lisp.h"
#include "blockinput.h"
#include "sysselect.h"
#define KEY_NS_INSERT_WORKING_TEXT ((1<<28)|(0<<16)|9)
#define KEY_NS_DELETE_WORKING_TEXT ((1<<28)|(0<<16)|10)
#define KEY_NS_SPI_SERVICE_CALL ((1<<28)|(0<<16)|11)
+#define KEY_NS_NEW_FRAME ((1<<28)|(0<<16)|12)
/* Convert a symbol indexed with an NSxxx value to a value as defined
in keyboard.c (lispy_function_key). I hope this is a correct way
the Function modifer (laptops). May be any of the modifier lisp symbols. */
Lisp_Object ns_function_modifier;
-/* A floating point value specifying the rate at which to blink the cursor.
- YES indicates 0.5, NO indicates no blinking. */
-Lisp_Object ns_cursor_blink_rate;
-
-/* Used for liason with core emacs cursor-blink-mode. */
-Lisp_Object ns_cursor_blink_mode;
-
/* A floating point value specifying vertical stretch (positive) or shrink
(negative) of text line spacing. Zero means default spacing.
YES indicates 0.5, NO indicates 0.0. */
static NSEvent *last_appdefined_event = 0;
static NSTimer *timed_entry = 0;
static NSTimer *fd_entry = nil;
-static NSTimer *cursor_blink_entry = nil;
static NSTimer *scroll_repeat_entry = nil;
static fd_set select_readfds, t_readfds;
static struct timeval select_timeout;
#define EV_UDMODIFIERS(e) \
((([e type] == NSLeftMouseDown) ? down_modifier : 0) \
| (([e type] == NSRightMouseDown) ? down_modifier : 0) \
+ | (([e type] == NSOtherMouseDown) ? down_modifier : 0) \
| (([e type] == NSLeftMouseDragged) ? down_modifier : 0) \
| (([e type] == NSRightMouseDragged) ? down_modifier : 0) \
+ | (([e type] == NSOtherMouseDragged) ? down_modifier : 0) \
| (([e type] == NSLeftMouseUp) ? up_modifier : 0) \
- | (([e type] == NSRightMouseUp) ? up_modifier : 0))
+ | (([e type] == NSRightMouseUp) ? up_modifier : 0) \
+ | (([e type] == NSOtherMouseUp) ? up_modifier : 0))
#define EV_BUTTON(e) \
((([e type] == NSLeftMouseDown) || ([e type] == NSLeftMouseUp)) ? 0 : \
- (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : 1)
+ (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : \
+ [e buttonNumber] - 1)
/* Convert the time field to a timestamp in milliseconds. */
#ifdef NS_IMPL_GNUSTEP
{
NSView *view = FRAME_NS_VIEW (f);
NSTRACE (ns_update_begin);
-/*fprintf (stderr, "\\%p\n", f); */
ns_updating_frame = f;
[view lockFocus];
the entire window.
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_focus);
+// NSTRACE (ns_focus);
#ifdef NS_IMPL_GNUSTEP
NSRect u;
if (n == 2)
Internal: Remove focus on given frame
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_unfocus);
+// NSTRACE (ns_unfocus);
if (gsaved)
{
static void
-ns_clip_to_row (struct window *w, struct glyph_row *row, int area, GC gc)
+ns_clip_to_row (struct window *w, struct glyph_row *row, int area, BOOL gc)
/* --------------------------------------------------------------------------
23: Internal (but parallels other terms): Focus drawing on given row
-------------------------------------------------------------------------- */
r.origin.y += (r.size.height - dim.y) / 2;
r.size.width = dim.x;
r.size.height = dim.y;
- /* XXX: cacheImageInRect under GNUSTEP does not account for
+ /* XXX: cacheImageInRect under GNUstep does not account for
offset in x_set_window_size, so overestimate (4 fine on Cocoa) */
surr = NSInsetRect (r, -10, -10);
ns_focus (frame, &surr, 1);
if (dpyinfo->x_highlight_frame &&
dpyinfo->x_highlight_frame != old_highlight)
{
- /* as of 20080602 the lower and raise are superfluous */
if (old_highlight)
- {
- /*ns_lower_frame (old_highlight); */
+ {
x_update_cursor (old_highlight, 1);
- }
+ x_set_frame_alpha (old_highlight);
+ }
if (dpyinfo->x_highlight_frame)
- {
- /*ns_raise_frame (dpyinfo->x_highlight_frame); */
+ {
x_update_cursor (dpyinfo->x_highlight_frame, 1);
- }
+ x_set_frame_alpha (dpyinfo->x_highlight_frame);
+ }
}
}
pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
-
+
/* If we have a change in toolbar display, calculate height */
if (tb)
/* XXX: GNUstep has not yet implemented the first method below, added
}
+
/* ==========================================================================
Color management
========================================================================== */
+
NSColor *
ns_lookup_indexed_color (unsigned long idx, struct frame *f)
{
color_table->size * sizeof (NSColor *));
}
idx = color_table->avail++;
- index = [NSNumber numberWithUnsignedInt: idx];
}
color_table->colors[idx] = color;
void
ns_free_indexed_color (unsigned long idx, struct frame *f)
{
- struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
+ struct ns_color_table *color_table;
NSColor *color;
- if (!idx)
+ NSNumber *index;
+
+ if (!f)
+ return;
+
+ 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");
+ return;
+ }
+
+ index = [NSNumber numberWithUnsignedInt: idx];
+ if ([color_table->empty_indices containsObject: index]) {
+ 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;
/* Direct colors (hex values) */
if (hex)
{
- unsigned int color = 0;
+ unsigned long color = 0;
if (sscanf (hex, "%x", &color))
{
- float f1 = ((color >> 24) & 0xff) / 255.0;
- float f2 = ((color >> 16) & 0xff) / 255.0;
- float f3 = ((color >> 8) & 0xff) / 255.0;
- float f4 = ((color ) & 0xff) / 255.0;
+ float f1, f2, f3, f4;
+ /* Assume it's either 1 byte or 2 per channel... */
+ if (strlen(hex) > 8) {
+ f1 = ((color >> 48) & 0xffff) / 65535.0;
+ f2 = ((color >> 32) & 0xffff) / 65535.0;
+ f3 = ((color >> 16) & 0xffff) / 65535.0;
+ f4 = ((color ) & 0xffff) / 65535.0;
+ } else {
+ f1 = ((color >> 24) & 0xff) / 255.0;
+ f2 = ((color >> 16) & 0xff) / 255.0;
+ f3 = ((color >> 8) & 0xff) / 255.0;
+ f4 = ((color ) & 0xff) / 255.0;
+ }
switch (color_space)
{
NSEnumerator *lenum, *cenum;
NSString *name;
NSColorList *clist;
+
#ifdef NS_IMPL_GNUSTEP
/* XXX: who is wrong, the requestor or the implementation? */
if ([nsname compare: @"Highlight" options: NSCaseInsensitiveSearch]
== NSOrderedSame)
nsname = @"highlightColor";
#endif
- if ([nsname compare: @"dark blue" options: NSCaseInsensitiveSearch]
- == NSOrderedSame
- || [nsname compare: @"darkblue" options: NSCaseInsensitiveSearch]
- == NSOrderedSame)
- nsname = @"navy blue";
lenum = [[NSColorList availableColorLists] objectEnumerator];
while ( (clist = [lenum nextObject]) && new == nil)
}
+void
+x_set_frame_alpha (struct frame *f)
+/* --------------------------------------------------------------------------
+ change the entire-frame transparency
+ -------------------------------------------------------------------------- */
+{
+ struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
+ EmacsView *view = FRAME_NS_VIEW (f);
+ double alpha = 1.0;
+ double alpha_min = 1.0;
+
+ if (dpyinfo->x_highlight_frame == f)
+ alpha = f->alpha[0];
+ else
+ alpha = f->alpha[1];
+
+ if (FLOATP (Vframe_alpha_lower_limit))
+ alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
+ else if (INTEGERP (Vframe_alpha_lower_limit))
+ alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
+
+ if (alpha < 0.0)
+ return;
+ else if (1.0 < alpha)
+ alpha = 1.0;
+ else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
+ alpha = alpha_min;
+
+#ifdef NS_IMPL_COCOA
+ [[view window] setAlphaValue: alpha];
+#endif
+}
+
/* ==========================================================================
known as last_mouse_glyph.
------------------------------------------------------------------------ */
{
- NSTRACE (note_mouse_movement);
+// NSTRACE (note_mouse_movement);
XSETFRAME (last_mouse_motion_frame, frame);
-
+
/* Note, this doesn't get called for enter/leave, since we don't have a
position. Those are taken care of in the corresponding NSView methods. */
if (!view || !face)
return;
+ NSTRACE (ns_clear_frame_area);
+
r = NSIntersectionRect (r, [view frame]);
ns_focus (f, &r, 1);
[ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
int oldVH = row->visible_height;
row->visible_height = p->h;
row->y -= rowY - p->y;
- ns_clip_to_row (w, row, -1, NULL);
+ ns_clip_to_row (w, row, -1, NO);
row->y = oldY;
row->visible_height = oldVH;
}
int on_p, int active_p)
/* --------------------------------------------------------------------------
External call (RIF): draw cursor
+ (modeled after x_draw_window_cursor
+ FIXME: cursor_width is effectively bogus -- it sometimes gets set
+ in xdisp.c set_frame_cursor_types, sometimes left uninitialized;
+ DON'T USE IT (no other terms do)
-------------------------------------------------------------------------- */
{
NSRect r, s;
int fx, fy, h;
struct frame *f = WINDOW_XFRAME (w);
struct glyph *phys_cursor_glyph;
- int overspill;
- unsigned char drawGlyph = 0, cursorType, oldCursorType;
+ int overspill, cursorToDraw;
NSTRACE (dumpcursor);
+//fprintf(stderr, "drawcursor (%d,%d) activep = %d\tonp = %d\tc_type = %d\twidth = %d\n",x,y, active_p,on_p,cursor_type,cursor_width);
if (!on_p)
- return;
+ return;
w->phys_cursor_type = cursor_type;
- w->phys_cursor_on_p = 1;
+ w->phys_cursor_on_p = on_p;
if (cursor_type == NO_CURSOR)
{
if (overspill > 0)
r.size.width -= overspill;
- /* TODO: 23: use emacs stored f->cursor_type instead of ns-specific */
- oldCursorType = FRAME_CURSOR (f);
- cursorType = FRAME_CURSOR (f) = FRAME_NEW_CURSOR (f);
- f->output_data.ns->current_cursor_color
- = f->output_data.ns->desired_cursor_color;
-
/* TODO: only needed in rare cases with last-resort font in HELLO..
should we do this more efficiently? */
- ns_clip_to_row (w, glyph_row, -1, NULL);
-/* ns_focus (f, &r, 1); */
-
- if (FRAME_LAST_INACTIVE (f))
- {
- /* previously hollow box; clear entire area */
- [FRAME_BACKGROUND_COLOR (f) set];
- NSRectFill (r);
- drawGlyph = 1;
- FRAME_LAST_INACTIVE (f) = NO;
- }
-
- /* prepare to draw */
- if (cursorType == no_highlight || cursor_type == NO_CURSOR)
- {
- /* clearing for blink: erase the cursor itself */
- [FRAME_BACKGROUND_COLOR (f) set];
- cursorType = oldCursorType; /* just clear what we had before */
- }
- else
- [FRAME_CURSOR_COLOR (f) set];
+ ns_clip_to_row (w, glyph_row, -1, NO); /* do ns_focus(f, &r, 1); if remove */
+ [FRAME_CURSOR_COLOR (f) set];
- if (!active_p)
- {
- /* inactive window: ignore what we just set and use a hollow box */
- cursorType = hollow_box;
- [FRAME_CURSOR_COLOR (f) set];
- }
+#ifdef NS_IMPL_COCOA
+ /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
+ atomic. Cleaner ways of doing this should be investigated.
+ One way would be to set a global variable DRAWING_CURSOR
+ when making the call to draw_phys..(), don't focus in that
+ case, then move the ns_unfocus() here after that call. */
+ NSDisableScreenUpdates ();
+#endif
- switch (cursorType)
+ cursorToDraw = active_p ? cursor_type : HOLLOW_BOX_CURSOR;
+ switch (cursorToDraw)
{
- case no_highlight:
+ case NO_CURSOR:
break;
- case filled_box:
+ case FILLED_BOX_CURSOR:
NSRectFill (r);
- drawGlyph = 1;
break;
- case hollow_box:
+ case HOLLOW_BOX_CURSOR:
NSRectFill (r);
[FRAME_BACKGROUND_COLOR (f) set];
NSRectFill (NSInsetRect (r, 1, 1));
[FRAME_CURSOR_COLOR (f) set];
- drawGlyph = 1;
break;
- case underscore:
+ case HBAR_CURSOR:
s = r;
s.origin.y += lrint (0.75 * s.size.height);
+ s.size.width = min (FRAME_COLUMN_WIDTH (f), s.size.width);
s.size.height = lrint (s.size.height * 0.25);
NSRectFill (s);
break;
- case bar:
+ case BAR_CURSOR:
s = r;
- s.size.width = 1;
+ s.size.width = min (cursor_width, 2); //FIXME(see above)
NSRectFill (s);
break;
}
ns_unfocus (f);
- /* if needed, draw the character under the cursor */
- if (drawGlyph)
+ /* draw the character under the cursor */
+ if (cursorToDraw != NO_CURSOR)
draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+
+#ifdef NS_IMPL_COCOA
+ NSEnableScreenUpdates ();
+#endif
+
}
struct face *face;
NSRect r = NSMakeRect (x, y0, 2, y1-y0);
+ NSTRACE (ns_draw_vertical_window_border);
+
face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
if (face)
[ns_lookup_indexed_color(face->foreground, f) set];
static inline NSRect
+ns_fix_rect_ibw (NSRect r, int fibw, int frame_pixel_width)
/* --------------------------------------------------------------------------
Under NS we draw internal borders inside fringes, and want full-width
rendering to go all the way to edge. This function makes that correction.
-------------------------------------------------------------------------- */
-ns_fix_rect_ibw (NSRect r, int fibw, int frame_pixel_width)
{
if (r.origin.y <= fibw+1)
{
NSTRACE (ns_draw_glyph_string);
- if (s->next && s->right_overhang && !s->for_overlaps && s->hl != DRAW_CURSOR)
+ if (s->next && s->right_overhang && !s->for_overlaps/*&&s->hl!=DRAW_CURSOR*/)
{
- xassert (s->next->img == NULL);
- n = ns_get_glyph_string_clip_rect (s->next, r);
- ns_focus (s->f, r, n);
- ns_maybe_dumpglyphs_background (s->next, 1);
- ns_unfocus (s->f);
+ int width;
+ struct glyph_string *next;
+
+ for (width = 0, next = s->next;
+ next && width < s->right_overhang;
+ width += next->width, next = next->next)
+ if (next->first_glyph->type != IMAGE_GLYPH)
+ {
+ n = ns_get_glyph_string_clip_rect (s->next, r);
+ ns_focus (s->f, r, n);
+ ns_maybe_dumpglyphs_background (s->next, 1);
+ ns_unfocus (s->f);
+ next->num_clips = 0;
+ }
}
if (!s->for_overlaps && s->face->box != FACE_NO_BOX
n = ns_get_glyph_string_clip_rect (s, r);
ns_focus (s->f, r, n);
- if (s->for_overlaps || s->gidx > 0)
+ if (s->for_overlaps || (s->cmp_from > 0
+ && ! s->first_glyph->u.cmp.automatic))
s->background_filled_p = 1;
else /* 1 */
ns_maybe_dumpglyphs_background
(s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND :
NS_DUMPGLYPH_NORMAL));
ns_tmp_font = (struct nsfont_info *)s->face->font;
- if (ns_tmp_font == ~0 || ns_tmp_font == NULL)
- ns_tmp_font = FRAME_FONT (s->f);
+ if (ns_tmp_font == NULL)
+ ns_tmp_font = (struct nsfont_info *)FRAME_FONT (s->f);
ns_tmp_font->font.driver->draw
(s, 0, s->nchars, s->x, s->y,
ns_unfocus (s->f);
}
+ s->num_clips = 0;
}
/* If have pending open-file requests, attend to the next one of those. */
if (ns_pending_files && [ns_pending_files count] != 0
- && [NSApp openFile: [ns_pending_files objectAtIndex: 0]])
+ && [(EmacsApp *)NSApp openFile: [ns_pending_files objectAtIndex: 0]])
{
[ns_pending_files removeObjectAtIndex: 0];
}
/* Deal with pending service requests. */
else if (ns_pending_service_names && [ns_pending_service_names count] != 0
- && [NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0]
- withArg: [ns_pending_service_args objectAtIndex: 0]])
+ && [(EmacsApp *)
+ NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0]
+ withArg: [ns_pending_service_args objectAtIndex: 0]])
{
[ns_pending_service_names removeObjectAtIndex: 0];
[ns_pending_service_args removeObjectAtIndex: 0];
repeats: YES]
retain];
- if (!NILP (ns_cursor_blink_mode) && !cursor_blink_entry)
- {
- if (!NUMBERP (ns_cursor_blink_rate))
- ns_cursor_blink_rate = make_float (0.5);
- cursor_blink_entry = [[NSTimer
- scheduledTimerWithTimeInterval: XFLOATINT (ns_cursor_blink_rate)
- target: NSApp
- selector: @selector (cursor_blink_handler:)
- userInfo: 0
- repeats: YES]
- retain];
- }
- else if (NILP (ns_cursor_blink_mode) && cursor_blink_entry)
- {
- if (NUMBERP (ns_cursor_blink_rate))
- ns_cursor_blink_rate = Qnil;
- struct ns_display_info *dpyinfo = x_display_list; /* HACK */
- [cursor_blink_entry invalidate];
- [cursor_blink_entry release];
- cursor_blink_entry = 0;
- if (dpyinfo->x_highlight_frame)
- {
- Lisp_Object tem
- = get_frame_param (dpyinfo->x_highlight_frame, Qcursor_type);
- dpyinfo->x_highlight_frame->output_data.ns->desired_cursor
- = ns_lisp_to_cursor_type (tem);
- }
- }
-
/* Let Application dispatch events until it receives an event of the type
NX_APPDEFINED, which should only be sent by timeout_handler. */
inNsSelect = 1;
========================================================================== */
-static Lisp_Object ns_string_to_lispmod (char *s)
+int
+x_display_pixel_height (dpyinfo)
+ struct ns_display_info *dpyinfo;
+{
+ NSScreen *screen = [NSScreen mainScreen];
+ return [screen frame].size.height;
+}
+
+int
+x_display_pixel_width (dpyinfo)
+ struct ns_display_info *dpyinfo;
+{
+ NSScreen *screen = [NSScreen mainScreen];
+ return [screen frame].size.width;
+}
+
+
+static Lisp_Object ns_string_to_lispmod (const char *s)
/* --------------------------------------------------------------------------
Convert modifier name to lisp symbol
-------------------------------------------------------------------------- */
ns_command_modifier = Qsuper;
ns_control_modifier = Qcontrol;
ns_function_modifier = Qnone;
- ns_cursor_blink_rate = Qnil;
- ns_cursor_blink_mode = Qnil;
ns_expand_space = make_float (0.0);
ns_antialias_text = Qt;
ns_antialias_threshold = 10.0; /* not exposed to lisp side */
NSScreen *screen = [NSScreen mainScreen];
NSWindowDepth depth = [screen depth];
- dpyinfo->width = [screen frame].size.width;
- dpyinfo->height = [screen frame].size.height;
dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */
dpyinfo->resy = 72.27;
dpyinfo->color_p = ![NSDeviceWhiteColorSpace isEqualToString:
struct ns_display_info *dpyinfo = terminal->display_info.ns;
int i;
- /* Protect against recursive calls. Fdelete_frame in
+ /* Protect against recursive calls. delete_frame in
delete_terminal calls us back when it deletes our last frame. */
if (!terminal->name)
return;
Qnil, Qnil, NO, YES);
if (NILP (ns_function_modifier))
ns_function_modifier = Qnone;
- ns_default ("CursorBlinkRate", &ns_cursor_blink_rate,
- make_float (0.5), Qnil, YES, NO);
- if (NUMBERP (ns_cursor_blink_rate))
- ns_cursor_blink_mode = Qt;
ns_default ("ExpandSpace", &ns_expand_space,
make_float (0.5), make_float (0.0), YES, NO);
ns_default ("GSFontAntiAlias", &ns_antialias_text,
#ifdef NS_IMPL_COCOA
{
NSMenu *appMenu;
- id<NSMenuItem> item;
+ NSMenuItem *item;
/* set up the application menu */
svcsMenu = [[EmacsMenu alloc] initWithTitle: @"Services"];
[svcsMenu setAutoenablesItems: NO];
appMenu = [[EmacsMenu alloc] initWithTitle: @"Emacs"];
[appMenu setAutoenablesItems: NO];
mainMenu = [[EmacsMenu alloc] initWithTitle: @""];
+ dockMenu = [[EmacsMenu alloc] initWithTitle: @""];
[appMenu insertItemWithTitle: @"About Emacs"
action: @selector (orderFrontStandardAboutPanel:)
keyEquivalent: @""
atIndex: 0];
[mainMenu setSubmenu: appMenu forItem: item];
+ [dockMenu insertItemWithTitle: @"New Frame"
+ action: @selector (newFrame:)
+ keyEquivalent: @""
+ atIndex: 0];
[NSApp setMainMenu: mainMenu];
[NSApp setAppleMenu: appMenu];
}
+- (void)newFrame: (id)sender
+{
+ struct frame *emacsframe = SELECTED_FRAME ();
+ NSEvent *theEvent = [NSApp currentEvent];
+
+ if (!emacs_event)
+ return;
+ emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
+ emacs_event->code = KEY_NS_NEW_FRAME;
+ emacs_event->modifiers = 0;
+ EV_TRAILER (theEvent);
+}
+
+
+/* Open a file (used by below, after going into queue read by ns_read_socket) */
+- (BOOL) openFile: (NSString *)fileName
+{
+ struct frame *emacsframe = SELECTED_FRAME ();
+ NSEvent *theEvent = [NSApp currentEvent];
+
+ if (!emacs_event)
+ return NO;
+
+ emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
+ emacs_event->code = KEY_NS_OPEN_FILE_LINE;
+ ns_input_file = append2 (ns_input_file, build_string ([fileName UTF8String]));
+ ns_input_line = Qnil; /* can be start or cons start,end */
+ emacs_event->modifiers =0;
+ EV_TRAILER (theEvent);
+
+ return YES;
+}
+
+
/* **************************************************************************
EmacsApp delegate implementation
[NSApp setServicesProvider: NSApp];
ns_send_appdefined (-2);
}
-
+
- (void) terminate: (id)sender
{
}
-/* Open a file (used by below, after going into queue read by ns_read_socket) */
--(BOOL) openFile: (NSString *)fileName
-{
- struct frame *emacsframe = SELECTED_FRAME ();
- NSEvent *theEvent = [NSApp currentEvent];
-
- if (!emacs_event)
- return NO;
-
- emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
- emacs_event->code = KEY_NS_OPEN_FILE_LINE;
- ns_input_file = append2 (ns_input_file, build_string ([fileName UTF8String]));
- ns_input_line = Qnil; /* can be start or cons start,end */
- emacs_event->modifiers =0;
- EV_TRAILER (theEvent);
-
- return YES;
-}
-
-
/* Notification from the Workspace to open a file */
- (BOOL)application: sender openFile: (NSString *)file
{
NSString *file;
while ((file = [files nextObject]) != nil)
[ns_pending_files addObject: file];
- return YES;
+
+/* TODO: when GNUstep implements this (and we require that version of
+ GNUstep), remove. */
+#ifndef NS_IMPL_GNUSTEP
+ [self replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
+#endif /* !NS_IMPL_GNUSTEP */
+
+}
+
+
+/* Handle dock menu requests. */
+- (NSMenu *)applicationDockMenu: (NSApplication *) sender
+{
+ return dockMenu;
}
+
/* TODO: these may help w/IO switching btwn terminal and NSApp */
- (void)applicationDidBecomeActive: (NSNotification *)notification
{
extern void update_window_cursor (struct window *w, int on);
-- (void)cursor_blink_handler: (NSTimer *)cursorEntry
-/* --------------------------------------------------------------------------
- Flash the cursor
- -------------------------------------------------------------------------- */
-{
- struct ns_display_info *dpyinfo = x_display_list; /*HACK, but OK for now */
- struct frame *f = dpyinfo->x_highlight_frame;
- NSTRACE (cursor_blink_handler);
-
- if (!f)
- return;
- if (f->output_data.ns->current_cursor == no_highlight)
- {
- Lisp_Object tem = get_frame_param (f, Qcursor_type);
- f->output_data.ns->desired_cursor = ns_lisp_to_cursor_type (tem);
- }
- else
- {
- f->output_data.ns->desired_cursor = no_highlight;
- }
- update_window_cursor (XWINDOW (FRAME_SELECTED_WINDOW (f)), 1);
- /*x_update_cursor (f, 1); */
-}
-
-
- (void)fd_handler: (NSTimer *) fdEntry
/* --------------------------------------------------------------------------
Check data waiting on file descriptors and terminate if so
if (newFont = [sender convertFont:
((struct nsfont_info *)face->font)->nsfont])
{
+ SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */
+
emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
emacs_event->modifiers = 0;
emacs_event->code = KEY_NS_CHANGE_FONT;
NSView most recently updated (I guess), which is not the correct one.
UPDATE: After multi-TTY merge this happens even w/o NO_SOCK_SIGIO */
if ([[theEvent window] isKindOfClass: [EmacsWindow class]])
- [[(EmacsView *)[theEvent window] delegate] keyDown: theEvent];
+ [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
return;
}
return rect;
}
-- (long)conversationIdentifier
+- (NSInteger)conversationIdentifier
{
- return (long)self;
+ return (NSInteger)self;
}
/* TODO: below here not yet implemented correctly, but may not be needed */
}
-- (void)mouseUp: (NSEvent *)theEvent
+- (void)rightMouseDown: (NSEvent *)theEvent
{
- NSTRACE (mouseUp);
+ NSTRACE (rightMouseDown);
[self mouseDown: theEvent];
}
-- (void)rightMouseDown: (NSEvent *)theEvent
+- (void)otherMouseDown: (NSEvent *)theEvent
{
- NSTRACE (rightMouseDown);
+ NSTRACE (otherMouseDown);
+ [self mouseDown: theEvent];
+}
+
+
+- (void)mouseUp: (NSEvent *)theEvent
+{
+ NSTRACE (mouseUp);
[self mouseDown: theEvent];
}
}
+- (void)otherMouseUp: (NSEvent *)theEvent
+{
+ NSTRACE (otherMouseUp);
+ [self mouseDown: theEvent];
+}
+
+
- (void) scrollWheel: (NSEvent *)theEvent
{
NSTRACE (scrollWheel);
struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
Lisp_Object frame;
- NSTRACE (mouseMoved);
+// NSTRACE (mouseMoved);
last_mouse_movement_time = EV_TIMESTAMP (e);
last_mouse_motion_position
}
+- (void)otherMouseDragged: (NSEvent *)e
+{
+ NSTRACE (otherMouseDragged);
+ [self mouseMoved: e];
+}
+
+
- (BOOL)windowShouldClose: (id)sender
{
NSEvent *e =[[self window] currentEvent];
NSTRACE (windowShouldClose);
windowClosing = YES;
- if (ns_window_num <= 1)
- return NO;
if (!emacs_event)
return NO;
emacs_event->kind = DELETE_WINDOW_EVENT;
x_set_window_size (emacsframe, 0, cols, rows);
ns_send_appdefined (-1);
+
+ /* The following line causes a crash on GNUstep. Adrian Robert
+ says he doesn't remember why he added this line, but removing it
+ doesn't seem to cause problems on OSX, either. */
+#if 0
[NSApp stopModal];
+#endif
}
- (void)windowDidBecomeKey: (NSNotification *)notification
+/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
{
- int val = ns_lisp_to_cursor_type (get_frame_param (emacsframe, Qcursor_type));
struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
struct frame *old_focus = dpyinfo->x_focus_frame;
if (emacsframe != old_focus)
dpyinfo->x_focus_frame = emacsframe;
- /*/last_mouse_frame = emacsframe;? */
-
- if (val >= 0)
- {
- FRAME_NEW_CURSOR (emacsframe) = val;
-/* x_update_cursor (emacsframe, 1); // will happen in ns_frame_rehighlight */
- }
ns_frame_rehighlight (emacsframe);
- (void)windowDidResignKey: (NSNotification *)notification
+/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
{
struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
NSTRACE (windowDidResignKey);
- if (!windowClosing && [[self window] isVisible] == YES)
- {
- FRAME_NEW_CURSOR (emacsframe) = hollow_box;
- x_update_cursor (emacsframe, 1);
- FRAME_LAST_INACTIVE (emacsframe) = YES;
- }
-
- if (dpyinfo->x_highlight_frame == emacsframe)
- dpyinfo->x_highlight_frame = 0;
if (dpyinfo->x_focus_frame == emacsframe)
dpyinfo->x_focus_frame = 0;
- if (dpyinfo->mouse_face_mouse_frame == emacsframe)
+ ns_frame_rehighlight (emacsframe);
+
+ /* FIXME: for some reason needed on second and subsequent clicks away
+ from sole-frame Emacs to get hollow box to show */
+ if (!windowClosing && [[self window] isVisible] == YES)
{
- clear_mouse_face (dpyinfo);
- dpyinfo->mouse_face_mouse_frame = 0;
+ x_update_cursor (emacsframe, 1);
+ x_set_frame_alpha (emacsframe);
}
if (emacs_event)
context_menu_value = [sender tag];
else
find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used,
- emacsframe->menu_bar_vector, [sender tag]);
+ emacsframe->menu_bar_vector,
+ (void *)[sender tag]);
ns_send_appdefined (-1);
return self;
}
int cursorType
= ns_lisp_to_cursor_type (get_frame_param (frame, Qcursor_type));
prevExpandSpace = XFLOATINT (ns_expand_space);
- prevBlinkRate = NILP (ns_cursor_blink_rate)
- ? 0 : XFLOATINT (ns_cursor_blink_rate);
#ifdef NS_IMPL_COCOA
prevUseHighlightColor = ns_use_system_highlight_color;
#endif
[expandSpaceSlider setFloatValue: prevExpandSpace];
- [cursorBlinkSlider setFloatValue: prevBlinkRate];
- [cursorTypeMatrix selectCellWithTag: (cursorType == filled_box ? 1 :
- (cursorType == bar ? 2 :
- (cursorType == underscore ? 3 : 4)))];
+ [cursorTypeMatrix selectCellWithTag: (cursorType == FILLED_BOX_CURSOR ? 1 :
+ (cursorType == BAR_CURSOR ? 2 :
+ (cursorType == HBAR_CURSOR ? 3 : 4)))];
selectItemWithTag (alternateModMenu,
parse_solitary_modifier (ns_alternate_modifier));
selectItemWithTag (commandModMenu,
- (void) setValuesFromPanel
{
- int cursorTag = [[cursorTypeMatrix selectedCell] tag];
int altTag = [[alternateModMenu selectedItem] tag];
int cmdTag = [[commandModMenu selectedItem] tag];
#ifdef NS_IMPL_COCOA
int ctrlTag = [[controlModMenu selectedItem] tag];
int fnTag = [[functionModMenu selectedItem] tag];
#endif
- float blinkRate = [cursorBlinkSlider floatValue];
float expandSpace = [expandSpaceSlider floatValue];
- Lisp_Object old_cursor_blink_mode;
+ int cursorTag = [[cursorTypeMatrix selectedCell] tag];
+ Lisp_Object cursor_type = ns_cursor_type_to_lisp
+ ( cursorTag == 1 ? FILLED_BOX_CURSOR
+ : cursorTag == 2 ? BAR_CURSOR
+ : cursorTag == 3 ? HBAR_CURSOR : HOLLOW_BOX_CURSOR);
if (expandSpace != prevExpandSpace)
{
x_set_window_size (frame, 0, frame->text_cols, frame->text_lines); */
prevExpandSpace = expandSpace;
}
- if (blinkRate != prevBlinkRate)
- {
- old_cursor_blink_mode = ns_cursor_blink_mode;
- if (blinkRate == 0.0)
- {
- ns_cursor_blink_rate = Qnil;
- ns_cursor_blink_mode = Qnil;
- }
- else
- {
- ns_cursor_blink_rate = make_float (blinkRate);
- ns_cursor_blink_mode = Qt;
- }
- if (!EQ (ns_cursor_blink_mode, old_cursor_blink_mode))
- Feval (Fcons (intern ("blink-cursor-mode"), Qnil));
-
- if (blinkRate != 0.0 && prevBlinkRate != 0.0)
- { /* if changed rates, remove blink handler so change picked up */
- struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
- [cursor_blink_entry invalidate];
- [cursor_blink_entry release];
- cursor_blink_entry = 0;
- if (dpyinfo->x_highlight_frame)
- {
- Lisp_Object tem
- = get_frame_param (dpyinfo->x_highlight_frame, Qcursor_type);
- dpyinfo->x_highlight_frame->output_data.ns->desired_cursor
- = ns_lisp_to_cursor_type (tem);
- }
- }
- prevBlinkRate = blinkRate;
- }
- FRAME_NEW_CURSOR (frame)
- = (cursorTag == 1 ? filled_box
- : cursorTag == 2 ? bar
- : cursorTag == 3 ? underscore : hollow_box);
- store_frame_param (frame, Qcursor_type,
- ns_cursor_type_to_lisp (FRAME_NEW_CURSOR (frame)));
+
+ store_frame_param (frame, Qcursor_type, cursor_type);
+ ns_set_cursor_type(frame, cursor_type, Qnil); /* FIXME: do only if changed */
+
ns_alternate_modifier = ns_mod_to_lisp (altTag);
ns_command_modifier = ns_mod_to_lisp (cmdTag);
#ifdef NS_IMPL_COCOA
/* ==========================================================================
Font-related functions; these used to be in nsfaces.m
+ The XLFD functions (115 lines) are an abomination that should be removed.
========================================================================== */
}
-Lisp_Object
-ns_list_fonts (FRAME_PTR f, Lisp_Object pattern, int size, int maxnames)
-/* --------------------------------------------------------------------------
- This is used by the xfaces system. It is expected to speak XLFD.
- -------------------------------------------------------------------------- */
-{
- Lisp_Object list = Qnil,
- rpattern,
- key,
- tem,
- args[2];
- struct re_pattern_buffer *bufp;
- id fm = [NSFontManager sharedFontManager];
- NSEnumerator *fenum, *senum;
- NSArray *membInfo;
- NSString *fontname;
- const char *xlfdName;
- char *pattFam;
- char *patt;
- NSString *famName;
-
- NSTRACE (ns_list_fonts);
-
- CHECK_STRING (pattern);
- patt = SDATA (pattern);
-
-#if 0
-/* temporary: for font_backend, we use fontsets, and when these are defined,
- the old XLFD-based system is used; eventually this will be replaced by
- backend code, but for now we allow specs that are just family names */
- /* if pattern is not XLFD, panic now */
- if (patt[0] != '-')
- error ("ns_list_fonts: X font name (XLFD) expected.");
-
- /* if unicode encoding not requested, also die */
- if (!strstr (patt, "iso10646") && patt[strlen (patt)-3] != '*')
- return Qnil;
-#endif /* 0 */
-
- key = f ? Fcons (pattern, make_number (maxnames)) : Qnil;
- tem = f ? XCDR (FRAME_NS_DISPLAY_INFO (f)->name_list_element) : Qnil;
-
- /* See if we cached the result for this particular query.
- The cache is an alist of the form:
- ((((PATTERN . MAXNAMES) FONTNAME) ...) ...)
- */
- if (f && !NILP (list = Fassoc (key, tem)))
- {
- list = Fcdr_safe (list);
- /* We have a cached list. Don't have to get the list again. */
- if (!NILP (list))
- return list;
- }
-
- if (patt[0] != '-')
- pattFam = patt;
- else
- pattFam = ns_xlfd_to_fontname (patt);
- /* XXX: '*' at beginning matches literally.. */
- if (pattFam[0] == '*')
- pattFam[0] = '.';
-
- /* must start w/family name, but can have other stuff afterwards
- (usually bold and italic specifiers) */
- args[0] = build_string ("^");
- args[1] = build_string (pattFam);
- rpattern = Fconcat (2, args);
- bufp = compile_pattern (rpattern, 0, Vascii_canon_table, 0, 0);
-
- list = Qnil;
- fenum = [[fm availableFontFamilies] objectEnumerator];
- while ( (famName = [fenum nextObject]) )
- {
- NSMutableString *tmp = [famName mutableCopy];
- const char *fname;
- NSRange r;
-
- /* remove spaces, to look like postscript name */
- while ((r = [tmp rangeOfString: @" "]).location != NSNotFound)
- [tmp deleteCharactersInRange: r];
-
- fname = [tmp UTF8String];
- int len = strlen (fname);
- BOOL foundItal;
- const char *synthItalFont;
-
- if (re_search (bufp, fname, len, 0, len, 0) >= 0)
- {
- /* Found a family. Add all variants. If we have no italic variant,
- add a synthItal. */
- senum =[[fm availableMembersOfFontFamily: famName] objectEnumerator];
- foundItal = NO;
- synthItalFont = NULL;
- while (membInfo = [senum nextObject])
- {
- xlfdName
- = ns_fontname_to_xlfd ([[membInfo objectAtIndex: 0]
- UTF8String]);
- list = Fcons (build_string (xlfdName), list);
- if (!synthItalFont)
- {
- NSString *synthName
- = [[membInfo objectAtIndex: 0]
- stringByAppendingString: @"-synthItal"];
- synthItalFont = [synthName UTF8String];
- }
- else if ([[membInfo objectAtIndex: 3] intValue]
- & NSItalicFontMask)
- foundItal = YES;
- }
- if (foundItal == NO)
- {
- xlfdName = ns_fontname_to_xlfd (synthItalFont);
- list = Fcons (build_string (xlfdName), list);
- }
- }
- [tmp release];
- }
-
- /* fallback */
- if (XFASTINT (Flength (list)) == 0)
- list = Fcons (build_string (ns_fontname_to_xlfd ("Monaco")), list);
-
- /* store result in cache */
- if (f != NULL)
- XCDR_AS_LVALUE (FRAME_NS_DISPLAY_INFO (f)->name_list_element)
- = Fcons (Fcons (key, list),
- XCDR (FRAME_NS_DISPLAY_INFO (f)->name_list_element));
- return list;
-}
-
-
/* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */
-const char *
+static const char *
ns_font_to_xlfd (NSFont *nsfont)
/* --------------------------------------------------------------------------
Convert an NS font name to an X font name (XLFD).
{
NSFontManager *mgr = [NSFontManager sharedFontManager];
NSString *sname = [nsfont /*familyName*/fontName];
- char *famName = [sname UTF8String];
+ char *famName = (char *)[sname UTF8String];
char *weightStr = [mgr fontNamed: sname hasTraits: NSBoldFontMask] ?
"bold" : "medium";
char *slantStr = [mgr fontNamed: sname hasTraits: NSItalicFontMask] ?
int i, len;
/* change '-' to '$' to avoid messing w/XLFD separator */
- for (len =strlen (famName), i =0; i<len; i++)
+ for (len = strlen (famName), i =0; i<len; i++)
if (famName[i] == '-')
{
famName[i] = '\0';
return xlfd;
}
-const char *
+static const char *
ns_fontname_to_xlfd (const char *name)
/* --------------------------------------------------------------------------
Convert an NS font name to an X font name (XLFD).
char *name = xmalloc (180);
int i, len;
const char *ret;
-
+
if (!strncmp (xlfd, "--", 2))
sscanf (xlfd, "--%*[^-]-%[^-]179-", name);
else
return ret;
}
+
void
syms_of_nsterm ()
{
Set to none means that the function key is not interpreted by Emacs at all,\n\
allowing it to be used at a lower level for accented character entry.");
- DEFVAR_LISP ("ns-cursor-blink-rate", &ns_cursor_blink_rate,
- "Rate at which the Emacs cursor blinks (in seconds).\n\
-Set to nil to disable blinking.");
-
- DEFVAR_LISP ("ns-cursor-blink-mode", &ns_cursor_blink_mode,
- "Internal variable -- use M-x blink-cursor-mode or preferences\n\
-panel to control this setting.");
-
DEFVAR_LISP ("ns-expand-space", &ns_expand_space,
"Amount by which spacing between lines is expanded (positive)\n\
or shrunk (negative). Zero (the default) means standard line height.\n\
/* Tell emacs about this window system. */
Fprovide (intern ("ns"), Qnil);
- /* TODO: try to move this back into lisp, ns-win.el loaded too late
- right now */
- {
- Lisp_Object args[3] = { intern ("ns-version-string"), build_string ("9.0"),
- build_string ("NS Window system port version number.") };
- Fdefconst (Flist (3, args));
- }
}