How To Obtain Character Width within Terminal Emulators

Background

A character's width is the number of columns a terminal emulator uses to display its glyph. This width may vary with the combination of character, terminal emulator and font set. For a given combination, the width does not seem to vary with font size, weight, emphasis or underlining. That is, if the terminal emulator has sized its grid cells for a 12 point font, increasing the font size (and all grid cells) to accomodate an 18 or 40 point font does not seem to change the number of columns the character occupies.

Technique

In order to measure a character's width, the bash shell script below puts the cursor in the home position, outputs a character, and then asks the terminal emulator for the new cursor position using terminfo's User string #7 (this string is often \033[6n). The terminal emulator then injects the cursor position into the stdin input stream from which it is read and used to determine the character's width.

And so the script does for each character from 0 through 0x10ffff, writing each character's width to a file named $TERM-character-width. The width will be a number from zero through four, or "exception" if the cursor moved unexpectedly. Often about 90 percent of characters will have a width of one column, with most of the rest being two.

#!/bin/bash
output_file=${TERM}-character-width
echo -n "" > ${output_file}
home=`infocmp -1 -l|grep "\shome="|sed "s/.*home=\(.*\),.*/\\1/"|sed "s/^\\\\[Ee]/\\\\033/"`
request=`infocmp -1 -l|grep "\su7="|sed "s/.*u7=\(.*\),.*/\\1/"|sed "s/^\\\\[Ee]/\\\\033/"`
trap "stty echo" EXIT; stty -echo
for i in {0..1114111}; do
  printf -v hex "%06x" $i
  echo -e "${home}_\U${hex}_${request}    "
  if [ $((${i} % 1000)) -eq 0 ]; then
    clear; echo -e "\n\n\nAbout "$(($((1114111-${i}))/11141))" percent remaining "
  fi
  read -d R response
  response=${response##*[}
  column=${response##*;}
  line=${response%%;*}
  width=$((${column}-3))
  if [ x${line} != x1 -o ${width} -lt 0 -o ${width} -gt 4 ]; then
    width=exception
  fi
  echo ${hex},${width} >> ${output_file}
done

Questions or Comments

Contact information

Public Domain

I dedicate this script to the public domain.