summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog22
-rw-r--r--src/conf_post.h2
-rw-r--r--src/image.c11
-rw-r--r--src/keyboard.c7
-rw-r--r--src/search.c164
-rw-r--r--src/xgselect.c25
6 files changed, 213 insertions, 18 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index bb2e2bad555..fdbf922173b 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,25 @@
+2014-04-22 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port to GCC 4.9.0 with --enable-gcc-warnings.
+ * image.c (struct my_jpeg_error_mgr) [lint]: Remove member fp.
+ All uses removed.
+ (jpeg_load_body) [lint]: Add a 'volatile' to pacify a buggy GCC in
+ a way that also works with GCC 4.9.0.
+
+ * search.c (Fnewline_cache_check): Remove unused locals.
+
+2014-04-22 Eli Zaretskii <eliz@gnu.org>
+
+ * search.c (find_newline1): New subroutine.
+ (Fnewline_cache_check): New function.
+ (syms_of_search): Defsubr it.
+
+2014-04-22 Jarek Czekalski <jarekczek@poczta.onet.pl>
+
+ Fix freezing with scroll bars of GTK3 Toolkit (bug#15801).
+ * keyboard.c (unblock_input): Add comment.
+ * xgselect.c (xg_select): Prevent Glib main loop recursion.
+
2014-04-22 Daniel Colascione <dancol@dancol.org>
* lread.c (readevalloop_eager_expand_eval): New function
diff --git a/src/conf_post.h b/src/conf_post.h
index e9101ce1c57..2e78c2f5e25 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -119,7 +119,7 @@ You lose; /* Emacs for DOS must be compiled with DJGPP */
#endif
/* We must intercept 'opendir' calls to stash away the directory name,
- so we could reuse it in realinkat, see msdos.c. */
+ so we could reuse it in readlinkat; see msdos.c. */
#define opendir sys_opendir
/* The "portable" definition of _GL_INLINE on config.h does not work
diff --git a/src/image.c b/src/image.c
index bfbdfbc86b2..d558540c6e7 100644
--- a/src/image.c
+++ b/src/image.c
@@ -6262,9 +6262,6 @@ struct my_jpeg_error_mgr
MY_JPEG_INVALID_IMAGE_SIZE,
MY_JPEG_CANNOT_CREATE_X
} failure_code;
-#ifdef lint
- FILE *fp;
-#endif
};
@@ -6479,7 +6476,8 @@ jpeg_load_body (struct frame *f, struct image *img,
{
Lisp_Object file, specified_file;
Lisp_Object specified_data;
- FILE *fp = NULL;
+ /* The 'volatile' silences a bogus diagnostic; see GCC bug 54561. */
+ FILE * IF_LINT (volatile) fp = NULL;
JSAMPARRAY buffer;
int row_stride, x, y;
XImagePtr ximg = NULL;
@@ -6512,8 +6510,6 @@ jpeg_load_body (struct frame *f, struct image *img,
return 0;
}
- IF_LINT (mgr->fp = fp);
-
/* Customize libjpeg's error handling to call my_error_exit when an
error is detected. This function will perform a longjmp. */
mgr->cinfo.err = fn_jpeg_std_error (&mgr->pub);
@@ -6552,9 +6548,6 @@ jpeg_load_body (struct frame *f, struct image *img,
return 0;
}
- /* Silence a bogus diagnostic; see GCC bug 54561. */
- IF_LINT (fp = mgr->fp);
-
/* Create the JPEG decompression object. Let it read from fp.
Read the JPEG image header. */
fn_jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
diff --git a/src/keyboard.c b/src/keyboard.c
index 678cf5abcbd..705e9191c61 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -7117,7 +7117,12 @@ unblock_input_to (int level)
/* End critical section.
If doing signal-driven input, and a signal came in when input was
- blocked, reinvoke the signal handler now to deal with it. */
+ blocked, reinvoke the signal handler now to deal with it.
+
+ It will also process queued input, if it was not read before.
+ When a longer code sequence does not use block/unblock input
+ at all, the whole input gathered up to the next call to
+ unblock_input will be processed inside that call. */
void
unblock_input (void)
diff --git a/src/search.c b/src/search.c
index 9bec825abcd..ee449213ace 100644
--- a/src/search.c
+++ b/src/search.c
@@ -3098,6 +3098,169 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
out - temp,
STRING_MULTIBYTE (string));
}
+
+/* Like find_newline, but doesn't use the cache, and only searches forward. */
+static ptrdiff_t
+find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
+ ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *shortage,
+ ptrdiff_t *bytepos, bool allow_quit)
+{
+ if (count > 0)
+ {
+ if (!end)
+ end = ZV, end_byte = ZV_BYTE;
+ }
+ else
+ {
+ if (!end)
+ end = BEGV, end_byte = BEGV_BYTE;
+ }
+ if (end_byte == -1)
+ end_byte = CHAR_TO_BYTE (end);
+
+ if (shortage != 0)
+ *shortage = 0;
+
+ immediate_quit = allow_quit;
+
+ if (count > 0)
+ while (start != end)
+ {
+ /* Our innermost scanning loop is very simple; it doesn't know
+ about gaps, buffer ends, or the newline cache. ceiling is
+ the position of the last character before the next such
+ obstacle --- the last character the dumb search loop should
+ examine. */
+ ptrdiff_t tem, ceiling_byte = end_byte - 1;
+
+ if (start_byte == -1)
+ start_byte = CHAR_TO_BYTE (start);
+
+ /* The dumb loop can only scan text stored in contiguous
+ bytes. BUFFER_CEILING_OF returns the last character
+ position that is contiguous, so the ceiling is the
+ position after that. */
+ tem = BUFFER_CEILING_OF (start_byte);
+ ceiling_byte = min (tem, ceiling_byte);
+
+ {
+ /* The termination address of the dumb loop. */
+ unsigned char *lim_addr = BYTE_POS_ADDR (ceiling_byte) + 1;
+ ptrdiff_t lim_byte = ceiling_byte + 1;
+
+ /* Nonpositive offsets (relative to LIM_ADDR and LIM_BYTE)
+ of the base, the cursor, and the next line. */
+ ptrdiff_t base = start_byte - lim_byte;
+ ptrdiff_t cursor, next;
+
+ for (cursor = base; cursor < 0; cursor = next)
+ {
+ /* The dumb loop. */
+ unsigned char *nl = memchr (lim_addr + cursor, '\n', - cursor);
+ next = nl ? nl - lim_addr : 0;
+
+ if (! nl)
+ break;
+ next++;
+
+ if (--count == 0)
+ {
+ immediate_quit = 0;
+ if (bytepos)
+ *bytepos = lim_byte + next;
+ return BYTE_TO_CHAR (lim_byte + next);
+ }
+ }
+
+ start_byte = lim_byte;
+ start = BYTE_TO_CHAR (start_byte);
+ }
+ }
+
+ immediate_quit = 0;
+ if (shortage)
+ *shortage = count;
+ if (bytepos)
+ {
+ *bytepos = start_byte == -1 ? CHAR_TO_BYTE (start) : start_byte;
+ eassert (*bytepos == CHAR_TO_BYTE (start));
+ }
+ return start;
+}
+
+DEFUN ("newline-cache-check", Fnewline_cache_check, Snewline_cache_check,
+ 0, 1, 0,
+ doc: /* Check the newline cache of BUFFER against buffer contents.
+
+BUFFER defaults to the current buffer.
+
+Value is an array of 2 sub-arrays of buffer positions for newlines,
+the first based on the cache, the second based on actually scanning
+the buffer. If the buffer doesn't have a cache, the value is nil. */)
+ (Lisp_Object buffer)
+{
+ struct buffer *buf;
+ ptrdiff_t shortage, nl_count_cache, nl_count_buf;
+ Lisp_Object cache_newlines, buf_newlines, val;
+ ptrdiff_t from, found, i;
+
+ if (NILP (buffer))
+ buf = current_buffer;
+ else
+ {
+ CHECK_BUFFER (buffer);
+ buf = XBUFFER (buffer);
+ }
+ if (buf->base_buffer)
+ buf = buf->base_buffer;
+
+ /* If the buffer doesn't have a newline cache, return nil. */
+ if (NILP (BVAR (buf, cache_long_scans))
+ || buf->newline_cache == NULL)
+ return Qnil;
+
+ /* How many newlines are there according to the cache? */
+ find_newline (BUF_BEG (buf), BUF_BEG_BYTE (buf),
+ BUF_Z (buf), BUF_Z_BYTE (buf),
+ TYPE_MAXIMUM (ptrdiff_t), &shortage, NULL, true);
+ nl_count_cache = TYPE_MAXIMUM (ptrdiff_t) - shortage;
+
+ /* Create vector and populate it. */
+ cache_newlines = make_uninit_vector (nl_count_cache);
+ for (from = BUF_BEG( buf), found = from, i = 0;
+ from < BUF_Z (buf);
+ from = found, i++)
+ {
+ ptrdiff_t from_byte = CHAR_TO_BYTE (from);
+
+ found = find_newline (from, from_byte, 0, -1, 1, &shortage, NULL, true);
+ if (shortage == 0)
+ ASET (cache_newlines, i, make_number (found - 1));
+ }
+
+ /* Now do the same, but without using the cache. */
+ find_newline1 (BUF_BEG (buf), BUF_BEG_BYTE (buf),
+ BUF_Z (buf), BUF_Z_BYTE (buf),
+ TYPE_MAXIMUM (ptrdiff_t), &shortage, NULL, true);
+ nl_count_buf = TYPE_MAXIMUM (ptrdiff_t) - shortage;
+ buf_newlines = make_uninit_vector (nl_count_buf);
+ for (from = BUF_BEG( buf), found = from, i = 0;
+ from < BUF_Z (buf);
+ from = found, i++)
+ {
+ ptrdiff_t from_byte = CHAR_TO_BYTE (from);
+
+ found = find_newline1 (from, from_byte, 0, -1, 1, &shortage, NULL, true);
+ if (shortage == 0)
+ ASET (buf_newlines, i, make_number (found - 1));
+ }
+
+ /* Construct the value and return it. */
+ val = make_uninit_vector (2);
+ ASET (val, 0, cache_newlines);
+ ASET (val, 1, buf_newlines);
+ return val;
+}
void
syms_of_search (void)
@@ -3170,4 +3333,5 @@ is to bind it with `let' around a small expression. */);
defsubr (&Smatch_data);
defsubr (&Sset_match_data);
defsubr (&Sregexp_quote);
+ defsubr (&Snewline_cache_check);
}
diff --git a/src/xgselect.c b/src/xgselect.c
index 5f71ff84014..bf889a90e97 100644
--- a/src/xgselect.c
+++ b/src/xgselect.c
@@ -28,6 +28,18 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <stdbool.h>
#include <timespec.h>
#include "frame.h"
+#include "blockinput.h"
+
+/* `xg_select' is a `pselect' replacement. Why do we need a separate function?
+ 1. Timeouts. Glib and Gtk rely on timer events. If we did pselect
+ with a greater timeout then the one scheduled by Glib, we would
+ not allow Glib to process its timer events. We want Glib to
+ work smoothly, so we need to reduce our timeout to match Glib.
+ 2. Descriptors. Glib may listen to more file descriptors than we do.
+ So we add Glib descriptors to our pselect pool, but we don't change
+ the value returned by the function. The return value matches only
+ the descriptors passed as arguments, making it compatible with
+ plain pselect. */
int
xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds,
@@ -47,12 +59,6 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds,
bool need_to_dispatch;
USE_SAFE_ALLOCA;
- /* Do not try to optimize with an initial check with g_main_context_pending
- and a call to pselect if it returns false. If Gdk has a timeout for 0.01
- second, and Emacs has a timeout for 1 second, g_main_context_pending will
- return false, but the timeout will be 1 second, thus missing the gdk
- timeout with a lot. */
-
context = g_main_context_default ();
if (rfds) all_rfds = *rfds;
@@ -136,8 +142,13 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds,
if (need_to_dispatch)
{
int pselect_errno = errno;
+ /* Prevent g_main_dispatch recursion, that would occur without
+ block_input wrapper, because event handlers call
+ unblock_input. Event loop recursion was causing Bug#15801. */
+ block_input ();
while (g_main_context_pending (context))
- g_main_context_dispatch (context);
+ g_main_context_dispatch (context);
+ unblock_input ();
errno = pselect_errno;
}