bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#19395: 25.0.50; Setting left fringe to 0 messes up window-width


From: Titus von der Malsburg
Subject: bug#19395: 25.0.50; Setting left fringe to 0 messes up window-width
Date: Sat, 20 Dec 2014 15:51:27 +0100

On 2014-12-18 Thu 17:15, Eli Zaretskii wrote:
>> From: Titus von der Malsburg <malsburg@posteo.de>
>> Cc: 19395@debbugs.gnu.org
>> Date: Wed, 17 Dec 2014 19:36:04 -0800
>> 
>> > But if we want this function to be more generally useful, it
>> > shouldn't be limited to the frame's canonical character size, and
>> > should at least take the face-remapping into account.  Bonus points
>> > for accepting a face as an argument and using that face's font
>> > dimensions.
>> 
>> This is more difficult than I thought.  Below is a first sketch.  Let me
>> know if you think this is going in the right direction and I'll polish
>> it and add the bonus feature.
>> 
>> It appears that a font has to be rendered before Emacs can tell how wide
>> a character is.  That's why we need the temporary buffer.  Not elegant,
>> but I couldn't find a better way.  `default-font-width' complements
>> `default-font-height' in simple.el.  The other function would go into
>> window.el.
>
> Given the changes I pushed in commit b197822, you will no longer need
> all this complexity.  Just
>
>    (aref (font-info (face-font 'default)) 11)

Great, thanks for adding this.  Below the updated version of my solution
to the original problem:

(defun window-char-width (&optional window face)
   "Return character width for WINDOW.
WINDOW must be a live window and defaults to the selected one.

FACE is the face for which character width should be
returned.  Buffer-local face remappings are applied.  If nil, the
default face is used."
   (with-selected-window (window-normalize-window window t)
     (let* ((face (if face face 'default))
            (info (font-info (face-font face)))
            (width (aref info 11)))
       (if (> width 0)
          width
         (aref info 10)))))

(defun window-max-characters-per-line (&optional window face)
  "Return the number of characters that can be displayed
on one line.
WINDOW must be a live window and defaults to the selected one.

FACE is the face whose character width should be used for the
calculation.  Buffer-local face remappings are applied.  If nil,
the default face is used.

This function is different from `window-body-width' in that it
accounts for fringes (when at least one fringe has zero width,
one column is reserved for continuation characters) and for the
size of the default font (which may have been adjusted using,
e.g., `text-scale-increase')."
  (with-selected-window (window-normalize-window window t)
    (let* ((window-width (window-body-width window t))
           (font-width (window-char-width window face))
           (ncols (/ window-width font-width)))
      (if (and (display-graphic-p)
               overflow-newline-into-fringe
               (/= (frame-parameter nil 'left-fringe) 0)
               (/= (frame-parameter nil 'right-fringe) 0))
          ncols
        (1- ncols)))))

Note that the first function is a variant of Martin's version which had
a bug: if the buffer in the specified window is displayed in two frames,
the returned character width was always the one used in the current
frame which is not necessarily the character width in the specified
window (the window may be in the other frame).  This is a problem
because character width can be different, if the two frames use
different default fonts.

For completeness, it probably also makes sense to include the following
function in simple.el, which already has a function
`default-font-height'.

(defun default-font-width () 
  "Return the width in pixels of the current buffer's default face font.

Buffer-local face remappings are applied."
  (let* ((info (font-info (face-font 'default)))
         (width (aref info 11)))
    (if (> width 0)
        width
      (aref info 10))))

> (For bullet-proof code, check that this is not zero, and if it is, use
> the 10th member instead; see the docs.)

This is checked.

> If we are going to put this in simple.el or subr.el, I don't think we
> need to worry about XEmacs.

I removed that part of the condition.

I also added the bonus feature which lets you specify a specific face
that should be used for the calculations.

  Titus

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]