Check-in [c3a5dab823]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:add optional asciimath package to TSB
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c3a5dab823c0fdace73dec91c593a3ea6259d6d8
User & Date: chw 2019-07-12 09:02:30
Context
2019-07-12
16:21
update sqlite to version 3.29.0 check-in: 513d4da72a user: chw tags: trunk
09:02
add optional asciimath package to TSB check-in: c3a5dab823 user: chw tags: trunk
04:31
add selected tcl upstream changes check-in: 83c841b3cd user: chw tags: trunk
Changes

Added undroid/tsb/asciimath/ASCIIMathML.js.

            1  +/*
            2  +ASCIIMathML.js
            3  +==============
            4  +This file contains JavaScript functions to convert ASCII math notation
            5  +and (some) LaTeX to Presentation MathML. The conversion is done while the
            6  +HTML page loads, and should work with Firefox and other browsers that can
            7  +render MathML.
            8  +
            9  +Just add the next line to your HTML page with this file in the same folder:
           10  +
           11  +<script type="text/javascript" src="ASCIIMathML.js"></script>
           12  +
           13  +Version 2.2 Mar 3, 2014.
           14  +Latest version at https://github.com/mathjax/asciimathml
           15  +If you use it on a webpage, please send the URL to jipsen@chapman.edu
           16  +
           17  +Copyright (c) 2014 Peter Jipsen and other ASCIIMathML.js contributors
           18  +
           19  +Permission is hereby granted, free of charge, to any person obtaining a copy
           20  +of this software and associated documentation files (the "Software"), to deal
           21  +in the Software without restriction, including without limitation the rights
           22  +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
           23  +copies of the Software, and to permit persons to whom the Software is
           24  +furnished to do so, subject to the following conditions:
           25  +
           26  +The above copyright notice and this permission notice shall be included in
           27  +all copies or substantial portions of the Software.
           28  +
           29  +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
           30  +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
           31  +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
           32  +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
           33  +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
           34  +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
           35  +THE SOFTWARE.
           36  +
           37  +WARNING: This is a minimally adapted version for use in Taygete Scrap Book.
           38  +*/
           39  +var asciimath = {};
           40  +
           41  +(function(){
           42  +var mathcolor = "";            // change it to "" (to inherit) or another color
           43  +var mathfontsize = "1em";      // change to e.g. 1.2em for larger math
           44  +var mathfontfamily = "serif";  // change to "" to inherit (works in IE)
           45  +                               // or another family (e.g. "arial")
           46  +var automathrecognize = false; // writing "amath" on page makes this true
           47  +var checkForMathML = true;     // check if browser can display MathML
           48  +var notifyIfNoMathML = true;   // display note at top if no MathML capability
           49  +var alertIfNoMathML = false;   // show alert box if no MathML capability
           50  +var translateOnLoad = false;   // set to false to do call translators from js
           51  +var translateASCIIMath = true; // false to preserve `..`
           52  +var displaystyle = true;       // puts limits above and below large operators
           53  +var showasciiformulaonhover = false; // helps students learn ASCIIMath
           54  +var decimalsign = ".";         // if "," then when writing lists or matrices put
           55  +			       //a space after the "," like `(1, 2)` not `(1,2)`
           56  +var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters
           57  +var AMdocumentId = "wikitext"; // PmWiki element containing math (default=body)
           58  +var fixphi = true;	       //false to return to legacy phi/varphi mapping
           59  +
           60  +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
           61  +
           62  +var isIE = (navigator.appName.slice(0,9)=="Microsoft");
           63  +var noMathML = false, translated = false;
           64  +
           65  +if (isIE) { // add MathPlayer info to IE webpages
           66  +  document.write("<object id=\"mathplayer\"\
           67  +  classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");
           68  +  document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");
           69  +}
           70  +
           71  +// Add a stylesheet, replacing any previous custom stylesheet (adapted from TW)
           72  +function setStylesheet(s) {
           73  +	var id = "AMMLcustomStyleSheet";
           74  +	var n = document.getElementById(id);
           75  +	if(document.createStyleSheet) {
           76  +		// Test for IE's non-standard createStyleSheet method
           77  +		if(n)
           78  +			n.parentNode.removeChild(n);
           79  +		// This failed without the &nbsp;
           80  +		document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd","&nbsp;<style id='" + id + "'>" + s + "</style>");
           81  +	} else {
           82  +		if(n) {
           83  +			n.replaceChild(document.createTextNode(s),n.firstChild);
           84  +		} else {
           85  +			n = document.createElement("style");
           86  +			n.type = "text/css";
           87  +			n.id = id;
           88  +			n.appendChild(document.createTextNode(s));
           89  +			document.getElementsByTagName("head")[0].appendChild(n);
           90  +		}
           91  +	}
           92  +}
           93  +
           94  +setStylesheet("#AMMLcloseDiv \{font-size:0.8em; padding-top:1em; color:#014\}\n#AMMLwarningBox \{position:absolute; width:100%; top:0; left:0; z-index:200; text-align:center; font-size:1em; font-weight:bold; padding:0.5em 0 0.5em 0; color:#ffc; background:#c30\}");
           95  +
           96  +function init(){
           97  +	var msg, warnings = new Array();
           98  +	if (document.getElementById==null){
           99  +		alert("This webpage requires a recent browser such as Mozilla Firefox");
          100  +		return null;
          101  +	}
          102  +	if (checkForMathML && (msg = checkMathML())) warnings.push(msg);
          103  +	if (warnings.length>0) displayWarnings(warnings);
          104  +	if (!noMathML) initSymbols();
          105  +	return true;
          106  +}
          107  +
          108  +function checkMathML(){
          109  +  if (navigator.appName.slice(0,8)=="Netscape")
          110  +    if (navigator.appVersion.slice(0,1)>="5") noMathML = null;
          111  +    else noMathML = true;
          112  +  else if (navigator.appName.slice(0,9)=="Microsoft")
          113  +    try {
          114  +        var ActiveX = new ActiveXObject("MathPlayer.Factory.1");
          115  +        noMathML = null;
          116  +    } catch (e) {
          117  +        noMathML = true;
          118  +    }
          119  +  else if (navigator.appName.slice(0,5)=="Opera")
          120  +    if (navigator.appVersion.slice(0,3)>="9.5") noMathML = null;
          121  +  else noMathML = true;
          122  +
          123  +  //noMathML = true; //uncomment to check
          124  +  if (noMathML && notifyIfNoMathML) {
          125  +    var msg = "To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later.";
          126  +    if (alertIfNoMathML)
          127  +       alert(msg);
          128  +    else return msg;
          129  +  }
          130  +}
          131  +
          132  +function hideWarning(){
          133  +	var body = document.getElementsByTagName("body")[0];
          134  +	body.removeChild(document.getElementById('AMMLwarningBox'));
          135  +	body.onclick = null;
          136  +}
          137  +
          138  +function displayWarnings(warnings) {
          139  +  var i, frag, nd = createElementXHTML("div");
          140  +  var body = document.getElementsByTagName("body")[0];
          141  +  body.onclick=hideWarning;
          142  +  nd.id = 'AMMLwarningBox';
          143  +  for (i=0; i<warnings.length; i++) {
          144  +	frag = createElementXHTML("div");
          145  +	frag.appendChild(document.createTextNode(warnings[i]));
          146  +	frag.style.paddingBottom = "1.0em";
          147  +	nd.appendChild(frag);
          148  +  }
          149  +  nd.appendChild(createElementXHTML("p"));
          150  +  nd.appendChild(document.createTextNode("For instructions see the "));
          151  +  var an = createElementXHTML("a");
          152  +  an.appendChild(document.createTextNode("ASCIIMathML"));
          153  +  an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");
          154  +  nd.appendChild(an);
          155  +  nd.appendChild(document.createTextNode(" homepage"));
          156  +  an = createElementXHTML("div");
          157  +  an.id = 'AMMLcloseDiv';
          158  +  an.appendChild(document.createTextNode('(click anywhere to close this warning)'));
          159  +  nd.appendChild(an);
          160  +  var body = document.getElementsByTagName("body")[0];
          161  +  body.insertBefore(nd,body.childNodes[0]);
          162  +}
          163  +
          164  +function translate(spanclassAM) {
          165  +  if (!translated) { // run this only once
          166  +    translated = true;
          167  +    var body = document.getElementsByTagName("body")[0];
          168  +    var processN = document.getElementById(AMdocumentId);
          169  +    if (translateASCIIMath) AMprocessNode((processN!=null?processN:body), false, spanclassAM);
          170  +  }
          171  +}
          172  +
          173  +function createElementXHTML(t) {
          174  +  if (isIE) return document.createElement(t);
          175  +  else return document.createElementNS("http://www.w3.org/1999/xhtml",t);
          176  +}
          177  +
          178  +var AMmathml = "http://www.w3.org/1998/Math/MathML";
          179  +
          180  +function AMcreateElementMathML(t) {
          181  +  if (isIE) return document.createElement("m:"+t);
          182  +  else return document.createElementNS(AMmathml,t);
          183  +}
          184  +
          185  +function createMmlNode(t,frag) {
          186  +  var node;
          187  +  if (isIE) node = document.createElement("m:"+t);
          188  +  else node = document.createElementNS(AMmathml,t);
          189  +  if (frag) node.appendChild(frag);
          190  +  return node;
          191  +}
          192  +
          193  +function newcommand(oldstr,newstr) {
          194  +  AMsymbols.push({input:oldstr, tag:"mo", output:newstr, tex:null, ttype:DEFINITION});
          195  +  refreshSymbols();
          196  +}
          197  +
          198  +function newsymbol(symbolobj) {
          199  +  AMsymbols.push(symbolobj);
          200  +  refreshSymbols();
          201  +}
          202  +
          203  +// character lists for Mozilla/Netscape fonts
          204  +var AMcal = ["\uD835\uDC9C","\u212C","\uD835\uDC9E","\uD835\uDC9F","\u2130","\u2131","\uD835\uDCA2","\u210B","\u2110","\uD835\uDCA5","\uD835\uDCA6","\u2112","\u2133","\uD835\uDCA9","\uD835\uDCAA","\uD835\uDCAB","\uD835\uDCAC","\u211B","\uD835\uDCAE","\uD835\uDCAF","\uD835\uDCB0","\uD835\uDCB1","\uD835\uDCB2","\uD835\uDCB3","\uD835\uDCB4","\uD835\uDCB5","\uD835\uDCB6","\uD835\uDCB7","\uD835\uDCB8","\uD835\uDCB9","\u212F","\uD835\uDCBB","\u210A","\uD835\uDCBD","\uD835\uDCBE","\uD835\uDCBF","\uD835\uDCC0","\uD835\uDCC1","\uD835\uDCC2","\uD835\uDCC3","\u2134","\uD835\uDCC5","\uD835\uDCC6","\uD835\uDCC7","\uD835\uDCC8","\uD835\uDCC9","\uD835\uDCCA","\uD835\uDCCB","\uD835\uDCCC","\uD835\uDCCD","\uD835\uDCCE","\uD835\uDCCF"];
          205  +
          206  +var AMfrk = ["\uD835\uDD04","\uD835\uDD05","\u212D","\uD835\uDD07","\uD835\uDD08","\uD835\uDD09","\uD835\uDD0A","\u210C","\u2111","\uD835\uDD0D","\uD835\uDD0E","\uD835\uDD0F","\uD835\uDD10","\uD835\uDD11","\uD835\uDD12","\uD835\uDD13","\uD835\uDD14","\u211C","\uD835\uDD16","\uD835\uDD17","\uD835\uDD18","\uD835\uDD19","\uD835\uDD1A","\uD835\uDD1B","\uD835\uDD1C","\u2128","\uD835\uDD1E","\uD835\uDD1F","\uD835\uDD20","\uD835\uDD21","\uD835\uDD22","\uD835\uDD23","\uD835\uDD24","\uD835\uDD25","\uD835\uDD26","\uD835\uDD27","\uD835\uDD28","\uD835\uDD29","\uD835\uDD2A","\uD835\uDD2B","\uD835\uDD2C","\uD835\uDD2D","\uD835\uDD2E","\uD835\uDD2F","\uD835\uDD30","\uD835\uDD31","\uD835\uDD32","\uD835\uDD33","\uD835\uDD34","\uD835\uDD35","\uD835\uDD36","\uD835\uDD37"];
          207  +
          208  +var AMbbb = ["\uD835\uDD38","\uD835\uDD39","\u2102","\uD835\uDD3B","\uD835\uDD3C","\uD835\uDD3D","\uD835\uDD3E","\u210D","\uD835\uDD40","\uD835\uDD41","\uD835\uDD42","\uD835\uDD43","\uD835\uDD44","\u2115","\uD835\uDD46","\u2119","\u211A","\u211D","\uD835\uDD4A","\uD835\uDD4B","\uD835\uDD4C","\uD835\uDD4D","\uD835\uDD4E","\uD835\uDD4F","\uD835\uDD50","\u2124","\uD835\uDD52","\uD835\uDD53","\uD835\uDD54","\uD835\uDD55","\uD835\uDD56","\uD835\uDD57","\uD835\uDD58","\uD835\uDD59","\uD835\uDD5A","\uD835\uDD5B","\uD835\uDD5C","\uD835\uDD5D","\uD835\uDD5E","\uD835\uDD5F","\uD835\uDD60","\uD835\uDD61","\uD835\uDD62","\uD835\uDD63","\uD835\uDD64","\uD835\uDD65","\uD835\uDD66","\uD835\uDD67","\uD835\uDD68","\uD835\uDD69","\uD835\uDD6A","\uD835\uDD6B"];
          209  +/*var AMcal = [0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];
          210  +var AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];
          211  +var AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];*/
          212  +
          213  +var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,
          214  +    RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,
          215  +    LEFTRIGHT = 9, TEXT = 10, BIG = 11, LONG = 12, STRETCHY = 13,
          216  +    MATRIX = 14, UNARYUNDEROVER = 15; // token types
          217  +
          218  +var AMquote = {input:"\"",   tag:"mtext", output:"mbox", tex:null, ttype:TEXT};
          219  +
          220  +var AMsymbols = [
          221  +//some greek symbols
          222  +{input:"alpha",  tag:"mi", output:"\u03B1", tex:null, ttype:CONST},
          223  +{input:"beta",   tag:"mi", output:"\u03B2", tex:null, ttype:CONST},
          224  +{input:"chi",    tag:"mi", output:"\u03C7", tex:null, ttype:CONST},
          225  +{input:"delta",  tag:"mi", output:"\u03B4", tex:null, ttype:CONST},
          226  +{input:"Delta",  tag:"mo", output:"\u0394", tex:null, ttype:CONST},
          227  +{input:"epsi",   tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},
          228  +{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},
          229  +{input:"eta",    tag:"mi", output:"\u03B7", tex:null, ttype:CONST},
          230  +{input:"gamma",  tag:"mi", output:"\u03B3", tex:null, ttype:CONST},
          231  +{input:"Gamma",  tag:"mo", output:"\u0393", tex:null, ttype:CONST},
          232  +{input:"iota",   tag:"mi", output:"\u03B9", tex:null, ttype:CONST},
          233  +{input:"kappa",  tag:"mi", output:"\u03BA", tex:null, ttype:CONST},
          234  +{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},
          235  +{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},
          236  +{input:"lamda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},
          237  +{input:"Lamda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},
          238  +{input:"mu",     tag:"mi", output:"\u03BC", tex:null, ttype:CONST},
          239  +{input:"nu",     tag:"mi", output:"\u03BD", tex:null, ttype:CONST},
          240  +{input:"omega",  tag:"mi", output:"\u03C9", tex:null, ttype:CONST},
          241  +{input:"Omega",  tag:"mo", output:"\u03A9", tex:null, ttype:CONST},
          242  +{input:"phi",    tag:"mi", output:fixphi?"\u03D5":"\u03C6", tex:null, ttype:CONST},
          243  +{input:"varphi", tag:"mi", output:fixphi?"\u03C6":"\u03D5", tex:null, ttype:CONST},
          244  +{input:"Phi",    tag:"mo", output:"\u03A6", tex:null, ttype:CONST},
          245  +{input:"pi",     tag:"mi", output:"\u03C0", tex:null, ttype:CONST},
          246  +{input:"Pi",     tag:"mo", output:"\u03A0", tex:null, ttype:CONST},
          247  +{input:"psi",    tag:"mi", output:"\u03C8", tex:null, ttype:CONST},
          248  +{input:"Psi",    tag:"mi", output:"\u03A8", tex:null, ttype:CONST},
          249  +{input:"rho",    tag:"mi", output:"\u03C1", tex:null, ttype:CONST},
          250  +{input:"sigma",  tag:"mi", output:"\u03C3", tex:null, ttype:CONST},
          251  +{input:"Sigma",  tag:"mo", output:"\u03A3", tex:null, ttype:CONST},
          252  +{input:"tau",    tag:"mi", output:"\u03C4", tex:null, ttype:CONST},
          253  +{input:"theta",  tag:"mi", output:"\u03B8", tex:null, ttype:CONST},
          254  +{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},
          255  +{input:"Theta",  tag:"mo", output:"\u0398", tex:null, ttype:CONST},
          256  +{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},
          257  +{input:"xi",     tag:"mi", output:"\u03BE", tex:null, ttype:CONST},
          258  +{input:"Xi",     tag:"mo", output:"\u039E", tex:null, ttype:CONST},
          259  +{input:"zeta",   tag:"mi", output:"\u03B6", tex:null, ttype:CONST},
          260  +
          261  +//binary operation symbols
          262  +//{input:"-",  tag:"mo", output:"\u0096", tex:null, ttype:CONST},
          263  +{input:"*",  tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},
          264  +{input:"**", tag:"mo", output:"\u2217", tex:"ast", ttype:CONST},
          265  +{input:"***", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},
          266  +{input:"//", tag:"mo", output:"/",      tex:null, ttype:CONST},
          267  +{input:"\\\\", tag:"mo", output:"\\",   tex:"backslash", ttype:CONST},
          268  +{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},
          269  +{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},
          270  +{input:"|><", tag:"mo", output:"\u22C9", tex:"ltimes", ttype:CONST},
          271  +{input:"><|", tag:"mo", output:"\u22CA", tex:"rtimes", ttype:CONST},
          272  +{input:"|><|", tag:"mo", output:"\u22C8", tex:"bowtie", ttype:CONST},
          273  +{input:"-:", tag:"mo", output:"\u00F7", tex:"div", ttype:CONST},
          274  +{input:"divide",   tag:"mo", output:"-:", tex:null, ttype:DEFINITION},
          275  +{input:"@",  tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},
          276  +{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},
          277  +{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},
          278  +{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},
          279  +{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},
          280  +{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},
          281  +{input:"^^",  tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},
          282  +{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},
          283  +{input:"vv",  tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},
          284  +{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},
          285  +{input:"nn",  tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},
          286  +{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},
          287  +{input:"uu",  tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},
          288  +{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},
          289  +
          290  +//binary relation symbols
          291  +{input:"!=",  tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},
          292  +{input:":=",  tag:"mo", output:":=",     tex:null, ttype:CONST},
          293  +{input:"lt",  tag:"mo", output:"<",      tex:null, ttype:CONST},
          294  +{input:"<=",  tag:"mo", output:"\u2264", tex:"le", ttype:CONST},
          295  +{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},
          296  +{input:"gt",  tag:"mo", output:">",      tex:null, ttype:CONST},
          297  +{input:">=",  tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},
          298  +{input:"gt=", tag:"mo", output:"\u2265", tex:"geq", ttype:CONST},
          299  +{input:"-<",  tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},
          300  +{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},
          301  +{input:">-",  tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},
          302  +{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},
          303  +{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},
          304  +{input:"in",  tag:"mo", output:"\u2208", tex:null, ttype:CONST},
          305  +{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},
          306  +{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},
          307  +{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},
          308  +{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},
          309  +{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},
          310  +{input:"-=",  tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},
          311  +{input:"~=",  tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},
          312  +{input:"~~",  tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},
          313  +{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},
          314  +
          315  +//logical symbols
          316  +{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},
          317  +{input:"or",  tag:"mtext", output:"or",  tex:null, ttype:SPACE},
          318  +{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},
          319  +{input:"=>",  tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},
          320  +{input:"if",  tag:"mo", output:"if",     tex:null, ttype:SPACE},
          321  +{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},
          322  +{input:"AA",  tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},
          323  +{input:"EE",  tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},
          324  +{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},
          325  +{input:"TT",  tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},
          326  +{input:"|--",  tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},
          327  +{input:"|==",  tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},
          328  +
          329  +//grouping brackets
          330  +{input:"(", tag:"mo", output:"(", tex:"left(", ttype:LEFTBRACKET},
          331  +{input:")", tag:"mo", output:")", tex:"right)", ttype:RIGHTBRACKET},
          332  +{input:"[", tag:"mo", output:"[", tex:"left[", ttype:LEFTBRACKET},
          333  +{input:"]", tag:"mo", output:"]", tex:"right]", ttype:RIGHTBRACKET},
          334  +{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},
          335  +{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},
          336  +{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},
          337  +{input:":|:", tag:"mo", output:"|", tex:null, ttype:CONST},
          338  +{input:"|:", tag:"mo", output:"|", tex:null, ttype:LEFTBRACKET},
          339  +{input:":|", tag:"mo", output:"|", tex:null, ttype:RIGHTBRACKET},
          340  +//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},
          341  +{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},
          342  +{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},
          343  +{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},
          344  +{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},
          345  +{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},
          346  +{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},
          347  +
          348  +//miscellaneous symbols
          349  +{input:"int",  tag:"mo", output:"\u222B", tex:null, ttype:CONST},
          350  +{input:"dx",   tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},
          351  +{input:"dy",   tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},
          352  +{input:"dz",   tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},
          353  +{input:"dt",   tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},
          354  +{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},
          355  +{input:"del",  tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},
          356  +{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},
          357  +{input:"+-",   tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},
          358  +{input:"O/",   tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},
          359  +{input:"oo",   tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},
          360  +{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},
          361  +{input:"...",  tag:"mo", output:"...",    tex:"ldots", ttype:CONST},
          362  +{input:":.",  tag:"mo", output:"\u2234",  tex:"therefore", ttype:CONST},
          363  +{input:":'",  tag:"mo", output:"\u2235",  tex:"because", ttype:CONST},
          364  +{input:"/_",  tag:"mo", output:"\u2220",  tex:"angle", ttype:CONST},
          365  +{input:"/_\\",  tag:"mo", output:"\u25B3",  tex:"triangle", ttype:CONST},
          366  +{input:"'",   tag:"mo", output:"\u2032",  tex:"prime", ttype:CONST},
          367  +{input:"tilde", tag:"mover", output:"~", tex:null, ttype:UNARY, acc:true},
          368  +{input:"\\ ",  tag:"mo", output:"\u00A0", tex:null, ttype:CONST},
          369  +{input:"frown",  tag:"mo", output:"\u2322", tex:null, ttype:CONST},
          370  +{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},
          371  +{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},
          372  +{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},
          373  +{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},
          374  +{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},
          375  +{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},
          376  +{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},
          377  +{input:"|__", tag:"mo", output:"\u230A",  tex:"lfloor", ttype:CONST},
          378  +{input:"__|", tag:"mo", output:"\u230B",  tex:"rfloor", ttype:CONST},
          379  +{input:"|~", tag:"mo", output:"\u2308",  tex:"lceiling", ttype:CONST},
          380  +{input:"~|", tag:"mo", output:"\u2309",  tex:"rceiling", ttype:CONST},
          381  +{input:"CC",  tag:"mo", output:"\u2102", tex:null, ttype:CONST},
          382  +{input:"NN",  tag:"mo", output:"\u2115", tex:null, ttype:CONST},
          383  +{input:"QQ",  tag:"mo", output:"\u211A", tex:null, ttype:CONST},
          384  +{input:"RR",  tag:"mo", output:"\u211D", tex:null, ttype:CONST},
          385  +{input:"ZZ",  tag:"mo", output:"\u2124", tex:null, ttype:CONST},
          386  +{input:"f",   tag:"mi", output:"f",      tex:null, ttype:UNARY, func:true},
          387  +{input:"g",   tag:"mi", output:"g",      tex:null, ttype:UNARY, func:true},
          388  +
          389  +//standard functions
          390  +{input:"lim",  tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},
          391  +{input:"Lim",  tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},
          392  +{input:"sin",  tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},
          393  +{input:"cos",  tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},
          394  +{input:"tan",  tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},
          395  +{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},
          396  +{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},
          397  +{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},
          398  +{input:"cot",  tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},
          399  +{input:"sec",  tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},
          400  +{input:"csc",  tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},
          401  +{input:"arcsin",  tag:"mo", output:"arcsin", tex:null, ttype:UNARY, func:true},
          402  +{input:"arccos",  tag:"mo", output:"arccos", tex:null, ttype:UNARY, func:true},
          403  +{input:"arctan",  tag:"mo", output:"arctan", tex:null, ttype:UNARY, func:true},
          404  +{input:"coth",  tag:"mo", output:"coth", tex:null, ttype:UNARY, func:true},
          405  +{input:"sech",  tag:"mo", output:"sech", tex:null, ttype:UNARY, func:true},
          406  +{input:"csch",  tag:"mo", output:"csch", tex:null, ttype:UNARY, func:true},
          407  +{input:"exp",  tag:"mo", output:"exp", tex:null, ttype:UNARY, func:true},
          408  +{input:"abs",   tag:"mo", output:"abs",  tex:null, ttype:UNARY, rewriteleftright:["|","|"]},
          409  +{input:"norm",   tag:"mo", output:"norm",  tex:null, ttype:UNARY, rewriteleftright:["\u2225","\u2225"]},
          410  +{input:"floor",   tag:"mo", output:"floor",  tex:null, ttype:UNARY, rewriteleftright:["\u230A","\u230B"]},
          411  +{input:"ceil",   tag:"mo", output:"ceil",  tex:null, ttype:UNARY, rewriteleftright:["\u2308","\u2309"]},
          412  +{input:"log",  tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},
          413  +{input:"ln",   tag:"mo", output:"ln",  tex:null, ttype:UNARY, func:true},
          414  +{input:"det",  tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},
          415  +{input:"dim",  tag:"mo", output:"dim", tex:null, ttype:CONST},
          416  +{input:"mod",  tag:"mo", output:"mod", tex:null, ttype:CONST},
          417  +{input:"gcd",  tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},
          418  +{input:"lcm",  tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},
          419  +{input:"lub",  tag:"mo", output:"lub", tex:null, ttype:CONST},
          420  +{input:"glb",  tag:"mo", output:"glb", tex:null, ttype:CONST},
          421  +{input:"min",  tag:"mo", output:"min", tex:null, ttype:UNDEROVER},
          422  +{input:"max",  tag:"mo", output:"max", tex:null, ttype:UNDEROVER},
          423  +{input:"Sin",  tag:"mo", output:"Sin", tex:null, ttype:UNARY, func:true},
          424  +{input:"Cos",  tag:"mo", output:"Cos", tex:null, ttype:UNARY, func:true},
          425  +{input:"Tan",  tag:"mo", output:"Tan", tex:null, ttype:UNARY, func:true},
          426  +{input:"Arcsin",  tag:"mo", output:"Arcsin", tex:null, ttype:UNARY, func:true},
          427  +{input:"Arccos",  tag:"mo", output:"Arccos", tex:null, ttype:UNARY, func:true},
          428  +{input:"Arctan",  tag:"mo", output:"Arctan", tex:null, ttype:UNARY, func:true},
          429  +{input:"Sinh", tag:"mo", output:"Sinh", tex:null, ttype:UNARY, func:true},
          430  +{input:"Cosh", tag:"mo", output:"Cosh", tex:null, ttype:UNARY, func:true},
          431  +{input:"Tanh", tag:"mo", output:"Tanh", tex:null, ttype:UNARY, func:true},
          432  +{input:"Cot",  tag:"mo", output:"Cot", tex:null, ttype:UNARY, func:true},
          433  +{input:"Sec",  tag:"mo", output:"Sec", tex:null, ttype:UNARY, func:true},
          434  +{input:"Csc",  tag:"mo", output:"Csc", tex:null, ttype:UNARY, func:true},
          435  +{input:"Log",  tag:"mo", output:"Log", tex:null, ttype:UNARY, func:true},
          436  +{input:"Ln",   tag:"mo", output:"Ln",  tex:null, ttype:UNARY, func:true},
          437  +{input:"Abs",   tag:"mo", output:"abs",  tex:null, ttype:UNARY, notexcopy:true, rewriteleftright:["|","|"]},
          438  +
          439  +//arrows
          440  +{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},
          441  +{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},
          442  +{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},
          443  +{input:"->",   tag:"mo", output:"\u2192", tex:"to", ttype:CONST},
          444  +{input:">->",   tag:"mo", output:"\u21A3", tex:"rightarrowtail", ttype:CONST},
          445  +{input:"->>",   tag:"mo", output:"\u21A0", tex:"twoheadrightarrow", ttype:CONST},
          446  +{input:">->>",   tag:"mo", output:"\u2916", tex:"twoheadrightarrowtail", ttype:CONST},
          447  +{input:"|->",  tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},
          448  +{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},
          449  +{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},
          450  +{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},
          451  +{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},
          452  +{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},
          453  +//commands with argument
          454  +{input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},
          455  +{input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},
          456  +{input:"frac", tag:"mfrac", output:"/",    tex:null, ttype:BINARY},
          457  +{input:"/",    tag:"mfrac", output:"/",    tex:null, ttype:INFIX},
          458  +{input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},
          459  +{input:"overset", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},
          460  +{input:"underset", tag:"munder", output:"stackrel", tex:null, ttype:BINARY},
          461  +{input:"_",    tag:"msub",  output:"_",    tex:null, ttype:INFIX},
          462  +{input:"^",    tag:"msup",  output:"^",    tex:null, ttype:INFIX},
          463  +{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},
          464  +{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},
          465  +{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},
          466  +{input:"dot", tag:"mover", output:".",      tex:null, ttype:UNARY, acc:true},
          467  +{input:"ddot", tag:"mover", output:"..",    tex:null, ttype:UNARY, acc:true},
          468  +{input:"overarc", tag:"mover", output:"\u23DC", tex:"overparen", ttype:UNARY, acc:true},
          469  +{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},
          470  +{input:"ubrace", tag:"munder", output:"\u23DF", tex:"underbrace", ttype:UNARYUNDEROVER, acc:true},
          471  +{input:"obrace", tag:"mover", output:"\u23DE", tex:"overbrace", ttype:UNARYUNDEROVER, acc:true},
          472  +{input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},
          473  +{input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},
          474  +{input:"color", tag:"mstyle", ttype:BINARY},
          475  +{input:"id", tag:"mrow", ttype:BINARY},
          476  +{input:"class", tag:"mrow", ttype:BINARY},
          477  +{input:"cancel", tag:"menclose", output:"cancel", tex:null, ttype:UNARY},
          478  +AMquote,
          479  +{input:"bb", tag:"mstyle", atname:"mathvariant", atval:"bold", output:"bb", tex:null, ttype:UNARY},
          480  +{input:"mathbf", tag:"mstyle", atname:"mathvariant", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},
          481  +{input:"sf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},
          482  +{input:"mathsf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},
          483  +{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},
          484  +{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},
          485  +{input:"cc",  tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},
          486  +{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},
          487  +{input:"tt",  tag:"mstyle", atname:"mathvariant", atval:"monospace", output:"tt", tex:null, ttype:UNARY},
          488  +{input:"mathtt", tag:"mstyle", atname:"mathvariant", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},
          489  +{input:"fr",  tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},
          490  +{input:"mathfrak",  tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}
          491  +];
          492  +
          493  +function compareNames(s1,s2) {
          494  +  if (s1.input > s2.input) return 1
          495  +  else return -1;
          496  +}
          497  +
          498  +var AMnames = []; //list of input symbols
          499  +
          500  +function initSymbols() {
          501  +  var i;
          502  +  var symlen = AMsymbols.length;
          503  +  for (i=0; i<symlen; i++) {
          504  +    if (AMsymbols[i].tex) {
          505  +      AMsymbols.push({input:AMsymbols[i].tex,
          506  +        tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype,
          507  +        acc:(AMsymbols[i].acc||false)});
          508  +    }
          509  +  }
          510  +  refreshSymbols();
          511  +}
          512  +
          513  +function refreshSymbols(){
          514  +  var i;
          515  +  AMsymbols.sort(compareNames);
          516  +  for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;
          517  +}
          518  +
          519  +function define(oldstr,newstr) {
          520  +  AMsymbols.push({input:oldstr, tag:"mo", output:newstr, tex:null, ttype:DEFINITION});
          521  +  refreshSymbols(); // this may be a problem if many symbols are defined!
          522  +}
          523  +
          524  +function AMremoveCharsAndBlanks(str,n) {
          525  +//remove n characters and any following blanks
          526  +  var st;
          527  +  if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ")
          528  +    st = str.slice(n+1);
          529  +  else st = str.slice(n);
          530  +  for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);
          531  +  return st.slice(i);
          532  +}
          533  +
          534  +function position(arr, str, n) {
          535  +// return position >=n where str appears or would be inserted
          536  +// assumes arr is sorted
          537  +  if (n==0) {
          538  +    var h,m;
          539  +    n = -1;
          540  +    h = arr.length;
          541  +    while (n+1<h) {
          542  +      m = (n+h) >> 1;
          543  +      if (arr[m]<str) n = m; else h = m;
          544  +    }
          545  +    return h;
          546  +  } else
          547  +    for (var i=n; i<arr.length && arr[i]<str; i++);
          548  +  return i; // i=arr.length || arr[i]>=str
          549  +}
          550  +
          551  +function AMgetSymbol(str) {
          552  +//return maximal initial substring of str that appears in names
          553  +//return null if there is none
          554  +  var k = 0; //new pos
          555  +  var j = 0; //old pos
          556  +  var mk; //match pos
          557  +  var st;
          558  +  var tagst;
          559  +  var match = "";
          560  +  var more = true;
          561  +  for (var i=1; i<=str.length && more; i++) {
          562  +    st = str.slice(0,i); //initial substring of length i
          563  +    j = k;
          564  +    k = position(AMnames, st, j);
          565  +    if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){
          566  +      match = AMnames[k];
          567  +      mk = k;
          568  +      i = match.length;
          569  +    }
          570  +    more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];
          571  +  }
          572  +  AMpreviousSymbol=AMcurrentSymbol;
          573  +  if (match!=""){
          574  +    AMcurrentSymbol=AMsymbols[mk].ttype;
          575  +    return AMsymbols[mk];
          576  +  }
          577  +// if str[0] is a digit or - return maxsubstring of digits.digits
          578  +  AMcurrentSymbol=CONST;
          579  +  k = 1;
          580  +  st = str.slice(0,1);
          581  +  var integ = true;
          582  +  while ("0"<=st && st<="9" && k<=str.length) {
          583  +    st = str.slice(k,k+1);
          584  +    k++;
          585  +  }
          586  +  if (st == decimalsign) {
          587  +    st = str.slice(k,k+1);
          588  +    if ("0"<=st && st<="9") {
          589  +      integ = false;
          590  +      k++;
          591  +      while ("0"<=st && st<="9" && k<=str.length) {
          592  +        st = str.slice(k,k+1);
          593  +        k++;
          594  +      }
          595  +    }
          596  +  }
          597  +  if ((integ && k>1) || k>2) {
          598  +    st = str.slice(0,k-1);
          599  +    tagst = "mn";
          600  +  } else {
          601  +    k = 2;
          602  +    st = str.slice(0,1); //take 1 character
          603  +    tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");
          604  +  }
          605  +  if (st=="-" && AMpreviousSymbol==INFIX) {
          606  +    AMcurrentSymbol = INFIX;  //trick "/" into recognizing "-" on second parse
          607  +    return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};
          608  +  }
          609  +  return {input:st, tag:tagst, output:st, ttype:CONST};
          610  +}
          611  +
          612  +function AMremoveBrackets(node) {
          613  +  var st;
          614  +  if (!node.hasChildNodes()) { return; }
          615  +  if (node.firstChild.hasChildNodes() && (node.nodeName=="mrow" || node.nodeName=="M:MROW")) {
          616  +    st = node.firstChild.firstChild.nodeValue;
          617  +    if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);
          618  +  }
          619  +  if (node.lastChild.hasChildNodes() && (node.nodeName=="mrow" || node.nodeName=="M:MROW")) {
          620  +    st = node.lastChild.firstChild.nodeValue;
          621  +    if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);
          622  +  }
          623  +}
          624  +
          625  +/*Parsing ASCII math expressions with the following grammar
          626  +v ::= [A-Za-z] | greek letters | numbers | other constant symbols
          627  +u ::= sqrt | text | bb | other unary symbols for font commands
          628  +b ::= frac | root | stackrel         binary symbols
          629  +l ::= ( | [ | { | (: | {:            left brackets
          630  +r ::= ) | ] | } | :) | :}            right brackets
          631  +S ::= v | lEr | uS | bSS             Simple expression
          632  +I ::= S_S | S^S | S_S^S | S          Intermediate expression
          633  +E ::= IE | I/I                       Expression
          634  +Each terminal symbol is translated into a corresponding mathml node.*/
          635  +
          636  +var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;
          637  +
          638  +function AMparseSexpr(str) { //parses str and returns [node,tailstr]
          639  +  var symbol, node, result, i, st,// rightvert = false,
          640  +    newFrag = document.createDocumentFragment();
          641  +  str = AMremoveCharsAndBlanks(str,0);
          642  +  symbol = AMgetSymbol(str);             //either a token or a bracket or empty
          643  +  if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {
          644  +    return [null,str];
          645  +  }
          646  +  if (symbol.ttype == DEFINITION) {
          647  +    str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length);
          648  +    symbol = AMgetSymbol(str);
          649  +  }
          650  +  switch (symbol.ttype) {  case UNDEROVER:
          651  +  case CONST:
          652  +    str = AMremoveCharsAndBlanks(str,symbol.input.length);
          653  +    return [createMmlNode(symbol.tag,        //its a constant
          654  +                             document.createTextNode(symbol.output)),str];
          655  +  case LEFTBRACKET:   //read (expr+)
          656  +    AMnestingDepth++;
          657  +    str = AMremoveCharsAndBlanks(str,symbol.input.length);
          658  +    result = AMparseExpr(str,true);
          659  +    AMnestingDepth--;
          660  +    if (typeof symbol.invisible == "boolean" && symbol.invisible)
          661  +      node = createMmlNode("mrow",result[0]);
          662  +    else {
          663  +      node = createMmlNode("mo",document.createTextNode(symbol.output));
          664  +      node = createMmlNode("mrow",node);
          665  +      node.appendChild(result[0]);
          666  +    }
          667  +    return [node,result[1]];
          668  +  case TEXT:
          669  +      if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);
          670  +      if (str.charAt(0)=="{") i=str.indexOf("}");
          671  +      else if (str.charAt(0)=="(") i=str.indexOf(")");
          672  +      else if (str.charAt(0)=="[") i=str.indexOf("]");
          673  +      else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;
          674  +      else i = 0;
          675  +      if (i==-1) i = str.length;
          676  +      st = str.slice(1,i);
          677  +      if (st.charAt(0) == " ") {
          678  +        node = createMmlNode("mspace");
          679  +        node.setAttribute("width","1ex");
          680  +        newFrag.appendChild(node);
          681  +      }
          682  +      newFrag.appendChild(
          683  +        createMmlNode(symbol.tag,document.createTextNode(st)));
          684  +      if (st.charAt(st.length-1) == " ") {
          685  +        node = createMmlNode("mspace");
          686  +        node.setAttribute("width","1ex");
          687  +        newFrag.appendChild(node);
          688  +      }
          689  +      str = AMremoveCharsAndBlanks(str,i+1);
          690  +      return [createMmlNode("mrow",newFrag),str];
          691  +  case UNARYUNDEROVER:
          692  +  case UNARY:
          693  +      str = AMremoveCharsAndBlanks(str,symbol.input.length);
          694  +      result = AMparseSexpr(str);
          695  +      if (result[0]==null) return [createMmlNode(symbol.tag,
          696  +                             document.createTextNode(symbol.output)),str];
          697  +      if (typeof symbol.func == "boolean" && symbol.func) { // functions hack
          698  +        st = str.charAt(0);
          699  +          if (st=="^" || st=="_" || st=="/" || st=="|" || st=="," ||
          700  +             (symbol.input.length==1 && symbol.input.match(/\w/) && st!="(")) {
          701  +          return [createMmlNode(symbol.tag,
          702  +                    document.createTextNode(symbol.output)),str];
          703  +        } else {
          704  +          node = createMmlNode("mrow",
          705  +           createMmlNode(symbol.tag,document.createTextNode(symbol.output)));
          706  +          node.appendChild(result[0]);
          707  +          return [node,result[1]];
          708  +        }
          709  +      }
          710  +      AMremoveBrackets(result[0]);
          711  +      if (symbol.input == "sqrt") {           // sqrt
          712  +        return [createMmlNode(symbol.tag,result[0]),result[1]];
          713  +      } else if (typeof symbol.rewriteleftright != "undefined") {    // abs, floor, ceil
          714  +          node = createMmlNode("mrow", createMmlNode("mo",document.createTextNode(symbol.rewriteleftright[0])));
          715  +          node.appendChild(result[0]);
          716  +          node.appendChild(createMmlNode("mo",document.createTextNode(symbol.rewriteleftright[1])));
          717  +          return [node,result[1]];
          718  +      } else if (symbol.input == "cancel") {   // cancel
          719  +        node = createMmlNode(symbol.tag,result[0]);
          720  +	node.setAttribute("notation","updiagonalstrike");
          721  +	return [node,result[1]];
          722  +      } else if (typeof symbol.acc == "boolean" && symbol.acc) {   // accent
          723  +        node = createMmlNode(symbol.tag,result[0]);
          724  +        var accnode = createMmlNode("mo",document.createTextNode(symbol.output));
          725  +        if (symbol.input=="vec" && (
          726  +		(result[0].nodeName=="mrow" && result[0].childNodes.length==1
          727  +			&& result[0].firstChild.firstChild.nodeValue !== null
          728  +			&& result[0].firstChild.firstChild.nodeValue.length==1) ||
          729  +		(result[0].firstChild.nodeValue !== null
          730  +			&& result[0].firstChild.nodeValue.length==1) )) {
          731  +			accnode.setAttribute("stretchy",false);
          732  +        }
          733  +        node.appendChild(accnode);
          734  +        return [node,result[1]];
          735  +      } else {                        // font change command
          736  +        if (!isIE && typeof symbol.codes != "undefined") {
          737  +          for (i=0; i<result[0].childNodes.length; i++)
          738  +            if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {
          739  +              st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:
          740  +                              result[0].childNodes[i].firstChild.nodeValue);
          741  +              var newst = [];
          742  +              for (var j=0; j<st.length; j++)
          743  +		  if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91)
          744  +		  	newst = newst + symbol.codes[st.charCodeAt(j)-65];
          745  +                else if (st.charCodeAt(j)>96 && st.charCodeAt(j)<123)
          746  +                	newst = newst + symbol.codes[st.charCodeAt(j)-71];
          747  +                else newst = newst + st.charAt(j);
          748  +              if (result[0].nodeName=="mi")
          749  +                result[0]=createMmlNode("mo").
          750  +                          appendChild(document.createTextNode(newst));
          751  +              else result[0].replaceChild(createMmlNode("mo").
          752  +                               appendChild(document.createTextNode(newst)),
          753  +                                           result[0].childNodes[i]);
          754  +            }
          755  +        }
          756  +        node = createMmlNode(symbol.tag,result[0]);
          757  +        node.setAttribute(symbol.atname,symbol.atval);
          758  +        return [node,result[1]];
          759  +      }
          760  +  case BINARY:
          761  +    str = AMremoveCharsAndBlanks(str,symbol.input.length);
          762  +    result = AMparseSexpr(str);
          763  +    if (result[0]==null) return [createMmlNode("mo",
          764  +                           document.createTextNode(symbol.input)),str];
          765  +    AMremoveBrackets(result[0]);
          766  +    var result2 = AMparseSexpr(result[1]);
          767  +    if (result2[0]==null) return [createMmlNode("mo",
          768  +                           document.createTextNode(symbol.input)),str];
          769  +    AMremoveBrackets(result2[0]);
          770  +    if (['color', 'class', 'id'].indexOf(symbol.input) >= 0) {
          771  +
          772  +      // Get the second argument
          773  +    	if (str.charAt(0)=="{") i=str.indexOf("}");
          774  +      else if (str.charAt(0)=="(") i=str.indexOf(")");
          775  +      else if (str.charAt(0)=="[") i=str.indexOf("]");
          776  +    	st = str.slice(1,i);
          777  +
          778  +      // Make a mathml node
          779  +    	node = createMmlNode(symbol.tag,result2[0]);
          780  +
          781  +      // Set the correct attribute
          782  +      if (symbol.input === "color") node.setAttribute("mathcolor", st)
          783  +      else if (symbol.input === "class") node.setAttribute("class", st)
          784  +      else if (symbol.input === "id") node.setAttribute("id", st)
          785  +    	return [node,result2[1]];
          786  +    }
          787  +    if (symbol.input=="root" || symbol.output=="stackrel")
          788  +      newFrag.appendChild(result2[0]);
          789  +    newFrag.appendChild(result[0]);
          790  +    if (symbol.input=="frac") newFrag.appendChild(result2[0]);
          791  +    return [createMmlNode(symbol.tag,newFrag),result2[1]];
          792  +  case INFIX:
          793  +    str = AMremoveCharsAndBlanks(str,symbol.input.length);
          794  +    return [createMmlNode("mo",document.createTextNode(symbol.output)),str];
          795  +  case SPACE:
          796  +    str = AMremoveCharsAndBlanks(str,symbol.input.length);
          797  +    node = createMmlNode("mspace");
          798  +    node.setAttribute("width","1ex");
          799  +    newFrag.appendChild(node);
          800  +    newFrag.appendChild(
          801  +      createMmlNode(symbol.tag,document.createTextNode(symbol.output)));
          802  +    node = createMmlNode("mspace");
          803  +    node.setAttribute("width","1ex");
          804  +    newFrag.appendChild(node);
          805  +    return [createMmlNode("mrow",newFrag),str];
          806  +  case LEFTRIGHT:
          807  +//    if (rightvert) return [null,str]; else rightvert = true;
          808  +    AMnestingDepth++;
          809  +    str = AMremoveCharsAndBlanks(str,symbol.input.length);
          810  +    result = AMparseExpr(str,false);
          811  +    AMnestingDepth--;
          812  +    st = "";
          813  +    if (result[0].lastChild!=null)
          814  +      st = result[0].lastChild.firstChild.nodeValue;
          815  +    if (st == "|" && str.charAt(0)!==",") { // its an absolute value subterm
          816  +      node = createMmlNode("mo",document.createTextNode(symbol.output));
          817  +      node = createMmlNode("mrow",node);
          818  +      node.appendChild(result[0]);
          819  +      return [node,result[1]];
          820  +    } else { // the "|" is a \mid so use unicode 2223 (divides) for spacing
          821  +      node = createMmlNode("mo",document.createTextNode("\u2223"));
          822  +      node = createMmlNode("mrow",node);
          823  +      return [node,str];
          824  +    }
          825  +  default:
          826  +//alert("default");
          827  +    str = AMremoveCharsAndBlanks(str,symbol.input.length);
          828  +    return [createMmlNode(symbol.tag,        //its a constant
          829  +                             document.createTextNode(symbol.output)),str];
          830  +  }
          831  +}
          832  +
          833  +function AMparseIexpr(str) {
          834  +  var symbol, sym1, sym2, node, result, underover;
          835  +  str = AMremoveCharsAndBlanks(str,0);
          836  +  sym1 = AMgetSymbol(str);
          837  +  result = AMparseSexpr(str);
          838  +  node = result[0];
          839  +  str = result[1];
          840  +  symbol = AMgetSymbol(str);
          841  +  if (symbol.ttype == INFIX && symbol.input != "/") {
          842  +    str = AMremoveCharsAndBlanks(str,symbol.input.length);
          843  +//    if (symbol.input == "/") result = AMparseIexpr(str); else ...
          844  +    result = AMparseSexpr(str);
          845  +    if (result[0] == null) // show box in place of missing argument
          846  +      result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));
          847  +    else AMremoveBrackets(result[0]);
          848  +    str = result[1];
          849  +//    if (symbol.input == "/") AMremoveBrackets(node);
          850  +    underover = (sym1.ttype == UNDEROVER || sym1.ttype == UNARYUNDEROVER);
          851  +    if (symbol.input == "_") {
          852  +      sym2 = AMgetSymbol(str);
          853  +      if (sym2.input == "^") {
          854  +        str = AMremoveCharsAndBlanks(str,sym2.input.length);
          855  +        var res2 = AMparseSexpr(str);
          856  +        AMremoveBrackets(res2[0]);
          857  +        str = res2[1];
          858  +        node = createMmlNode((underover?"munderover":"msubsup"),node);
          859  +        node.appendChild(result[0]);
          860  +        node.appendChild(res2[0]);
          861  +        node = createMmlNode("mrow",node); // so sum does not stretch
          862  +      } else {
          863  +        node = createMmlNode((underover?"munder":"msub"),node);
          864  +        node.appendChild(result[0]);
          865  +      }
          866  +    } else if (symbol.input == "^" && underover) {
          867  +    	node = createMmlNode("mover",node);
          868  +        node.appendChild(result[0]);
          869  +    } else {
          870  +      node = createMmlNode(symbol.tag,node);
          871  +      node.appendChild(result[0]);
          872  +    }
          873  +    if (typeof sym1.func != 'undefined' && sym1.func) {
          874  +    	sym2 = AMgetSymbol(str);
          875  +    	if (sym2.ttype != INFIX && sym2.ttype != RIGHTBRACKET &&
          876  +    	    (sym1.input.length>1 || sym2.ttype == LEFTBRACKET)) {
          877  +    		result = AMparseIexpr(str);
          878  +    		node = createMmlNode("mrow",node);
          879  +    		node.appendChild(result[0]);
          880  +    		str = result[1];
          881  +    	}
          882  +    }
          883  +  }
          884  +  return [node,str];
          885  +}
          886  +
          887  +function AMparseExpr(str,rightbracket) {
          888  +  var symbol, node, result, i,
          889  +  newFrag = document.createDocumentFragment();
          890  +  do {
          891  +    str = AMremoveCharsAndBlanks(str,0);
          892  +    result = AMparseIexpr(str);
          893  +    node = result[0];
          894  +    str = result[1];
          895  +    symbol = AMgetSymbol(str);
          896  +    if (symbol.ttype == INFIX && symbol.input == "/") {
          897  +      str = AMremoveCharsAndBlanks(str,symbol.input.length);
          898  +      result = AMparseIexpr(str);
          899  +      if (result[0] == null) // show box in place of missing argument
          900  +        result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));
          901  +      else AMremoveBrackets(result[0]);
          902  +      str = result[1];
          903  +      AMremoveBrackets(node);
          904  +      node = createMmlNode(symbol.tag,node);
          905  +      node.appendChild(result[0]);
          906  +      newFrag.appendChild(node);
          907  +      symbol = AMgetSymbol(str);
          908  +    }
          909  +    else if (node!=undefined) newFrag.appendChild(node);
          910  +  } while ((symbol.ttype != RIGHTBRACKET &&
          911  +           (symbol.ttype != LEFTRIGHT || rightbracket)
          912  +           || AMnestingDepth == 0) && symbol!=null && symbol.output!="");
          913  +  if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {
          914  +//    if (AMnestingDepth > 0) AMnestingDepth--;
          915  +    var len = newFrag.childNodes.length;
          916  +    if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow"
          917  +    	    && newFrag.childNodes[len-1].lastChild
          918  +    	    && newFrag.childNodes[len-1].lastChild.firstChild ) { //matrix
          919  +    	    //removed to allow row vectors: //&& len>1 &&
          920  +    	    //newFrag.childNodes[len-2].nodeName == "mo" &&
          921  +    	    //newFrag.childNodes[len-2].firstChild.nodeValue == ","
          922  +      var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;
          923  +      if (right==")" || right=="]") {
          924  +        var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;
          925  +        if (left=="(" && right==")" && symbol.output != "}" ||
          926  +            left=="[" && right=="]") {
          927  +        var pos = []; // positions of commas
          928  +        var matrix = true;
          929  +        var m = newFrag.childNodes.length;
          930  +        for (i=0; matrix && i<m; i=i+2) {
          931  +          pos[i] = [];
          932  +          node = newFrag.childNodes[i];
          933  +          if (matrix) matrix = node.nodeName=="mrow" &&
          934  +            (i==m-1 || node.nextSibling.nodeName=="mo" &&
          935  +            node.nextSibling.firstChild.nodeValue==",")&&
          936  +            node.firstChild.firstChild.nodeValue==left &&
          937  +            node.lastChild.firstChild.nodeValue==right;
          938  +          if (matrix)
          939  +            for (var j=0; j<node.childNodes.length; j++)
          940  +              if (node.childNodes[j].firstChild.nodeValue==",")
          941  +                pos[i][pos[i].length]=j;
          942  +          if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;
          943  +        }
          944  +        matrix = matrix && (pos.length>1 || pos[0].length>0);
          945  +        var columnlines = [];
          946  +        if (matrix) {
          947  +          var row, frag, n, k, table = document.createDocumentFragment();
          948  +          for (i=0; i<m; i=i+2) {
          949  +            row = document.createDocumentFragment();
          950  +            frag = document.createDocumentFragment();
          951  +            node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>
          952  +            n = node.childNodes.length;
          953  +            k = 0;
          954  +            node.removeChild(node.firstChild); //remove (
          955  +            for (j=1; j<n-1; j++) {
          956  +              if (typeof pos[i][k] != "undefined" && j==pos[i][k]){
          957  +                node.removeChild(node.firstChild); //remove ,
          958  +                if (node.firstChild.nodeName=="mrow" && node.firstChild.childNodes.length==1 &&
          959  +         	  node.firstChild.firstChild.firstChild.nodeValue=="\u2223") {
          960  +         	    //is columnline marker - skip it
          961  +         	    if (i==0) { columnlines.push("solid"); }
          962  +         	    node.removeChild(node.firstChild); //remove mrow
          963  +         	    node.removeChild(node.firstChild); //remove ,
          964  +         	    j+=2;
          965  +         	    k++;
          966  +            	} else if (i==0) { columnlines.push("none"); }
          967  +                row.appendChild(createMmlNode("mtd",frag));
          968  +                k++;
          969  +              } else frag.appendChild(node.firstChild);
          970  +            }
          971  +            row.appendChild(createMmlNode("mtd",frag));
          972  +            if (i==0) { columnlines.push("none"); }
          973  +            if (newFrag.childNodes.length>2) {
          974  +              newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>
          975  +              newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>
          976  +            }
          977  +            table.appendChild(createMmlNode("mtr",row));
          978  +          }
          979  +          node = createMmlNode("mtable",table);
          980  +          node.setAttribute("columnlines", columnlines.join(" "));
          981  +          if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");
          982  +          newFrag.replaceChild(node,newFrag.firstChild);
          983  +        }
          984  +       }
          985  +      }
          986  +    }
          987  +    str = AMremoveCharsAndBlanks(str,symbol.input.length);
          988  +    if (typeof symbol.invisible != "boolean" || !symbol.invisible) {
          989  +      node = createMmlNode("mo",document.createTextNode(symbol.output));
          990  +      newFrag.appendChild(node);
          991  +    }
          992  +  }
          993  +  return [newFrag,str];
          994  +}
          995  +
          996  +function parseMath(str,latex) {
          997  +  var frag, node;
          998  +  AMnestingDepth = 0;
          999  +  //some basic cleanup for dealing with stuff editors like TinyMCE adds
         1000  +  str = str.replace(/&nbsp;/g,"");
         1001  +  str = str.replace(/&gt;/g,">");
         1002  +  str = str.replace(/&lt;/g,"<");
         1003  +  frag = AMparseExpr(str.replace(/^\s+/g,""),false)[0];
         1004  +  node = createMmlNode("mstyle",frag);
         1005  +  if (mathcolor != "") node.setAttribute("mathcolor",mathcolor);
         1006  +  if (mathfontsize != "") {
         1007  +	  node.setAttribute("fontsize", mathfontsize);
         1008  +	  node.setAttribute("mathsize", mathfontsize);
         1009  +  }
         1010  +  if (mathfontfamily != "") {
         1011  +	  node.setAttribute("fontfamily", mathfontfamily);
         1012  +	  node.setAttribute("mathvariant", mathfontfamily);
         1013  +  }
         1014  +
         1015  +  if (displaystyle) node.setAttribute("displaystyle","true");
         1016  +  node = createMmlNode("math",node);
         1017  +  if (showasciiformulaonhover)                      //fixed by djhsu so newline
         1018  +    node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko
         1019  +  return node;
         1020  +}
         1021  +
         1022  +function strarr2docFrag(arr, linebreaks, latex) {
         1023  +  var newFrag=document.createDocumentFragment();
         1024  +  var expr = false;
         1025  +  for (var i=0; i<arr.length; i++) {
         1026  +    if (expr) newFrag.appendChild(parseMath(arr[i],latex));
         1027  +    else {
         1028  +      var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);
         1029  +      newFrag.appendChild(createElementXHTML("span").
         1030  +      appendChild(document.createTextNode(arri[0])));
         1031  +      for (var j=1; j<arri.length; j++) {
         1032  +        newFrag.appendChild(createElementXHTML("p"));
         1033  +        newFrag.appendChild(createElementXHTML("span").
         1034  +        appendChild(document.createTextNode(arri[j])));
         1035  +      }
         1036  +    }
         1037  +    expr = !expr;
         1038  +  }
         1039  +  return newFrag;
         1040  +}
         1041  +
         1042  +function AMautomathrec(str) {
         1043  +//formula is a space (or start of str) followed by a maximal sequence of *two* or more tokens, possibly separated by runs of digits and/or space.
         1044  +//tokens are single letters (except a, A, I) and ASCIIMathML tokens
         1045  +  var texcommand = "\\\\[a-zA-Z]+|\\\\\\s|";
         1046  +  var ambigAMtoken = "\\b(?:oo|lim|ln|int|oint|del|grad|aleph|prod|prop|sinh|cosh|tanh|cos|sec|pi|tt|fr|sf|sube|supe|sub|sup|det|mod|gcd|lcm|min|max|vec|ddot|ul|chi|eta|nu|mu)(?![a-z])|";
         1047  +  var englishAMtoken = "\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|";
         1048  +  var secondenglishAMtoken = "|\\bI\\b|\\bin\\b|\\btext\\b"; // took if and or not out
         1049  +  var simpleAMtoken = "NN|ZZ|QQ|RR|CC|TT|AA|EE|sqrt|dx|dy|dz|dt|xx|vv|uu|nn|bb|cc|csc|cot|alpha|beta|delta|Delta|epsilon|gamma|Gamma|kappa|lambda|Lambda|omega|phi|Phi|Pi|psi|Psi|rho|sigma|Sigma|tau|theta|Theta|xi|Xi|zeta"; // uuu nnn?
         1050  +  var letter = "[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|"+ambigAMtoken+englishAMtoken+simpleAMtoken+"))|";
         1051  +  var token = letter+texcommand+"\\d+|[-()[\\]{}+=*&^_%\\\@/<>,\\|!:;'~]|\\.(?!(?:\x20|$))|"+ambigAMtoken+englishAMtoken+simpleAMtoken;
         1052  +  var re = new RegExp("(^|\\s)((("+token+")\\s?)(("+token+secondenglishAMtoken+")\\s?)+)([,.?]?(?=\\s|$))","g");
         1053  +  str = str.replace(re," `$2`$7");
         1054  +  var arr = str.split(AMdelimiter1);
         1055  +  var re1 = new RegExp("(^|\\s)([b-zB-HJ-Z+*<>]|"+texcommand+ambigAMtoken+simpleAMtoken+")(\\s|\\n|$)","g");
         1056  +  var re2 = new RegExp("(^|\\s)([a-z]|"+texcommand+ambigAMtoken+simpleAMtoken+")([,.])","g"); // removed |\d+ for now
         1057  +  for (i=0; i<arr.length; i++)   //single nonenglish tokens
         1058  +    if (i%2==0) {
         1059  +      arr[i] = arr[i].replace(re1," `$2`$3");
         1060  +      arr[i] = arr[i].replace(re2," `$2`$3");
         1061  +      arr[i] = arr[i].replace(/([{}[\]])/,"`$1`");
         1062  +    }
         1063  +  str = arr.join(AMdelimiter1);
         1064  +  str = str.replace(/((^|\s)\([a-zA-Z]{2,}.*?)\)`/g,"$1`)");  //fix parentheses
         1065  +  str = str.replace(/`(\((a\s|in\s))(.*?[a-zA-Z]{2,}\))/g,"$1`$3");  //fix parentheses
         1066  +  str = str.replace(/\sin`/g,"` in");
         1067  +  str = str.replace(/`(\(\w\)[,.]?(\s|\n|$))/g,"$1`");
         1068  +  str = str.replace(/`([0-9.]+|e.g|i.e)`(\.?)/gi,"$1$2");
         1069  +  str = str.replace(/`([0-9.]+:)`/g,"$1");
         1070  +  return str;
         1071  +}
         1072  +
         1073  +function processNodeR(n, linebreaks,latex) {
         1074  +  var mtch, str, arr, frg, i;
         1075  +  if (n.childNodes.length == 0) {
         1076  +   if ((n.nodeType!=8 || linebreaks) &&
         1077  +    n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&
         1078  +    n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" /*&&
         1079  +    n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE"*/) {
         1080  +    str = n.nodeValue;
         1081  +    if (!(str == null)) {
         1082  +      str = str.replace(/\r\n\r\n/g,"\n\n");
         1083  +      str = str.replace(/\x20+/g," ");
         1084  +      str = str.replace(/\s*\r\n/g," ");
         1085  +      if(latex) {
         1086  +// DELIMITERS:
         1087  +        mtch = (str.indexOf("\$")==-1 ? false : true);
         1088  +        str = str.replace(/([^\\])\$/g,"$1 \$");
         1089  +        str = str.replace(/^\$/," \$");	// in case \$ at start of string
         1090  +        arr = str.split(" \$");
         1091  +        for (i=0; i<arr.length; i++)
         1092  +	  arr[i]=arr[i].replace(/\\\$/g,"\$");
         1093  +      } else {
         1094  +      mtch = false;
         1095  +      str = str.replace(new RegExp(AMescape1, "g"),
         1096  +              function(){mtch = true; return "AMescape1"});
         1097  +      str = str.replace(/\\?end{?a?math}?/i,
         1098  +              function(){automathrecognize = false; mtch = true; return ""});
         1099  +      str = str.replace(/amath\b|\\begin{a?math}/i,
         1100  +              function(){automathrecognize = true; mtch = true; return ""});
         1101  +      arr = str.split(AMdelimiter1);
         1102  +      if (automathrecognize)
         1103  +        for (i=0; i<arr.length; i++)
         1104  +          if (i%2==0) arr[i] = AMautomathrec(arr[i]);
         1105  +      str = arr.join(AMdelimiter1);
         1106  +      arr = str.split(AMdelimiter1);
         1107  +      for (i=0; i<arr.length; i++) // this is a problem ************
         1108  +        arr[i]=arr[i].replace(/AMescape1/g,AMdelimiter1);
         1109  +      }
         1110  +      if (arr.length>1 || mtch) {
         1111  +        if (!noMathML) {
         1112  +          frg = strarr2docFrag(arr,n.nodeType==8,latex);
         1113  +          var len = frg.childNodes.length;
         1114  +          n.parentNode.replaceChild(frg,n);
         1115  +          return len-1;
         1116  +        } else return 0;
         1117  +      }
         1118  +    }
         1119  +   } else return 0;
         1120  +  } else if (n.nodeName!="math") {
         1121  +    for (i=0; i<n.childNodes.length; i++)
         1122  +      i += processNodeR(n.childNodes[i], linebreaks,latex);
         1123  +  }
         1124  +  return 0;
         1125  +}
         1126  +
         1127  +function AMprocessNode(n, linebreaks, spanclassAM) {
         1128  +  var frag,st;
         1129  +  if (spanclassAM!=null) {
         1130  +    frag = document.getElementsByTagName("span")
         1131  +    for (var i=0;i<frag.length;i++)
         1132  +      if (frag[i].className == "AM")
         1133  +        processNodeR(frag[i],linebreaks,false);
         1134  +  } else {
         1135  +    try {
         1136  +      st = n.innerHTML; // look for AMdelimiter on page
         1137  +    } catch(err) {}
         1138  +//alert(st)
         1139  +    if (st==null || /amath\b|\\begin{a?math}/i.test(st) ||
         1140  +      st.indexOf(AMdelimiter1+" ")!=-1 || st.slice(-1)==AMdelimiter1 ||
         1141  +      st.indexOf(AMdelimiter1+"<")!=-1 || st.indexOf(AMdelimiter1+"\n")!=-1) {
         1142  +      processNodeR(n,linebreaks,false);
         1143  +    }
         1144  +  }
         1145  +}
         1146  +
         1147  +function generic(){
         1148  +  if(!init()) return;
         1149  +  if (translateOnLoad) {
         1150  +      translate();
         1151  +  }
         1152  +};
         1153  +//setup onload function
         1154  +if(typeof window.addEventListener != 'undefined'){
         1155  +  //.. gecko, safari, konqueror and standard
         1156  +  window.addEventListener('load', generic, false);
         1157  +}
         1158  +else if(typeof document.addEventListener != 'undefined'){
         1159  +  //.. opera 7
         1160  +  document.addEventListener('load', generic, false);
         1161  +}
         1162  +else if(typeof window.attachEvent != 'undefined'){
         1163  +  //.. win/ie
         1164  +  window.attachEvent('onload', generic);
         1165  +}else{
         1166  +  //.. mac/ie5 and anything else that gets this far
         1167  +  //if there's an existing onload function
         1168  +  if(typeof window.onload == 'function'){
         1169  +    //store it
         1170  +    var existing = onload;
         1171  +    //add new onload handler
         1172  +    window.onload = function(){
         1173  +      //call existing onload function
         1174  +      existing();
         1175  +      //call generic onload function
         1176  +      generic();
         1177  +    };
         1178  +  }else{
         1179  +    window.onload = generic;
         1180  +  }
         1181  +}
         1182  +
         1183  +//expose some functions to outside
         1184  +asciimath.newcommand = newcommand;
         1185  +asciimath.newsymbol = newsymbol;
         1186  +asciimath.AMprocessNode = AMprocessNode;
         1187  +asciimath.parseMath = parseMath;
         1188  +asciimath.translate = translate;
         1189  +asciimath.init = init;
         1190  +})();

Added undroid/tsb/asciimath/README.txt.

            1  +See https://asciimath.org for usage information. Unfortunately, this
            2  +works only reliably with Webkit based browsers/webviews and Firefox.
            3  +Neither Chrome, nor IE/Edge are usable.

Added undroid/tsb/asciimath/pkgIndex.tcl.

            1  +package ifneeded tsb::asciimath 0.1 [apply {dir {
            2  +    if {![catch {open [file join $dir ASCIIMathML.js] r} f]} {
            3  +	if {[catch {read $f} script]} {
            4  +	    unset script
            5  +	}
            6  +	close $f
            7  +    }
            8  +    if {[info exists script]} {
            9  +	catch {$::W call Wjs $script}
           10  +	catch {$::W call asciimath.init}
           11  +	# Needed for MathML in IE?
           12  +	append ::tsb::D_wrscr {
           13  +	    <object id="mathplayer"
           14  +	    classid="clsid:32F66A20-7614-11D4-BD11-00104BD3F987">
           15  +	    </object>
           16  +	    <?import namespace="m" implementation="#mathplayer"?>
           17  +	}
           18  +    }
           19  +    package provide tsb::asciimath 0.1
           20  +}} $dir]

Changes to undroid/tsb/tsb.tcl.

    19     19   # we don't need it for now.
    20     20   
    21     21   if {([info command winfo] eq "winfo") &&
    22     22       [winfo exists .] && ([winfo children .] eq "")} {
    23     23       wm withdraw .
    24     24   }
    25     25   
           26  +# For tsb related packages.
           27  +
           28  +lappend auto_path [file dirname [info script]]
           29  +
    26     30   namespace eval ::tsb {
    27     31       variable inload 0
    28     32       variable ready 0
    29     33       variable dump ""
    30     34       variable file ""
    31     35   }
    32     36   
................................................................................
    36     40   
    37     41   # This is invoked from the JS window.external.invoke function.
    38     42   # The first non-blank characters are assumed to be the integer id
    39     43   # of the (input) field.
    40     44   
    41     45   proc ::tsb::call_from_js {str} {
    42     46       variable dump
    43         -    if {[string first "<" $str] == 0} {
           47  +    if {![string match {[0-9]*} $str]} {
    44     48   	set dump $str
    45     49   	return
    46     50       }
    47     51       set n [string first " " $str]
    48     52       if {$n < 0} {
    49     53   	return
    50     54       }
................................................................................
   474    478       set f [open $name w]
   475    479       puts $f $D_head
   476    480       puts $f "<title>$t</title>"
   477    481       # No hover in output
   478    482       set style $D_style
   479    483       regsub -all -- :hover $style :nohover style
   480    484       puts $f $style
   481         -    puts $f "</head><body>\n"
          485  +    puts $f "</head>\n<body>"
   482    486       puts $f [::tsb::dump]
   483         -    puts $f "</body></html>"
          487  +    puts $f "</body>\n</html>"
   484    488       close $f
   485    489       return -code 4 ;# continue
   486    490   }
   487    491   
   488    492   # A minimal canvas emulation for plotchart. The svg method
   489    493   # produces SVG into the current (output) field.
   490    494   #
................................................................................
   937    941   	</style>
   938    942       }
   939    943   
   940    944       # SCRIPT
   941    945       set D_script {
   942    946   	<script type="text/javascript">
   943    947   
          948  +	var asciimath = {};
          949  +	
   944    950   	var msLike = /MSIE|Trident|Edge/i.test(navigator.userAgent);
   945    951   
   946    952   	if (!msLike && !window.external) {
   947    953   	    /* See also webview.h */
   948    954   	    window.external = {
   949    955   		invoke: function(str) {
   950    956   		    window.webkit.messageHandlers.external.postMessage(str);
................................................................................
  1024   1030   	var Wraw = function(id, str) {
  1025   1031   	    var output = document.getElementById('out' + id + '-raw');
  1026   1032   	    if (needsClear[id]) {
  1027   1033   		output.innerHTML = str;
  1028   1034   	    } else {
  1029   1035   		output.innerHTML += str;
  1030   1036   	    }
         1037  +	    if (asciimath.AMprocessNode) {
         1038  +		asciimath.AMprocessNode(output, false, null);
         1039  +	    }
  1031   1040   	    if (needsClear[id]) {
  1032   1041   		output =
  1033   1042   		    document.getElementById('out' + id + '-pre').firstChild;
  1034   1043   		if (output.innerHTML.length > 0) {
  1035   1044   		    output.style.color = 'inherit';
  1036   1045   		    output.innerHTML = '';
  1037   1046   		}
................................................................................
  1234   1243   		    fields[i].innerHTML = "";
  1235   1244   		    if (msLike) {
  1236   1245   			fields[i].value = values[i];
  1237   1246   		    }
  1238   1247   		}
  1239   1248   	    }
  1240   1249   	};
         1250  +
         1251  +	var Wcss = function(str) {
         1252  +	    var t = document.createElement('style');
         1253  +	    var d = document.head || document.getElementsByTagName('head')[0];
         1254  +	    t.setAttribute('type', 'text/css');
         1255  +	    t.styleSheet ?
         1256  +	        t.styleSheet.cssText = str :
         1257  +	        t.appendChild(document.createTextNode(str));
         1258  +	    d.appendChild(t);
         1259  +	};
         1260  +	
         1261  +	var Wjs = function(str) {
         1262  +	    var t = document.createElement('script');
         1263  +	    var d = document.head || document.getElementsByTagName('head')[0];
         1264  +	    t.setAttribute('type', 'text/javascript');
         1265  +	    t.appendChild(document.createTextNode(str));
         1266  +	    d.appendChild(t);
         1267  +	};
  1241   1268   
  1242   1269   	/* Is this really needed? */
  1243   1270   	window.addEventListener('unload', function(event) {
  1244   1271   	    window.clearInterval(Gtimer);
  1245   1272   	    Gtimer = null;
  1246   1273   	});
  1247   1274