]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(display_text_line): Clear out redisplay_end_trigger
[gnu-emacs] / src / xdisp.c
index 7014219d59ceec2f9255bcb4f4eae377e71a161f..655d1d90c06afe323fe7f3ad53cac9204cb43b0b 100644 (file)
@@ -36,7 +36,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "intervals.h"
 #include "keyboard.h"
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
 extern void set_frame_menubar ();
 #endif
 
@@ -50,7 +50,7 @@ extern Lisp_Object Voverriding_local_map_menu_flag;
 
 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
-Lisp_Object Qredisplay_end_trigger_hook;
+Lisp_Object Qredisplay_end_trigger_functions;
 
 /* Nonzero means print newline to stdout before next minibuffer message.  */
 
@@ -248,6 +248,7 @@ message_dolog (m, len, nlflag)
     {
       struct buffer *oldbuf;
       int oldpoint, oldbegv, oldzv;
+      int old_windows_or_buffers_changed = windows_or_buffers_changed;
 
       oldbuf = current_buffer;
       Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
@@ -316,6 +317,7 @@ message_dolog (m, len, nlflag)
       ZV = oldzv;
       TEMP_SET_PT (oldpoint);
       set_buffer_internal (oldbuf);
+      windows_or_buffers_changed = old_windows_or_buffers_changed;
       message_log_need_newline = !nlflag;
     }
 }
@@ -612,7 +614,7 @@ echo_area_display ()
   previous_echo_glyphs = echo_area_glyphs;
 }
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 static char frame_title_buf[512];
 static char *frame_title_ptr;
 
@@ -641,7 +643,7 @@ x_consider_frame_title (frame)
   int len;
   FRAME_PTR f = XFRAME (frame);
 
-  if (!FRAME_X_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name)
+  if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name))
     return;
 
   /* Do we have more than one visible frame on this X display?  */
