#!/bin/ksh93

typeset -r FPROG=${.sh.file}
typeset -r PROG=${FPROG##*/}
SDIR=${FPROG%/*}
 
VERSION='v1.7 (2013/07/15)'	# tested with TeXLive2013/Cygwin
 
function showUsage {
	[[ -z $1 ]] && X='--man' || X='-?'
	getopts -a ${PROG} "${ print ${USAGE} ; }" OPT $X
}

FNTFAM='5bb'
FNTNAME='Softmaker Barbedor'
FNTCMD='FFBarbedor'
FNTSCALEPREFIX='Sbb'
PACKAGENAME='barbedor'
PACKAGEDATE='2010/03/05'
PACKAGEVERSION='v1.0'
MAPFILENAME=
LOCALTEXMF="${ kpsewhich --expand-var='$TEXMFLOCAL' ; }"
FNTSUBDIR='MyFonts/Barbedor'
FNTENC='8a'	# (AdobeStandardEncoding)
OTF_FEATURES='-fkern -fliga'
INSTALLAS='rmdefault'
[[ ${ uname -s; } == 'SunOS' ]] && GREP='/usr/xpg4/bin/grep' || GREP='grep'

function uninstall {
	[[ -z ${FNTSUBDIR} ]] && \
		print -u2 'The font subdirectory to use needs to be set.' \
			'Use option -s ...' && exit 1
	[[ -z ${LOCALTEXMF} ]] && \
		print -u2 'The root directory of your local texmf tree is not set.' \
			'Use option -l ...' && exit 2

	typeset D A X
	for X in fonts/{tfm,vf,pl,vpl,type1,{enc,map}/dvips} tex/latex ; do
		[[ -d ${LOCALTEXMF}/$X/${FNTSUBDIR} ]] && D+=( "$X" ) A+="$X\n"
	done

	[[ -z $D ]] && print -u2 'Nothing to do - exiting.' && return 0

	print "$A\n"
	X='n'
	read -v X?'
Do you want to delete these directories (y/n): '
	[[ $X == 'y' || $X == 'Y' ]] || return 1
    rm -rf "${D[@]}"
}

function renameFont {
	typeset AFM="$1" SSCRIPT=$2 WHAT="$3" CUT=$4 A
	A=${ ${GREP} -q -E '(FontName|FullName)' "${AFM}" ; }
	[[ $A =~ ${WHAT} ]] || return
	A=( ${ ${GREP} -F 'ItalicAngle' "${AFM}"; } )
	[[ -n ${A[1]} && ${A[1]:0:1} != '0' ]] && CUT+='i'
	A="${FNTFAM}${CUT}${FNTENC}"
	mv "${AFM}" Rename/${A}.afm
	mv "${AFM%afm}pfb" Rename/${A}.pfb
	print "s/<${A}/<${AFM%.afm}/" >>${SSCRIPT}
}

function renameFonts {
	typeset SEDMAP=$1 X=${ ls *.pfb 2>/dev/null; } CUT F
	[[ -z $X ]] && print 'No font(s) to rename!' && return 1

	mkdir -p Rename
	# rename small caps font(s)
	for X in ~(N)*.afm ; do
		[[ -z $X ]] && continue
		${GREP} -q -E '(Smc|Caps|SCOsF)' "$X" || continue
		if ${GREP} -q -E '(XLight|Xlight|extra light)' "$X" ; then
			CUT='jc'
		elif ${GREP} -q -F 'Light' "$X" ; then
			CUT='lc'
		elif ${GREP} -q -E '(Semibold|SemiBold)' "$X" ; then
			CUT='sc'
		elif ${GREP} -q -E '(Demi|Demibold|DemiBold)' "$X" ; then
			CUT='dc'
		elif ${GREP} -q -E '(Extrabold|ExtraBold)' "$X" ; then
			CUT='xc'
		elif ${GREP} -q -E '(Heavy|Ultrabold|UltraBold)' "$X" ; then
			CUT='uc'
		elif ${GREP} -q -E '(Bold|bold)' "$X" ; then
			CUT="bc"
		else
			CUT='rc'
		fi
		F="${FNTFAM}${CUT}${FNTENC}"
		mv "$X" Rename/${F}.afm
		mv "${X%afm}pfb" Rename/${F}.pfb
		print "s/<${F}/<${X%.afm}/" >>${SEDMAP}
	done
	# rename the extra light font(s)
	for X in ~(N)*.afm ; do
		[[ -n $X ]] && renameFont "$X" ${SEDMAP} '(XLight|Xlight|extra light)' j
	done
	# rename the light font(s)
	for X in ~(N)*.afm ; do
		[[ -n $X ]] && renameFont "$X" ${SEDMAP} 'Light' l
	done
	# rename the semi(bold) font
	for X in ~(N)*.afm ; do
		[[ -n $X ]] && renameFont "$X" ${SEDMAP} '(Semibold|SemiBold)' s
	done
	# rename the demi(bold) font
	for X in ~(N)*.afm ; do
		[[ -n $X ]] && renameFont "$X" ${SEDMAP} '(Demi|Demibold|DemiBold)' d
	done
	# rename the extra bold font
	for X in ~(N)*.afm ; do
		[[ -n $X ]] && renameFont "$X" ${SEDMAP} '(Extrabold|ExtraBold)' x
	done
	# rename the ultra bold/heavy font
	for X in ~(N)*.afm ; do
		[[ -n $X ]] && renameFont "$X" ${SEDMAP} '(Heavy|Ultrabold|UltraBold)' u
	done
	# rename the bold font
	for X in ~(N)*.afm ; do
		[[ -n $X ]] && renameFont "$X" ${SEDMAP} '(Bold|bold)' b
	done
	# rename the regular font
	for X in ~(N)*.afm ; do
		[[ -n $X ]] && renameFont "$X" ${SEDMAP} '(Regular|Medium|Book)' r
	done
	mv Rename/* .
	rmdir Rename
	ls -l *.pfb *.afm
	X='y'
	read -v X?'
Please check the font name(s). Continue (y/n): '
	[[ $X == 'n' || $X = 'N' ]] && return 1 || return 0
}

# needs to be global
unset TDIR ; TDIR=

function cleanup {
	cd
	[[ -n ${TDIR} && -d ${TDIR} ]] && rm -rf ${TDIR}
}

# Move all relevant font files to ${TMPDIR}/ and generate type1 files
# if needed. This way we do not need to backup/restore anything from $CWD .
function copyAndConvert {
	typeset STEP=$1 DST=$2 T A X
	if [[ ${FNTTYPE} == 'ttf' ]]; then
		T=${ whence ttf2pt1 ; }
		if [[ -z $T ]]; then
			print -u2 'ttf2pt1 is required for TrueType fonts - exiting'
			return 1
		fi
		print "\n\n${STEP}) Converting TTF font(s) to Postscript Type1 ...\n\n"
		for X in ~(N)*.TTF; do
			[[ -n $X ]] && cp -L "$X" "${DST}/${X%TTF}ttf"
		done
		cp -L *.ttf "${DST}/" 2>/dev/null
		cd ${DST} || exit 2
		for X in ~(N)*.ttf; do
			[[ -n $X ]] && $T -a -b -l adobestd "$X"
		done
	elif [[ ${FNTTYPE} == 'otf' ]]; then
		T=${ whence otftotfm ; }
		A=${ whence pf2afm ; }
		if [[ -z $T || -z $A ]]; then
			print -u2 'otftotfm and pf2afm are required for OpenType fonts' \
				'- exiting.'
			return 1
		fi
		print "\n\n${STEP}) Converting OTF font(s) to Postscript Type1 ...\n\n"
		for X in ~(N)*.OTF; do
			[[ -n $X ]] && cp -L "$X" "${DST}/${X%OTF}otf"
		done
		cp -L *.ttf "${DST}/" 2>/dev/null
		cd ${DST} || exit 2
		for X in ~(N)*.otf; do
			[[ -n $X ]] && $T ${OTF_FEATURES} -e - "$X" 555
		done
		for X in ~(N)*.pfb; do
			[[ -n $X ]] && $A "$X"
		done
	else
		print "\n\n${STEP}) Looking for Postscript Type1 fonts ...\n\n"
		for X in ~(N)*.AFM; do
			[[ -n $X ]] && cp -L "$X" "${DST}/${X%AFM}afm" 2>/dev/null
		done
		for X in ~(N)*.PFB; do
			[[ -n $X ]] && cp -L "$X" "${DST}/${X%PFB}pfb" 2>/dev/null
		done
		cp -L *.afm *.pfb "${DST}/" 2>/dev/null
		cd ${DST} || exit 2
	fi
	X=${ ls *.afm 2>/dev/null; }
	[[ -n $X ]] && return 0
	print -u2 'Nothing to do - exiting.'
	return 1
}

function doMain {
	(( LOG )) && rm -f LOG
	[[ -z ${MAPFILENAME} ]] && MAPFILENAME="${FNTFAM}"

	if (( UNINSTALL )) ; then
		uninstall
		return $?
	fi

	typeset X UMAP SED_SCRIPT
	integer STEP=0

	TDIR=${ mktemp --directory fontinst.XXXXXX ; }
	[[ -z ${TDIR} ]] && return 1
	SED_SCRIPT=${TDIR}/map.sed

	(( STEP++ ))
	copyAndConvert ${STEP} ${TDIR} || return $?

	if (( ! OFN )); then
		(( STEP++ ))
		print "\n\n${STEP}) Renaming fonts ...\n\n"
		renameFonts ${SED_SCRIPT} || return $?
	fi
 
	((STEP++))
	print "\n\n${STEP}) Creating metrics and virtual fonts ...\n\n"
	cat >${FNTFAM}-drv.tex <<EOF
\input fontinst.sty
\needsfontinstversion{1.926}
\recordtransforms{${FNTFAM}-rec.tex}
\latinfamily{${FNTFAM}}{}
\endrecordtransforms
\bye
EOF
	if (( LOG )); then
		tex ${FNTFAM}-drv.tex >>LOG 2>&1
	else
		tex ${FNTFAM}-drv.tex
	fi
 
	((STEP++))
	print "\n\n${STEP}) Compiling metrics and virtual fonts ...\n\n"
	for X in *.pl; do  
		if (( LOG )); then
			pltotf "$X" "${X%pl}tfm" >>LOG 2>&1
		else
			pltotf "$X" "${X%pl}tfm"
		fi
	done
	for X in *.vpl; do  
		if (( LOG )); then
			vptovf "$X" "${X%vpl}vf" "${X%vpl}tfm" >>LOG 2>&1
		else
			vptovf "$X" "${X%vpl}vf" "${X%vpl}tfm"
		fi
	done

	((STEP++))
	print "\n\n${STEP}) Creating the map file ...\n\n"
	cat >${FNTFAM}-map.tex <<EOF
\input finstmsc.sty
\resetstr{PSfontsuffix}{.pfb}
\adddriver{dvips}{${FNTFAM}.map}
\input ${FNTFAM}-rec.tex
\donedrivers
\bye
EOF
	if (( LOG )); then
		tex "${FNTFAM}-map.tex" >>LOG 2>&1
	else
		tex "${FNTFAM}-map.tex"
	fi
	if (( OFN )); then
		sed -f ${SED_SCRIPT} "${FNTFAM}.map" >"${MAPFILENAME}.map"
		rm "${FNTFAM}.map"
		UMAP="${MAPFILENAME}"
	else
		UMAP="${FNTFAM}"
	fi

	((STEP++))
	print "\n\n${STEP}) Creating the style file ..."
	cat >${PACKAGENAME}.sty <<EOF
\NeedsTeXFormat{LaTeX2e}%
\ProvidesPackage{$PACKAGENAME}[$PACKAGEDATE $PACKAGEVERSION $FNTNAME]%
\RequirePackage{textcomp}%
\RequirePackage{xkeyval}%
\define@key{${PACKAGENAME}.sty}{scaled}[1.0]%
{%
  \def\\${FNTSCALEPREFIX}@scale{#1}%
}%
\define@key{${PACKAGENAME}.sty}{leading}[1.0]%
{%
  \linespread{#1}%
}%
\ExecuteOptionsX{scaled}%
\ProcessOptionsX\relax%
\renewcommand*{\\${INSTALLAS}}{$FNTFAM}%
\newcommand\\${FNTCMD}{\fontfamily{$FNTFAM}\fontseries{m}\fontshape{n}\selectfont}%
\endinput%
EOF
 
	((STEP++))
	print "\n\n${STEP}) Insert scale factor into the fd files"
	cat >installfont.sed <<EOF
9 i\\
\\n\\\\expandafter\\\\ifx\\\\csname ${FNTSCALEPREFIX}@scale\\\\endcsname\\\\relax\\n  \\\\let\\\\${FNTSCALEPREFIX}@@scale\\\\@empty\\n\\\\else\\n  \\\\edef\\\\${FNTSCALEPREFIX}@@scale{s*[\\\\csname ${FNTSCALEPREFIX}@scale\\\\endcsname]}\\n\\\\fi\\n
s/<-> /<-> \\\\${FNTSCALEPREFIX}@@scale /
EOF

	for X in *.fd; do
		mv "$X" "${X%fd}fdb"
		sed -f installfont.sed "${X%fd}fdb" >"$X"
	done

	((STEP++))
	print "\n\n${STEP}) Installing font(s) and support files ..."
	for X in fonts/{tfm,vf,type1,map/dvips} tex/latex ; do
		[[ ! -d ${LOCALTEXMF}/$X/${FNTSUBDIR} ]] && \
			mkdir -p "${LOCALTEXMF}/$X/${FNTSUBDIR}"
	done
	cp *.tfm "${LOCALTEXMF}/fonts/tfm/${FNTSUBDIR}/"
	cp *.vf "${LOCALTEXMF}/fonts/vf/${FNTSUBDIR}/"
	cp *.pfb "${LOCALTEXMF}/fonts/type1/${FNTSUBDIR}/"
	cp *.map "${LOCALTEXMF}/fonts/map/dvips/${FNTSUBDIR}/"
	cp *.fd "${LOCALTEXMF}/tex/latex/${FNTSUBDIR}/"
	cp *.sty "${LOCALTEXMF}/tex/latex/${FNTSUBDIR}/"

	((STEP++))
	print "\n\n${STEP}) Update FNDB ...\n\n"
	texhash "${LOCALTEXMF}"
 
	((STEP++))
	print "\n\n${STEP}) Adding the map file ...\n\n"
	updmap --enable Map ${UMAP}.map

	print "\n\nThe font(s) should be installed now!"
	return 0
}
 
USAGE='[-?'"${VERSION}"' ]
[-copyright?(C) Josef Kleber 2009-2010,2013]
[-copyright?(C) Jens Elkner 2015 (ksh93 port/cleanup)]
[-license?LPPL]
[+NAME?'"${PROG}"' - install a font family for TexLive usage]
[+DESCRIPTION?'"${PROG}"' installs a TeXLive font family from the current working directory (Postscript Type1, Truetype, Opentype) into a TeXLive texmf tree. The script looks depending on the font type set (see option -t) for TrueType fonts (*.ttf and *.TTF) or OpenType fonts (*.otf and *.OTF) or PostScript Type1 fonts (*.afm, *.AFM, *.pfb and *.PFB) in the current working directory, converts them to Type1 if needed and creates the required TeXLive files. Finally all files get installed into the TexLive tree (see option --localtexmf).]
[+?The style file created with this script offers the following options:]{
	[+scaled?Scale the font to better match with other fonts.] 
	[+leading?For some fonts it might be necessary to increase the leading between lines for a better optical impression, where 1.0 means 100%.]
}
[h:help?Print this help and exit.]
[F:functions?Print a list of all functions available.]
[D:trace]:[fnList?A comma separated list of functions of this script to trace (convinience for troubleshooting).]
[+?]
[f:fontfamily]:[name?The \aname\a of the TeXLive font family, e.g. ptm (Adobe Times). Default: '"${FNTFAM}"']
[n:fontname]:[name?The font \aname\a, e.g. Adobe Times. Default: '"${FNTNAME}"']
[c:fontcommand]:[name?The \aname\a of the command that will switch to the font. Default: '"${FNTCMD}"']
[P:fontscaleprefix]:[prefix?The \aprefix\a of the scale macro, which should be different for each font (no digits allowed). Default: '"${FNTSCALEPREFIX}"']
[t:fonttype]:[type?The font \atype\a to process: pst1|ttf|otf. Default: '"${FNTTYPE}"']
[p:packagename]:[name?The \aname\a of the LaTeX package. Default: '"${PACKAGENAME}"']
[d:packagedate]:[date?The \adate\a of the LaTeX package. Default: '"${PACKAGEDATE}"']
[v:packageversion]:[version?The \aversion\a of the LaTeX package. Default: '"${PACKAGEVERSION}"']
[l:localtexmf]:[dir?The root of your local TeX metafont tree, e.g. ~/texmf/local/. Make sure, that this is not a directory managed by your OS packaging software: it may overwrite/remove changes being made by this script on updates/upgrades! Default: '"${LOCALTEXMF}"']
[m:mapfilename]:[file?The file name of the font map \afile\a. Default: The name of the font family + ".map".]
[O:origfontname?Use the current name of the related font files. Otherwise this script tries to rename them according to the Karl Berry scheme automatically (i.e. STTW[V...]][N]][E]][DD]], e.g. 5bbr8a.pfb).]
[s:fontsubdir]:[dir?The \asubdir\a where the fonts and support files should be installed, e.g. MyFonts/AdobeTimes. On uninstall the directory gets deleted with the given Tex tree. Default: '"${FNTSUBDIR}"']
[e:fontencoding]:[enc?The encoding of the font, e.g. 8a (AdobeStandardEncoding). Default: '"${FNTENC}"']
[o:otffontfeatures]:[features?The Opentype font \afeatures\a to use. Remember to properly quote the argument. Default: "'"${OTF_FEATURES}"'".]
[u:uninstall?Uninstall the given font family. Use --localtexmf ... and --fontsubdir ... to specify, what to remove.]
[R:rmdefault?Install font family as roman (serif) font family (default).]
[S:sfdefault?Install font family as sans serif font family.]
[T:ttdefault?Install font family as typewriter font family.]
[V:version?Print the version information for this script and exit.]
[L:log?Redirect the output of the programs internally used to the file \bLOG\b instead of stdout/stderr.]
[+SEE ALSO]{
	[+?https://bitbucket.org/kleberj/installfont/wiki/Home]
	[+?http://home.mit.bme.hu/~markus/latex/543e.html]
	[+?\bttf2pt1\b(1), \botftotfm\b(1), \bpf2afm\b(1), \btex\b(1), \btexhash\b(1), \bupdmap\b(1).]
}
'
X="${ print ${USAGE} ; }"
integer I=0 LOG=0 OFN=0 UNINSTALL=0
while getopts "${X}" OPT ; do
	case ${OPT} in
		h) showUsage ; exit 0 ;;
		D)	if [[ ${OPTARG} == 'ALL' ]]; then
				typeset -ft ${ typeset +f ; }
			else
				typeset -ft ${OPTARG//,/ }
			fi
			;;
		F)
			typeset +f && exit 0
			;;
		V)	print "This is version ${VERSION} of ${PROG}."; exit 0 ;;
		R)	INSTALLAS="rmdefault" ;;
		S)	INSTALLAS="sfdefault" ;;
		T)	INSTALLAS="ttdefault" ;;
		u)	UNINSTALL=1 ;;
		L)	LOG=1 ;;
		f)	FNTFAM="${OPTARG}" ;;
		n)	FNTNAME="${OPTARG}" ;;
		c)	FNTCMD="${OPTARG}" ;;
		P)	FNTSCALEPREFIX="${OPTARG}" ;;
		t)	FNTTYPE="${OPTARG}" ;;
		p)	PACKAGENAME="${OPTARG}" ;;
		d)	PACKAGEDATE="${OPTARG}" ;;
		v)	PACKAGEVERSION="${OPTARG}" ;;
		m)	MAPFILENAME="${OPTARG}" ;;
		O)	OFN=1 ;;
		l)	LOCALTEXMF="${OPTARG}" ;;
		s)	FNTSUBDIR="${OPTARG}" ;;
		e)	FNTENC="${OPTARG}" ;;
		o)	OTF_FEATURES="${OPTARG}" ;;
		*)	showUsage 1 ; exit 1 ;;
	esac
	(( I++ ))
done
X=$((OPTIND-1))
shift $X && OPTIND=1
unset X

if (( ! I )); then
	print "${PROG}: Could not find command line arguments." \
		"\nUse the '--help' option for explanation."
	X='n'
	read -v X?'Continue with default script variables (y/N): '
	[[ $X == 'n' || $X == 'N' ]] && exit 1
fi
unset I

trap cleanup EXIT
doMain "$@"
