]> code.delx.au - gnu-emacs/blobdiff - src/nsterm.m
* nsterm.m: (x_set_frame_alpha): Add prototype. (ns_fake_keydown, EmacsView-keyUp...
[gnu-emacs] / src / nsterm.m
index 6076364514453ed2522b5c0b4a363e992d2337e6..9b89c833cd9846d2757e15e98333a0c510b94505 100644 (file)
@@ -1,5 +1,5 @@
 /* NeXT/Open/GNUstep / MacOSX communication module.
-   Copyright (C) 1989, 1993, 1994, 2005, 2006, 2008
+   Copyright (C) 1989, 1993, 1994, 2005, 2006, 2008, 2009
      Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -25,12 +25,15 @@ MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
 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"
@@ -78,6 +81,7 @@ int term_trace_num = 0;
 #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
@@ -140,7 +144,7 @@ Lisp_Object ns_input_color, ns_input_text, ns_working_text;
 Lisp_Object ns_input_spi_name, ns_input_spi_arg;
 Lisp_Object Vx_toolkit_scroll_bars;
 static Lisp_Object Qmodifier_value;
-/*PENDING: unsure why these defined in term files, anyway we need in keymap.c */
+/* TODO: unsure why these defined in term files, anyway we need in keymap.c */
 Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper;
 extern Lisp_Object Qcursor_color, Qcursor_type, Qns;
 
@@ -167,20 +171,13 @@ Lisp_Object ns_control_modifier;
    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. */
 Lisp_Object ns_expand_space;
 
 /* Control via default 'GSFontAntiAlias' on OS X and GNUstep. */
-int ns_antialias_text;
+Lisp_Object ns_antialias_text;
 
 /* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
    the maximum font size to NOT antialias.  On GNUstep there is currently
@@ -189,17 +186,17 @@ float ns_antialias_threshold;
 
 /* Controls use of an undocumented CG function to do Quickdraw-style font
    smoothing (less heavy) instead of regular Quartz smoothing. */
-int ns_use_qd_smoothing;
+Lisp_Object ns_use_qd_smoothing;
 
 /* Used to pick up AppleHighlightColor on OS X */
-int ns_use_system_highlight_color;
+Lisp_Object ns_use_system_highlight_color;
 NSString *ns_selection_color;
 
 
 NSArray *ns_send_types =0, *ns_return_types =0, *ns_drag_types =0;
 
 /* Display variables */
-struct ns_display_info *ns_display_list; /* Chain of existing displays */
+struct ns_display_info *x_display_list; /* Chain of existing displays */
 Lisp_Object ns_display_name_list;
 long context_menu_value = 0;
 
@@ -215,8 +212,9 @@ static int ns_window_num =0;
 static NSRect uRect;
 static BOOL gsaved = NO;
 BOOL ns_in_resize = NO;
-int ns_tmp_flags; /*PENDING */
-struct nsfont_info *ns_tmp_font; /*PENDING */
+static BOOL ns_fake_keydown = NO;
+int ns_tmp_flags; /* FIXME */
+struct nsfont_info *ns_tmp_font; /* FIXME */
 /*static int debug_lock = 0; */
 
 #ifdef NS_IMPL_COCOA
@@ -234,7 +232,6 @@ static BOOL send_appdefined = YES;
 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;
@@ -267,14 +264,18 @@ static BOOL inNsSelect = 0;
 #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
@@ -297,13 +298,16 @@ static BOOL inNsSelect = 0;
   ns_send_appdefined (-1);                                    \
   }
 
-/*PENDING: get rid of need for these forward declarations */
-static void ns_condemn_scroll_bars (struct frame *f),
-            ns_judge_scroll_bars (struct frame *f);
+void x_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object);
+
+/* TODO: get rid of need for these forward declarations */
+static void ns_condemn_scroll_bars (struct frame *f);
+static void ns_judge_scroll_bars (struct frame *f);
+void x_set_frame_alpha (struct frame *f);
 
 /* unused variables needed for compatibility reasons */
 int x_use_underline_position_properties, x_underline_at_descent_line;
-/* PENDING: figure out what to do with underline_minimum_offset. */
+/* FIXME: figure out what to do with underline_minimum_offset. */
 
 
 /* ==========================================================================
@@ -413,7 +417,6 @@ ns_init_paths ()
         }
     }
 
-  /*PENDING: append to INFOPATH... */
   if (!getenv ("INFOPATH"))
     {
       resourcePath = [resourceDir stringByAppendingPathComponent: @"info"];
@@ -555,7 +558,6 @@ ns_update_begin (struct frame *f)
 {
   NSView *view = FRAME_NS_VIEW (f);
   NSTRACE (ns_update_begin);
-/*fprintf (stderr, "\\%p\n", f); */
 
   ns_updating_frame = f;
   [view lockFocus];
@@ -691,7 +693,7 @@ ns_focus (struct frame *f, NSRect *r, int n)
      the entire window.
    -------------------------------------------------------------------------- */
 {
-  NSTRACE (ns_focus);
+//  NSTRACE (ns_focus);
 #ifdef NS_IMPL_GNUSTEP
   NSRect u;
     if (n == 2)
@@ -764,7 +766,7 @@ ns_unfocus (struct frame *f)
      Internal: Remove focus on given frame
    -------------------------------------------------------------------------- */
 {
-  NSTRACE (ns_unfocus);
+//  NSTRACE (ns_unfocus);
 
   if (gsaved)
     {
@@ -786,7 +788,7 @@ ns_unfocus (struct frame *f)
 
 
 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
    -------------------------------------------------------------------------- */
@@ -847,7 +849,7 @@ ns_ring_bell ()
           r.origin.y += (r.size.height - dim.y) / 2;
           r.size.width = dim.x;
           r.size.height = dim.y;
-          /* PENDING: 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);
@@ -944,38 +946,37 @@ ns_frame_rehighlight (struct frame *frame)
    -------------------------------------------------------------------------- */
 {
   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
-  struct frame *old_highlight = dpyinfo->ns_highlight_frame;
+  struct frame *old_highlight = dpyinfo->x_highlight_frame;
 
   NSTRACE (ns_frame_rehighlight);
-  if (dpyinfo->ns_focus_frame)
+  if (dpyinfo->x_focus_frame)
     {
-      dpyinfo->ns_highlight_frame
-       = (FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->ns_focus_frame))
-           ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->ns_focus_frame))
-           : dpyinfo->ns_focus_frame);
-      if (!FRAME_LIVE_P (dpyinfo->ns_highlight_frame))
+      dpyinfo->x_highlight_frame
+       = (FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
+           ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
+           : dpyinfo->x_focus_frame);
+      if (!FRAME_LIVE_P (dpyinfo->x_highlight_frame))
         {
-          FRAME_FOCUS_FRAME (dpyinfo->ns_focus_frame) = Qnil;
-          dpyinfo->ns_highlight_frame = dpyinfo->ns_focus_frame;
+          FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
+          dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
         }
     }
   else
-      dpyinfo->ns_highlight_frame = 0;
+      dpyinfo->x_highlight_frame = 0;
 
-  if (dpyinfo->ns_highlight_frame &&
-         dpyinfo->ns_highlight_frame != old_highlight)
+  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);
-        }
-      if (dpyinfo->ns_highlight_frame)
-        {
-          /*ns_raise_frame (dpyinfo->ns_highlight_frame); */
-          x_update_cursor (dpyinfo->ns_highlight_frame, 1);
-        }
+         x_set_frame_alpha (old_highlight);
+       }
+      if (dpyinfo->x_highlight_frame)
+       {
+          x_update_cursor (dpyinfo->x_highlight_frame, 1);
+          x_set_frame_alpha (dpyinfo->x_highlight_frame);
+       }
     }
 }
 
