changeset 97569:09c3a29de655

Clear cursor properly rather than redrawing the area. Respect width of bar cursors. remove ns-specific code for cursor blinking.
author David Reitter <david.reitter@gmail.com>
date Wed, 20 Aug 2008 17:46:37 +0000
parents b7e30775f9ce
children 0bd8c433ca1f
files src/nsterm.m
diffstat 1 files changed, 127 insertions(+), 152 deletions(-) [+]
line wrap: on
line diff
--- a/src/nsterm.m	Wed Aug 20 17:39:14 2008 +0000
+++ b/src/nsterm.m	Wed Aug 20 17:46:37 2008 +0000
@@ -168,13 +168,6 @@
    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. */
@@ -235,7 +228,6 @@
 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;
@@ -2270,6 +2262,10 @@
                        int on_p, int active_p)
 /* --------------------------------------------------------------------------
      External call (RIF): draw cursor
+     (modeled after x_draw_window_cursor and erase_phys_cursor.
+     FIXME: erase_phys_cursor is called from display_and_set_cursor,
+     called from update_window_cursor/x_update_window_end/...
+     Why do we have to duplicate this code?
    -------------------------------------------------------------------------- */
 {
   NSRect r, s;
@@ -2278,14 +2274,23 @@
   struct glyph *phys_cursor_glyph;
   int overspill;
   unsigned char drawGlyph = 0, cursorType, oldCursorType;
+  int new_cursor_type;
+  int new_cursor_width;
+  int active_cursor;
+  enum draw_glyphs_face hl;
+  struct glyph_matrix *active_glyphs = w->current_matrix;
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  int hpos = w->phys_cursor.hpos;
+  int vpos = w->phys_cursor.vpos;
+  struct glyph_row *cursor_row;
 
   NSTRACE (dumpcursor);
 
-  if (!on_p)
+  if (!on_p) // check this?    && !w->phys_cursor_on_p)
       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)
     {
@@ -2318,9 +2323,10 @@
   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);
+
+  /* TODO: 23: use emacs stored cursor color instead of ns-specific */
   f->output_data.ns->current_cursor_color
     = f->output_data.ns->desired_cursor_color;
 
@@ -2342,51 +2348,125 @@
   if (cursorType == no_highlight || cursor_type == NO_CURSOR)
     {
       /* clearing for blink: erase the cursor itself */
+
+      /* No cursor displayed or row invalidated => nothing to do on the
+	 screen.  */
+      if (w->phys_cursor_type == NO_CURSOR)
+	return;
+
+      /* VPOS >= active_glyphs->nrows means that window has been resized.
+	 Don't bother to erase the cursor.  */
+      if (vpos >= active_glyphs->nrows)
+	return;
+
+      /* If row containing cursor is marked invalid, there is nothing we
+	 can do.  */
+      cursor_row = MATRIX_ROW (active_glyphs, vpos);
+      if (!cursor_row->enabled_p)
+	return;
+
+      /* If line spacing is > 0, old cursor may only be partially visible in
+	 window after split-window.  So adjust visible height.  */
+      cursor_row->visible_height = min (cursor_row->visible_height,
+					window_text_bottom_y (w) - cursor_row->y);
+
+      /* If row is completely invisible, don't attempt to delete a cursor which
+	 isn't there.  This can happen if cursor is at top of a window, and
+	 we switch to a buffer with a header line in that window.  */
+      if (cursor_row->visible_height <= 0)
+	return;
+
+      /* If cursor is in the fringe, erase by drawing actual bitmap there.  */
+      if (cursor_row->cursor_in_fringe_p)
+	{
+	  cursor_row->cursor_in_fringe_p = 0;
+	  draw_fringe_bitmap (w, cursor_row, 0);
+	  return;
+	}
+
+      /* This can happen when the new row is shorter than the old one.
+	 In this case, either draw_glyphs or clear_end_of_line
+	 should have cleared the cursor.  Note that we wouldn't be
+	 able to erase the cursor in this case because we don't have a
+	 cursor glyph at hand.  */
+      if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
+	return;
+
+      /* If the cursor is in the mouse face area, redisplay that when
+	 we clear the cursor.  */
+      if (! NILP (dpyinfo->mouse_face_window)
+	  && w == XWINDOW (dpyinfo->mouse_face_window)
+	  && (vpos > dpyinfo->mouse_face_beg_row
+	      || (vpos == dpyinfo->mouse_face_beg_row
+		  && hpos >= dpyinfo->mouse_face_beg_col))
+	  && (vpos < dpyinfo->mouse_face_end_row
+	      || (vpos == dpyinfo->mouse_face_end_row
+		  && hpos < dpyinfo->mouse_face_end_col))
+	  /* Don't redraw the cursor's spot in mouse face if it is at the
+	     end of a line (on a newline).  The cursor appears there, but
+	     mouse highlighting does not.  */
+	  && cursor_row->used[TEXT_AREA] > hpos)
+	hl = DRAW_MOUSE_FACE;
+      else
+	hl = DRAW_NORMAL_TEXT;
+      drawGlyph = 1; // just draw the Glyph
       [FRAME_BACKGROUND_COLOR (f) set];
-      cursorType = oldCursorType; /* just clear what we had before */
+
+      NSDisableScreenUpdates ();
     }
   else
