Mercurial > emacs
changeset 109201:0aaff477ec9f
Merge from mainline.
author | Katsumi Yamaoka <katsumi@flagship2> |
---|---|
date | Sun, 23 May 2010 11:52:45 +0000 |
parents | 141ddbd4a5e0 (current diff) 3339da3cfeb3 (diff) |
children | 1a5381cbfe12 |
files | |
diffstat | 17 files changed, 378 insertions(+), 218 deletions(-) [+] |
line wrap: on
line diff
--- a/admin/notes/bugtracker Sat May 22 03:32:53 2010 +0000 +++ b/admin/notes/bugtracker Sun May 23 11:52:45 2010 +0000 @@ -553,9 +553,13 @@ If a non-spam message accidentally gets discarded, just do: cat /var/lib/mailman/spam/not-really-spam.msg | /usr/lib/debbugs/receive +chown Debian-debbugs:Debian-debbugs /var/lib/debbugs/spool/incoming/* ... check it works ... mv /var/lib/mailman/spam/not-really-spam.msg /var/lib/mailman/not-spam/ +Also check that the sender was not added to the auto-discard/reject list +in the debbugs-submit Mailman interface. + ** Administrivia The debbugs-submit list should have the administrivia option off,
--- a/configure Sat May 22 03:32:53 2010 +0000 +++ b/configure Sun May 23 11:52:45 2010 +0000 @@ -9561,7 +9561,10 @@ fi if test $ac_enable_autodepend = yes; then DEPFLAGS='-MMD -MF ${DEPDIR}/$*.d' - MKDEPDIR='test -d ${DEPDIR} || mkdir ${DEPDIR}' + ## In parallel builds, another make might create depdir between + ## the first test and mkdir, so stick another test on the end. + ## Or use mkinstalldirs? mkdir -p is not portable. + MKDEPDIR='test -d ${DEPDIR} || mkdir ${DEPDIR} || test -d ${DEPDIR}' deps_frag=autodeps.mk fi fi
--- a/doc/lispref/ChangeLog Sat May 22 03:32:53 2010 +0000 +++ b/doc/lispref/ChangeLog Sun May 23 11:52:45 2010 +0000 @@ -1,3 +1,8 @@ +2010-05-22 Chong Yidong <cyd@stupidchicken.com> + + * display.texi (Image Cache): Update documentation about image + caching. + 2010-05-08 Štěpán Němec <stepnem@gmail.com> (tiny change) * windows.texi (Textual Scrolling):
--- a/doc/lispref/display.texi Sat May 22 03:32:53 2010 +0000 +++ b/doc/lispref/display.texi Sun May 23 11:52:45 2010 +0000 @@ -4730,29 +4730,35 @@ efficiently. When Emacs displays an image, it searches the image cache for an existing image specification @code{equal} to the desired specification. If a match is found, the image is displayed from the -cache; otherwise, Emacs loads the image normally. - - Occasionally, you may need to tell Emacs to refresh the images -associated with a given image specification. For example, suppose you -display an image using a specification that contains a @code{:file} -property. The image is automatically cached, and subsequent displays -of that image, with the same image specification, will use the image -cache. If the image file changes in the meantime, Emacs would be -displaying the old version of the image. In such a situation, you can -``refresh'' the image by calling @code{image-refresh}. - - In Emacs' current implementation, each graphical terminal possesses -an image cache, which is shared by all the frames on that terminal +cache. Otherwise, Emacs loads the image normally. + +@defun image-flush spec &optional frame +This function removes the image with specification @var{spec} from the +image cache of frame @var{frame}. Image specifications are compared +using @code{equal}. If @var{frame} is @code{nil}, it defaults to the +selected frame. If @var{frame} is @code{t}, the image is flushed on +all existing frames. + +In Emacs' current implementation, each graphical terminal possesses an +image cache, which is shared by all the frames on that terminal (@pxref{Multiple Terminals}). Thus, refreshing an image in one frame also refreshes it in all other frames on the same terminal. - -@defun image-refresh spec &optional frame -This function refreshes any images with image specifications -@code{equal} to @var{spec} on frame @var{frame}. If @var{frame} is -@code{nil}, it defaults to the selected frame. If @var{frame} is -@code{t}, the refresh is applied to all existing frames. @end defun + One use for @code{image-flush} is to tell Emacs about a change in an +image file. If an image specification contains a @code{:file} +property, the image is cached based on the file's contents when the +image is first displayed. Even if the file subsequently changes, +Emacs continues displaying the old version of the image. Calling +@code{image-flush} flushes the image from the cache, forcing Emacs to +re-read the file the next time it needs to display that image. + + Another use for @code{image-flush} is for memory conservation. If +your Lisp program creates a large number of temporary images over a +period much shorter than @code{image-cache-eviction-delay} (see +below), you can opt to flush unused images yourself, instead of +waiting for Emacs to do it automatically. + @defun clear-image-cache &optional filter This function clears an image cache, removing all the images stored in it. If @var{filter} is omitted or @code{nil}, it clears the cache for @@ -4768,9 +4774,12 @@ associated memory. @defvar image-cache-eviction-delay -This variable specifies the number of seconds an image can remain in the -cache without being displayed. When an image is not displayed for this -length of time, Emacs removes it from the image cache. +This variable specifies the number of seconds an image can remain in +the cache without being displayed. When an image is not displayed for +this length of time, Emacs removes it from the image cache. + +Under some circumstances, if the number of images in the cache grows +too large, the actual eviction delay may be shorter than this. If the value is @code{nil}, Emacs does not remove images from the cache except when you explicitly clear it. This mode can be useful for
--- a/lib-src/ChangeLog Sat May 22 03:32:53 2010 +0000 +++ b/lib-src/ChangeLog Sun May 23 11:52:45 2010 +0000 @@ -1,3 +1,11 @@ +2010-05-22 Jan Djärv <jan.h.d@swipnet.se> + + * Makefile.in (STAMP_INST_SCRIPTS, STAMP_SCRIPS): New (Bug #6246). + (all): Depend onSTAMP_INST_SCRIPTS, STAMP_SCRIPS (Bug #6246). + (stamp-rcs2log, stamp-rcs-checkin, stamp-grep-changelog, stamp-vcdiff): + New rules (Bug #6246). + (clean): Remove stamp-* (Bug #6246). + 2010-05-12 Glenn Morris <rgm@gnu.org> * Makefile.in (INSTALLABLES): Remove @LIB_SRC_EXTRA_INSTALLABLES@.
--- a/lib-src/Makefile.in Sat May 22 03:32:53 2010 +0000 +++ b/lib-src/Makefile.in Sun May 23 11:52:45 2010 +0000 @@ -111,6 +111,7 @@ b2m${EXEEXT} ebrowse${EXEEXT} INSTALLABLE_SCRIPTS = rcs-checkin grep-changelog +STAMP_INST_SCRIPTS = stamp-rcs-checkin stamp-grep-changelog # Things that Emacs runs internally, or during the build process, # which should not be installed in bindir. @@ -123,6 +124,7 @@ # Like UTILITIES, but they're not system-dependent, and should not be # deleted by the distclean target. SCRIPTS= rcs2log vcdiff +STAMP_SCRIPTS= stamp-rcs2log stamp-vcdiff EXECUTABLES= ${UTILITIES} ${INSTALLABLES} ${SCRIPTS} ${INSTALLABLE_SCRIPTS} @@ -180,23 +182,27 @@ .c.o: ${CC} -c ${CPP_CFLAGS} $< -all: ${DONT_INSTALL} ${UTILITIES} ${INSTALLABLES} ${SCRIPTS} ${INSTALLABLE_SCRIPTS} +all: ${DONT_INSTALL} ${UTILITIES} ${INSTALLABLES} ${SCRIPTS} ${INSTALLABLE_SCRIPTS} ${STAMP_INST_SCRIPTS} ${STAMP_SCRIPTS} ## These targets copy the scripts into the build directory so that ## they can be run from there in an uninstalled Emacs. ## The "-" is prepended because some versions of cp barf when srcdir ## is the current directory, and thus the file will be copied into itself. -rcs2log: $(srcdir)/rcs2log +stamp-rcs2log: $(srcdir)/rcs2log -cp -p $(srcdir)/rcs2log rcs2log + touch $@ -rcs-checkin: $(srcdir)/rcs-checkin +stamp-rcs-checkin: $(srcdir)/rcs-checkin -cp -p $(srcdir)/rcs-checkin rcs-checkin + touch $@ -grep-changelog: $(srcdir)/grep-changelog +stamp-grep-changelog: $(srcdir)/grep-changelog -cp -p $(srcdir)/grep-changelog grep-changelog + touch $@ -vcdiff: $(srcdir)/vcdiff +stamp-vcdiff: $(srcdir)/vcdiff -cp -p $(srcdir)/vcdiff vcdiff + touch $@ ## Only used if we need blessmail, but no harm in always defining. ## This makes the actual blessmail executable. @@ -273,7 +279,7 @@ clean: mostlyclean -rm -f ${INSTALLABLES} ${UTILITIES} ${DONT_INSTALL} - -rm -f fns*.el *.tab.c *.tab.h + -rm -f fns*.el *.tab.c *.tab.h stamp-* distclean: clean -rm -f TAGS
--- a/lisp/ChangeLog Sat May 22 03:32:53 2010 +0000 +++ b/lisp/ChangeLog Sun May 23 11:52:45 2010 +0000 @@ -1,3 +1,9 @@ +2010-05-22 Chong Yidong <cyd@stupidchicken.com> + + * image.el (image-refresh): Define as an alias for image-flush. + + * image-mode.el (image-toggle-display-image): Caller changed. + 2010-05-21 Juri Linkov <juri@jurta.org> * progmodes/grep.el (grep-read-files): Fix multi-pattern aliases.
--- a/lisp/image-mode.el Sat May 22 03:32:53 2010 +0000 +++ b/lisp/image-mode.el Sun May 23 11:52:45 2010 +0000 @@ -448,7 +448,7 @@ (defvar archive-superior-buffer) (defvar tar-superior-buffer) -(declare-function image-refresh "image.c" (spec &optional frame)) +(declare-function image-flush "image.c" (spec &optional frame)) (defun image-toggle-display-image () "Show the image of the image file. @@ -477,7 +477,7 @@ (inhibit-read-only t) (buffer-undo-list t) (modified (buffer-modified-p))) - (image-refresh image) + (image-flush image) (let ((buffer-file-truename nil)) ; avoid changing dir mtime by lock_file (add-text-properties (point-min) (point-max) props) (restore-buffer-modified-p modified))
--- a/lisp/image.el Sat May 22 03:32:53 2010 +0000 +++ b/lisp/image.el Sun May 23 11:52:45 2010 +0000 @@ -30,6 +30,7 @@ "Image support." :group 'multimedia) +(defalias 'image-refresh 'image-flush) (defconst image-type-header-regexps `(("\\`/[\t\n\r ]*\\*.*XPM.\\*/" . xpm)
--- a/src/.gdbinit Sat May 22 03:32:53 2010 +0000 +++ b/src/.gdbinit Sun May 23 11:52:45 2010 +0000 @@ -616,7 +616,7 @@ end define prowlims - printf "start=%d,end=%d,reversed=%d,cont=%d,at_zv=%d\n", $arg0->start.pos.charpos, $arg0->end.pos.charpos, $arg0->reversed_p, $arg0->continued_p, $arg0->ends_at_zv_p + printf "edges=(%d,%d),r2l=%d,cont=%d,trunc=(%d,%d),at_zv=%d\n", $arg0->minpos.charpos, $arg0->maxpos.charpos, $arg0->reversed_p, $arg0->continued_p, $arg0->truncated_on_left_p, $arg0->truncated_on_right_p, $arg0->ends_at_zv_p end document prowlims Print important attributes of a glyph_row structure. @@ -626,10 +626,13 @@ define pmtxrows set $mtx = $arg0 set $gl = $mtx->rows - set $glend = $mtx->rows + $mtx->nrows + set $glend = $mtx->rows + $mtx->nrows - 1 + set $i = 0 while ($gl < $glend) + printf "%d: ", $i prowlims $gl set $gl = $gl + 1 + set $i = $i + 1 end end document pmtxrows
--- a/src/ChangeLog Sat May 22 03:32:53 2010 +0000 +++ b/src/ChangeLog Sun May 23 11:52:45 2010 +0000 @@ -1,3 +1,59 @@ +2010-05-19 Eli Zaretskii <eliz@gnu.org> + + Redesign and reimplement bidi-aware edge positions of glyph rows. + + * dispextern.h (struct glyph_row): New members minpos and maxpos. + (MATRIX_ROW_START_CHARPOS, MATRIX_ROW_START_BYTEPOS) + (MATRIX_ROW_END_CHARPOS, MATRIX_ROW_END_BYTEPOS): Reference minpos + and maxpos members instead of start.pos and end.pos, respectively. + + * xdisp.c (display_line): Compare IT_CHARPOS with the position in + row->start.pos, rather than with MATRIX_ROW_START_CHARPOS. + (cursor_row_p): Use row->end.pos rather than MATRIX_ROW_END_CHARPOS. + (try_window_reusing_current_matrix, try_window_id): Use + ROW->minpos rather than ROW->start.pos. + (init_from_display_pos, init_iterator): Use EMACS_INT for + character and byte positions. + (find_row_edges): Renamed from find_row_end. Accept additional + arguments for minimum and maximum buffer positions seen by + display_line for this row. Don't use iterator to find the + position following the maximum one; instead, increment the + position found by display_line directly. Fix logic; eol_pos + should be tested before the rest. Handle the case of characters + delivered from display vector (bug#6036). Fix tests related to + it->method. Handle the truncated_on_right_p rows. + (RECORD_MAX_MIN_POS): New macro. + (display_line): Use it to record the minimum and maximum buffer + positions for glyphs in the row being assembled. Record the + position of the newline that terminates the line. If word wrap is + in effect, restore minimum and maximum positions seen up to the + wrap point, when iterator returns to it. + (try_window_reusing_current_matrix): Give up if in bidi-reordered + row and cursor not already at point. Restore original pre-bidi + code for unidirectional buffers. + + * dispnew.c (increment_row_positions, check_matrix_invariants): + Increment and check row->start.pos and row->end.pos, in addition + to MATRIX_ROW_START_CHARPOS and MATRIX_ROW_END_CHARPOS. + + * .gdbinit (prowlims): Display row->minpos and row->maxpos. + Display truncated_on_left_p and truncated_on_right_p flags. + Formatting fixes. + (pmtxrows): Display the ordinal number of each row. Don't display + rows beyond the last one. + + * bidi.c (bidi_cache_iterator_state): Don't zero out new_paragraph: + it is not copied by bidi_copy_it. + +2010-05-22 Eli Zaretskii <eliz@gnu.org> + + * w32.c (sys_write): Break writes into chunks smaller than 32MB. + (Bug#6237) + +2010-05-22 Chong Yidong <cyd@stupidchicken.com> + + * image.c (Fimage_flush): Rename from image-refresh. + 2010-05-21 Chong Yidong <cyd@stupidchicken.com> * xdisp.c (redisplay_internal): Clear caches even if redisplaying @@ -42,8 +98,6 @@ Move static/dynamic dependency stuff to deps.mk/autodeps.mk. * deps.mk, autodeps.mk: New files, extracted from Makefile.in. -2010-05-19 Eli Zaretskii <eliz@gnu.org> - * bidi.c (bidi_cache_shrink, bidi_cache_iterator_state): Fix reallocation of the cache. (Bug#6210) @@ -166,6 +220,8 @@ * xdisp.c (Fcurrent_bidi_paragraph_direction): New function. (syms_of_xdisp): Defsubr it. + * cmds.c (Fforward_char, Fbackward_char): Doc fix. + * Makefile.in: Fix MSDOS-related comments. 2010-05-15 Glenn Morris <rgm@gnu.org>
--- a/src/bidi.c Sat May 22 03:32:53 2010 +0000 +++ b/src/bidi.c Sun May 23 11:52:45 2010 +0000 @@ -707,7 +707,6 @@ bidi_copy_it (&bidi_cache[idx], bidi_it); if (!resolved) bidi_cache[idx].resolved_level = -1; - bidi_cache[idx].new_paragraph = 0; } else {
--- a/src/dispextern.h Sat May 22 03:32:53 2010 +0000 +++ b/src/dispextern.h Sun May 23 11:52:45 2010 +0000 @@ -748,21 +748,29 @@ /* First position in this row. This is the text position, including overlay position information etc, where the display of this row - started, and can thus be less the position of the first glyph - (e.g. due to invisible text or horizontal scrolling). BIDI Note: - This is the smallest character position in the row, but not - necessarily the character that is the leftmost on the display. */ + started, and can thus be less than the position of the first + glyph (e.g. due to invisible text or horizontal scrolling). + BIDI Note: In R2L rows, that have its reversed_p flag set, this + position is at or beyond the right edge of the row. */ struct display_pos start; /* Text position at the end of this row. This is the position after the last glyph on this row. It can be greater than the last - glyph position + 1, due to truncation, invisible text etc. In an - up-to-date display, this should always be equal to the start - position of the next row. BIDI Note: this is the character whose - buffer position is the largest, but not necessarily the rightmost - one on the display. */ + glyph position + 1, due to a newline that ends the line, + truncation, invisible text etc. In an up-to-date display, this + should always be equal to the start position of the next row. + BIDI Note: In R2L rows, this position is at or beyond the left + edge of the row. */ struct display_pos end; + /* The smallest and the largest buffer positions that contributed to + glyphs in this row. Note that due to bidi reordering, these are + in general different from the text positions stored in `start' + and `end' members above, and also different from the buffer + positions recorded in the glyphs displayed the leftmost and + rightmost on the screen. */ + struct text_pos minpos, maxpos; + /* Non-zero means the overlay arrow bitmap is on this line. -1 means use default overlay arrow bitmap, else it specifies actual fringe bitmap number. */ @@ -947,16 +955,16 @@ displayed by ROW, which is not necessarily the smallest horizontal position. */ -#define MATRIX_ROW_START_CHARPOS(ROW) ((ROW)->start.pos.charpos) -#define MATRIX_ROW_START_BYTEPOS(ROW) ((ROW)->start.pos.bytepos) +#define MATRIX_ROW_START_CHARPOS(ROW) ((ROW)->minpos.charpos) +#define MATRIX_ROW_START_BYTEPOS(ROW) ((ROW)->minpos.bytepos) /* Return the character/ byte position at which ROW ends. BIDI Note: this is the largest character/byte position among characters in ROW, i.e. the last logical-order character displayed by ROW, which is not necessarily the largest horizontal position. */ -#define MATRIX_ROW_END_CHARPOS(ROW) ((ROW)->end.pos.charpos) -#define MATRIX_ROW_END_BYTEPOS(ROW) ((ROW)->end.pos.bytepos) +#define MATRIX_ROW_END_CHARPOS(ROW) ((ROW)->maxpos.charpos) +#define MATRIX_ROW_END_BYTEPOS(ROW) ((ROW)->maxpos.bytepos) /* Return the vertical position of ROW in MATRIX. */ @@ -1789,7 +1797,7 @@ EMACS_INT next_en_pos; /* position of next EN char for ET */ EMACS_INT ignore_bn_limit; /* position until which to ignore BNs */ bidi_dir_t sor; /* direction of start-of-run in effect */ - int scan_dir; /* direction of text scan */ + int scan_dir; /* direction of text scan, 1: forw, -1: back */ int stack_idx; /* index of current data on the stack */ /* Note: Everything from here on is not copied/saved when the bidi iterator state is saved, pushed, or popped. So only put here
--- a/src/dispnew.c Sat May 22 03:32:53 2010 +0000 +++ b/src/dispnew.c Sun May 23 11:52:45 2010 +0000 @@ -1188,6 +1188,10 @@ MATRIX_ROW_START_BYTEPOS (row) += delta_bytes; MATRIX_ROW_END_CHARPOS (row) += delta; MATRIX_ROW_END_BYTEPOS (row) += delta_bytes; + CHARPOS (row->start.pos) += delta; + BYTEPOS (row->start.pos) += delta_bytes; + CHARPOS (row->end.pos) += delta; + BYTEPOS (row->end.pos) += delta_bytes; if (!row->enabled_p) return; @@ -1748,13 +1752,19 @@ /* Check that character and byte positions are in sync. */ xassert (MATRIX_ROW_START_BYTEPOS (row) == CHAR_TO_BYTE (MATRIX_ROW_START_CHARPOS (row))); + xassert (BYTEPOS (row->start.pos) + == CHAR_TO_BYTE (CHARPOS (row->start.pos))); /* CHAR_TO_BYTE aborts when invoked for a position > Z. We can have such a position temporarily in case of a minibuffer displaying something like `[Sole completion]' at its end. */ if (MATRIX_ROW_END_CHARPOS (row) < BUF_ZV (current_buffer)) - xassert (MATRIX_ROW_END_BYTEPOS (row) - == CHAR_TO_BYTE (MATRIX_ROW_END_CHARPOS (row))); + { + xassert (MATRIX_ROW_END_BYTEPOS (row) + == CHAR_TO_BYTE (MATRIX_ROW_END_CHARPOS (row))); + xassert (BYTEPOS (row->end.pos) + == CHAR_TO_BYTE (CHARPOS (row->end.pos))); + } /* Check that end position of `row' is equal to start position of next row. */ @@ -1764,6 +1774,8 @@ == MATRIX_ROW_START_CHARPOS (next)); xassert (MATRIX_ROW_END_BYTEPOS (row) == MATRIX_ROW_START_BYTEPOS (next)); + xassert (CHARPOS (row->end.pos) == CHARPOS (next->start.pos)); + xassert (BYTEPOS (row->end.pos) == BYTEPOS (next->start.pos)); } row = next; }
--- a/src/image.c Sat May 22 03:32:53 2010 +0000 +++ b/src/image.c Sun May 23 11:52:45 2010 +0000 @@ -1689,11 +1689,13 @@ } -DEFUN ("image-refresh", Fimage_refresh, Simage_refresh, +DEFUN ("image-flush", Fimage_flush, Simage_flush, 1, 2, 0, - doc: /* Refresh the image with specification SPEC on frame FRAME. -If SPEC specifies an image file, the displayed image is updated with -the current contents of that file. + doc: /* Fush the image with specification SPEC on frame FRAME. +This removes the image from the Emacs image cache. If SPEC specifies +an image file, the next redisplay of this image will read from the +current contents of that file. + FRAME nil or omitted means use the selected frame. FRAME t means refresh the image on all frames. */) (spec, frame) @@ -8526,7 +8528,7 @@ defsubr (&Sinit_image_library); defsubr (&Sclear_image_cache); - defsubr (&Simage_refresh); + defsubr (&Simage_flush); defsubr (&Simage_size); defsubr (&Simage_mask_p); defsubr (&Simage_metadata);
--- a/src/w32.c Sat May 22 03:32:53 2010 +0000 +++ b/src/w32.c Sun May 23 11:52:45 2010 +0000 @@ -5700,7 +5700,34 @@ } else #endif - nchars = _write (fd, buffer, count); + { + /* Some networked filesystems don't like too large writes, so + break them into smaller chunks. See the Comments section of + the MSDN documentation of WriteFile for details behind the + choice of the value of CHUNK below. See also the thread + http://thread.gmane.org/gmane.comp.version-control.git/145294 + in the git mailing list. */ + const unsigned char *p = buffer; + const unsigned chunk = 30 * 1024 * 1024; + + nchars = 0; + while (count > 0) + { + unsigned this_chunk = count < chunk ? count : chunk; + int n = _write (fd, p, this_chunk); + + nchars += n; + if (n < 0) + { + nchars = n; + break; + } + else if (n < this_chunk) + break; + count -= n; + p += n; + } + } return nchars; }
--- a/src/xdisp.c Sat May 22 03:32:53 2010 +0000 +++ b/src/xdisp.c Sun May 23 11:52:45 2010 +0000 @@ -2598,7 +2598,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id) struct it *it; struct window *w; - int charpos, bytepos; + EMACS_INT charpos, bytepos; struct glyph_row *row; enum face_id base_face_id; { @@ -3012,7 +3012,7 @@ struct window *w; struct display_pos *pos; { - int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos); + EMACS_INT charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos); int i, overlay_strings_with_newlines = 0; /* If POS specifies a position in a display vector, this might @@ -14975,7 +14975,7 @@ /* The variable new_start now holds the new window start. The old start `start' can be determined from the current matrix. */ SET_TEXT_POS_FROM_MARKER (new_start, w->start); - start = start_row->start.pos; + start = start_row->minpos; start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix); /* Clear the desired matrix for the display below. */ @@ -15014,7 +15014,7 @@ { /* Advance to the next row as the "start". */ start_row++; - start = start_row->start.pos; + start = start_row->minpos; /* If there are no more rows to try, or just one, give up. */ if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row) @@ -15296,39 +15296,26 @@ { struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos; struct glyph *end = glyph + row->used[TEXT_AREA]; - struct glyph *orig_glyph = glyph; - struct cursor_pos orig_cursor = w->cursor; - - for (; glyph < end - && (!BUFFERP (glyph->object) - || glyph->charpos != PT); - glyph++) - { - w->cursor.hpos++; - w->cursor.x += glyph->pixel_width; - } - /* With bidi reordering, charpos changes non-linearly - with hpos, so the right glyph could be to the - left. */ - if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering) - && (!BUFFERP (glyph->object) || glyph->charpos != PT)) - { - struct glyph *start_glyph = row->glyphs[TEXT_AREA]; - - glyph = orig_glyph - 1; - orig_cursor.hpos--; - orig_cursor.x -= glyph->pixel_width; - for (; glyph >= start_glyph - && (!BUFFERP (glyph->object) - || glyph->charpos != PT); - glyph--) - { - w->cursor.hpos--; - w->cursor.x -= glyph->pixel_width; - } - if (BUFFERP (glyph->object) && glyph->charpos == PT) - w->cursor = orig_cursor; - } + + /* Can't use this optimization with bidi-reordered glyph + rows, unless cursor is already at point. */ + if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering)) + { + if (!(w->cursor.hpos >= 0 + && w->cursor.hpos < row->used[TEXT_AREA] + && BUFFERP (glyph->object) + && glyph->charpos == PT)) + return 0; + } + else + for (; glyph < end + && (!BUFFERP (glyph->object) + || glyph->charpos < PT); + glyph++) + { + w->cursor.hpos++; + w->cursor.x += glyph->pixel_width; + } } } @@ -15908,13 +15895,13 @@ as is, without changing glyph positions since no text has been added/removed in front of the window end. */ r0 = MATRIX_FIRST_TEXT_ROW (current_matrix); - if (TEXT_POS_EQUAL_P (start, r0->start.pos) + if (TEXT_POS_EQUAL_P (start, r0->minpos) /* PT must not be in a partially visible line. */ && !(PT >= MATRIX_ROW_START_CHARPOS (row) && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w))) { /* We have to compute the window end anew since text - can have been added/removed after it. */ + could have been added/removed after it. */ w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row)); w->window_end_bytepos @@ -15946,7 +15933,7 @@ start is not in changed text, otherwise positions would not be comparable. */ row = MATRIX_FIRST_TEXT_ROW (current_matrix); - if (!TEXT_POS_EQUAL_P (start, row->start.pos)) + if (!TEXT_POS_EQUAL_P (start, row->minpos)) GIVE_UP (16); /* Give up if the window ends in strings. Overlay strings @@ -17338,7 +17325,7 @@ { int cursor_row_p = 1; - if (PT == MATRIX_ROW_END_CHARPOS (row)) + if (PT == CHARPOS (row->end.pos)) { /* Suppose the row ends on a string. Unless the row is continued, that means it ends on a newline @@ -17375,14 +17362,15 @@ { /* If the row ends in middle of a real character, and the line is continued, we want the cursor here. - That's because MATRIX_ROW_END_CHARPOS would equal + That's because CHARPOS (ROW->end.pos) would equal PT if PT is before the character. */ if (!row->ends_in_ellipsis_p) cursor_row_p = row->continued_p; else /* If the row ends in an ellipsis, then - MATRIX_ROW_END_CHARPOS will equal point after the invisible text. - We want that position to be displayed after the ellipsis. */ + CHARPOS (ROW->end.pos) will equal point after the + invisible text. We want that position to be displayed + after the ellipsis. */ cursor_row_p = 0; } /* If the row ends at ZV, display the cursor at the end of that @@ -17518,122 +17506,87 @@ glyph[-n] = *glyph; } -/* Find the positions in a bidi-reordered ROW to serve as ROW->start - and ROW->end. */ -static struct display_pos -find_row_end (it, row) +/* Find the positions in a bidi-reordered ROW to serve as ROW->minpos + and ROW->maxpos. */ +static void +find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos) struct it *it; struct glyph_row *row; + EMACS_INT min_pos, min_bpos, max_pos, max_bpos; { /* FIXME: Revisit this when glyph ``spilling'' in continuation lines' rows is implemented for bidi-reordered rows. */ - EMACS_INT min_pos = ZV + 1, max_pos = 0; - struct glyph *g; - struct it save_it; - struct text_pos tpos; - struct display_pos row_end = it->current; - - for (g = row->glyphs[TEXT_AREA]; - g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; - g++) - { - if (BUFFERP (g->object)) - { - if (g->charpos > 0 && g->charpos < min_pos) - min_pos = g->charpos; - if (g->charpos > max_pos) - max_pos = g->charpos; - } - } - /* Empty lines have a valid buffer position at their first - glyph, but that glyph's OBJECT is zero, as if it didn't come - from a buffer. If we didn't find any valid buffer positions - in this row, maybe we have such an empty line. */ - if (max_pos == 0 && row->used[TEXT_AREA]) - { - for (g = row->glyphs[TEXT_AREA]; - g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; - g++) - { - if (INTEGERP (g->object)) - { - if (g->charpos > 0 && g->charpos < min_pos) - min_pos = g->charpos; - if (g->charpos > max_pos) - max_pos = g->charpos; - } - } - } - - /* ROW->start is the value of min_pos, the minimal buffer position + + /* ROW->minpos is the value of min_pos, the minimal buffer position we have in ROW. */ if (min_pos <= ZV) - { - /* Avoid calling the costly CHAR_TO_BYTE if possible. */ - if (min_pos != row->start.pos.charpos) - SET_TEXT_POS (row->start.pos, min_pos, CHAR_TO_BYTE (min_pos)); - if (max_pos == 0) - max_pos = min_pos; - } - - /* For ROW->end, we need the position that is _after_ max_pos, in - the logical order, unless we are at ZV. */ + SET_TEXT_POS (row->minpos, min_pos, min_bpos); + else + { + /* We didn't find _any_ valid buffer positions in any of the + glyphs, so we must trust the iterator's computed + positions. */ + row->minpos = row->start.pos; + max_pos = CHARPOS (it->current.pos); + max_bpos = BYTEPOS (it->current.pos); + } + + if (!max_pos) + abort (); + + /* Here are the various use-cases for ending the row, and the + corresponding values for ROW->maxpos: + + Line ends in a newline from buffer eol_pos + 1 + Line is continued from buffer max_pos + 1 + Line is truncated on right it->current.pos + Line ends in a newline from string max_pos + Line is continued from string max_pos + Line is continued from display vector max_pos + Line is entirely from a string min_pos == max_pos + Line is entirely from a display vector min_pos == max_pos + Line that ends at ZV ZV + + If you discover other use-cases, please add them here as + appropriate. */ if (row->ends_at_zv_p) - { - if (!row->used[TEXT_AREA]) - row->start.pos = row_end.pos; - } - else if (row->used[TEXT_AREA] && max_pos) - { - int at_eol_p; - - SET_TEXT_POS (tpos, max_pos, CHAR_TO_BYTE (max_pos)); - save_it = *it; - it->bidi_p = 0; - reseat (it, tpos, 0); - if (!get_next_display_element (it)) - abort (); /* this row cannot be at ZV, see above */ - at_eol_p = ITERATOR_AT_END_OF_LINE_P (it); - set_iterator_to_next (it, 1); - row_end = it->current; - /* If the character at max_pos is not a newline and the - characters at max_pos+1 is a newline, skip that newline as - well. Note that this may skip some invisible text. */ - if (!at_eol_p - && get_next_display_element (it) - && ITERATOR_AT_END_OF_LINE_P (it)) - { - set_iterator_to_next (it, 1); - /* Record the position after the newline of a continued row. - We will need that to set ROW->end of the last row - produced for a continued line. */ - if (row->continued_p) - save_it.eol_pos = it->current.pos; - else - { - row_end = it->current; - save_it.eol_pos.charpos = save_it.eol_pos.bytepos = 0; - } - } - else if (!row->continued_p - && MATRIX_ROW_CONTINUATION_LINE_P (row) - && it->eol_pos.charpos > 0) - { - /* Last row of a continued line. Use the position recorded - in IT->eol_pos, to the effect that the newline belongs to - this row, not to the row which displays the character - with the largest buffer position before the newline. */ - row_end.pos = it->eol_pos; - it->eol_pos.charpos = it->eol_pos.bytepos = 0; - } - *it = save_it; - /* The members of ROW->end that are not taken from buffer - positions are copied from IT->current. */ - row_end.string_pos = it->current.string_pos; - row_end.overlay_string_index = it->current.overlay_string_index; - row_end.dpvec_index = it->current.dpvec_index; - } - return row_end; + row->maxpos = it->current.pos; + else if (row->used[TEXT_AREA]) + { + if (row->ends_in_newline_from_string_p) + SET_TEXT_POS (row->maxpos, max_pos, max_bpos); + else if (CHARPOS (it->eol_pos) > 0) + SET_TEXT_POS (row->maxpos, + CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1); + else if (row->continued_p) + { + /* If max_pos is different from IT's current position, it + means IT->method does not belong to the display element + at max_pos. However, it also means that the display + element at max_pos was displayed in its entirety on this + line, which is equivalent to saying that the next line + starts at the next buffer position. */ + if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER) + SET_TEXT_POS (row->maxpos, max_pos, max_bpos); + else + { + INC_BOTH (max_pos, max_bpos); + SET_TEXT_POS (row->maxpos, max_pos, max_bpos); + } + } + else if (row->truncated_on_right_p) + /* display_line already called reseat_at_next_visible_line_start, + which puts the iterator at the beginning of the next line, in + the logical order. */ + row->maxpos = it->current.pos; + else if (max_pos == min_pos && it->method != GET_FROM_BUFFER) + /* A line that is entirely from a string/image/stretch... */ + row->maxpos = row->minpos; + else + abort (); + } + else + row->maxpos = it->current.pos; } /* Construct the glyph row IT->glyph_row in the desired matrix of @@ -17653,7 +17606,10 @@ int wrap_row_used = -1, wrap_row_ascent, wrap_row_height; int wrap_row_phys_ascent, wrap_row_phys_height; int wrap_row_extra_line_spacing; + EMACS_INT wrap_row_min_pos, wrap_row_min_bpos; + EMACS_INT wrap_row_max_pos, wrap_row_max_bpos; int cvpos; + EMACS_INT min_pos = ZV + 1, min_bpos, max_pos = 0, max_bpos; /* We always start displaying at hpos zero even if hscrolled. */ xassert (it->hpos == 0 && it->current_x == 0); @@ -17710,6 +17666,23 @@ row->phys_height = it->max_phys_ascent + it->max_phys_descent; row->extra_line_spacing = it->max_extra_line_spacing; +/* Utility macro to record max and min buffer positions seen until now. */ +#define RECORD_MAX_MIN_POS(IT) \ + do \ + { \ + if (IT_CHARPOS (*(IT)) < min_pos) \ + { \ + min_pos = IT_CHARPOS (*(IT)); \ + min_bpos = IT_BYTEPOS (*(IT)); \ + } \ + if (IT_CHARPOS (*(IT)) > max_pos) \ + { \ + max_pos = IT_CHARPOS (*(IT)); \ + max_bpos = IT_BYTEPOS (*(IT)); \ + } \ + } \ + while (0) + /* Loop generating characters. The loop is left with IT on the next character to display. */ while (1) @@ -17744,7 +17717,8 @@ row->ends_at_zv_p = 1; /* A row that displays right-to-left text must always have its last face extended all the way to the end of line, - even if this row ends in ZV. */ + even if this row ends in ZV, because we still write to th + screen left to right. */ if (row->reversed_p) extend_face_to_end_of_line (it); break; @@ -17778,6 +17752,10 @@ wrap_row_phys_ascent = row->phys_ascent; wrap_row_phys_height = row->phys_height; wrap_row_extra_line_spacing = row->extra_line_spacing; + wrap_row_min_pos = min_pos; + wrap_row_min_bpos = min_bpos; + wrap_row_max_pos = max_pos; + wrap_row_max_bpos = max_bpos; may_wrap = 0; } } @@ -17828,6 +17806,10 @@ it->max_extra_line_spacing); if (it->current_x - it->pixel_width < it->first_visible_x) row->x = x - it->first_visible_x; + /* Record the maximum and minimum buffer positions seen so + far in glyphs that will be displayed by this row. */ + if (it->bidi_p) + RECORD_MAX_MIN_POS (it); } else { @@ -17861,6 +17843,11 @@ it->current_x = new_x; it->continuation_lines_width += new_x; ++it->hpos; + /* Record the maximum and minimum buffer + positions seen so far in glyphs that will be + displayed by this row. */ + if (it->bidi_p) + RECORD_MAX_MIN_POS (it); if (i == nglyphs - 1) { /* If line-wrap is on, check if a previous @@ -17935,6 +17922,10 @@ row->phys_ascent = wrap_row_phys_ascent; row->phys_height = wrap_row_phys_height; row->extra_line_spacing = wrap_row_extra_line_spacing; + min_pos = wrap_row_min_pos; + min_bpos = wrap_row_min_bpos; + max_pos = wrap_row_max_pos; + max_bpos = wrap_row_max_bpos; row->continued_p = 1; row->ends_at_zv_p = 0; row->exact_window_width_line_p = 0; @@ -17997,6 +17988,12 @@ /* Increment number of glyphs actually displayed. */ ++it->hpos; + /* Record the maximum and minimum buffer positions + seen so far in glyphs that will be displayed by + this row. */ + if (it->bidi_p) + RECORD_MAX_MIN_POS (it); + if (x < it->first_visible_x) /* Glyph is partially visible, i.e. row starts at negative X position. */ @@ -18048,6 +18045,10 @@ if (used_before == 0) row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position); + /* Record the position of the newline, for use in + find_row_edges. */ + it->eol_pos = it->current.pos; + /* Consume the line end. This skips over invisible lines. */ set_iterator_to_next (it, 1); it->continuation_lines_width = 0; @@ -18127,7 +18128,7 @@ /* If line is not empty and hscrolled, maybe insert truncation glyphs at the left window margin. */ if (it->first_visible_x - && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row)) + && IT_CHARPOS (*it) != CHARPOS (row->start.pos)) { if (!FRAME_WINDOW_P (it->f)) insert_left_trunc_glyphs (it); @@ -18181,12 +18182,19 @@ /* Remember the position at which this line ends. */ row->end = it->current; - /* ROW->start and ROW->end must be the smallest and the largest - buffer positions in ROW. But if ROW was bidi-reordered, these - two positions can be anywhere in the row, so we must rescan all - of the ROW's glyphs to find them. */ - if (it->bidi_p) - row->end = find_row_end (it, row); + if (!it->bidi_p) + { + row->minpos = row->start.pos; + row->maxpos = row->end.pos; + } + else + { + /* ROW->minpos and ROW->maxpos must be the smallest and + `1 + the largest' buffer positions in ROW. But if ROW was + bidi-reordered, these two positions can be anywhere in the + row, so we must determine them now. */ + find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos); + } /* Record whether this row ends inside an ellipsis. */ row->ends_in_ellipsis_p @@ -18232,6 +18240,7 @@ row to be used. */ it->current_x = it->hpos = 0; it->current_y += row->height; + SET_TEXT_POS (it->eol_pos, 0, 0); ++it->vpos; ++it->glyph_row; /* The next row should by default use the same value of the @@ -18242,6 +18251,8 @@ it->glyph_row->reversed_p = row->reversed_p; it->start = row->end; return row->displays_text_p; + +#undef RECORD_MAX_MIN_POS } DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,