#!/usr/bin/env bash :<<'__comments__' Name: ttf4enscript Usage: $0 [] [-s|--select|--show] Synopsis: Convert a TrueType font file to Postscript Type 1 files for use by GNU enscript; show/select AFMPath directories searched by enscript; show/select TrueType file(s) found by the fontconfig utilities; show Postscript font names in the AFMPath directories. Notes: Developed from information in 'man 1 enscript' and these sources: https://east.fm/posts/adding-fonts-to-enscript/index.html http://linux-sxs.org/pipermail/linux-users/2007-September/068355.html https://www.emacswiki.org/emacs/EnscriptPrint Author: G. D. LaBossiere, Xview Solutions Inc. Version: 1.1.0 Created: 2019-02-01 (version 1.0.0) Modified: 2019-03-28 License: GNU GPL v3 __comments__ #------------------------------------------------------------------------------ # constants #------------------------------------------------------------------------------ # export ENSCRIPT_AFMPATH="/first/path:/second/path:/third/path..." #+ to the environment before running this script if you want to override the #+ AFMPath directive in the default enscript config files '$HOME/.enscriptrc' #+ and '/etc/enscript.cfg' # ENSCRIPT_AFMPATH="" #------------------------------------------------------------------------------ # error codes #------------------------------------------------------------------------------ ERROR_0="Program terminated normally" ERROR_10="Requires bash 4.2+" ERROR_15="Missing required program(s)" ERROR_16="Missing required function(s)" ERROR_20="Insufficient user privilege" ERROR_23="Required directory not found" ERROR_35="Bad file content, format, syntax or type" ERROR_255="Called program error or user interrupt" #------------------------------------------------------------------------------ # variables #------------------------------------------------------------------------------ argList="" errFuncName="" exitMessage="" showTui="" psDirs=() psNames=() sourceFile="" targetPath="" ttFiles=() #------------------------------------------------------------------------------ # functions #------------------------------------------------------------------------------ :<<'__comments__' Name: check_bash Synopsis: Check for supported bash versions Arguments: --- Requires: bash 4.2+ Returns: 0 on success; $errFuncName and exit 10 on error. Calls: --- __comments__ check_bash() { errFuncName="$FUNCNAME" [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -ge 2 ]] || \ [[ ${BASH_VERSINFO[0]} -gt 4 ]] || exit 10 return 0 } #------------------------------------------------------------------------------ :<<'__comments__' Name: check_required Synopsis: Verify all required tools/utilities are available on this host. Arguments: --- Requires: sed, sort, tr Returns: 0 on success; $errFuncName, $exitMessage and exit 15 on error. Calls: --- __comments__ check_required() { errFuncName="$FUNCNAME" type -p sed sort tr &>/dev/null || exit 15 local each missing required # explanation of commands: #+ sed -e "s/#.*$//" -e "/^$/d" ==> exclude commented or blank lines #+ sed -ne "/ type /p" ==> select only lines containing ' type ' #+ ${0} ==> this file #+ sed -e "s/.*type \-*p*P*\(.*\).\+>.*/\1/" ==> extract strings between #+ 'type -p' and '?>' (i.e. save the arguments passed to 'type' but exclude #+ everything from and after the first char before a '>' redirection symbol) #+ sed -e "s/\$.\+ //g" ==> delete any space-terminated strings that start with #+ a '$' dollar symbol (i.e. unexpanded vars) #+ sed -e "s/[^0-9a-zA-Z_ -]//g" ==> delete chars not allowed in program names required=($(sed -e "s/#.*$//" -e "/^$/d" -ne "/ type /p" "${0}" | \ sed -e "s/.*type \-*p*P*\(.*\).\+>.*/\1/" -e "s/\$.\+ //g" \ -e "s/[^0-9a-zA-Z_ -]//g")) # explanation of commands: #+ printf "%s\n" "${required[@]}" ==> output each array element #+ sort -u ==> remove duplicate names #+ tr '\n' ' ' ==> replace newlines with spaces (i.e. convert to a string) #+ tr -s ' ' ==> squeeze spaces (i.e. leave a single space between names) required="$(printf "%s\n" "${required[@]}" | sort -u | tr '\n' ' ' | \ tr -s ' ' )" for each in ${required}; do type -p "${each}" &>/dev/null || missing="${missing} ${each}" done exitMessage="Program(s) required but not found: ${missing}" [[ $missing ]] && exit 15 return 0 } #------------------------------------------------------------------------------ :<<'__comments__' Name: convert_font Synopsis: Create Postscript *afm, *.pfa and *.pfb files from TrueType $sourceFile; update font.map file in $targetPath. Arguments: --- Requires: fc-query, file, grep, mkafmmap, ttf2pt1 Returns: 0 on success; $errFuncName, $exitMessage and exit 15, 20, 23, 35 or 255 on error. Calls: --- __comments__ convert_font() { errFuncName="$FUNCNAME" [[ $showTui ]] && return 0 type -p fc-query file grep mkafmmap ttf2pt1 &>/dev/null || exit 15 local name output [[ -t 1 ]] && printf "\ec\n\n%s %s\n" "${0##*/}: Attempting to convert" \ "a TrueType font to Postscript Type 1 format" [[ $targetPath ]] || { [[ -t 1 ]] && printf "%s\n" "No AFMPath target directory was specified" } [[ $targetPath ]] || { targetPath=${psDirs[0]} [[ -t 1 ]] && printf "%s %s %s\n" "Attempting to set the target" \ "directory for the Postscript font files to" \ "the default AFMPath directory '${targetPath}'" } exitMessage="The target path '${targetPath}' is not an AFMPath directory" exitMessage="${exitMessage} or does not exist" [[ -d $targetPath && ${psDirs[@]} =~ $targetPath ]] || exit 23 exitMessage="User '${USER}' cannot write to '${targetPath}'" [[ -w $targetPath ]] || exit 20 [[ -t 1 ]] && printf "%s %s\n" "Attempting to extract font data from" \ "'${sourceFile}'" exitMessage="The file '${sourceFile}' is not a valid TrueType font file" # quote "$sourceFile" arg to 'file' in case it contains spaces [[ -f $sourceFile ]] && file "${sourceFile}" | grep -ioq 'truetype' || \ exit 35 name=$(fc-query --format="%{postscriptname}" "${sourceFile}") [[ ${psNames[@]} =~ $name ]] && { [[ -t 1 ]] && printf "%s %s\n" "The TrueType font '$name' is already" \ "enabled for enscript" return 0 } # suppress stderr output unless script runs in a terminal output="&>/dev/null" [[ -t 1 ]] && unset output exitMessage="ttf2pt1: failed to create '${name}.pfa' and '${name}.afm' in" exitMessage="${exitMessage} '${targetPath}'" # do not quote $output arg to ttf2pt1 ttf2pt1 --encode "${sourceFile}" "${targetPath}"/"${name}" ${output} || \ exit 255 exitMessage="ttf2pt1: failed to convert Unicode to Latin-1/ASCII font" exitMessage="${exitMessage} encoding (required for GNU enscript)" ttf2pt1 --language latin1 "${sourceFile}" "${targetPath}"/"${name}" \ ${output} || exit 255 exitMessage="ttf2pt1: failed to create '${targetPath}/${name}.pfb'" ttf2pt1 --pfb "${sourceFile}" "${targetPath}"/"${name}" ${output} || exit 255 exitMessage="mkafmmap: failed to update '${targetPath}/font.map'" mkafmmap --output-file="${targetPath}/font.map" \ "${targetPath}"/*.afm ${output} || exit 255 [[ -t 1 ]] && printf "\n%s\n" "Success! All done..." return 0 } #------------------------------------------------------------------------------ :<<'__comments__' Name: exit_message Synopsis: If attached to a tty and $? is non-zero, display a message; exit with value $?; the first statement to appear in main() must be: trap exit_message EXIT Arguments: --- Requires: --- Returns: exit $? Calls: --- __comments__ exit_message() { local errNum="$?" local errTxt="ERROR_${errNum}" local errMsg="Error ${errNum}: No description available" [[ ${!errTxt} ]] && errMsg="Error ${errNum}: ${!errTxt}" [[ ${errFuncName} ]] && errMsg="${errFuncName}: ${errMsg}" errMsg="${0##*/}: ${errMsg}" [[ -t 1 && $errNum -ne 0 ]] && { [[ $exitMessage ]] && printf "%b\n" "${exitMessage}" printf "%s\n" "${errMsg}" } } #------------------------------------------------------------------------------ :<<'__comments__' Name: find_fonts Synopsis: Populate ${psDirs[@]} with GNU enscript 'AFMPath' directory paths; populate ${psNames[@]} with the postscript font names found by fc-query for any files in 'AFMPath' directories; populate ${ttFiles[@]} with the postscript font name and full path to each TrueType font file found by fc-list. Arguments: --- Requires: fc-list, fc-query, grep, sort, tr Returns: ${psDirs[@]}, ${psNames[@]}, ${ttFiles[@]} and 0 on success; $errFuncName and exit 15 on error. Calls: --- __comments__ find_fonts() { errFuncName="$FUNCNAME" type -p fc-list fc-query grep sort tr &>/dev/null || exit 15 local afmPath dir file files=() # get the list of AFMPath directories to search; first check the envar [[ $ENSCRIPT_AFMPATH ]] && { afmPath="${ENSCRIPT_AFMPATH//:/ }" for dir in ${afmPath}; do psDirs=(${psDirs[@]} ${dir}) done } # then check the enscript config files in ascending order files=("${HOME}/.enscriptrc" "/etc/enscriptsite.cfg" "/etc/enscript.cfg") for file in ${files[@]}; do [[ $psDirs ]] || { afmPath="$(grep -s 'AFMPath:' "${file}")" afmPath="${afmPath#*:}" afmPath="${afmPath//:/ }" for dir in ${afmPath}; do psDirs=(${psDirs[@]} ${dir}) done } done # psNames[@] lists postscript names associated with font files found in #+ directories listed in psDirs[@] for dir in ${psDirs[@]}; do [[ -d $dir ]] && \ psNames=(${psNames[@]} $(fc-query --format="%{postscriptname}\n" \ ${dir}/* 2>/dev/null | sort -bdfu)) done # each element of ttFiles[@] contains: a postscript font name, a pipe '|' #+ delimiter and the path to its corresponding TrueType font file on this host: #+ 'PostscriptFontName|/full/path/to/font/file.ttf' #+ the postscript font name is the one required by: 'enscript -f|--font ' #+ We must replace spaces ' ' with carets '^' in font names and filepaths in #+ order to correctly load and access the ttFiles[@] array elements; the spaces #+ must be restored in the select_tt_font() function ttFiles=($(fc-list --format="%{postscriptname}|%{file}\n" | tr ' ' '^' \ | grep -Ei '*.ttf' | sort -bdfu)) return 0 } #------------------------------------------------------------------------------ :<<'__comments__' Name: list_ps_fonts Synopsis: If called by show_tui() display each element of ${psNames[@]}. Arguments: --- Requires: stty Returns: 0 on success; exit 0 on quit; $errFuncName and exit 15 on error. Calls: --- __comments__ list_ps_fonts() { errFuncName="$FUNCNAME" [[ -t 1 && $showTui ]] || return 0 type -p stty &>/dev/null || exit 15 local a b c choice count dashes i items margin pad page pages rows ttySize=() printf -v dashes "%79s\n" dashes="${dashes// /-}" # BEGIN loop while true; do ttySize=($(stty size)) # display is 80 chars wide margin=$((${ttySize[1]}-80)) [[ $margin -lt 2 ]] && unset margin pad # $pad value centers each 80-character line [[ $margin ]] && printf -v pad "%$((${margin}/2))s" printf "\ec\n\n%s %s\n" "${pad}${0##*/}: Postscript font names found" \ "in the AFMPath directories" printf "%s" "${pad}${dashes}" [[ $psNames ]] && { # each page has ${ttySize[0]} rows (less 12 lines for headers and footers) and #+ displays $items font names in 3 left-justified columns (each of 25 chars) #+ with 2 spaces between columns for a total display width of 79 chars rows=$((${ttySize[0]}-12)) items=$((${rows}*3)) pages=$((${#psNames[@]}/${items})) # full pages [[ $((${#psNames[@]}%${items})) -gt 0 ]] && ((++pages)) # remainder } [[ $pages ]] || printf "\n%s\n" "${pad}None found" [[ $pages ]] && { [[ $page ]] || page="1" printf "%s%79s\n\n" "${pad}" "Page ${page} of ${pages} page(s)" # display font names in 3 columns count=$((${page}-1)) count=$((${count}*${items})) for ((a=${count}; a<$((${count}+${rows})); a++)); do b=$((${rows}+${a})) c=$((${rows}*2)) c=$((${c}+${a})) # truncate font names to fit in 25 chars for i in $a $b $c; do [[ ${#psNames[$i]} -gt 25 ]] && psNames[$i]="${psNames[$i]:0:22}..." done # do not display empty elements [[ ${psNames[$a]} ]] && printf "%s%-25s" "${pad}" "${psNames[$a]}" [[ ${psNames[$b]} ]] && printf "%2s%-25s" "" "${psNames[$b]}" [[ ${psNames[$c]} ]] && printf "%2s%-25s" "" "${psNames[$c]}" [[ ${psNames[$a]} ]] && printf "\n" done } printf "\n%s" "${pad}Type M and press Enter to return to the main menu" [[ $pages && $page -lt $pages ]] && \ printf "\n%s" "${pad}Type N and press Enter to view the next screen" [[ $pages && $page -gt 1 ]] && \ printf "\n%s" \ "${pad}Type P and press Enter to return to the previous screen" printf "\n%s\n%s" "${pad}Type Q and press Enter to quit" "${pad}" read -p'Choice ==> ' choice case "$choice" in m|M) break 1 ;; n|N) [[ $pages && $page -lt $pages ]] && ((++page)) ;; p|P) [[ $pages && $page -gt 1 ]] && ((--page)) ;; q|Q) printf "\ec" && exit 0 ;; *) choice="" ;; esac # END loop done return 0 } #------------------------------------------------------------------------------ :<<'__comments__' Name: parse_command_line Synopsis: Parse the command line arguments. Arguments: [] [-s|--select|--show] Requires: --- Returns: $showTui, $sourceFile, $targetPath and 0 in all cases. Calls: --- __comments__ parse_command_line() { errFuncName="$FUNCNAME" local arg args=("${argList[@]}") next while [[ $arg -lt ${#args[@]} ]]; do case "${args[$arg]}" in -s|--select|--show) showTui="true" ((++arg)) ;; -*) unset showTui sourceFile return 0 ;; *) ((++arg)) ;; esac done [[ $showTui ]] || { # if passed as args, test is a file and is a dir [[ -f ${args[0]} ]] && sourceFile="${args[0]}" [[ -d ${args[1]} ]] && targetPath="${args[1]}" } return 0 } #------------------------------------------------------------------------------ :<<'__comments__' Name: select_afmpath Synopsis: Display each element of ${psDirs[@]}; indicate if the element is a valid directory and if the directory is writable by the script user; optionally set a user-selected element as $targetPath. Arguments: --- Requires: stty Returns: 0 on success; exit 0 on quit; $errFuncName and exit 15 on error. Calls: --- __comments__ select_afmpath() { errFuncName="$FUNCNAME" [[ -t 1 && $showTui ]] || return 0 type -p stty &>/dev/null || exit 15 local choice count dashes dir margin num pad state ttySize=() writable=() # BEGIN loop while true; do # $pad value centers each 80-character line ttySize=($(stty size)) margin=$((${ttySize[1]}-80)) [[ $margin -lt 2 ]] && unset margin pad [[ $margin ]] && printf -v pad "%$((${margin}/2))s" printf "\ec\n\n%s %s\n" "${pad}${0##*/}:" \ "GNU enscript searches these AFMPath directories for usable fonts" [[ $psDirs ]] || { printf -v dashes "%79s" dashes="${dashes// /-}" printf "%s%s\n" "${pad}" "${dashes}" printf "\n%s" "${pad}There are none" } [[ $psDirs ]] && { count=0 printf -v dashes "%60s" dashes="${dashes// /-}" printf "\n%s%2s%2s%-60s%2s%-14s" "${pad}" "ID" "" "Directory" "" "Status" printf "\n%s%2s%2s%60s%2s%14s" "${pad}" "--" "" "${dashes}" "" \ "--------------" for dir in ${psDirs[@]}; do ((++count)) num="" state="Does not exist" [[ -d $dir ]] && state="Read only" [[ -w $dir ]] && { num="${count}" state="Writable" writable=(${writable[@]} ${num}=${dir}) } [[ ${#dir} -gt 60 ]] && dir="...${dir:(-57)}" printf "\n%s%2s%2s%-60s%2s%-14s" "${pad}" "${num}" "" "${dir}" "" \ "${state}" [[ $count -eq 9 ]] && break 1 done } printf "\n" [[ $count -eq 9 && ${#psDirs[@]} -gt 9 ]] && { [[ $((${#psDirs[@]}-9)) -eq 1 ]] && printf "\n%s" \ "${pad}There is 1 more directory not shown" || printf "\n%s" \ "${pad}There are $((${#psDirs[@]}-9)) more directories not shown" } [[ $writable ]] || printf "\n%s %s\n" \ "${pad}User '${USER}' does not have write permission for any" \ "AFMPath directory" [[ $writable ]] && printf "\n%s %s" "${pad}Type an ID number and" \ "press Enter to select an AFMPath target directory" printf "\n%s\n%s\n%s" \ "${pad}Type M and press Enter to return to the main menu" \ "${pad}Type Q and press Enter to quit" "${pad}" read -p'Choice ==> ' choice case "$choice" in [0-9]*) [[ $writable ]] && { targetPath="" for dir in ${writable[@]}; do [[ ${dir%=*} == $choice ]] && targetPath="${dir#*=}" done } [[ $targetPath ]] && break 1 printf "\ec\n\n%s %s\n" "${pad}${0##*/}: GNU enscript" \ "searches these AFMPath directories for usable fonts" printf -v dashes "%79s" dashes="${dashes// /-}" printf "%s%s\n" "${pad}" "${dashes}" printf "\n%s %s" "${pad}ID number '${choice}' is not" \ "a valid choice. Wait... " sleep 3s ;; m|M) break 1 ;; q|Q) printf "\ec" && exit 0 ;; *) choice="" ;; esac # END loop done return 0 } #------------------------------------------------------------------------------ :<<'__comments__' Name: select_tt_font Synopsis: Display each element of ${ttFiles[@]}; optionally pass a user-selected element to convert_font() as $sourceFile. Arguments: --- Requires: sleep, stty Returns: $sourceFile and 0 on success; exit 0 on quit; $errFuncName and exit 15 on error. Calls: --- __comments__ select_tt_font() { errFuncName="$FUNCNAME" [[ -t 1 && $showTui ]] || return 0 type -p sleep stty &>/dev/null || exit 15 local choice count dashes each file id margin name pad page pages rows local ttySize=() printf -v dashes "%79s\n" dashes="${dashes// /-}" # BEGIN loop while true; do ttySize=($(stty size)) # display is 80 chars wide margin=$((${ttySize[1]}-80)) [[ $margin -lt 2 ]] && unset margin pad # $pad value centers each 80-character line [[ $margin ]] && printf -v pad "%$((${margin}/2))s" printf "\ec\n\n%s %s\n" "${pad}${0##*/}: TrueType fonts installed" \ "but not enabled for GNU enscript" [[ ${#ttFiles[@]} -gt 0 ]] && { # each page displays ${ttySize[0]} rows (less 15 lines for headers and #+ footers) of elements from ${ttFiles[@]} rows=$((${ttySize[0]}-15)) pages=$((${#ttFiles[@]}/${rows})) # full pages [[ $((${#ttFiles[@]}%${rows})) -gt 0 ]] && ((++pages)) # remainder } [[ $pages ]] || printf "%s\n%s\n" "${pad}${dashes}" "${pad}None found" [[ $pages ]] && { [[ $page ]] || page="1" printf "%s%79s\n\n" "${pad}" "Page ${page} of ${pages} page(s)" printf "%s%4s%2s%25s%2s%46s\n" "${pad}" "ID" "" "Font name" "" \ "Font file" printf "%s%2s%s%2s%s\n" "${pad}----" "" "-------------------------" "" \ "----------------------------------------------" count=$((${page}-1)) count=$((${count}*${rows})) for ((each=${count}; each<$((${count}+${rows})); each++)); do id="${each}" name="${ttFiles[$each]%|*}" [[ ${#name} -gt 25 ]] && name="${name:0:22}..." [[ $name ]] || id="" file="${ttFiles[$each]#*|}" file="${file%%\.*}" [[ ${#file} -gt 46 ]] && file="...${file:(-43)}" # must restore spaces escaped to carets in ${ttFiles[@]} [[ $id ]] && printf "%s%4s%2s%-25s%2s%-46s\n" "${pad}" "$id" "" \ "${name//^/ }" "" "${file//^/ }" done } printf "\n%s\n%s" \ "${pad}Type an ID number and press Enter to select a font" \ "${pad}Type M and press Enter to return to the main menu" [[ $pages && $page -lt $pages ]] && \ printf "\n%s" "${pad}Type N and press Enter to view the next screen" [[ $pages && $page -gt 1 ]] && \ printf "\n%s" \ "${pad}Type P and press Enter to return to the previous screen" printf "\n%s\n%s" "${pad}Type Q and press Enter to quit" "${pad}" read -p'Choice ==> ' choice case "$choice" in [0-9]*) sourceFile="" choice="${choice//[!0-9]/}" [[ ${ttFiles[$choice]} ]] && { sourceFile="${ttFiles[$choice]#*|}" # restore spaces replaced by carets in ${ttFiles[@]} by find_fonts() sourceFile="${sourceFile//^/ }" break 1 } printf "\ec\n\n%s %s\n%s\n\n%s" "${pad}${0##*/}: TrueType fonts" \ "installed but not enabled for GNU enscript" "${pad}${dashes}" \ "${pad}ID number '${choice}' is not a valid choice. Wait... " sleep 3s ;; m|M) break 1 ;; n|N) [[ $pages && $page -lt $pages ]] && ((++page)) ;; p|P) [[ $pages && $page -gt 1 ]] && ((--page)) ;; q|Q) printf "\ec" && exit 0 ;; *) choice="" ;; esac # END loop done return 0 } #------------------------------------------------------------------------------ :<<'__comments__' Name: show_tui Synopsis: Display menu if $showTui is set; call functions that display font names and filepaths. Arguments: --- Requires: sleep, stty Returns: 0 on success; exit 0 on user quit; $errFuncName and exit 15 or 16 on error. Calls: list_ps_fonts, select_afmpath, select_tt_font __comments__ show_tui() { errFuncName="$FUNCNAME" [[ -t 1 && $showTui ]] || return 0 type -p fc-query sleep stty &>/dev/null || exit 15 declare -F select_afmpath list_ps_fonts select_tt_font &>/dev/null || exit 16 local choice dashes dir font margin pad ttySize=() printf -v dashes "%79s\n" dashes="${dashes// /-}" # BEGIN loop -- user select while true; do ttySize=($(stty size)) # BEGIN loop -- resize display while [[ ${ttySize[0]} -lt 24 || ${ttySize[1]} -lt 80 ]]; do printf "\n\n%s\n%s" \ "Resize your terminal window to at least 24 lines by 80 columns" \ "Type Q to quit, any other key to continue" read -n1 -p' ==> ' choice printf "\n" case "$choice" in q|Q) printf "\ec" && exit 0 ;; *) choice="" ;; esac printf "\ec" sleep 1s ttySize=($(stty size)) # END loop -- resize display done # $pad value centers each 80-character line ttySize=($(stty size)) margin=$((${ttySize[1]}-80)) [[ $margin -lt 2 ]] && unset margin pad [[ $margin ]] && printf -v pad "%$((${margin}/2))s" printf "\ec\n\n%s %s\n" "${pad}${0##*/}: Convert a TrueType font" \ "to Postscript Type 1 for GNU enscript" printf "%s" "${pad}${dashes}" printf "\n%s\n%s %s\n%s %s\n" \ "${pad}[1] Show Postscript fonts found in the AFMPath directories" \ "${pad}[2] Select an installed TrueType font to convert to Postscript" \ "format" \ "${pad}[3] Select an AFMPath directory for the converted Postscript" \ "font files" font="[none]" [[ $sourceFile ]] && \ font=$(fc-query --format="%{postscriptname}" "${sourceFile}") printf "\n%s" "${pad}Selected TrueType font name: ${font}" dir="[none]" [[ $targetPath ]] && dir="${targetPath}" [[ ${#dir} -gt 50 ]] && dir="...${dir:(-47)}" printf "\n%s\n" "${pad} Selected AFMPath directory: ${dir}" printf "\n%s" "${pad}Type a number and press Enter to show or select" [[ $sourceFile && $targetPath ]] && printf "\n%s" \ "${pad}Type C and press Enter to convert and enable the selected font" printf "\n%s\n%s" "${pad}Type Q and press Enter to quit" "${pad}" read -p'Choice ==> ' choice case "$choice" in c|C) [[ $sourceFile && $targetPath ]] && break 1 || choice="" ;; q|Q) printf "\ec" && exit 0 ;; 1) list_ps_fonts ;; 2) select_tt_font ;; 3) select_afmpath ;; *) choice="" ;; esac # END loop -- user select done showTui="" return 0 } #------------------------------------------------------------------------------ :<<'__comments__' Name: show_usage Synopsis: Exit 0 if neither $sourceFile nor $showTui is set; display script usage before exiting if attached to a tty. Arguments: --- Requires: --- Returns: 0 if $showTui or $sourceFile is set; else exit 0. Calls: --- __comments__ show_usage() { [[ $sourceFile || $showTui ]] && return 0 [[ -t 1 ]] || exit 0 printf "%b" " ------------------------------------------------------------------------------- Usage: ${0##*/} [] [-s|--select|--show] Convert a TrueType to Postscript *.afm, *.pfa and *.pfb files in and update the font.map file in that directory. If is omitted or is not one of enscript's 'AFMPath' directories then the first directory found in 'AFMPath' where the user '${USER}' has write permission will be used. The enscript configuration files '~/.enscriptrc', '/etc/ensriptsite.cfg' and '/etc/enscript.cfg' (if they exist and in that order) are checked for the 'AFMPath' directive. To override those file checks export ENSCRIPT_AFMPATH='/first/path:/second/path:/third/path' into the environment. Flags: -s, --select, --show Show enscript's 'AFMPath' directories; optionally allow the user to select a valid . Show the font names available to enscript in the 'AFMPath' directories. Show TrueType fonts located in the system font directories; optionally allow the user to select a to convert to Postscript format in . Unrecognized flags cause this message to be displayed. ------------------------------------------------------------------------------- " exit 0 } #------------------------------------------------------------------------------ # main #------------------------------------------------------------------------------ main() { trap exit_message EXIT argList=("$@") errFuncName="$FUNCNAME" declare -F check_bash check_required convert_font exit_message find_fonts \ list_ps_fonts parse_command_line select_afmpath select_tt_font show_tui \ show_usage &>/dev/null || exit 16 check_bash check_required parse_command_line show_usage find_fonts show_tui convert_font exit 0 } #------------------------------------------------------------------------------ # run program #------------------------------------------------------------------------------ main "$@"