On 2014-12-18 Thu 17:15, Eli Zaretskii wrote: >> From: Titus von der Malsburg >> 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