From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Ihor Radchenko Newsgroups: gmane.emacs.bugs Subject: bug#51766: string-pixel-width limitations (was: bug#51766: 29.0.50; Return value of buffer-chars-modified-tick changes when buffer text is not yet changed before inserting a character for non-latin input methods) Date: Tue, 21 Jun 2022 20:39:10 +0800 Message-ID: <87a6a6qjgx.fsf@localhost> References: <87mtmalrs1.fsf@localhost> <837dde200c.fsf@gnu.org> <87k0helmig.fsf@localhost> <831r3m1tpk.fsf@gnu.org> <8735o1r31q.fsf@localhost> <834k8hzi10.fsf@gnu.org> <87zgq9pmb6.fsf@localhost> <831r3lzfk4.fsf@gnu.org> <87wnldpk5x.fsf@localhost> <83zgq9xv1y.fsf@gnu.org> <87r1bkpgjw.fsf@localhost> <87y1xv7ggf.fsf@localhost> <838rpvpns3.fsf@gnu.org> <8735fyslgq.fsf@localhost> <83fsjyl3sz.fsf@gnu.org> <87r13iqo19.fsf@localhost> <834k0eky7h.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="25007"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 51766@debbugs.gnu.org, monnier@iro.umontreal.ca To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Jun 21 14:39:16 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1o3dA3-0006Fz-MY for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 21 Jun 2022 14:39:15 +0200 Original-Received: from localhost ([::1]:41412 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3dA2-0003GC-JR for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 21 Jun 2022 08:39:14 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:50642) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3d9q-0003Ck-Bc for bug-gnu-emacs@gnu.org; Tue, 21 Jun 2022 08:39:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:37256) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o3d9q-00028g-2d for bug-gnu-emacs@gnu.org; Tue, 21 Jun 2022 08:39:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1o3d9q-0005pE-0g for bug-gnu-emacs@gnu.org; Tue, 21 Jun 2022 08:39:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Ihor Radchenko Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 21 Jun 2022 12:39:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 51766 X-GNU-PR-Package: emacs Original-Received: via spool by 51766-submit@debbugs.gnu.org id=B51766.165581508822319 (code B ref 51766); Tue, 21 Jun 2022 12:39:01 +0000 Original-Received: (at 51766) by debbugs.gnu.org; 21 Jun 2022 12:38:08 +0000 Original-Received: from localhost ([127.0.0.1]:59386 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1o3d8x-0005nu-Qe for submit@debbugs.gnu.org; Tue, 21 Jun 2022 08:38:08 -0400 Original-Received: from mail-oa1-f46.google.com ([209.85.160.46]:37433) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1o3d8v-0005nO-9x for 51766@debbugs.gnu.org; Tue, 21 Jun 2022 08:38:06 -0400 Original-Received: by mail-oa1-f46.google.com with SMTP id 586e51a60fabf-fb6b4da1dfso18179667fac.4 for <51766@debbugs.gnu.org>; Tue, 21 Jun 2022 05:38:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:in-reply-to:references:date:message-id :mime-version; bh=V/K/yOPYT5YcrBKtVFXa5/DN8ftRe1G5E6PhpWar0lY=; b=KP+x9AN3Pi+mf6opUFwlb4CWXRW5wOcKXUm8/3swVID2Y4DP56WlzZCty9m+g1GLJG F6Y92ORPN+txMEbhoqXzvjoUs+JErSUQ555qgNynWD7ynZwhIaOjMasC6/TmFkOP2Jq9 lIW5BKtmRMf5zbPwuqicgEAvKrD74SVZd4YRWCEJNyN4N/77pWdnee2CC2Yk2LCgXqeA zne1FeGbGtbTEW6/DiWNny2f/V2F4ka+7VMod3gVRVm67G1ya+GGw0hE5zPv5dPF+sPL 4mv3oN/neQVTx9oNlfyKO2TQjqbAfzW8YEZoG3Y3GgNXjK+jEzo3GoErarZ+coiQF3Uz t3KQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:in-reply-to:references:date :message-id:mime-version; bh=V/K/yOPYT5YcrBKtVFXa5/DN8ftRe1G5E6PhpWar0lY=; b=q7I11mYChnh2XzOaw3s6Yzk3/G+JyjECrODHqjloqKlGJkul4ftwt0hmzjL30KK0C2 MPYfmezOpC3Hg2nSBVag9YZAyAxtcjDZFqRE24w99R+Vbm1JbHfiO7iLdqKFNSnUin2h xIl8ZcSMkZxRRJDKJNz8dWR5kZE+E+t/1Avq3rPZzBWG0eum/hsJZvwg4qzWLRBieRDc MsrI2Xvm1rPe3hSJ+krWOzwe8new8I9eHF6rwqhDKckE4Y4XzIVP9bng42jZ1NQmJGro 6/0xVy/WZFL0dyFmoMTAfAj2gKtRya9VPHQy1nwpkdo/8SF93QKvyvQOtYtrqtB51USQ j33w== X-Gm-Message-State: AJIora8483OU6RIEOmlxTL8BJ+s0+iyEA8I57GXpe92B9abyBkSIN0MI nIpwO6pzCWFKUtu8zQmLuxM= X-Google-Smtp-Source: AGRyM1v/9s7RuRKAbq7NH15VXT8D858BUCuocygjakyGJNaH6Ofn1IrC8UvQCFoP1blqHbwyDI+Dlw== X-Received: by 2002:a05:6870:631a:b0:101:6275:67e7 with SMTP id s26-20020a056870631a00b00101627567e7mr15881230oao.114.1655815079404; Tue, 21 Jun 2022 05:37:59 -0700 (PDT) Original-Received: from localhost ([207.126.88.10]) by smtp.gmail.com with ESMTPSA id u10-20020a4ab5ca000000b0041ba884d42csm9421168ooo.42.2022.06.21.05.37.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Jun 2022 05:37:58 -0700 (PDT) In-Reply-To: <834k0eky7h.fsf@gnu.org> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list 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-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:234957 Archived-At: Eli Zaretskii writes: >> >> Because string width in different buffers may be different depending on >> >> the fontification, frame font size, face remapping, >> >> wrap-prefix/line-prefix string properties (AFAIK, the built-in >> >> string-pixel-width will return incorrect value on string with such >> >> properties), invisibility specs in the buffer, line numbers mode, etc >> >> We have implemented a number of workarounds in org-string-width on main, >> >> but I am not 100% sure that I covered all the edge cases. >> > >> > If you need such high accuracy, may I suggest window-text-pixel-size? >> >> window-text-pixel-size suffers from the same issues with >> wrap-prefix/line-prefix and line numbers mode. > > What issue are those? The length of line-prefix is added to the return value of window-text-pixel-size, which makes it wrong when the intention is measuring the actual string width. Not that window-text-pixel-size is misbehaving here - line-prefix does need to be included if the intention is to query the actual full width of text in buffer. The same goes for line numbers mode - line numbers are a part of window size. However, using window-text-pixel-size becomes awkward as the means to measure expected string width when it is going to be inserted into current buffer. >> Also, in order to use it in current buffer on not-yet-inserted string, >> you need to insert it. That where the issue in valign originated from. > > The usual method is to use a temporary buffer. Yes, and it is not accurate because temporary buffer may not have the same local environment for face remapping, invisibility specs, char-property-alias, etc To show all the trickery, let me share org-string-width I had to implement for the purposes of Org mode. I did not want this function to be complex and every single extra LOC there is fixing some edge case, test failure, or bug report: (defun org-string-width (string &optional pixels) "Return width of STRING when displayed in the current buffer. Return width in pixels when PIXELS is non-nil." (if (and (version< emacs-version "28") (not pixels)) ;; FIXME: Fallback to old limited version, because ;; `window-pixel-width' is buggy in older Emacs. (org--string-width-1 string) ;; Wrap/line prefix will make `window-text-pizel-size' return too ;; large value including the prefix. (remove-text-properties 0 (length string) '(wrap-prefix t line-prefix t) string) ;; Face should be removed to make sure that all the string symbols ;; are using default face with constant width. Constant char width ;; is critical to get right string width from pixel width (not needed ;; when PIXELS are requested though). (unless pixels (remove-text-properties 0 (length string) '(face t) string)) (let (;; We need to remove the folds to make sure that folded table ;; alignment is not messed up. (current-invisibility-spec (or (and (not (listp buffer-invisibility-spec)) buffer-invisibility-spec) (let (result) (dolist (el buffer-invisibility-spec) (unless (or (memq el '(org-fold-drawer org-fold-block org-fold-outline)) (and (listp el) (memq (car el) '(org-fold-drawer org-fold-block org-fold-outline)))) (push el result))) result))) (current-char-property-alias-alist char-property-alias-alist)) (with-temp-buffer (setq-local display-line-numbers nil) (setq-local buffer-invisibility-spec (if (listp current-invisibility-spec) (mapcar (lambda (el) ;; Consider elipsis to have 0 width. ;; It is what Emacs 28+ does, but we have ;; to force it in earlier Emacs versions. (if (and (consp el) (cdr el)) (list (car el)) el)) current-invisibility-spec) current-invisibility-spec)) (setq-local char-property-alias-alist current-char-property-alias-alist) (let (pixel-width symbol-width) (with-silent-modifications (setf (buffer-string) string) (setq pixel-width (if (get-buffer-window (current-buffer)) (car (window-text-pixel-size nil (line-beginning-position) (point-max))) (set-window-buffer nil (current-buffer)) (car (window-text-pixel-size nil (line-beginning-position) (point-max))))) (unless pixels (setf (buffer-string) "a") (setq symbol-width (if (get-buffer-window (current-buffer)) (car (window-text-pixel-size nil (line-beginning-position) (point-max))) (set-window-buffer nil (current-buffer)) (car (window-text-pixel-size nil (line-beginning-position) (point-max))))))) (if pixels pixel-width (/ pixel-width symbol-width))))))) Best, Ihor