@@ -987,7 +988,7 @@ x_make_frame_visible (struct frame *f)
    -------------------------------------------------------------------------- */
 {
   NSTRACE (x_make_frame_visible);
-  /* PENDING: at some points in past this was not needed, as the only place that
+  /* XXX: at some points in past this was not needed, as the only place that
      called this (frame.c:Fraise_frame ()) also called raise_lower;
      if this ends up the case again, comment this out again. */
   if (!FRAME_VISIBLE_P (f))
@@ -1019,8 +1020,8 @@ x_iconify_frame (struct frame *f)
   NSTRACE (x_iconify_frame);
   check_ns ();
 
-  if (dpyinfo->ns_highlight_frame == f)
-    dpyinfo->ns_highlight_frame = 0;
+  if (dpyinfo->x_highlight_frame == f)
+    dpyinfo->x_highlight_frame = 0;
 
   if ([[view window] windowNumber] <= 0)
     {
@@ -1058,10 +1059,10 @@ x_destroy_window (struct frame *f)
   if (FRAME_FACE_CACHE (f))
     free_frame_faces (f);
 
-  if (f == dpyinfo->ns_focus_frame)
-    dpyinfo->ns_focus_frame = 0;
-  if (f == dpyinfo->ns_highlight_frame)
-    dpyinfo->ns_highlight_frame = 0;
+  if (f == dpyinfo->x_focus_frame)
+    dpyinfo->x_focus_frame = 0;
+  if (f == dpyinfo->x_highlight_frame)
+    dpyinfo->x_highlight_frame = 0;
   if (f == dpyinfo->mouse_face_mouse_frame)
     {
       dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
@@ -1155,11 +1156,11 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
 
   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)
-    /* PENDING: GNUstep has not yet implemented the first method below, added
-                in Panther, however the second is incorrect under Cocoa. */
+    /* XXX: GNUstep has not yet implemented the first method below, added
+           in Panther, however the second is incorrect under Cocoa. */
 #ifdef NS_IMPL_GNUSTEP
     FRAME_NS_TOOLBAR_HEIGHT (f)
       = NSHeight ([NSWindow frameRectForContentRect: NSMakeRect (0, 0, 0, 0)
@@ -1235,12 +1236,14 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
 }
 
 
+
 /* ==========================================================================
 
     Color management
 
    ========================================================================== */
 
+
 NSColor *
 ns_lookup_indexed_color (unsigned long idx, struct frame *f)
 {
@@ -1294,7 +1297,6 @@ ns_index_color (NSColor *color, struct frame *f)
                                    color_table->size * sizeof (NSColor *));
         }
       idx = color_table->avail++;
-      index = [NSNumber numberWithUnsignedInt: idx];
     }
 
   color_table->colors[idx] = color;
@@ -1307,10 +1309,26 @@ ns_index_color (NSColor *color, struct frame *f)
 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;
@@ -1328,7 +1346,8 @@ ns_get_color (const char *name, NSColor **col)
    of colors found in the file Emacs.clr. Color formats include:
    - #rrggbb or RGBrrggbb where rr, gg, bb specify red, green and blue in hex
    - ARGBaarrggbb is similar, with aa being the alpha channel (FF = opaque)
-   - HSVhhssvv and AHSVaahhssvv are similar for hue, saturation, value
+   - HSVhhssvv and AHSVaahhssvv (or HSB/AHSB) are similar for hue, saturation,
+     value;
    - CMYKccmmyykk is similar for cyan, magenta, yellow, black. */
 {
   NSColor * new = nil;
@@ -1358,9 +1377,9 @@ ns_get_color (const char *name, NSColor **col)
       return 0;
     }
 
-  /* 23: PENDING: emacs seems to downcase everything before passing it here,
-     which we can work around, except for GRAY, since gray##, where ## is
-     decimal between 0 and 99, is also an X11 colorname. */
+  /* 23: FIXME: emacs seems to downcase everything before passing it here,
+      which we can work around, except for GRAY, since gray##, where ## is
+      decimal between 0 and 99, is also an X11 colorname. */
   if (name[0] == '#')             /* X11 format */
     {
       hex = name + 1;
@@ -1376,12 +1395,14 @@ ns_get_color (const char *name, NSColor **col)
       hex = name + 4;
       color_space = argb;
     }
-  else if (!memcmp (name, "HSV", 3) || !memcmp (name, "hsv", 3))
+  else if (!memcmp (name, "HSV", 3) || !memcmp (name, "hsv", 3) || 
+           !memcmp (name, "HSB", 3) || !memcmp (name, "hsb", 3))
     {
       hex = name + 3;
       color_space = hsv;
     }
-  else if (!memcmp (name, "AHSV", 4) || !memcmp (name, "ahsv", 4))
+  else if (!memcmp (name, "AHSV", 4) || !memcmp (name, "ahsv", 4) ||
+           !memcmp (name, "AHSB", 4) || !memcmp (name, "ahsb", 4))
     {
       hex = name + 4;
       color_space = ahsv;
@@ -1400,13 +1421,22 @@ ns_get_color (const char *name, NSColor **col)
   /* Direct colors (hex values) */
   if (hex)
     {
-      unsigned int color = 0;
+      unsigned long 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)
             {
@@ -1456,17 +1486,13 @@ ns_get_color (const char *name, NSColor **col)
     NSEnumerator *lenum, *cenum;
     NSString *name;
     NSColorList *clist;
+
 #ifdef NS_IMPL_GNUSTEP
-    /* PENDING: who is wrong, the requestor or the implementation? */
+    /* 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)
@@ -1582,7 +1608,7 @@ ns_defined_color (struct frame *f, char *name, XColor *color_def, int alloc,
     return 0;
 
   if (makeIndex && alloc)
-      color_def->pixel = ns_index_color(temp, f);//[temp retain];
+      color_def->pixel = ns_index_color(temp, f); /* [temp retain]; */
 
   [temp getRed: &r green: &g blue: &b alpha: &a];
   color_def->red   = r * 256;
@@ -1618,6 +1644,39 @@ ns_get_rgb_color (struct frame *f, float r, float g, float b, float a)
 }
 
 
+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
+}
+
 
 /* ==========================================================================
 
@@ -1635,7 +1694,7 @@ x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
   NSTRACE (x_set_mouse_pixel_position);
   ns_raise_frame (f);
 #if 0
-  /*PENDING: this does not work, and what about GNUstep? */
+  /* FIXME: this does not work, and what about GNUstep? */
 #ifdef NS_IMPL_COCOA
   [FRAME_NS_VIEW (f) lockFocus];
   PSsetmouse ((float)pix_x, (float)pix_y);
@@ -1674,10 +1733,10 @@ note_mouse_movement (struct frame *frame, float x, float y)
      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. */
 
@@ -1729,8 +1788,8 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
 
   if (last_mouse_scroll_bar != nil && insist == 0)
     {
-      /* PENDING: we do not use this path at the moment because drag events will
-         go directly to the EmacsScroller.  Leaving code in for now. */
+      /* TODO: we do not use this path at the moment because drag events will
+           go directly to the EmacsScroller.  Leaving code in for now. */
       [last_mouse_scroll_bar getMouseMotionPart: (int *)part window: bar_window
                                               x: x y: y];
       if (time) *time = last_mouse_movement_time;
@@ -1748,10 +1807,10 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
       if (last_mouse_frame && FRAME_LIVE_P (last_mouse_frame))
         f = last_mouse_frame;
       else
-        f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame
+        f = dpyinfo->x_focus_frame ? dpyinfo->x_focus_frame
                                     : SELECTED_FRAME ();
 
-      if (f && f->output_data.ns)  /*PENDING: 2nd check no longer needed? */
+      if (f && f->output_data.ns)  /* TODO: 2nd check no longer needed? */
         {
           view = FRAME_NS_VIEW (*fp);
 
@@ -1937,6 +1996,8 @@ ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
   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];
@@ -2210,7 +2271,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
       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;
     }
@@ -2271,22 +2332,26 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
                        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)
     {
@@ -2311,7 +2376,7 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
   r.size.height = h;
   r.size.width = w->phys_cursor_width;
 
-  /* PENDING: if we overwrite the internal border area, it does not get erased;
+  /* FIXME: if we overwrite the internal border area, it does not get erased;
      fix by truncating cursor, but better would be to erase properly */
   overspill = r.origin.x + r.size.width -
     WINDOW_TEXT_TO_FRAME_PIXEL_X (w, WINDOW_BOX_RIGHT_EDGE_X (w) 
@@ -2319,75 +2384,57 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
   if (overspill > 0)
     r.size.width -= overspill;
 
-  /* PENDING: 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;
-
-  /* PENDING: only needed in rare cases with last-resort font in HELLO..
+  /* 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
+
 }
 
 
@@ -2401,6 +2448,8 @@ ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
   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];
@@ -2419,7 +2468,7 @@ show_hourglass (struct atimer *timer)
 
   BLOCK_INPUT;
 
-  /*PENDING: add NSProgressIndicator to selected frame (see macfns.c) */
+  /* TODO: add NSProgressIndicator to selected frame (see macfns.c) */
 
   hourglass_shown_p = 1;
   UNBLOCK_INPUT;
@@ -2432,7 +2481,9 @@ hide_hourglass ()
   if (!hourglass_shown_p)
     return;
 
-  /*PENDING: remove NSProgressIndicator from all frames */
+  BLOCK_INPUT;
+
+  /* TODO: remove NSProgressIndicator from all frames */
 
   hourglass_shown_p = 0;
   UNBLOCK_INPUT;
@@ -2448,11 +2499,11 @@ hide_hourglass ()
 
 
 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)
     {
@@ -2560,7 +2611,7 @@ ns_draw_relief (NSRect r, int thickness, char raised_p,
   if (newBaseCol == nil)
     newBaseCol = [NSColor grayColor];
 
-  if (newBaseCol != baseCol)  /* PENDING: better check */
+  if (newBaseCol != baseCol)  /* TODO: better check */
     {
       [baseCol release];
       baseCol = [newBaseCol retain];
@@ -2692,7 +2743,7 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
           else
             face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
           if (!face->stipple)
-            [(NS_FACE_BACKGROUND (face) != nil
+            [(NS_FACE_BACKGROUND (face) != 0
               ? ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f)
               : FRAME_BACKGROUND_COLOR (s->f)) set];
           else
@@ -2840,20 +2891,29 @@ ns_draw_glyph_string (struct glyph_string *s)
       External (RIF): Main draw-text call.
    -------------------------------------------------------------------------- */
 {
-  /*PENDING (optimize): focus for box and contents draw */
+  /* TODO (optimize): focus for box and contents draw */
   NSRect r[2];
   int n;
   char box_drawn_p = 0;
 
   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
@@ -2891,11 +2951,11 @@ ns_draw_glyph_string (struct glyph_string *s)
                                     - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
               r[0].size.width -= overrun;
 
-              /* PENDING: Try to work between problem where a stretch glyph on
-                 a partially-visible bottom row will clear part of the
-                 modeline, and another where list-buffers headers and similar
-                 rows erroneously have visible_height set to 0.  Not sure
-                 where this is coming from as other terms seem not to show. */
+              /* XXX: Try to work between problem where a stretch glyph on
+                  a partially-visible bottom row will clear part of the
+                  modeline, and another where list-buffers headers and similar
+                  rows erroneously have visible_height set to 0.  Not sure
+                  where this is coming from as other terms seem not to show. */
               r[0].size.height = min (s->height, s->row->visible_height);
             }
 
@@ -2928,7 +2988,8 @@ ns_draw_glyph_string (struct glyph_string *s)
       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
@@ -2939,8 +3000,8 @@ ns_draw_glyph_string (struct glyph_string *s)
                      (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,
@@ -2963,6 +3024,7 @@ ns_draw_glyph_string (struct glyph_string *s)
       ns_unfocus (s->f);
     }
 
+  s->num_clips = 0;
 }
 
 
@@ -3068,14 +3130,15 @@ ns_read_socket (struct terminal *terminal, int expected,
 
   /* 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];
@@ -3086,7 +3149,7 @@ ns_read_socket (struct terminal *terminal, int expected,
          to ourself, otherwise [NXApp run] will never exit.  */
       send_appdefined = YES;
 
-      /*PENDING: from termhooks.h: */
+      /* TODO: from termhooks.h: */
       /* XXX Please note that a non-zero value of EXPECTED only means that
      there is available input on at least one of the currently opened
      terminal devices -- but not necessarily on this device.
@@ -3171,35 +3234,6 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
                                               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 = ns_display_list; /* HACK */
-      [cursor_blink_entry invalidate];
-      [cursor_blink_entry release];
-      cursor_blink_entry = 0;
-      if (dpyinfo->ns_highlight_frame)
-        {
-          Lisp_Object tem
-           = get_frame_param (dpyinfo->ns_highlight_frame, Qcursor_type);
-          dpyinfo->ns_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;
@@ -3433,7 +3467,24 @@ x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
 
    ========================================================================== */
 
-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
    -------------------------------------------------------------------------- */
@@ -3485,13 +3536,11 @@ ns_set_default_prefs ()
   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 = YES;
-  ns_antialias_threshold = 10.0;
-  ns_use_qd_smoothing = NO;
-  ns_use_system_highlight_color = YES;
+  ns_antialias_text = Qt;
+  ns_antialias_threshold = 10.0; /* not exposed to lisp side */
+  ns_use_qd_smoothing = Qnil;
+  ns_use_system_highlight_color = Qt;
 }
 
 
@@ -3534,8 +3583,6 @@ ns_initialize_display_info (struct ns_display_info *dpyinfo)
     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:
@@ -3560,7 +3607,7 @@ ns_initialize_display_info (struct ns_display_info *dpyinfo)
     dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
     dpyinfo->mouse_face_defer = 0;
 
-    dpyinfo->ns_highlight_frame = dpyinfo->ns_focus_frame = NULL;
+    dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL;
 
     dpyinfo->n_fonts = 0;
     dpyinfo->smallest_font_height = 1;
@@ -3593,7 +3640,7 @@ static struct redisplay_interface ns_redisplay_interface =
   x_get_glyph_overhangs, /*23: generic OK */
   x_fix_overlapping_area, /*generic OK */
   ns_draw_fringe_bitmap, /*23 */
-  0, /* define_fringe_bitmap */ /*PENDING: simplify ns_draw_fringe_bitmap? */
+  0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
   0, /* destroy_fringe_bitmap */
   ns_compute_glyph_string_overhangs, /*23 */
   ns_draw_glyph_string, /*23: interface to nsfont.m */
@@ -3608,7 +3655,7 @@ static struct redisplay_interface ns_redisplay_interface =
 static void
 ns_delete_display (struct ns_display_info *dpyinfo)
 {
-  /*PENDING... */
+  /* TODO... */
 }
 
 
@@ -3619,7 +3666,7 @@ ns_delete_terminal (struct terminal *terminal)
   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;
@@ -3714,7 +3761,7 @@ ns_term_init (Lisp_Object display_name)
   /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */
   /*GSDebugAllocationActive (YES); */
   BLOCK_INPUT;
-handling_signal = 0;
+  handling_signal = 0;
 
   if (!ns_initialized)
     {
@@ -3757,8 +3804,8 @@ handling_signal = 0;
     current_kboard = terminal->kboard;
   terminal->kboard->reference_count++;
 
-  dpyinfo->next = ns_display_list;
-  ns_display_list = dpyinfo;
+  dpyinfo->next = x_display_list;
+  x_display_list = dpyinfo;
 
   /* Put it on ns_display_name_list */
   ns_display_name_list = Fcons (Fcons (display_name, Qnil),
@@ -3793,10 +3840,6 @@ handling_signal = 0;
              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,
@@ -3809,7 +3852,7 @@ handling_signal = 0;
              Qt, Qnil, NO, NO);
   ns_default ("UseSystemHighlightColor", &ns_use_system_highlight_color,
              Qt, Qnil, NO, NO);
-  if (ns_use_system_highlight_color == YES)
+  if (EQ (ns_use_system_highlight_color, Qt))
     {
       ns_selection_color = [[NSUserDefaults standardUserDefaults]
                                stringForKey: @"AppleHighlightColor"];
@@ -3820,37 +3863,37 @@ handling_signal = 0;
     ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
 
   {
-    id cl;
-    Lisp_Object tem, tem1;
-    extern Lisp_Object Vsource_directory;
-
-    cl = [NSColorList colorListNamed: @"Emacs"];
+    NSColorList *cl = [NSColorList colorListNamed: @"Emacs"];
 
     if ( cl == nil )
       {
-        /* first try data_dir, then invocation-dir
-           and finally source-directory/etc */
-        tem1 = tem
-         = Fexpand_file_name (build_string ("Emacs.clr"), Vdata_directory);
-        if (NILP (Ffile_exists_p (tem)))
+        Lisp_Object color_file, color_map, color;
+        int r,g,b;
+        unsigned long c;
+        char *name;
+
+        color_file = Fexpand_file_name (build_string ("rgb.txt"),
+                         Fsymbol_value (intern ("data-directory")));
+        if (NILP (Ffile_readable_p (color_file)))
+          fatal ("Could not find %s.\n", SDATA (color_file));
+
+        color_map = Fx_load_color_file (color_file);
+        if (NILP (color_map))
+          fatal ("Could not read %s.\n", SDATA (color_file));
+
+        cl = [[NSColorList alloc] initWithName: @"Emacs"];
+        for ( ; CONSP (color_map); color_map = XCDR (color_map))
           {
-            tem = Fexpand_file_name (build_string ("Emacs.clr"),
-                                     Vinvocation_directory);
-            if (NILP (Ffile_exists_p (tem)))
-              {
-                Lisp_Object newdir
-                 = Fexpand_file_name (build_string ("etc/"),
-                                      Vsource_directory);
-                tem = Fexpand_file_name (build_string ("Emacs.clr"),
-                                         newdir);
-              }
+            color = XCAR (color_map);
+            name = SDATA (XCAR (color));
+            c = XINT (XCDR (color));
+            [cl setColor:
+                  [NSColor colorWithCalibratedRed: RED_FROM_ULONG (c) / 255.0
+                                            green: GREEN_FROM_ULONG (c) / 255.0
+                                             blue: BLUE_FROM_ULONG (c) / 255.0
+                                            alpha: 1.0]
+                  forKey: [NSString stringWithUTF8String: name]];
           }
-
-        cl = [[NSColorList alloc]
-               initWithName: @"Emacs"
-                   fromFile: [NSString stringWithCString: SDATA (tem)]];
-        if (cl ==nil)
-          fatal ("Could not find %s.\n", SDATA (tem1));
         [cl writeToFile: nil];
       }
   }
@@ -3872,13 +3915,14 @@ handling_signal = 0;
 #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:)
@@ -3917,6 +3961,10 @@ handling_signal = 0;
                            keyEquivalent: @""
                                  atIndex: 0];
     [mainMenu setSubmenu: appMenu forItem: item];
+    [dockMenu insertItemWithTitle: @"New Frame"
+                          action: @selector (newFrame:)
+                   keyEquivalent: @""
+                         atIndex: 0];
 
     [NSApp setMainMenu: mainMenu];
     [NSApp setAppleMenu: appMenu];
@@ -3940,157 +3988,18 @@ ns_term_shutdown (int sig)
   if (STRINGP (Vauto_save_list_file_name))
     unlink (SDATA (Vauto_save_list_file_name));
 
-  ns_shutdown_properly = YES;
-  [NSApp terminate: NSApp];
-}
-
-
-void
-syms_of_nsterm ()
-{
-  NSTRACE (syms_of_nsterm);
-  DEFVAR_LISP ("ns-input-file", &ns_input_file,
-              "The file specified in the last NS event.");
-  ns_input_file =Qnil;
-
-  DEFVAR_LISP ("ns-input-text", &ns_input_text,
-              "The data received in the last NS text drag event.");
-  ns_input_text =Qnil;
-
-  DEFVAR_LISP ("ns-working-text", &ns_working_text,
-              "String for visualizing working composition sequence.");
-  ns_working_text =Qnil;
-
-  DEFVAR_LISP ("ns-input-font", &ns_input_font,
-              "The font specified in the last NS event.");
-  ns_input_font =Qnil;
-
-  DEFVAR_LISP ("ns-input-fontsize", &ns_input_fontsize,
-              "The fontsize specified in the last NS event.");
-  ns_input_fontsize =Qnil;
-
-  DEFVAR_LISP ("ns-input-line", &ns_input_line,
-               "The line specified in the last NS event.");
-  ns_input_line =Qnil;
-
-  DEFVAR_LISP ("ns-input-color", &ns_input_color,
-               "The color specified in the last NS event.");
-  ns_input_color =Qnil;
-
-  DEFVAR_LISP ("ns-input-spi-name", &ns_input_spi_name,
-               "The service name specified in the last NS event.");
-  ns_input_spi_name =Qnil;
-
-  DEFVAR_LISP ("ns-input-spi-arg", &ns_input_spi_arg,
-               "The service argument specified in the last NS event.");
-  ns_input_spi_arg =Qnil;
-
-  DEFVAR_LISP ("ns-alternate-modifier", &ns_alternate_modifier,
-               "This variable describes the behavior of the alternate or option key.\n\
-Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
-Set to none means that the alternate / option key is not interpreted by Emacs\n\
-at all, allowing it to be used at a lower level for accented character entry.");
-
-  DEFVAR_LISP ("ns-command-modifier", &ns_command_modifier,
-               "This variable describes the behavior of the command key.\n\
-Set to control, meta, alt, super, or hyper means it is taken to be that key.");
-
-  DEFVAR_LISP ("ns-control-modifier", &ns_control_modifier,
-               "This variable describes the behavior of the control key.\n\
-Set to control, meta, alt, super, or hyper means it is taken to be that key.");
-
-  DEFVAR_LISP ("ns-function-modifier", &ns_function_modifier,
-               "This variable describes the behavior of the function key (on laptops).\n\
-Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
-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\
-(This variable should only be read, never set.)");
-
-  DEFVAR_BOOL ("ns-antialias-text", &ns_antialias_text,
-               "Non-nil (the default) means to render text antialiased. Only has an effect on OS X Panther and above.");
-
-  DEFVAR_BOOL ("ns-use-qd-smoothing", &ns_use_qd_smoothing,
-               "Whether to render text using QuickDraw (less heavy) antialiasing. Only has an effect on OS X Panther and above.  Default is nil (use Quartz smoothing).");
-
-  DEFVAR_BOOL ("ns-use-system-highlight-color",
-               &ns_use_system_highlight_color,
-               "Whether to use the system default (on OS X only) for the highlight color.  Nil means to use standard emacs (prior to version 21) 'grey'.");
-
-  staticpro (&ns_display_name_list);
-  ns_display_name_list = Qnil;
-
-  staticpro (&last_mouse_motion_frame);
-  last_mouse_motion_frame = Qnil;
-
-/*23: now apparently we need to tell emacs what modifiers there are.. */
-  Qmodifier_value = intern ("modifier-value");
-  Qalt = intern ("alt");
-  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
-  Qhyper = intern ("hyper");
-  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
-  Qmeta = intern ("meta");
-  Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
-  Qsuper = intern ("super");
-  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
-  Qcontrol = intern ("control");
-  Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
-
-  /*PENDING: 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
-  Vx_toolkit_scroll_bars = Qt; 
-#else
-  Vx_toolkit_scroll_bars = Qnil;
-#endif
-
-  /* these are unsupported but we need the declarations to avoid whining
-     messages from cus-start.el */
-  DEFVAR_BOOL ("x-use-underline-position-properties",
-              &x_use_underline_position_properties,
-     doc: /* NOT SUPPORTED UNDER NS.
-*Non-nil means make use of UNDERLINE_POSITION font properties.
-A value of nil means ignore them.  If you encounter fonts with bogus
-UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
-to 4.1, set this to nil.
-
-NOTE: Not supported on Mac yet.  */);
-  x_use_underline_position_properties = 0;
-
-  DEFVAR_BOOL ("x-underline-at-descent-line",
-              &x_underline_at_descent_line,
-     doc: /* NOT SUPPORTED UNDER NS.
-*Non-nil means to draw the underline at the same place as the descent line.
-A value of nil means to draw the underline according to the value of the
-variable `x-use-underline-position-properties', which is usually at the
-baseline level.  The default value is nil.  */);
-  x_underline_at_descent_line = 0;
-
-  /* Tell emacs about this window system. */
-  Fprovide (intern ("ns-windowing"), Qnil);
-  /* PENDING: 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));
-  }
+  if (sig == 0 || sig == SIGTERM)
+    {
+      ns_shutdown_properly = YES;
+      [NSApp terminate: NSApp];
+    }
+  else // force a stack trace to happen
+    {
+      abort();
+    }
 }
 
 
-
 /* ==========================================================================
 
     EmacsApp implementation
@@ -4171,24 +4080,58 @@ baseline level.  The default value is nil.  */);
 }
 
 
-/* **************************************************************************
+- (void)newFrame: (id)sender
+{
+  struct frame *emacsframe = SELECTED_FRAME ();
+  NSEvent *theEvent = [NSApp currentEvent];
 
-      EmacsApp delegate implementation
+  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);
+}
 
-   ************************************************************************** */
 
-- (void)applicationDidFinishLaunching: (NSNotification *)notification
-/* --------------------------------------------------------------------------
-     When application is loaded, terminate event loop in ns_term_init
-   -------------------------------------------------------------------------- */
+/* Open a file (used by below, after going into queue read by ns_read_socket) */
+- (BOOL) openFile: (NSString *)fileName
 {
-  NSTRACE (applicationDidFinishLaunching);
-  [NSApp setServicesProvider: NSApp];
-  ns_send_appdefined (-2);
-}
+  struct frame *emacsframe = SELECTED_FRAME ();
+  NSEvent *theEvent = [NSApp currentEvent];
 
-- (void) terminate: (id)sender
+  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
+
+   ************************************************************************** */
+
+- (void)applicationDidFinishLaunching: (NSNotification *)notification
+/* --------------------------------------------------------------------------
+     When application is loaded, terminate event loop in ns_term_init
+   -------------------------------------------------------------------------- */
+{
+  NSTRACE (applicationDidFinishLaunching);
+  [NSApp setServicesProvider: NSApp];
+  ns_send_appdefined (-2);
+}
+
+
+- (void) terminate: (id)sender
 {
   BLOCK_INPUT;
   if (ns_shutdown_properly)
@@ -4212,7 +4155,7 @@ baseline level.  The default value is nil.  */);
       Fcons (build_string ("Cancel"), Qnil),
       Fcons (build_string ("Save and Exit"), Qt));
   Lisp_Object res = ns_popup_dialog (Qt, contents, Qnil);
-fprintf (stderr, "res = %d\n", EQ (res, Qt)); // FIXME
+fprintf (stderr, "res = %d\n", EQ (res, Qt)); /* FIXME */
   if (EQ (res, Qt))
     {
       Feval (Fcons (intern ("save-buffers-kill-emacs"), Qnil));
@@ -4222,26 +4165,6 @@ fprintf (stderr, "res = %d\n", EQ (res, Qt)); // FIXME
 }
 
 
-/* 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
 {
@@ -4273,10 +4196,24 @@ fprintf (stderr, "res = %d\n", EQ (res, Qt)); // FIXME
   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 */
+
 }
 
-/*PENDING: these may help w/IO switching btwn terminal and NSApp */
+
+/* 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
 {
 }
@@ -4305,31 +4242,6 @@ fprintf (stderr, "res = %d\n", EQ (res, Qt)); // FIXME
 
 extern void update_window_cursor (struct window *w, int on);
 
-- (void)cursor_blink_handler: (NSTimer *)cursorEntry
-/* --------------------------------------------------------------------------
-     Flash the cursor
-   -------------------------------------------------------------------------- */
-{
-  struct ns_display_info *dpyinfo = ns_display_list; /*HACK, but OK for now */
-  struct frame *f = dpyinfo->ns_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
@@ -4435,16 +4347,14 @@ extern void update_window_cursor (struct window *w, int on);
   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;
 
       size = [newFont pointSize];
-      /* PENDING: stick w/integer sizes for now. */
-/*        if (size == lrint (size)) */
-        ns_input_fontsize = make_number (lrint (size));
-/*          else
-            ns_input_fontsize = make_float (size); */
+      ns_input_fontsize = make_number (lrint (size));
       ns_input_font = build_string ([[newFont familyName] UTF8String]);
       EV_TRAILER (e);
     }
@@ -4473,6 +4383,7 @@ extern void update_window_cursor (struct window *w, int on);
 }
 
 
+
 /*****************************************************************************/
 /* Keyboard handling. */
 #define NS_KEYLOG 0
@@ -4489,27 +4400,27 @@ extern void update_window_cursor (struct window *w, int on);
   NSTRACE (keyDown);
 
   /* Rhapsody and OS X give up and down events for the arrow keys */
-  if ([theEvent type] != NSKeyDown)
+  if (ns_fake_keydown == YES)
+    ns_fake_keydown = NO;
+  else if ([theEvent type] != NSKeyDown)
     return;
 
   if (!emacs_event)
     return;
 
-/*#if defined (COCOA_EXPERIMENTAL_CTRL_G) */
  if (![[self window] isKeyWindow])
    {
-     /* PENDING: Using NO_SOCK_SIGIO like Carbon causes a condition in which,
-        when Emacs display updates a different frame from the current one,
-        and temporarily selects it, then processes some interrupt-driven
-        input (dispnew.c:3878), OS will send the event to the correct NSWindow,
-        but for some reason that window has its first responder set to the
-        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 */
+     /* XXX: Using NO_SOCK_SIGIO like Carbon causes a condition in which,
+         when Emacs display updates a different frame from the current one,
+         and temporarily selects it, then processes some interrupt-driven
+         input (dispnew.c:3878), OS will send the event to the correct NSWindow,
+         but for some reason that window has its first responder set to the
+         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;
    }
-/*#endif */
 
   if (nsEvArray == nil)
     nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
@@ -4559,7 +4470,7 @@ extern void update_window_cursor (struct window *w, int on);
               && !fnKeysym
               && [[theEvent characters] length] != 0)
             {
-              /* PENDING: the code we get will be unshifted, so if we have
+              /* XXX: the code we get will be unshifted, so if we have
                  a shift modifier, must convert ourselves */
               if (!(flags & NSShiftKeyMask))
                 code = [[theEvent characters] characterAtIndex: 0];
@@ -4586,10 +4497,12 @@ extern void update_window_cursor (struct window *w, int on);
         }
 
       if (flags & NSControlKeyMask)
-          emacs_event->modifiers |= parse_solitary_modifier (ns_control_modifier);
+          emacs_event->modifiers |=
+            parse_solitary_modifier (ns_control_modifier);
 
       if (flags & NS_FUNCTION_KEY_MASK && !fnKeysym)
-          emacs_event->modifiers |= parse_solitary_modifier (ns_function_modifier);
+          emacs_event->modifiers |=
+            parse_solitary_modifier (ns_function_modifier);
 
       if (flags & NSAlternateKeyMask) /* default = meta */
         {
@@ -4602,10 +4515,13 @@ extern void update_window_cursor (struct window *w, int on);
                 emacs_event->modifiers = 0;
             }
           else
-              emacs_event->modifiers |= parse_solitary_modifier (ns_alternate_modifier);
+              emacs_event->modifiers |=
+                parse_solitary_modifier (ns_alternate_modifier);
         }
 
-/*fprintf (stderr,"code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",code,fnKeysym,flags,emacs_event->modifiers); */
+  if (NS_KEYLOG)
+    fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",
+             code, fnKeysym, flags, emacs_event->modifiers);
 
       /* if it was a function key or had modifiers, pass it directly to emacs */
       if (fnKeysym || (emacs_event->modifiers
@@ -4635,7 +4551,7 @@ extern void update_window_cursor (struct window *w, int on);
   firstTime = NO;
 
   if (NS_KEYLOG && !processingCompose)
-    fprintf (stderr, "Begin compose sequence.\n");
+    fprintf (stderr, "keyDown: Begin compose sequence.\n");
 
   processingCompose = YES;
   [nsEvArray addObject: theEvent];
@@ -4644,6 +4560,26 @@ extern void update_window_cursor (struct window *w, int on);
 }
 
 
+#ifdef NS_IMPL_COCOA
+/* Needed to pick up Ctrl-tab and possibly other events that OS X has
+   decided not to send key-down for.
+   See http://osdir.com/ml/editors.vim.mac/2007-10/msg00141.html
+   If it matches one of these, send it on to keyDown. */
+-(void)keyUp: (NSEvent *)theEvent
+{
+  int flags = [theEvent modifierFlags];
+  int code = [theEvent keyCode];
+  if (code == 0x30 && (flags & NSControlKeyMask) && !(flags & NSCommandKeyMask))
+    {
+      if (NS_KEYLOG)
+        fprintf (stderr, "keyUp: passed test");
+      ns_fake_keydown = YES;
+      [self keyDown: theEvent];
+    }
+}
+#endif
+
+
 /* <NSTextInput> implementation (called through super interpretKeyEvents:]). */
 
 
@@ -4654,7 +4590,8 @@ extern void update_window_cursor (struct window *w, int on);
   int len = [(NSString *)aString length];
   int i;
 
-if (NS_KEYLOG) NSLog (@"insertText '%@'\tlen = %d", aString, len);
+  if (NS_KEYLOG)
+    NSLog (@"insertText '%@'\tlen = %d", aString, len);
   processingCompose = NO;
 
   if (!emacs_event)
@@ -4668,7 +4605,7 @@ if (NS_KEYLOG) NSLog (@"insertText '%@'\tlen = %d", aString, len);
   for (i =0; i<len; i++)
     {
       code = [aString characterAtIndex: i];
-      /* PENDING: still need this? */
+      /* TODO: still need this? */
       if (code == 0x2DC)
         code = '~'; /* 0x7E */
       emacs_event->modifiers = 0;
@@ -4755,13 +4692,15 @@ if (NS_KEYLOG) NSLog (@"insertText '%@'\tlen = %d", aString, len);
 {
   NSRange rng = workingText != nil
     ? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0);
-if (NS_KEYLOG) NSLog (@"markedRange request");
+  if (NS_KEYLOG)
+    NSLog (@"markedRange request");
   return rng;
 }
 
 - (void)unmarkText
 {
-if (NS_KEYLOG) NSLog (@"unmark (accept) text");
+  if (NS_KEYLOG)
+    NSLog (@"unmark (accept) text");
   [self deleteWorkingText];
   processingCompose = NO;
 }
@@ -4772,7 +4711,8 @@ if (NS_KEYLOG) NSLog (@"unmark (accept) text");
   NSRect rect;
   NSPoint pt;
   struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));
