From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.bugs Subject: bug#38966: 27.0.60; Assertion failure in set_cursor_from_row Date: Mon, 06 Jan 2020 19:14:49 +0200 Message-ID: <83lfqkecc6.fsf@gnu.org> References: <497636f5-1728-1e7e-b826-8310e2a6fe13@gmx.at> Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="153791"; mail-complaints-to="usenet@blaine.gmane.org" Cc: 38966@debbugs.gnu.org To: martin rudalics Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Jan 06 18:15:36 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1ioVyX-000dqh-J1 for geb-bug-gnu-emacs@m.gmane.org; Mon, 06 Jan 2020 18:15:33 +0100 Original-Received: from localhost ([::1]:55458 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ioVyV-0008LF-QP for geb-bug-gnu-emacs@m.gmane.org; Mon, 06 Jan 2020 12:15:31 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:49023) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ioVy5-0008I5-2y for bug-gnu-emacs@gnu.org; Mon, 06 Jan 2020 12:15:07 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ioVy3-0007Yj-JH for bug-gnu-emacs@gnu.org; Mon, 06 Jan 2020 12:15:05 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:40633) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ioVy3-0007YS-FH for bug-gnu-emacs@gnu.org; Mon, 06 Jan 2020 12:15:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ioVy3-0000HL-Bg for bug-gnu-emacs@gnu.org; Mon, 06 Jan 2020 12:15:03 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 06 Jan 2020 17:15:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 38966 X-GNU-PR-Package: emacs Original-Received: via spool by 38966-submit@debbugs.gnu.org id=B38966.15783308901023 (code B ref 38966); Mon, 06 Jan 2020 17:15:03 +0000 Original-Received: (at 38966) by debbugs.gnu.org; 6 Jan 2020 17:14:50 +0000 Original-Received: from localhost ([127.0.0.1]:46605 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ioVxp-0000GQ-S6 for submit@debbugs.gnu.org; Mon, 06 Jan 2020 12:14:50 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:39698) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ioVxo-0000GE-Fp for 38966@debbugs.gnu.org; Mon, 06 Jan 2020 12:14:48 -0500 Original-Received: from fencepost.gnu.org ([2001:470:142:3::e]:58626) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ioVxj-0007EP-1v; Mon, 06 Jan 2020 12:14:43 -0500 Original-Received: from [176.228.60.248] (port=1709 helo=home-c4e4a596f7) by fencepost.gnu.org with esmtpsa (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1ioVxh-0001xx-Hb; Mon, 06 Jan 2020 12:14:42 -0500 In-reply-to: <497636f5-1728-1e7e-b826-8310e2a6fe13@gmx.at> (message from martin rudalics on Mon, 6 Jan 2020 10:19:02 +0100) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:174247 Archived-At: > From: martin rudalics > Date: Mon, 6 Jan 2020 10:19:02 +0100 > > The immediate cause is that the *scratch* window has a header _and_ a > tab line. Disabling either of these makes the failure disappear. > > The culprit is IIUC this part of xdisp.c > > /* Finally, fall back on the first row of the window after the > header line (if any). This is slightly better than not > displaying the cursor at all. */ > if (!row) > { > row = matrix->rows; > if (row->mode_line_p) > ++row; > } > set_cursor_from_row (w, row, matrix, 0, 0, 0, 0); > > which is no more valid because the first row is now the tab line of > the *scratch* window. In this case the line we get by ++row is the > header line triggering the subsequent assertion failure > > /* Don't even try doing anything if called for a mode-line or > header-line row, since the rest of the code isn't prepared to > deal with such calamities. */ > eassert (!row->mode_line_p); > if (row->mode_line_p) > return false; Thanks for the analysis. I agree with you. A proposed patch is below. > If my analysis is correct, we should probably skip two lines to move > to the first text line of the window. But I would not exclude the > possibility (I have not tried to produce such behavior yet) that that > third line does not even exist (what would the "(if any)" in the > comment otherwise allude to?) or at least is the mode line of that > window and the assertion failure would trigger again. I don't expect to have a window that has no lines showing text. I believe we don't allow creation/resizing of windows to such a small size? If that's not guaranteed, I'm okay with adding an assertion somewhere, but that would be a separate problem: we never expected such a calamity even before tab-lines were added. > So I think we should do two things there: (1) skip subsequent lines > with row->mode_line_p enabled and (2) not call set_cursor_from_row > when we have consumed all rows. If we don't call set_cursor_from_row, we will not have a cursor displayed where it should be, which is a display bug in and of itself. > BTW: I would also recommend to rename mode_line_p to something like > say "no_text_line_p". Presently, people like me not used to hack the > display code, might consider mode_line_p verbatim and not apply its > semantics to header or tab lines. Sorry, but that ship sailed a long time ago. You will have to make do with the comments in dispextern.h, which document this weirdness. diff --git a/src/xdisp.c b/src/xdisp.c index 3d286cb22f..8b20601a93 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -16244,8 +16244,8 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, bool string_from_text_prop = false; /* Don't even try doing anything if called for a mode-line or - header-line row, since the rest of the code isn't prepared to - deal with such calamities. */ + header-line or tab-line row, since the rest of the code isn't + prepared to deal with such calamities. */ eassert (!row->mode_line_p); if (row->mode_line_p) return false; @@ -17504,6 +17504,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, else { row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos); + if (row->tab_line_p) + ++row; if (row->mode_line_p) ++row; if (!row->enabled_p) @@ -17576,6 +17578,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, || row->mode_line_p) { row = w->current_matrix->rows; + if (row->tab_line_p) + ++row; if (row->mode_line_p) ++row; } @@ -17640,8 +17644,9 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, ; else if (rc != CURSOR_MOVEMENT_SUCCESS && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row) - /* Make sure this isn't a header line by any chance, since - then MATRIX_ROW_PARTIALLY_VISIBLE_P might yield true. */ + /* Make sure this isn't a header line nor a tab-line by + any chance, since then MATRIX_ROW_PARTIALLY_VISIBLE_P + might yield true. */ && !row->mode_line_p && !cursor_row_fully_visible_p (w, true, true, true)) { @@ -18769,11 +18774,13 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) } } /* Finally, fall back on the first row of the window after the - header line (if any). This is slightly better than not - displaying the cursor at all. */ + tab-line and header line (if any). This is slightly better + than not displaying the cursor at all. */ if (!row) { row = matrix->rows; + if (row->tab_line_p) + ++row; if (row->mode_line_p) ++row; } @@ -19787,7 +19794,9 @@ row_containing_pos (struct window *w, ptrdiff_t charpos, ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1; int last_y; - /* If we happen to start on a header-line, skip that. */ + /* If we happen to start on a header-line or a tab-line, skip that. */ + if (row->tab_line_p) + ++row; if (row->mode_line_p) ++row; @@ -22380,7 +22389,7 @@ find_row_edges (struct it *it, struct glyph_row *row, if (STRINGP (it->object) /* this is not the first row */ && row > it->w->desired_matrix->rows - /* previous row is not the header line */ + /* previous row is not the header line or tab-line */ && !r1->mode_line_p /* previous row also ends in a newline from a string */ && r1->ends_in_newline_from_string_p)