@@ -706,8 +708,8 @@ prepare_menu_bars ()
      create its menu bar using the name `emacs' if no other name
      has yet been specified."
      I think that is no longer a concern.  */
-#ifdef HAVE_X_WINDOWS
-  if (windows_or_buffers_changed)
+#ifdef HAVE_WINDOW_SYSTEM
+  if (windows_or_buffers_changed || update_mode_lines)
     {
       Lisp_Object tail, frame;
 
@@ -987,7 +989,7 @@ redisplay ()
          pos = *compute_motion (tlbufpos, 0,
                                 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
                                 0,
-                                PT, 2, - (1 << (SHORTBITS - 1)),
+                                PT, 2, - (1 << (BITS_PER_SHORT - 1)),
                                 window_internal_width (w) - 1,
                                 XINT (w->hscroll),
                                 pos_tab_offset (w, tlbufpos), w);
@@ -1284,13 +1286,14 @@ update_menu_bar (f, save_match_data)
   if (update_mode_lines)
     w->update_mode_line = Qt;
 
-  if (
-#ifdef USE_X_TOOLKIT
+  if (FRAME_X_P (f)
+      ?
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
       FRAME_EXTERNAL_MENU_BAR (f) 
 #else
       FRAME_MENU_BAR_LINES (f) > 0
 #endif
-      )
+      : FRAME_MENU_BAR_LINES (f) > 0)
     {
       /* If the user has switched buffers or windows, we need to
         recompute to reflect the new bindings.  But we'll
@@ -1328,9 +1331,10 @@ update_menu_bar (f, save_match_data)
            call0 (Qrecompute_lucid_menubar);
          call1 (Vrun_hooks, Qmenu_bar_update_hook);
          FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
-#ifdef USE_X_TOOLKIT
-         set_frame_menubar (f, 0, 0);
-#endif /* USE_X_TOOLKIT */
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
+         if (FRAME_X_P (f))
+           set_frame_menubar (f, 0, 0);
+#endif /* USE_X_TOOLKIT || HAVE_NTGUI */
 
          unbind_to (count, Qnil);
          set_buffer_internal_1 (prev);
@@ -1498,11 +1502,16 @@ redisplay_window (window, just_this_one)
      unless the specified location is outside the accessible range.  */
   if (!NILP (w->force_start))
     {
+      w->force_start = Qnil;
       /* Forget any recorded base line for line number display.  */
       w->base_line_number = Qnil;
       /* Redisplay the mode line.  Select the buffer properly for that.
         Also, run the hook window-scroll-functions
         because we have scrolled.  */
+      /* Note, we do this after clearing force_start because
+        if there's an error, it is better to forget about force_start
+        than to get into an infinite loop calling the hook functions
+        and having them get more errors.  */
       if (!update_mode_line
          || ! NILP (Vwindow_scroll_functions))
        {
@@ -1516,7 +1525,6 @@ redisplay_window (window, just_this_one)
            run_hook_with_args_2 (Qwindow_scroll_functions, window,
                                  make_number (startp));
        }
-      w->force_start = Qnil;
       XSETFASTINT (w->last_modified, 0);
       if (startp < BEGV) startp = BEGV;
       if (startp > ZV)   startp = ZV;
@@ -1531,7 +1539,7 @@ redisplay_window (window, just_this_one)
                                  + (hscroll ? 1 - hscroll : 0)),
                                 0,
                                 ZV, height / 2,
-                                - (1 << (SHORTBITS - 1)),
+                                - (1 << (BITS_PER_SHORT - 1)),
                                 width, hscroll, pos_tab_offset (w, startp), w);
          BUF_PT (current_buffer) = pos.bufpos;
          if (w != XWINDOW (selected_window))
@@ -1675,7 +1683,8 @@ redisplay_window (window, just_this_one)
 
   /* Try to scroll by specified few lines */
 
-  if (scroll_step && !current_buffer->clip_changed)
+  if (scroll_step && !current_buffer->clip_changed
+      && startp >= BEGV && startp <= ZV)
     {
       if (PT > startp)
        {
@@ -1713,6 +1722,9 @@ recenter:
   w->base_line_number = Qnil;
 
   pos = *vmotion (PT, - (height / 2), w);
+  /* Set startp here explicitly in case that helps avoid an infinite loop
+     in case the window-scroll-functions functions get errors.  */
+  Fset_marker (w->start, make_number (pos), Qnil);
   if (! NILP (Vwindow_scroll_functions))
     run_hook_with_args_2 (Qwindow_scroll_functions, window,
                          make_number (pos.bufpos));
@@ -1741,11 +1753,14 @@ done:
 
   /* When we reach a frame's selected window, redo the frame's menu bar.  */
   if (update_mode_line
-#ifdef USE_X_TOOLKIT
-      && FRAME_EXTERNAL_MENU_BAR (f) 
+      && (FRAME_X_P (f)
+         ?
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
+         FRAME_EXTERNAL_MENU_BAR (f) 
 #else
-      && FRAME_MENU_BAR_LINES (f) > 0
+         FRAME_MENU_BAR_LINES (f) > 0
 #endif
+         : FRAME_MENU_BAR_LINES (f) > 0)
       && EQ (FRAME_SELECTED_WINDOW (f), window))
     display_menu_bar (w);
 
@@ -1894,7 +1909,7 @@ try_window_id (window)
   struct position val, bp, ep, xp, pp;
   int scroll_amount = 0;
   int delta;
-  int tab_offset, epto;
+  int tab_offset, epto, old_tick;
 
   if (GPT - BEG < beg_unchanged)
     beg_unchanged = GPT - BEG;
@@ -1967,7 +1982,7 @@ try_window_id (window)
 
   /* Compute the cursor position after that newline.  */
   ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
-                       height, - (1 << (SHORTBITS - 1)),
+                       height, - (1 << (BITS_PER_SHORT - 1)),
                        width, hscroll, pos_tab_offset (w, bp.bufpos), w);
 
   /* If changes reach past the text available on the frame,
@@ -2023,13 +2038,13 @@ try_window_id (window)
          if (PT <= xp.bufpos)
            {
              pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
-                                   PT, height, - (1 << (SHORTBITS - 1)),
+                                   PT, height, - (1 << (BITS_PER_SHORT - 1)),
                                    width, hscroll, epto, w);
            }
          else
            {
              pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
-                                   PT, height, - (1 << (SHORTBITS - 1)),
+                                   PT, height, - (1 << (BITS_PER_SHORT - 1)),
                                    width, hscroll,
                                    pos_tab_offset (w, xp.bufpos), w);
            }
@@ -2088,8 +2103,8 @@ try_window_id (window)
                 lines' charstarts in the case where the text of the
                 screen line at bp.vpos has changed.
                 (This can happen in a deletion that ends in mid-line.)
-                To adjust properly, we need to make things constent at
-                the position ep.
+                To adjust properly, we need to make things consistent
+                at the position ep.
                 So do a second adjust to make that happen.
                 Note that stop_vpos >= ep.vpos, so it is sufficient
                 to update the charstarts for lines at ep.vpos and below.  */
@@ -2139,9 +2154,15 @@ try_window_id (window)
      to account for passing the line that that character really starts in.  */
   if (val.hpos < lmargin)
     tab_offset += width;
+  old_tick = MODIFF;
   while (vpos < stop_vpos)
     {
       val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
+      /* If display_text_line ran a hook and changed some text,
+        redisplay all the way to bottom of buffer
+        So that we show the changes.  */
+      if (old_tick != MODIFF)
+       stop_vpos = height;
       tab_offset += width;
       if (val.vpos) tab_offset = 0;
       if (pos != val.bufpos)
@@ -2250,7 +2271,7 @@ try_window_id (window)
   if (debug_end_pos)
     {
       val = *compute_motion (start, 0, lmargin, 0, ZV,
-                            height, - (1 << (SHORTBITS - 1)),
+                            height, - (1 << (BITS_PER_SHORT - 1)),
                             width, hscroll, pos_tab_offset (w, start), w);
       if (val.vpos != XFASTINT (w->window_end_vpos))
        abort ();
@@ -2700,22 +2721,13 @@ display_text_line (w, start, vpos, hpos, taboffset)
              break;
            }
 
-#ifdef HAVE_FACES
-         /* Did we hit a face change?  Figure out what face we should
-            use now.  We also hit this the first time through the
-            loop, to see what face we should start with.  */
-         if (pos >= next_face_change && FRAME_X_P (f))
-           current_face = compute_char_face (f, w, pos,
-                                             region_beg, region_end,
-                                             &next_face_change, pos + 50, 0);
-#endif
-
          /* Figure out where (if at all) the
             redisplay_end_trigger-hook should run.  */
-         if (MARKERP (current_buffer->redisplay_end_trigger))
-           e_t_h = marker_position (current_buffer->redisplay_end_trigger);
-         else if (INTEGERP (current_buffer->redisplay_end_trigger))
-           e_t_h = XINT (current_buffer->redisplay_end_trigger);
+         if (MARKERP (w->redisplay_end_trigger)
+             && XMARKER (w->redisplay_end_trigger)->buffer != 0)
+           e_t_h = marker_position (w->redisplay_end_trigger);
+         else if (INTEGERP (w->redisplay_end_trigger))
+           e_t_h = XINT (w->redisplay_end_trigger);
          else
            e_t_h = ZV;
 
@@ -2723,11 +2735,32 @@ display_text_line (w, start, vpos, hpos, taboffset)
             run the hook.  */
          if (pos >= e_t_h && e_t_h != ZV)
            {
-             call1 (Vrun_hooks, Qredisplay_end_trigger_hook);
-             current_buffer->redisplay_end_trigger = Qnil;
+             Lisp_Object args[3];
+
+             args[0] = Qredisplay_end_trigger_functions;
+             XSETWINDOW (args[1], w);
+             XSETINT (args[2], e_t_h);
+
+             /* Since we are *trying* to run these functions,
+                don't try to run them again, even if they get an error.  */
+             w->redisplay_end_trigger = Qnil;
+             Frun_hook_with_args (3, args);
+
              e_t_h = ZV;
+             /* Notice if it changed the face of this character.  */
+             next_face_change = pos;
            }
 
+#ifdef HAVE_FACES
+         /* Did we hit a face change?  Figure out what face we should
+            use now.  We also hit this the first time through the
+            loop, to see what face we should start with.  */
+         if (pos >= next_face_change && (FRAME_WINDOW_P (f)))
+           current_face = compute_char_face (f, w, pos,
+                                             region_beg, region_end,
+                                             &next_face_change, pos + 50, 0);
+#endif
+
          /* Compute the next place we need to stop
             and do something special; set PAUSE.  */
 
@@ -3158,9 +3191,14 @@ display_menu_bar (w)
   int hpos = 0;
   int i;
 
-#ifndef USE_X_TOOLKIT
-  if (FRAME_MENU_BAR_LINES (f) <= 0)
+#ifdef HAVE_NTGUI
+  return;
+#endif
+
+#ifdef USE_X_TOOLKIT
+  if (FRAME_X_P (f))
     return;
+#endif /* USE_X_TOOLKIT */
 
   get_display_line (f, vpos, 0);
 
@@ -3199,7 +3237,6 @@ display_menu_bar (w)
   vpos++;
   while (vpos < FRAME_MENU_BAR_LINES (f))
     get_display_line (f, vpos++, 0);
-#endif /* not USE_X_TOOLKIT */
 }
 \f
 /* Display the mode line for window w */
@@ -3766,7 +3803,11 @@ decode_mode_spec (w, c, spec_width, maxwidth)
          return "Top";
        else
          {
-           total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
+           if (total > 1000000)
+             /* Do it differently for a large value, to avoid overflow.  */
+             total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
+           else
+             total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
            /* We can't normally display a 3-digit number,
               so get us a 2-digit number that is close.  */
            if (total == 100)
@@ -3792,7 +3833,11 @@ decode_mode_spec (w, c, spec_width, maxwidth)
          }
        else
          {
-           total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
+           if (total > 1000000)
+             /* Do it differently for a large value, to avoid overflow.  */
+             total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
+           else
+             total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
            /* We can't normally display a 3-digit number,
               so get us a 2-digit number that is close.  */
            if (total == 100)
@@ -3994,6 +4039,7 @@ display_string (w, vpos, string, length, hpos, truncate,
      int mincol, maxcol;
 {
   register int c;
+  int truncated;
   register GLYPH *p1;
   int hscroll = XINT (w->hscroll);
   int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
@@ -4046,7 +4092,10 @@ display_string (w, vpos, string, length, hpos, truncate,
   if (maxcol >= 0 && mincol > maxcol)
     mincol = maxcol;
 
-  while (p1 < end)
+  /* We set truncated to 1 if we get stopped by trying to pass END
+     (that is, trying to pass MAXCOL.)  */
+  truncated = 0;
+  while (1)
     {
       if (length == 0)
        break;
@@ -4058,6 +4107,12 @@ display_string (w, vpos, string, length, hpos, truncate,
       else if (c == 0)
        break;
 
+      if (p1 >= end)
+       {
+         truncated = 1;
+         break;
+       }
+
       if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
        {
          p1 = copy_part_of_rope (f, p1, start,
@@ -4111,7 +4166,7 @@ display_string (w, vpos, string, length, hpos, truncate,
        }
     }
 
-  if (c && length > 0)
+  if (truncated)
     {
       p1 = end;
       if (truncate) *p1++ = fix_glyph (f, truncate, 0);
@@ -4229,8 +4284,8 @@ syms_of_xdisp ()
   staticpro (&Qwindow_scroll_functions);
   Qwindow_scroll_functions = intern ("window-scroll-functions");
 
-  staticpro (&Qredisplay_end_trigger_hook);
-  Qredisplay_end_trigger_hook = intern ("redisplay-end-trigger-hook");
+  staticpro (&Qredisplay_end_trigger_functions);
+  Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
 
   staticpro (&last_arrow_position);
   staticpro (&last_arrow_string);