From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Yuan Fu Newsgroups: gmane.emacs.devel Subject: Re: Line wrap reconsidered Date: Mon, 25 May 2020 23:30:36 -0400 Message-ID: <090B0FA5-2AA6-4134-BB8B-3FD9BFCC5AA0@gmail.com> References: <92FF4412-04FB-4521-B6CE-52B08526E4E5@gmail.com> <878shfsq35.fsf@gnus.org> <6795D9A1-904E-4C6F-AE86-9EDD52718F01@gmail.com> Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.80.23.2.2\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_2AA19033-5352-4E28-859F-25C1D5EECD19" Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="121360"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel To: Lars Ingebrigtsen , Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Tue May 26 05:31:25 2020 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jdQJI-000VXA-GQ for ged-emacs-devel@m.gmane-mx.org; Tue, 26 May 2020 05:31:24 +0200 Original-Received: from localhost ([::1]:35374 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jdQJH-0000wC-JJ for ged-emacs-devel@m.gmane-mx.org; Mon, 25 May 2020 23:31:23 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:46936) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdQIb-0000Vy-Rf for emacs-devel@gnu.org; Mon, 25 May 2020 23:30:41 -0400 Original-Received: from mail-qk1-x734.google.com ([2607:f8b0:4864:20::734]:39041) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jdQIa-0003VD-9y; Mon, 25 May 2020 23:30:41 -0400 Original-Received: by mail-qk1-x734.google.com with SMTP id w3so13751659qkb.6; Mon, 25 May 2020 20:30:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:message-id:mime-version:subject:date:in-reply-to:cc:to :references; bh=YckEYCERr8/hcUB3BohRqmOoUSunJjspOztXmEesdf8=; b=Fvytlfrt0lo+LAC3G9M9VoaRUWEEVBzhDXOmnfdl4IguRvq/b/P4UflcqyrVJPX4j0 pbjZ+ljlNEDW5jXE0nrjxlsJ2rdH4Y6x7n1dDmzZJKpwU465vNHoNOVe6aJVPl1qwj4i q/8r7oHvJxpHPliRmMADwlg+SGeZT81K2hkPi5rDjziECc93seM9eJVJK8DiN/hjsc9P CYyukM/IXtQy6V1uH56UJKHiD07DbY6M5Ptz+OPb0tdVK4Nr+r0+SlMBdaSp28IEpUuQ R6rbbKGFk/xMVJbr1gVtpTclRicoJ84qJWdQb4Hqwvxgu2SwsjPKLFxkpRxcmLLSHpa4 oxKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:message-id:mime-version:subject:date :in-reply-to:cc:to:references; bh=YckEYCERr8/hcUB3BohRqmOoUSunJjspOztXmEesdf8=; b=b6Q8sz5Fu3anEUjC/XIpLi8dR4BNmyHA7DqRc4l6dZLncB+A5GHOraGCQfkUbnuO3M 7JfvLa55WUZzXuJv3oFyU+HerMmlWnUpO7iUHyt+cnVWJx1cqMommzH3GKut2MB7WpR3 jB19NshkiIl0ihYC7H7KlWcbwzv9M5+xZm+nYKAmMwFqwATD+yN9f67FIj81XSPqnjKL WTQVf+7wt2+xEOPCXWxT4pIyeIi5x6q0+6g3fBQNiCS+XVKcO8gvBkzIpT4146CWMuOz 70q9ABPcUCBwqxXU4FiwlxNhoKy4v38uL4ksxAPUyjUk/2I1VqfM1YKAw8ubPInw7RNd VFsQ== X-Gm-Message-State: AOAM530tgcXER+YI1GVd2Djh9i5EFbv51r5sKKRAzmmSztxfb/TcUfy0 Knyg/H534kg6hAh8uiNf1+Y= X-Google-Smtp-Source: ABdhPJyKnYH8DTk9b46BNvb1KAWFmZczL4hMweyGPM1bV23FBWQyER0Mr/CVA1RjsEDse3YsOBlblg== X-Received: by 2002:a37:b95:: with SMTP id 143mr20849931qkl.99.1590463838631; Mon, 25 May 2020 20:30:38 -0700 (PDT) Original-Received: from [192.168.1.10] (c-174-60-229-153.hsd1.pa.comcast.net. [174.60.229.153]) by smtp.gmail.com with ESMTPSA id s74sm16360438qka.54.2020.05.25.20.30.37 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 25 May 2020 20:30:38 -0700 (PDT) In-Reply-To: <6795D9A1-904E-4C6F-AE86-9EDD52718F01@gmail.com> X-Mailer: Apple Mail (2.3608.80.23.2.2) Received-SPF: pass client-ip=2607:f8b0:4864:20::734; envelope-from=casouri@gmail.com; helo=mail-qk1-x734.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:251416 Archived-At: --Apple-Mail=_2AA19033-5352-4E28-859F-25C1D5EECD19 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii The redisplay code now works! Now I need to explore how to apply the = text properties. I had a look at category table. IIUC, a category table = for all unicode characters would be impractically large and unnecessary. = A normal list of ranges would probably work.=20 Yuan --Apple-Mail=_2AA19033-5352-4E28-859F-25C1D5EECD19 Content-Disposition: attachment; filename=wrap.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="wrap.patch" Content-Transfer-Encoding: 7bit diff --git a/src/xdisp.c b/src/xdisp.c index 01f272033e..7f04c1bc67 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -427,6 +427,28 @@ #define IT_DISPLAYING_WHITESPACE(it) \ && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \ || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t')))) +/* Return true if the current character allows wrapping before it. */ +static bool char_can_wrap_before (struct it *it) +{ + Lisp_Object charpos = make_fixnum (IT_CHARPOS (*it)); + Lisp_Object prop = Fget_text_property (charpos, Qcan_wrap, Qnil); + if (EQ (Qt, prop) || EQ (Qbefore_only, prop)) + return true; + else + return false; +} + +/* Return true if the current character allows wrapping after it. */ +static bool char_can_wrap_after (struct it *it) +{ + Lisp_Object charpos = make_fixnum (IT_CHARPOS (*it)); + Lisp_Object prop = Fget_text_property (charpos, Qcan_wrap, Qnil); + if (EQ (Qt, prop) || EQ (Qafter_only, prop)) + return true; + else + return false; +} + /* If all the conditions needed to print the fill column indicator are met, return the (nonnegative) column number, else return a negative value. */ @@ -9098,9 +9120,12 @@ #define IT_RESET_X_ASCENT_DESCENT(IT) \ { if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA) { - if (IT_DISPLAYING_WHITESPACE (it)) + /* If this character displays a whitespace or the text + property says you can wrap after it, the next one can + wrap. */ + if (IT_DISPLAYING_WHITESPACE (it) || char_can_wrap_after (it)) may_wrap = true; - else if (may_wrap) + if (! IT_DISPLAYING_WHITESPACE (it) && may_wrap) { /* We have reached a glyph that follows one or more whitespace characters. If the position is @@ -9249,9 +9274,13 @@ #define IT_RESET_X_ASCENT_DESCENT(IT) \ bool can_wrap = true; /* If we are at a whitespace character - that barely fits on this screen line, - but the next character is also - whitespace, we cannot wrap here. */ + (or a character that allows wrapping + after it) that barely fits on this + screen line, but the next character + is also whitespace (or a character + that forbids wrapping before it), we + cannot wrap here. + */ if (it->line_wrap == WORD_WRAP && wrap_it.sp >= 0 && may_wrap @@ -9263,7 +9292,8 @@ #define IT_RESET_X_ASCENT_DESCENT(IT) \ SAVE_IT (tem_it, *it, tem_data); set_iterator_to_next (it, true); if (get_next_display_element (it) - && IT_DISPLAYING_WHITESPACE (it)) + && (IT_DISPLAYING_WHITESPACE (it) + || !char_can_wrap_before (it))) can_wrap = false; RESTORE_IT (it, &tem_it, tem_data); } @@ -9342,19 +9372,23 @@ #define IT_RESET_X_ASCENT_DESCENT(IT) \ else IT_RESET_X_ASCENT_DESCENT (it); - /* If the screen line ends with whitespace, and we - are under word-wrap, don't use wrap_it: it is no - longer relevant, but we won't have an opportunity - to update it, since we are done with this screen - line. */ + /* If the screen line ends with whitespace (or + wrap-able character), and we are under word-wrap, + don't use wrap_it: it is no longer relevant, but + we won't have an opportunity to update it, since + we are done with this screen line. */ if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it) /* If the character after the one which set the - may_wrap flag is also whitespace, we can't - wrap here, since the screen line cannot be - wrapped in the middle of whitespace. - Therefore, wrap_it _is_ relevant in that + may_wrap flag is also whitespace (or is a + character that forbids wrapping before it), + we can't wrap here, since the screen line + cannot be wrapped in the middle of whitespace + (or before a character that forbids wrapping + before it). Therefore, wrap_it (previously + found wrap-point) _is_ relevant in that case. */ - && !(moved_forward && IT_DISPLAYING_WHITESPACE (it))) + && !(moved_forward && (IT_DISPLAYING_WHITESPACE (it) + || !char_can_wrap_before (it)))) { /* If we've found TO_X, go back there, as we now know the last word fits on this screen line. */ @@ -23180,9 +23214,9 @@ #define RECORD_MAX_MIN_POS(IT) \ if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA) { - if (IT_DISPLAYING_WHITESPACE (it)) + if (IT_DISPLAYING_WHITESPACE (it) || char_can_wrap_after (it)) may_wrap = true; - else if (may_wrap) + if (! IT_DISPLAYING_WHITESPACE (it) && may_wrap) { SAVE_IT (wrap_it, *it, wrap_data); wrap_x = x; @@ -23328,7 +23362,8 @@ #define RECORD_MAX_MIN_POS(IT) \ was a space or tab AND (ii) the current character is not. */ && (!may_wrap - || IT_DISPLAYING_WHITESPACE (it))) + || IT_DISPLAYING_WHITESPACE (it) + || char_can_wrap_after (it))) goto back_to_wrap; /* Record the maximum and minimum buffer @@ -23362,7 +23397,8 @@ #define RECORD_MAX_MIN_POS(IT) \ was a space or tab AND (ii) the current character is not. */ && (!may_wrap - || IT_DISPLAYING_WHITESPACE (it))) + || IT_DISPLAYING_WHITESPACE (it) + || char_can_wrap_after (it))) goto back_to_wrap; } @@ -34231,6 +34267,9 @@ syms_of_xdisp (void) DEFSYM (QCfile, ":file"); DEFSYM (Qfontified, "fontified"); DEFSYM (Qfontification_functions, "fontification-functions"); + DEFSYM (Qcan_wrap, "can-wrap"); + DEFSYM (Qbefore_only, "before-only"); + DEFSYM (Qafter_only, "after-only"); /* Name of the symbol which disables Lisp evaluation in 'display' properties. This is used by enriched.el. */ --Apple-Mail=_2AA19033-5352-4E28-859F-25C1D5EECD19--