(run-python): Remove '' from sys.path.
[bpt/emacs.git] / src / xdisp.c
index f6d0d85..89dc814 100644 (file)
@@ -167,6 +167,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
+#include <limits.h>
 
 #include "lisp.h"
 #include "keyboard.h"
@@ -196,8 +197,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef WINDOWSNT
 #include "w32term.h"
 #endif
-#ifdef MAC_OS
-#include "macterm.h"
+#ifdef HAVE_NS
+#include "nsterm.h"
+#endif
+#ifdef USE_GTK
+#include "gtkutil.h"
 #endif
 
 #include "font.h"
@@ -208,8 +212,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #define INFINITY 10000000
 
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined(HAVE_NS) || defined (USE_GTK)
 extern void set_frame_menubar P_ ((struct frame *f, int, int));
 extern int pending_menu_activation;
 #endif
@@ -861,11 +865,11 @@ int display_hourglass_p;
 int hourglass_shown_p;
 
 /* If non-null, an asynchronous timer that, when it expires, displays
-    an hourglass cursor on all frames.  */
+   an hourglass cursor on all frames.  */
 struct atimer *hourglass_atimer;
 
 /* Number of seconds to wait before displaying an hourglass cursor.  */
-static Lisp_Object Vhourglass_delay;
+Lisp_Object Vhourglass_delay;
 
 /* Default number of seconds to wait before displaying an hourglass
    cursor.  */
@@ -886,10 +890,6 @@ static Lisp_Object get_it_property P_ ((struct it *it, Lisp_Object prop));
 
 static void handle_line_prefix P_ ((struct it *));
 
-#if 0
-static int invisible_text_between_p P_ ((struct it *, int, int));
-#endif
-
 static void pint2str P_ ((char *, int, int));
 static void pint2hrstr P_ ((char *, int, int));
 static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
@@ -1757,9 +1757,7 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
    text, or we can't tell because W's current matrix is not up to
    date.  */
 
-#ifndef HAVE_CARBON
 static
-#endif
 struct glyph *
 x_y_to_hpos_vpos (w, x, y, hpos, vpos, dx, dy, area)
      struct window *w;
@@ -2096,7 +2094,7 @@ get_phys_cursor_geometry (w, row, glyph, xp, yp, heightp)
      rectangle as wide as the glyph, but use a canonical character
      width instead.  */
   wd = glyph->pixel_width - 1;
-#ifdef HAVE_NTGUI
+#if defined(HAVE_NTGUI) || defined(HAVE_NS)
   wd++; /* Why? */
 #endif
 
@@ -3107,6 +3105,7 @@ handle_stop (it)
   it->current.dpvec_index = -1;
   handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
   it->ignore_overlay_strings_at_pos_p = 0;
+  it->ellipsis_p = 0;
 
   /* Use face of preceding text for ellipsis (if invisible) */
   if (it->selective_display_ellipsis_p)
@@ -3127,10 +3126,14 @@ handle_stop (it)
            {
              /* We still want to show before and after strings from
                 overlays even if the actual buffer text is replaced.  */
-             if (!handle_overlay_change_p || it->sp > 1)
-               return;
-             if (!get_overlay_strings_1 (it, 0, 0))
-               return;
+             if (!handle_overlay_change_p
+                 || it->sp > 1
+                 || !get_overlay_strings_1 (it, 0, 0))
+               {
+                 if (it->ellipsis_p)
+                   setup_for_ellipsis (it, 0);
+                 return;
+               }
              it->ignore_overlay_strings_at_pos_p = 1;
              it->string_from_display_prop_p = 0;
              handle_overlay_change_p = 0;
@@ -3154,6 +3157,12 @@ handle_stop (it)
          if (handle_overlay_change_p)
            handled = handle_overlay_change (it);
        }
+
+      if (it->ellipsis_p)
+       {
+         setup_for_ellipsis (it, 0);
+         break;
+       }
     }
   while (handled == HANDLED_RECOMPUTE_PROPS);
 
@@ -3837,7 +3846,7 @@ handle_invisible_prop (it)
                  it->position.charpos = IT_CHARPOS (*it) - 1;
                  it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
                }
-              setup_for_ellipsis (it, 0);
+             it->ellipsis_p = 1;
              /* Let the ellipsis display before
                 considering any properties of the following char.
                 Fixes jasonr@gnu.org 01 Oct 07 bug.  */