-if (NS_KEYLOG) NSLog (@"firstRectForCharRange request");
+  if (NS_KEYLOG)
+    NSLog (@"firstRectForCharRange request");
 
   rect.size.width = theRange.length * FRAME_COLUMN_WIDTH (emacsframe);
   rect.size.height = FRAME_LINE_HEIGHT (emacsframe);
@@ -4786,17 +4726,17 @@ if (NS_KEYLOG) NSLog (@"firstRectForCharRange request");
   return rect;
 }
 
-- (long)conversationIdentifier
+- (NSInteger)conversationIdentifier
 {
-  return (long)self;
+  return (NSInteger)self;
 }
 
-/*PENDING: below here not yet implemented correctly, but may not be needed */
+/* TODO: below here not yet implemented correctly, but may not be needed */
 
 - (void)doCommandBySelector: (SEL)aSelector
 {
-  if (NS_KEYLOG) NSLog (@"Do command by selector: %@",
-                       NSStringFromSelector (aSelector));
+  if (NS_KEYLOG)
+    NSLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector));
 
   if (aSelector == @selector (deleteBackward:))
     {
@@ -4820,13 +4760,15 @@ if (NS_KEYLOG) NSLog (@"firstRectForCharRange request");
 
 - (NSRange)selectedRange
 {
-if (NS_KEYLOG) NSLog (@"selectedRange request");
+  if (NS_KEYLOG)
+    NSLog (@"selectedRange request");
   return NSMakeRange (NSNotFound, 0);
 }
 
 - (unsigned int)characterIndexForPoint: (NSPoint)thePoint
 {
-if (NS_KEYLOG) NSLog (@"characterIndexForPoint request");
+  if (NS_KEYLOG)
+    NSLog (@"characterIndexForPoint request");
   return 0;
 }
 
@@ -4834,7 +4776,8 @@ if (NS_KEYLOG) NSLog (@"characterIndexForPoint request");
 {
   static NSAttributedString *str = nil;
   if (str == nil) str = [NSAttributedString new];
-if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
+  if (NS_KEYLOG)
+    NSLog (@"attributedSubstringFromRange request");
   return str;
 }
 
@@ -4884,16 +4827,23 @@ if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
 }
 
 
