Function: org-string-width

org-string-width is a byte-compiled function defined in org-macs.el.gz.

Signature

(org-string-width STRING &optional PIXELS)

Documentation

Return width of STRING when displayed in the current buffer.

Return width in pixels when PIXELS is non-nil.

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-macs.el.gz
(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-pixel-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 ellipsis 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
            (erase-buffer)
            (insert string)
            (setq pixel-width
                  (if (get-buffer-window (current-buffer))
                      (car (window-text-pixel-size
                            ;; FIXME: 10000 because
                            ;; `most-positive-fixnum' ain't working
                            ;; (tests failing) and this call will be
                            ;; removed after we drop Emacs 28 support
                            ;; anyway.
                            nil (line-beginning-position) (point-max) 10000))
                    (let ((dedicatedp (window-dedicated-p))
                          (oldbuffer (window-buffer)))
                      (unwind-protect
                          (progn
                            ;; Do not throw error in dedicated windows.
                            (set-window-dedicated-p nil nil)
                            (set-window-buffer nil (current-buffer))
                            (car (window-text-pixel-size
                                  nil (line-beginning-position) (point-max) 10000)))
                        (set-window-buffer nil oldbuffer)
                        (set-window-dedicated-p nil dedicatedp)))))
            (unless pixels
              (erase-buffer)
              (insert "a")
              (setq symbol-width
                    (if (get-buffer-window (current-buffer))
                        (car (window-text-pixel-size
                              nil (line-beginning-position) (point-max) 10000))
                      (let ((dedicatedp (window-dedicated-p))
                            (oldbuffer (window-buffer)))
                        (unwind-protect
                            (progn
                              ;; Do not throw error in dedicated windows.
                              (set-window-dedicated-p nil nil)
                              (set-window-buffer nil (current-buffer))
                              (car (window-text-pixel-size
                                    nil (line-beginning-position) (point-max) 10000)))
                          (set-window-buffer nil oldbuffer)
                          (set-window-dedicated-p nil dedicatedp)))))))
          (if pixels
              pixel-width
            (/ pixel-width symbol-width)))))))