@@ -4859,8 +4868,8 @@ next_overlay_string (it)
       /* No more overlay strings.  Restore IT's settings to what
         they were before overlay strings were processed, and
         continue to deliver from current_buffer.  */
-      int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
 
+      it->ellipsis_p = (it->stack[it->sp - 1].display_ellipsis_p != 0);
       pop_it (it);
       xassert (it->sp > 0
               || it->method == GET_FROM_COMPOSITION
@@ -4876,11 +4885,6 @@ next_overlay_string (it)
         next_element_from_buffer doesn't try it again.  */
       if (NILP (it->string) && IT_CHARPOS (*it) >= it->end_charpos)
        it->overlay_strings_at_end_processed_p = 1;
-
-      /* If we have to display `...' for invisible text, set
-        the iterator up for that.  */
-      if (display_ellipsis_p)
-       setup_for_ellipsis (it, 0);
     }
   else
     {
@@ -6192,7 +6196,12 @@ set_iterator_to_next (it, reseat_p)
          /* IT->string is an overlay string.  Advance to the
             next, if there is one.  */
          if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
-           next_overlay_string (it);
+           {
+             it->ellipsis_p = 0;
+             next_overlay_string (it);
+             if (it->ellipsis_p)
+               setup_for_ellipsis (it, 0);
+           }
        }
       else
        {
@@ -7061,7 +7070,25 @@ move_it_in_display_line (struct it *it,
                         EMACS_INT to_charpos, int to_x,
                         enum move_operation_enum op)
 {
-  move_it_in_display_line_to (it, to_charpos, to_x, op);
+  if (it->line_wrap == WORD_WRAP
+      && (op & MOVE_TO_X))
+    {
+      struct it save_it = *it;
+      int skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
+      /* When word-wrap is on, TO_X may lie past the end
+        of a wrapped line.  Then it->current is the
+        character on the next line, so backtrack to the
+        space before the wrap point.  */
+      if (skip == MOVE_LINE_CONTINUED)
+       {
+         int prev_x = max (it->current_x - 1, 0);
+         *it = save_it;
+         move_it_in_display_line_to
+           (it, -1, prev_x, MOVE_TO_X);
+       }
+    }
+  else
+    move_it_in_display_line_to (it, to_charpos, to_x, op);
 }
 
 
@@ -7277,6 +7304,30 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
 
  out:
 
+  /* On text terminals, we may stop at the end of a line in the middle
+     of a multi-character glyph.  If the glyph itself is continued,
+     i.e. it is actually displayed on the next line, don't treat this
+     stopping point as valid; move to the next line instead (unless
+     that brings us offscreen).  */
+  if (!FRAME_WINDOW_P (it->f)
+      && op & MOVE_TO_POS
+      && IT_CHARPOS (*it) == to_charpos
+      && it->what == IT_CHARACTER
+      && it->nglyphs > 1
+      && it->line_wrap == WINDOW_WRAP
+      && it->current_x == it->last_visible_x - 1
+      && it->c != '\n'
+      && it->c != '\t'
+      && it->vpos < XFASTINT (it->w->window_end_vpos))
+    {
+      it->continuation_lines_width += it->current_x;
+      it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
+      it->current_y += it->max_ascent + it->max_descent;
+      ++it->vpos;
+      last_height = it->max_ascent + it->max_descent;
+      last_max_ascent = it->max_ascent;
+    }
+
   TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
 }
 
@@ -7459,41 +7510,6 @@ move_it_past_eol (it)
 }
 
 
-#if 0 /* Currently not used.  */
-
-/* Return non-zero if some text between buffer positions START_CHARPOS
-   and END_CHARPOS is invisible.  IT->window is the window for text
-   property lookup.  */
-
-static int
-invisible_text_between_p (it, start_charpos, end_charpos)
-     struct it *it;
-     int start_charpos, end_charpos;
-{
-  Lisp_Object prop, limit;
-  int invisible_found_p;
-
-  xassert (it != NULL && start_charpos <= end_charpos);
-
-  /* Is text at START invisible?  */
-  prop = Fget_char_property (make_number (start_charpos), Qinvisible,
-                            it->window);
-  if (TEXT_PROP_MEANS_INVISIBLE (prop))
-    invisible_found_p = 1;
-  else
-    {
-      limit = Fnext_single_char_property_change (make_number (start_charpos),
-                                                Qinvisible, Qnil,
-                                                make_number (end_charpos));
-      invisible_found_p = XFASTINT (limit) < end_charpos;
-    }
-
-  return invisible_found_p;
-}
-
-#endif /* 0 */
-
-
 /* Move IT by a specified number DVPOS of screen lines down.  DVPOS
    negative means move up.  DVPOS == 0 means move to the start of the
    screen line.  NEED_Y_P non-zero means calculate IT->current_y.  If
@@ -8277,6 +8293,9 @@ ensure_echo_area_buffers ()
        sprintf (name, " *Echo Area %d*", i);
        echo_buffer[i] = Fget_buffer_create (build_string (name));
        XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
+       /* to force word wrap in echo area - 
+          it was decided to postpone this*/
+       /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
 
        for (j = 0; j < 2; ++j)
          if (EQ (old_buffer, echo_area_buffer[j]))