-- (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];
 }
 
@@ -4905,6 +4855,13 @@ if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
 }
 
 
+- (void)otherMouseUp: (NSEvent *)theEvent
+{
+  NSTRACE (otherMouseUp);
+  [self mouseDown: theEvent];
+}
+
+
 - (void) scrollWheel: (NSEvent *)theEvent
 {
   NSTRACE (scrollWheel);
@@ -4918,7 +4875,7 @@ if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
   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
@@ -4973,14 +4930,19 @@ if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
 }
 
 
+- (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;
@@ -5087,27 +5049,26 @@ if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
     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->ns_focus_frame;
+  struct frame *old_focus = dpyinfo->x_focus_frame;
 
   NSTRACE (windowDidBecomeKey);
 
   if (emacsframe != old_focus)
-    dpyinfo->ns_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 */
-    }
+    dpyinfo->x_focus_frame = emacsframe;
 
   ns_frame_rehighlight (emacsframe);
 
@@ -5120,26 +5081,22 @@ if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
 
 
 - (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_focus_frame == emacsframe)
+    dpyinfo->x_focus_frame = 0;
 
-  if (dpyinfo->ns_highlight_frame == emacsframe)
-    dpyinfo->ns_highlight_frame = 0;
-  if (dpyinfo->ns_focus_frame == emacsframe)
-    dpyinfo->ns_focus_frame = 0;
+  ns_frame_rehighlight (emacsframe);
 