-      [FRAME_CURSOR_COLOR (f) set];
-
-  if (!active_p)
-    {
-      /* inactive window: ignore what we just set and use a hollow box */
-      cursorType = hollow_box;
+    { 
+      cursorType = cursor_type;
+      hl = DRAW_CURSOR;
       [FRAME_CURSOR_COLOR (f) set];
-    }
-
-  switch (cursorType)
-    {
-    case no_highlight:
-      break;
-    case filled_box:
-      NSRectFill (r);
-      drawGlyph = 1;
-      break;
-    case hollow_box:
-      NSRectFill (r);
-      [FRAME_BACKGROUND_COLOR (f) set];
-      NSRectFill (NSInsetRect (r, 1, 1));
-      [FRAME_CURSOR_COLOR (f) set];
-      drawGlyph = 1;
-      break;
-    case underscore:
-      s = r;
-      s.origin.y += lrint (0.75 * s.size.height);
-      s.size.height = lrint (s.size.height * 0.25);
-      NSRectFill (s);
-      break;
-    case bar:
-      s = r;
-      s.size.width = 1;
-      NSRectFill (s);
-      break;
+    
+
+      if (!active_p)
+	{
+	  /* inactive window: ignore what we just set and use a hollow box */
+	  cursorType = hollow_box;
+	  [FRAME_CURSOR_COLOR (f) set];
+	}
+
+      NSDisableScreenUpdates ();
+
+      switch (cursorType)
+	{
+	case NO_CURSOR: // no_highlight:
+	  break;
+	case FILLED_BOX_CURSOR: //filled_box:
+	  NSRectFill (r);
+	  drawGlyph = 1;
+	  break;
+	case HOLLOW_BOX_CURSOR: //hollow_box:
+	  NSRectFill (r);
+	  [FRAME_BACKGROUND_COLOR (f) set];
+	  NSRectFill (NSInsetRect (r, 1, 1));
+	  [FRAME_CURSOR_COLOR (f) set];
+	  drawGlyph = 1;
+	  break;
+	case HBAR_CURSOR: // underscore:
+	  s = r;
+	  s.origin.y += lrint (0.75 * s.size.height);
+	  s.size.height = cursor_width; //lrint (s.size.height * 0.25);
+	  NSRectFill (s);
+	  break;
+	case BAR_CURSOR: //bar:
+	  s = r;
+	  s.size.width = cursor_width;
+	  NSRectFill (s);
+	  drawGlyph = 1;
+	  break;
+	}
     }
   ns_unfocus (f);
 
   /* if needed, draw the character under the cursor */
   if (drawGlyph)
-    draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+    draw_phys_cursor_glyph (w, glyph_row, hl);
+
+  NSEnableScreenUpdates ();
+
 }
 
 
@@ -3173,35 +3253,6 @@
                                               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;
@@ -3487,8 +3538,6 @@
   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 */
@@ -3795,10 +3844,6 @@
              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,
@@ -4194,31 +4239,6 @@
 
 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
@@ -6025,15 +6045,12 @@
   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)))];
@@ -6062,9 +6079,7 @@
   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;
 
   if (expandSpace != prevExpandSpace)
     {
@@ -6075,38 +6090,6 @@
            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
@@ -6419,14 +6402,6 @@
 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\