]> code.delx.au - gnu-emacs/blobdiff - src/dispnew.c
Remove buggy non-native image scrolling
[gnu-emacs] / src / dispnew.c
index 3c8117e6b65981b0e0f9060803de053e4c5a7505..3a0532a693b0047910289cef8f78fa183380e39c 100644 (file)
@@ -1,14 +1,14 @@
 /* Updating of data structures for redisplay.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2015 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1997-2016 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,7 +28,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 /* cm.h must come after dispextern.h on Windows.  */
 #include "dispextern.h"
 #include "cm.h"
-#include "character.h"
 #include "buffer.h"
 #include "keyboard.h"
 #include "frame.h"
@@ -36,13 +35,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "window.h"
 #include "commands.h"
 #include "disptab.h"
-#include "indent.h"
-#include "intervals.h"
 #include "blockinput.h"
-#include "process.h"
-
 #include "syssignal.h"
+#include "systime.h"
 #include "tparam.h"
+#include "xwidget.h"
 
 #ifdef HAVE_WINDOW_SYSTEM
 #include TERM_HEADER
@@ -51,7 +48,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <errno.h>
 
 #include <fpending.h>
-#include <timespec.h>
 
 #ifdef WINDOWSNT
 #include "w32.h"
@@ -177,7 +173,7 @@ add_window_display_history (struct window *w, const char *msg, bool paused_p)
   ++history_idx;
 
   snprintf (buf, sizeof redisplay_history[0].trace,
-           "%"pMu": window %p (`%s')%s\n%s",
+           "%"pMu": window %p (%s)%s\n%s",
            history_tick++,
            ptr,
            ((BUFFERP (w->contents)
@@ -325,7 +321,9 @@ margin_glyphs_to_reserve (struct window *w, int total_glyphs, int margin)
       int width = w->total_cols;
       double d = max (0, margin);
       d = min (width / 2 - 1, d);
-      return (int) ((double) total_glyphs / width * d);
+      /* Since MARGIN is positive, we cannot possibly have less than
+        one glyph for the marginal area.  */
+      return max (1, (int) ((double) total_glyphs / width * d));
     }
   return 0;
 }
@@ -567,6 +565,12 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
              for (i = 0; i < matrix->nrows; ++i)
                matrix->rows[i].enabled_p = false;
            }