-  if (dpyinfo->mouse_face_mouse_frame == 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)
@@ -5387,7 +5344,8 @@ if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
     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;
 }
@@ -5726,8 +5684,8 @@ if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
 
 + (float) scrollerWidth
 {
-  /* PENDING: if we want to allow variable widths, this is the place to do it,
-     however neither GNUstep nor Cocoa support it very well */
+  /* TODO: if we want to allow variable widths, this is the place to do it,
+           however neither GNUstep nor Cocoa support it very well */
   return [NSScroller scrollerWidth];
 }
 
@@ -5870,8 +5828,8 @@ if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
   return self;
 }
 
-/* PENDING: unused at moment (see ns_mouse_position) at the moment because
-   drag events will go directly to the EmacsScroller.  Leaving in for now. */
+/* FIXME: unused at moment (see ns_mouse_position) at the moment because
+     drag events will go directly to the EmacsScroller.  Leaving in for now. */
 -(void)getMouseMotionPart: (int *)part window: (Lisp_Object *)window
                         x: (Lisp_Object *)x y: ( Lisp_Object *)y
 {
@@ -6137,18 +6095,15 @@ static void selectItemWithTag (NSPopUpButton *popup, int tag)
   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,
@@ -6158,85 +6113,53 @@ static void selectItemWithTag (NSPopUpButton *popup, int tag)
                     parse_solitary_modifier (ns_control_modifier));
   selectItemWithTag (functionModMenu,
                     parse_solitary_modifier (ns_function_modifier));