@@ -9462,7 +9481,32 @@ x_consider_frame_title (frame)
       if (! STRINGP (f->name)
          || SBYTES (f->name) != len
          || bcmp (title, SDATA (f->name), len) != 0)
-       x_implicitly_set_name (f, make_string (title, len), Qnil);
+        {
+#ifdef HAVE_NS
+          if (FRAME_NS_P (f))
+            {
+              if (!MINI_WINDOW_P(XWINDOW(f->selected_window)))
+                {
+                  if (EQ (fmt, Qt))
+                    ns_set_name_as_filename (f);
+                  else
+                    x_implicitly_set_name (f, make_string(title, len),
+                                           Qnil);
+                }
+            }
+          else
+#endif
+           x_implicitly_set_name (f, make_string (title, len), Qnil);
+        }
+#ifdef HAVE_NS
+      if (FRAME_NS_P (f))
+        {
+          /* do this also for frames with explicit names */
+          ns_implicitly_set_icon_type(f);
+          ns_set_doc_edited(f, Fbuffer_modified_p
+                            (XWINDOW (f->selected_window)->buffer), Qnil);
+        }
+#endif
     }
 }
 
@@ -9557,9 +9601,6 @@ prepare_menu_bars ()
          menu_bar_hooks_run = update_menu_bar (f, 0, menu_bar_hooks_run);
 #ifdef HAVE_WINDOW_SYSTEM
          update_tool_bar (f, 0);
-#ifdef MAC_OS
-         mac_update_title_bar (f, 0);
-#endif
 #endif
          UNGCPRO;
        }
@@ -9572,9 +9613,6 @@ prepare_menu_bars ()
       update_menu_bar (sf, 1, 0);
 #ifdef HAVE_WINDOW_SYSTEM
       update_tool_bar (sf, 1);
-#ifdef MAC_OS
-      mac_update_title_bar (sf, 1);
-#endif
 #endif
     }
 
@@ -9615,19 +9653,10 @@ update_menu_bar (f, save_match_data, hooks_run)
   window = FRAME_SELECTED_WINDOW (f);
   w = XWINDOW (window);
 