+         /* We've disabled the mode-line row, so force redrawing of
+            the mode line, if any, since otherwise it will remain
+            disabled in the current matrix, and expose events won't
+            redraw it.  */
+         if (WINDOW_WANTS_MODELINE_P (w))
+           w->update_mode_line = 1;
        }
       else if (matrix == w->desired_matrix)
        {
@@ -679,7 +683,9 @@ void
 clear_glyph_matrix_rows (struct glyph_matrix *matrix, int start, int end)
 {
   eassert (start <= end);
-  eassert (start >= 0 && start < matrix->nrows);
+  eassert (start >= 0 && (start < matrix->nrows
+                         /* matrix->nrows can be 0 for the initial frame.  */
+                         || (matrix->nrows == 0)));
   eassert (end >= 0 && end <= matrix->nrows);
 
   for (; start < end; ++start)
@@ -1330,10 +1336,8 @@ realloc_glyph_pool (struct glyph_pool *pool, struct dim matrix_dim)
               || matrix_dim.width != pool->ncolumns);
 
   /* Enlarge the glyph pool.  */
-  needed = matrix_dim.width;
-  if (INT_MULTIPLY_OVERFLOW (needed, matrix_dim.height))
+  if (INT_MULTIPLY_WRAPV (matrix_dim.height, matrix_dim.width, &needed))
     memory_full (SIZE_MAX);
-  needed *= matrix_dim.height;
   if (needed > pool->nglyphs)
     {
       ptrdiff_t old_nglyphs = pool->nglyphs;
@@ -1693,7 +1697,8 @@ required_matrix_height (struct window *w)
 
   if (FRAME_WINDOW_P (f))
     {
-      int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f);
+      /* http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html  */
+      int ch_height = max (FRAME_SMALLEST_FONT_HEIGHT (f), 1);
       int window_pixel_height = window_box_height (w) + eabs (w->vscroll);
 
       return (((window_pixel_height + ch_height - 1)
@@ -1719,7 +1724,8 @@ required_matrix_width (struct window *w)
   struct frame *f = XFRAME (w->frame);
   if (FRAME_WINDOW_P (f))
     {
-      int ch_width = FRAME_SMALLEST_CHAR_WIDTH (f);
+      /* http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html  */
+      int ch_width = max (FRAME_SMALLEST_CHAR_WIDTH (f), 1);
 
       /* Compute number of glyphs needed in a glyph row.  */
       return (((WINDOW_PIXEL_WIDTH (w) + ch_width - 1)
@@ -2998,7 +3004,7 @@ redraw_frame (struct frame *f)
   clear_frame (f);
   clear_current_matrices (f);
   update_end (f);
-  windows_or_buffers_changed = 13;
+  fset_redisplay (f);
   /* Mark all windows as inaccurate, so that every window will have
      its redisplay done.  */
   mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
@@ -3542,6 +3548,7 @@ update_window (struct window *w, bool force_p)
   add_window_display_history (w, w->current_matrix->method, paused_p);
 #endif
 
+  xwidget_end_redisplay (w, w->current_matrix);
   clear_glyph_matrix (desired_matrix);
 
   return paused_p;
@@ -3904,45 +3911,35 @@ set_window_cursor_after_update (struct window *w)
     {
       cx = cy = vpos = hpos = 0;
 
-      if (cursor_in_echo_area >= 0)
-       {
-         /* If the mini-buffer is several lines high, find the last
-            line that has any text on it.  Note: either all lines
-            are enabled or none.  Otherwise we wouldn't be able to
-            determine Y.  */
-         struct glyph_row *row, *last_row;
-         struct glyph *glyph;
-         int yb = window_text_bottom_y (w);
-
-         last_row = NULL;
-         row = w->current_matrix->rows;
-         while (row->enabled_p
-                && (last_row == NULL
-                    || MATRIX_ROW_BOTTOM_Y (row) <= yb))
-           {
-             if (row->used[TEXT_AREA]
-                 && row->glyphs[TEXT_AREA][0].charpos >= 0)
-               last_row = row;
-             ++row;
-           }
+      /* If the mini-buffer is several lines high, find the last
+        line that has any text on it.  Note: either all lines
+        are enabled or none.  Otherwise we wouldn't be able to
+        determine Y.  */
+      struct glyph_row *last_row = NULL;
+      int yb = window_text_bottom_y (w);
 
-         if (last_row)
-           {
-             struct glyph *start = last_row->glyphs[TEXT_AREA];
-             struct glyph *last = start + last_row->used[TEXT_AREA] - 1;
+      for (struct glyph_row *row = w->current_matrix->rows;
+          row->enabled_p && (!last_row || MATRIX_ROW_BOTTOM_Y (row) <= yb);
+          row++)
+       if (row->used[TEXT_AREA] && row->glyphs[TEXT_AREA][0].charpos >= 0)
+         last_row = row;
 
-             while (last > start && last->charpos < 0)
-               --last;
+      if (last_row)
+       {
+         struct glyph *start = last_row->glyphs[TEXT_AREA];
+         struct glyph *last = start + last_row->used[TEXT_AREA] - 1;
 
-             for (glyph = start; glyph < last; ++glyph)
-               {
-                 cx += glyph->pixel_width;
-                 ++hpos;
-               }
+         while (last > start && last->charpos < 0)
+           --last;
 
-             cy = last_row->y;
-             vpos = MATRIX_ROW_VPOS (last_row, w->current_matrix);
+         for (struct glyph *glyph = start; glyph < last; glyph++)
+           {
+             cx += glyph->pixel_width;
+             hpos++;
            }
+
+         cy = last_row->y;
+         vpos = MATRIX_ROW_VPOS (last_row, w->current_matrix);
        }
     }
   else
@@ -4125,6 +4122,11 @@ scrolling_window (struct window *w, bool header_line_p)
        break;
     }
 
+#ifdef HAVE_XWIDGETS
+  /* Currently this seems needed to detect xwidget movement reliably. */
+    return 0;
+#endif
+
   /* Give up if some rows in the desired matrix are not enabled.  */
   if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
     return -1;
@@ -4557,58 +4559,43 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
          && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
        {
          int top = WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
-         int row, col;
+         int col;
 
-         if (cursor_in_echo_area < 0)
+         /* Put cursor at the end of the prompt.  If the mini-buffer
+            is several lines high, find the last line that has
+            any text on it.  */
+         int row = FRAME_TOTAL_LINES (f);
+         do
            {
-             /* Negative value of cursor_in_echo_area means put
-                 cursor at beginning of line.  */
-             row = top;
+             row--;
              col = 0;
-           }
-         else
-           {
-             /* Positive value of cursor_in_echo_area means put
-                cursor at the end of the prompt.  If the mini-buffer
-                is several lines high, find the last line that has
-                any text on it.  */
-             row = FRAME_TOTAL_LINES (f);
-             do
-               {
-                 --row;
-                 col = 0;
 
-                 if (MATRIX_ROW_ENABLED_P (current_matrix, row))
-                   {
-                     /* Frame rows are filled up with spaces that
-                        must be ignored here.  */
-                     struct glyph_row *r = MATRIX_ROW (current_matrix,
-                                                       row);
-                     struct glyph *start = r->glyphs[TEXT_AREA];
-                     struct glyph *last = start + r->used[TEXT_AREA];
-
-                     while (last > start
-                            && (last - 1)->charpos < 0)
-                       --last;
-
-                     col = last - start;
-                   }
+             if (MATRIX_ROW_ENABLED_P (current_matrix, row))
+               {
+                 /* Frame rows are filled up with spaces that
+                    must be ignored here.  */
+                 struct glyph_row *r = MATRIX_ROW (current_matrix, row);
+                 struct glyph *start = r->glyphs[TEXT_AREA];
+
+                 col = r->used[TEXT_AREA];
+                 while (0 < col && start[col - 1].charpos < 0)
+                   col--;
                }
-             while (row > top && col == 0);
+           }
+         while (row > top && col == 0);
 
-             /* Make sure COL is not out of range.  */
-             if (col >= FRAME_CURSOR_X_LIMIT (f))
+         /* Make sure COL is not out of range.  */
+         if (col >= FRAME_CURSOR_X_LIMIT (f))
+           {
+             /* If we have another row, advance cursor into it.  */
+             if (row < FRAME_TOTAL_LINES (f) - 1)
                {
-                 /* If we have another row, advance cursor into it.  */
-                 if (row < FRAME_TOTAL_LINES (f) - 1)
-                   {
-                     col = FRAME_LEFT_SCROLL_BAR_COLS (f);
-                     row++;
-                   }
-                 /* Otherwise move it back in range.  */
-                 else
-                   col = FRAME_CURSOR_X_LIMIT (f) - 1;
+                 col = FRAME_LEFT_SCROLL_BAR_COLS (f);
+                 row++;
                }
+             /* Otherwise move it back in range.  */
+             else
+               col = FRAME_CURSOR_X_LIMIT (f) - 1;
            }
 
          cursor_to (f, row, col);
@@ -5698,8 +5685,16 @@ additional wait period, in milliseconds; this is for backwards compatibility.
   if (duration > 0)
     {
       struct timespec t = dtotimespec (duration);
-      wait_reading_process_output (min (t.tv_sec, WAIT_READING_MAX),
-                                  t.tv_nsec, 0, 0, Qnil, NULL, 0);
+      struct timespec tend = timespec_add (current_timespec (), t);
+
+      /* wait_reading_process_output returns as soon as it detects
+        output from any subprocess, so we wait in a loop until the
+        time expires.  */
+      do {
+       wait_reading_process_output (min (t.tv_sec, WAIT_READING_MAX),
+                                    t.tv_nsec, 0, 0, Qnil, NULL, 0);
+       t = timespec_sub (tend, current_timespec ());
+      } while (timespec_sign (t) > 0);
     }
 
   return Qnil;
@@ -5954,7 +5949,7 @@ init_display (void)
   space_glyph.charpos = -1;
 
   inverse_video = 0;
-  cursor_in_echo_area = 0;
+  cursor_in_echo_area = false;
 
   /* Now is the time to initialize this; it's used by init_sys_modes
      during startup.  */
@@ -5974,9 +5969,12 @@ init_display (void)
     }
 #endif /* SIGWINCH */
 
-  /* If running as a daemon, no need to initialize any frames/terminal. */
+  /* If running as a daemon, no need to initialize any frames/terminal,
+     except on Windows, where we at least want to initialize it.  */
+#ifndef WINDOWSNT
   if (IS_DAEMON)
       return;
+#endif
 
   /* If the user wants to use a window system, we shouldn't bother
      initializing the terminal.  This is especially important when the
@@ -6052,10 +6050,10 @@ init_display (void)
     {
 #ifdef HAVE_WINDOW_SYSTEM
       if (! inhibit_window_system)
-       fprintf (stderr, "Please set the environment variable DISPLAY or TERM (see `tset').\n");
+       fprintf (stderr, "Please set the environment variable DISPLAY or TERM (see 'tset').\n");
       else
 #endif /* HAVE_WINDOW_SYSTEM */
-       fprintf (stderr, "Please set the environment variable TERM; see `tset'.\n");
+       fprintf (stderr, "Please set the environment variable TERM; see 'tset'.\n");
       exit (1);
     }
 
@@ -6105,15 +6103,15 @@ init_display (void)
     struct frame *sf = SELECTED_FRAME ();
     int width = FRAME_TOTAL_COLS (sf);
     int height = FRAME_TOTAL_LINES (sf);
+    int area;
 
     /* If these sizes are so big they cause overflow, just ignore the
        change.  It's not clear what better we could do.  The rest of
        the code assumes that (width + 2) * height * sizeof (struct glyph)
        does not overflow and does not exceed PTRDIFF_MAX or SIZE_MAX.  */
-    if (INT_ADD_RANGE_OVERFLOW (width, 2, INT_MIN, INT_MAX)
-       || INT_MULTIPLY_RANGE_OVERFLOW (width + 2, height, INT_MIN, INT_MAX)
-       || (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph)
-           < (width + 2) * height))
+    if (INT_ADD_WRAPV (width, 2, &area)
+       || INT_MULTIPLY_WRAPV (height, area, &area)
+       || min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph) < area)
       fatal ("screen size %dx%d too big", width, height);
   }
 
@@ -6219,10 +6217,10 @@ It is up to you to set this variable if your terminal can do that.  */);
               doc: /* Name of the window system that Emacs uses for the first frame.
 The value is a symbol:
  nil for a termcap frame (a character-only terminal),
'x' for an Emacs frame that is really an X window,
'w32' for an Emacs frame that is a window on MS-Windows display,
'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
'pc' for a direct-write MS-DOS frame.
`x' for an Emacs frame that is really an X window,
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
 
 Use of this variable as a boolean is deprecated.  Instead,
 use `display-graphic-p' or any of the other `display-*-p'
@@ -6232,10 +6230,10 @@ predicates which report frame's specific UI-related capabilities.  */);
                 doc: /* Name of window system through which the selected frame is displayed.
 The value is a symbol:
  nil for a termcap frame (a character-only terminal),
'x' for an Emacs frame that is really an X window,
'w32' for an Emacs frame that is a window on MS-Windows display,
'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
'pc' for a direct-write MS-DOS frame.
`x' for an Emacs frame that is really an X window,
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
 
 Use of this variable as a boolean is deprecated.  Instead,
 use `display-graphic-p' or any of the other `display-*-p'
@@ -6261,6 +6259,7 @@ Each element can be:
 
   DEFVAR_LISP ("standard-display-table", Vstandard_display_table,
               doc: /* Display table to use for buffers that specify none.
+It is also used for standard output and error streams.
 See `buffer-display-table' for more information.  */);
   Vstandard_display_table = Qnil;