-  [smoothFontsCheck setState: ns_antialias_text ? YES : NO];
-  [useQuickdrawCheck setState: ns_use_qd_smoothing ? YES : NO];
-  [useSysHiliteCheck setState: prevUseHighlightColor ? YES : NO];
+  [smoothFontsCheck setState: (NILP (ns_antialias_text) ? NO : YES)];
+  [useQuickdrawCheck setState: (NILP (ns_use_qd_smoothing) ? NO : YES)];
+  [useSysHiliteCheck setState: (NILP (prevUseHighlightColor) ? NO : YES)];
 #endif
 }
 
 
 - (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)
     {
       ns_expand_space = make_float (expandSpace);
-      /* PENDING: more needed: store needed metrics in nsfont_info, update
+      /* TODO: more needed: store needed metrics in nsfont_info, update
          frame default font max_bounds and fontp, recompute faces */
 /*         FRAME_LINE_HEIGHT (frame) *= (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->ns_highlight_frame)
-            {
-              Lisp_Object tem
-               = get_frame_param (dpyinfo->ns_highlight_frame, Qcursor_type);
-              dpyinfo->ns_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);
+  x_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
   ns_control_modifier = ns_mod_to_lisp (ctrlTag);
   ns_function_modifier = ns_mod_to_lisp (fnTag);
-  ns_antialias_text = [smoothFontsCheck state];
-  ns_use_qd_smoothing = [useQuickdrawCheck state];
-  ns_use_system_highlight_color = [useSysHiliteCheck state];
-  if (ns_use_system_highlight_color != prevUseHighlightColor)
+  ns_antialias_text = [smoothFontsCheck state] ? Qt : Qnil;
+  ns_use_qd_smoothing = [useQuickdrawCheck state] ? Qt : Qnil;
+  ns_use_system_highlight_color = [useSysHiliteCheck state] ? Qt : Qnil;
+  if (! EQ (ns_use_system_highlight_color, prevUseHighlightColor))
     {
       prevUseHighlightColor = ns_use_system_highlight_color;
-      if (ns_use_system_highlight_color == YES)
+      if (EQ (ns_use_system_highlight_color, Qt))
         {
           ns_selection_color = [[NSUserDefaults standardUserDefaults]
                                  stringForKey: @"AppleHighlightColor"];
@@ -6304,6 +6227,7 @@ static void selectItemWithTag (NSPopUpButton *popup, int tag)
 /* ==========================================================================
 
    Font-related functions; these used to be in nsfaces.m
+   The XLFD functions (115 lines) are an abomination that should be removed.
 
    ========================================================================== */
 
@@ -6352,141 +6276,9 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
 }
 
 
