├── src ├── testfonts.h ├── drawbox.h ├── parser.h ├── gentexprintfsymbols.sh ├── error.h ├── utfstringinfo.1 ├── stringutils.h ├── gen_errorflags.sh ├── error.c ├── texprintf.h ├── boxes.h ├── Makefile.am ├── drawchars.h ├── texprintf.3 ├── lexer.h ├── drawbox.c ├── testfonts.c ├── main.c ├── texprintf.c ├── utf2unicode.c ├── mapunicode.h ├── stringutils.c ├── utftex.1 ├── boxes.c └── unicodeblocks.h ├── AUTHORS ├── NEWS ├── autogen.sh ├── testeqs.sh ├── testfonts.sh ├── testsuite.sh ├── Makefile.am ├── .gitignore ├── testerrors.sh ├── ChangeLog ├── configure.ac ├── .github └── workflows │ └── CI.yml ├── test ├── MakeTest.sh ├── README ├── testfonts.txt ├── test.awk ├── testsuite.txt └── testeqs.txt ├── README.md ├── INSTALL └── testtexsymbols.sh /src/testfonts.h: -------------------------------------------------------------------------------- 1 | void TestFonts(); 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Bart Pieters 2 | bartp5@netscape.net 3 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 2018-10-31: Initial Realease of utftex 2 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir -p m4 3 | export AUTOMAKE="automake --foreign -a" 4 | autoreconf -f -i 5 | -------------------------------------------------------------------------------- /src/drawbox.h: -------------------------------------------------------------------------------- 1 | char * DrawBox(box *b); /* puts a formatted equation in a multiline string */ 2 | int PrintBox(box *b); /* dumps an equation to screen */ 3 | void DrawBoxTree(box *b); 4 | -------------------------------------------------------------------------------- /src/parser.h: -------------------------------------------------------------------------------- 1 | #include "drawchars.h" 2 | extern Style STYLE_UNI; 3 | extern Style STYLE_ASC; 4 | extern Style * style; 5 | extern int avoidcombining; 6 | box ParseString(char *string, int LW, char *font); 7 | -------------------------------------------------------------------------------- /testeqs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd test 3 | R=$(awk -f test.awk -v exe="$utftex" testeqs.txt |tail -n 1|awk '{print $2}') 4 | 5 | if [ "$R" -gt 0 ] 6 | then 7 | exit 1 8 | else 9 | exit 0 10 | fi 11 | -------------------------------------------------------------------------------- /testfonts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd test 3 | R=$(awk -f test.awk -v exe="$utftex" testfonts.txt |tail -n 1|awk '{print $2}') 4 | 5 | if [ "$R" -gt 0 ] 6 | then 7 | exit 1 8 | else 9 | exit 0 10 | fi 11 | -------------------------------------------------------------------------------- /testsuite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd test 3 | R=$(awk -f test.awk -v exe="$utftex" testsuite.txt |tail -n 1|awk '{print $2}') 4 | 5 | if [ "$R" -gt 0 ] 6 | then 7 | exit 1 8 | else 9 | exit 0 10 | fi 11 | -------------------------------------------------------------------------------- /src/gentexprintfsymbols.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # generate a list of symbols to export in libtexprintf 3 | # parses texprintf.h to collect all relavant symbols 4 | 5 | # get global variables 6 | grep 'extern' texprintf.h |grep -o -E '[^ ;]+;'|grep -o -E '[^;]+' >texprintfsymbols 7 | grep -o -E '[^ \*\(]+\(' texprintf.h |grep -o -E '^[^\(]+' >>texprintfsymbols 8 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src 2 | 3 | TESTS_ENVIRONMENT = \ 4 | utftex=$(abs_builddir)/src/utftex 5 | export utftex; 6 | TESTS=testsuite.sh testeqs.sh testfonts.sh testerrors.sh testtexsymbols.sh 7 | 8 | EXTRA_DIST = testsuite.sh testeqs.sh testfonts.sh testerrors.sh testtexsymbols.sh test/testsuite.txt test/testeqs.txt test/testfonts.txt test/test.awk test/README 9 | 10 | DISTCLEANFILES = configure~ src/config.h.in~ 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | src/utfstringinfo 2 | src/utftex 3 | src/errorflags.h 4 | src/errormessages.h 5 | 6 | *.o 7 | *.lo 8 | *.la 9 | 10 | test/*.new 11 | *.log 12 | *.trs 13 | 14 | config.* 15 | aclocal.m4 16 | autom4te.cache/ 17 | Makefile 18 | Makefile.in 19 | src/.deps/ 20 | src/.libs/ 21 | compile 22 | configure 23 | configure~ 24 | depcomp 25 | install-sh 26 | libtool 27 | ltmain.sh 28 | missing 29 | m4/ 30 | stamp-h1 31 | test-driver 32 | -------------------------------------------------------------------------------- /testerrors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | separate=`$utftex '\frac{\alp' 2>&1 | tail -n 3` 4 | combined=`$utftex -E '\frac{\alp' 2>&1 | tail -n 2` 5 | 6 | if test "$separate" != $'ERROR: Premature end of string (1x)\nERROR: Unknown command (1x)'; then 7 | echo "FAIL: separate" 8 | exit 1 9 | fi 10 | 11 | if test "$combined" != "ERRORS: Premature end of string (1x); Unknown command (1x)"; then 12 | echo "FAIL: combined" 13 | exit 1 14 | fi 15 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | New in version 1.25 2 | - support for fixedf size big braces (e.g. `\big[`) 3 | - make dummy commands for `\mathop`, `\mathord` (i.e. ignore without throwing error) 4 | - added `\relstack` 5 | 6 | bug fixes 7 | - some memory issues 8 | - allow spaces in things like `\left [` 9 | - fixed some collisions between symbols and keywords. Keywords take presidence over symbols. For example `\\u` is now interpreted as an endline followed by a u and not as `\˘` 10 | 11 | -------------------------------------------------------------------------------- /src/error.h: -------------------------------------------------------------------------------- 1 | /* TODO: 2 | * We do not want the texprintf library to errorexit all the time 3 | * It should rather give up parsing and set some error flags 4 | */ 5 | #include "errorflags.h" /* generated by gen_errorflags.sh, defines error flags */ 6 | 7 | extern char *EMessages[]; 8 | extern int ERRORSTATE; /* signals error occurred, if 0 everything is OK */ 9 | void AddErr(int ERRFLAG); /* call to set an error flag as defined in errorflags.h */ 10 | int QueryErr(int ERRFLAG); 11 | void E_Messages(); 12 | char *E_Messages_str(); 13 | void ResetErrors(); 14 | -------------------------------------------------------------------------------- /src/utfstringinfo.1: -------------------------------------------------------------------------------- 1 | .TH utfstringinfo 1 "05 Jul 2022" 2 | .SH NAME 3 | utfstringinfo \- Analyze a UTF-8 encoded string 4 | .SH SYNOPSIS 5 | .B utfstring [string] 6 | .I 7 | .SH DESCRIPTION 8 | .B utfstringinfo 9 | reads arguments or, if no arguments are provided, stdin and for every single character it finds it shows the UTF-8 character sequence, the unicode code-point 10 | and, if applicable, the utftex command that can be used to generate the symbol. 11 | 12 | .SH AUTHOR 13 | Bart Pieters 14 | .SH LICENSE 15 | GNU GENERAL PUBLIC LICENSE Version 3 16 | .SH VERSION 17 | 1.0 18 | .SH SEE ALSO 19 | .B 20 | -------------------------------------------------------------------------------- /src/stringutils.h: -------------------------------------------------------------------------------- 1 | #define PRINTABLE(C) iswprint((C)) 2 | extern int WCSPACES; 3 | extern int FCSPACES; 4 | 5 | int strspaces(char *str); 6 | char * Unicode2Utf8(int U); 7 | int NumByte(char *p); /* return the number of bytes of the multibyte char pointed to by p */ 8 | int UNumByte(int U); /* return the number of UTF-8 bytes for the unicode code point */ 9 | int IsInSet(char c, const char *set); 10 | int Unicode(char *p, int *N); 11 | int IsCombiningMark(int ch); 12 | char * UnicodeMapper(char *in); 13 | 14 | int MappableSuper(char *super); 15 | char *MapSuperScript(char *super); 16 | int MappableSub(char *sub); 17 | char *MapSubScript(char *sub); 18 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([libtexprintf],[1.28]) 2 | AC_CONFIG_MACRO_DIRS([m4]) 3 | LT_INIT([]) 4 | AC_ENABLE_SHARED 5 | AC_ENABLE_SHARED([]) 6 | LT_INIT() 7 | AM_INIT_AUTOMAKE() 8 | AC_PROG_CC 9 | AC_CHECK_HEADER([getopt.h], 10 | [AC_DEFINE([HAVE_GETOPT_H], 1, [Define to 1 if you have .])], 11 | [AC_MSG_ERROR([utftex needs getopt support to run. Please install it.])]) 12 | AC_MSG_CHECKING([if libtool needs -no-undefined flag to build shared libraries]) 13 | case "$host_os" in 14 | cygwin*|msys*|mingw*) 15 | ## Add in the -no-undefined flag to LDFLAGS for libtool. 16 | AC_MSG_RESULT([yes]) 17 | LDFLAGS="$LDFLAGS -no-undefined" 18 | ;; 19 | *) 20 | ## Don't add in anything. 21 | AC_MSG_RESULT([no]) 22 | ;; 23 | esac 24 | AC_DEFINE([UTFTEXVERSION], ["1.16"], [utftex version string]) 25 | AC_CONFIG_SRCDIR([src/boxes.c]) 26 | AC_CONFIG_HEADERS([src/config.h]) 27 | AC_CHECK_LIB([m],[cos]) 28 | AC_CONFIG_FILES([ 29 | Makefile src/Makefile 30 | ]) 31 | AC_OUTPUT 32 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | - dev 8 | tags: '*' 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | os: [ubuntu-latest, macOS-latest] 14 | runs-on: ${{ matrix.os }} 15 | name: ${{ matrix.os }} 16 | steps: 17 | - if : matrix.os == 'macos-latest' 18 | run: brew install libtool automake autoconf 19 | - name: Checkout repository 20 | uses: actions/checkout@v2 21 | - name: Ensure m4 directory exists 22 | run: mkdir -p m4 23 | - name: Autogen 24 | run: sh autogen.sh && ./configure 25 | - name: Build 26 | run: make -j16 27 | - name: Run tests 28 | run: make check 29 | - name: Run distcheck 30 | run: make distcheck 31 | - name: Clean 32 | run: make maintainer-clean && rm *.gz && test "$(git status --ignored --porcelain | tr -d '\n!!')" = " Makefile.in aclocal.m4 compile config.guess config.sub configure depcomp install-sh ltmain.sh m4/ missing src/Makefile.in src/config.h.in test-driver" 33 | -------------------------------------------------------------------------------- /test/MakeTest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ] 4 | then 5 | echo "Usage:" 6 | echo "MakeTest.sh [optional utftex arguments]" 7 | echo I need a name 8 | exit 1 9 | fi 10 | name="$1" 11 | shift 12 | 13 | if [ -z "$1" ] 14 | then 15 | echo "Usage:" 16 | echo "MakeTest.sh [optional utftex arguments]" 17 | echo I an equation 18 | exit 1 19 | fi 20 | eq="$1" 21 | 22 | shift 23 | opt=(" " "-A" "-S" "-m") 24 | refs=(0 0 0 0) 25 | N=4; 26 | while [ ! -z "$1" ] 27 | do 28 | opt+=("$1") 29 | refs+=(0) 30 | let "N++" 31 | shift 32 | done 33 | 34 | 35 | # test various options 36 | for ((i = 0; i < $N; i++)) 37 | do 38 | arg="${opt[$i]}" 39 | utftex $arg -e "$eq" > "$i.tmp" 40 | done 41 | echo " $name" 42 | echo "$eq" 43 | i=0 44 | for ((i = 0; i < $N; i++)) 45 | do 46 | arg="${opt[$i]}" 47 | if [ "${refs[$i]}" -eq 0 ] 48 | then 49 | let "j=i+1" 50 | while [ "$j" -lt 4 ] 51 | do 52 | if [ "${refs[$j]}" -eq 0 ] 53 | then 54 | if cmp -s $i.tmp $j.tmp 55 | then 56 | arg="$arg | ${opt[$j]}" 57 | refs[$j]=1 58 | fi 59 | fi 60 | let "j=j+1" 61 | done 62 | echo " $arg" 63 | cat $i.tmp 64 | refs[$i]=1 65 | fi 66 | done 67 | echo "" 68 | for ((i = 0; i < $N; i++)) 69 | do 70 | rm "$i.tmp" 71 | done 72 | -------------------------------------------------------------------------------- /src/gen_errorflags.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Generate error flags and messages 4 | # to be used in conjunction with error.c and error.h 5 | # searches the sources for commentlines following the pattern: 6 | # // ERRORFLAG "" 7 | # 8 | # it gen generates a macro by the name FLAGNAME and adds a string to the error string array 9 | # the defines are in errorflags.h" 10 | # the message array in "errormessages.h" 11 | # the errorflags.h should be included in all sources ther throw errors 12 | # the "errormessages.h" is a private incldue for the error.c file so it 13 | # knows what messages to throw out when error occur. 14 | 15 | #sources="boxes.c drawbox.c lexer.c parser.c" 16 | echo "/* File generated by gen_errorflags.sh, do not edit by hand */" > "errorflags.h" 17 | NERR=0; 18 | 19 | # first collect all error flags in one file 20 | for s in $@ 21 | do 22 | echo Collecting error flags from $s 23 | egrep -o '// ERRORFLAG.*' $s >>tmperrflags 24 | done 25 | 26 | # create the error flag defines 27 | awk '{print "#define",$3,NR-1}' tmperrflags>>"errorflags.h" 28 | NERR=$(wc -l tmperrflags | awk '{print $1}') 29 | 30 | 31 | echo "#define NERR $NERR" >>"errorflags.h" 32 | 33 | 34 | echo "/* File generated by gen_errorflags.sh, do not edit by hand */" > "errormessages.h" 35 | echo "char *EMessages[] = {" >>"errormessages.h" 36 | egrep -o '// ERRORFLAG.*' tmperrflags|egrep -o '\".*\"' |awk '{print " "$0","}' >>"errormessages.h" 37 | 38 | echo " NULL" >>"errormessages.h" 39 | echo "};" >>"errormessages.h" 40 | 41 | 42 | rm tmperrflags 43 | -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "error.h" 5 | #include "errormessages.h" /* generated by gen_errorflags.sh, defines error messages for eachg error flag */ 6 | 7 | int ERRORSTATE=0; /* single boolean indicating whether there were any errors */ 8 | char ERRORS[NERR] = {0}; /* zero initialized error flags */ 9 | 10 | void AddErr(int ERRFLAG) 11 | { 12 | ERRORSTATE=1; 13 | if (ERRFLAG>NERR) 14 | fprintf(stderr, "ERROR: In Adderr() Error flag out of range!"); 15 | else 16 | ERRORS[ERRFLAG]++; 17 | } 18 | int QueryErr(int ERRFLAG) 19 | { 20 | if (ERRFLAG>NERR) 21 | fprintf(stderr, "ERROR: In QueryErr() Error flag out of range!"); 22 | if (ERRORS[ERRFLAG]) 23 | return 1; 24 | return 0; 25 | } 26 | 27 | void E_Messages() 28 | { 29 | int i; 30 | for (i=1;i s) *(p - 2) = 0; /* chomp trailing ; */ 50 | return s; 51 | } 52 | 53 | void ResetErrors() 54 | { 55 | int i; 56 | for (i=1;i [optional arguments] 12 | 13 | Some examples: 14 | ./MakeTest.sh Lorenz '\begin{aligned} 15 | \dot{x} & = \sigma(y-x) \\ 16 | \dot{y} & = \rho x - y - xz \\ 17 | \dot{z} & = -\beta z + xy 18 | \end{aligned}' 19 | 20 | returns: 21 | Lorenz 22 | \begin{aligned} 23 | \dot{x} & = \sigma(y-x) \\ 24 | \dot{y} & = \rho x - y - xz \\ 25 | \dot{z} & = -\beta z + xy 26 | \end{aligned} 27 | | -S | -m 28 | ẋ = σ(y-x) 29 | ẏ = ρx - y - xz 30 | ż = -βz + xy 31 | -A 32 | . 33 | x = σ(y-x) 34 | . 35 | y = ρx - y - xz 36 | . 37 | z = -βz + xy 38 | 39 | 40 | You may also add commandline arguments to utftex, e.g. we can add the 41 | option '-F mathnormal': 42 | 43 | ./MakeTest.sh Lorenz '\begin{aligned} 44 | \dot{x} & = \sigma(y-x) \\ 45 | \dot{y} & = \rho x - y - xz \\ 46 | \dot{z} & = -\beta z + xy 47 | \end{aligned}' '-F mathnormal' 48 | 49 | which returns: 50 | 51 | Lorenz 52 | \begin{aligned} 53 | \dot{x} & = \sigma(y-x) \\ 54 | \dot{y} & = \rho x - y - xz \\ 55 | \dot{z} & = -\beta z + xy 56 | \end{aligned} 57 | | -S | -m 58 | ẋ = σ(y-x) 59 | ẏ = ρx - y - xz 60 | ż = -βz + xy 61 | -A 62 | . 63 | x = σ(y-x) 64 | . 65 | y = ρx - y - xz 66 | . 67 | z = -βz + xy 68 | -F mathnormal 69 | 𝑥̇ = σ(𝑦-𝑥) 70 | 𝑦̇ = ρ𝑥 - 𝑦 - 𝑥𝑧 71 | 𝑧̇ = -β𝑧 + 𝑥𝑦 72 | 73 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | AM_CFLAGS = -Wall 3 | 4 | # -- Top-level Makefile.am -- 5 | lib_LTLIBRARIES = libtexprintf.la 6 | libtexprintf_la_SOURCES = boxes.c drawbox.c texprintf.c parser.c lexer.c boxes.h error.c drawbox.h drawchars.h texprintf.h stringutils.h unicodeblocks.h parser.h lexer.h parsedef.h mapunicode.h error.h gen_errorflags.sh texprintfsymbols texprintf.3 7 | nodist_libtexprintf_la_SOURCES = errorflags.h errormessages.h texprintfsymbols 8 | CLEANFILES = errorflags.h errormessages.h texprintfsymbols 9 | libtexprintf_la_LIBADD = libstringutils.la 10 | libtexprintf_la_LDFLAGS = -export-symbols ${srcdir}/texprintfsymbols -version-info 1:0:0 11 | man3_MANS = texprintf.3 12 | include_HEADERS = texprintf.h 13 | 14 | # -- libstringutils/Makefile.am -- 15 | noinst_LTLIBRARIES = libstringutils.la 16 | libstringutils_la_SOURCES = stringutils.c 17 | 18 | 19 | bin_PROGRAMS = utftex utfstringinfo 20 | utftex_SOURCES = main.c testfonts.c testfonts.h boxes.c error.c stringutils.c drawbox.c lexer.c parser.c 21 | utftex_LDADD = libtexprintf.la 22 | utftex_CFLAGS = $(AM_CFLAGS) # see https://www.gnu.org/software/automake/manual/html_node/Objects-created-both-with-libtool-and-without.html 23 | utfstringinfo_SOURCES = stringutils.h unicodeblocks.h utf2unicode.c parsedef.h 24 | utfstringinfo_LDADD = libstringutils.la 25 | man1_MANS = utftex.1 utfstringinfo.1 26 | 27 | EXTRA_DIST = utftex.1 utfstringinfo.1 gen_errorflags.sh gentexprintfsymbols.sh 28 | 29 | BUILT_SOURCES = errorflags.h errormessages.h texprintfsymbols 30 | 31 | errorflags.h: gen_errorflags.sh boxes.c drawbox.c lexer.c parser.c 32 | ${SHELL} ${srcdir}/gen_errorflags.sh ${srcdir}/boxes.c ${srcdir}/drawbox.c ${srcdir}/lexer.c ${srcdir}/parser.c 33 | 34 | # see https://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html 35 | errormessages.h: errorflags.h 36 | @test -f $@ || rm -f errorflags.h 37 | @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) errorflags.h 38 | 39 | texprintfsymbols: gentexprintfsymbols.sh texprintf.h 40 | ${SHELL} ${srcdir}/gentexprintfsymbols.sh 41 | -------------------------------------------------------------------------------- /src/drawchars.h: -------------------------------------------------------------------------------- 1 | #ifndef DRAWCHAR_H 2 | #define DRAWCHAR_H 3 | /* The style struct contains all "drawing characters" 4 | * This way one can change libtexprintf style for some things 5 | * Currently we have a "UNI" style, which will use unicode for 6 | * everything, and an "ASC" style, which preferrs ASCII when possible. 7 | */ 8 | typedef struct Style { 9 | int mapsupersub; 10 | int avoidcombining; // option to avoid combining diacritical marks if possible 11 | int LBRACKCHAR[4]; // single, lower, extender, upper 12 | int RBRACKCHAR[4]; 13 | int LSQUARECHAR[4]; 14 | int RSQUARECHAR[4]; 15 | int VBARCHAR[4]; 16 | int DVBARCHAR[4]; 17 | /* floor/ceil and up/down arrows */ 18 | int LFLOORCHAR[4]; // single, lower, extender, upper 19 | int RFLOORCHAR[4]; 20 | int LCEILCHAR[4]; 21 | int RCEILCHAR[4]; 22 | int UPARROWCHAR[4]; // single, lower, extender, extender 23 | int DUPARROWCHAR[4]; 24 | int DOWNARROWCHAR[4]; // single, extender, extender, upper 25 | int DDOWNARROWCHAR[4]; 26 | int UPDOWNARROWCHAR[4]; // single, lower, extender, upper 27 | int DUPDOWNARROWCHAR[4]; 28 | /* symmetrical brackets (for use with SymBrac)*/ 29 | int LCURLYCHAR[5]; // single, lower, center, extender, upper 30 | int RCURLYCHAR[5]; // single, lower, center, extender, upper 31 | /* angle brackets (for use with AngleBrac) */ 32 | int ANGLECHAR[4]; // single left, single right, downward, upward 33 | int FSLASH; // forward slash 34 | int BSLASH; // backward slash 35 | /* fraction, overline, underline */ 36 | int FRACLINE; 37 | int OVERLINE; 38 | int UNDERLINE; 39 | /* array characters 40 | * 0 1 2 3 4 5 6 7 8 9 10 41 | * │ ─ ┌ ┬ ┐ ├ ┼ ┤ └ ┴ ┘ */ 42 | int ARRAYCHAR[11]; 43 | /* integrals and sqrt */ 44 | int SQRTCHAR[5]; // downward diagonal, vertical, left top corner, horizontal, right top corner 45 | int INTCHAR[3]; // bottom, extender, top 46 | int IINTCHAR[4]; // single, double, tripple, dots 47 | int OINTCHAR[2]; // quasi-circle 48 | int OIINTCHAR[4]; // single, double, tripple, dots 49 | /* row mayor arrays of characters to draw symbols*/ 50 | int SUMCHAR[10]; // width, height, start lower left, end upper right 51 | int PRODCHAR[8]; // width, height, start lower left, end upper right 52 | int prime[3]; // prime width, height, start lower left, end upper right 53 | int dprime[4]; 54 | int tprime[5]; 55 | int qprime[6]; 56 | } Style; 57 | 58 | #endif //#ifndef DRAWCHAR_H 59 | -------------------------------------------------------------------------------- /test/testfonts.txt: -------------------------------------------------------------------------------- 1 | 2 | ################# Test Fonts 3 | fonts 4 | abcdefghijklmnopqrstuvwxyz\\ 5 | ABCDEFGHIJKLMNOPQRSTUVWXYZ\\ 6 | 1234567890 7 | |-F text 8 | abcdefghijklmnopqrstuvwxyz 9 | ABCDEFGHIJKLMNOPQRSTUVWXYZ 10 | 1234567890 11 | -F mathtt 12 | 𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣 13 | 𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉 14 | 𝟷𝟸𝟹𝟺𝟻𝟼𝟽𝟾𝟿𝟶 15 | -F mathsfit 16 | 𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻 17 | 𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡 18 | 1234567890 19 | -F mathsfbfit 20 | 𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯 21 | 𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕 22 | 1234567890 23 | -F mathsfbf 24 | 𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇 25 | 𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭 26 | 𝟭𝟮𝟯𝟰𝟱𝟲𝟳𝟴𝟵𝟬 27 | -F mathsf 28 | 𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓 29 | 𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹 30 | 𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫𝟢 31 | -F mathscr 32 | 𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃 33 | 𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩 34 | 1234567890 35 | -F mathnormal 36 | 𝑎𝑏𝑐𝑑𝑒𝑓𝑔ℎ𝑖𝑗𝑘𝑙𝑚𝑛𝑜𝑝𝑞𝑟𝑠𝑡𝑢𝑣𝑤𝑥𝑦𝑧 37 | 𝐴𝐵𝐶𝐷𝐸𝐹𝐺𝐻𝐼𝐽𝐾𝐿𝑀𝑁𝑂𝑃𝑄𝑅𝑆𝑇𝑈𝑉𝑊𝑋𝑌𝑍 38 | 1234567890 39 | -F mathfrak 40 | 𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷 41 | 𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ 42 | 1234567890 43 | -F mathcal 44 | 𝒶𝒷𝒸𝒹ℯ𝒻ℊ𝒽𝒾𝒿𝓀𝓁𝓂𝓃ℴ𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏 45 | 𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℳ𝒩𝒪𝒫𝒬ℛ𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵 46 | 1234567890 47 | -F mathbfit 48 | 𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛 49 | 𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁 50 | 1234567890 51 | -F mathbf 52 | 𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳 53 | 𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙 54 | 𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗𝟎 55 | -F mathbb 56 | 𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫 57 | 𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ 58 | 𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡𝟘 59 | 60 | 61 | it 62 | a{\it bc}d 63 | | -S | -A 64 | a𝘣𝘤d 65 | 66 | rm 67 | a{\rm bc}d 68 | | -S | -A 69 | abcd 70 | -F mathnormal 71 | 𝑎bc𝑑 72 | 73 | mathrm 74 | a\mathrm{bc}d 75 | | -S | -A 76 | abcd 77 | -F mathnormal 78 | 𝑎bc𝑑 79 | 80 | boldmathbm 81 | a\bm{a}\alpha\bm{\alpha}abcd\bm{abcd} 82 | | -A | -S | -m 83 | a𝐚α𝛂abcd𝐚𝐛𝐜𝐝 84 | 85 | boldmathpmb 86 | a\pmb{a}\alpha\pmb{\alpha}abcd\pmb{abcd} 87 | | -A | -S | -m 88 | a𝐚α𝛂abcd𝐚𝐛𝐜𝐝 89 | 90 | -------------------------------------------------------------------------------- /test/test.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | # awk script to run tests 3 | # test format: 4 | # A text file where a start of a block is indicated with a line: 5 | # 6 | # The rest is considered input untill the keyword is encountered 7 | # arg1 | arg2 | ... 8 | # a reference block describes what should come out. A reference block 9 | # ends with either a second reference block or the keyword 10 | # For each argument for the reference block (arg1, arg2, ...) utftex is 11 | # called with the input and the specified argument. Note that if a 12 | # reference block has more than one argument, it means you expect the 13 | # output to be independent of the provided arguments 14 | 15 | function test() 16 | { 17 | n=split(arglist,args,"|"); 18 | if (n==0) { 19 | args[1]=" " 20 | } 21 | ac=0; 22 | for (arg in args) 23 | { 24 | ac=ac+1; 25 | tc=tc+1; 26 | system("cat tmp | "exe" "args[arg]" > out"); 27 | r=system("cmp -s ref out") 28 | if (!(r==0)){ 29 | fail=fail+1; 30 | print "FAIL: "name" ref" ref ", arg"ac" = " args[arg] 31 | if (debug>0) 32 | { 33 | file="debug_"name"_ref"ref"_arg"ac 34 | print " test results written to file: " file 35 | system("echo \"# args:\" > "file) 36 | system("echo \"# input:\" >> "file) 37 | system("cat tmp >> "file) 38 | system("echo \"# reference:\" >> "file) 39 | system("cat ref >> "file) 40 | system("echo \"# output:\" >> "file) 41 | system("cat out >> "file) 42 | } 43 | } 44 | else { 45 | print "PASS: "name" ref" ref ", arg"ac" = " args[arg] 46 | } 47 | } 48 | } 49 | 50 | # variables 51 | # eq: boolean, are we in an equation input block? 52 | # ref: boolean, are we in a reference block? 53 | # name: string, name of the test 54 | # arglist: string, list of '|' separated arguments to test a reference against 55 | # fail: integer, counter for failed tests 56 | # tc: integer, test counter (all tests) 57 | # exe: string, with name and path of the utftex executable, defaults to "utftex" 58 | # debug: if >0, each failed tests generates an output file with test and test results 59 | BEGIN {eq=0;ref=0;name="none";arglist="";fail=0;tc=0;if(!exe){exe="utftex"};if(!debug){debug=0}} 60 | { 61 | if ($1=="") { 62 | close("ref") 63 | close("tmp") 64 | test() 65 | system("rm ref") 66 | system("rm tmp") 67 | ref=0; 68 | } 69 | if ($1=="") { 70 | if (ref>0) { 71 | close("ref") 72 | close("tmp") 73 | test() 74 | system("rm ref") 75 | } 76 | eq=0; 77 | ref=ref+1; 78 | $1=""; 79 | arglist=$0; 80 | } else if (ref>0) { 81 | print >> "ref" 82 | } 83 | if (eq) { 84 | print >> "tmp" 85 | } 86 | if ($1=="") { 87 | eq=1; 88 | name=$2; 89 | } 90 | } 91 | END{system("rm out");print tc,fail} 92 | -------------------------------------------------------------------------------- /src/texprintf.3: -------------------------------------------------------------------------------- 1 | .TH texprintf 1.1.0 "05 Jul 2022" 2 | .SH NAME 3 | texprintf, stexprintf, ftexprintf, texlistsymbols, texboxtree \- Extended formatted output functions 4 | .SH SYNOPSIS 5 | .nf 6 | .B #include 7 | .PP 8 | .BI "int texprintf(const char *format, ...);" 9 | .BI "char * stexprintf(const char *format, ...);" 10 | .BI "int ftexprintf(const char *format, ...);" 11 | .BI "void texlistsymbols();" 12 | .BI "void texboxtree(const char *format, ...);" 13 | .BI "void texlistsymbols();" 14 | .BI "void texerrors();" 15 | .fi 16 | .PP 17 | In adition to the above functions defines several variables: 18 | .nf 19 | .PP 20 | .BI "int TEXPRINTF_LW;" 21 | .BI "char * TEXPRINTF_FONT;" 22 | .BI "int TEXPRINTF_ERR;" 23 | .fi 24 | .PP 25 | 26 | .SH DESCRIPTION 27 | The functions in the texprintf family provide formatted output like the printf family of functions extended 28 | with a tex-like syntax. The functions generate UTF-8 encoded strings and assume that monospace fonts are used 29 | (also for symbols, beware of non-monospace fallback fonts). 30 | 31 | .br 32 | Please refer to the utftex man page for details on the tex-like syntax provided by these functions. Refer to 33 | the man page of printf for a description of the format. 34 | 35 | .br 36 | Upon successful return the functions texprintf, and ftexprintf return the number of characters 37 | printed (excluding the null byte used to end output to strings). The stexprintf function 38 | returns an allocated string containing the result. 39 | 40 | .br 41 | With the integer TEXPRINTF_LW, the line width may be limited. Per default the line width is not limited 42 | (TEXPRINTF_LW=0). If TEXPRINTF_LW is set to a positive integer, the texprintf functions will 43 | .B try 44 | to limit the line width to this number of characters, i.e., tt tries to break up the equation 45 | over more than one line. To this end the texprinf engine must find suitable places to break the equation. 46 | As it is not guaranteed a suitable location is found, the line width is 47 | .B not 48 | guaranteed. 49 | 50 | .br 51 | The string TEXPRINTF_FONT can be used to specify the default font. The available fonts are 52 | .nf 53 | .BI "mathsfbfit" 54 | .BI "mathsfbf" 55 | .BI "mathfrak" 56 | .BI "mathbfit" 57 | .BI "mathsfit" 58 | .BI "mathcal" 59 | .BI "mathscr" 60 | .BI "mathbf" 61 | .BI "mathbb" 62 | .BI "mathsf" 63 | .BI "mathtt" 64 | .BI "mathnormal" 65 | .BI "text (default)" 66 | .fi 67 | .br 68 | The integer TEXPRINTF_ERR is an error flag. If its value is non zero after a call to any of the texprintf functions, 69 | an error has occurred in parsing the input. A call to texerrors() will print the corresponding error messages. 70 | A call to texerrors() will print the related error messages. 71 | .br 72 | The function texlistsymbols() prints all symbols the texprintf system knows. 73 | .br 74 | The texboxtree(const char *format, ...) is for debugginbg purposes. It takes the same arguments as texprintf, however, 75 | its output is a description of the resulting internal box datastructures. 76 | 77 | 78 | .SH SEE ALSO 79 | printf(3), utftex(1) 80 | 81 | -------------------------------------------------------------------------------- /src/lexer.h: -------------------------------------------------------------------------------- 1 | typedef enum { 2 | PD_RAISEBOX, 3 | PD_ENDLINE, 4 | PD_COMB_GRAVE, 5 | PD_COMB_ACUTE, 6 | PD_COMB_HAT, 7 | PD_COMB_TILDE, 8 | PD_COMB_BREVE, 9 | PD_COMB_DOT, 10 | PD_COMB_DIAERESIS, 11 | PD_COMB_MRING, 12 | PD_COMB_DACUTE, 13 | PD_COMB_CARON, 14 | PD_COMB_CEDILLA, 15 | PD_COMB_OGONEK, 16 | PD_COMB_UTILDE, 17 | PD_COMB_SSOLIDUS, 18 | PD_COMB_LSOLIDUS, 19 | PD_COMB_OVERLINE, 20 | PD_COMB_UNDERLINE, 21 | 22 | // auto generated 23 | PD_COMB_LVEC, 24 | PD_COMB_LLVEC, 25 | PD_COMB_VEC, 26 | PD_COMB_DDDOT, 27 | PD_COMB_DDDDOT, 28 | PD_COMB_OVERLEFTRIGHTARROW, 29 | PD_COMB_OVHOOK, 30 | PD_COMB_OTURNEDCOMMA, 31 | PD_COMB_OCOMMATOPRIGHT, 32 | PD_COMB_DROANG, 33 | PD_COMB_RIGHTHARPOONACCENT, 34 | PD_COMB_WIDEBRIDGEABOVE, 35 | PD_COMB_ASTERACCENT, 36 | PD_COMB_CANDRA, 37 | PD_COMB_WIDEUTILDE, 38 | PD_COMB_THREEUNDERDOT, 39 | PD_COMB_UNDERLEFTARROW, 40 | PD_COMB_UNDERRIGHTARROW, 41 | PD_COMB_UNDERBAR, 42 | PD_COMB_UNDERLEFTRIGHTARROW, 43 | PD_COMB_UNDERRIGHTHARPOONDOWN, 44 | PD_COMB_UNDERLEFTHARPOONDOWN, 45 | PD_COMB_PALH, 46 | PD_COMB_RH, 47 | PD_COMB_SBBRG, 48 | PD_COMB_SOUT, 49 | PD_COMB_STRIKE, 50 | PD_COMB_ANNUITY, 51 | PD_COMB_ENCLOSECIRCLE, 52 | PD_COMB_ENCLOSESQUARE, 53 | PD_COMB_ENCLOSEDIAMOND, 54 | PD_COMB_ENCLOSETRIANGLE, 55 | PD_COMB_VERTOVERLAY, 56 | 57 | PD_FUNCTION, 58 | PD_FRAC, 59 | PD_BINOM, 60 | PD_STACK, 61 | PD_OVER, 62 | PD_CHOOSE, 63 | PD_SQRT, 64 | PD_INT, 65 | PD_IINT, 66 | PD_IIINT, 67 | PD_IIIINT, 68 | PD_IDOTSINT, 69 | PD_OINT, 70 | PD_OIINT, 71 | PD_OIIINT, 72 | PD_OIIIINT, 73 | PD_OIDOTSINT, 74 | PD_SUM, 75 | PD_PROD, 76 | PD_SUPER, 77 | PD_SUB, 78 | PD_LIMITS, 79 | PD_NOLIMITS, 80 | PD_LIM, 81 | PD_LEFTRIGHT, 82 | PD_BIG1, 83 | PD_BIG2, 84 | PD_BIG3, 85 | PD_BIG4, 86 | PD_SYMBOL, 87 | PD_BACKSLASH, 88 | PD_TEXT, 89 | PD_BOLD, 90 | PD_MATHBF, 91 | PD_MATHBFIT, 92 | PD_MATHCAL, 93 | PD_MATHSCR, 94 | PD_MATHFRAK, 95 | PD_MATHBB, 96 | PD_MATHSF, 97 | PD_MATHSFBF, 98 | PD_MATHSFIT, 99 | PD_MATHSFBFIT, 100 | PD_MATHTT, 101 | PD_MATHNORMAL, 102 | PD_ROOTFONT, // switch to the root font for $...$ 103 | PD_BEGIN, 104 | PD_END, 105 | PD_BOX, /* custom command to make a box of some size */ 106 | PD_KERN, 107 | PD_PHANTOM, 108 | PD_VPHANTOM, 109 | PD_HPHANTOM, 110 | /* subsection for \begin ... \end sections */ 111 | PD_ALIGN, 112 | PD_ARRAY, 113 | PD_CASES, 114 | PD_PMATRIX, 115 | PD_BMATRIX, 116 | PD_BBMATRIX, 117 | PD_VMATRIX, 118 | PD_VVMATRIX, 119 | PD_MATRIX, 120 | PD_HLINE, 121 | PD_BLOCK, 122 | PD_SETROMAN, 123 | PD_SETITALIC, 124 | PD_SETBOLD, 125 | PD_SPACE, 126 | PD_DSPACE, 127 | PD_TSPACE, 128 | PD_NSPACE, 129 | PD_PRIME, 130 | PD_NONE 131 | } PRSDEF; 132 | typedef enum { 133 | F_ROMAN, 134 | F_ITALIC, 135 | F_BOLD, 136 | F_NOFONT 137 | } FONT; 138 | 139 | typedef enum { 140 | DEL_L, 141 | DEL_R, 142 | DEL_LSQ, 143 | DEL_RSQ, 144 | DEL_LCURL, 145 | DEL_RCURL, 146 | DEL_LANGLE, 147 | DEL_RANGLE, 148 | DEL_LCEIL, 149 | DEL_RCEIL, 150 | DEL_LFLOOR, 151 | DEL_RFLOOR, 152 | DEL_VBAR, 153 | DEL_DVBAR, 154 | DEL_DOT, 155 | DEL_UPARROW, 156 | DEL_DOWNARROW, 157 | DEL_UPDOWNARROW, 158 | DEL_DUPARROW, 159 | DEL_DDOWNARROW, 160 | DEL_DUPDOWNARROW, 161 | DEL_SLASH, 162 | DEL_BACKSLASH, 163 | DEL_NONE, 164 | } SCALABLE_DELIMITER; 165 | 166 | typedef struct { 167 | char **args; 168 | int Nargs; 169 | char **opt; 170 | int Nopt; 171 | char *sub; 172 | char *super; 173 | char *next; /* reference to the next thing to lex */ 174 | char *self; /* a reference to the own lexed string */ 175 | int limits; 176 | PRSDEF P; 177 | FONT F; 178 | } TOKEN; 179 | 180 | void ListSymbols(); 181 | char * Symbols_Str(); 182 | int IsTexConstruct(char *string); 183 | TOKEN Lexer(char *begin, FONT F); 184 | void FreeToken(TOKEN T); 185 | void PrintToken(TOKEN T); 186 | char * Unicode2Utf8(int U); 187 | char * PreProcessor(char *string2); 188 | PRSDEF LookupFont(char *begin); 189 | SCALABLE_DELIMITER LookupDelimiter(char *begin, char **del); 190 | void LookupCombining(PRSDEF P, unsigned int *comb, unsigned int *alt, unsigned int *altascii); 191 | int ReadLengthWidth(char *str); 192 | int ReadLengthHeight(char *str); 193 | -------------------------------------------------------------------------------- /src/drawbox.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "stringutils.h" 5 | #include "boxes.h" 6 | #include "error.h" 7 | 8 | char *RemoveLineTrailingWhitespace(char *str) 9 | { 10 | // search for whitespace ending with endline 11 | char *p, *q; 12 | p=str; 13 | q=str; 14 | while (*p) 15 | { 16 | if (*p==' ') 17 | { 18 | char *z; 19 | z=p; 20 | while(*z==' ') 21 | z++; 22 | if ((*z=='\n')||(*z=='\0')) 23 | p=z; 24 | else 25 | { 26 | while(pS==ABSPOSKNOWN) 51 | { 52 | char *buffer; 53 | int i, w=0; 54 | int x, y, off=0, Na; 55 | box *bb; 56 | if ((b->ax!=0)||(b->ay!=0)) 57 | { 58 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 59 | // ERRORFLAG ERRDRAWBOXNOROOT "Drawbox needs a rootbox as input" 60 | AddErr(ERRDRAWBOXNOROOT); 61 | out[0]='\0'; /* return empty string */ 62 | return out; 63 | } 64 | buffer=malloc((b->w+1)*sizeof(char)); 65 | w=b->w; 66 | Na=w+1; 67 | for (y=b->h-1;y>=0;y--) 68 | { 69 | off=0; /* offset from multibyte and combinational characters */ 70 | 71 | for (x=0;xw;x++) 72 | { 73 | bb=FindBoxAtPos(b, x, y); 74 | if (bb) 75 | { 76 | if (bb->ax==x) 77 | { 78 | /* insert unit box bb's string in our buffer */ 79 | char *str; 80 | str=UnicodeMapper((char *) bb->content); 81 | i=x+off; 82 | off+=strlen(str)-strspaces(str); /* update offset */ 83 | if (i+strlen(str)>=Na-1) 84 | { 85 | Na+=strlen(str)+2; 86 | buffer=realloc(buffer, Na*sizeof(char)); 87 | } 88 | sprintf(buffer+i, "%s", str); 89 | i+=strlen(str); 90 | free(str); 91 | } 92 | } 93 | else 94 | { 95 | /* nothing there, fill up with whitespace */ 96 | if (x+off+1>=Na-1) 97 | { 98 | Na+=2; 99 | buffer=realloc(buffer, Na*sizeof(char)); 100 | } 101 | buffer[x+off]=' '; 102 | 103 | } 104 | } 105 | out=realloc(out,(k+w+off+2)*sizeof(char)); 106 | for (i=0;iS); 155 | Indent(indent); 156 | printf("Pos:\n"); 157 | Indent(indent+NIDENT); 158 | if (b->S==ABSPOSKNOWN) 159 | printf("(x,y)=(%d,%d)\n", b->ax, b->ay); 160 | else 161 | printf("(x,y)=(?,?)\n"); 162 | 163 | Indent(indent+NIDENT); 164 | if (b->S>=RELPOSKNOWN) 165 | printf("(rx,ry)=(%d,%d)\n", b->rx, b->ry); 166 | else 167 | printf("(rx,ry)=(?,?)\n"); 168 | if (b->S>=SIZEKNOWN) 169 | { 170 | Indent(indent+NIDENT); 171 | printf("(xc,yc)=(%d,%d)\n", b->xc, b->yc); 172 | Indent(indent+NIDENT); 173 | printf("(X,Y)=(%d,%d)\n", b->X, b->Y); 174 | Indent(indent+NIDENT); 175 | printf("(w,h)=(%d,%d)\n", b->w, b->h); 176 | } 177 | else 178 | { 179 | Indent(indent+NIDENT); 180 | printf("(xc,yc)=(?,?)\n"); 181 | Indent(indent+NIDENT); 182 | printf("(X,Y)=(?,?)\n"); 183 | Indent(indent+NIDENT); 184 | printf("(w,h)=(?,?)\n"); 185 | } 186 | Indent(indent); 187 | printf("Type: "); 188 | switch(b->T) 189 | { 190 | case B_UNIT: 191 | { 192 | char *str; 193 | printf("UNIT\n"); 194 | str=UnicodeMapper((char *) b->content); 195 | Indent(indent+NIDENT); 196 | printf("Content: %s\n",str); 197 | free(str); 198 | break; 199 | } 200 | case B_ARRAY: 201 | printf("ARRAY\n"); 202 | Indent(indent+NIDENT); 203 | printf("Nc=%d\n", b->Nc); 204 | for (i=0;iNc;i++) 205 | DrawBoxTreeRec(b->child+i, indent+NIDENT); 206 | break; 207 | case B_POS: 208 | printf("POS\n"); 209 | Indent(indent+NIDENT); 210 | printf("Nc=%d\n", b->Nc); 211 | for (i=0;iNc;i++) 212 | DrawBoxTreeRec(b->child+i, indent+NIDENT); 213 | break; 214 | case B_DUMMY: 215 | printf("DUMMY\n"); 216 | break; 217 | case B_LINE: 218 | printf("LINE\n"); 219 | Indent(indent+NIDENT); 220 | printf("Nc=%d\n", b->Nc); 221 | for (i=0;iNc;i++) 222 | DrawBoxTreeRec(b->child+i, indent+NIDENT); 223 | break; 224 | case B_ENDLINE: 225 | printf("ENDLINE\n"); 226 | break; 227 | default: 228 | break; 229 | } 230 | 231 | } 232 | void DrawBoxTree(box *b) 233 | { 234 | DrawBoxTreeRec(b, 0); 235 | } 236 | -------------------------------------------------------------------------------- /src/testfonts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "boxes.h" 7 | #include "drawbox.h" 8 | #include "parser.h" 9 | #include "lexer.h" 10 | #include "stringutils.h" 11 | #include "testfonts.h" 12 | char *styles[]={ 13 | "mathsfbfit", 14 | "mathsfbf", 15 | "mathfrak", 16 | "mathbfit", 17 | "mathsfit", 18 | "mathcal", 19 | "mathscr", 20 | "mathbf", 21 | "mathbb", 22 | "mathsf", 23 | "mathtt", 24 | "mathnormal", 25 | "text", 26 | NULL 27 | }; 28 | 29 | typedef struct Test_String{ 30 | char *str, *descr; 31 | } Test_String; 32 | 33 | Test_String font_tests[]={ 34 | {"abcdefghijklmnopqrstuvwxyz", "latin "}, 35 | {"ABCDEFGHIJKLMNOPQRSTUVWXYZ", "latin "}, 36 | {"1234567890", "numbers "}, 37 | {"𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯", "mathsfbfit"}, 38 | {"𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕", "mathsfbfit"}, 39 | {"1234567890", "mathsfbfit"}, 40 | {"𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇", "mathsfbf "}, 41 | {"𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭", "mathsfbf "}, 42 | {"𝟭𝟮𝟯𝟰𝟱𝟲𝟳𝟴𝟵𝟬", "mathsfbf "}, 43 | {"𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷", "mathfrak "}, 44 | {"𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ", "mathfrak "}, 45 | {"1234567890", "mathfrak "}, 46 | {"𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛", "mathbfit "}, 47 | {"𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁", "mathbfit "}, 48 | {"1234567890", "mathbfit "}, 49 | {"𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻", "mathsfit "}, 50 | {"𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡", "mathsfit "}, 51 | {"1234567890", "mathsfit "}, 52 | {"𝒶𝒷𝒸𝒹ℯ𝒻ℊ𝒽𝒾𝒿𝓀𝓁𝓂𝓃ℴ𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏", "mathcal "}, 53 | {"𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℓ𝒩𝒪𝒫𝒬ℛ𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵", "mathcal "}, 54 | {"1234567890", "mathcal "}, 55 | {"𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃", "mathscr "}, 56 | {"𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩", "mathscr "}, 57 | {"1234567890", "mathscr "}, 58 | {"𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳", "mathbf "}, 59 | {"𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙", "mathbf "}, 60 | {"𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗𝟎", "mathbf "}, 61 | {"𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫", "mathbb "}, 62 | {"𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ", "mathbb "}, 63 | {"𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡𝟘", "mathbb "}, 64 | {"𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓", "mathsf "}, 65 | {"𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹", "mathsf "}, 66 | {"𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫𝟢", "mathsf "}, 67 | {"𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣", "mathtt "}, 68 | {"𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉", "mathtt "}, 69 | {"𝟷𝟸𝟹𝟺𝟻𝟼𝟽𝟾𝟿𝟶", "mathtt "}, 70 | {"𝑎𝑏𝑐𝑑𝑒𝑓𝑔ℎ𝑖𝑗𝑘𝑙𝑚𝑛𝑜𝑝𝑞𝑟𝑠𝑡𝑢𝑣𝑤𝑥𝑦𝑧", "mathnormal"}, 71 | {"𝐴𝐵𝐶𝐷𝐸𝐹𝐺𝐻𝐼𝐽𝐾𝐿𝑀𝑁𝑂𝑃𝑄𝑅𝑆𝑇𝑈𝑉𝑊𝑋𝑌𝑍", "mathnormal"}, 72 | {"1234567890", "mathnormal"}, 73 | {"αβγδεζηθικλμνξοπρςστυφχψωϊ", "greek "}, 74 | {"ϋόύώϏϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡ ", "greek "}, 75 | {"─━│┃┄┅┆┇┈┉┊┋┌┍┎┏┐┑┒┓└┕┖┗┘┙", "box draw "}, 76 | {"┚┛├┝┞┟┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳", "box draw "}, 77 | {"┴┵┶┷┸┹┺┻┼┽┾┿╀╁╂╃╄╅╆╇╈╉╊╋╌╍", "box draw "}, 78 | {"╎╏═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡╢╣╤╥╦╧", "box draw "}, 79 | {"╨╩╪╫╬╭╮╯╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿ ", "box draw "}, 80 | {NULL,NULL} 81 | }; 82 | 83 | #define MTESTSTRLEN 255 84 | char *AlignChars(int j) 85 | { 86 | char *str; 87 | char *max; 88 | char *p, *s; 89 | int k,n=0; 90 | str=malloc(MTESTSTRLEN*sizeof(char)); 91 | s=str; 92 | *s='|'; 93 | s++; 94 | max=str+MTESTSTRLEN; 95 | p=font_tests[j].str; 96 | while (*p) 97 | { 98 | /* copy one utf-8 character at a time */ 99 | k=NumByte(p); 100 | while(k) 101 | { 102 | *s=*p; 103 | p++; 104 | s++; 105 | if (s>=max) 106 | { 107 | fprintf(stderr,"Error: in AlignChars not enough space in allocated string\n"); 108 | exit(1); 109 | } 110 | k--; 111 | } 112 | n++; 113 | if (n%5) 114 | { 115 | *s=' '; 116 | s++; 117 | } 118 | else 119 | { 120 | strncpy(s,"\\text{|}", 9); 121 | s+=8; 122 | } 123 | if (s>=max) 124 | { 125 | fprintf(stderr,"Error: in AlignChars not enough space in allocated string\n"); 126 | exit(1); 127 | } 128 | } 129 | *s='\0'; 130 | return str; 131 | } 132 | 133 | void MakeBlockString(int start, int end) 134 | { 135 | char *str; 136 | char *c; 137 | char *s; 138 | int i, k; 139 | if (end 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "texprintf.h" 7 | #include "testfonts.h" 8 | #include "config.h" 9 | #ifdef __MINGW32__ 10 | #include 11 | #endif 12 | 13 | int main(int argc, char **argv) 14 | { 15 | int i, c, e=1; 16 | int printsource=0; 17 | int boxtree=0; 18 | int test_stexprintf=0; 19 | int done=0; 20 | int ret=0; 21 | int combine_errors=0; 22 | char *font=NULL; 23 | char *symbols=NULL; 24 | #ifdef __MINGW32__ 25 | UINT oldcp = GetConsoleOutputCP(); 26 | SetConsoleOutputCP(CP_UTF8); 27 | #endif 28 | while (e) 29 | { 30 | static struct option long_options[] = 31 | { 32 | {"line-width", required_argument, 0, 'l'}, 33 | {"symbol-list", no_argument, 0, 's'}, 34 | {"test-texsymbols", no_argument, 0, 'T'}, 35 | {"version", no_argument, 0, 'v'}, 36 | {"show-input", no_argument, 0, 'i'}, 37 | {"wchar-width", required_argument, 0, 'w'}, 38 | {"fchar-width", required_argument, 0, 'f'}, 39 | {"default-font",required_argument, 0, 'F'}, 40 | {"box-tree", no_argument, 0, 'B'}, 41 | {"test-fonts", required_argument, 0, 't'}, 42 | {"test-stexprintf", required_argument, 0, 'S'}, 43 | {"ascii", no_argument, 0, 'A'}, 44 | {"combine-errors", no_argument, 0, 'E'}, 45 | {"mapsupersub", no_argument, 0, 'm'}, 46 | {"avoidcombining" , no_argument, 0, 'a'}, 47 | {"end-options" , no_argument, 0, 'e'}, 48 | {0, 0, 0, 0} 49 | }; 50 | int option_index = 0; 51 | c = getopt_long (argc, argv, "l:sTviw:f:F:BtSAEmae",long_options, &option_index); 52 | if (c == -1) 53 | break; 54 | 55 | switch (c) 56 | { 57 | case 'l': 58 | if (!optarg) 59 | { 60 | fprintf(stderr, "Error: --line-width requires an integer as argument\n"); 61 | return 1; 62 | } 63 | 64 | TEXPRINTF_LW=atoi(optarg); 65 | break; 66 | case 's': 67 | texlistsymbols(); 68 | done++; 69 | break; 70 | case 'T': 71 | symbols = texsymbols_str(); 72 | puts(symbols); 73 | texfree(symbols); 74 | done++; 75 | break; 76 | case 't': 77 | TestFonts(); 78 | done++; 79 | break; 80 | case 'v': 81 | printf(" __ ____________________ _ __\n"); 82 | printf(" / / / /_ __/ ____/_ __/__ | |/ /\n"); 83 | printf(" / / / / / / / /_ / / / _ \\| / \n"); 84 | printf("/ /_/ / / / / __/ / / / __/ | \n"); 85 | printf("\\____/ /_/ /_/ /_/ \\___/_/|_| \n"); 86 | printf("This is utftex version %s\nPowered by %s\n", UTFTEXVERSION, PACKAGE_STRING); 87 | done++; 88 | break; 89 | case 'i': 90 | printsource=1; 91 | break; 92 | case 'w': 93 | if (!optarg) 94 | { 95 | fprintf(stderr, "Error: --wchar-width requires the number of spaces for a wide character (1 or 2)\n"); 96 | return 1; 97 | } 98 | 99 | TEXPRINTF_WCW=atoi(optarg); 100 | break; 101 | case 'f': 102 | if (!optarg) 103 | { 104 | fprintf(stderr, "Error: --fchar-width requires the number of spaces for a full width character (1 or 2)\n"); 105 | return 1; 106 | } 107 | 108 | TEXPRINTF_FCW=atoi(optarg); 109 | break; 110 | case 'F': 111 | if (!optarg) 112 | { 113 | fprintf(stderr, "Error: --default-font requires the default font style name\n"); 114 | return 1; 115 | } 116 | font=malloc((strlen(optarg)+1)*sizeof(char)); 117 | strcpy(font, optarg); 118 | TEXPRINTF_FONT=font; 119 | break; 120 | case 'B': 121 | boxtree=1; 122 | break; 123 | case 'S': 124 | test_stexprintf=1; 125 | break; 126 | case 'A': 127 | SetStyleASCII(); 128 | break; 129 | case 'E': 130 | combine_errors = 1; 131 | break; 132 | case 'm': 133 | ToggleMapSuperSub(); 134 | break; 135 | case 'a': 136 | ToggleAvoidCombining(); 137 | break; 138 | case 'e': 139 | e=0; 140 | break; 141 | case '?': 142 | default: 143 | exit(1); 144 | } 145 | } 146 | 147 | if (optind < argc) 148 | { 149 | while (optind < argc) 150 | { 151 | if (printsource) 152 | printf("%s\n",argv[optind]); 153 | if (test_stexprintf) { 154 | char *str = stexprintf("%s\n",argv[optind]); 155 | puts(str); 156 | texfree(str); 157 | } 158 | else 159 | texprintf("%s\n",argv[optind]); 160 | 161 | if (combine_errors) { 162 | char *err = texerrors_str(); 163 | fprintf(stderr, "ERRORS: %s\n", err); 164 | texfree(err); 165 | } 166 | else 167 | texerrors(); 168 | if (boxtree) 169 | texboxtree("%s\n",argv[optind]); 170 | ret|=TEXPRINTF_ERR; 171 | done++; 172 | optind++; 173 | } 174 | } 175 | 176 | if (!done) 177 | { 178 | char *buffer; 179 | int Na=50; 180 | char ch; 181 | buffer=malloc(Na*sizeof(char)); 182 | i=0; 183 | while(read(STDIN_FILENO, &ch, 1) > 0) 184 | { 185 | buffer[i++]=ch; 186 | if (i==Na) 187 | { 188 | Na+=50; 189 | buffer=realloc(buffer, Na*sizeof(char)); 190 | } 191 | } 192 | buffer[i]='\0'; 193 | if (printsource) 194 | printf("%s\n",buffer); 195 | 196 | if (test_stexprintf) { 197 | char *str = stexprintf("%s\n",buffer); 198 | puts(str); 199 | texfree(str); 200 | } 201 | else 202 | texprintf("%s\n",buffer); 203 | 204 | if (combine_errors) { 205 | char *err = texerrors_str(); 206 | fprintf(stderr, "ERRORS: %s\n", err); 207 | texfree(err); 208 | } 209 | else 210 | texerrors(); 211 | if (boxtree) 212 | texboxtree("%s\n",argv[optind]); 213 | ret|=TEXPRINTF_ERR; 214 | } 215 | 216 | #ifdef __MINGW32__ 217 | SetConsoleOutputCP(oldcp); 218 | #endif 219 | return ret; 220 | } 221 | -------------------------------------------------------------------------------- /src/texprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "boxes.h" 6 | #include "drawbox.h" 7 | #include "parser.h" 8 | #include "lexer.h" 9 | #include "stringutils.h" 10 | #include "error.h" 11 | 12 | int TEXPRINTF_LW=0; 13 | char * TEXPRINTF_FONT="text"; 14 | int TEXPRINTF_FCW=2; 15 | int TEXPRINTF_WCW=2; 16 | 17 | int TEXPRINTF_ERR=0; 18 | 19 | int texprintf(const char *format, ...) 20 | { 21 | va_list ap; 22 | char *str; 23 | int Na=255, np; 24 | box root; 25 | 26 | ResetErrors(); 27 | FCSPACES=TEXPRINTF_FCW; 28 | WCSPACES=TEXPRINTF_WCW; 29 | if ((WCSPACES<1)||(WCSPACES>2)) 30 | { 31 | fprintf(stderr,"Error: TEXPRINTF_WCW out of range, wide characters can occupy either 1 or 2 character spaces\n"); 32 | exit(1); 33 | } 34 | if ((FCSPACES<1)||(FCSPACES>2)) 35 | { 36 | fprintf(stderr,"Error: TEXPRINTF_FCW out of range, wide characters can occupy either 1 or 2 character spaces\n"); 37 | exit(1); 38 | } 39 | 40 | str=malloc(Na*sizeof(char)); 41 | va_start (ap, format); 42 | np=vsnprintf(str, Na*sizeof(char), format, ap); 43 | while (np>=Na) 44 | { 45 | Na+=255; 46 | str=realloc(str, Na*sizeof(char)); 47 | va_start (ap, format); 48 | np=vsnprintf(str, Na*sizeof(char), format, ap); 49 | } 50 | 51 | root=ParseString(str, TEXPRINTF_LW, TEXPRINTF_FONT); 52 | BoxPos(&root); 53 | np=PrintBox(&root); 54 | FreeBox(&root); 55 | free(str); 56 | TEXPRINTF_ERR=ERRORSTATE; 57 | return np; 58 | } 59 | 60 | char * texstring(const char *str) 61 | { 62 | box root; 63 | char *res; 64 | 65 | ResetErrors(); 66 | FCSPACES=TEXPRINTF_FCW; 67 | WCSPACES=TEXPRINTF_WCW; 68 | if ((WCSPACES<1)||(WCSPACES>2)) 69 | { 70 | fprintf(stderr,"Error: TEXPRINTF_WCW out of range, wide characters can occupy either 1 or 2 character spaces\n"); 71 | exit(1); 72 | } 73 | if ((FCSPACES<1)||(FCSPACES>2)) 74 | { 75 | fprintf(stderr,"Error: TEXPRINTF_FCW out of range, wide characters can occupy either 1 or 2 character spaces\n"); 76 | exit(1); 77 | } 78 | 79 | root=ParseString(str, TEXPRINTF_LW, TEXPRINTF_FONT); 80 | BoxPos(&root); 81 | res=DrawBox(&root); 82 | FreeBox(&root); 83 | TEXPRINTF_ERR=ERRORSTATE; 84 | 85 | return res; 86 | } 87 | 88 | 89 | char * stexprintf(const char *format, ...) 90 | { 91 | va_list ap; 92 | char *res; 93 | char *str; 94 | int Na=255, np; 95 | 96 | str=malloc(Na*sizeof(char)); 97 | va_start (ap, format); 98 | np=vsnprintf(str, Na*sizeof(char), format, ap); 99 | while (np>=Na) 100 | { 101 | Na+=255; 102 | str=realloc(str, Na*sizeof(char)); 103 | va_start (ap, format); 104 | np=vsnprintf(str, Na*sizeof(char), format, ap); 105 | } 106 | 107 | res = texstring(str); 108 | free(str); 109 | return res; 110 | } 111 | 112 | void texfree(void *ptr) 113 | { 114 | free(ptr); 115 | } 116 | 117 | int ftexprintf(FILE *f, const char *format, ...) 118 | { 119 | va_list ap; 120 | char *res; 121 | char *str; 122 | int Na=255, np; 123 | box root; 124 | 125 | ResetErrors(); 126 | FCSPACES=TEXPRINTF_FCW; 127 | WCSPACES=TEXPRINTF_WCW; 128 | if ((WCSPACES<1)||(WCSPACES>2)) 129 | { 130 | fprintf(stderr,"Error: TEXPRINTF_WCW out of range, wide characters can occupy either 1 or 2 character spaces\n"); 131 | exit(1); 132 | } 133 | if ((FCSPACES<1)||(FCSPACES>2)) 134 | { 135 | fprintf(stderr,"Error: TEXPRINTF_FCW out of range, wide characters can occupy either 1 or 2 character spaces\n"); 136 | exit(1); 137 | } 138 | 139 | str=malloc(Na*sizeof(char)); 140 | va_start (ap, format); 141 | np=vsnprintf(str, Na*sizeof(char), format, ap); 142 | while (np>=Na) 143 | { 144 | Na+=255; 145 | str=realloc(str, Na*sizeof(char)); 146 | va_start (ap, format); 147 | np=vsnprintf(str, Na*sizeof(char), format, ap); 148 | } 149 | 150 | root=ParseString(str, TEXPRINTF_LW, TEXPRINTF_FONT); 151 | BoxPos(&root); 152 | res=DrawBox(&root); 153 | FreeBox(&root); 154 | free(str); 155 | np=strlen(res); 156 | fprintf(f,"%s",res); 157 | free(res); 158 | TEXPRINTF_ERR=ERRORSTATE; 159 | 160 | return np; 161 | } 162 | 163 | void texboxtree(const char *format, ...) 164 | { 165 | va_list ap; 166 | char *str; 167 | int Na=255, np; 168 | box root; 169 | 170 | ResetErrors(); 171 | FCSPACES=TEXPRINTF_FCW; 172 | WCSPACES=TEXPRINTF_WCW; 173 | if ((WCSPACES<1)||(WCSPACES>2)) 174 | { 175 | fprintf(stderr,"Error: TEXPRINTF_WCW out of range, wide characters can occupy either 1 or 2 character spaces\n"); 176 | exit(1); 177 | } 178 | if ((FCSPACES<1)||(FCSPACES>2)) 179 | { 180 | fprintf(stderr,"Error: TEXPRINTF_FCW out of range, wide characters can occupy either 1 or 2 character spaces\n"); 181 | exit(1); 182 | } 183 | 184 | str=malloc(Na*sizeof(char)); 185 | va_start (ap, format); 186 | np=vsnprintf(str, Na*sizeof(char), format, ap); 187 | while (np>=Na) 188 | { 189 | Na+=255; 190 | str=realloc(str, Na*sizeof(char)); 191 | va_start (ap, format); 192 | np=vsnprintf(str, Na*sizeof(char), format, ap); 193 | } 194 | 195 | root=ParseString(str, TEXPRINTF_LW, TEXPRINTF_FONT); 196 | BoxPos(&root); 197 | DrawBoxTree(&root); 198 | FreeBox(&root); 199 | free(str); 200 | TEXPRINTF_ERR=ERRORSTATE; 201 | 202 | } 203 | 204 | void texlistsymbols() 205 | { 206 | ListSymbols(); /* link to lexer.o */ 207 | } 208 | 209 | char *texsymbols_str() 210 | { 211 | return Symbols_Str(); /* link to lexer.o */ 212 | } 213 | 214 | void texerrors() 215 | { 216 | ERRORSTATE=TEXPRINTF_ERR; 217 | E_Messages(); /* link to error.o */ 218 | ResetErrors(); 219 | } 220 | 221 | /* Like texerror(), but return "; "-delimited string instead of 222 | writing to stderr. Caller should free return value with texfree. */ 223 | char *texerrors_str() 224 | { 225 | char *s; 226 | ERRORSTATE=TEXPRINTF_ERR; 227 | s = E_Messages_str(); /* link to error.o */ 228 | ResetErrors(); 229 | return s; 230 | } 231 | 232 | void SetStyleASCII() 233 | { 234 | style=&STYLE_ASC; 235 | } 236 | void SetStyleUNICODE() 237 | { 238 | style=&STYLE_UNI; 239 | } 240 | void ToggleMapSuperSub() 241 | { 242 | style->mapsupersub=!style->mapsupersub; 243 | } 244 | void ToggleAvoidCombining() 245 | { 246 | style->avoidcombining=!style->avoidcombining; 247 | } 248 | 249 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | libtexprintf & utftex 2 | ===================== 3 | [![CI](https://github.com/bartp5/libtexprintf/workflows/CI/badge.svg)](https://github.com/bartp5/libtexprintf/actions?query=workflow%3ACI) 4 | 5 | The utftex program and underlying libtexprintf library provide tools to 6 | pretty print math in mono-space fonts, using a tex-like syntax. It 7 | produces UTF-8 encoded text. The program was inspired by 8 | [asciiTeX](http://asciitex.sourceforge.net/), and the improved 9 | [asciiTeX fork](https://github.com/larseggert/asciiTeX). However, 10 | utftex supports much more TeX syntax and contains extensive Unicode 11 | tables to map latex commands to Unicode symbols. Use 12 | libtexprintf/utftex to unlock the math capabilities of Unicode in 13 | mono-space text applications. 14 | 15 | Note that how the equations look depends strongly on the font you use. 16 | Naturally, one needs a monospace font with good Unicode support for the 17 | symbols you use. A good monospace font for math is, for example, 18 | [JuliaMono](https://juliamono.netlify.app/). 19 | 20 | libtexprintf 21 | ------------ 22 | The core library to pretty print math in mono-space font. Use it to 23 | enable your c or c++ code to print out formatted math. The calls are 24 | modeled after the printf family to produce formatted output. 25 | 26 | utftex 27 | ------ 28 | The utftex program uses libtexprinf to implement a command-line utility 29 | to format math. For example: 30 | 31 | > utftex '\frac{\alpha}{\beta+x}' 32 | gives 33 | 34 | α 35 | ─── 36 | β+x 37 | 38 | 39 | The texprintf library provides a fairly full featured tex-like syntax 40 | with arrays, brackets, many symbols, and even font style (note that 41 | texprintf outputs UTF-8 and as such cannot change the fonts. However, 42 | Unicode does provide several font-styles like mathematical calligraphic 43 | style, or italic). For example: 44 | 45 | > utftex -F mathnormal '\frac{1}{a+x}' 46 | gives 47 | 48 | 1 49 | ─── 50 | 𝑎+𝑥 51 | 52 | It also supports some diacritical combining marks, to do things like 53 | 54 | utftex '\vec x' 55 | to get 56 | 57 | x⃗. 58 | 59 | A bit more elaborate example is this small table of Laplace transforms: 60 | 61 | > utftex '\begin{array}{|l|l|} 62 | \hline 63 | f(t) & \mathscr{L}[f(t)]=F(s) \\\hline 64 | 1 & \frac{1}{s} \\\hline 65 | e^{at}f(t) & F(s-a) \\\hline 66 | \delta\left(t\right) & 1 \\\hline 67 | \delta\left(t-t_0\right) & e^{-st_0} \\\hline 68 | \int_0^t f(x)g(t-x)dx & F(s)G(s)\hline 69 | \end{array}' 70 | 71 | ┌────────────────┬──────────────┐ 72 | │f(t) │ 𝓛[f(t)]=F(s) │ 73 | ├────────────────┼──────────────┤ 74 | │ │ 1 │ 75 | │1 │ ─ │ 76 | │ │ s │ 77 | ├────────────────┼──────────────┤ 78 | │ at │ │ 79 | │e f(t) │ F(s-a) │ 80 | ├────────────────┼──────────────┤ 81 | │δ(t) │ 1 │ 82 | ├────────────────┼──────────────┤ 83 | │ │ -st │ 84 | │ │ 0 │ 85 | │δ⎛t-t ⎞ │ e │ 86 | │ ⎝ 0⎠ │ │ 87 | ├────────────────┼──────────────┤ 88 | │ t │ │ 89 | │⌠ │ │ 90 | │⎮ f(x)g(t-x)dx │ F(s)G(s) │ 91 | │⌡ │ │ 92 | │ 0 │ │ 93 | └────────────────┴──────────────┘ 94 | 95 | 96 | Note that if the table borders do not properly align you are not viewing 97 | the table in monospace fonts. 98 | 99 | utfstringinfo 100 | ------------- 101 | Utility to analyze UTF-8 strings. The utfstringinfo program reads 102 | arguments or, if no arguments are provided, stdin and for every single 103 | character it finds it shows the UTF-8 byte sequence, the Unicode 104 | code-point and, if applicable, the utftex command that can be used to 105 | generate the symbol. 106 | 107 | Software using libtexprintf/utftex 108 | ---------------------------------- 109 | Several projects use libtexprintf or utftex. Some projects that I am aware of are (in arbitrary order): 110 | 111 | * [LibTeXPrintf](https://github.com/JuliaStrings/LibTeXPrintf.jl): a 112 | wrapper around libtexprintf to use the library directly from the 113 | julia programming language 114 | * [kramdown-rfc](https://github.com/cabo/kramdown-rfc): (a backend for 115 | [kramdown](https://kramdown.gettalong.org/)) uses utftex to format 116 | latex equations 117 | * [utftex-gui](https://github.com/wpeaton/utftex-gui/): a simple 118 | graphical user interface to utftex (much like the gui that came with 119 | asciiTeX) 120 | * [utftexbot](https://github.com/LRDPRDX/utftexbot): a telegram bot to 121 | pretty print LaTeX 122 | * [render-markdown.nvim](https://github.com/MeanderingProgrammer/render-markdown.nvim): a markdown plugin for Neovim which can use utftex to format LaTeX 123 | equations 124 | 125 | Questions One Might Ask (QOMA) 126 | ------------------------------ 127 | 128 | * Why is my equation all misaligned? 129 | - Make sure you are using mono-space fonts. 130 | 131 | * I am using mono-space fonts, why are my equations still poorly aligned? 132 | - Most fonts do not support all Unicode characters. Your program 133 | may use some variable-width fallback fonts. 134 | 135 | * Why are some symbols are not displayed (properly)? 136 | - Most fonts do not support all Unicode characters. Perhaps your 137 | font engine just gave up? This also often happens when using 138 | combining diacritical marks. Find the right set of font engine 139 | and fonts to use. 140 | 141 | * Can you recommend a good mono-space symbol font? 142 | - Best is if the monospace font you use supports lots of symbols by 143 | itself. There are various fonts that support a great deal of 144 | Unicode. See for example 145 | [this discussion](https://stackoverflow.com/a/73313342/3662120). 146 | As mentioned before I recommend 147 | [JuliaMono](https://juliamono.netlify.app/). 148 | - Make your own out of your favorite (variable-space) fonts! The 149 | great "monospacifier" will do that for you. Get it at 150 | https://github.com/cpitclaudel/monospacifier 151 | 152 | * How do I specify the fallback fonts in ? 153 | - This will depend on your system and/or program you are using. If 154 | your system uses fontconfig you may try that to set up an 155 | appropriate mono-space fallback font. 156 | 157 | * How do I specify the fallback fonts in with fontconfig? 158 | - Let us assume you use some mono-space font called "MONO" and we 159 | have some symbol mono-space fallback font for it "SYMBOLMONO". 160 | Here are the steps: 161 | 1. Install all fonts (e.g. copy font files to 162 | ~/.local/share/fonts and run "fc-cache -f -v") 163 | 2. Then create a fontconfig file in 164 | ~/.config/fontconfig/fonts.conf 165 | It could look something like (replace the font names with the 166 | appropriate values): 167 | 168 | ``` 169 | 170 | 171 | 172 | 173 | monospace 174 | 175 | MONO 176 | SYMBOLMONO 177 | 178 | 179 | 180 | ``` 181 | 182 | 183 | -------------------------------------------------------------------------------- /src/utf2unicode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "stringutils.h" 6 | #include "lexer.h" 7 | #include "parsedef.h" 8 | #ifdef __MINGW32__ 9 | #include 10 | #endif 11 | /* lookup the unicode symbol in the latex symbol list to sort out the latex command */ 12 | PRSDEF LookupCombining_PRSDEF(unsigned int U) 13 | { 14 | int j=0; 15 | while (Combining[j].P!=PD_NONE) 16 | { 17 | if (Combining[j].comb==U) 18 | return Combining[j].P; 19 | j++; 20 | } 21 | return PD_NONE; 22 | } 23 | 24 | char * LookupCombiningName(PRSDEF P, int N) 25 | { 26 | int j=0, n=-1; 27 | while (Keys[j].name) 28 | { 29 | if (Keys[j].P==P) 30 | { 31 | n++; 32 | if (n==N) 33 | return Keys[j].name; 34 | } 35 | j++; 36 | } 37 | return NULL; 38 | } 39 | /* lookup the unicode symbol in the latex symbol list to sort out the latex command */ 40 | Symbol LookupSymbol(unsigned int U, int N) 41 | { 42 | int j=0, n=-1; 43 | while (Symbols[j].name) 44 | { 45 | if (Symbols[j].unicode==U) 46 | { 47 | n++; 48 | if (n==N) 49 | return Symbols[j]; 50 | } 51 | j++; 52 | } 53 | return Symbols[j]; 54 | } 55 | int main(int argc, char **argv) 56 | { 57 | int i, j, k, l,N; 58 | char *p, c; 59 | Symbol S; 60 | PRSDEF P; 61 | #ifdef __MINGW32__ 62 | UINT oldcp = GetConsoleOutputCP(); 63 | SetConsoleOutputCP(CP_UTF8); 64 | #endif 65 | p=Unicode2Utf8(0x25CC); /*dotted circle for combining marks */ 66 | if (argc==1) 67 | { 68 | char *buffer; 69 | int Na=50; 70 | char ch; 71 | buffer=malloc(Na*sizeof(char)); 72 | i=0; 73 | while(read(STDIN_FILENO, &ch, 1) > 0) 74 | { 75 | buffer[i++]=ch; 76 | if (i==Na) 77 | { 78 | Na+=50; 79 | buffer=realloc(buffer, Na*sizeof(char)); 80 | } 81 | } 82 | buffer[i]='\0'; 83 | printf("Input String:\n%s\n", buffer); 84 | j=strlen(buffer); 85 | printf("length in chars: %d\n", j); 86 | 87 | k=strlen(buffer); 88 | j=0; 89 | printf("Char\tUnicode\tUTF-8 texprintf\n"); 90 | while(j 2 | #include 3 | #include 4 | #include 5 | #include "unicodeblocks.h" 6 | #include "stringutils.h" 7 | #include "error.h" 8 | 9 | #define IsPrintable(C) iswprint((C)) 10 | 11 | int IsInSet(char c, const char *set) /* check whether char c in set */ 12 | { 13 | char *s; 14 | s=(char *)set; 15 | while (*s) 16 | { 17 | if ((*s)==c) 18 | return 1; 19 | s++; 20 | } 21 | return 0; 22 | 23 | } 24 | char * Unicode2Utf8(int U) /* convert unicode code point to an allocated and null teminated string (i.e. 5 bytes) */ 25 | { 26 | char *r, *b; 27 | r=calloc(5,sizeof(char)); 28 | b=r; 29 | if (U<0x80) 30 | *b++=U; 31 | else if (U<0x800) 32 | { 33 | *b++=192+U/64; 34 | *b++=128+U%64; 35 | } 36 | else if (U-0xd800u<0x800) 37 | { 38 | fprintf(stderr, "Invalid Unicode Code Point 0x%X\n", U); 39 | return r; 40 | } 41 | else if (U<0x10000) 42 | { 43 | *b++=224+U/4096; 44 | *b++=128+U/64%64; 45 | *b++=128+U%64; 46 | } 47 | else if (U<0x110000) 48 | { 49 | *b++=240+U/262144; 50 | *b++=128+U/4096%64; 51 | *b++=128+U/64%64; 52 | *b++=128+U%64; 53 | } 54 | else 55 | fprintf(stderr, "Invalid Unicode Code Point 0x%X\n", U); 56 | return r; 57 | } 58 | 59 | int NumByte(char *p) /* return the number of bytes of the multibyte char pointed to by p */ 60 | { 61 | int n=1; 62 | if (*p & 0x80) /* multibyte char */ 63 | { 64 | if ((*p & 0xF0) == 0xF0)/* 4-bytes */ 65 | n=4; 66 | else if ((*p & 0xE0) == 0xE0)/* 3-bytes */ 67 | n=3; 68 | else if ((*p & 0xC0) == 0xC0)/* 2-bytes */ 69 | n=2; 70 | } 71 | return n; 72 | } 73 | int UNumByte(int U) /* return the number of UTF-8 bytes for the unicode code point */ 74 | { 75 | if (U<0x80) 76 | return 1; 77 | if (U<0x800) 78 | return 2; 79 | if (U-0xd800u<0x800) 80 | { 81 | fprintf(stderr, "Invalid Unicode Code Point 0x%X\n", U); 82 | return 0; 83 | } 84 | if (U<0x10000) 85 | return 3; 86 | if (U<0x110000) 87 | return 4; 88 | return 0; 89 | } 90 | 91 | int Unicode(char *p, int *N)/* convert the UTF-8 char pointed to by p to unicode, if N is provided it will be set to the number of bytes of the character*/ 92 | { 93 | int u=0; 94 | int n; 95 | n=NumByte(p); 96 | if (N) 97 | *N=n; 98 | switch(n) 99 | { 100 | case 4: 101 | u=(int)(0x07&*p); 102 | n--; 103 | break; 104 | case 3: 105 | u=(int)(0x0F&*p); 106 | n--; 107 | break; 108 | case 2: 109 | u=(int)(0x1F&*p); 110 | n--; 111 | break; 112 | case 1: 113 | u=(int)(*p); 114 | n--; 115 | break; 116 | default: 117 | break; 118 | } 119 | while (n) 120 | { 121 | /* each subsequent byte contains 6 relevant bits */ 122 | p++; 123 | if ((*p&0xC0)!=0x80) 124 | return -1; 125 | u=(u<<6); 126 | u|=((int)(0x3F&*p)); 127 | n--; 128 | } 129 | return u; 130 | } 131 | 132 | int IsCombiningMark(int ch) /* check whether the unicode code point ch is a combining mark */ 133 | { 134 | int i=0; 135 | while (Combining[i].start>=0) 136 | { 137 | if ((ch>=Combining[i].start)&&(ch<=Combining[i].end)) 138 | return 1; 139 | i++; 140 | } 141 | return 0; 142 | } 143 | 144 | int WCSPACES=2; 145 | int FCSPACES=2; 146 | int IsWideChar(int ch) /* check whether the unicode code point ch is a wide character */ 147 | { 148 | int i=0; 149 | while (Wide[i].start>=0) 150 | { 151 | if ((ch>=Wide[i].start)&&(ch<=Wide[i].end)) 152 | return 1; 153 | i++; 154 | } 155 | return 0; 156 | } 157 | int IsFullChar(int ch) /* check whether the unicode code point ch is a full width character */ 158 | { 159 | int i=0; 160 | while (Full[i].start>=0) 161 | { 162 | if ((ch>=Full[i].start)&&(ch<=Full[i].end)) 163 | return 1; 164 | i++; 165 | } 166 | return 0; 167 | } 168 | 169 | 170 | int strspaces(char *p) /* count the number of character spaces in the string where each multibyte character counts as one and combining marks as 0 */ 171 | { 172 | int l=0; 173 | int n; 174 | int u; 175 | while(*p) 176 | { 177 | u=Unicode(p, &n); 178 | if (u<0) 179 | { 180 | fprintf(stderr, "Error, string is not proper UTF-8 code\n"); 181 | return 0; 182 | } 183 | if (!IsCombiningMark(u)) 184 | l++; 185 | if (IsWideChar(u)) 186 | l+=WCSPACES-1; 187 | if (IsFullChar(u)) /* we make wide characters two characters wide */ 188 | l+=FCSPACES-1; 189 | p+=n; 190 | } 191 | return l; 192 | } 193 | 194 | typedef struct { 195 | int point; 196 | int mapped; 197 | } UniMap; 198 | int Nmap=24; 199 | const UniMap Mappings[] = { 200 | /* some unicode codeblocks have gaps in em wile some symbols are defined in another block. 201 | * This table maps the gaps to the correct codepoint. */ 202 | {0x1D455, 0x210E}, /* Mathematical italic h */ 203 | {0x1D49D, 0x212C}, /* Mathematical Script B */ 204 | {0x1D4A0, 0x2130}, /* Mathematical Script E */ 205 | {0x1D4A1, 0x2131}, /* Mathematical Script F */ 206 | {0x1D4A3, 0x210B}, /* Mathematical Script H */ 207 | {0x1D4A4, 0x2110}, /* Mathematical Script I */ 208 | {0x1D4A7, 0x2112}, /* Mathematical Script L */ 209 | {0x1D4A8, 0x2133}, /* Mathematical Script M */ 210 | {0x1D4AD, 0x211B}, /* Mathematical Script R */ 211 | {0x1D4BA, 0x212F}, /* Mathematical Script e */ 212 | {0x1D4BC, 0x210A}, /* Mathematical Script g */ 213 | {0x1D4C4, 0x2134}, /* Mathematical Script o */ 214 | {0x1D506, 0x212D}, /* Mathematical Fraktur B */ 215 | {0x1D50B, 0x210C}, /* Mathematical Fraktur H*/ 216 | {0x1D50C, 0x2111}, /* Mathematical Fraktur I*/ 217 | {0x1D515, 0x211C}, /* Mathematical Fraktur R*/ 218 | {0x1D51D, 0x2128}, /* Mathematical Fraktur Z*/ 219 | {0x1D53A, 0x2102}, /* Mathematical double stroke capital C */ 220 | {0x1D53F, 0x210D}, /* Mathematical double stroke capital H */ 221 | {0x1D545, 0x2115}, /* Mathematical double stroke capital N */ 222 | {0x1D547, 0x2119}, /* Mathematical double stroke capital P */ 223 | {0x1D548, 0x211A}, /* Mathematical double stroke capital Q */ 224 | {0x1D549, 0x211D}, /* Mathematical double stroke capital R */ 225 | {0x1D551, 0x2124}, /* Mathematical double stroke capital Z */ 226 | }; 227 | 228 | int MapU(int in, const UniMap M[], int N) 229 | { 230 | int i, min=0, max=N-1; 231 | do 232 | { 233 | i=(min+max)/2; 234 | if (M[i].point==in) 235 | return M[i].mapped; 236 | else if (M[i].point1); 241 | if (M[min].point==in) 242 | return M[min].mapped; 243 | if (M[max].point==in) 244 | return M[max].mapped; 245 | return in; 246 | } 247 | 248 | char * UnicodeMapper(char *in) 249 | { 250 | char *out; 251 | char *p, *u; 252 | int na=2*strlen(in), len, pos=0; 253 | int Nin, Nout, U, Um; 254 | if (!in) 255 | return NULL; 256 | out=malloc(na*sizeof(char)); 257 | p=in; 258 | len=strlen(in); 259 | while (*p) 260 | { 261 | U=Unicode(p, &Nin); 262 | p+=Nin; 263 | 264 | Um=MapU(U,Mappings,Nmap); 265 | if (U!=Um) 266 | { 267 | u=Unicode2Utf8(Um); 268 | Unicode(u, &Nout); 269 | len+=(Nout-Nin); 270 | Nin=Nout; 271 | if (len>na) 272 | { 273 | na=len+10; 274 | out=realloc(out,na*sizeof(char)); 275 | } 276 | } 277 | else 278 | u=Unicode2Utf8(Um); 279 | strcpy(out+pos,u); 280 | pos+=Nin; 281 | free(u); 282 | } 283 | return out; 284 | } 285 | 286 | 287 | /* map sub/super scripts 288 | */ 289 | typedef struct { 290 | const char *c; // quick search whether the character is mappable 291 | const int N; 292 | const UniMap Map[]; // map table 293 | } MapScriptTable; 294 | 295 | MapScriptTable SuperScriptMap = { 296 | "231hjrwylsxABDEGHIJKLMNOPRTUWabdegkmoptuvcfz0i456789+-=()nV! ", // note we add a space 297 | 60, 298 | { 299 | {0x00021,0x0A71D}, 300 | {0x00028,0x0207D}, 301 | {0x00029,0x0207E}, 302 | {0x0002B,0x0207A}, 303 | {0x0002D,0x0207B}, 304 | {0x00030,0x02070}, 305 | {0x00031,0x000B9}, // 1 -> ¹ 306 | {0x00032,0x000B2}, // 2 -> ² 307 | {0x00033,0x000B3}, // 3 -> ³ 308 | {0x00034,0x02074}, 309 | {0x00035,0x02075}, 310 | {0x00036,0x02076}, 311 | {0x00037,0x02077}, 312 | {0x00038,0x02078}, 313 | {0x00039,0x02079}, 314 | {0x0003D,0x0207C}, 315 | {0x00041,0x01D2C}, 316 | {0x00042,0x01D2E}, 317 | {0x00044,0x01D30}, 318 | {0x00045,0x01D31}, 319 | {0x00047,0x01D33}, 320 | {0x00048,0x01D34}, 321 | {0x00049,0x01D35}, 322 | {0x0004A,0x01D36}, 323 | {0x0004B,0x01D37}, 324 | {0x0004C,0x01D38}, 325 | {0x0004D,0x01D39}, 326 | {0x0004E,0x01D3A}, 327 | {0x0004F,0x01D3C}, 328 | {0x00050,0x01D3E}, 329 | {0x00052,0x01D3F}, 330 | {0x00054,0x01D40}, 331 | {0x00055,0x01D41}, 332 | {0x00056,0x02C7D}, 333 | {0x00057,0x01D42}, 334 | {0x00061,0x01D43}, 335 | {0x00062,0x01D47}, 336 | {0x00063,0x01D9C}, 337 | {0x00064,0x01D48}, 338 | {0x00065,0x01D49}, 339 | {0x00066,0x01DA0}, 340 | {0x00067,0x01D4D}, 341 | {0x00068,0x002B0}, 342 | {0x00069,0x02071}, 343 | {0x0006A,0x002B2}, 344 | {0x0006B,0x01D4F}, 345 | {0x0006C,0x002E1}, 346 | {0x0006D,0x01D50}, 347 | {0x0006E,0x0207F}, 348 | {0x0006F,0x01D52}, 349 | {0x00070,0x01D56}, 350 | {0x00072,0x002B3}, 351 | {0x00073,0x002E2}, 352 | {0x00074,0x01D57}, 353 | {0x00075,0x01D58}, 354 | {0x00076,0x01D5B}, 355 | {0x00077,0x002B7}, 356 | {0x00078,0x002E3}, 357 | {0x00079,0x002B8}, 358 | {0x0007A,0x01DBB}, 359 | } 360 | }; 361 | 362 | MapScriptTable SubScriptMap = { 363 | "iruv0123456789+-=()aeoxhklmnpstj ",// note we add a space 364 | 32, 365 | { 366 | {0x00028,0x0208D}, 367 | {0x00029,0x0208E}, 368 | {0x0002B,0x0208A}, 369 | {0x0002D,0x0208B}, 370 | {0x00030,0x02080}, 371 | {0x00031,0x02081}, 372 | {0x00032,0x02082}, 373 | {0x00033,0x02083}, 374 | {0x00034,0x02084}, 375 | {0x00035,0x02085}, 376 | {0x00036,0x02086}, 377 | {0x00037,0x02087}, 378 | {0x00038,0x02088}, 379 | {0x00039,0x02089}, 380 | {0x0003D,0x0208C}, 381 | {0x00061,0x02090}, 382 | {0x00065,0x02091}, 383 | {0x00068,0x02095}, 384 | {0x00069,0x01D62}, 385 | {0x0006A,0x02C7C}, 386 | {0x0006B,0x02096}, 387 | {0x0006C,0x02097}, 388 | {0x0006D,0x02098}, 389 | {0x0006E,0x02099}, 390 | {0x0006F,0x02092}, 391 | {0x00070,0x0209A}, 392 | {0x00072,0x01D63}, 393 | {0x00073,0x0209B}, 394 | {0x00074,0x0209C}, 395 | {0x00075,0x01D64}, 396 | {0x00076,0x01D65}, 397 | {0x00078,0x02093}, 398 | } 399 | }; 400 | 401 | int MappableScript(char *script, MapScriptTable *S) 402 | { 403 | char *p; 404 | int r=1; 405 | p=script; 406 | while ((*p)&&(r)) 407 | { 408 | r*=IsInSet(*p,S->c); 409 | p++; 410 | } 411 | return r; 412 | } 413 | 414 | char *MapScript(char *script, MapScriptTable *S) 415 | { 416 | char *out; 417 | char *p, *u; 418 | int na=2*strlen(script), len, pos=0; 419 | int Nin, Nout, U, Um; 420 | out=malloc((na+1)*sizeof(char)); 421 | p=script; 422 | len=strlen(script); 423 | while (*p) 424 | { 425 | U=Unicode(p, &Nin); 426 | p+=Nin; 427 | 428 | Um=MapU(U,S->Map,S->N); 429 | if (U!=Um) 430 | { 431 | u=Unicode2Utf8(Um); 432 | Unicode(u, &Nout); 433 | len+=(Nout-Nin); 434 | Nin=Nout; 435 | if (len>na) 436 | { 437 | na=len+10; 438 | out=realloc(out,(na+1)*sizeof(char)); 439 | } 440 | } 441 | else 442 | u=Unicode2Utf8(Um); 443 | strcpy(out+pos,u); 444 | pos+=Nin; 445 | free(u); 446 | } 447 | return out; 448 | } 449 | 450 | int MappableSuper(char *super) 451 | { 452 | return MappableScript(super, &SuperScriptMap); 453 | } 454 | char *MapSuperScript(char *super) 455 | { 456 | return MapScript(super, &SuperScriptMap); 457 | } 458 | int MappableSub(char *sub) 459 | { 460 | return MappableScript(sub, &SubScriptMap); 461 | } 462 | char *MapSubScript(char *sub) 463 | { 464 | return MapScript(sub, &SubScriptMap); 465 | } 466 | -------------------------------------------------------------------------------- /src/utftex.1: -------------------------------------------------------------------------------- 1 | .TH utftex 1 "05 Jul 2022" 2 | .SH NAME 3 | utftex \- An UTF-8 unicode equation renderer 4 | .SH SYNOPSIS 5 | .B utftex 6 | .I [options] [equation] ... 7 | .SH DESCRIPTION 8 | The aim of utftex is to use the possibilities unicode provides to display math in simple UTF-8 encoded text. 9 | utftex renders mathematical equations in mono-space unicode characters, i.e. unicode-art. It is intended 10 | to insert equations in source code, e-mails, and man-pages. It generally works without introducing additional 11 | dependencies as most text editors and e-mail programs already support UTF-8 encoding out of the box. 12 | 13 | Unicode provides many code-points which are intended for mathematical expressions. It even supplies some 14 | characters which are intended to "draw" math such as the top (⌠) and bottom (⌡) of an integral symbol. This way 15 | you can draw an integral symbol such as this: 16 | .br 17 | ⌠ 18 | .br 19 | ⎮ 20 | .br 21 | ⌡ 22 | .br 23 | 24 | .B utftex 25 | uses an (ASCII or UTF-8 encoded) input with a syntax similar to LaTeX and outputs an UTF-8 encoded text. 26 | 27 | .SH OPTIONS 28 | All arguments are optional. 29 | If no arguments are passed utftex will read one equation from stdin. 30 | .br 31 | 32 | .B [equation] 33 | .br 34 | Each [equation] argument is parsed as one latex equation (i.e. more than one equation may be passed). 35 | 36 | .B [--line-width -l] 37 | .br 38 | Define the output line width. If it is 0 the line width is unlimited (default). This causes utftex to insert line breaks 39 | at suitable places to divide the expression over multiple lines. It is not guaranteed that suitable locations are found 40 | to insert line breaks and thus the actual line length may exceed the specified one. 41 | 42 | .B [--symbol-list -s] 43 | .br 44 | List all symbols supported by this version of utftex. Supported in this case means that an input command exists to 45 | generate the symbol as output, e.g. \ealpha as input generates α as output 46 | 47 | .B [--test-texsymbols -T] 48 | .br 49 | Same as above (list all symbols) in a more machine readable format. 50 | 51 | .B [--version -v] 52 | .br 53 | Print utftex and libtexprintf versions. 54 | 55 | .B [--show-input -i] 56 | .br 57 | Print input before the rendered results. 58 | 59 | .B [--wchar-width -w] 60 | .br 61 | Specify the size of wide characters. Valid sizes are 1 and 2. Default is 2. 62 | 63 | .B [--fchar-width -f] 64 | .br 65 | Specify the size of full width characters. Valid sizes are 1 and 2. Default is 2. 66 | 67 | .B [--default-font -F] 68 | .br 69 | Specify the default font style to use. See the Fonts below. The font names correspond to the font commands minus the slash and the argument. 70 | e.g. one could pass "-F mathnormal". Without this option the default font is set to "text" as not all fonts support the other font styles. 71 | 72 | .B [--test-fonts -t] 73 | .br 74 | Print table with chacters in various styles. 75 | 76 | .B [--test-stexprintf -S] 77 | .br 78 | 79 | .B [--box-tree -B] 80 | .br 81 | Print box structure (for debugging purposes) 82 | 83 | .B [--ascii -A] 84 | .br 85 | Try to stick to ASCII characters. This affects all "drawing" characters used for integral signs, brackets, fractions, and tables. 86 | It does not affect symbols like \alpha (The user can avoid those, and there is no ASCII equivalent for \alpha). 87 | 88 | .B [--combine-errors -E] 89 | .br 90 | Combines error messages in a semicolon delimited string. 91 | 92 | .B [--mapsupersub -m] 93 | .br 94 | Turns on or off sub/super script mapping (mapping of sub/super scripts to corresponding unicode code points for sub/super script symbols). 95 | 96 | .B [--avoidcombining -a] 97 | .br 98 | Per default utftex tries to use combining diacritical marks for accents whenever possible. This toggle swhich will change this in trying 99 | to avoid combining characters unless no alternative is available. 100 | 101 | .B [--end-options -e] 102 | .br 103 | Ends the option parser (allows to pass equations starting with a minus). 104 | 105 | .SH SYNTAX 106 | 107 | .B Fonts: 108 | Unicode defines various font styles which may be accessed with utftex. For this the following commands are available 109 | .br 110 | .B \emathsfbfit{...}\t 111 | Mathematical sans-serif bold italic fonts 112 | .br 113 | .B \emathsfbf{...}\t\t 114 | Mathematical sans-serif bold fonts 115 | .br 116 | .B \emathfrak{...}\t\t 117 | Fraktur caligraphic script 118 | .br 119 | .B \emathbfit{...}\t\t 120 | Mathematical serif bold italic fonts 121 | .br 122 | .B \emathsfit{...}\t\t 123 | Mathematical sans-serif italic fonts 124 | .br 125 | .B \emathcal{...}\t\t 126 | Mathematical caligraphic fonts 127 | .br 128 | .B \emathscr{...}\t\t 129 | Euler script fonts 130 | .br 131 | .B \emathbf{...}\t\t 132 | Mathematical serif bold fonts 133 | .br 134 | .B \emathbb{...}\t\t 135 | Mathematical black-board bold fonts 136 | .br 137 | .B \emathsf{...}\t\t 138 | Mathematical sans-serif fonts 139 | .br 140 | .B \emathtt{...}\t\t 141 | Mathematical typewriter fonts 142 | .br 143 | .B \emathnormal{...}\t 144 | Normal Mathematical fonts 145 | .br 146 | .B \etext{...}\t\t 147 | Roman fonts (plain font style) 148 | .br 149 | .B \eit\t\t\t\t 150 | Switch current block to italic fonts 151 | .br 152 | .B \ebf\t\t\t\t 153 | Switch current block to bold fonts 154 | .br 155 | .B \erm\t\t\t\t 156 | Switch current block to roman fonts 157 | .br 158 | 159 | .B commands to insert symbols, special characters, and operators 160 | .br 161 | There is a large set of symbols that may be inserted with the usual (or sometimes less usual) LaTeX commands. 162 | You can list the available symbols and corresponding commands by running 163 | .B utftex 164 | with the --symbol-list option 165 | 166 | .B \efrac{a}{b}, a\eover b 167 | .br 168 | A fraction of a and b. 169 | 170 | .B a^{b} 171 | .br 172 | super-script 173 | One can also omit the braces. 174 | In this case the first character following ^ will be in super-scripted. 175 | 176 | .B a_{b} 177 | .br 178 | sub-script 179 | Works just like super-script only now it is a sub-script. 180 | 181 | .B \esqrt[n]{a} 182 | .br 183 | A n-th root of a, the argument [n] is optional. 184 | Without it it produces the square root of a. Note that these commands draw a variable size 185 | radix. The unicode radix signs (one character sized) are available as \eutfsqrt \eutfsqrt[3] and \eutfsqrt[4] 186 | 187 | .B \esum 188 | .br 189 | Expands to a large sigma symbol. The unicode sum symbol can be generated using \eutfsum. 190 | 191 | .B \eprod 192 | .br 193 | Expands to the product symbol. The unicode product symbol can be generated using \eutfprod. 194 | 195 | 196 | .B \eint[S] 197 | .br 198 | Expands to the integral symbol. The optional argument [S] makes the symbol scale with the height of the integrand. The 199 | unicode integral symbol can be generated using \eutfint. 200 | 201 | 202 | .B \eiint[S] 203 | .br 204 | Expands to a double integral symbol. The optional argument [S] makes the symbol scale with the height of the integrand. The 205 | unicode double integral symbol can be generated using \eutfiint. 206 | 207 | .B \eiiint[S] 208 | .br 209 | Expands to a triple integral symbol. The optional argument [S] makes the symbol scale with the height of the integrand. The 210 | unicode triple integral symbol can be generated using \eutfiint. 211 | 212 | .B \eiiiint[S] 213 | .br 214 | Expands to a quadruple integral symbol. The optional argument [S] makes the symbol scale with the height of the integrand. The 215 | unicode quadruple integral symbol can be generated using \eutfiint. 216 | 217 | .B \eidotsint[S] 218 | .br 219 | Expands to two integral symbols with dots in between. The optional argument [S] makes the symbol scale with the height of the integrand. 220 | 221 | .B \eoint[S] 222 | .br 223 | A contour integral. The optional argument [S] makes the symbol scale with the height of the integrand. 224 | 225 | .B \eoiint[S] 226 | .br 227 | A double contour integral. The optional argument [S] makes the symbol scale with the height of the integrand. 228 | 229 | .B \eoiiint[S] 230 | .br 231 | A tripple contour integral. The optional argument [S] makes the symbol scale with the height of the integrand. 232 | 233 | .B \eoiiiint[S] 234 | .br 235 | A quadruple contour integral. The optional argument [S] makes the symbol scale with the height of the integrand. 236 | 237 | .B \eoidotsint[S] 238 | .br 239 | Expands to two contour integral symbols with dots in between. The optional argument [S] makes the symbol scale with the height of the integrand. 240 | 241 | .B \eleft 242 | , 243 | .B \emiddle 244 | , 245 | .B \eright 246 | .br 247 | Creates variable sized delimiters around and in between content. 248 | Available variable size delimiters are: 249 | .br 250 | .B ( ), [ ], { }, < >, |, 251 | .br 252 | .B \euparrow, \eUparrow, \edownarrow, \eDownarrow, \eupdownarrow, \eUpdownarrow , 253 | .br 254 | .B \elceil \erceil, \elfloor \erfloor, 255 | .br 256 | .B/ \ebackslash. 257 | .br 258 | The \emiddle command is optional and may be omitted. The special dot (.) delimiter is a dummy delimiter that can be used to open 259 | or close a \eleft ... \eright construct without a delimiter being shown. 260 | 261 | .B \elim 262 | .br 263 | Expands to a limit, i.e. \elim_{x \eto 0}. 264 | 265 | .B \eoverline{X}, \ebar{X} 266 | .br 267 | Draws a line above expression X 268 | 269 | .B \eunderline{X} 270 | .br 271 | Draws a line under expression X 272 | 273 | .B \e\e 274 | .br 275 | Insert a line break. 276 | 277 | .B \e 278 | .br 279 | Escapes the character. 280 | 281 | .B \elimits 282 | .br 283 | Controls the placements of sub and superscripts. Normally the sub and superscripts are places to 284 | the left of its arguments. Using limits you can change this to centered below and above its argument, 285 | e.g. \eint\elimits_a^b 286 | 287 | .B \ebox{W}{H} 288 | .br 289 | Makes an empty box which is W characters wide and H characters high. This may be used to adjust spacing 290 | 291 | .B \eraisebox{off}{...} 292 | .br 293 | Makes a box and raises its contents by off characters 294 | 295 | .B \ephantom{...} 296 | .br 297 | Makes an empty box with the same width and height as its rendered argument would have. 298 | 299 | .B \evphantom{...} 300 | .br 301 | Makes an empty box with 0 width and the same height as its rendered argument would have. 302 | 303 | .B \ehphantom{...} 304 | .br 305 | Makes an empty box with 0 height and the same width as its rendered argument would have. 306 | 307 | .B \eover 308 | .br 309 | Alternative way of making a fraction, e.g. "a \eover b". 310 | 311 | .B \echoose 312 | .br 313 | Alternative way of making a binominal, e.g. "n \echoose k". 314 | 315 | 316 | .B \eexp, \eln, \elog, \emin, \emax, \esin, \ecos, \etan, \ecot, \earcsin, \earccos, \earctan, \earccot, \esinh, \ecosh, \etanh, \ecoth, \esec, \ecsc 317 | .br 318 | Functions (function names are formatted in normal text fonts) 319 | 320 | .B Environments 321 | .br 322 | Several array-like environments are available. The most general form is the array environment 323 | .br 324 | .B \ebegin{array}[pos]{column alignments} 325 | .br 326 | .I 327 | a00 & a01 & ... a0n \e\e 328 | .br 329 | a10 & a11 & ... a1n \e\e 330 | .br 331 | ... & ... & ... ... \e\e 332 | .br 333 | am0 & am1 & ... amn 334 | .br 335 | .B \eend{array} 336 | .br 337 | Makes an array. 338 | The optional argument pos sets the alignment of the array to t(op), b(ottom) or c(enter). 339 | The column alignments consist of one character per column, l(eft), c(enter), or r(ight). 340 | Horizontal lines may be inserted with a \ehline command. Vertical lines may be inserted 341 | by inserting |'s in the column alignment argument (as with LaTeX). 342 | .br 343 | .br 344 | Several derived environments are provided. 345 | .br 346 | .B \ebegin{aligned} 347 | .br 348 | .B \eend{aligned} 349 | .br 350 | and 351 | .br 352 | .B \ebegin{align} 353 | .br 354 | .B \eend{align} 355 | .br 356 | to align equiations. 357 | .br 358 | 359 | .B \ebegin{cases} 360 | .br 361 | .B \eend{cases} 362 | .br 363 | Equivalent to \eleft{\ebegin{array}{c...c} ...\eend{array}\eright. 364 | .br 365 | .br 366 | 367 | .B \ebegin{pmatrix} 368 | .br 369 | .B \eend{pmatrix} 370 | .br 371 | Equivalent to \eleft(\ebegin{array}{c...c} ...\eend{array}\eright) 372 | .br 373 | .br 374 | 375 | .B \ebegin{vmatrix} 376 | .br 377 | .B \eend{vmatrix} 378 | .br 379 | Equivalent to \eleft|\ebegin{array}{c...c} ...\eend{array}\eright| 380 | .br 381 | .br 382 | 383 | .B \ebegin{bmatrix} 384 | .br 385 | .B \eend{bmatrix} 386 | .br 387 | Equivalent to \eleft[\ebegin{array}{c...c} ...\eend{array}\eright] 388 | .br 389 | .br 390 | 391 | .B \ebegin{Bmatrix} 392 | .br 393 | .B \eend{Bmatrix} 394 | .br 395 | Equivalent to \eleft{\ebegin{array}{c...c} ...\eend{array}\eright} 396 | .br 397 | .br 398 | 399 | .B \ebegin{matrix} 400 | .br 401 | .B \eend{matrix} 402 | .br 403 | Equivalent to \ebegin{array}{c...c} ...\eend{array} 404 | .br 405 | 406 | .SH A NOTE ON FONTS 407 | .B utftex 408 | depends on mono-space fonts. If your equations are all misaligned make sure you use a mono-space fonts. If you do specify a mono-spaced font, 409 | be aware that most fonts do not support all defined unicode code-points. When a font does not provide a requested unicode code-point your 410 | program/system may use a fall-back font or simply not display the character properly. This could also mean your math will still get misaligned, 411 | despite using a monospace font, if the fall-back font is not mono-spaced. In this case make sure the fall-back font is mono-spaced and that the 412 | spacing matches that of your primary font. I recommend "monospacifier" to generate an appropriate fall-back font for your primary font. 413 | Get it at 414 | .br 415 | .B https://github.com/cpitclaudel/monospacifier 416 | 417 | .SH A NOTE ON COMBINING DIACRITICAL MARKS 418 | .B utftex 419 | provides commands to insert combining diacritical marks, e.g. \ehat for the Combining Circumflex Accent. In principle this system is great but 420 | due to limitations in layout engine and/or the used fonts such combining characters do not always display properly and various glitches in 421 | display may be the result. 422 | 423 | .SH EXAMPLES 424 | If the following equations do not render properly make sure you read and understood the section "A NOTE ON FONTS". 425 | .B A simple fraction: 426 | .nf 427 | utftex "\efrac{1}{1+x}" 428 | 1 429 | ─── 430 | 1+x 431 | 432 | .fi 433 | .B An arbitrary equation with the mathnormal font as default: 434 | .nf 435 | utftex -F mathnormal '\elfloor x\erfloor = x - \efrac{1}{2} + \esum_{k=1}^{\einfty} 436 | \efrac{\esin(2 \epi k x)}{\epi k}' 437 | ∞ 438 | 1 ⎲ sin(2 π𝑘 𝑥) 439 | ⌊𝑥⌋ = 𝑥 - ─ + ⎳ ─────────── 440 | 2 𝑘=1 π𝑘 441 | 442 | .fi 443 | .B A small table of Laplace transforms: 444 | .nf 445 | utftex '\ebegin{array}{|l|l|} 446 | \ehline 447 | f(t) & \emathscr{L}[f(t)]=F(s) \e\e\ehline 448 | 1 & \efrac{1}{s} \e\e\ehline 449 | e^{at}f(t) & F(s-a) \e\e\ehline 450 | \edelta(t) & 1 \e\e\ehline 451 | \edelta(t-t_0) & e^{-st_0} \e\e\ehline 452 | \eint_0^t f(x)g(t-x)dx & F(s)G(s) \ehline 453 | \eend{array}' 454 | ┌────────────────┬──────────────┐ 455 | │f(t) │ 𝓛[f(t)]=F(s) │ 456 | ├────────────────┼──────────────┤ 457 | │ │ 1 │ 458 | │1 │ ─ │ 459 | │ │ s │ 460 | ├────────────────┼──────────────┤ 461 | │ at │ │ 462 | │e f(t) │ F(s-a) │ 463 | ├────────────────┼──────────────┤ 464 | │δ(t) │ 1 │ 465 | ├────────────────┼──────────────┤ 466 | │ │ -st │ 467 | │ │ 0 │ 468 | │δ(t-t ) │ e │ 469 | │ 0 │ │ 470 | ├────────────────┼──────────────┤ 471 | │ t │ │ 472 | │⌠ │ │ 473 | │⎮ f(x)g(t-x)dx │ F(s)G(s) │ 474 | │⌡ │ │ 475 | │ 0 │ │ 476 | └────────────────┴──────────────┘ 477 | .fi 478 | .SH AUTHOR 479 | Bart Pieters 480 | .SH LICENSE 481 | GNU GENERAL PUBLIC LICENSE Version 3 482 | .SH VERSION 483 | 1.0 484 | .SH SEE ALSO 485 | .B 486 | 487 | -------------------------------------------------------------------------------- /src/boxes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "boxes.h" 4 | #include "stringutils.h" 5 | #include "error.h" 6 | 7 | box InitBox(box *parent, boxtype T, void *content) 8 | { 9 | box b; 10 | b.parent=parent; 11 | if (parent) 12 | parent->Nc++; 13 | 14 | b.child=NULL; 15 | b.Nc=0; 16 | b.X=CENTER; 17 | b.Y=CENTER; 18 | b.S=INIT; 19 | b.T=T; 20 | b.content=content; 21 | b.rx=0; 22 | b.ry=0; 23 | b.ax=0; 24 | b.ay=0; 25 | b.w=0; 26 | b.h=0; 27 | b.xc=0; 28 | b.yc=0; 29 | if (T==B_DUMMY) 30 | { 31 | b.w=((int *)content)[0]; 32 | b.h=((int *)content)[1]; 33 | b.S=SIZEKNOWN; 34 | } 35 | if (T==B_ENDLINE) 36 | { 37 | b.w=0; 38 | b.h=0; 39 | b.S=SIZEKNOWN; 40 | } 41 | return b; 42 | } 43 | 44 | void AddChild(box * parent, boxtype T, void *content) 45 | { 46 | if (!parent->child) 47 | parent->child=malloc(sizeof(box)); 48 | else 49 | parent->child=realloc(parent->child, (parent->Nc+1)*sizeof(box)); 50 | parent->child[parent->Nc]=InitBox(parent, T, content); 51 | } 52 | 53 | void FreeBox(box *b) 54 | { 55 | int i; 56 | if (b->Nc) 57 | { 58 | for (i=0;iNc;i++) 59 | FreeBox(b->child+i); 60 | free(b->child); 61 | } 62 | 63 | free(b->content); 64 | } 65 | 66 | 67 | int BoxInBox(box *b, boxtype T, void *content) 68 | { 69 | /* wraps the box b (not the root) into another box os specified type and content */ 70 | /* i.e. after running box in box a new box is created where b used to be and b becomes the (single) child of this box */ 71 | box c; 72 | int i; 73 | 74 | if (!b->parent) 75 | { 76 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 77 | // ERRORFLAG ERRBOXINBOX "BoxInBox cannot take the root box as an agument" 78 | AddErr(ERRBOXINBOX); 79 | return 1; 80 | } 81 | c=*b; 82 | b->Nc=1; 83 | b->child=malloc(sizeof(box)); 84 | 85 | c.parent=b; 86 | b->child[0]=c; 87 | for (i=0;ichild[0].child[i].parent=b->child; 89 | 90 | b->S=INIT; 91 | b->X=CENTER; 92 | b->Y=CENTER; 93 | b->T=T; 94 | b->content=content; 95 | b->rx=0; 96 | b->ry=0; 97 | b->ax=0; 98 | b->ay=0; 99 | b->w=0; 100 | b->h=0; 101 | b->xc=0; 102 | b->yc=0; 103 | return 0; 104 | } 105 | 106 | boxstate StateBoxtree(box *b, box **minstate) 107 | { 108 | int i; 109 | box *ms=b; 110 | boxstate S; 111 | boxstate SUB; 112 | S=b->S; 113 | if (minstate) 114 | (*minstate)=b; 115 | for (i=0;iNc;i++) 116 | { 117 | SUB=StateBoxtree(b->child+i, &ms); 118 | if (SUB<=S) 119 | { 120 | S=SUB; 121 | if (minstate) 122 | (*minstate)=ms; 123 | } 124 | } 125 | return S; 126 | 127 | } 128 | 129 | box *FindBoxAtPos(box *b, int x, int y) 130 | { 131 | if (b->S==ABSPOSKNOWN) 132 | { 133 | /* go to level where the coordinate is contained in the box */ 134 | while ((b->parent)&&((xax)||(x>=b->ax+b->w)||(yay)||(y>=b->ay+b->h))) 135 | b=b->parent; 136 | 137 | if ((xax)||(x>=b->ax+b->w)||(yay)||(y>=b->ay+b->h)) 138 | return NULL; 139 | 140 | while (b->Nc) /* as long as we have children */ 141 | { 142 | int i=0, f=0; 143 | while (iNc) 144 | { 145 | if (!((xchild[i].ax)||(x>=b->child[i].ax+b->child[i].w)||(ychild[i].ay)||(y>=b->child[i].ay+b->child[i].h))) 146 | { 147 | b=b->child+i; 148 | if (b->T!=B_DUMMY) /* a dummy box is like no box */ 149 | f=1; 150 | break; /* found a box containing the coordinate */ 151 | } 152 | i++; 153 | } 154 | if (f==0) 155 | return NULL; /* no unit box containing this coordinate */ 156 | } 157 | return b; 158 | 159 | } 160 | else 161 | { 162 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 163 | // ERRORFLAG ERRBOXATPOS "Box positions unknown in FindBoxAtPos" 164 | AddErr(ERRBOXATPOS); 165 | return NULL; 166 | } 167 | } 168 | 169 | 170 | 171 | int UnitBoxSize(box *b) 172 | { 173 | if (b->T!=B_UNIT) 174 | { 175 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 176 | // ERRORFLAG ERRUBOXSIZE "Call of UnitBoxSize on something not a unit box" 177 | AddErr(ERRUBOXSIZE); 178 | return 1; 179 | } 180 | if (b->Scontent; 184 | b->w=strspaces(str); 185 | b->h=1; 186 | switch(b->X) 187 | { 188 | case MAX: 189 | b->xc=b->w; 190 | break; 191 | case MIN: 192 | b->xc=0; 193 | break; 194 | case CENTER: 195 | b->xc=(b->w-1)/2; 196 | break; 197 | default: 198 | break; 199 | } 200 | b->yc=0; 201 | b->S=SIZEKNOWN; 202 | } 203 | return 0; 204 | } 205 | 206 | 207 | int ArrayBoxSize(box *b) 208 | { 209 | int i, r, c, Nc, Nr, *h, *w, *xc, *yc, *rx, *ry; 210 | int *content; 211 | 212 | if (b->T!=B_ARRAY) 213 | { 214 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 215 | // ERRORFLAG ERRABOXSIZE "Call of ArrayBoxSize on something not an array box" 216 | AddErr(ERRABOXSIZE); 217 | return 1; 218 | } 219 | /* first compute all sizes of all children boxes */ 220 | if (BoxSize_children(b)) 221 | return 1; 222 | 223 | /* Sizes of all children are known, now align the children */ 224 | /* fetch number of columns from the content blob */ 225 | content=(int *)b->content; 226 | Nc=content[0]; 227 | 228 | if (Nc<=0) 229 | { 230 | Nr=1; 231 | Nc=b->Nc; 232 | } 233 | else /* number of rows: */ 234 | Nr=b->Nc/Nc+(b->Nc%Nc>0); 235 | 236 | /* allocate row and column heights, widths respectively */ 237 | h=calloc(Nr,sizeof(int)); 238 | yc=calloc(Nr,sizeof(int)); 239 | w=calloc(Nc,sizeof(int)); 240 | xc=calloc(Nc,sizeof(int)); 241 | ry=calloc(Nr,sizeof(int)); 242 | rx=calloc(Nc,sizeof(int)); 243 | 244 | 245 | for (i=0;iNc;i++) 246 | { 247 | int m; 248 | c=i%Nc; 249 | r=i/Nc; 250 | 251 | /* upper half of the box */ 252 | m=(b->child[i].h-b->child[i].yc); 253 | if (m>h[r]-yc[r]) 254 | h[r]+=m-h[r]+yc[r]; 255 | 256 | 257 | /* lower half of the box */ 258 | m=(b->child[i].yc); 259 | if (m>yc[r]) 260 | { 261 | /* height increases along with the baseline */ 262 | h[r]+=m-yc[r]; 263 | yc[r]+=m-yc[r]; 264 | } 265 | 266 | /* right half of the box */ 267 | m=(b->child[i].w-b->child[i].xc); 268 | if (m>w[c]-xc[c]) 269 | w[c]+=m-w[c]+xc[c]; 270 | 271 | 272 | /* left half of the box */ 273 | m=(b->child[i].xc); 274 | if (m>xc[c]) 275 | { 276 | /* height increases along with the baseline */ 277 | w[c]+=m-xc[c]; 278 | xc[c]+=m-xc[c]; 279 | } 280 | } 281 | for (i=1;i=0;i--) 284 | ry[i]=ry[i+1]+h[i+1]; 285 | b->w=rx[Nc-1]+w[Nc-1]; 286 | b->h=ry[0]+h[0]; 287 | b->S=SIZEKNOWN; 288 | switch(b->X) 289 | { 290 | case MAX: 291 | b->xc=b->w; 292 | break; 293 | case MIN: 294 | b->xc=0; 295 | break; 296 | case CENTER: 297 | b->xc=(b->w-1)/2; 298 | break; 299 | default: 300 | break; 301 | } 302 | switch(b->Y) 303 | { 304 | case MAX: 305 | b->yc=b->h; 306 | break; 307 | case MIN: 308 | b->yc=0; 309 | break; 310 | case CENTER: 311 | b->yc=(b->h-1)/2; 312 | break; 313 | default: 314 | break; 315 | } 316 | 317 | /* propagate the x an y positions of the boxes */ 318 | 319 | for (i=0;iNc;i++) 320 | { 321 | c=i%Nc; 322 | r=i/Nc; 323 | b->child[i].ry=ry[r]+(yc[r]-b->child[i].yc); 324 | b->child[i].rx=rx[c]+(xc[c]-b->child[i].xc); 325 | b->child[i].S=RELPOSKNOWN; 326 | } 327 | 328 | free(h); 329 | free(w); 330 | free(yc); 331 | free(xc); 332 | free(ry); 333 | free(rx); 334 | return 0; 335 | } 336 | 337 | #define WIDTH b->w 338 | #define HEIGHT b->h 339 | int PosBoxSize(box *b) 340 | { 341 | int i, *xy; 342 | void *content; 343 | 344 | 345 | if (b->T!=B_POS) 346 | { 347 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 348 | // ERRORFLAG ERRPBOXSIZE "Call of PosBoxSize on something not a pos box" 349 | AddErr(ERRPBOXSIZE); 350 | return 1; 351 | } 352 | /* first compute all sizes of all children boxes */ 353 | if (BoxSize_children(b)) 354 | return 1; 355 | 356 | /* Sizes of all children are known, now align the children */ 357 | /* fetch number of columns from the content blob */ 358 | content=b->content; 359 | xy=(int *)content; 360 | 361 | WIDTH=0; 362 | HEIGHT=0; 363 | for (i=0;iNc;i++) 364 | { 365 | if ((xy[2*i]<0)||(xy[2*i+1]<0)) 366 | { 367 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 368 | // ERRORFLAG ERRNEGRELPOS "Relative positions may not be negative in PosBoxSize" 369 | AddErr(ERRNEGRELPOS); 370 | return 1; 371 | } 372 | b->child[i].rx=xy[2*i]; 373 | b->child[i].ry=xy[2*i+1]; 374 | b->child[i].S=RELPOSKNOWN; 375 | if (b->child[i].rx+b->child[i].w>WIDTH) 376 | WIDTH=b->child[i].rx+b->child[i].w; 377 | if (b->child[i].ry+b->child[i].h>HEIGHT) 378 | HEIGHT=b->child[i].ry+b->child[i].h; 379 | } 380 | b->S=SIZEKNOWN; 381 | switch(b->X) 382 | { 383 | case MAX: 384 | b->xc=WIDTH; 385 | break; 386 | case MIN: 387 | b->xc=0; 388 | break; 389 | case CENTER: 390 | b->xc=(WIDTH-1)/2; 391 | break; 392 | default: 393 | break; 394 | } 395 | switch(b->Y) 396 | { 397 | case MAX: 398 | b->yc=HEIGHT; 399 | break; 400 | case MIN: 401 | b->yc=0; 402 | break; 403 | case CENTER: 404 | b->yc=(HEIGHT-1)/2; 405 | break; 406 | default: 407 | break; 408 | } 409 | return 0; 410 | } 411 | 412 | 413 | int DummyBoxSize(box *b) 414 | { 415 | if (b->T!=B_DUMMY) 416 | { 417 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 418 | // ERRORFLAG ERRDBOXSIZE "Call of DummyBoxSize on something not a dummy box" 419 | AddErr(ERRDBOXSIZE); 420 | return 1; 421 | } 422 | if (b->SS=SIZEKNOWN; 424 | return 0; 425 | } 426 | 427 | int EndlineBoxSize(box *b) 428 | { 429 | if (b->T!=B_ENDLINE) 430 | { 431 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 432 | // ERRORFLAG ERRELBOXSIZE "Call of EndlineBoxSize on something not a endline box" 433 | AddErr(ERRELBOXSIZE); 434 | return 1; 435 | } 436 | b->h=0; 437 | b->w=0; 438 | b->yc=0; 439 | b->xc=0; 440 | if (b->SS=SIZEKNOWN; 442 | return 0; 443 | } 444 | 445 | 446 | int LineBoxSize(box *b) 447 | { 448 | int i, j, LW, X, *line, nl=0, H=0, Yc=0, W=0, *y, *yc, nra=2; 449 | int *content; 450 | 451 | if (b->T!=B_LINE) 452 | { 453 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 454 | // ERRORFLAG ERRLBOXSIZE "LineBoxSize can only be used on line boxes" 455 | AddErr(ERRLBOXSIZE); 456 | return 1; 457 | } 458 | /* first compute all sizes of all children boxes */ 459 | if (BoxSize_children(b)) 460 | return 1; 461 | 462 | /* fetch the line width from the binary blob */ 463 | content=(int *)b->content; 464 | LW=content[0]; 465 | line=malloc(b->Nc*sizeof(int)); 466 | y=malloc(nra*sizeof(int)); 467 | yc=malloc(nra*sizeof(int)); 468 | 469 | if (LW<0) 470 | LW=0; 471 | 472 | 473 | X=0; 474 | for (i=0;iNc;i++) 475 | { 476 | /* we first set the X positions for each box */ 477 | if (((LW>0)&&(X+b->child[i].w>LW)&&(X>0))||(b->child[i].T==B_ENDLINE))/* if X = 0 -> w>LW, we stay on this line */ 478 | { 479 | for (j=0;jchild[i].rx=X; 495 | X+=b->child[i].w; 496 | if (X>W) /* compute maximum line width */ 497 | W=X; 498 | line[i]=nl; 499 | /* compute height and baseline of the current line */ 500 | if (H-Ycchild[i].h-b->child[i].yc) 501 | H+=(b->child[i].h-b->child[i].yc)-(H-Yc); 502 | if (Ycchild[i].yc) 503 | { 504 | H+=b->child[i].yc-Yc; 505 | Yc=b->child[i].yc; 506 | } 507 | } 508 | for (j=0;jNc-1;i>=0;i--) 520 | { 521 | /* set relative y coordinates */ 522 | b->child[i].ry=y[line[i]]+(yc[line[i]]-b->child[i].yc); 523 | b->child[i].S=RELPOSKNOWN; 524 | } 525 | b->h=H; 526 | b->w=W; 527 | b->S=SIZEKNOWN; 528 | 529 | switch(b->X) 530 | { 531 | case MAX: 532 | b->xc=WIDTH; 533 | break; 534 | case MIN: 535 | b->xc=0; 536 | break; 537 | case CENTER: 538 | b->xc=(WIDTH-1)/2; 539 | break; 540 | default: 541 | break; 542 | } 543 | if (nl==0) 544 | b->yc=yc[0]; /* if we do not have a linebox spanning several lines we must preserve the baseline */ 545 | else 546 | { 547 | switch(b->Y) 548 | { 549 | case MAX: 550 | b->yc=HEIGHT; 551 | break; 552 | case MIN: 553 | b->yc=0; 554 | break; 555 | case CENTER: 556 | b->yc=(HEIGHT-1)/2; 557 | break; 558 | default: 559 | break; 560 | } 561 | } 562 | 563 | 564 | free(y); 565 | free(yc); 566 | free(line); 567 | return 0; 568 | } 569 | 570 | int BoxSize_children(box *b) /* computes size of the children */ 571 | { 572 | int i; 573 | boxstate S; 574 | box *ms=b; 575 | int err=0; 576 | 577 | for (i=0;iNc;i++) 578 | { 579 | while((S=StateBoxtree(b->child+i, &ms))==INIT) 580 | { 581 | switch(ms->T) 582 | { 583 | case B_UNIT: 584 | err+=UnitBoxSize(ms); 585 | break; 586 | case B_ARRAY: 587 | err+=ArrayBoxSize(ms); 588 | break; 589 | case B_POS: 590 | err+=PosBoxSize(ms); 591 | break; 592 | case B_DUMMY: 593 | ms->S=SIZEKNOWN; 594 | break; 595 | case B_LINE: 596 | err+=LineBoxSize(ms); 597 | break; 598 | case B_ENDLINE: 599 | err+=EndlineBoxSize(ms); 600 | break; 601 | default: 602 | /* The following comment line lets the gen_errorflags.sh script generate appropriate error flags and messages */ 603 | // ERRORFLAG ERRUNKNOWNBOX "Unknown box type in BoxSize" 604 | AddErr(ERRUNKNOWNBOX); 605 | return 1; 606 | } 607 | } 608 | } 609 | if (err) 610 | return 1; 611 | return 0; 612 | } 613 | 614 | int BoxSize(box *b) /* computes size of box b */ 615 | { 616 | if (b->S==INIT) 617 | { 618 | switch(b->T) 619 | { 620 | case B_UNIT: 621 | return UnitBoxSize(b); 622 | break; 623 | case B_ARRAY: 624 | return ArrayBoxSize(b); 625 | break; 626 | case B_POS: 627 | return PosBoxSize(b); 628 | break; 629 | case B_DUMMY: 630 | return 0; /* dummy box size is known from the start */ 631 | break; 632 | case B_LINE: 633 | return LineBoxSize(b); 634 | break; 635 | case B_ENDLINE: 636 | return EndlineBoxSize(b); 637 | break; 638 | default: 639 | AddErr(ERRUNKNOWNBOX); /* reuse previously defined unknown box type error */ 640 | return 1; 641 | } 642 | } 643 | return 0; /* if not init, size must be known already */ 644 | } 645 | 646 | void BoxPos_recursive(box *b) 647 | { 648 | int i; 649 | for (i=0;iNc;i++) 650 | { 651 | b->child[i].ax=b->ax+b->child[i].rx; 652 | b->child[i].ay=b->ay+b->child[i].ry; 653 | b->child[i].S=ABSPOSKNOWN; 654 | BoxPos_recursive(b->child+i); 655 | } 656 | 657 | } 658 | void BoxPos(box *b) 659 | { 660 | if (b->Sax=0; 665 | b->ay=0; 666 | b->S=ABSPOSKNOWN; 667 | BoxPos_recursive(b); 668 | } 669 | 670 | void BoxSetState_recursive(box *b, boxstate S) 671 | { 672 | int i; 673 | for (i=0;iNc;i++) 674 | { 675 | if (b->child[i].S>S) 676 | b->child[i].S=S; 677 | BoxSetState_recursive(b->child+i, S); 678 | } 679 | 680 | } 681 | void BoxSetState(box *b, boxstate S) 682 | { 683 | if (b->S>S) 684 | b->S=S; 685 | BoxSetState_recursive(b, S); 686 | } 687 | 688 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software 5 | Foundation, Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell command './configure && make && make install' 16 | should configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the 'README' file for 18 | instructions specific to this package. Some packages provide this 19 | 'INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The 'configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a 'Makefile' in each directory of the package. 27 | It may also create one or more '.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script 'config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file 'config.log' containing compiler output (useful mainly for 31 | debugging 'configure'). 32 | 33 | It can also use an optional file (typically called 'config.cache' and 34 | enabled with '--cache-file=config.cache' or simply '-C') that saves the 35 | results of its tests to speed up reconfiguring. Caching is disabled by 36 | default to prevent problems with accidental use of stale cache files. 37 | 38 | If you need to do unusual things to compile the package, please try 39 | to figure out how 'configure' could check whether to do them, and mail 40 | diffs or instructions to the address given in the 'README' so they can 41 | be considered for the next release. If you are using the cache, and at 42 | some point 'config.cache' contains results you don't want to keep, you 43 | may remove or edit it. 44 | 45 | The file 'configure.ac' (or 'configure.in') is used to create 46 | 'configure' by a program called 'autoconf'. You need 'configure.ac' if 47 | you want to change it or regenerate 'configure' using a newer version of 48 | 'autoconf'. 49 | 50 | The simplest way to compile this package is: 51 | 52 | 1. 'cd' to the directory containing the package's source code and type 53 | './configure' to configure the package for your system. 54 | 55 | Running 'configure' might take a while. While running, it prints 56 | some messages telling which features it is checking for. 57 | 58 | 2. Type 'make' to compile the package. 59 | 60 | 3. Optionally, type 'make check' to run any self-tests that come with 61 | the package, generally using the just-built uninstalled binaries. 62 | 63 | 4. Type 'make install' to install the programs and any data files and 64 | documentation. When installing into a prefix owned by root, it is 65 | recommended that the package be configured and built as a regular 66 | user, and only the 'make install' phase executed with root 67 | privileges. 68 | 69 | 5. Optionally, type 'make installcheck' to repeat any self-tests, but 70 | this time using the binaries in their final installed location. 71 | This target does not install anything. Running this target as a 72 | regular user, particularly if the prior 'make install' required 73 | root privileges, verifies that the installation completed 74 | correctly. 75 | 76 | 6. You can remove the program binaries and object files from the 77 | source code directory by typing 'make clean'. To also remove the 78 | files that 'configure' created (so you can compile the package for 79 | a different kind of computer), type 'make distclean'. There is 80 | also a 'make maintainer-clean' target, but that is intended mainly 81 | for the package's developers. If you use it, you may have to get 82 | all sorts of other programs in order to regenerate files that came 83 | with the distribution. 84 | 85 | 7. Often, you can also type 'make uninstall' to remove the installed 86 | files again. In practice, not all packages have tested that 87 | uninstallation works correctly, even though it is required by the 88 | GNU Coding Standards. 89 | 90 | 8. Some packages, particularly those that use Automake, provide 'make 91 | distcheck', which can by used by developers to test that all other 92 | targets like 'make install' and 'make uninstall' work correctly. 93 | This target is generally not run by end users. 94 | 95 | Compilers and Options 96 | ===================== 97 | 98 | Some systems require unusual options for compilation or linking that 99 | the 'configure' script does not know about. Run './configure --help' 100 | for details on some of the pertinent environment variables. 101 | 102 | You can give 'configure' initial values for configuration parameters 103 | by setting variables in the command line or in the environment. Here is 104 | an example: 105 | 106 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 107 | 108 | *Note Defining Variables::, for more details. 109 | 110 | Compiling For Multiple Architectures 111 | ==================================== 112 | 113 | You can compile the package for more than one kind of computer at the 114 | same time, by placing the object files for each architecture in their 115 | own directory. To do this, you can use GNU 'make'. 'cd' to the 116 | directory where you want the object files and executables to go and run 117 | the 'configure' script. 'configure' automatically checks for the source 118 | code in the directory that 'configure' is in and in '..'. This is known 119 | as a "VPATH" build. 120 | 121 | With a non-GNU 'make', it is safer to compile the package for one 122 | architecture at a time in the source code directory. After you have 123 | installed the package for one architecture, use 'make distclean' before 124 | reconfiguring for another architecture. 125 | 126 | On MacOS X 10.5 and later systems, you can create libraries and 127 | executables that work on multiple system types--known as "fat" or 128 | "universal" binaries--by specifying multiple '-arch' options to the 129 | compiler but only a single '-arch' option to the preprocessor. Like 130 | this: 131 | 132 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 133 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CPP="gcc -E" CXXCPP="g++ -E" 135 | 136 | This is not guaranteed to produce working output in all cases, you 137 | may have to build one architecture at a time and combine the results 138 | using the 'lipo' tool if you have problems. 139 | 140 | Installation Names 141 | ================== 142 | 143 | By default, 'make install' installs the package's commands under 144 | '/usr/local/bin', include files under '/usr/local/include', etc. You 145 | can specify an installation prefix other than '/usr/local' by giving 146 | 'configure' the option '--prefix=PREFIX', where PREFIX must be an 147 | absolute file name. 148 | 149 | You can specify separate installation prefixes for 150 | architecture-specific files and architecture-independent files. If you 151 | pass the option '--exec-prefix=PREFIX' to 'configure', the package uses 152 | PREFIX as the prefix for installing programs and libraries. 153 | Documentation and other data files still use the regular prefix. 154 | 155 | In addition, if you use an unusual directory layout you can give 156 | options like '--bindir=DIR' to specify different values for particular 157 | kinds of files. Run 'configure --help' for a list of the directories 158 | you can set and what kinds of files go in them. In general, the default 159 | for these options is expressed in terms of '${prefix}', so that 160 | specifying just '--prefix' will affect all of the other directory 161 | specifications that were not explicitly provided. 162 | 163 | The most portable way to affect installation locations is to pass the 164 | correct locations to 'configure'; however, many packages provide one or 165 | both of the following shortcuts of passing variable assignments to the 166 | 'make install' command line to change installation locations without 167 | having to reconfigure or recompile. 168 | 169 | The first method involves providing an override variable for each 170 | affected directory. For example, 'make install 171 | prefix=/alternate/directory' will choose an alternate location for all 172 | directory configuration variables that were expressed in terms of 173 | '${prefix}'. Any directories that were specified during 'configure', 174 | but not in terms of '${prefix}', must each be overridden at install time 175 | for the entire installation to be relocated. The approach of makefile 176 | variable overrides for each directory variable is required by the GNU 177 | Coding Standards, and ideally causes no recompilation. However, some 178 | platforms have known limitations with the semantics of shared libraries 179 | that end up requiring recompilation when using this method, particularly 180 | noticeable in packages that use GNU Libtool. 181 | 182 | The second method involves providing the 'DESTDIR' variable. For 183 | example, 'make install DESTDIR=/alternate/directory' will prepend 184 | '/alternate/directory' before all installation names. The approach of 185 | 'DESTDIR' overrides is not required by the GNU Coding Standards, and 186 | does not work on platforms that have drive letters. On the other hand, 187 | it does better at avoiding recompilation issues, and works well even 188 | when some directory options were not specified in terms of '${prefix}' 189 | at 'configure' time. 190 | 191 | Optional Features 192 | ================= 193 | 194 | If the package supports it, you can cause programs to be installed 195 | with an extra prefix or suffix on their names by giving 'configure' the 196 | option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. 197 | 198 | Some packages pay attention to '--enable-FEATURE' options to 199 | 'configure', where FEATURE indicates an optional part of the package. 200 | They may also pay attention to '--with-PACKAGE' options, where PACKAGE 201 | is something like 'gnu-as' or 'x' (for the X Window System). The 202 | 'README' should mention any '--enable-' and '--with-' options that the 203 | package recognizes. 204 | 205 | For packages that use the X Window System, 'configure' can usually 206 | find the X include and library files automatically, but if it doesn't, 207 | you can use the 'configure' options '--x-includes=DIR' and 208 | '--x-libraries=DIR' to specify their locations. 209 | 210 | Some packages offer the ability to configure how verbose the 211 | execution of 'make' will be. For these packages, running './configure 212 | --enable-silent-rules' sets the default to minimal output, which can be 213 | overridden with 'make V=1'; while running './configure 214 | --disable-silent-rules' sets the default to verbose, which can be 215 | overridden with 'make V=0'. 216 | 217 | Particular systems 218 | ================== 219 | 220 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC 221 | is not installed, it is recommended to use the following options in 222 | order to use an ANSI C compiler: 223 | 224 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 225 | 226 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 227 | 228 | HP-UX 'make' updates targets which have the same time stamps as their 229 | prerequisites, which makes it generally unusable when shipped generated 230 | files such as 'configure' are involved. Use GNU 'make' instead. 231 | 232 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 233 | parse its '' header file. The option '-nodtk' can be used as a 234 | workaround. If GNU CC is not installed, it is therefore recommended to 235 | try 236 | 237 | ./configure CC="cc" 238 | 239 | and if that doesn't work, try 240 | 241 | ./configure CC="cc -nodtk" 242 | 243 | On Solaris, don't put '/usr/ucb' early in your 'PATH'. This 244 | directory contains several dysfunctional programs; working variants of 245 | these programs are available in '/usr/bin'. So, if you need '/usr/ucb' 246 | in your 'PATH', put it _after_ '/usr/bin'. 247 | 248 | On Haiku, software installed for all users goes in '/boot/common', 249 | not '/usr/local'. It is recommended to use the following options: 250 | 251 | ./configure --prefix=/boot/common 252 | 253 | Specifying the System Type 254 | ========================== 255 | 256 | There may be some features 'configure' cannot figure out 257 | automatically, but needs to determine by the type of machine the package 258 | will run on. Usually, assuming the package is built to be run on the 259 | _same_ architectures, 'configure' can figure that out, but if it prints 260 | a message saying it cannot guess the machine type, give it the 261 | '--build=TYPE' option. TYPE can either be a short name for the system 262 | type, such as 'sun4', or a canonical name which has the form: 263 | 264 | CPU-COMPANY-SYSTEM 265 | 266 | where SYSTEM can have one of these forms: 267 | 268 | OS 269 | KERNEL-OS 270 | 271 | See the file 'config.sub' for the possible values of each field. If 272 | 'config.sub' isn't included in this package, then this package doesn't 273 | need to know the machine type. 274 | 275 | If you are _building_ compiler tools for cross-compiling, you should 276 | use the option '--target=TYPE' to select the type of system they will 277 | produce code for. 278 | 279 | If you want to _use_ a cross compiler, that generates code for a 280 | platform different from the build platform, you should specify the 281 | "host" platform (i.e., that on which the generated programs will 282 | eventually be run) with '--host=TYPE'. 283 | 284 | Sharing Defaults 285 | ================ 286 | 287 | If you want to set default values for 'configure' scripts to share, 288 | you can create a site shell script called 'config.site' that gives 289 | default values for variables like 'CC', 'cache_file', and 'prefix'. 290 | 'configure' looks for 'PREFIX/share/config.site' if it exists, then 291 | 'PREFIX/etc/config.site' if it exists. Or, you can set the 292 | 'CONFIG_SITE' environment variable to the location of the site script. 293 | A warning: not all 'configure' scripts look for a site script. 294 | 295 | Defining Variables 296 | ================== 297 | 298 | Variables not defined in a site shell script can be set in the 299 | environment passed to 'configure'. However, some packages may run 300 | configure again during the build, and the customized values of these 301 | variables may be lost. In order to avoid this problem, you should set 302 | them in the 'configure' command line, using 'VAR=value'. For example: 303 | 304 | ./configure CC=/usr/local2/bin/gcc 305 | 306 | causes the specified 'gcc' to be used as the C compiler (unless it is 307 | overridden in the site shell script). 308 | 309 | Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an 310 | Autoconf limitation. Until the limitation is lifted, you can use this 311 | workaround: 312 | 313 | CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 314 | 315 | 'configure' Invocation 316 | ====================== 317 | 318 | 'configure' recognizes the following options to control how it 319 | operates. 320 | 321 | '--help' 322 | '-h' 323 | Print a summary of all of the options to 'configure', and exit. 324 | 325 | '--help=short' 326 | '--help=recursive' 327 | Print a summary of the options unique to this package's 328 | 'configure', and exit. The 'short' variant lists options used only 329 | in the top level, while the 'recursive' variant lists options also 330 | present in any nested packages. 331 | 332 | '--version' 333 | '-V' 334 | Print the version of Autoconf used to generate the 'configure' 335 | script, and exit. 336 | 337 | '--cache-file=FILE' 338 | Enable the cache: use and save the results of the tests in FILE, 339 | traditionally 'config.cache'. FILE defaults to '/dev/null' to 340 | disable caching. 341 | 342 | '--config-cache' 343 | '-C' 344 | Alias for '--cache-file=config.cache'. 345 | 346 | '--quiet' 347 | '--silent' 348 | '-q' 349 | Do not print messages saying which checks are being made. To 350 | suppress all normal output, redirect it to '/dev/null' (any error 351 | messages will still be shown). 352 | 353 | '--srcdir=DIR' 354 | Look for the package's source code in directory DIR. Usually 355 | 'configure' can determine that directory automatically. 356 | 357 | '--prefix=DIR' 358 | Use DIR as the installation prefix. *note Installation Names:: for 359 | more details, including other options available for fine-tuning the 360 | installation locations. 361 | 362 | '--no-create' 363 | '-n' 364 | Run the configure checks, but stop before creating any output 365 | files. 366 | 367 | 'configure' also accepts some other, not widely useful, options. Run 368 | 'configure --help' for more details. 369 | -------------------------------------------------------------------------------- /test/testsuite.txt: -------------------------------------------------------------------------------- 1 | libtexprintf/utftex test file 2 | run some specific tests 3 | 4 | How this test file works: 5 | Each test consists of a named block with input and reference outputs 6 | Text inbetween blocks is ignored. One block may have more than one 7 | reference outputs. To this end you can specify arguments for which the 8 | reference should be obtained. If several arguments produce the same 9 | reference you may specify several sets of arguments with one reference 10 | output. The argument sets should be separated with '|' 11 | For Example: 12 | 13 | example 14 | abcd 15 | |-S|-A|-F text 16 | abcd 17 | -F mathnormal 18 | 𝑎𝑏𝑐𝑑 19 | 20 | 21 | This creates a block named "example" which tests the input "abcd" and 22 | has two reference outputs, the first reference output is "abcd" and 23 | should be obtained 24 | - without arguments 25 | - with "-S" 26 | - with "-A" 27 | - with "-F text" 28 | The second reference output ("𝑎𝑏𝑐𝑑") is obtained with the argument 29 | "-F mathnormal" 30 | Thus this example produces in total 5 test results, one for each 31 | reference/argument combination. 32 | 33 | 34 | ################# specific tests 35 | test raisebox 36 | raisebox 37 | a\raisebox{2}{b}c 38 | |-S|-A 39 | b 40 | 41 | a c 42 | 43 | 44 | test integrals 45 | integral 46 | \int_a^b f(x) dx 47 | |-S 48 | ⌠ᵇ 49 | ⎮ f(x) dx 50 | ⌡ₐ 51 | -A 52 | b 53 | / 54 | | f(x) dx 55 | / 56 | a 57 | -m 58 | b 59 | ⌠ 60 | ⎮ f(x) dx 61 | ⌡ 62 | a 63 | 64 | 65 | double integral 66 | iintegral 67 | \iint_a^b f(x) dx 68 | |-S 69 | b 70 | ⌠⌠ 71 | ⎮⎮ f(x) dx 72 | ⌡⌡ 73 | ᵃ 74 | -A 75 | b 76 | // 77 | || f(x) dx 78 | // 79 | a 80 | -m 81 | b 82 | ⌠⌠ 83 | ⎮⎮ f(x) dx 84 | ⌡⌡ 85 | a 86 | 87 | 88 | iiint 89 | \iiint_a^b f(x) dx 90 | | -S 91 | b 92 | ⌠⌠⌠ 93 | ⎮⎮⎮ f(x) dx 94 | ⌡⌡⌡ 95 | ᵃ 96 | -A 97 | b 98 | /// 99 | ||| f(x) dx 100 | /// 101 | a 102 | -m 103 | b 104 | ⌠⌠⌠ 105 | ⎮⎮⎮ f(x) dx 106 | ⌡⌡⌡ 107 | a 108 | 109 | 110 | iiiint 111 | \iiiint_a^b f(x) dx 112 | | -S 113 | b 114 | ⌠⌠⌠⌠ 115 | ⎮⎮⎮⎮ f(x) dx 116 | ⌡⌡⌡⌡ 117 | ᵃ 118 | -A 119 | b 120 | //// 121 | |||| f(x) dx 122 | //// 123 | a 124 | -m 125 | b 126 | ⌠⌠⌠⌠ 127 | ⎮⎮⎮⎮ f(x) dx 128 | ⌡⌡⌡⌡ 129 | a 130 | 131 | 132 | n-dimensional integral 133 | idotsintegral 134 | \idotsint_a^b f(x) dx 135 | |-S 136 | b 137 | ⌠ ⌠ 138 | ⎮⋯⎮ f(x) dx 139 | ⌡ ⌡ 140 | ᵃ 141 | -A 142 | b 143 | / / 144 | |⋯| f(x) dx 145 | / / 146 | a 147 | -m 148 | b 149 | ⌠ ⌠ 150 | ⎮⋯⎮ f(x) dx 151 | ⌡ ⌡ 152 | a 153 | 154 | 155 | oint 156 | \oint_a^b f(x) dx 157 | | -S 158 | ⌠ ᵇ 159 | ⸦⎮⸧ f(x) dx 160 | ⌡ ₐ 161 | -A 162 | b 163 | / 164 | (|) f(x) dx 165 | / 166 | a 167 | -m 168 | b 169 | ⌠ 170 | ⸦⎮⸧ f(x) dx 171 | ⌡ 172 | a 173 | 174 | 175 | oiint 176 | \oiint_a^b f(x) dx 177 | | -S 178 | b 179 | ⌠⌠ 180 | ⸦⎮⎮⸧ f(x) dx 181 | ⌡⌡ 182 | ᵃ 183 | -A 184 | b 185 | // 186 | (||) f(x) dx 187 | // 188 | a 189 | -m 190 | b 191 | ⌠⌠ 192 | ⸦⎮⎮⸧ f(x) dx 193 | ⌡⌡ 194 | a 195 | 196 | 197 | 198 | oiiint 199 | \oiiint_a^b f(x) dx 200 | | -S 201 | b 202 | ⌠⌠⌠ 203 | ⸦⎮⎮⎮⸧ f(x) dx 204 | ⌡⌡⌡ 205 | ᵃ 206 | -A 207 | b 208 | /// 209 | (|||) f(x) dx 210 | /// 211 | a 212 | -m 213 | b 214 | ⌠⌠⌠ 215 | ⸦⎮⎮⎮⸧ f(x) dx 216 | ⌡⌡⌡ 217 | a 218 | 219 | 220 | 221 | oiiiint 222 | \oiiiint_a^b f(x) dx 223 | | -S 224 | b 225 | ⌠⌠⌠⌠ 226 | ⸦⎮⎮⎮⎮⸧ f(x) dx 227 | ⌡⌡⌡⌡ 228 | ᵃ 229 | -A 230 | b 231 | //// 232 | (||||) f(x) dx 233 | //// 234 | a 235 | -m 236 | b 237 | ⌠⌠⌠⌠ 238 | ⸦⎮⎮⎮⎮⸧ f(x) dx 239 | ⌡⌡⌡⌡ 240 | a 241 | 242 | 243 | oidotsint 244 | \oidotsint_a^b f(x) dx 245 | | -S 246 | b 247 | ⌠ ⌠ 248 | ⸦⎮⋯⎮⸧ f(x) dx 249 | ⌡ ⌡ 250 | ᵃ 251 | -A 252 | b 253 | / / 254 | (|⋯|) f(x) dx 255 | / / 256 | a 257 | -m 258 | b 259 | ⌠ ⌠ 260 | ⸦⎮⋯⎮⸧ f(x) dx 261 | ⌡ ⌡ 262 | a 263 | 264 | 265 | 266 | overline 267 | \overline{abc} \overline{a} \overline a 268 | | -S | -m 269 | ▁▁▁ 270 | abc a̅ a̅ 271 | -A 272 | ___ _ _ 273 | abc a a 274 | -a 275 | ▁▁▁ ▁ ▁ 276 | abc a a 277 | 278 | 279 | 280 | underline 281 | \underline{abc} \underline{a} \underline a 282 | | -S | -m 283 | abc a̲ a̲ 284 | ─── 285 | -A 286 | abc a a 287 | --- - - 288 | -a 289 | abc a a 290 | ─── ─ ─ 291 | 292 | 293 | 294 | bar 295 | \bar{abc} \bar{a} \bar a 296 | | -S | -m 297 | ▁▁▁ 298 | abc a̅ a̅ 299 | -A 300 | ___ _ _ 301 | abc a a 302 | -a 303 | ▁▁▁ ▁ ▁ 304 | abc a a 305 | -F mathnormal 306 | ▁▁▁ 307 | 𝑎𝑏𝑐 𝑎̅ 𝑎̅ 308 | 309 | 310 | grave 311 | \grave{abc} \grave{a} \grave a 312 | | -S | -m 313 | ` 314 | abc à à 315 | -A 316 | ` ` ` 317 | abc a a 318 | -a 319 | ` ` ` 320 | abc a a 321 | -F mathnormal 322 | ` 323 | 𝑎𝑏𝑐 𝑎̀ 𝑎̀ 324 | 325 | 326 | 327 | 328 | acute 329 | \acute{abc} \acute{a} \acute a 330 | | -S | -m 331 | ´ 332 | abc á á 333 | -A 334 | ´ ´ ´ 335 | abc a a 336 | -a 337 | ´ ´ ´ 338 | abc a a 339 | -F mathnormal 340 | ´ 341 | 𝑎𝑏𝑐 𝑎́ 𝑎́ 342 | 343 | 344 | 345 | hat 346 | \hat{abc} \hat{a} \hat a 347 | | -S | -m 348 | ^ 349 | abc â â 350 | -A 351 | ^ ^ ^ 352 | abc a a 353 | -a 354 | ^ ^ ^ 355 | abc a a 356 | -F mathnormal 357 | ^ 358 | 𝑎𝑏𝑐 𝑎̂ 𝑎̂ 359 | 360 | 361 | 362 | tilde 363 | \tilde{abc} \tilde{a} \tilde a 364 | | -S | -m 365 | ~ 366 | abc ã ã 367 | -A 368 | ~ ~ ~ 369 | abc a a 370 | -a 371 | ~ ~ ~ 372 | abc a a 373 | -F mathnormal 374 | ~ 375 | 𝑎𝑏𝑐 𝑎̃ 𝑎̃ 376 | 377 | 378 | 379 | breve 380 | \breve{abc} \breve{a} \breve a 381 | | -A | -S | -m 382 | ◡ 383 | abc ă ă 384 | 385 | 386 | dot_s 387 | \dot{a} 388 | | -S | -m 389 | ȧ 390 | -A 391 | . 392 | a 393 | 394 | 395 | dot_l 396 | \dot{abc} 397 | | -A | -S | -m 398 | . 399 | abc 400 | 401 | 402 | ddot 403 | \ddot{abc} \ddot{a} \ddot a 404 | | -A | -S | -m 405 | abc ä ä 406 | 407 | 408 | 409 | mathring 410 | \mathring{abc} \mathring{a} \mathring a 411 | | -A | -S | -m 412 | ∘ 413 | abc å å 414 | 415 | 416 | 417 | double_accute 418 | \H{abc} \H{a} \H a 419 | | -A | -S | -m 420 | abc a̋ a̋ 421 | 422 | 423 | 424 | check 425 | \check{abc} \check{a} \check a 426 | | -A | -S | -m 427 | abc ǎ ǎ 428 | 429 | 430 | 431 | cedilla 432 | \c{abc} \c{c} \c c 433 | | -A | -S | -m 434 | abc ç ç 435 | 436 | 437 | ogonek 438 | \k{abc} \k{a} \k a 439 | | -A | -S | -m 440 | abc ą ą 441 | 442 | 443 | utilde 444 | \utilde{abc} \utilde{c} \utilde c 445 | | -S | -m 446 | abc c̰ c̰ 447 | ~ 448 | -A 449 | abc c c 450 | ~ ~ ~ 451 | 452 | 453 | solidus1 454 | \l{abc} \l{a} \l a 455 | | -A | -S | -m 456 | abc a̷ a̷ 457 | 458 | 459 | not 460 | \not{abc} \not{a} \not a 461 | | -A | -S | -m 462 | abc a̸ a̸ 463 | 464 | 465 | Lvec 466 | \Lvec{abc} \Lvec{a} \Lvec a 467 | | -A | -S | -m 468 | ← 469 | abc a⃖ a⃖ 470 | 471 | 472 | lvec 473 | \lvec{abc} \lvec{a} \lvec a 474 | | -A | -S | -m 475 | ↼ 476 | abc a⃐ a⃐ 477 | 478 | 479 | vec 480 | \vec{abc} \vec{a} \vec a 481 | | -A | -S | -m 482 | → 483 | abc a⃗ a⃗ 484 | 485 | 486 | 487 | dddot 488 | \dddot{abc} \dddot{a} \dddot a 489 | | -A | -S | -m 490 | … 491 | abc a⃛ a⃛ 492 | 493 | 494 | 495 | ddddot 496 | \ddddot{abc} \ddddot{a} \ddddot a 497 | | -A | -S | -m 498 | abc a⃜ a⃜ 499 | 500 | 501 | overleftrightarrow 502 | \overleftrightarrow{abc} \overleftrightarrow{a} \overleftrightarrow a 503 | | -A | -S | -m 504 | ↔ 505 | abc a⃡ a⃡ 506 | 507 | 508 | ocommatopright 509 | \ocommatopright{abc} \ocommatopright{a} \ocommatopright a 510 | | -A | -S | -m 511 | , 512 | abc a̕ a̕ 513 | 514 | 515 | ocommatopright 516 | \droang{abc} \droang{a} \droang a 517 | | -A | -S | -m 518 | ┐ 519 | abc a̚ a̚ 520 | 521 | 522 | ocommatopright 523 | \rightharpoonaccent{abc} \rightharpoonaccent{a} \rightharpoonaccent a 524 | | -A | -S | -m 525 | ⇀ 526 | abc a⃑ a⃑ 527 | 528 | 529 | widebridgeabove 530 | \widebridgeabove{abc} \widebridgeabove{a} \widebridgeabove a 531 | | -A | -S | -m 532 | ⎴ 533 | abc a⃩ a⃩ 534 | 535 | 536 | 537 | asteraccent 538 | \asteraccent{abc} \asteraccent{a} \asteraccent a 539 | | -A | -S | -m 540 | * 541 | abc a⃰ a⃰ 542 | 543 | 544 | 545 | candra 546 | \candra{abc} \candra{a} \candra a 547 | | -A | -S | -m 548 | 𝄑 549 | abc a̐ a̐ 550 | 551 | 552 | 553 | wideutilde 554 | \wideutilde{abc} \wideutilde{a} \wideutilde a 555 | | -S | -m 556 | abc a̰ a̰ 557 | ~ 558 | -A 559 | abc a a 560 | ~ ~ ~ 561 | 562 | 563 | 564 | threeunderdot 565 | \threeunderdot{abc} \threeunderdot{a} \threeunderdot a 566 | | -A | -S | -m 567 | abc a⃨ a⃨ 568 | … 569 | 570 | 571 | underleftarrow 572 | \underleftarrow{abc} \underleftarrow{a} \underleftarrow a 573 | | -A | -S | -m 574 | abc a⃮ a⃮ 575 | ↼ 576 | 577 | 578 | 579 | underrightarrow 580 | \underrightarrow{abc} \underrightarrow{a} \underrightarrow a 581 | | -A | -S | -m 582 | abc a⃯ a⃯ 583 | → 584 | 585 | 586 | underleftrightarrow 587 | \underleftrightarrow{abc} \underleftrightarrow{a} \underleftrightarrow a 588 | | -A | -S | -m 589 | abc a͍ a͍ 590 | ↔ 591 | 592 | 593 | underrightharpoondown 594 | \underrightharpoondown{abc} \underrightharpoondown{a} \underrightharpoondown a 595 | | -A | -S | -m 596 | abc a⃬ a⃬ 597 | ⇁ 598 | 599 | 600 | underleftharpoondown 601 | \underleftharpoondown{abc} \underleftharpoondown{a} \underleftharpoondown a 602 | | -A | -S | -m 603 | abc a⃭ a⃭ 604 | ↽ 605 | 606 | 607 | 608 | palh 609 | \palh{abc} \palh{a} \palh a 610 | | -A | -S | -m 611 | abc a̡ a̡ 612 | ◞ 613 | 614 | 615 | rh 616 | \rh{abc} \rh{a} \rh a 617 | | -A | -S | -m 618 | abc a̢ a̢ 619 | ◟ 620 | 621 | 622 | 623 | sbbrg 624 | \sbbrg{abc} \sbbrg{a} \sbbrg a 625 | | -A | -S | -m 626 | abc a̪ a̪ 627 | ⎴ 628 | 629 | 630 | accent without multi-character support 631 | sout 632 | \sout{abc} \sout{a} \sout a 633 | | -A | -S | -m 634 | abc a̶ a̶ 635 | 636 | 637 | 638 | strike 639 | \strike{abc} \strike{a} \strike a 640 | | -A | -S | -m 641 | abc a̶ a̶ 642 | 643 | 644 | annuity 645 | \annuity{abc} \annuity{a} \annuity a 646 | | -A | -S | -m 647 | abc a⃧ a⃧ 648 | 649 | 650 | enclosecircle 651 | \enclosecircle{abc} \enclosecircle{a} \enclosecircle a 652 | | -A | -S | -m 653 | abc a⃝ a⃝ 654 | 655 | 656 | enclosesquare 657 | \enclosesquare{abc} \enclosesquare{a} \enclosesquare a 658 | | -A | -S | -m 659 | abc a⃞ a⃞ 660 | 661 | 662 | enclosediamond 663 | \enclosediamond{abc} \enclosediamond{a} \enclosediamond a 664 | | -A | -S | -m 665 | abc a⃟ a⃟ 666 | 667 | 668 | enclosetriangle 669 | \enclosetriangle{abc} \enclosetriangle{a} \enclosetriangle a 670 | | -A | -S | -m 671 | abc a⃤ a⃤ 672 | 673 | 674 | vertoverlay 675 | \vertoverlay{abc} \vertoverlay{a} \vertoverlay a 676 | | -A | -S | -m 677 | abc a⃒ a⃒ 678 | 679 | 680 | test stacking of diacritics 681 | stack_diacritics 682 | jul\dot{\ddot{\iota}}a 683 | | -S 684 | julϊ̇a 685 | 686 | 687 | backslash. The backslash command produces a symbol but is not included 688 | in the symbol table. We test it here 689 | 690 | backslash 691 | \backslash 692 | |-S|-A 693 | \ 694 | 695 | 696 | utftex has a "box" command producing an empty space with a given width 697 | and height 698 | box 699 | _f\box{2}{2}^q 700 | |-S | -A 701 | q 702 | 703 | 704 | f 705 | 706 | 707 | 708 | test phantom boxes 709 | phantom 710 | \sum_{j\in 0,\ldots\, 10 \vphantom{3^{3^{3^j}}}} \sum_{i\in 0,\ldots\, 3^{3^{3^j}}} i\cdot j 711 | |-S 712 | ⎲ ⎲ 713 | ⎳ ⎳ i⋅j 714 | 3ʲ 715 | 3 716 | j∈0,… 10 i∈0,… 3 717 | -A 718 | __ __ 719 | \ \ i⋅j 720 | /_ /_ 721 | j 722 | 3 723 | 3 724 | j∈0,… 10 i∈0,… 3 725 | 726 | 727 | 728 | test arrays 729 | array1 730 | \left[ 731 | \begin{array}{ccc} 732 | x_{11} & x_{12} & x_{13}\\ 733 | x_{21} & x_{22} & x_{23}\\ 734 | x_{31} & x_{32} & x_{33} 735 | \end{array} 736 | \right] 737 | |-S 738 | ⎡x₁₁ x₁₂ x₁₃⎤ 739 | ⎢x₂₁ x₂₂ x₂₃⎥ 740 | ⎣x₃₁ x₃₂ x₃₃⎦ 741 | -A 742 | +x x x + 743 | | 11 12 13| 744 | |x x x | 745 | | 21 22 23| 746 | |x x x | 747 | + 31 32 33+ 748 | 749 | 750 | array2 751 | \left[ 752 | \begin{array}{ccc} 753 | x_{11} & x_{12} & x_{13}\\ 754 | x_{21} & x_{22} & x_{23}\\ 755 | x_{31} & x_{32} & x_{33} 756 | \end{array} \left| 757 | \begin{array}{ccc} 758 | y_{11} & y_{12} & y_{13}\\ 759 | y_{21} & y_{22} & y_{23}\\ 760 | y_{31} & y_{32} & y_{33} 761 | \end{array} 762 | \right. 763 | \right] 764 | |-S 765 | ⎡x₁₁ x₁₂ x₁₃ ⎢y₁₁ y₁₂ y₁₃⎤ 766 | ⎢x₂₁ x₂₂ x₂₃ ⎢y₂₁ y₂₂ y₂₃⎥ 767 | ⎣x₃₁ x₃₂ x₃₃ ⎢y₃₁ y₃₂ y₃₃⎦ 768 | -A 769 | +x x x |y y y + 770 | | 11 12 13 | 11 12 13| 771 | |x x x |y y y | 772 | | 21 22 23 | 21 22 23| 773 | |x x x |y y y | 774 | + 31 32 33 | 31 32 33+ 775 | 776 | 777 | the limits command 778 | limits 779 | F(x)\limits_a^x 780 | |-S 781 | ₓ 782 | F(x) 783 | ᵃ 784 | -m |-A 785 | x 786 | F(x) 787 | a 788 | 789 | 790 | 791 | limit 792 | lim 793 | \lim_{x\downarrow 1} \frac{1}{x-1} 794 | |-S 795 | 1 796 | lim ─── 797 | x↓1 x-1 798 | -A 799 | 1 800 | lim --- 801 | x↓1 x-1 802 | 803 | 804 | over 805 | {a\over b} 806 | |-S 807 | a 808 | ─ 809 | b 810 | -A 811 | a 812 | - 813 | b 814 | 815 | 816 | choose 817 | {n\choose k} 818 | |-S 819 | ⎛n⎞ 820 | ⎜ ⎟ 821 | ⎝k⎠ 822 | -A 823 | /n\ 824 | | | 825 | \k/ 826 | 827 | 828 | 829 | exp 830 | \exp 831 | |-S|-F mathnormal|-A 832 | exp 833 | 834 | 835 | 836 | primes 837 | a' a'' a''' a'''' 838 | |-S 839 | a′ a″ a‴ a⁗ 840 | -A 841 | a' a'' a''' a'''' 842 | 843 | 844 | sqrt 845 | \sqrt[3]{\box{2}{3}} 846 | | -S | -m 847 | ┌──┐ 848 | 3 │ 849 | ╲ │ 850 | ╲│ 851 | -A 852 | ____ 853 | 3 | 854 | \ | 855 | \| 856 | 857 | sqrt2 858 | \sqrt[3000]{\box{2}{3}} 859 | | -S | -m 860 | ┌──┐ 861 | 3000 │ 862 | ╲ │ 863 | ╲│ 864 | -A 865 | ____ 866 | 3000 | 867 | \ | 868 | \| 869 | 870 | sqrt3 871 | \sqrt{\box{2}{3}} 872 | | -S | -m 873 | ┌──┐ 874 | │ 875 | ╲ │ 876 | ╲│ 877 | -A 878 | ____ 879 | | 880 | \ | 881 | \| 882 | 883 | brac1 884 | \left(\box{2}{3}\right) 885 | | -S | -m 886 | ⎛ ⎞ 887 | ⎜ ⎟ 888 | ⎝ ⎠ 889 | -A 890 | / \ 891 | | | 892 | \ / 893 | 894 | brac2 895 | \left[\box{2}{3}\right] 896 | | -S | -m 897 | ⎡ ⎤ 898 | ⎢ ⎥ 899 | ⎣ ⎦ 900 | -A 901 | + + 902 | | | 903 | + + 904 | 905 | brac3 906 | \left{\box{2}{3}\right} 907 | | -S | -m 908 | ⎧ ⎫ 909 | ⎨ ⎬ 910 | ⎩ ⎭ 911 | -A 912 | / \ 913 | < > 914 | \ / 915 | 916 | brac4 917 | \left<\box{2}{3}\right> 918 | | -S | -m 919 | ╱ ╲ 920 | ╱ ╲ 921 | ╲ ╱ 922 | ╲ ╱ 923 | -A 924 | / \ 925 | / \ 926 | \ / 927 | \ / 928 | 929 | brac5 930 | \left|\box{2}{3}\right| 931 | | -S | -m 932 | ⎢ ⎢ 933 | ⎢ ⎢ 934 | ⎢ ⎢ 935 | -A 936 | | | 937 | | | 938 | | | 939 | 940 | 941 | For the more special brackets we have the issue that we could also draw 942 | some of these in ASCII but I don't... 943 | 944 | brac6 945 | \left\uparrow\box{2}{3}\right\uparrow 946 | | -A | -S | -m 947 | ▲ ▲ 948 | ⎢ ⎢ 949 | ⎢ ⎢ 950 | 951 | brac7 952 | \left\downarrow\box{2}{3}\right\downarrow 953 | | -A | -S | -m 954 | ⎢ ⎢ 955 | ⎢ ⎢ 956 | ▼ ▼ 957 | 958 | brac8 959 | \left\lceil\box{2}{3}\right\rceil 960 | | -A | -S | -m 961 | ⎡ ⎤ 962 | ⎢ ⎥ 963 | ⎢ ⎥ 964 | 965 | brac9 966 | \left\lfloor\box{2}{3}\right\rfloor 967 | | -A | -S | -m 968 | ⎢ ⎥ 969 | ⎢ ⎥ 970 | ⎣ ⎦ 971 | 972 | 973 | test argument parsing 974 | 975 | argparse_space 976 | \frac {1}{\alpha} 977 | | -S | -m 978 | 1 979 | ─ 980 | α 981 | -A 982 | 1 983 | - 984 | α 985 | 986 | 987 | argparse_nobrac1 988 | \frac {1}\alpha 989 | | -S | -m 990 | 1 991 | ─ 992 | α 993 | -A 994 | 1 995 | - 996 | α 997 | 998 | 999 | argparse_nobrac2 1000 | \frac1\alpha 1001 | | -S | -m 1002 | 1 1003 | ─ 1004 | α 1005 | -A 1006 | 1 1007 | - 1008 | α 1009 | 1010 | 1011 | test greedy operators 1012 | greedyover 1013 | a + b\over c 1014 | | -S | -m 1015 | a + b 1016 | ───── 1017 | c 1018 | -A 1019 | a + b 1020 | ----- 1021 | c 1022 | 1023 | 1024 | greedyover2 1025 | {a + b\over c} + d 1026 | | -S | -m 1027 | a + b 1028 | ───── + d 1029 | c 1030 | -A 1031 | a + b 1032 | ----- + d 1033 | c 1034 | 1035 | 1036 | test whether nested brackets are processed correctly 1037 | greedyover3 1038 | {a {+} b\over c} + d 1039 | | -S | -m 1040 | a + b 1041 | ───── + d 1042 | c 1043 | -A 1044 | a + b 1045 | ----- + d 1046 | c 1047 | 1048 | 1049 | ambigous input. libtexprintf lets 1050 | \over precede over \choose 1051 | and the first appearance over any subsequent 1052 | Note that latex throws and error and tells you it is ambiguous... 1053 | greedyoverchoose 1054 | a\choose b+s\over d 1055 | | -S | -m 1056 | ⎛ a ⎞ 1057 | ⎜ ⎟ 1058 | ⎝b+s⎠ 1059 | ───── 1060 | d 1061 | -A 1062 | / a \ 1063 | | | 1064 | \b+s/ 1065 | ----- 1066 | d 1067 | 1068 | nestedbrackets 1069 | \left(\left[a+b\right]+c\right) 1070 | | -A | -S | -m 1071 | ([a+b]+c) 1072 | 1073 | -------------------------------------------------------------------------------- /test/testeqs.txt: -------------------------------------------------------------------------------- 1 | ################# random equations to test 2 | 3 | eq1 4 | \mathrm{W_{cubic}}(t) = C * (t - K)^3 + W_{max} 5 | |-S 6 | W (t) = C * (t - K)³ + Wₘₐₓ 7 | cubic 8 | -A 9 | 3 10 | W (t) = C * (t - K) + W 11 | cubic max 12 | 13 | 14 | eq2 15 | K = \sqrt[3]{\frac{W_{max} - cwnd}{C}} 16 | |-S 17 | ┌───────────┐ 18 | 3 │Wₘₐₓ - cwnd 19 | K = ╲ │─────────── 20 | ╲│ C 21 | -A 22 | _____________ 23 | 3 |W - cwnd 24 | \ | max 25 | K = \ |----------- 26 | \| C 27 | 28 | 29 | eq3 30 | target = \left\{ 31 | \begin{array}{ll} 32 | cwnd & \text{if } \mathrm{W_{cubic}}(t + RTT) <= cwnd \\ 33 | 1.5 * cwnd & \text{if } \mathrm{W_{cubic}}(t + RTT) != 1.5 * cwnd \\ 34 | \mathrm{W_{cubic}}(t + RTT) & \text{otherwise} \\ 35 | \end{array} \right. 36 | |-S 37 | ⎧cwnd if W (t + RTT) <= cwnd 38 | ⎪ cubic 39 | ⎪1.5 * cwnd if W (t + RTT) != 1.5 * cwnd 40 | target = ⎨ cubic 41 | ⎪W (t + RTT) otherwise 42 | ⎪ cubic 43 | ⎩ 44 | -A 45 | /cwnd if W (t + RTT) <= cwnd 46 | | cubic 47 | |1.5 * cwnd if W (t + RTT) != 1.5 * cwnd 48 | target = < cubic 49 | |W (t + RTT) otherwise 50 | | cubic 51 | \ 52 | 53 | 54 | eq4 55 | \mathrm{AIMD}(\alpha_{aimd}, \beta_{aimd}) = 56 | \sqrt{\frac{\alpha_{aimd} * (1 + \beta_{aimd})}{2 * (1 - \beta_{aimd}) * p}} 57 | |-S 58 | ┌───────────────────┐ 59 | │α * (1 + β ) 60 | │ aimd aimd 61 | AIMD(α , β ) = ╲ │─────────────────── 62 | aimd aimd ╲ │2 * (1 - β ) * p 63 | ╲│ aimd 64 | -A 65 | _____________________ 66 | |α * (1 + β ) 67 | | aimd aimd 68 | AIMD(α , β ) = \ |------------------- 69 | aimd aimd \ |2 * (1 - β ) * p 70 | \| aimd 71 | 72 | 73 | eq5 74 | \begin{array}[b]{ll} 75 | W_{max} = cwnd & \text{// save cwnd before reduction} \\ 76 | ssthresh = \mathrm{max}(cwnd * \beta_{cubic}, 2) & \text{// new ssthresh (at least 2 MSS)} \\ 77 | cwnd = ssthresh & \text{// window reduction} \\ 78 | \end{array} 79 | |-S 80 | Wₘₐₓ = cwnd // save cwnd before reduction 81 | ssthresh = max(cwnd * β , 2) // new ssthresh (at least 2 MSS) 82 | cubic 83 | cwnd = ssthresh // window reduction 84 | -A 85 | W = cwnd // save cwnd before reduction 86 | max 87 | ssthresh = max(cwnd * β , 2) // new ssthresh (at least 2 MSS) 88 | cubic 89 | cwnd = ssthresh // window reduction 90 | 91 | 92 | eq6 93 | \left = \left\{ 94 | \begin{array}{ll} 95 | \left & \text{if } W_{max} < W_{last\_max} \\ 96 | \left &\text{otherwise} \\ 97 | \end{array} \right. 98 | |-S 99 | ⎧ ╱ 1 + β ╲ 100 | ⎪╱ cubic ╲ 101 | ╱W , Wₘₐₓ╲ = ⎨╲ Wₘₐₓ, Wₘₐₓ * ────────── ╱ if Wₘₐₓ < W 102 | ╲ last_max ╱ ⎪ ╲ 2 ╱ last_max 103 | ⎩⟨Wₘₐₓ, Wₘₐₓ⟩ otherwise 104 | -A 105 | / / 1 + β \ 106 | |/ cubic \ 107 | |\ W , W * ---------- / if W < W 108 | /W , W \ = < \ max max 2 / max last_max 109 | \ last_max max/ |/W , W \ otherwise 110 | |\ max max/ 111 | \ 112 | 113 | 114 | eq7 115 | \left. 116 | \begin{array}{l} 117 | cwnd = prior\_cwnd \\ 118 | ssthresh = prior\_ssthresh \\ 119 | W_{max} = prior\_W_{max} \\ 120 | K = prior\_K \\ 121 | epoch\_start = prior\_epoch\_start \\ 122 | W_{est} = prior\_W_{est} \\ 123 | \end{array} 124 | \right\} 125 | \text{if }cwnd < prior\_cwnd 126 | |-S 127 | cwnd = prior_cwnd ⎫ 128 | ssthresh = prior_ssthresh ⎮ 129 | Wₘₐₓ = prior_Wₘₐₓ ⎮ 130 | K = prior_K ⎬if cwnd < prior_cwnd 131 | epoch_start = prior_epoch_start ⎮ 132 | Wₑₛₜ = prior_Wₑₛₜ ⎮ 133 | ⎭ 134 | -A 135 | cwnd = prior_cwnd \ 136 | ssthresh = prior_ssthresh | 137 | W = prior_W | 138 | max max | 139 | K = prior_K >if cwnd < prior_cwnd 140 | epoch_start = prior_epoch_start | 141 | W = prior_W | 142 | est est | 143 | / 144 | 145 | 146 | 147 | eq8 148 | \begin{array}{lll} 149 | ssthresh = & 150 | flight\_size * \beta_{cubic} & 151 | \text{new } ssthresh \\ 152 | cwnd_{prior} = & 153 | cwnd & 154 | \text{save } cwnd \\ 155 | cwnd = & 156 | \left\{ 157 | \begin{array}{ll} 158 | \mathrm{max}(ssthresh, 2) & \\ 159 | \mathrm{max}(ssthresh, 1) & \\ 160 | \end{array} 161 | \right. & 162 | \begin{array}{ll} 163 | \text{reduction on loss}, cwnd \text{ is at least 2 MSS} & \\ 164 | \text{reduction on ECE}, cwnd \text{ is at least 1 MSS} & \\ 165 | \end{array} 166 | \\ 167 | ssthresh = & 168 | \mathrm{max}(ssthresh, 2) & 169 | ssthresh \text{ is at least 2 MSS} \\ 170 | \end{array} 171 | |-S 172 | ssthresh = flight_size * β new ssthresh 173 | cubic 174 | cwndₚᵣᵢₒᵣ = cwnd save cwnd 175 | ⎧ max(ssthresh, 2) reduction on loss, cwnd is at least 2 MSS 176 | cwnd = ⎨ max(ssthresh, 1) reduction on ECE, cwnd is at least 1 MSS 177 | ⎩ 178 | ssthresh = max(ssthresh, 2) ssthresh is at least 2 MSS 179 | -A 180 | ssthresh = flight_size * β new ssthresh 181 | cubic 182 | cwnd = cwnd save cwnd 183 | prior 184 | / max(ssthresh, 2) reduction on loss, cwnd is at least 2 MSS 185 | cwnd = < max(ssthresh, 1) reduction on ECE, cwnd is at least 1 MSS 186 | \ 187 | ssthresh = max(ssthresh, 2) ssthresh is at least 2 MSS 188 | 189 | 190 | eq9 191 | \begin{align} 192 | f(x) & = \sin(x) \\ 193 | gobo(x) & = \arctan(\sin(x)) 194 | \end{align} 195 | |-S 196 | f(x) = sin(x) 197 | gobo(x) = arctan(sin(x)) 198 | -A 199 | f(x) = sin(x) 200 | gobo(x) = arctan(sin(x)) 201 | 202 | 203 | 204 | 205 | 206 | Shockly-Read-Hall recombination over depletion width 207 | SRH 208 | \int_0^W \frac{np}{n+p}dx = \int_0^W \frac{n_0}{exp \left( \frac{E_0(x-x_0)}{kT} \right)+exp \left( -\frac{E_0(x-x_0)}{kT}\right)}dx=\frac{n_0kT}{E_0} \left[ arctan \left( exp \left[\frac{E_0(x-x_0)}{kT}\right]\right)\right]^{x=W}_{x=0} \approx \frac{n_0kT}{E_0} pi 209 | |-S 210 | ⌠ᵂ np ⌠ᵂ n₀ n₀kT ⎡ ⎛ ⎡E₀(x-x₀)⎤⎞⎤ˣ⁼ᵂ n₀kT 211 | ⎮ ───dx = ⎮ ─────────────────────────────────dx=──── ⎢ arctan ⎜ exp ⎢────────⎥⎟⎥ ≈ ──── pi 212 | ⌡₀ n+p ⌡₀ ⎛ E₀(x-x₀) ⎞ ⎛ E₀(x-x₀)⎞ E₀ ⎣ ⎝ ⎣ kT ⎦⎠⎦ₓ₌₀ E₀ 213 | exp ⎜ ──────── ⎟+exp ⎜ -────────⎟ 214 | ⎝ kT ⎠ ⎝ kT ⎠ 215 | -A 216 | x=W 217 | W W n n kT + / +E (x-x )+\+ n kT 218 | / np / 0 0 | | | 0 0 ||| 0 219 | | ---dx = | ---------------------------------dx=---- | arctan | exp |--------||| ≈ ---- pi 220 | / n+p / / E (x-x ) \ / E (x-x )\ E + \ + kT +/+ E 221 | 0 0 | 0 0 | | 0 0 | 0 x=0 0 222 | exp | -------- |+exp | ---------| 223 | \ kT / \ kT / 224 | 225 | 226 | cases 227 | f(x) = \left{\begin{array}{lr} 228 | \frac{1}{x+1} +12 & -120 230 | \end{array}\right. 231 | |-S 232 | ⎧ 1 233 | ⎪ ─── +12 -120 237 | -A 238 | / 1 239 | | --- +12 -120 243 | 244 | 245 | Continues fraction 246 | contfraction 247 | a = \frac{1}{\sqrt{2} + 248 | \frac{1}{\sqrt{2} + 249 | \frac{1}{\sqrt{2} + 250 | \frac{1}{\sqrt{2} + ... 251 | }}}} 252 | |-S 253 | 1 254 | a = ──────────────────────────── 255 | ┌─┐ 1 256 | ╲│2 +────────────────────── 257 | ┌─┐ 1 258 | ╲│2 +──────────────── 259 | ┌─┐ 1 260 | ╲│2 +────────── 261 | ┌─┐ 262 | ╲│2 + ... 263 | -A 264 | 1 265 | a = ---------------------------- 266 | ___ 1 267 | \|2 +---------------------- 268 | ___ 1 269 | \|2 +---------------- 270 | ___ 1 271 | \|2 +---------- 272 | ___ 273 | \|2 + ... 274 | 275 | 276 | eq29 277 | \prod_{i=1}^{\infty} \sqrt{ 278 | a_{ala}+b^{ela}- \frac{ 279 | \left[ 280 | a+\frac{ 281 | a+b^{ 282 | \left( 283 | 3+4a 284 | \right) 285 | } 286 | }{ 287 | 4a-3c 288 | } 289 | \right] 290 | }{ 291 | a_1-\sqrt{2} 292 | } 293 | } 294 | + 295 | \left| 296 | \begin{array}{ccc} 297 | \frac{8}{2} &1 &3 \\ 298 | 2 &3 & 299 | \left| 300 | \begin{array}{cc} 301 | 1 &2 \\ 302 | 3 &4 303 | \end{array} 304 | \right| \\ 305 | 3 &\sqrt{5} &12 306 | \end{array} 307 | \right| 308 | |-S 309 | ┌───────────────────────────────────┐ 310 | │ ⎡ a+b ⁽ ³⁺⁴ᵃ ⁾ ⎤ ⎢8 ⎢ 311 | ∞ │ ⎢ a+─────────────── ⎥ ⎢─ 1 3 ⎢ 312 | ┬─┬ ╲ │ ⎣ 4a-3c ⎦ ⎢2 ⎢ 313 | │ │ ╲ │ aₐₗₐ+bᵉˡᵃ- ─────────────────────── +⎢ ⎢1 2 ⎢ ⎢ 314 | ⁱ⁼¹ ╲ │ ┌─┐ ⎢2 3 ⎢3 4 ⎢ ⎢ 315 | ╲│ a₁-╲│2 ⎢ ┌─┐ ⎢ 316 | ⎢3 ╲│5 12 ⎢ 317 | -A 318 | _____________________________________ 319 | | + ( 3+4a ) + 320 | | | a+b | |8 | 321 | ∞ | | a+--------------- | |- 1 3 | 322 | +-+ \ | ela + 4a-3c + |2 | 323 | | | \ | a +b - ----------------------- +| |1 2 | | 324 | i=1 \ | ala ___ |2 3 |3 4 | | 325 | \ | a -\|2 | ___ | 326 | \| 1 |3 \|5 12 | 327 | 328 | 329 | Taylor 330 | f(x) = \sum^{\infty}_{i=0} \frac{f^{(i)}(a)}{i!}(x-a)^i 331 | |-S 332 | ∞ 333 | ⎲ f⁽ⁱ⁾(a) 334 | f(x) = ⎳ ───────(x-a)ⁱ 335 | ⁱ⁼⁰ i! 336 | -A 337 | ∞ (i) 338 | __ f (a) i 339 | f(x) = \ -------(x-a) 340 | /_ i! 341 | i=0 342 | 343 | 344 | 345 | binom1 346 | \binom{a}{b} = \frac{a!}{(a-b)!b!} 347 | |-S 348 | ⎛a⎞ a! 349 | ⎜ ⎟ = ──────── 350 | ⎝b⎠ (a-b)!b! 351 | -A 352 | /a\ a! 353 | | | = -------- 354 | \b/ (a-b)!b! 355 | 356 | 357 | 358 | binom2 359 | \sum_{i=6}^{10}\left[\binom{A}{i} \binom{L}{10-i}\right] 360 | |-S 361 | ₁₀ 362 | ⎲ ⎡⎛A⎞ ⎛ L ⎞⎤ 363 | ⎳ ⎢⎜ ⎟ ⎜ ⎟⎥ 364 | ⁱ⁼⁶⎣⎝i⎠ ⎝10-i⎠⎦ 365 | -A 366 | 10 367 | __ +/A\ / L \+ 368 | \ || | | || 369 | /_ +\i/ \10-i/+ 370 | i=6 371 | 372 | 373 | 374 | binom3 375 | \sum_{i=6}^{10}{\frac{\binom{A}{i} \binom{L}{10-i}}{\binom{L + A}{10}}} 376 | |-S 377 | ⎛A⎞ ⎛ L ⎞ 378 | ₁₀ ⎜ ⎟ ⎜ ⎟ 379 | ⎲ ⎝i⎠ ⎝10-i⎠ 380 | ⎳ ────────── 381 | ⁱ⁼⁶ ⎛L + A⎞ 382 | ⎜ ⎟ 383 | ⎝ 10 ⎠ 384 | -A 385 | /A\ / L \ 386 | 10 | | | | 387 | __ \i/ \10-i/ 388 | \ ---------- 389 | /_ /L + A\ 390 | i=6 | | 391 | \ 10 / 392 | 393 | 394 | 395 | binom4 396 | C(N) = \binom{L}{10 - N} \sum_{i=0}^{min(N,2)}\left[\binom{B}{i} \sum_{j=0}^{min(2, 397 | N-i)}\left(\binom{B}{j} \binom{B}{min(2, N-i-j)}\right)\right] 398 | |-S 399 | min(N,2)⎡ min(2,N-i) ⎤ 400 | ⎛ L ⎞ ⎲ ⎢⎛B⎞ ⎲ ⎛⎛B⎞ ⎛ B ⎞⎞⎥ 401 | C(N) = ⎜ ⎟ ⎳ ⎢⎜ ⎟ ⎳ ⎜⎜ ⎟ ⎜ ⎟⎟⎥ 402 | ⎝10 - N⎠ ⁱ⁼⁰ ⎣⎝i⎠ ʲ⁼⁰ ⎝⎝j⎠ ⎝min(2, N-i-j)⎠⎠⎦ 403 | -A 404 | min(N,2)+ min(2,N-i) + 405 | / L \ __ |/B\ __ //B\ / B \\| 406 | C(N) = | | \ || | \ || | | ||| 407 | \10 - N/ /_ |\i/ /_ \\j/ \min(2, N-i-j)//| 408 | i=0 + j=0 + 409 | 410 | Lorenz Equations 411 | 412 | Lorenz 413 | \begin{aligned} 414 | \dot{x} & = \sigma(y-x) \\ 415 | \dot{y} & = \rho x - y - xz \\ 416 | \dot{z} & = -\beta z + xy 417 | \end{aligned} 418 | | -S | -m 419 | ẋ = σ(y-x) 420 | ẏ = ρx - y - xz 421 | ż = -βz + xy 422 | -A 423 | . 424 | x = σ(y-x) 425 | . 426 | y = ρx - y - xz 427 | . 428 | z = -βz + xy 429 | 430 | 431 | Cauchy-Schwarz Inequality 432 | CauchySchwarz 433 | \left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right) 434 | |-S 435 | ⎛ ₙ ⎞² ⎛ ₙ ⎞ ⎛ ₙ ⎞ 436 | ⎜ ⎲ ⎟ ⎜ ⎲ 2 ⎟ ⎜ ⎲ 2 ⎟ 437 | ⎜ ⎳ aₖ bₖ ⎟ ≤⎜ ⎳ aₖ ⎟ ⎜ ⎳ bₖ ⎟ 438 | ⎝ ᵏ⁼¹ ⎠ ⎝ ᵏ⁼¹ ⎠ ⎝ ᵏ⁼¹ ⎠ 439 | -A 440 | 2 441 | / n \ / n \ / n \ 442 | | __ | | __ 2 | | __ 2 | 443 | | \ a b | ≤| \ a | | \ b | 444 | | /_ k k | | /_ k | | /_ k | 445 | \ k=1 / \ k=1 / \ k=1 / 446 | 447 | 448 | cross-product 449 | CrossProd 450 | \mathbf{V}_1 \times \mathbf{V}_2 = \begin{vmatrix} \mathbf{i} & \mathbf{j} & \mathbf{k} \\ \frac{\partial X}{\partial u} & \frac{\partial Y}{\partial u} & 0 \\ \frac{\partial X}{\partial v} & \frac{\partial Y}{\partial v} & 0 \end{vmatrix} 451 | |-S 452 | ⎢ 𝐢 𝐣 𝐤 ⎢ 453 | ⎢ 𝜕X 𝜕Y ⎢ 454 | ⎢ ── ── 0 ⎢ 455 | 𝐕₁ ×𝐕₂ = ⎢ 𝜕u 𝜕u ⎢ 456 | ⎢ 𝜕X 𝜕Y ⎢ 457 | ⎢ ── ── 0 ⎢ 458 | ⎢ 𝜕v 𝜕v ⎢ 459 | -A 460 | | 𝐢 𝐣 𝐤 | 461 | | 𝜕X 𝜕Y | 462 | | -- -- 0 | 463 | 𝐕 ×𝐕 = | 𝜕u 𝜕u | 464 | 1 2 | 𝜕X 𝜕Y | 465 | | -- -- 0 | 466 | | 𝜕v 𝜕v | 467 | 468 | 469 | The probability of getting k heads when flipping a coin n times 470 | HeadProbability 471 | P(E) = {n\choose k} p^k (1-p)^{ n-k} 472 | |-S 473 | ⎛n⎞ 474 | P(E) = ⎜ ⎟ pᵏ (1-p) ⁿ⁻ᵏ 475 | ⎝k⎠ 476 | -A 477 | /n\ k n-k 478 | P(E) = | | p (1-p) 479 | \k/ 480 | 481 | 482 | An Identity of Ramanujan 483 | Ramanujan 484 | \frac{1}{\left(\sqrt{\phi \sqrt{5}}-\phi\right) e^{\frac25 \pi}} = 1+\frac{e^{-2\pi}}{1+\frac{e^{-4\pi}}{1+\frac{e^{-6\pi}}{1+\frac{e^{-8\pi}}{1+\ldots}}}} 485 | |-S 486 | -2π 487 | 1 e 488 | ────────────────── = 1+────────── 489 | 2 -4π 490 | ⎛ ┌─────┐ ⎞ ─ π e 491 | ⎜╲ │ ┌─┐ ⎟ 5 1+──────── 492 | ⎝ ╲│ϕ╲│5 -ϕ⎠ e -6π 493 | e 494 | 1+────── 495 | -8π 496 | e 497 | 1+──── 498 | 1+… 499 | -A 500 | -2π 501 | 1 e 502 | ------------------ = 1+---------- 503 | 2 -4π 504 | / _______ \ - π e 505 | |\ | ___ | 5 1+-------- 506 | \ \|ϕ\|5 -ϕ/ e -6π 507 | e 508 | 1+------ 509 | -8π 510 | e 511 | 1+---- 512 | 1+… 513 | 514 | 515 | A Rogers-Ramanujan Identity. 516 | Issue: utftex does not switch to a math environment from within a \text{} 517 | Should be fixed now, try that below! 518 | First the modified version with \text{for $|q|<1$} replaced with \text{for} |q|<1 519 | Rogers-Ramanujan 520 | 1 + \frac{q^2}{(1-q)}+\frac{q^6}{(1-q)(1-q^2)}+\cdots = \prod_{j=0}^{\infty}\frac{1}{(1-q^{5j+2})(1-q^{5j+3})}, \quad\quad \text{for} |q|<1. 521 | |-S 522 | ∞ 523 | q² q⁶ ┬─┬ 1 524 | 1 + ─────+───────────+⋯= │ │──────────────────, for |q|<1. 525 | (1-q) (1-q)(1-q²) ʲ⁼⁰(1-q⁵ʲ⁺²)(1-q⁵ʲ⁺³) 526 | -A 527 | 2 6 ∞ 528 | q q +-+ 1 529 | 1 + -----+-----------+⋯= | |------------------, for |q|<1. 530 | (1-q) 2 j=0 5j+2 5j+3 531 | (1-q)(1-q ) (1-q )(1-q ) 532 | 533 | A Rogers-Ramanujan Identity. 534 | here the original version 535 | Rogers-Ramanujan2 536 | 1 + \frac{q^2}{(1-q)}+\frac{q^6}{(1-q)(1-q^2)}+\cdots = \prod_{j=0}^{\infty}\frac{1}{(1-q^{5j+2})(1-q^{5j+3})}, \quad\quad \text{for $|q|<1$}. 537 | |-S 538 | ∞ 539 | q² q⁶ ┬─┬ 1 540 | 1 + ─────+───────────+⋯= │ │──────────────────, for |q|<1. 541 | (1-q) (1-q)(1-q²) ʲ⁼⁰(1-q⁵ʲ⁺²)(1-q⁵ʲ⁺³) 542 | -A 543 | 2 6 ∞ 544 | q q +-+ 1 545 | 1 + -----+-----------+⋯= | |------------------, for |q|<1. 546 | (1-q) 2 j=0 5j+2 5j+3 547 | (1-q)(1-q ) (1-q )(1-q ) 548 | -F mathnormal 549 | ∞ 550 | 𝑞² 𝑞⁶ ┬─┬ 1 551 | 1 + ─────+───────────+⋯= │ │──────────────────, for |𝑞|<1. 552 | (1-𝑞) (1-𝑞)(1-𝑞²) 𝑗=0 5𝑗+2 5𝑗+3 553 | (1-𝑞 )(1-𝑞 ) 554 | 555 | Maxwell’s Equations 556 | 557 | Maxwell 558 | \begin{aligned} 559 | \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ 560 | \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ 561 | \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ 562 | \nabla \cdot \vec{\mathbf{B}} & = 0 563 | \end{aligned} 564 | | -S | -m 565 | 1 𝜕𝐄⃗ 4π 566 | ∇×𝐁⃗ - ─ ── = ──𝐣⃗ 567 | c 𝜕t c 568 | ∇⋅𝐄⃗ = 4 πρ 569 | 1 𝜕𝐁⃗ 570 | ∇×𝐄⃗ + ─ ── = 𝟎⃗ 571 | c 𝜕t 572 | ∇⋅𝐁⃗ = 0 573 | -A 574 | 1 𝜕𝐄⃗ 4π 575 | ∇×𝐁⃗ - - -- = --𝐣⃗ 576 | c 𝜕t c 577 | ∇⋅𝐄⃗ = 4 πρ 578 | 1 𝜕𝐁⃗ 579 | ∇×𝐄⃗ + - -- = 𝟎⃗ 580 | c 𝜕t 581 | ∇⋅𝐁⃗ = 0 582 | 583 | 584 | One-Diode solar cell equation 585 | Diode 586 | I(V) = I_{00}\left(\frac{T}{T_0}\right)^3 \exp\left(\frac{E_\text{x}(T-T_0)}{kTT_0}\right) \left[\exp\left(\frac{V-I(V)R_\text{s}}{nkT}\right) - 1\right] - I_\text{ph} + \frac{V}{R_\text{sh}} 587 | |-S 588 | ⎛T ⎞³ ⎛Eₓ(T-T₀)⎞ ⎡ ⎛V-I(V)Rₛ⎞ ⎤ V 589 | I(V) = I₀₀⎜──⎟ exp⎜────────⎟ ⎢exp⎜────────⎟ - 1⎥ - Iₚₕ + ─── 590 | ⎝T₀⎠ ⎝ kTT₀ ⎠ ⎣ ⎝ nkT ⎠ ⎦ Rₛₕ 591 | -A 592 | 3 /E (T-T )\ + /V-I(V)R \ + 593 | /T \ | x 0 | | | s| | V 594 | I(V) = I |--| exp|--------| |exp|--------| - 1| - I + --- 595 | 00|T | | kTT | + \ nkT / + ph R 596 | \ 0/ \ 0 / sh 597 | 598 | -------------------------------------------------------------------------------- /src/unicodeblocks.h: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | int start, end; 3 | char *name; 4 | } BlockEntry; 5 | 6 | typedef struct { 7 | int start; 8 | int end; 9 | } Range; 10 | 11 | static const Range Combining[] = { 12 | {0x101fd, 0x101fd}, 13 | {0x102e0, 0x102e0}, 14 | {0x10376, 0x1037a}, 15 | {0x10a01, 0x10a03}, 16 | {0x10a05, 0x10a06}, 17 | {0x10a0c, 0x10a0f}, 18 | {0x10a38, 0x10a3a}, 19 | {0x10a3f, 0x10a3f}, 20 | {0x10ae5, 0x10ae6}, 21 | {0x11000, 0x11002}, 22 | {0x11038, 0x11046}, 23 | {0x1107f, 0x11082}, 24 | {0x110b0, 0x110ba}, 25 | {0x11100, 0x11102}, 26 | {0x11127, 0x11134}, 27 | {0x11173, 0x11173}, 28 | {0x11180, 0x11182}, 29 | {0x111b3, 0x111c0}, 30 | {0x111ca, 0x111cc}, 31 | {0x1122c, 0x11237}, 32 | {0x1123e, 0x1123e}, 33 | {0x112df, 0x112ea}, 34 | {0x11300, 0x11303}, 35 | {0x1133c, 0x1133c}, 36 | {0x1133e, 0x11344}, 37 | {0x11347, 0x11348}, 38 | {0x1134b, 0x1134d}, 39 | {0x11357, 0x11357}, 40 | {0x11362, 0x11363}, 41 | {0x11366, 0x1136c}, 42 | {0x11370, 0x11374}, 43 | {0x11435, 0x11446}, 44 | {0x114b0, 0x114c3}, 45 | {0x115af, 0x115b5}, 46 | {0x115b8, 0x115c0}, 47 | {0x115dc, 0x115dd}, 48 | {0x11630, 0x11640}, 49 | {0x116ab, 0x116b7}, 50 | {0x1171d, 0x1172b}, 51 | {0x11a01, 0x11a0a}, 52 | {0x11a33, 0x11a39}, 53 | {0x11a3b, 0x11a3e}, 54 | {0x11a51, 0x11a5a}, 55 | {0x11a8a, 0x11a98}, 56 | {0x11c30, 0x11c36}, 57 | {0x11c38, 0x11c3f}, 58 | {0x11c92, 0x11ca7}, 59 | {0x11ca9, 0x11cb6}, 60 | {0x11d31, 0x11d36}, 61 | {0x11d3a, 0x11d3a}, 62 | {0x11d3c, 0x11d3d}, 63 | {0x11d3f, 0x11d44}, 64 | {0x11d47, 0x11d47}, 65 | {0x16af0, 0x16af4}, 66 | {0x16b30, 0x16b36}, 67 | {0x16f51, 0x16f7e}, 68 | {0x16f8f, 0x16f92}, 69 | {0x1bc9d, 0x1bc9e}, 70 | {0x1d165, 0x1d169}, 71 | {0x1d16d, 0x1d172}, 72 | {0x1d17b, 0x1d182}, 73 | {0x1d185, 0x1d18b}, 74 | {0x1d1aa, 0x1d1ad}, 75 | {0x1d242, 0x1d244}, 76 | {0x1da00, 0x1da36}, 77 | {0x1da3b, 0x1da6c}, 78 | {0x1da75, 0x1da75}, 79 | {0x1da84, 0x1da84}, 80 | {0x1da9b, 0x1da9f}, 81 | {0x1daa1, 0x1daaf}, 82 | {0x1e000, 0x1e006}, 83 | {0x1e008, 0x1e018}, 84 | {0x1e01b, 0x1e021}, 85 | {0x1e023, 0x1e024}, 86 | {0x1e026, 0x1e02a}, 87 | {0x1e8d0, 0x1e8d6}, 88 | {0x1e944, 0x1e94a}, 89 | {0x300, 0x36f}, 90 | {0x483, 0x489}, 91 | {0x591, 0x5bd}, 92 | {0x5bf, 0x5bf}, 93 | {0x5c1, 0x5c2}, 94 | {0x5c4, 0x5c5}, 95 | {0x5c7, 0x5c7}, 96 | {0x610, 0x61a}, 97 | {0x64b, 0x65f}, 98 | {0x670, 0x670}, 99 | {0x6d6, 0x6dc}, 100 | {0x6df, 0x6e4}, 101 | {0x6e7, 0x6e8}, 102 | {0x6ea, 0x6ed}, 103 | {0x711, 0x711}, 104 | {0x730, 0x74a}, 105 | {0x7a6, 0x7b0}, 106 | {0x7eb, 0x7f3}, 107 | {0x816, 0x819}, 108 | {0x81b, 0x823}, 109 | {0x825, 0x827}, 110 | {0x829, 0x82d}, 111 | {0x859, 0x85b}, 112 | {0x8d4, 0x8e1}, 113 | {0x8e3, 0x903}, 114 | {0x93a, 0x93c}, 115 | {0x93e, 0x94f}, 116 | {0x951, 0x957}, 117 | {0x962, 0x963}, 118 | {0x981, 0x983}, 119 | {0x9bc, 0x9bc}, 120 | {0x9be, 0x9c4}, 121 | {0x9c7, 0x9c8}, 122 | {0x9cb, 0x9cd}, 123 | {0x9d7, 0x9d7}, 124 | {0x9e2, 0x9e3}, 125 | {0xa01, 0xa03}, 126 | {0xa3c, 0xa3c}, 127 | {0xa3e, 0xa42}, 128 | {0xa47, 0xa48}, 129 | {0xa4b, 0xa4d}, 130 | {0xa51, 0xa51}, 131 | {0xa70, 0xa71}, 132 | {0xa75, 0xa75}, 133 | {0xa81, 0xa83}, 134 | {0xabc, 0xabc}, 135 | {0xabe, 0xac5}, 136 | {0xac7, 0xac9}, 137 | {0xacb, 0xacd}, 138 | {0xae2, 0xae3}, 139 | {0xafa, 0xaff}, 140 | {0xb01, 0xb03}, 141 | {0xb3c, 0xb3c}, 142 | {0xb3e, 0xb44}, 143 | {0xb47, 0xb48}, 144 | {0xb4b, 0xb4d}, 145 | {0xb56, 0xb57}, 146 | {0xb62, 0xb63}, 147 | {0xb82, 0xb82}, 148 | {0xbbe, 0xbc2}, 149 | {0xbc6, 0xbc8}, 150 | {0xbca, 0xbcd}, 151 | {0xbd7, 0xbd7}, 152 | {0xc00, 0xc03}, 153 | {0xc3e, 0xc44}, 154 | {0xc46, 0xc48}, 155 | {0xc4a, 0xc4d}, 156 | {0xc55, 0xc56}, 157 | {0xc62, 0xc63}, 158 | {0xc81, 0xc83}, 159 | {0xcbc, 0xcbc}, 160 | {0xcbe, 0xcc4}, 161 | {0xcc6, 0xcc8}, 162 | {0xcca, 0xccd}, 163 | {0xcd5, 0xcd6}, 164 | {0xce2, 0xce3}, 165 | {0xd00, 0xd03}, 166 | {0xd3b, 0xd3c}, 167 | {0xd3e, 0xd44}, 168 | {0xd46, 0xd48}, 169 | {0xd4a, 0xd4d}, 170 | {0xd57, 0xd57}, 171 | {0xd62, 0xd63}, 172 | {0xd82, 0xd83}, 173 | {0xdca, 0xdca}, 174 | {0xdcf, 0xdd4}, 175 | {0xdd6, 0xdd6}, 176 | {0xdd8, 0xddf}, 177 | {0xdf2, 0xdf3}, 178 | {0xe31, 0xe31}, 179 | {0xe34, 0xe3a}, 180 | {0xe47, 0xe4e}, 181 | {0xeb1, 0xeb1}, 182 | {0xeb4, 0xeb9}, 183 | {0xebb, 0xebc}, 184 | {0xec8, 0xecd}, 185 | {0xf18, 0xf19}, 186 | {0xf35, 0xf35}, 187 | {0xf37, 0xf37}, 188 | {0xf39, 0xf39}, 189 | {0xf3e, 0xf3f}, 190 | {0xf71, 0xf84}, 191 | {0xf86, 0xf87}, 192 | {0xf8d, 0xf97}, 193 | {0xf99, 0xfbc}, 194 | {0xfc6, 0xfc6}, 195 | {0x102b, 0x103e}, 196 | {0x1056, 0x1059}, 197 | {0x105e, 0x1060}, 198 | {0x1062, 0x1064}, 199 | {0x1067, 0x106d}, 200 | {0x1071, 0x1074}, 201 | {0x1082, 0x108d}, 202 | {0x108f, 0x108f}, 203 | {0x109a, 0x109d}, 204 | {0x135d, 0x135f}, 205 | {0x1712, 0x1714}, 206 | {0x1732, 0x1734}, 207 | {0x1752, 0x1753}, 208 | {0x1772, 0x1773}, 209 | {0x17b4, 0x17d3}, 210 | {0x17dd, 0x17dd}, 211 | {0x180b, 0x180d}, 212 | {0x18a9, 0x18a9}, 213 | {0x1920, 0x192b}, 214 | {0x1930, 0x193b}, 215 | {0x1a17, 0x1a1b}, 216 | {0x1a55, 0x1a5e}, 217 | {0x1a60, 0x1a7c}, 218 | {0x1a7f, 0x1a7f}, 219 | {0x1ab0, 0x1abe}, 220 | {0x1b00, 0x1b04}, 221 | {0x1b34, 0x1b44}, 222 | {0x1b6b, 0x1b73}, 223 | {0x1b80, 0x1b82}, 224 | {0x1ba1, 0x1bad}, 225 | {0x1be6, 0x1bf3}, 226 | {0x1c24, 0x1c37}, 227 | {0x1cd0, 0x1cd2}, 228 | {0x1cd4, 0x1ce8}, 229 | {0x1ced, 0x1ced}, 230 | {0x1cf2, 0x1cf4}, 231 | {0x1cf7, 0x1cf9}, 232 | {0x1dc0, 0x1df9}, 233 | {0x1dfb, 0x1dff}, 234 | {0x20d0, 0x20f0}, 235 | {0x2cef, 0x2cf1}, 236 | {0x2d7f, 0x2d7f}, 237 | {0x2de0, 0x2dff}, 238 | {0x302a, 0x302f}, 239 | {0x3099, 0x309a}, 240 | {0xa66f, 0xa672}, 241 | {0xa674, 0xa67d}, 242 | {0xa69e, 0xa69f}, 243 | {0xa6f0, 0xa6f1}, 244 | {0xa802, 0xa802}, 245 | {0xa806, 0xa806}, 246 | {0xa80b, 0xa80b}, 247 | {0xa823, 0xa827}, 248 | {0xa880, 0xa881}, 249 | {0xa8b4, 0xa8c5}, 250 | {0xa8e0, 0xa8f1}, 251 | {0xa926, 0xa92d}, 252 | {0xa947, 0xa953}, 253 | {0xa980, 0xa983}, 254 | {0xa9b3, 0xa9c0}, 255 | {0xa9e5, 0xa9e5}, 256 | {0xaa29, 0xaa36}, 257 | {0xaa43, 0xaa43}, 258 | {0xaa4c, 0xaa4d}, 259 | {0xaa7b, 0xaa7d}, 260 | {0xaab0, 0xaab0}, 261 | {0xaab2, 0xaab4}, 262 | {0xaab7, 0xaab8}, 263 | {0xaabe, 0xaabf}, 264 | {0xaac1, 0xaac1}, 265 | {0xaaeb, 0xaaef}, 266 | {0xaaf5, 0xaaf6}, 267 | {0xabe3, 0xabea}, 268 | {0xabec, 0xabed}, 269 | {0xfb1e, 0xfb1e}, 270 | {0xfe00, 0xfe0f}, 271 | {0xe040, 0xe04f}, 272 | {0xe056, 0xe058}, 273 | {0xe05a, 0xe05a}, 274 | {0xe05c, 0xe05d}, 275 | {0xe06c, 0xe06e}, 276 | {0xe0ea, 0xe0ec}, 277 | {0xe185, 0xe18c}, 278 | {0xe256, 0xe259}, 279 | {0xf8bf, 0xf8bf}, 280 | {0xf8c5, 0xf8c6}, 281 | {-1, -1} 282 | }; 283 | 284 | static int NUCB=273; // number of unicode code blocks 285 | static const BlockEntry BlockTable[273]={ 286 | {0x0000, 0x007F, "Basic Latin[g]"}, 287 | {0x0080, 0x00FF, "Latin-1 Supplement[h]"}, 288 | {0x0100, 0x017F, "Latin Extended-A"}, 289 | {0x0180, 0x024F, "Latin Extended-B"}, 290 | {0x0250, 0x02AF, "IPA Extensions"}, 291 | {0x02B0, 0x02FF, "Spacing Modifier Letters"}, 292 | {0x0300, 0x036F, "Combining Diacritical Marks"}, 293 | {0x0370, 0x03FF, "Greek and Coptic"}, 294 | {0x0400, 0x04FF, "Cyrillic"}, 295 | {0x0500, 0x052F, "Cyrillic Supplement"}, 296 | {0x0530, 0x058F, "Armenian"}, 297 | {0x0590, 0x05FF, "Hebrew"}, 298 | {0x0600, 0x06FF, "Arabic"}, 299 | {0x0700, 0x074F, "Syriac"}, 300 | {0x0750, 0x077F, "Arabic Supplement"}, 301 | {0x0780, 0x07BF, "Thaana"}, 302 | {0x07C0, 0x07FF, "NKo"}, 303 | {0x0800, 0x083F, "Samaritan"}, 304 | {0x0840, 0x085F, "Mandaic"}, 305 | {0x08A0, 0x08FF, "Arabic Extended-A"}, 306 | {0x0900, 0x097F, "Devanagari"}, 307 | {0x0980, 0x09FF, "Bengali"}, 308 | {0x0A00, 0x0A7F, "Gurmukhi"}, 309 | {0x0A80, 0x0AFF, "Gujarati"}, 310 | {0x0B00, 0x0B7F, "Oriya"}, 311 | {0x0B80, 0x0BFF, "Tamil"}, 312 | {0x0C00, 0x0C7F, "Telugu"}, 313 | {0x0C80, 0x0CFF, "Kannada"}, 314 | {0x0D00, 0x0D7F, "Malayalam"}, 315 | {0x0D80, 0x0DFF, "Sinhala"}, 316 | {0x0E00, 0x0E7F, "Thai"}, 317 | {0x0E80, 0x0EFF, "Lao"}, 318 | {0x0F00, 0x0FFF, "Tibetan"}, 319 | {0x1000, 0x109F, "Myanmar"}, 320 | {0x10A0, 0x10FF, "Georgian"}, 321 | {0x1100, 0x11FF, "Hangul Jamo"}, 322 | {0x1200, 0x137F, "Ethiopic"}, 323 | {0x1380, 0x139F, "Ethiopic Supplement"}, 324 | {0x13A0, 0x13FF, "Cherokee"}, 325 | {0x1400, 0x167F, "Unified Canadian Aboriginal Syllabics"}, 326 | {0x1680, 0x169F, "Ogham"}, 327 | {0x16A0, 0x16FF, "Runic"}, 328 | {0x1700, 0x171F, "Tagalog"}, 329 | {0x1720, 0x173F, "Hanunoo"}, 330 | {0x1740, 0x175F, "Buhid"}, 331 | {0x1760, 0x177F, "Tagbanwa"}, 332 | {0x1780, 0x17FF, "Khmer"}, 333 | {0x1800, 0x18AF, "Mongolian"}, 334 | {0x18B0, 0x18FF, "Unified Canadian Aboriginal Syllabics Extended"}, 335 | {0x1900, 0x194F, "Limbu"}, 336 | {0x1950, 0x197F, "Tai Le"}, 337 | {0x1980, 0x19DF, "New Tai Lue"}, 338 | {0x19E0, 0x19FF, "Khmer Symbols"}, 339 | {0x1A00, 0x1A1F, "Buginese"}, 340 | {0x1A20, 0x1AAF, "Tai Tham"}, 341 | {0x1AB0, 0x1AFF, "Combining Diacritical Marks Extended"}, 342 | {0x1B00, 0x1B7F, "Balinese"}, 343 | {0x1B80, 0x1BBF, "Sundanese"}, 344 | {0x1BC0, 0x1BFF, "Batak"}, 345 | {0x1C00, 0x1C4F, "Lepcha"}, 346 | {0x1C50, 0x1C7F, "Ol Chiki"}, 347 | {0x1C80, 0x1C8F, "Cyrillic Extended-C"}, 348 | {0x1CC0, 0x1CCF, "Sundanese Supplement"}, 349 | {0x1CD0, 0x1CFF, "Vedic Extensions"}, 350 | {0x1D00, 0x1D7F, "Phonetic Extensions"}, 351 | {0x1D80, 0x1DBF, "Phonetic Extensions Supplement"}, 352 | {0x1DC0, 0x1DFF, "Combining Diacritical Marks Supplement"}, 353 | {0x1E00, 0x1EFF, "Latin Extended Additional"}, 354 | {0x1F00, 0x1FFF, "Greek Extended"}, 355 | {0x2000, 0x206F, "General Punctuation"}, 356 | {0x2070, 0x209F, "Superscripts and Subscripts"}, 357 | {0x20A0, 0x20CF, "Currency Symbols"}, 358 | {0x20D0, 0x20FF, "Combining Diacritical Marks for Symbols"}, 359 | {0x2100, 0x214F, "Letterlike Symbols"}, 360 | {0x2150, 0x218F, "Number Forms"}, 361 | {0x2190, 0x21FF, "Arrows"}, 362 | {0x2200, 0x22FF, "Mathematical Operators"}, 363 | {0x2300, 0x23FF, "Miscellaneous Technical"}, 364 | {0x2400, 0x243F, "Control Pictures"}, 365 | {0x2440, 0x245F, "Optical Character Recognition"}, 366 | {0x2460, 0x24FF, "Enclosed Alphanumerics"}, 367 | {0x2500, 0x257F, "Box Drawing"}, 368 | {0x2580, 0x259F, "Block Elements"}, 369 | {0x25A0, 0x25FF, "Geometric Shapes"}, 370 | {0x2600, 0x26FF, "Miscellaneous Symbols"}, 371 | {0x2700, 0x27BF, "Dingbats"}, 372 | {0x27C0, 0x27EF, "Miscellaneous Mathematical Symbols-A"}, 373 | {0x27F0, 0x27FF, "Supplemental Arrows-A"}, 374 | {0x2800, 0x28FF, "Braille Patterns"}, 375 | {0x2900, 0x297F, "Supplemental Arrows-B"}, 376 | {0x2980, 0x29FF, "Miscellaneous Mathematical Symbols-B"}, 377 | {0x2A00, 0x2AFF, "Supplemental Mathematical Operators"}, 378 | {0x2B00, 0x2BFF, "Miscellaneous Symbols and Arrows"}, 379 | {0x2C00, 0x2C5F, "Glagolitic"}, 380 | {0x2C60, 0x2C7F, "Latin Extended-C"}, 381 | {0x2C80, 0x2CFF, "Coptic"}, 382 | {0x2D00, 0x2D2F, "Georgian Supplement"}, 383 | {0x2D30, 0x2D7F, "Tifinagh"}, 384 | {0x2D80, 0x2DDF, "Ethiopic Extended"}, 385 | {0x2DE0, 0x2DFF, "Cyrillic Extended-A"}, 386 | {0x2E00, 0x2E7F, "Supplemental Punctuation"}, 387 | {0x2E80, 0x2EFF, "CJK Radicals Supplement"}, 388 | {0x2F00, 0x2FDF, "Kangxi Radicals"}, 389 | {0x2FF0, 0x2FFF, "Ideographic Description Characters"}, 390 | {0x3000, 0x303F, "CJK Symbols and Punctuation"}, 391 | {0x3040, 0x309F, "Hiragana"}, 392 | {0x30A0, 0x30FF, "Katakana"}, 393 | {0x3100, 0x312F, "Bopomofo"}, 394 | {0x3130, 0x318F, "Hangul Compatibility Jamo"}, 395 | {0x3190, 0x319F, "Kanbun"}, 396 | {0x31A0, 0x31BF, "Bopomofo Extended"}, 397 | {0x31C0, 0x31EF, "CJK Strokes"}, 398 | {0x31F0, 0x31FF, "Katakana Phonetic Extensions"}, 399 | {0x3200, 0x32FF, "Enclosed CJK Letters and Months"}, 400 | {0x3300, 0x33FF, "CJK Compatibility"}, 401 | {0x3400, 0x4DBF, "CJK Unified Ideographs Extension A"}, 402 | {0x4DC0, 0x4DFF, "Yijing Hexagram Symbols"}, 403 | {0x4E00, 0x9FFF, "CJK Unified Ideographs"}, 404 | {0xA000, 0xA48F, "Yi Syllables"}, 405 | {0xA490, 0xA4CF, "Yi Radicals"}, 406 | {0xA4D0, 0xA4FF, "Lisu"}, 407 | {0xA500, 0xA63F, "Vai"}, 408 | {0xA640, 0xA69F, "Cyrillic Extended-B"}, 409 | {0xA6A0, 0xA6FF, "Bamum"}, 410 | {0xA700, 0xA71F, "Modifier Tone Letters"}, 411 | {0xA720, 0xA7FF, "Latin Extended-D"}, 412 | {0xA800, 0xA82F, "Syloti Nagri"}, 413 | {0xA830, 0xA83F, "Common Indic Number Forms"}, 414 | {0xA840, 0xA87F, "Phags-pa"}, 415 | {0xA880, 0xA8DF, "Saurashtra"}, 416 | {0xA8E0, 0xA8FF, "Devanagari Extended"}, 417 | {0xA900, 0xA92F, "Kayah Li"}, 418 | {0xA930, 0xA95F, "Rejang"}, 419 | {0xA960, 0xA97F, "Hangul Jamo Extended-A"}, 420 | {0xA980, 0xA9DF, "Javanese"}, 421 | {0xA9E0, 0xA9FF, "Myanmar Extended-B"}, 422 | {0xAA00, 0xAA5F, "Cham"}, 423 | {0xAA60, 0xAA7F, "Myanmar Extended-A"}, 424 | {0xAA80, 0xAADF, "Tai Viet"}, 425 | {0xAAE0, 0xAAFF, "Meetei Mayek Extensions"}, 426 | {0xAB00, 0xAB2F, "Ethiopic Extended-A"}, 427 | {0xAB30, 0xAB6F, "Latin Extended-E"}, 428 | {0xAB70, 0xABBF, "Cherokee Supplement"}, 429 | {0xABC0, 0xABFF, "Meetei Mayek"}, 430 | {0xAC00, 0xD7AF, "Hangul Syllables"}, 431 | {0xD7B0, 0xD7FF, "Hangul Jamo Extended-B"}, 432 | {0xD800, 0xDB7F, "High Surrogates"}, 433 | {0xDB80, 0xDBFF, "High Private Use Surrogates"}, 434 | {0xDC00, 0xDFFF, "Low Surrogates"}, 435 | {0xE000, 0xF8FF, "Private Use Area"}, 436 | {0xF900, 0xFAFF, "CJK Compatibility Ideographs"}, 437 | {0xFB00, 0xFB4F, "Alphabetic Presentation Forms"}, 438 | {0xFB50, 0xFDFF, "Arabic Presentation Forms-A"}, 439 | {0xFE00, 0xFE0F, "Variation Selectors"}, 440 | {0xFE10, 0xFE1F, "Vertical Forms"}, 441 | {0xFE20, 0xFE2F, "Combining Half Marks"}, 442 | {0xFE30, 0xFE4F, "CJK Compatibility Forms"}, 443 | {0xFE50, 0xFE6F, "Small Form Variants"}, 444 | {0xFE70, 0xFEFF, "Arabic Presentation Forms-B"}, 445 | {0xFF00, 0xFFEF, "Halfwidth and Fullwidth Forms"}, 446 | {0xFFF0, 0xFFFF, "Specials"}, 447 | {0x10000, 0x1007F, "Linear B Syllabary"}, 448 | {0x10080, 0x100FF, "Linear B Ideograms"}, 449 | {0x10100, 0x1013F, "Aegean Numbers"}, 450 | {0x10140, 0x1018F, "Ancient Greek Numbers"}, 451 | {0x10190, 0x101CF, "Ancient Symbols"}, 452 | {0x101D0, 0x101FF, "Phaistos Disc"}, 453 | {0x10280, 0x1029F, "Lycian"}, 454 | {0x102A0, 0x102DF, "Carian"}, 455 | {0x102E0, 0x102FF, "Coptic Epact Numbers"}, 456 | {0x10300, 0x1032F, "Old Italic"}, 457 | {0x10330, 0x1034F, "Gothic"}, 458 | {0x10350, 0x1037F, "Old Permic"}, 459 | {0x10380, 0x1039F, "Ugaritic"}, 460 | {0x103A0, 0x103DF, "Old Persian"}, 461 | {0x10400, 0x1044F, "Deseret"}, 462 | {0x10450, 0x1047F, "Shavian"}, 463 | {0x10480, 0x104AF, "Osmanya"}, 464 | {0x104B0, 0x104FF, "Osage"}, 465 | {0x10500, 0x1052F, "Elbasan"}, 466 | {0x10530, 0x1056F, "Caucasian Albanian"}, 467 | {0x10600, 0x1077F, "Linear A"}, 468 | {0x10800, 0x1083F, "Cypriot Syllabary"}, 469 | {0x10840, 0x1085F, "Imperial Aramaic"}, 470 | {0x10860, 0x1087F, "Palmyrene"}, 471 | {0x10880, 0x108AF, "Nabataean"}, 472 | {0x108E0, 0x108FF, "Hatran"}, 473 | {0x10900, 0x1091F, "Phoenician"}, 474 | {0x10920, 0x1093F, "Lydian"}, 475 | {0x10980, 0x1099F, "Meroitic Hieroglyphs"}, 476 | {0x109A0, 0x109FF, "Meroitic Cursive"}, 477 | {0x10A00, 0x10A5F, "Kharoshthi"}, 478 | {0x10A60, 0x10A7F, "Old South Arabian"}, 479 | {0x10A80, 0x10A9F, "Old North Arabian"}, 480 | {0x10AC0, 0x10AFF, "Manichaean"}, 481 | {0x10B00, 0x10B3F, "Avestan"}, 482 | {0x10B40, 0x10B5F, "Inscriptional Parthian"}, 483 | {0x10B60, 0x10B7F, "Inscriptional Pahlavi"}, 484 | {0x10B80, 0x10BAF, "Psalter Pahlavi"}, 485 | {0x10C00, 0x10C4F, "Old Turkic"}, 486 | {0x10C80, 0x10CFF, "Old Hungarian"}, 487 | {0x10E60, 0x10E7F, "Rumi Numeral Symbols"}, 488 | {0x11000, 0x1107F, "Brahmi"}, 489 | {0x11080, 0x110CF, "Kaithi"}, 490 | {0x110D0, 0x110FF, "Sora Sompeng"}, 491 | {0x11100, 0x1114F, "Chakma"}, 492 | {0x11150, 0x1117F, "Mahajani"}, 493 | {0x11180, 0x111DF, "Sharada"}, 494 | {0x111E0, 0x111FF, "Sinhala Archaic Numbers"}, 495 | {0x11200, 0x1124F, "Khojki"}, 496 | {0x11280, 0x112AF, "Multani"}, 497 | {0x112B0, 0x112FF, "Khudawadi"}, 498 | {0x11300, 0x1137F, "Grantha"}, 499 | {0x11400, 0x1147F, "Newa"}, 500 | {0x11480, 0x114DF, "Tirhuta"}, 501 | {0x11580, 0x115FF, "Siddham"}, 502 | {0x11600, 0x1165F, "Modi"}, 503 | {0x11660, 0x1167F, "Mongolian Supplement"}, 504 | {0x11680, 0x116CF, "Takri"}, 505 | {0x11700, 0x1173F, "Ahom"}, 506 | {0x118A0, 0x118FF, "Warang Citi"}, 507 | {0x11AC0, 0x11AFF, "Pau Cin Hau"}, 508 | {0x11C00, 0x11C6F, "Bhaiksuki"}, 509 | {0x11C70, 0x11CBF, "Marchen"}, 510 | {0x12000, 0x123FF, "Cuneiform"}, 511 | {0x12400, 0x1247F, "Cuneiform Numbers and Punctuation"}, 512 | {0x12480, 0x1254F, "Early Dynastic Cuneiform"}, 513 | {0x13000, 0x1342F, "Egyptian Hieroglyphs"}, 514 | {0x14400, 0x1467F, "Anatolian Hieroglyphs"}, 515 | {0x16800, 0x16A3F, "Bamum Supplement"}, 516 | {0x16A40, 0x16A6F, "Mro"}, 517 | {0x16AD0, 0x16AFF, "Bassa Vah"}, 518 | {0x16B00, 0x16B8F, "Pahawh Hmong"}, 519 | {0x16F00, 0x16F9F, "Miao"}, 520 | {0x16FE0, 0x16FFF, "Ideographic Symbols and Punctuation"}, 521 | {0x17000, 0x187FF, "Tangut"}, 522 | {0x18800, 0x18AFF, "Tangut Components"}, 523 | {0x1B000, 0x1B0FF, "Kana Supplement"}, 524 | {0x1BC00, 0x1BC9F, "Duployan"}, 525 | {0x1BCA0, 0x1BCAF, "Shorthand Format Controls"}, 526 | {0x1D000, 0x1D0FF, "Byzantine Musical Symbols"}, 527 | {0x1D100, 0x1D1FF, "Musical Symbols"}, 528 | {0x1D200, 0x1D24F, "Ancient Greek Musical Notation"}, 529 | {0x1D300, 0x1D35F, "Tai Xuan Jing Symbols"}, 530 | {0x1D360, 0x1D37F, "Counting Rod Numerals"}, 531 | {0x1D400, 0x1D7FF, "Mathematical Alphanumeric Symbols"}, 532 | {0x1D800, 0x1DAAF, "Sutton SignWriting"}, 533 | {0x1E000, 0x1E02F, "Glagolitic Supplement"}, 534 | {0x1E800, 0x1E8DF, "Mende Kikakui"}, 535 | {0x1E900, 0x1E95F, "Adlam"}, 536 | {0x1EE00, 0x1EEFF, "Arabic Mathematical Alphabetic Symbols"}, 537 | {0x1F000, 0x1F02F, "Mahjong Tiles"}, 538 | {0x1F030, 0x1F09F, "Domino Tiles"}, 539 | {0x1F0A0, 0x1F0FF, "Playing Cards"}, 540 | {0x1F100, 0x1F1FF, "Enclosed Alphanumeric Supplement"}, 541 | {0x1F200, 0x1F2FF, "Enclosed Ideographic Supplement"}, 542 | {0x1F300, 0x1F5FF, "Miscellaneous Symbols and Pictographs"}, 543 | {0x1F600, 0x1F64F, "Emoticons"}, 544 | {0x1F650, 0x1F67F, "Ornamental Dingbats"}, 545 | {0x1F680, 0x1F6FF, "Transport and Map Symbols"}, 546 | {0x1F700, 0x1F77F, "Alchemical Symbols"}, 547 | {0x1F780, 0x1F7FF, "Geometric Shapes Extended"}, 548 | {0x1F800, 0x1F8FF, "Supplemental Arrows-C"}, 549 | {0x1F900, 0x1F9FF, "Supplemental Symbols and Pictographs"}, 550 | {0x20000, 0x2A6DF, "CJK Unified Ideographs Extension B"}, 551 | {0x2A700, 0x2B73F, "CJK Unified Ideographs Extension C"}, 552 | {0x2B740, 0x2B81F, "CJK Unified Ideographs Extension D"}, 553 | {0x2B820, 0x2CEAF, "CJK Unified Ideographs Extension E"}, 554 | {0x2F800, 0x2FA1F, "CJK Compatibility Ideographs Supplement"}, 555 | {0xE0000, 0xE007F, "Tags"}, 556 | {0xE0100, 0xE01EF, "Variation Selectors Supplement"}, 557 | {0xF0000, 0xFFFFF, "Supplementary Private Use Area-A"}, 558 | {0x100000, 0x10FFFF, "Supplementary Private Use Area-B"} 559 | }; 560 | 561 | static const Range Wide[] = { 562 | /* wide characters */ 563 | {0x1100,0x11F9}, /* ᄀ..ᇹ; HANGUL CHOSEONG KIYEOK..HANGUL JONGSEONG YEORINHIEUH */ 564 | {0x3000,0x303F}, /*  ..〿; IDEOGRAPHIC SPACE..IDEOGRAPHIC HALF FILL SPACE*/ 565 | {0x3041,0x3094}, /* ぁ..ゔ; HIRAGANA LETTER SMALL A..HIRAGANA LETTER VU*/ 566 | {0x3099,0x309E}, /* ◦゙..ゞ; COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..HIRAGANA VOICED ITERATION MARK*/ 567 | {0x30A1,0x30FE}, /* ァ..ヾ; KATAKANA LETTER SMALL A..KATAKANA VOICED ITERATION MARK*/ 568 | {0x3131,0x318E}, /* ㄱ..ㆎ; HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE*/ 569 | {0x3190,0x319F}, /* ㆐..㆟; IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION MAN MARK*/ 570 | {0x3200,0x321C}, /* ㈀..㈜; PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED HANGUL CIEUC U*/ 571 | {0x3220,0x3243}, /* ㈠..㉃; PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH REACH*/ 572 | {0x3260,0x32B0}, /* ㉠..㊰; CIRCLED HANGUL KIYEOK..CIRCLED IDEOGRAPH NIGHT*/ 573 | {0x32C0,0x3376}, /* ㋀..㍶; IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY..SQUARE PC*/ 574 | {0x337B,0x33DD}, /* ㍻..㏝; SQUARE ERA NAME HEISEI..SQUARE WB*/ 575 | {0x33E0,0x33FE}, /* ㏠..㏾; IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE..IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE*/ 576 | {0x4E00,0x9FA5}, /* 一..龥; (!CJK Ideograph, First!)..(!CJK Ideograph, Last!)*/ 577 | {0xAC00,0xD7A3}, /* 가..힣; (!Hangul Syllable, First!)..(!Hangul Syllable, Last!)*/ 578 | {0xE000,0xE757}, /* ..; (!Private Use, First!)..(!Private Use, First!)*/ 579 | {0xF900,0xFA2D}, /* 豈..鶴; CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA2D*/ 580 | {-1, -1} 581 | }; 582 | static const Range Full[] = { 583 | /* full width characters */ 584 | {0xFE30,0xFE44}, /* ︰..﹄; PRESENTATION FORM FOR VERTICAL TWO DOT LEADER..PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET*/ 585 | {0xFE49,0xFE52}, /* ﹉..﹒; DASHED OVERLINE..SMALL FULL STOP*/ 586 | {0xFE54,0xFE6B}, /* ﹔..﹫; SMALL SEMICOLON..SMALL COMMERCIAL AT*/ 587 | {0xFF01,0xFF5E}, /* !..~; FULLWIDTH EXCLAMATION MARK..FULLWIDTH TILDE*/ 588 | {0xFFE0,0xFFE6}, /* ¢..₩; FULLWIDTH CENT SIGN..FULLWIDTH WON SIGN*/ 589 | {-1, -1} 590 | }; 591 | -------------------------------------------------------------------------------- /testtexsymbols.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "$1" == "debug" ] 3 | then 4 | DEBUG=1 5 | else 6 | DEBUG=0 7 | fi 8 | generated=`$utftex -T` 9 | reference="\\_:_;\\}:};\\lbrac:[;\\rbrac:];\\sphat:^;\\sptilde:~;\\vert:|;\\mid:|;\\lvert:|;\\rvert:|;\\divides:|;\\cent:¢;\\pounds:£;\\yen:¥;\\neg:¬;\\circledR:®;\\pm:±;\\Micro:µ;\\times:×;\\eth:ð;\\div:÷;\\imath:ı;\\jmath:ȷ;\\Gamma:Γ;\\Delta:Δ;\\Theta:Θ;\\Lambda:Λ;\\Xi:Ξ;\\Pi:Π;\\Sigma:Σ;\\Upsilon:Υ;\\Phi:Φ;\\Psi:Ψ;\\Omega:Ω;\\alpha:α;\\beta:β;\\gamma:γ;\\delta:δ;\\varepsilon:ε;\\epsilon:ϵ;\\backepsilon:϶;\\zeta:ζ;\\eta:η;\\theta:θ;\\iota:ι;\\kappa:κ;\\lambda:λ;\\mu:μ;\\nu:ν;\\Nu:Ν;\\xi:ξ;\\pi:π;\\rho:ρ;\\varrho:ϱ;\\sigma:σ;\\varsigma:ς;\\tau:τ;\\upsilon:υ;\\varphi:𝜑;\\chi:χ;\\psi:ψ;\\omega:ω;\\varbeta:ϐ;\\vartheta:ϑ;\\phi:ϕ;\\varpi:ϖ;\\Qoppa:Ϙ;\\qoppa:ϙ;\\Stigma:Ϛ;\\stigma:ϛ;\\Digamma:Ϝ;\\digamma:ϝ;\\Koppa:Ϟ;\\koppa:ϟ;\\Sampi:Ϡ;\\sampi:ϡ;\\|:‖;\\dagger:†;\\ddagger:‡;\\ldots:…;\\prime:′;\\pprime:″;\\second:″;\\third:‴;\\ppprime:‴;\\backprime:‵;\\backpprime:‶;\\backppprime:‷;\\cat:⁀;\\fourth:⁗;\\pppprime:⁗;\\Euler:ℇ;\\hslash:ℏ;\\Im:ℑ;\\ell:ℓ;\\wp:℘;\\Re:ℜ;\\tcohm:Ω;\\mho:℧;\\Angstroem:Å;\\Finv:Ⅎ;\\aleph:ℵ;\\beth:ℶ;\\gimel:ℷ;\\daleth:ℸ;\\Yup:⅄;\\CapitalDifferentialD:ⅅ;\\DifferentialD:ⅆ;\\ExponetialE:ⅇ;\\ComplexI:ⅈ;\\ComplexJ:ⅉ;\\invamp:⅋;\\leftarrow:←;\\uparrow:↑;\\to:→;\\rightarrow:→;\\downarrow:↓;\\leftrightarrow:↔;\\updownarrow:↕;\\nwarrow:↖;\\nearrow:↗;\\searrow:↘;\\swarrow:↙;\\nleftarrow:↚;\\nrightarrow:↛;\\twoheadleftarrow:↞;\\twoheadrightarrow:↠;\\leftarrowtail:↢;\\rightarrowtail:↣;\\mapsfrom:↤;\\MapsUp:↥;\\mapsto:↦;\\MapsDown:↧;\\hookleftarrow:↩;\\hookrightarrow:↪;\\looparrowleft:↫;\\looparrowright:↬;\\leftrightsquigarrow:↭;\\nleftrightarrow:↮;\\lightning:↯;\\Lsh:↰;\\Rsh:↱;\\dlsh:↲;\\drsh:↳;\\curvearrowleft:↶;\\curvearrowright:↷;\\circlearrowleft:↺;\\circlearrowright:↻;\\leftharpoonup:↼;\\leftharpoondown:↽;\\upharpoonright:↾;\\upharpoonleft:↿;\\rightharpoonup:⇀;\\rightharpoondown:⇁;\\downharpoonright:⇂;\\downharpoonleft:⇃;\\rightleftarrows:⇄;\\updownarrows:⇅;\\leftrightarrows:⇆;\\leftleftarrows:⇇;\\upuparrows:⇈;\\rightrightarrows:⇉;\\downdownarrows:⇊;\\leftrightharpoons:⇋;\\rightleftharpoons:⇌;\\nLeftarrow:⇍;\\nLeftrightarrow:⇎;\\nRightarrow:⇏;\\Leftarrow:⇐;\\Uparrow:⇑;\\Rightarrow:⇒;\\Downarrow:⇓;\\Leftrightarrow:⇔;\\Updownarrow:⇕;\\Nwarrow:⇖;\\Nearrow:⇗;\\Searrow:⇘;\\Swarrow:⇙;\\Lleftarrow:⇚;\\Rrightarrow:⇛;\\leftsquigarrow:⇜;\\rightsquigarrow:⇝;\\dashleftarrow:⇠;\\dashrightarrow:⇢;\\LeftArrowBar:⇤;\\RightArrowBar:⇥;\\downuparrows:⇵;\\pfun:⇸;\\ffun:⇻;\\leftarrowtriangle:⇽;\\rightarrowtriangle:⇾;\\leftrightarrowtriangle:⇿;\\forall:∀;\\complement:∁;\\partialup:∂;\\exists:∃;\\nexists:∄;\\varnothing:∅;\\nabla:∇;\\in:∈;\\notin:∉;\\ni:∋;\\nni:∌;\\utfprod:∏;\\coprod:∐;\\utfsum:∑;\\mp:∓;\\dotplus:∔;\\slash:∕;\\smallsetminus:∖;\\ast:∗;\\circ:∘;\\bullet:∙;\\utfsqrt:√;\\utfsqrt[3]:∛;\\utfsqrt[4]:∜;\\propto:∝;\\infty:∞;\\rightangle:∟;\\angle:∠;\\measuredangle:∡;\\sphericalangle:∢;\\mid:∣;\\nmid:∤;\\parallel:∥;\\nparallel:∦;\\wedge:∧;\\vee:∨;\\cap:∩;\\cup:∪;\\utfint:∫;\\utfiint:∬;\\utfiiint:∭;\\utfoint:∮;\\utfoiint:∯;\\utfoiiint:∰;\\varointclockwise:∲;\\ointctrclockwise:∳;\\therefore:∴;\\because:∵;\\Proportion:∷;\\eqcolon:∹;\\sim:∼;\\backsim:∽;\\AC:∿;\\wr:≀;\\nsim:≁;\\eqsim:≂;\\simeq:≃;\\nsimeq:≄;\\cong:≅;\\ncong:≇;\\approx:≈;\\napprox:≉;\\approxeq:≊;\\asymp:≍;\\Bumpeq:≎;\\bumpeq:≏;\\doteq:≐;\\Doteq:≑;\\fallingdotseq:≒;\\risingdotseq:≓;\\coloneq:≔;\\eqcolon:≕;\\eqcirc:≖;\\circeq:≗;\\corresponds:≙;\\triangleq:≜;\\neq:≠;\\equiv:≡;\\nequiv:≢;\\leq:≤;\\geq:≥;\\leqq:≦;\\geqq:≧;\\lneqq:≨;\\gneqq:≩;\\ll:≪;\\gg:≫;\\between:≬;\\notasymp:≭;\\nless:≮;\\ngtr:≯;\\nleq:≰;\\ngeq:≱;\\lesssim:≲;\\gtrsim:≳;\\NotLessTilde:≴;\\NotGreaterTilde:≵;\\lessgtr:≶;\\gtrless:≷;\\NotGreaterLess:≹;\\prec:≺;\\succ:≻;\\preccurlyeq:≼;\\succcurlyeq:≽;\\precsim:≾;\\succsim:≿;\\nprec:⊀;\\nsucc:⊁;\\subset:⊂;\\supset:⊃;\\nsubset:⊄;\\nsupset:⊅;\\subseteq:⊆;\\supseteq:⊇;\\nsubseteq:⊈;\\nsupseteq:⊉;\\subsetneq:⊊;\\supsetneq:⊋;\\uplus:⊎;\\sqsubset:⊏;\\sqsupset:⊐;\\sqsubseteq:⊑;\\sqsupseteq:⊒;\\sqcap:⊓;\\sqcup:⊔;\\oplus:⊕;\\ominus:⊖;\\otimes:⊗;\\oslash:⊘;\\odot:⊙;\\circledcirc:⊚;\\circledast:⊛;\\circleddash:⊝;\\boxplus:⊞;\\boxminus:⊟;\\boxtimes:⊠;\\boxdot:⊡;\\vdash:⊢;\\dashv:⊣;\\top:⊤;\\bot:⊥;\\models:⊧;\\vDash:⊨;\\Vdash:⊩;\\Vvdash:⊪;\\VDash:⊫;\\nvdash:⊬;\\nvDash:⊭;\\nVdash:⊮;\\nVDash:⊯;\\vartriangleleft:⊲;\\vartriangleright:⊳;\\trianglelefteq:⊴;\\trianglerighteq:⊵;\\multimapdotbothA:⊶;\\multimapdotbothB:⊷;\\multimap:⊸;\\intercal:⊺;\\veebar:⊻;\\barwedge:⊼;\\bigwedge:⋀;\\bigvee:⋁;\\bigcap:⋂;\\bigcup:⋃;\\diamond:⋄;\\cdot:⋅;\\star:⋆;\\divideontimes:⋇;\\bowtie:⋈;\\ltimes:⋉;\\rtimes:⋊;\\leftthreetimes:⋋;\\rightthreetimes:⋌;\\backsimeq:⋍;\\curlyvee:⋎;\\curlywedge:⋏;\\Subset:⋐;\\Supset:⋑;\\Cap:⋒;\\Cup:⋓;\\pitchfork:⋔;\\hash:⋕;\\lessdot:⋖;\\gtrdot:⋗;\\lll:⋘;\\ggg:⋙;\\lesseqgtr:⋚;\\gtreqless:⋛;\\curlyeqprec:⋞;\\curlyeqsucc:⋟;\\npreceq:⋠;\\nsucceq:⋡;\\nsqsubseteq:⋢;\\nsqsupseteq:⋣;\\lnsim:⋦;\\gnsim:⋧;\\precnsim:⋨;\\succnsim:⋩;\\ntriangleleft:⋪;\\ntriangleright:⋫;\\ntrianglelefteq:⋬;\\ntrianglerighteq:⋭;\\vdots:⋮;\\cdots:⋯;\\iddots:⋰;\\ddots:⋱;\\barin:⋶;\\diameter:⌀;\\lceil:⌈;\\rceil:⌉;\\lfloor:⌊;\\rfloor:⌋;\\invneg:⌐;\\wasylozenge:⌑;\\ulcorner:⌜;\\urcorner:⌝;\\llcorner:⌞;\\lrcorner:⌟;\\frown:⌢;\\smile:⌣;\\APLinv:⌹;\\notslash:⌿;\\notbackslash:⍀;\\APLleftarrowbox:⍇;\\APLrightarrowbox:⍈;\\APLuparrowbox:⍐;\\APLdownarrowbox:⍗;\\APLcomment:⍝;\\APLinput:⍞;\\APLlog:⍟;\\overparen:⏜;\\underparen:⏝;\\overbrace:⏞;\\underbrace:⏟;\\bigtriangleup:△;\\blacktriangleup:▴;\\smalltriangleup:▵;\\RHD:▶;\\rhd:▷;\\blacktriangleright:▸;\\smalltriangleright:▹;\\bigtriangledown:▽;\\blacktriangledown:▾;\\smalltriangledown:▿;\\LHD:◀;\\lhd:◁;\\blacktriangleleft:◂;\\smalltriangleleft:◃;\\Diamondblack:◆;\\Diamond:◇;\\lozenge:◊;\\Box:□;\\Circle:○;\\CIRCLE:●;\\LEFTcircle:◐;\\RIGHTcircle:◑;\\LEFTCIRCLE:◖;\\RIGHTCIRCLE:◗;\\boxbar:◫;\\square:◻;\\blacksquare:◼;\\bigstar:★;\\Sun:☉;\\Square:☐;\\CheckedBox:☑;\\XBox:☒;\\steaming:☕;\\pointright:☞;\\skull:☠;\\radiation:☢;\\biohazard:☣;\\yinyang:☯;\\frownie:☹;\\smiley:☺;\\blacksmiley:☻;\\sun:☼;\\rightmoon:☽;\\leftmoon:☾;\\mercury:☿;\\female:♀;\\earth:♁;\\male:♂;\\jupiter:♃;\\saturn:♄;\\uranus:♅;\\neptune:♆;\\pluto:♇;\\aries:♈;\\taurus:♉;\\gemini:♊;\\cancer:♋;\\leo:♌;\\virgo:♍;\\libra:♎;\\scorpio:♏;\\sagittarius:♐;\\capricornus:♑;\\aquarius:♒;\\pisces:♓;\\spadesuit:♠;\\heartsuit:♡;\\diamondsuit:♢;\\clubsuit:♣;\\varspadesuit:♤;\\varheartsuit:♥;\\vardiamondsuit:♦;\\varclubsuit:♧;\\quarternote:♩;\\eighthnote:♪;\\twonotes:♫;\\sixteenthnote:♬;\\flat:♭;\\natural:♮;\\sharp:♯;\\recycle:♻;\\anchor:⚓;\\swords:⚔;\\warning:⚠;\\medcirc:⚪;\\medbullet:⚫;\\pencil:✎;\\checkmark:✓;\\ballotx:✗;\\maltese:✠;\\arrowbullet:➢;\\perp:⟂;\\Lbag:⟅;\\Rbag:⟆;\\Diamonddot:⟐;\\multimapinv:⟜;\\llbracket:⟦;\\rrbracket:⟧;\\langle:⟨;\\rangle:⟩;\\lang:⟪;\\rang:⟫;\\lgroup:⟮;\\rgroup:⟯;\\longleftarrow:⟵;\\longrightarrow:⟶;\\longleftrightarrow:⟷;\\Longleftarrow:⟸;\\Longrightarrow:⟹;\\Longleftrightarrow:⟺;\\longmapsfrom:⟻;\\longmapsto:⟼;\\Longmapsfrom:⟽;\\Longmapsto:⟾;\\psur:⤀;\\Mapsfrom:⤆;\\Mapsto:⤇;\\UpArrowBar:⤒;\\DownArrowBar:⤓;\\pinj:⤔;\\finj:⤕;\\bij:⤖;\\leadsto:⤳;\\leftrightharpoon:⥊;\\rightleftharpoon:⥋;\\leftrightharpoonup:⥎;\\rightupdownharpoon:⥏;\\leftrightharpoondown:⥐;\\leftupdownharpoon:⥑;\\LeftVectorBar:⥒;\\RightVectorBar:⥓;\\RightUpVectorBar:⥔;\\RightDownVectorBar:⥕;\\DownLeftVectorBar:⥖;\\DownRightVectorBar:⥗;\\LeftUpVectorBar:⥘;\\LeftDownVectorBar:⥙;\\LeftTeeVector:⥚;\\RightTeeVector:⥛;\\RightUpTeeVector:⥜;\\RightDownTeeVector:⥝;\\DownLeftTeeVector:⥞;\\DownRightTeeVector:⥟;\\LeftUpTeeVector:⥠;\\LeftDownTeeVector:⥡;\\leftleftharpoons:⥢;\\upupharpoons:⥣;\\rightrightharpoons:⥤;\\downdownharpoons:⥥;\\leftbarharpoon:⥪;\\barleftharpoon:⥫;\\rightbarharpoon:⥬;\\barrightharpoon:⥭;\\updownharpoons:⥮;\\downupharpoons:⥯;\\strictfi:⥼;\\strictif:⥽;\\VERT:⦀;\\spot:⦁;\\Lparen:⦅;\\Rparen:⦆;\\limg:⦇;\\rimg:⦈;\\lblot:⦉;\\rblot:⦊;\\circledbslash:⦸;\\circledless:⧀;\\circledgtr:⧁;\\boxslash:⧄;\\boxbslash:⧅;\\boxast:⧆;\\boxcircle:⧇;\\boxbox:⧈;\\LeftTriangleBar:⧏;\\RightTriangleBar:⧐;\\multimapboth:⧟;\\blacklozenge:⧫;\\setminus:⧵;\\zhide:⧹;\\bigodot:⨀;\\bigoplus:⨁;\\bigotimes:⨂;\\biguplus:⨄;\\bigsqcap:⨅;\\bigsqcup:⨆;\\varprod:⨉;\\utfiiiint:⨌;\\utffint:⨏;\\utfsqint:⨖;\\Join:⨝;\\zcmp:⨟;\\zpipe:⨠;\\zproject:⨡;\\fcmp:⨾;\\amalg:⨿;\\doublebarwedge:⩞;\\dsub:⩤;\\rsub:⩥;\\Coloneqq:⩴;\\Equal:⩵;\\Same:⩶;\\leqslant:⩽;\\geqslant:⩾;\\lessapprox:⪅;\\gtrapprox:⪆;\\lneq:⪇;\\gneq:⪈;\\lnapprox:⪉;\\gnapprox:⪊;\\lesseqqgtr:⪋;\\gtreqqless:⪌;\\eqslantless:⪕;\\eqslantgtr:⪖;\\NestedLessLess:⪡;\\NestedGreaterGreater:⪢;\\leftslice:⪦;\\rightslice:⪧;\\preceq:⪯;\\succeq:⪰;\\preceqq:⪳;\\succeqq:⪴;\\precapprox:⪷;\\succapprox:⪸;\\precnapprox:⪹;\\succnapprox:⪺;\\llcurly:⪻;\\ggcurly:⪼;\\subseteqq:⫅;\\supseteqq:⫆;\\subsetneqq:⫋;\\supsetneqq:⫌;\\Top:⫪;\\Bot:⫫;\\interleave:⫴;\\biginterleave:⫼;\\sslash:⫽;\\talloblong:⫾;\\blacksquare:⬛;\\square:⬜;\\partial:𝜕;\\emojify:️;\\cbrt:∛;\\mars:♂;\\xor:⊻;\\nand:⊼;\\nor:⊽;\\iff:⟺;\\implies:⟹;\\impliedby:⟸;\\euler:ℯ;\\ohm:Ω;\\hbar:ħ;\\del:∇;\\euro:€;\\exclamdown:¡;\\sterling:£;\\brokenbar:¦;\\S:§;\\copyright:©;\\ordfeminine:ª;\\highminus:¯;\\P:¶;\\cdotp:·;\\ordmasculine:º;\\questiondown:¿;\\AA:Å;\\AE:Æ;\\DH:Ð;\\O:Ø;\\TH:Þ;\\ss:ß;\\aa:å;\\ae:æ;\\dh:ð;\\o:ø;\\th:þ;\\DJ:Đ;\\dj:đ;\\L:Ł;\\NG:Ŋ;\\ng:ŋ;\\OE:Œ;\\oe:œ;\\hvlig:ƕ;\\nrleg:ƞ;\\doublepipe:ǂ;\\trna:ɐ;\\trnsa:ɒ;\\openo:ɔ;\\rtld:ɖ;\\schwa:ə;\\pgamma:ɣ;\\pbgam:ɤ;\\trnh:ɥ;\\btdl:ɬ;\\rtll:ɭ;\\trnm:ɯ;\\trnmlr:ɰ;\\ltlmr:ɱ;\\ltln:ɲ;\\rtln:ɳ;\\clomeg:ɷ;\\ltphi:ɸ;\\trnr:ɹ;\\trnrl:ɺ;\\rttrnr:ɻ;\\rl:ɼ;\\rtlr:ɽ;\\fhr:ɾ;\\rtls:ʂ;\\esh:ʃ;\\trnt:ʇ;\\rtlt:ʈ;\\pupsil:ʊ;\\pscrv:ʋ;\\invv:ʌ;\\invw:ʍ;\\trny:ʎ;\\rtlz:ʐ;\\yogh:ʒ;\\glst:ʔ;\\reglst:ʕ;\\inglst:ʖ;\\turnk:ʞ;\\dyogh:ʤ;\\tesh:ʧ;\\rasp:ʼ;\\verts:ˈ;\\verti:ˌ;\\lmrk:ː;\\hlmrk:ˑ;\\sbrhr:˒;\\sblhr:˓;\\rais:˔;\\low:˕;\\u:˘;\\tildelow:˜;\\Alpha:Α;\\Beta:Β;\\Epsilon:Ε;\\Zeta:Ζ;\\Eta:Η;\\Iota:Ι;\\Kappa:Κ;\\Rho:Ρ;\\Tau:Τ;\\Chi:Χ;\\varkappa:ϰ;\\varTheta:ϴ;\\enspace: ;\\thickspace: ;\\thinspace: ;\\hspace: ;\\endash:–;\\emdash:—;\\Vert:‖;\\lVert:‖;\\rVert:‖;\\lq:‘;\\rq:’;\\reapos:‛;\\ldq:“;\\rdq:”;\\dots:…;\\perthousand:‰;\\pertenthousand:‱;\\guilsinglleft:‹;\\guilsinglright:›;\\nolinebreak:⁠;\\pes:₧;\\numero:№;\\xrat:℞;\\trademark:™;\\bbsum:⅀;\\Game:⅁;\\dblarrowupdown:⇅;\\DownArrowUpArrow:⇵;\\emptyset:∅;\\surd:√;\\clwintegral:∱;\\Colon:∷;\\dotminus:∸;\\kernelcontraction:∻;\\lazysinv:∾;\\neqsim:≂;\\nsime:≄;\\approxnotequal:≆;\\tildetrpl:≋;\\allequal:≌;\\nBumpeq:≎;\\nbumpeq:≏;\\wedgeq:≙;\\starequal:≛;\\questeq:≟;\\ne:≠;\\le:≤;\\ge:≥;\\lvertneqq:≨;\\gvertneqq:≩;\\NotLessLess:≪;\\NotGreaterGreater:≫;\\notlessgreater:≸;\\notgreaterless:≹;\\nprecsim:≾;\\nsuccsim:≿;\\varsubsetneqq:⊊;\\varsupsetneq:⊋;\\cupdot:⊍;\\NotSquareSubset:⊏;\\NotSquareSuperset:⊐;\\indep:⫫;\\downvDash:⫪;\\upvDash:⫫;\\original:⊶;\\image:⊷;\\hermitconjmatrix:⊹;\\rightanglearc:⊾;\\verymuchless:⋘;\\adots:⋰;\\recorder:⌕;\\obar:⌽;\\dlcorn:⎣;\\lmoustache:⎰;\\visiblespace:␣;\\circledS:Ⓢ;\\dshfnc:┆;\\sqfnw:┙;\\diagup:╱;\\diagdown:╲;\\vrecto:▯;\\blacktriangle:▴;\\vartriangle:▵;\\triangledown:▿;\\bigcirc:○;\\cirfl:◐;\\cirfr:◑;\\cirfb:◒;\\rvbull:◘;\\sqfl:◧;\\sqfr:◨;\\sqfse:◪;\\venus:♀;\\Uuparrow:⤊;\\Ddownarrow:⤋;\\bkarow:⤍;\\dbkarow:⤏;\\drbkarrow:⤐;\\twoheadrightarrowtail:⤖;\\hksearow:⤥;\\hkswarow:⤦;\\tona:⤧;\\toea:⤨;\\tosa:⤩;\\towa:⤪;\\rdiagovfdiag:⤫;\\fdiagovrdiag:⤬;\\seovnearrow:⤭;\\neovsearrow:⤮;\\fdiagovnearrow:⤯;\\rdiagovsearrow:⤰;\\neovnwarrow:⤱;\\nwovnearrow:⤲;\\Rlarr:⥂;\\rLarr:⥄;\\rarrx:⥇;\\LeftRightVector:⥎;\\RightUpDownVector:⥏;\\DownLeftRightVector:⥐;\\LeftUpDownVector:⥑;\\UpEquilibrium:⥮;\\ReverseUpEquilibrium:⥯;\\RoundImplies:⥰;\\Vvert:⦀;\\Elroang:⦆;\\ddfnc:⦙;\\Angle:⦜;\\lpargt:⦠;\\obslash:⦸;\\Lap:⧊;\\defas:⧋;\\NotLeftTriangleBar:⧏;\\NotRightTriangleBar:⧐;\\dualmap:⧟;\\shuffle:⧢;\\RuleDelayed:⧴;\\bigcupdot:⨃;\\conjquant:⨇;\\disjquant:⨈;\\bigtimes:⨉;\\clockoint:⨏;\\sqrint:⨖;\\upint:⨛;\\lowint:⨜;\\plusdot:⨥;\\Times:⨯;\\btimes:⨲;\\And:⩓;\\Or:⩔;\\ElOr:⩖;\\perspcorrespond:⩞;\\ddotseq:⩷;\\nleqslant:⩽;\\ngeqslant:⩾;\\NotNestedLessLess:⪡;\\NotNestedGreaterGreater:⪢;\\partialmeetcontraction:⪣;\\bumpeqq:⪮;\\precneqq:⪵;\\succneqq:⪶;\\nsubseteqq:⫅;\\nsupseteqq:⫆;\\mlcp:⫛;\\forks:⫝̸;\\forksnot:⫝;\\dashV:⫣;\\Dashv:⫤;\\tdcol:⫶;\\openbracketleft:⟦;\\openbracketright:⟧;\\Zbar:Ƶ;\\upMu:Μ;\\upNu:Ν;\\upOmicron:Ο;\\upepsilon:ε;\\upomicron:ο;\\upvarbeta:ϐ;\\upoldKoppa:Ϙ;\\upoldkoppa:ϙ;\\upstigma:ϛ;\\upkoppa:ϟ;\\upsampi:ϡ;\\tieconcat:⁀;\\eulermascheroni:ℇ;\\planck:ℎ;\\turnediota:℩;\\Angstrom:Å;\\sansLturned:⅂;\\sansLmirrored:⅃;\\PropertyLine:⅊;\\upand:⅋;\\twoheaduparrow:↟;\\twoheaddownarrow:↡;\\mapsup:↥;\\mapsdown:↧;\\updownarrowbar:↨;\\downzigzagarrow:↯;\\Ldsh:↲;\\Rdsh:↳;\\linefeed:↴;\\carriagereturn:↵;\\nHuparrow:⇞;\\nHdownarrow:⇟;\\leftdasharrow:⇠;\\updasharrow:⇡;\\rightdasharrow:⇢;\\downdasharrow:⇣;\\rightarrowbar:⇥;\\leftwhitearrow:⇦;\\upwhitearrow:⇧;\\rightwhitearrow:⇨;\\downwhitearrow:⇩;\\whitearrowupfrombar:⇪;\\circleonrightarrow:⇴;\\rightthreearrows:⇶;\\nvleftarrow:⇷;\\nvrightarrow:⇸;\\nvleftrightarrow:⇹;\\nVleftarrow:⇺;\\nVrightarrow:⇻;\\nVleftrightarrow:⇼;\\increment:∆;\\smallin:∊;\\smallni:∍;\\QED:∎;\\vysmblkcircle:∙;\\fourthroot:∜;\\dotsminusdots:∺;\\arceq:≘;\\veeeq:≚;\\eqdef:≝;\\measeq:≞;\\Equiv:≣;\\nasymp:≭;\\nlesssim:≴;\\ngtrsim:≵;\\circledequal:⊜;\\prurel:⊰;\\scurel:⊱;\\varlrtriangle:⊿;\\equalparallel:⋕;\\eqless:⋜;\\eqgtr:⋝;\\npreccurlyeq:⋠;\\nsucccurlyeq:⋡;\\sqsubsetneq:⋤;\\sqsupsetneq:⋥;\\disin:⋲;\\varisins:⋳;\\isins:⋴;\\isindot:⋵;\\varisinobar:⋶;\\isinobar:⋷;\\isinvb:⋸;\\isinE:⋹;\\nisd:⋺;\\varnis:⋻;\\nis:⋼;\\varniobar:⋽;\\niobar:⋾;\\bagmember:⋿;\\house:⌂;\\vardoublebarwedge:⌆;\\invnot:⌐;\\sqlozenge:⌑;\\profline:⌒;\\profsurf:⌓;\\viewdata:⌗;\\turnednot:⌙;\\varhexagonlrbonds:⌬;\\conictaper:⌲;\\topbot:⌶;\\hexagon:⎔;\\underbracket:⎵;\\bbrktbrk:⎶;\\lvboxline:⎸;\\rvboxline:⎹;\\varcarriagereturn:⏎;\\trapezium:⏢;\\benzenr:⏣;\\strns:⏤;\\fltns:⏥;\\accurrent:⏦;\\elinters:⏧;\\blanksymbol:␢;\\blockuphalf:▀;\\blocklowhalf:▄;\\blockfull:█;\\blocklefthalf:▌;\\blockrighthalf:▐;\\blockqtrshaded:░;\\blockhalfshaded:▒;\\blockthreeqtrshaded:▓;\\squoval:▢;\\blackinwhitesquare:▣;\\squarehfill:▤;\\squarevfill:▥;\\squarehvfill:▦;\\squarenwsefill:▧;\\squareneswfill:▨;\\squarecrossfill:▩;\\smblksquare:▪;\\smwhtsquare:▫;\\hrectangleblack:▬;\\hrectangle:▭;\\vrectangleblack:▮;\\parallelogramblack:▰;\\parallelogram:▱;\\bigblacktriangleup:▲;\\blackpointerright:►;\\whitepointerright:▻;\\bigblacktriangledown:▼;\\blackpointerleft:◄;\\whitepointerleft:◅;\\mdlgblkdiamond:◆;\\mdlgwhtdiamond:◇;\\blackinwhitediamond:◈;\\fisheye:◉;\\dottedcircle:◌;\\circlevertfill:◍;\\bullseye:◎;\\mdlgblkcircle:●;\\circletophalfblack:◓;\\circleurquadblack:◔;\\blackcircleulquadwhite:◕;\\blacklefthalfcircle:◖;\\blackrighthalfcircle:◗;\\inversewhitecircle:◙;\\invwhiteupperhalfcircle:◚;\\invwhitelowerhalfcircle:◛;\\ularc:◜;\\urarc:◝;\\lrarc:◞;\\llarc:◟;\\topsemicircle:◠;\\botsemicircle:◡;\\lrblacktriangle:◢;\\llblacktriangle:◣;\\ulblacktriangle:◤;\\urblacktriangle:◥;\\smwhtcircle:◦;\\squareulblack:◩;\\trianglecdot:◬;\\triangleleftblack:◭;\\trianglerightblack:◮;\\lgwhtcircle:◯;\\squareulquad:◰;\\squarellquad:◱;\\squarelrquad:◲;\\squareurquad:◳;\\circleulquad:◴;\\circlellquad:◵;\\circlelrquad:◶;\\circleurquad:◷;\\ultriangle:◸;\\urtriangle:◹;\\lltriangle:◺;\\mdwhtsquare:◻;\\mdblksquare:◼;\\mdsmwhtsquare:◽;\\mdsmblksquare:◾;\\lrtriangle:◿;\\bigwhitestar:☆;\\astrosun:☉;\\danger:☡;\\acidfree:♾;\\dicei:⚀;\\diceii:⚁;\\diceiii:⚂;\\diceiv:⚃;\\dicev:⚄;\\dicevi:⚅;\\circledrightdot:⚆;\\circledtwodots:⚇;\\blackcircledrightdot:⚈;\\blackcircledtwodots:⚉;\\hermaphrodite:⚥;\\mdwhtcircle:⚪;\\mdblkcircle:⚫;\\mdsmwhtcircle:⚬;\\neuter:⚲;\\circledstar:✪;\\varstar:✶;\\dingasterisk:✽;\\draftingarrow:➛;\\threedangle:⟀;\\whiteinwhitetriangle:⟁;\\bsolhsub:⟈;\\suphsol:⟉;\\wedgedot:⟑;\\veedot:⟇;\\upin:⟒;\\bigbot:⟘;\\bigtop:⟙;\\UUparrow:⟰;\\DDownarrow:⟱;\\longrightsquigarrow:⟿;\\nvtwoheadrightarrow:⤀;\\nVtwoheadrightarrow:⤁;\\nvLeftarrow:⤂;\\nvRightarrow:⤃;\\nvLeftrightarrow:⤄;\\twoheadmapsto:⤅;\\downarrowbarred:⤈;\\uparrowbarred:⤉;\\leftbkarrow:⤌;\\leftdbkarrow:⤎;\\rightdotarrow:⤑;\\nvrightarrowtail:⤔;\\nVrightarrowtail:⤕;\\nvtwoheadrightarrowtail:⤗;\\nVtwoheadrightarrowtail:⤘;\\diamondleftarrow:⤝;\\rightarrowdiamond:⤞;\\diamondleftarrowbar:⤟;\\rightarrowplus:⥅;\\leftarrowplus:⥆;\\leftrightarrowcircle:⥈;\\twoheaduparrowcircle:⥉;\\leftrightharpoonupdown:⥊;\\leftrightharpoondownup:⥋;\\updownharpoonrightleft:⥌;\\updownharpoonleftright:⥍;\\leftharpoonsupdown:⥢;\\upharpoonsleftright:⥣;\\rightharpoonsupdown:⥤;\\downharpoonsleftright:⥥;\\leftrightharpoonsup:⥦;\\leftrightharpoonsdown:⥧;\\rightleftharpoonsup:⥨;\\rightleftharpoonsdown:⥩;\\leftharpoonupdash:⥪;\\dashleftharpoondown:⥫;\\rightharpoonupdash:⥬;\\dashrightharpoondown:⥭;\\measuredangleleft:⦛;\\rightanglemdot:⦝;\\angles:⦞;\\angdnr:⦟;\\sphericalangleup:⦡;\\turnangle:⦢;\\revangle:⦣;\\angleubar:⦤;\\revangleubar:⦥;\\wideangledown:⦦;\\wideangleup:⦧;\\measanglerutone:⦨;\\measanglelutonw:⦩;\\measanglerdtose:⦪;\\measangleldtosw:⦫;\\measangleurtone:⦬;\\measangleultonw:⦭;\\measangledrtose:⦮;\\measangledltosw:⦯;\\revemptyset:⦰;\\emptysetobar:⦱;\\emptysetocirc:⦲;\\emptysetoarr:⦳;\\emptysetoarrl:⦴;\\circledparallel:⦷;\\odotslashdot:⦼;\\circledwhitebullet:⦾;\\circledbullet:⦿;\\olessthan:⧀;\\ogreaterthan:⧁;\\lrtriangleeq:⧡;\\eparsl:⧣;\\smeparsl:⧤;\\eqvparsl:⧥;\\dsol:⧶;\\rsolbar:⧷;\\doubleplus:⧺;\\tripleplus:⧻;\\modtwosum:⨊;\\cirfnint:⨐;\\awint:⨑;\\rppolint:⨒;\\scpolint:⨓;\\npolint:⨔;\\pointint:⨕;\\ringplus:⨢;\\plushat:⨣;\\simplus:⨤;\\plussim:⨦;\\plussubtwo:⨧;\\plustrif:⨨;\\commaminus:⨩;\\opluslhrim:⨭;\\oplusrhrim:⨮;\\dottimes:⨰;\\timesbar:⨱;\\smashtimes:⨳;\\otimeslhrim:⨴;\\otimesrhrim:⨵;\\otimeshat:⨶;\\Otimes:⨷;\\odiv:⨸;\\triangleplus:⨹;\\triangleminus:⨺;\\triangletimes:⨻;\\capdot:⩀;\\uminus:⩁;\\capwedge:⩄;\\cupvee:⩅;\\twocups:⩊;\\twocaps:⩋;\\closedvarcup:⩌;\\closedvarcap:⩍;\\Sqcap:⩎;\\Sqcup:⩏;\\closedvarcupsmashprod:⩐;\\wedgeodot:⩑;\\veeodot:⩒;\\wedgeonwedge:⩕;\\bigslopedvee:⩗;\\bigslopedwedge:⩘;\\wedgemidvert:⩚;\\veemidvert:⩛;\\midbarwedge:⩜;\\midbarvee:⩝;\\wedgedoublebar:⩠;\\varveebar:⩡;\\doublebarvee:⩢;\\veedoublebar:⩣;\\eqdot:⩦;\\dotequiv:⩧;\\dotsim:⩪;\\simrdots:⩫;\\simminussim:⩬;\\congdot:⩭;\\asteq:⩮;\\hatapprox:⩯;\\approxeqq:⩰;\\eqqplus:⩱;\\pluseqq:⩲;\\eqqsim:⩳;\\Coloneq:⩴;\\eqeqeq:⩶;\\equivDD:⩸;\\ltcir:⩹;\\gtcir:⩺;\\ltquest:⩻;\\gtquest:⩼;\\lesdot:⩿;\\gesdot:⪀;\\lesdoto:⪁;\\gesdoto:⪂;\\lesdotor:⪃;\\gesdotol:⪄;\\lsime:⪍;\\gsime:⪎;\\lsimg:⪏;\\gsiml:⪐;\\lgE:⪑;\\glE:⪒;\\lesges:⪓;\\gesles:⪔;\\elsdot:⪗;\\egsdot:⪘;\\eqqless:⪙;\\eqqgtr:⪚;\\eqqslantless:⪛;\\eqqslantgtr:⪜;\\simless:⪝;\\simgtr:⪞;\\simlE:⪟;\\simgE:⪠;\\glj:⪤;\\gla:⪥;\\ltcc:⪦;\\gtcc:⪧;\\lescc:⪨;\\gescc:⪩;\\smt:⪪;\\lat:⪫;\\smte:⪬;\\late:⪭;\\precneq:⪱;\\succneq:⪲;\\Prec:⪻;\\Succ:⪼;\\subsetdot:⪽;\\supsetdot:⪾;\\subsetplus:⪿;\\supsetplus:⫀;\\submult:⫁;\\supmult:⫂;\\subedot:⫃;\\supedot:⫄;\\subsim:⫇;\\supsim:⫈;\\subsetapprox:⫉;\\supsetapprox:⫊;\\lsqhook:⫍;\\rsqhook:⫎;\\csub:⫏;\\csup:⫐;\\csube:⫑;\\csupe:⫒;\\subsup:⫓;\\supsub:⫔;\\subsub:⫕;\\supsup:⫖;\\suphsub:⫗;\\supdsub:⫘;\\forkv:⫙;\\lllnest:⫷;\\gggnest:⫸;\\leqqslant:⫹;\\geqqslant:⫺;\\squaretopblack:⬒;\\squarebotblack:⬓;\\squareurblack:⬔;\\squarellblack:⬕;\\diamondleftblack:⬖;\\diamondrightblack:⬗;\\diamondtopblack:⬘;\\diamondbotblack:⬙;\\dottedsquare:⬚;\\lgblksquare:⬛;\\lgwhtsquare:⬜;\\vysmblksquare:⬝;\\vysmwhtsquare:⬞;\\pentagonblack:⬟;\\pentagon:⬠;\\varhexagon:⬡;\\varhexagonblack:⬢;\\hexagonblack:⬣;\\lgblkcircle:⬤;\\mdblkdiamond:⬥;\\mdwhtdiamond:⬦;\\mdblklozenge:⬧;\\mdwhtlozenge:⬨;\\smblkdiamond:⬩;\\smblklozenge:⬪;\\smwhtlozenge:⬫;\\blkhorzoval:⬬;\\whthorzoval:⬭;\\blkvertoval:⬮;\\whtvertoval:⬯;\\circleonleftarrow:⬰;\\leftthreearrows:⬱;\\leftarrowonoplus:⬲;\\longleftsquigarrow:⬳;\\nvtwoheadleftarrow:⬴;\\nVtwoheadleftarrow:⬵;\\twoheadmapsfrom:⬶;\\twoheadleftdbkarrow:⬷;\\leftdotarrow:⬸;\\nvleftarrowtail:⬹;\\nVleftarrowtail:⬺;\\twoheadleftarrowtail:⬻;\\nvtwoheadleftarrowtail:⬼;\\nVtwoheadleftarrowtail:⬽;\\leftarrowx:⬾;\\leftcurvedarrow:⬿;\\equalleftarrow:⭀;\\bsimilarleftarrow:⭁;\\leftarrowbackapprox:⭂;\\rightarrowgtr:⭃;\\leftarrowless:⥷;\\rightarrowsupset:⭄;\\leftarrowsubset:⥺;\\LLeftarrow:⭅;\\RRightarrow:⭆;\\bsimilarrightarrow:⭇;\\rightarrowbackapprox:⭈;\\similarleftarrow:⭉;\\leftarrowapprox:⭊;\\leftarrowbsimilar:⭋;\\rightarrowbsimilar:⭌;\\medwhitestar:⭐;\\medblackstar:⭑;\\smwhitestar:⭒;\\rightpentagonblack:⭓;\\rightpentagon:⭔;\\postalmark:〒;\\triangleright:▷;\\triangleleft:◁;\\leftouterjoin:⟕;\\rightouterjoin:⟖;\\fullouterjoin:⟗;\\join:⨝;\\leftwavearrow:↜;\\rightwavearrow:↝;\\varbarwedge:⌅;\\smallblacktriangleright:▸;\\smallblacktriangleleft:◂;\\tricolon:⁝;\\grave ◌:◌̀;\\\` ◌:◌̀;\\acute ◌:◌́;\\' ◌:◌́;\\hat ◌:◌̂;\\^ ◌:◌̂;\\tilde ◌:◌̃;\\~ ◌:◌̃;\\breve ◌:◌̆;\\overline ◌:◌̅;\\bar ◌:◌̅;\\underline ◌:◌̲;\\underbar ◌:◌̲;\\dot ◌:◌̇;\\ddot ◌:◌̈;\\\" ◌:◌̈;\\mathring ◌:◌̊;\\ocirc ◌:◌̊;\\H ◌:◌̋;\\check ◌:◌̌;\\c ◌:◌̧;\\k ◌:◌̨;\\utilde ◌:◌̰;\\l ◌:◌̷;\\not ◌:◌̸;\\lvec ◌:◌⃐;\\leftharpoonaccent ◌:◌⃐;\\Lvec ◌:◌⃖;\\vec ◌:◌⃗;\\dddot ◌:◌⃛;\\ddddot ◌:◌⃜;\\overleftrightarrow ◌:◌⃡;\\ovhook ◌:◌̉;\\oturnedcomma ◌:◌̒;\\ocommatopright ◌:◌̕;\\droang ◌:◌̚;\\rightharpoonaccent ◌:◌⃑;\\widebridgeabove ◌:◌⃩;\\asteraccent ◌:◌⃰;\\candra ◌:◌̐;\\wideutilde ◌:◌̰;\\threeunderdot ◌:◌⃨;\\underleftarrow ◌:◌⃮;\\underrightarrow ◌:◌⃯;\\underleftrightarrow ◌:◌͍;\\underrightharpoondown ◌:◌⃬;\\underleftharpoondown ◌:◌⃭;\\palh ◌:◌̡;\\rh ◌:◌̢;\\sbbrg ◌:◌̪;\\sout ◌:◌̶;\\strike ◌:◌̶;\\annuity ◌:◌⃧;\\enclosecircle ◌:◌⃝;\\enclosesquare ◌:◌⃞;\\enclosediamond ◌:◌⃟;\\enclosetriangle ◌:◌⃤;\\vertoverlay ◌:◌⃒;" 10 | if test "$generated" != "$reference"; then 11 | echo "FAIL: texsymbols" 12 | if [ "$DEBUG" -eq 1 ] 13 | then 14 | diff <(echo $generated|sed 's/;/\n/g') <(echo $reference|sed 's/;/\n/g') 15 | fi 16 | exit 1 17 | fi 18 | --------------------------------------------------------------------------------