-#if 0 /* The if statement below this if statement used to include the
-         condition !NILP (w->update_mode_line), rather than using
-         update_mode_lines directly, and this if statement may have
-         been added to make that condition work.  Now the if
-         statement below matches its comment, this isn't needed.  */
-  if (update_mode_lines)
-    w->update_mode_line = Qt;
-#endif
-
   if (FRAME_WINDOW_P (f)
       ?
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined (HAVE_NS) || defined (USE_GTK)
       FRAME_EXTERNAL_MENU_BAR (f)
 #else
       FRAME_MENU_BAR_LINES (f) > 0
@@ -9685,11 +9714,11 @@ update_menu_bar (f, save_match_data, hooks_run)
          FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
 
          /* Redisplay the menu bar in case we changed it.  */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined (HAVE_NS) || defined (USE_GTK)
          if (FRAME_WINDOW_P (f))
-           {
-#ifdef MAC_OS
+            {
+#if defined (HAVE_NS)
               /* All frames on Mac OS share the same menubar.  So only
                  the selected frame should be allowed to set it.  */
               if (f == SELECTED_FRAME ())
@@ -9700,11 +9729,11 @@ update_menu_bar (f, save_match_data, hooks_run)
            /* On a terminal screen, the menu bar is an ordinary screen
               line, and this makes it get updated.  */
            w->update_mode_line = Qt;
-#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
+#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
          /* In the non-toolkit version, the menu bar is an ordinary screen
             line, and this makes it get updated.  */
          w->update_mode_line = Qt;
-#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
+#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
 
          unbind_to (count, Qnil);
          set_buffer_internal_1 (prev);
@@ -9815,7 +9844,7 @@ update_tool_bar (f, save_match_data)
      struct frame *f;
      int save_match_data;
 {
-#if defined (USE_GTK) || USE_MAC_TOOLBAR
+#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
   int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
   int do_update = WINDOWP (f->tool_bar_window)
@@ -10281,7 +10310,7 @@ redisplay_tool_bar (f)
   struct it it;
   struct glyph_row *row;
 
-#if defined (USE_GTK) || USE_MAC_TOOLBAR
+#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
   if (FRAME_EXTERNAL_TOOL_BAR (f))
     update_frame_tool_bar (f);
   return 0;
@@ -11311,7 +11340,7 @@ redisplay_internal (preserve_echo_area)
        return;
     }
 
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
   if (popup_activated ())
     return;
 #endif
@@ -11375,7 +11404,7 @@ redisplay_internal (preserve_echo_area)
         the whole thing.  */
       windows_or_buffers_changed++;
       SET_FRAME_GARBAGED (sf);
-#ifndef WINDOWSNT
+#ifndef DOS_NT
       set_tty_color_mode (FRAME_TTY (sf), sf);
 #endif
       FRAME_TTY (sf)->previous_frame = sf;
@@ -11501,6 +11530,10 @@ redisplay_internal (preserve_echo_area)
       /* Resized active mini-window to fit the size of what it is
          showing if its contents might have changed.  */
       must_finish = 1;
+/* FIXME: this causes all frames to be updated, which seems unnecessary
+   since only the current frame needs to be considered.  This function needs
+   to be rewritten with two variables, consider_all_windows and
+   consider_all_frames. */
       consider_all_windows_p = 1;
       ++windows_or_buffers_changed;
       ++update_mode_lines;
@@ -11810,11 +11843,6 @@ redisplay_internal (preserve_echo_area)
                  /* Update the display.  */
                  set_window_update_flags (XWINDOW (f->root_window), 1);
                  pause |= update_frame (f, 0, 0);
-#if 0  /* Exiting the loop can leave the wrong value for buffer_shared.  */
-                 if (pause)
-                   break;
-#endif
-
                  f->updated_p = 1;
                }
            }
@@ -12108,11 +12136,6 @@ mark_window_display_accurate_1 (w, accurate_p)
   if (accurate_p)
     {
       w->window_end_valid = w->buffer;
-#if 0 /* This is incorrect with variable-height lines.  */
-      xassert (XINT (w->window_end_vpos)
-              < (WINDOW_TOTAL_LINES (w)
-                 - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
-#endif
       w->update_mode_line = Qnil;
     }
 }
@@ -12613,19 +12636,13 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
-  struct text_pos scroll_margin_pos;
-  struct text_pos pos;
-  struct text_pos startp;
+  struct text_pos pos, startp;
   struct it it;
-  Lisp_Object window_end;
-  int this_scroll_margin;
-  int dy = 0;
-  int scroll_max;
-  int rc;
-  int amount_to_scroll = 0;
-  Lisp_Object aggressive;
-  int height;
+  int this_scroll_margin, scroll_max, rc, height;
+  int dy = 0, amount_to_scroll = 0, scroll_down_p = 0;
   int extra_scroll_margin_lines = last_line_misfit ? 1 : 0;
+  Lisp_Object aggressive;
+  int scroll_limit = INT_MAX / FRAME_LINE_HEIGHT (f);
 
 #if GLYPH_DEBUG
   debug_method_add (w, "try_scrolling");
@@ -12643,69 +12660,67 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   else
     this_scroll_margin = 0;
 
-  /* Force scroll_conservatively to have a reasonable value so it doesn't
-     cause an overflow while computing how much to scroll.  */
-  if (scroll_conservatively)
-    scroll_conservatively = min (scroll_conservatively,
-                                 MOST_POSITIVE_FIXNUM / FRAME_LINE_HEIGHT (f));
-
-  /* Compute how much we should try to scroll maximally to bring point
-     into view.  */
-  if (scroll_step || scroll_conservatively || temp_scroll_step)
-    scroll_max = max (scroll_step,
-                     max (scroll_conservatively, temp_scroll_step));
+  /* Force scroll_conservatively to have a reasonable value, to avoid
+     overflow while computing how much to scroll.  Note that it's
+     fairly common for users to supply scroll-conservatively equal to
+     `most-positive-fixnum', which can be larger than INT_MAX.  */
+  if (scroll_conservatively > scroll_limit)
+    {
+      scroll_conservatively = scroll_limit;
+      scroll_max = INT_MAX;
+    }
+  else if (scroll_step || scroll_conservatively || temp_scroll_step)
+    /* Compute how much we should try to scroll maximally to bring
+       point into view.  */
+    scroll_max = (max (scroll_step,
+                      max (scroll_conservatively, temp_scroll_step))
+                 * FRAME_LINE_HEIGHT (f));
   else if (NUMBERP (current_buffer->scroll_down_aggressively)
           || NUMBERP (current_buffer->scroll_up_aggressively))
-    /* We're trying to scroll because of aggressive scrolling
-       but no scroll_step is set.  Choose an arbitrary one.  Maybe
-       there should be a variable for this.  */
-    scroll_max = 10;
+    /* We're trying to scroll because of aggressive scrolling but no
+       scroll_step is set.  Choose an arbitrary one.  */
+    scroll_max = 10 * FRAME_LINE_HEIGHT (f);
   else
     scroll_max = 0;
-  scroll_max *= FRAME_LINE_HEIGHT (f);
-
-  /* Decide whether we have to scroll down.  Start at the window end
-     and move this_scroll_margin up to find the position of the scroll
-     margin.  */
-  window_end = Fwindow_end (window, Qt);
 
  too_near_end:
 
-  CHARPOS (scroll_margin_pos) = XINT (window_end);
-  BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
-
-  if (this_scroll_margin || extra_scroll_margin_lines)
+  /* Decide whether we have to scroll down.  */
+  if (PT > CHARPOS (startp))
     {
-      start_display (&it, w, scroll_margin_pos);
-      if (this_scroll_margin)
-       move_it_vertically_backward (&it, this_scroll_margin);
-      if (extra_scroll_margin_lines)
-       move_it_by_lines (&it, - extra_scroll_margin_lines, 0);
-      scroll_margin_pos = it.current.pos;
-    }
+      int scroll_margin_y;
 
-  if (PT >= CHARPOS (scroll_margin_pos))
-    {
-      int y0;
+      /* Compute the pixel ypos of the scroll margin, then move it to
+        either that ypos or PT, whichever comes first.  */
+      start_display (&it, w, startp);
+      scroll_margin_y = it.last_visible_y - this_scroll_margin
+       - FRAME_LINE_HEIGHT (f) * extra_scroll_margin_lines;
+      move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
+                 (MOVE_TO_POS | MOVE_TO_Y));
 
-      /* Point is in the scroll margin at the bottom of the window, or
-        below.  Compute a new window start that makes point visible.  */
+      if (PT > CHARPOS (it.current.pos))
+       {
+         /* Point is in the scroll margin at the bottom of the
+            window, or below.  Compute the distance from the scroll
+            margin to PT, and give up if the distance is greater than
+            scroll_max.  */
+         move_it_to (&it, PT, -1, it.last_visible_y - 1, -1,
+                     MOVE_TO_POS | MOVE_TO_Y);
 
-      /* Compute the distance from the scroll margin to PT.
-        Give up if the distance is greater than scroll_max.  */
-      start_display (&it, w, scroll_margin_pos);
-      y0 = it.current_y;
-      move_it_to (&it, PT, 0, it.last_visible_y, -1,
-                 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+         /* To make point visible, we must move the window start down
+            so that the cursor line is visible, which means we have
+            to add in the height of the cursor line.  */
+         dy = line_bottom_y (&it) - scroll_margin_y;
 
-      /* To make point visible, we have to move the window start
-        down so that the line the cursor is in is visible, which
-        means we have to add in the height of the cursor line.  */
-      dy = line_bottom_y (&it) - y0;
+         if (dy > scroll_max)
+           return SCROLLING_FAILED;
 
-      if (dy > scroll_max)
-       return SCROLLING_FAILED;
+         scroll_down_p = 1;
+       }
+    }
 
+  if (scroll_down_p)
+    {
       /* Move the window start down.  If scrolling conservatively,
         move it just enough down to make point visible.  If
         scroll_step is set, move it down by scroll_step.  */
@@ -12745,9 +12760,10 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
     }
   else
     {
+      struct text_pos scroll_margin_pos = startp;
+
       /* See if point is inside the scroll margin at the top of the
          window.  */
-      scroll_margin_pos = startp;
       if (this_scroll_margin)
        {
          start_display (&it, w, startp);
@@ -12996,9 +13012,13 @@ try_cursor_movement (window, startp, scroll_step)
 
       /* Scroll if point within this distance from the top or bottom
         of the window.  This is a pixel value.  */
-      this_scroll_margin = max (0, scroll_margin);
-      this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
-      this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+      if (scroll_margin > 0)
+       {
+         this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+         this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+       }
+      else
+       this_scroll_margin = 0;
 
       top_scroll_margin = this_scroll_margin;
       if (WINDOW_WANTS_HEADER_LINE_P (w))
@@ -13442,7 +13462,6 @@ redisplay_window (window, just_this_one_p)
     {
       /* We set this later on if we have to adjust point.  */
       int new_vpos = -1;
-      int val;
 
       w->force_start = Qnil;
       w->vscroll = 0;
@@ -13476,16 +13495,15 @@ redisplay_window (window, just_this_one_p)
 
       /* Redisplay, then check if cursor has been set during the
         redisplay.  Give up if new fonts were loaded.  */
-      val = try_window (window, startp, 1);
-      if (!val)
+      /* We used to issue a CHECK_MARGINS argument to try_window here,
+        but this causes scrolling to fail when point begins inside
+        the scroll margin (bug#148) -- cyd  */
+      if (!try_window (window, startp, 0))
        {
          w->force_start = Qt;
          clear_glyph_matrix (w->desired_matrix);
          goto need_larger_matrices;
        }
-      /* Point was outside the scroll margins.  */
-      if (val < 0)
-       new_vpos = window_box_height (w) / 2;
 
       if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
        {
@@ -13616,11 +13634,16 @@ redisplay_window (window, just_this_one_p)
          && NILP (do_mouse_tracking)
          && CHARPOS (startp) > BEGV
          && CHARPOS (startp) > BEG + beg_unchanged
-         && CHARPOS (startp) <= Z - end_unchanged)
+         && CHARPOS (startp) <= Z - end_unchanged
+         /* Even if w->start_at_line_beg is nil, a new window may
+            start at a line_beg, since that's how set_buffer_window
+            sets it.  So, we need to check the return value of
+            compute_window_start_on_continuation_line.  (See also
+            bug#197).  */
+         && XMARKER (w->start)->buffer == current_buffer
+         && compute_window_start_on_continuation_line (w))
        {
          w->force_start = Qt;
-         if (XMARKER (w->start)->buffer == current_buffer)
-           compute_window_start_on_continuation_line (w);
          SET_TEXT_POS_FROM_MARKER (startp, w->start);
          goto force_start;
        }
@@ -13747,11 +13770,6 @@ redisplay_window (window, just_this_one_p)
     {
       init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
       move_it_vertically_backward (&it, 0);
-#if 0
-      /* I think this assert is bogus if buffer contains
-        invisible text or images.  KFS.  */
-      xassert (IT_CHARPOS (it) <= PT);
-#endif
       it.current_y = 0;
     }
 
@@ -13912,8 +13930,8 @@ redisplay_window (window, just_this_one_p)
 
       if (FRAME_WINDOW_P (f))
        {
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined (HAVE_NS) || defined (USE_GTK)
          redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
 #else
          redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
@@ -13928,7 +13946,7 @@ redisplay_window (window, just_this_one_p)
 #ifdef HAVE_WINDOW_SYSTEM
       if (FRAME_WINDOW_P (f))
         {
-#if defined (USE_GTK) || USE_MAC_TOOLBAR
+#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
           redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
           redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
@@ -14035,9 +14053,13 @@ try_window (window, pos, check_margins)
     {
       int this_scroll_margin;
 
-      this_scroll_margin = max (0, scroll_margin);
-      this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
-      this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
+      if (scroll_margin > 0)
+       {
+         this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+         this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+       }
+      else
+       this_scroll_margin = 0;
 
       if ((w->cursor.y >= 0    /* not vscrolled */
           && w->cursor.y < this_scroll_margin
@@ -14047,7 +14069,7 @@ try_window (window, pos, check_margins)
             seems to give wrong results.  We don't want to recenter
             when the last line is partly visible, we want to allow
             that case to be handled in the usual way.  */
-         || (w->cursor.y + 1) > it.last_visible_y)
+         || w->cursor.y > it.last_visible_y - this_scroll_margin - 1)
        {
          w->cursor.vpos = -1;
          clear_glyph_matrix (w->desired_matrix);
@@ -17067,10 +17089,11 @@ display_menu_bar (w)
   if (FRAME_X_P (f))
     return;
 #endif
-#ifdef MAC_OS
-  if (FRAME_MAC_P (f))
+
+#ifdef HAVE_NS
+  if (FRAME_NS_P (f))
     return;
-#endif
+#endif /* HAVE_NS */
 
 #ifdef USE_X_TOOLKIT
   xassert (!FRAME_WINDOW_P (f));
@@ -19900,7 +19923,7 @@ left_overwriting (s)
 
 
 /* Return the index of the last glyph following glyph string S that is
-   not overwritten by S because of S's right overhang.  Value is -1 if
+   overwritten by S because of S's right overhang.  Value is -1 if
    no such glyph is found.  */
 
 static int
@@ -21299,25 +21322,33 @@ x_produce_glyphs (it)
        }
       else if (it->char_to_display == '\t')
        {
-         int tab_width = it->tab_width * font->space_width;
-         int x = it->current_x + it->continuation_lines_width;
-         int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
-
-         /* If the distance from the current position to the next tab
-            stop is less than a space character width, use the
-            tab stop after that.  */
-         if (next_tab_x - x < font->space_width)
-           next_tab_x += tab_width;
-
-         it->pixel_width = next_tab_x - x;
-         it->nglyphs = 1;
-         it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
-         it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
-
-         if (it->glyph_row)
+         if (font->space_width > 0)
            {
-             append_stretch_glyph (it, it->object, it->pixel_width,
-                                   it->ascent + it->descent, it->ascent);
+             int tab_width = it->tab_width * font->space_width;
+             int x = it->current_x + it->continuation_lines_width;
+             int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
+
+             /* If the distance from the current position to the next tab
+                stop is less than a space character width, use the
+                tab stop after that.  */
+             if (next_tab_x - x < font->space_width)
+               next_tab_x += tab_width;
+
+             it->pixel_width = next_tab_x - x;
+             it->nglyphs = 1;
+             it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
+             it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+
+             if (it->glyph_row)
+               {
+                 append_stretch_glyph (it, it->object, it->pixel_width,
+                                       it->ascent + it->descent, it->ascent);
+               }
+           }
+         else
+           {
+             it->pixel_width = 0;
+             it->nglyphs = 1;
            }
        }
       else
@@ -22539,7 +22570,10 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
 /* Switch the display of W's cursor on or off, according to the value
    of ON.  */
 
-static void
+#ifndef HAVE_NS
+static
+#endif
+void
 update_window_cursor (w, on)
      struct window *w;
      int on;
@@ -22758,9 +22792,7 @@ cursor_in_mouse_face_p (w)
         in 20.x as well, and I think it's too risky to install
         so near the release of 21.1.  2001-09-25 gerd.  */
 
-#ifndef HAVE_CARBON
 static
-#endif
 int
 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
      struct window *w;
@@ -23472,7 +23504,7 @@ note_mouse_highlight (f, x, y)
   struct buffer *b;
 
   /* When a menu is active, don't highlight because this looks odd.  */
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
   if (popup_activated ())
     return;
 #endif
@@ -25229,6 +25261,10 @@ init_xdisp ()
   help_echo_showing_p = 0;
 }
 
+/* Since w32 does not support atimers, it defines its own implementation of
+   the following three functions in w32fns.c.  */
+#ifndef WINDOWSNT
+
 /* Platform-independent portion of hourglass implementation. */
 
 /* Return non-zero if houglass timer has been started or hourglass is shown.  */
@@ -25238,7 +25274,6 @@ hourglass_started ()
   return hourglass_shown_p || hourglass_atimer != NULL;
 }
 
-
 /* Cancel a currently active hourglass timer, and start a new one.  */
 void
 start_hourglass ()
@@ -25286,7 +25321,7 @@ cancel_hourglass ()
     hide_hourglass ();
 #endif
 }
-
+#endif /* ! WINDOWSNT  */
 
 /* arch-tag: eacc864d-bb6a-4b74-894a-1a4399a1358b
    (do not change this comment) */