-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);
-  /*PENDING: '*' 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).
@@ -6495,7 +6287,7 @@ ns_font_to_xlfd (NSFont *nsfont)
 {
   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] ?
@@ -6506,7 +6298,7 @@ ns_font_to_xlfd (NSFont *nsfont)
   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';
@@ -6521,7 +6313,7 @@ ns_font_to_xlfd (NSFont *nsfont)
   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).
@@ -6567,7 +6359,7 @@ ns_xlfd_to_fontname (const char *xlfd)
   char *name = xmalloc (180);
   int i, len;
   const char *ret;
-  
+
   if (!strncmp (xlfd, "--", 2))
     sscanf (xlfd, "--%*[^-]-%[^-]179-", name);
   else
@@ -6601,4 +6393,135 @@ ns_xlfd_to_fontname (const char *xlfd)
   return ret;
 }
 
+
+void
+syms_of_nsterm ()
+{
+  NSTRACE (syms_of_nsterm);
+  DEFVAR_LISP ("ns-input-file", &ns_input_file,
+              "The file specified in the last NS event.");
+  ns_input_file =Qnil;
+
+  DEFVAR_LISP ("ns-input-text", &ns_input_text,
+              "The data received in the last NS text drag event.");
+  ns_input_text =Qnil;
+
+  DEFVAR_LISP ("ns-working-text", &ns_working_text,
+              "String for visualizing working composition sequence.");
+  ns_working_text =Qnil;
+
+  DEFVAR_LISP ("ns-input-font", &ns_input_font,
+              "The font specified in the last NS event.");
+  ns_input_font =Qnil;
+
+  DEFVAR_LISP ("ns-input-fontsize", &ns_input_fontsize,
+              "The fontsize specified in the last NS event.");
+  ns_input_fontsize =Qnil;
+
+  DEFVAR_LISP ("ns-input-line", &ns_input_line,
+               "The line specified in the last NS event.");
+  ns_input_line =Qnil;
+
+  DEFVAR_LISP ("ns-input-color", &ns_input_color,
+               "The color specified in the last NS event.");
+  ns_input_color =Qnil;
+
+  DEFVAR_LISP ("ns-input-spi-name", &ns_input_spi_name,
+               "The service name specified in the last NS event.");
+  ns_input_spi_name =Qnil;
+
+  DEFVAR_LISP ("ns-input-spi-arg", &ns_input_spi_arg,
+               "The service argument specified in the last NS event.");
+  ns_input_spi_arg =Qnil;
+
+  DEFVAR_LISP ("ns-alternate-modifier", &ns_alternate_modifier,
+               "This variable describes the behavior of the alternate or option key.\n\
+Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
+Set to none means that the alternate / option key is not interpreted by Emacs\n\
+at all, allowing it to be used at a lower level for accented character entry.");
+
+  DEFVAR_LISP ("ns-command-modifier", &ns_command_modifier,
+               "This variable describes the behavior of the command key.\n\
+Set to control, meta, alt, super, or hyper means it is taken to be that key.");
+
+  DEFVAR_LISP ("ns-control-modifier", &ns_control_modifier,
+               "This variable describes the behavior of the control key.\n\
+Set to control, meta, alt, super, or hyper means it is taken to be that key.");
+
+  DEFVAR_LISP ("ns-function-modifier", &ns_function_modifier,
+               "This variable describes the behavior of the function key (on laptops).\n\
+Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
+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-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\
+(This variable should only be read, never set.)");
+
+  DEFVAR_LISP ("ns-antialias-text", &ns_antialias_text,
+               "Non-nil (the default) means to render text antialiased. Only has an effect on OS X Panther and above.");
+
+  DEFVAR_LISP ("ns-use-qd-smoothing", &ns_use_qd_smoothing,
+               "Whether to render text using QuickDraw (less heavy) antialiasing. Only has an effect on OS X Panther and above.  Default is nil (use Quartz smoothing).");
+
+  DEFVAR_LISP ("ns-use-system-highlight-color",
+               &ns_use_system_highlight_color,
+               "Whether to use the system default (on OS X only) for the highlight color.  Nil means to use standard emacs (prior to version 21) 'grey'.");
+
+  staticpro (&ns_display_name_list);
+  ns_display_name_list = Qnil;
+
+  staticpro (&last_mouse_motion_frame);
+  last_mouse_motion_frame = Qnil;
+
+  /*23: now apparently we need to tell emacs what modifiers there are.. */
+  Qmodifier_value = intern ("modifier-value");
+  Qalt = intern ("alt");
+  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
+  Qhyper = intern ("hyper");
+  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
+  Qmeta = intern ("meta");
+  Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
+  Qsuper = intern ("super");
+  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+  Qcontrol = intern ("control");
+  Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
+
+  /* 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
+  Vx_toolkit_scroll_bars = Qt;
+#else
+  Vx_toolkit_scroll_bars = Qnil;
+#endif
+
+  /* these are unsupported but we need the declarations to avoid whining
+     messages from cus-start.el */
+  DEFVAR_BOOL ("x-use-underline-position-properties",
+              &x_use_underline_position_properties,
+     doc: /* NOT SUPPORTED UNDER NS.
+*Non-nil means make use of UNDERLINE_POSITION font properties.
+A value of nil means ignore them.  If you encounter fonts with bogus
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
+to 4.1, set this to nil.
+
+NOTE: Not supported on Mac yet.  */);
+  x_use_underline_position_properties = 0;
+
+  DEFVAR_BOOL ("x-underline-at-descent-line",
+              &x_underline_at_descent_line,
+     doc: /* NOT SUPPORTED UNDER NS.
+*Non-nil means to draw the underline at the same place as the descent line.
+A value of nil means to draw the underline according to the value of the
+variable `x-use-underline-position-properties', which is usually at the
+baseline level.  The default value is nil.  */);
+  x_underline_at_descent_line = 0;
+
+  /* Tell emacs about this window system. */
+  Fprovide (intern ("ns"), Qnil);
+}
+
+
 // arch-tag: 6eaa8f7d-a69b-4e1c-b43d-ab31defbe0d2