Annotation of loncom/html/adm/jsMath/jsMath.js, revision 1.2

1.1       albertel    1: /*****************************************************************************
                      2:  * 
                      3:  *  jsMath: Mathematics on the Web
                      4:  *  
                      5:  *  This jsMath package makes it possible to display mathematics in HTML pages
                      6:  *  that are viewable by a wide range of browsers on both the Mac and the IBM PC,
                      7:  *  including browsers that don't process MathML.  See
                      8:  *  
                      9:  *            http://www.math.union.edu/locate/jsMath
                     10:  *
                     11:  *  for the latest version, and for documentation on how to use jsMath.
                     12:  * 
                     13:  *  Copyright (c) 2004-2005 by Davide P. Cervone.
                     14:  *
                     15:  *  This program is free software; you can redistribute it and/or
                     16:  *  modify it under the terms of the GNU General Public License
                     17:  *  as published by the Free Software Foundation; either version 2
                     18:  *  of the License.
                     19:  *  
                     20:  *  This program is distributed in the hope that it will be useful,
                     21:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     22:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     23:  *  GNU General Public License for more details.
                     24:  *  
                     25:  *  You should have received a copy of the GNU General Public License
                     26:  *  along with this program; if not, write to the Free Software
                     27:  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
                     28:  *  
                     29:  *****************************************************************************/
                     30: 
                     31: /*
                     32:  *  Prevent running everything again if this file is loaded twice
                     33:  */
1.2     ! albertel   34: if (!jsMath || !jsMath.loaded) {
        !            35: var jsMath_old = jsMath;  // save user customizations
1.1       albertel   36: 
                     37: //
                     38: // debugging routine
                     39: // 
                     40: function ShowObject (obj,spaces) {
                     41:   var s = ''; if (!spaces) {spaces = ""}
                     42:   for (var i in obj) {
                     43:     if (obj[i] != null) {
                     44:       if (typeof(obj[i]) == "object") {
                     45:         s += spaces + i + ": {\n"
                     46:           + ShowObject(obj[i],spaces + '  ')
                     47:           + spaces + "}\n";
                     48:       } else if (typeof(obj[i]) != "function") {
                     49:         s += spaces + i + ': ' + obj[i] + "\n";
                     50:       }
                     51:     }
                     52:   }
                     53:   return s;
                     54: }
                     55: 
                     56: /***************************************************************************/
                     57: //
                     58: //  Check for DOM support
                     59: //
                     60: if (!document.getElementById || !document.childNodes || !document.createElement) {
                     61:   alert('The mathematics on this page requires W3C DOM support in its JavaScript. '
                     62:       + 'Unfortunately, your browser doesn\'t seem to have this.');
                     63: } else {
                     64: 
                     65: /***************************************************************************/
                     66: 
                     67: var jsMath = {
1.2     ! albertel   68:   
        !            69:   version: "2.4b",  // change this if you edit the file
        !            70:   
1.1       albertel   71:   //
                     72:   //  Name of image files
                     73:   //
                     74:   blank: "blank.gif",
                     75:   
1.2     ! albertel   76:   defaultH: 0, // default height for characters with none specified
        !            77: 
1.1       albertel   78:   // Font sizes for \tiny, \small, etc. (must match styles below)
                     79:   sizes: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249],
                     80: 
                     81:   //
                     82:   //  The styles needed for the TeX fonts
                     83:   //
                     84:   styles: {
                     85:     '.size0':          'font-size: 50%',  // tiny (\scriptscriptsize)
                     86:     '.size1':          'font-size: 60%',  //       (50% of \large for consistency)
                     87:     '.size2':          'font-size: 70%',  // scriptsize
                     88:     '.size3':          'font-size: 85%',  // small (70% of \large for consistency)
                     89:     '.size4':          'font-size: 100%', // normalsize
                     90:     '.size5':          'font-size: 120%', // large
                     91:     '.size6':          'font-size: 144%', // Large
                     92:     '.size7':          'font-size: 173%', // LARGE
                     93:     '.size8':          'font-size: 207%', // huge
                     94:     '.size9':          'font-size: 249%', // Huge
                     95:   
1.2     ! albertel   96:     '.cmr10':          'font-family: cmr10, serif',
1.1       albertel   97:     '.cmbx10':         'font-family: cmbx10, cmr10',
                     98:     '.cmti10':         'font-family: cmti10, cmr10',
                     99:     '.cmmi10':         'font-family: cmmi10',
                    100:     '.cmsy10':         'font-family: cmsy10',
                    101:     '.cmex10':         'font-family: cmex10',
1.2     ! albertel  102:     
        !           103:     '.math':           'font-family: serif; font-style: normal; font-weight: normal',
        !           104:     '.typeset':        'font-family: serif; font-style: normal; font-weight: normal',
        !           105:     '.normal':         'font-family: serif; font-style: normal; font-weight: normal; '
        !           106:                           + 'padding:0px; border:0px; margin:0px;',
        !           107:     'span.typeset':    '',
        !           108:     'div.typeset':     'text-align: center; margin: 1em 0px;',
1.1       albertel  109:     '.mathlink':       'text-decoration: none',
1.2     ! albertel  110:     '.mathHD':         'border-width:0px; width: 1px; margin-right: -1px',
1.1       albertel  111:   
                    112:     '.error':          'font-size: 10pt; font-style: italic; '
1.2     ! albertel  113:                          + 'background-color: #FFFFCC; padding: 1px; '
        !           114:                          + 'border: 1px solid #CC0000',
        !           115: 
        !           116:     '.jsM_panel':      'position:fixed; bottom:1.5em; right:1.5em; padding: 10px 20px; '
        !           117:                          + 'background-color:#DDDDDD; border: outset 2px; '
        !           118:                          + 'z-index:103; width:auto;',
        !           119:     '.jsM_button':     'position:fixed; bottom:1px; right:2px; background-color:white; '
        !           120:                          + 'border: solid 1px #959595; margin:0px; padding: 0px 3px 1px 3px; '
        !           121:                          + 'z-index:102; color:black; text-decoration:none; font-size:x-small; width:auto;',
        !           122:     '.jsM_float':      'position:absolute; top:0px; left:0px; max-width:80%; '
        !           123:                          + 'z-index:101; width:auto; height:auto;',
        !           124:     '.jsM_drag':       'background-color:#DDDDDD; border: outset 1px; height:12px; font-size: 1px;',
        !           125:     '.jsM_close':      'background-color:#E6E6E6; border: inset 1px; width:8px; height:8px; margin: 1px 2px;',
        !           126:     '.jsM_source':     'background-color:#E2E2E2; border: outset 1px; '
        !           127:                          + 'width:auto; height:auto; padding: 8px 15px; '
        !           128:                          + 'font-family: courier, fixed; font-size: 90%',
        !           129:     '.jsM_noFont':     'text-align: center; padding: 10px 20px; border: 3px solid #DD0000; '
        !           130:                          + ' background-color: #FFF8F8; color: #AA0000; font-size:small; width:auto;',
        !           131:     '.jsM_fontLink':   'padding: 0px 5px 2px 5px; text-decoration:none; color:black;'
        !           132:                          + ' border: 2px outset; background-color:#E8E8E8; font-size:80%; width:auto;'
1.1       albertel  133:   },
1.2     ! albertel  134:   
1.1       albertel  135: 
                    136:   /***************************************************************************/
                    137: 
                    138:   /*
                    139:    *  Get the width and height (in pixels) of an HTML string
                    140:    */
                    141:   BBoxFor: function (s) {
1.2     ! albertel  142:     this.hidden.innerHTML = '<NOBR><SPAN CLASS="jsM_scale">'+s+'</SPAN></NOBR>';
1.1       albertel  143:     var bbox = {w: this.hidden.offsetWidth, h: this.hidden.offsetHeight};
1.2     ! albertel  144:     this.hidden.innerHTML = '';
1.1       albertel  145:     return bbox;
                    146:   },
                    147: 
                    148:   /*
                    149:    *  Get the width and height (in ems) of an HTML string
                    150:    */
                    151:   EmBoxFor: function (s) {
                    152:     var bbox = this.BBoxFor(s);
                    153:     return {w: bbox.w/this.em, h: bbox.h/this.em};
                    154:   },
                    155: 
                    156:   /*
1.2     ! albertel  157:    *  For browsers that don't handle sizes of italics properly (MSIE)
        !           158:    */
        !           159:   EmBoxForItalics: function (s) {
        !           160:     var bbox = this.BBoxFor(s);
        !           161:     if (s.match(/<I>|CLASS="icm/i)) {
        !           162:       bbox.w = this.BBoxFor(s+jsMath.Browser.italicString).w
        !           163:                 - jsMath.Browser.italicCorrection;
        !           164:     }
        !           165:     return {w: bbox.w/this.em, h: bbox.h/this.em};
        !           166:   },
        !           167: 
        !           168:   /*
        !           169:    *  Initialize jsMath.  This determines the em size, and a variety
        !           170:    *  of other parameters used throughout jsMath.
1.1       albertel  171:    */
1.2     ! albertel  172:   Init: function () {
        !           173:     if (jsMath.Setup.inited != 1) {
        !           174:       if (jsMath.Setup.inited) {
        !           175:         alert("It looks like jsMath failed to set up properly.");
        !           176:       } else {
        !           177:         alert("You must call jsMath.Setup.Body() explicitly when jsMath is" +
        !           178:               "loaded as part of the <HEAD> section");
        !           179:       }
        !           180:       jsMath.Setup.Init(); // may fail to load fallback files properly
        !           181:     }
        !           182:     this.em = this.BBoxFor('<IMG SRC="'+jsMath.blank+'" STYLE="width:10em; height:1em">').w/10;
        !           183:     if (jsMath.Browser.italicString) 
        !           184:       jsMath.Browser.italicCorrection = jsMath.BBoxFor(jsMath.Browser.italicString).w;
        !           185:     if (jsMath.Browser.hiddenSpace != '') {
        !           186:       jsMath.Browser.spaceWidth =
        !           187:         this.EmBoxFor(jsMath.Browser.hiddenSpace +
        !           188:                       jsMath.Browser.hiddenSpace +
        !           189:                       jsMath.Browser.hiddenSpace +
        !           190:                       jsMath.Browser.hiddenSpace +
        !           191:                       jsMath.Browser.hiddenSpace).w/5;
        !           192:     }
        !           193:     var bb = this.BBoxFor('x'); var h = bb.h;
        !           194:     var d = this.BBoxFor('x<IMG SRC="'+jsMath.blank+'" HEIGHT="'+(h*jsMath.Browser.imgScale)+'" WIDTH="1">').h - h;
        !           195:     this.h = (h-d)/this.em; this.d = d/this.em;
        !           196:     this.hd = this.h + this.d;
        !           197:     this.xWidth = bb.w;  // used to tell if scale has changed
        !           198:     
        !           199:     this.Setup.TeXfonts();
        !           200:     
        !           201:     var x_height = this.EmBoxFor('<SPAN CLASS="cmr10">M</SPAN>').w/2;
        !           202:     this.TeX.M_height = x_height*(26/14);
        !           203:     this.TeX.h = this.h; this.TeX.d = this.d; this.TeX.hd = this.hd;
        !           204:     
        !           205:     this.Img.Scale();
        !           206:     if (!this.initialized) {
        !           207:       this.Setup.Sizes();
        !           208:       this.Img.UpdateFonts();
        !           209:     }
        !           210: 
        !           211:     // factor for \big and its brethren
        !           212:     this.p_height = (this.TeX.cmex10[0].h + this.TeX.cmex10[0].d) / .85;
        !           213: 
        !           214:     this.initialized = 1;
1.1       albertel  215:   },
                    216:   
                    217:   /*
1.2     ! albertel  218:    *  Get the xWidth size and if it has changed, reinitialize the sizes
1.1       albertel  219:    */
1.2     ! albertel  220:   ReInit: function () {
        !           221:     var w = this.BBoxFor('x').w;
        !           222:     if (w != this.xWidth) {this.Init()}
1.1       albertel  223:   },
1.2     ! albertel  224:   
1.1       albertel  225:   /*
1.2     ! albertel  226:    *  Mark jsMath as loaded and copy any user-provided overrides
1.1       albertel  227:    */
1.2     ! albertel  228:   Loaded: function () {
        !           229:     this.Insert(jsMath,jsMath_old);
        !           230:     jsMath_old = null;
        !           231:     jsMath.loaded = 1;
        !           232:   },
        !           233:   
        !           234:   /*
        !           235:    *  Manage JavaScript objects:
        !           236:    *  
        !           237:    *      Add:        add/replace items in an object
        !           238:    *      Insert:     add items to an object
        !           239:    *      Package:    add items to an object prototype
        !           240:    */
        !           241:   Add: function (dst,src) {for (var id in src) {dst[id] = src[id]}},
        !           242:   Insert: function (dst,src) {
        !           243:     for (var id in src) {
        !           244:       if (dst[id] && typeof(src[id]) == 'object'
        !           245:                   && (typeof(dst[id]) == 'object'
        !           246:                   ||  typeof(dst[id]) == 'function')) {
        !           247:         this.Insert(dst[id],src[id]);
        !           248:       } else {
        !           249:         dst[id] = src[id];
        !           250:       }
        !           251:     }
1.1       albertel  252:   },
1.2     ! albertel  253:   Package: function (obj,def) {this.Insert(obj.prototype,def)}
        !           254: 
        !           255: }
        !           256: 
        !           257: /***************************************************************************/
1.1       albertel  258: 
1.2     ! albertel  259: /*
        !           260:  *  Miscellaneous setup and initialization
        !           261:  */
        !           262: jsMath.Setup = {
1.1       albertel  263:   
                    264:   /*
1.2     ! albertel  265:    *  Insert a DIV at the top of the page with given ID,
        !           266:    *  attributes, and style settings
1.1       albertel  267:    */
1.2     ! albertel  268:   TopHTML: function (id,attributes,styles) {
        !           269:     try {
        !           270:       var div = document.createElement('div');
        !           271:       div.setAttribute("id",'jsMath.'+id);
        !           272:       for (var i in attributes) {
        !           273:         div.setAttribute(i,attributes[i]);
        !           274:         if (i == "class") {div.setAttribute('className',attributes[i])} // MSIE
        !           275:       }
        !           276:       for (var i in styles) {div.style[i]= styles[i]}
        !           277:       if (!document.body.hasChildNodes) {document.body.appendChild(div)}
        !           278:         else {document.body.insertBefore(div,document.body.firstChild)}
        !           279:     } catch (err) {
        !           280:       var html = '<DIV ID="jsMath.'+id+'"';
        !           281:       for (var id in attributes) {html += ' '+id+'="'+attributes[id]+'"'}
        !           282:       if (styles) {
        !           283:         html += ' STYLE="';
        !           284:         for (var id in styles) {html += ' '+id+':'+styles[id]+';'}
        !           285:         html += '"';
        !           286:       }
        !           287:       html += '</DIV>';
        !           288:       if (!document.body.insertAdjacentHTML) {document.write(html)}
        !           289:         else {document.body.insertAdjacentHTML('AfterBegin',html)}
        !           290:       div = jsMath.Element(id);
1.1       albertel  291:     }
1.2     ! albertel  292:     return div;
1.1       albertel  293:   },
1.2     ! albertel  294:   
1.1       albertel  295:   /*
1.2     ! albertel  296:    *  Source a jsMath JavaScript file
1.1       albertel  297:    */
1.2     ! albertel  298:   Script: function (file) {
        !           299:     if (!file.match('^([a-zA-Z]+:/)?/')) {file = jsMath.root + file}
        !           300:     document.write('<SCRIPT SRC="'+file+'"></SCRIPT>');
1.1       albertel  301:   },
                    302:   
                    303:   /*
1.2     ! albertel  304:    *  Use a hidden <DIV> for measuring the BBoxes of things
1.1       albertel  305:    */
1.2     ! albertel  306:   HTML: function () {
        !           307:     jsMath.hidden = this.TopHTML("Hidden",{'class':"normal"},{
        !           308:       position:"absolute", top:0, left:0, border:0, padding:0, margin:0
        !           309:     });
        !           310:     jsMath.hiddenTop = jsMath.hidden;
        !           311:     return;
1.1       albertel  312:   },
                    313: 
                    314:   /*
                    315:    *  Find the root URL for the jsMath files (so we can load
1.2     ! albertel  316:    *  the other .js and .gif files)
1.1       albertel  317:    */
1.2     ! albertel  318:   Source: function () {
1.1       albertel  319:     var script = document.getElementsByTagName('SCRIPT');
1.2     ! albertel  320:     if (script) {
        !           321:       for (var i = 0; i < script.length; i++) {
        !           322:         var src = script[i].src;
        !           323:         if (src && src.match('(^|/)jsMath.js$')) {
        !           324:           jsMath.root = src.replace(/jsMath.js$/,'');
        !           325:           jsMath.Img.root = jsMath.root + "fonts/";
        !           326:           jsMath.blank = jsMath.root + jsMath.blank;
        !           327:           this.Domain();
        !           328:           return;
        !           329:         }
        !           330:       }
        !           331:     }
        !           332:     jsMath.root = ''; jsMath.Img.root = "fonts/";
        !           333:   },
        !           334:   
        !           335:   /*
        !           336:    *  Find the most restricted common domain for the main
        !           337:    *  page and jsMath.  Report an error if jsMath is outside
        !           338:    *  the domain of the calling page.
        !           339:    */
        !           340:   Domain: function () {
        !           341:     var jsDomain = ''; var pageDomain = document.domain;
        !           342:     if (jsMath.root.match('://([^/]*)/')) {jsDomain = RegExp.$1}
        !           343:     jsDomain = jsDomain.replace(/:\d+$/,'');
        !           344:     if (jsDomain == "" || jsDomain == pageDomain) return;
        !           345:     //
        !           346:     // MSIE on the Mac can't change document.domain and 'try' won't
        !           347:     //   catch the error (Grrr!), so exit for them
        !           348:     //
        !           349:     if (navigator.appName == 'Microsoft Internet Explorer' &&
        !           350:         navigator.platform == 'MacPPC' && navigator.onLine &&
        !           351:         navigator.userProfile && document.all) return;
        !           352:     jsDomain = jsDomain.split(/\./); pageDomain = pageDomain.split(/\./);
        !           353:     if (jsDomain.length < 2 || pageDomain.length < 2 ||
        !           354:         jsDomain[jsDomain.length-1] != pageDomain[pageDomain.length-1] ||
        !           355:         jsDomain[jsDomain.length-2] != pageDomain[pageDomain.length-2]) {
        !           356:       this.DomainWarning();
        !           357:       return;
1.1       albertel  358:     }
1.2     ! albertel  359:     var domain = jsDomain[jsDomain.length-2] + '.' + jsDomain[jsDomain.length-1];
        !           360:     for (var i = 3; i <= jsDomain.length && i <= pageDomain.length; i++) {
        !           361:       if (jsDomain[jsDomain.length-i] != pageDomain[pageDomain.length-i]) break;
        !           362:       domain = jsDomain[jsDomain.length-i] + '.' + domain;
        !           363:     }
        !           364:     document.domain = domain;
        !           365:   },
        !           366: 
        !           367:   DomainWarning: function () {
        !           368:     alert("In order for jsMath to be able to load the additional "
        !           369:         + "components that it may need, the jsMath.js file must be "
        !           370:         + "loaded from a server in the same domain as the page that "
        !           371:         + "contains it.  Because that is not the case for this page, "
        !           372:         + "the mathematics displayed here may not appear correctly.");
1.1       albertel  373:   },
                    374:   
                    375:   /*
                    376:    *  Look up the default height and depth for a TeX font
                    377:    *  and set the skewchar
                    378:    */
1.2     ! albertel  379:   TeXfont: function (name) {
        !           380:     var font = jsMath.TeX[name];
        !           381:     var WH = jsMath.EmBoxFor('<SPAN CLASS="'+name+'">'+font[65].c+'</SPAN>');
1.1       albertel  382:     font.hd = WH.h;
1.2     ! albertel  383:     font.d = jsMath.EmBoxFor('<SPAN CLASS="'+name+'">'+ font[65].c +
        !           384:       '<IMG SRC="'+jsMath.blank+'" STYLE="height:'+(font.hd*jsMath.Browser.imgScale)+'em; width:1px;"></SPAN>').h
1.1       albertel  385:       - font.hd;
                    386:     font.h = font.hd - font.d;
1.2     ! albertel  387:     font.dh = .05; if (jsMath.browser == 'Safari') {font.hd *= 2};
1.1       albertel  388:     if (name == 'cmmi10') {font.skewchar = 0177} 
                    389:     else if (name == 'cmsy10') {font.skewchar = 060}
                    390:   },
                    391: 
                    392:   /*
                    393:    *  Init all the TeX fonts
                    394:    */
1.2     ! albertel  395:   TeXfonts: function () {
        !           396:     for (var i = 0; i < jsMath.TeX.fam.length; i++) 
        !           397:       {if (jsMath.TeX.fam[i]) {this.TeXfont(jsMath.TeX.fam[i])}}
1.1       albertel  398:   },
                    399: 
                    400:   /*
                    401:    *  Compute font parameters for various sizes
                    402:    */
1.2     ! albertel  403:   Sizes: function () {
        !           404:     jsMath.TeXparams = [];
        !           405:     for (var j=0; j < jsMath.sizes.length; j++) {jsMath.TeXparams[j] = {}}
        !           406:     for (var i in jsMath.TeX) {
        !           407:       if (typeof(jsMath.TeX[i]) != 'object') {
        !           408:         for (var j=0; j < jsMath.sizes.length; j++) {
        !           409:           jsMath.TeXparams[j][i] = jsMath.sizes[j]*jsMath.TeX[i]/100;
1.1       albertel  410:         }
                    411:       }
                    412:     }
                    413:   },
                    414: 
1.2     ! albertel  415:   
1.1       albertel  416:   /*
1.2     ! albertel  417:    *  Send the style definitions to the browser (these may be adjusted
        !           418:    *  by the browser-specific code)
        !           419:    */
        !           420:   Styles: function (styles) {
        !           421:     if (!styles) {
        !           422:       styles = jsMath.styles;
        !           423:       styles['.jsM_scale'] = 'font-size:'+jsMath.Controls.cookie.scale+'%';
        !           424:     }
        !           425:     document.writeln('<STYLE TYPE="text/css" ID="jsMath.styles">');
        !           426:     for (var id in styles) {document.writeln('  '+id+'  {'+styles[id]+'}')}
        !           427:     document.writeln('</STYLE>');
        !           428:   },
        !           429:   
        !           430:   /*
        !           431:    *  Do the initialization that requires the BODY to be in place.
        !           432:    *  (called automatically if the jsMath.js file is loaded in the
        !           433:    *  BODY, but must be called explicitly if it is in the HEAD).
        !           434:    */
        !           435:   Body: function () {
        !           436:     if (this.inited) return;
        !           437: 
        !           438:     this.inited = -1;
        !           439: 
        !           440:     jsMath.Setup.HTML();
        !           441:     jsMath.Setup.Source();
        !           442:     jsMath.Browser.Init();
        !           443:     jsMath.Controls.Init();
        !           444:     jsMath.Click.Init();
        !           445:     jsMath.Setup.Styles();
        !           446:     
        !           447:     jsMath.Setup.User();  //  do user-specific initialization
        !           448: 
        !           449:     //make sure browser-specific loads are done before this
        !           450:     document.write('<SCRIPT>jsMath.Font.Check()</SCRIPT>');
        !           451:     
        !           452:     this.inited = 1;
        !           453:   },
        !           454:   
        !           455:   /*
        !           456:    *  Web page author can override this to do initialization
        !           457:    *  that must be done before the font check is performed
        !           458:    */
        !           459:   User: function () {}
        !           460:   
        !           461: };
        !           462: 
        !           463: jsMath.Update = {
        !           464: 
        !           465:   /*
        !           466:    *  Update specific parameters for a limited number of font entries
        !           467:    */
        !           468:   TeXfonts: function (change) {
        !           469:     for (var font in change) {
        !           470:       for (var code in change[font]) {
        !           471:         for (var id in change[font][code]) {
        !           472:           jsMath.TeX[font][code][id] = change[font][code][id];
        !           473:         }
        !           474:       }
        !           475:     }
        !           476:   },
        !           477:   
        !           478:   /*
        !           479:    *  Update the character code for every character in a list
        !           480:    *  of fonts
        !           481:    */
        !           482:   TeXfontCodes: function (change) {
        !           483:     for (var font in change) {
        !           484:       for (var i = 0; i < change[font].length; i++) {
        !           485:         jsMath.TeX[font][i].c = change[font][i];
        !           486:       }
        !           487:     }
        !           488:   },
        !           489: 
        !           490:   /*
        !           491:    *  Add a collection of styles to the style list
        !           492:    */
        !           493:   Styles: function (styles) {
        !           494:     for (var i in styles) {jsMath.styles[i] = styles[i]}
        !           495:   }
        !           496:   
        !           497: };
        !           498: 
        !           499: /***************************************************************************/
        !           500: 
        !           501: /*
        !           502:  *  Implement browser-specific checks
        !           503:  */
        !           504: 
        !           505: jsMath.Browser = {
        !           506: 
        !           507:   allowAbsolute: 1,           // tells if browser can nest absolutely positioned
        !           508:                               //   SPANs inside relative SPANs
        !           509:   allowAbsoluteDelim: 0,      // OK to use absolute placement for building delims?
        !           510:   separateSkips: 0,           // MSIE doesn't do negative left margins, and
        !           511:                               //   Netscape doesn't combine skips well
        !           512: 
        !           513:   msieSpaceFix: '',           // for MSIE spacing bug fix
        !           514:   msieCenterBugFix: '',       // for MSIE centering bug with image fonts
        !           515:   msieInlineBlockFix: '',     // for MSIE alignment bug in non-quirks mode
        !           516:   imgScale: 1,                // MSI scales images for 120dpi screens, so compensate
        !           517: 
        !           518:   renameOK: 1,                // tells if brower will find a tag whose name
        !           519:                               //   has been set via setAttributes
        !           520: 
        !           521:   delay: 1,                   // delay for asynchronous math processing
        !           522:   
        !           523:   spaceWidth: 0,              // Konqueror space fix
        !           524:   hiddenSpace: "",            // ditto
        !           525:   valignBug: 0,               // Konqueror doesn't nest vertical-align
        !           526: 
        !           527:   operaHiddenFix: '',         // for Opera to fix bug with math in tables
        !           528: 
        !           529:   /*
        !           530:    *  Determine if the "top" of a <SPAN> is always at the same height
        !           531:    *  or varies with the height of the rest of the line (MSIE).
        !           532:    */
        !           533:   TestSpanHeight: function () {
        !           534:     jsMath.hidden.innerHTML = '<SPAN><IMG SRC="'+jsMath.blank+'" STYLE="height: 2em"></SPAN>';
        !           535:     var span = jsMath.hidden.getElementsByTagName('SPAN')[0];
        !           536:     var img  = jsMath.hidden.getElementsByTagName('IMG')[0];
        !           537:     this.spanHeightVaries = (span.offsetHeight == img.offsetHeight);
        !           538:     jsMath.hidden.innerHTML = '';
        !           539:   },
        !           540:   
        !           541:   /*
        !           542:    *  Determine if the NAME attribute of a tag can be changed
        !           543:    *  using the setAttribute function, and then be properly
        !           544:    *  returned by getElementByName.
        !           545:    */
        !           546:   TestRenameOK: function () {
        !           547:     jsMath.hidden.innerHTML = '<SPAN ID="jsMath.test"></SPAN>';
        !           548:     var test = document.getElementById('jsMath.test');
        !           549:     test.setAttribute('NAME','jsMath_test');
        !           550:     this.renameOK = (document.getElementsByName('jsMath_test').length > 0);
        !           551:     jsMath.hidden.innerHTML = '';
        !           552:   },
        !           553: 
        !           554:   /*
        !           555:    *  Test for browser characteristics, and adjust things
1.1       albertel  556:    *  to overcome specific browser bugs
                    557:    */
1.2     ! albertel  558:   Init: function () {
1.1       albertel  559:     jsMath.browser = 'unknown';
                    560:     this.TestSpanHeight();
                    561:     this.TestRenameOK();
                    562: 
1.2     ! albertel  563:     this.MSIE();
        !           564:     this.Mozilla();
        !           565:     this.Opera();
        !           566:     this.OmniWeb();
        !           567:     this.Safari();
        !           568:     this.Konqueror();
        !           569:     
1.1       albertel  570:     //
1.2     ! albertel  571:     // Change some routines depending on the browser
        !           572:     // 
        !           573:     if (this.allowAbsoluteDelim) {
        !           574:       jsMath.Box.DelimExtend = jsMath.Box.DelimExtendAbsolute;
        !           575:       jsMath.Box.Layout = jsMath.Box.LayoutAbsolute;
        !           576:     } else {
        !           577:       jsMath.Box.DelimExtend = jsMath.Box.DelimExtendRelative;
        !           578:       jsMath.Box.Layout = jsMath.Box.LayoutRelative;
        !           579:     }
        !           580:     
        !           581:     if (this.separateSkips) {
        !           582:       jsMath.HTML.Place = jsMath.HTML.PlaceSeparateSkips;
        !           583:       jsMath.Typeset.prototype.Place = jsMath.Typeset.prototype.PlaceSeparateSkips;
        !           584:     }
        !           585:   },
        !           586:   
        !           587:   //
        !           588:   //  Handle bug-filled Internet Explorer
        !           589:   //
        !           590:   MSIE: function () {
1.1       albertel  591:     if (this.spanHeightVaries) {
                    592:       jsMath.browser = 'MSIE';
                    593:       if (navigator.platform == 'Win32') {
1.2     ! albertel  594:         jsMath.Update.TeXfonts({
1.1       albertel  595:           cmr10:  {'10': {c: '&Omega;', tclass: 'normal'}},
                    596:           cmmi10: {
1.2     ! albertel  597:              '10':  {c: '<I>&Omega;</I>', tclass: 'normal'},
        !           598:              '126': {c: '&#x7E;<SPAN STYLE="margin-left:.1em"></SPAN>'}
        !           599:           },
        !           600:           cmsy10: {
        !           601:             '10': {c: '&#x2297;', tclass: 'arial'},
        !           602:             '55': {c: '<SPAN STYLE="margin-right:-.54em">7</SPAN>'}
        !           603:           },
1.1       albertel  604:           cmex10: {'10': {c: '<SPAN STYLE="font-size: 67%">D</SPAN>'}},
                    605:           cmti10: {'10': {c: '<I>&Omega;</I>', tclass: 'normal'}},
                    606:           cmbx10: {'10': {c: '<B>&Omega;</B>', tclass: 'normal'}}
                    607:         });
                    608:         this.allowAbsoluteDelim = 1;
1.2     ! albertel  609:         this.separateSkips = 1;
        !           610:         this.buttonCheck = 1;
        !           611:         this.msieDivWidthBug = 1;
1.1       albertel  612:         this.msieFontBug = 1; this.msieIntegralBug = 1;
1.2     ! albertel  613:         this.msieAlphaBug = 1; this.alphaPrintBug = 1;
        !           614:         this.msieCenterBugFix = 'position:relative; ';
1.1       albertel  615:         this.msieSpaceFix = '<IMG SRC="'+jsMath.blank+'" CLASS="mathHD">';
1.2     ! albertel  616:         this.msieInlineBlockFix = ' display: inline-block;';
1.1       albertel  617:         jsMath.Macro('joinrel','\\mathrel{\\kern-5mu}'),
1.2     ! albertel  618:         jsMath.styles['.arial'] = "font-family: 'Arial unicode MS'";
        !           619:         // MSIE doesn't implement fixed positioning, so use absolute
        !           620:         jsMath.styles['.jsM_panel'] =
        !           621:               jsMath.styles['.jsM_panel'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
        !           622:         jsMath.styles['.jsM_button'] = 'width:1px; '
        !           623:             + jsMath.styles['.jsM_button'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
        !           624:         window.onscroll = jsMath.Controls.MoveButton;
        !           625:         // MSIE will rescale images if the DPIs differ
        !           626:         if (screen.deviceXDPI && screen.logicalXDPI 
        !           627:              && screen.deviceXDPI != screen.logicalXDPI) {
        !           628:           this.imgScale *= screen.logicalXDPI/screen.deviceXDPI;
        !           629:           jsMath.Controls.cookie.alpha = 0;
        !           630:         }
        !           631:         // Handle bug with getting width of italic text
        !           632:         this.italicString = '<I>x</I>';
        !           633:         jsMath.EmBoxFor = jsMath.EmBoxForItalics;
1.1       albertel  634:       } else if (navigator.platform == 'MacPPC') {
1.2     ! albertel  635:         this.msieAbsoluteBug = 1; this.msieButtonBug = 1;
        !           636:         this.msieDivWidthBug = 1;
        !           637:         jsMath.Setup.Script('jsMath-msie-mac.js');
1.1       albertel  638:         jsMath.Parser.prototype.macros.angle = ['Replace','ord','<FONT FACE="Symbol">&#x8B;</FONT>','normal'];
1.2     ! albertel  639:         jsMath.styles['.jsM_panel'] = 'width:25em; ' + jsMath.styles['.jsM_panel'].replace(/width:auto/,"");
        !           640:         jsMath.styles['.jsM_button'] = 'width:1px; ' + jsMath.styles['.jsM_button'].replace(/width:auto/,"");
1.1       albertel  641:       }
                    642:       jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');
                    643:     }
1.2     ! albertel  644:   },
1.1       albertel  645: 
1.2     ! albertel  646:   //
        !           647:   //  Handle Netscape/Mozilla (any flavor)
        !           648:   //
        !           649:   Mozilla: function () {
        !           650:     if (jsMath.hidden.ATTRIBUTE_NODE) {
1.1       albertel  651:       jsMath.browser = 'Mozilla';
                    652:       if (navigator.platform == 'MacPPC') {
1.2     ! albertel  653:         jsMath.Update.TeXfonts({
1.1       albertel  654:           cmr10:  {'10': {c: '&Omega;', tclass: 'normal'}},
                    655:           cmmi10: {'10': {c: '<I>&Omega;</I>', tclass: 'normal'}},
                    656:           cmsy10: {'10': {c: '&otimes;', tclass: 'normal'}},
                    657:           cmex10: {'10': {c: '<SPAN STYLE="font-size: 67%">D</SPAN>'}},
                    658:           cmti10: {'10': {c: '<I>&Omega;</I>', tclass: 'normal'}},
                    659:           cmbx10: {'10': {c: '<B>&Omega;</B>', tclass: 'normal'}}
                    660:         });
                    661:       } else {
1.2     ! albertel  662:         jsMath.Setup.Script('jsMath-mozilla.js');
        !           663:         this.alphaPrintBug = 1;
1.1       albertel  664:       }
1.2     ! albertel  665:       for (var i = 0; i < jsMath.TeX.fam.length; i++) {
        !           666:         if (jsMath.TeX.fam[i]) 
        !           667:           {jsMath.styles['.'+jsMath.TeX.fam[i]] += '; position: relative'}
1.1       albertel  668:       }
                    669:       this.allowAbsoluteDelim = 1;
                    670:       this.separateSkips = 1;
                    671:       jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');
                    672:     }
1.2     ! albertel  673:   },
        !           674:   
        !           675:   //
        !           676:   //  Handle OmniWeb
        !           677:   //
        !           678:   OmniWeb: function () {
1.1       albertel  679:     if (navigator.accentColorName) {
                    680:       jsMath.browser = 'OmniWeb';
1.2     ! albertel  681:       this.allowAbsolute = !navigator.userAgent.match("OmniWeb/v4");
        !           682:       this.allowAbsoluteDelim = this.allowAbsolute;
        !           683:       this.buttonCheck = 1;
1.1       albertel  684:     }
1.2     ! albertel  685:   },
1.1       albertel  686:     
1.2     ! albertel  687:   //
        !           688:   //  Handle Opera
        !           689:   //
        !           690:   Opera: function () {
        !           691:     if (navigator.appName == 'Opera' || navigator.userAgent.match(" Opera ")) {
1.1       albertel  692:       jsMath.browser = 'Opera';
1.2     ! albertel  693:       jsMath.Update.TeXfonts({
1.1       albertel  694:         cmr10:  {
                    695:           '10': {c: '&Omega;', tclass: 'normal'},
                    696:           '20': {c: '&#x2C7;', tclass: 'normal'}
                    697:         },
                    698:         cmmi10: {
                    699:           '10': {c: '<I>&Omega;</I>', tclass: 'normal'},
                    700:           '20': {c: '&kappa;', tclass: 'normal'}
                    701:         },
                    702:         cmsy10: {
                    703:           '10': {c: '&otimes;', tclass: 'normal'},
                    704:           '20': {c: '&#x2264;', tclass: 'normal'}
                    705:         },
                    706:         cmex10: {
                    707:           '10': {c: '<SPAN STYLE="font-size: 67%">D</SPAN>'},
                    708:           '20': {c: '<SPAN STYLE="font-size: 82%">"</SPAN>'}
                    709:         },
                    710:         cmti10: {
                    711:           '10': {c: '<I>&Omega;</I>', tclass: 'normal'},
                    712:           '20': {c: '<I>&#x2C7;</I>', tclass: 'normal'}
                    713:         },
                    714:         cmbx10: {
                    715:           '10': {c: '<B>&Omega;</B>', tclass: 'normal'},
                    716:           '20': {c: '<B>&#x2C7;</B>', tclass: 'normal'}
                    717:         }
                    718:       });
                    719:       this.allowAbsolute = 0;
1.2     ! albertel  720:       this.delay = 10;
        !           721:       this.operaHiddenFix = '[Processing Math]';
1.1       albertel  722:     }
1.2     ! albertel  723:   },
1.1       albertel  724: 
1.2     ! albertel  725:   //
        !           726:   //  Handle Safari
        !           727:   //
        !           728:   Safari: function () {
        !           729:     if (navigator.appVersion.match(/Safari\//)) {
1.1       albertel  730:       jsMath.browser = 'Safari';
1.2     ! albertel  731:       var version = navigator.userAgent.match("Safari/([0-9]+)");
        !           732:       version = (version)? version[1] : 200;  // FIXME: hack until I get Tiger
        !           733:       for (var i = 0; i < jsMath.TeX.fam.length; i++)
        !           734:         {if (jsMath.TeX.fam[i]) {jsMath.TeX[jsMath.TeX.fam[i]].dh = .1}}
        !           735:       jsMath.TeX.axis_height += .05;
        !           736:       this.allowAbsoluteDelim = version >= 125;
        !           737:       this.safariIFRAMEbug = version >= 312;  // FIXME: find out if they fixed it
        !           738:       this.safariImgBug = 1;
        !           739:       this.buttonCheck = 1;
        !           740:     }
        !           741:   },
        !           742:   
        !           743:   //
        !           744:   //  Handle Konqueror
        !           745:   //
        !           746:   Konqueror: function () {
        !           747:     if (navigator.product && navigator.product.match("Konqueror")) {
        !           748:       jsMath.browser = 'Konqueror';
        !           749:       jsMath.Update.TeXfonts({
        !           750:         cmr10:  {'20': {c: '&#x2C7;', tclass: 'normal'}},
        !           751:         cmmi10: {'20': {c: '&kappa;', tclass: 'normal'}},
        !           752:         cmsy10: {'20': {c: '&#x2264;', tclass: 'normal'}},
        !           753:         cmex10: {'20': {c: '<SPAN STYLE="font-size: 84%">"</SPAN>'}},
        !           754:         cmti10: {'20': {c: '<I>&#x2C7;</I>', tclass: 'normal'}},
        !           755:         cmbx10: {'20': {c: '<B>&#x2C7;</B>', tclass: 'normal'}}
        !           756:       });
        !           757:       this.allowAbsolute = 0;
        !           758:       this.allowAbsoluteDelim = 0;
        !           759:       if (navigator.userAgent.match(/Konqueror\/(\d+)\.(\d+)/)) {
        !           760:         if (RegExp.$1 < 3 || (RegExp.$1 == 3 && RegExp.$2 < 3)) {
        !           761:           this.separateSkips = 1;
        !           762:           this.valignBug = 1;
        !           763:           this.hiddenSpace = '&nbsp;';
        !           764:           jsMath.Box.prototype.Remeasured = function () {return this};
        !           765:         }
        !           766:       }
        !           767:     }
        !           768:   }
        !           769: 
        !           770: };
        !           771: 
        !           772: /***************************************************************************/
        !           773: 
        !           774: /*
        !           775:  *  Implement font check and messages
        !           776:  */
        !           777: jsMath.Font = {
        !           778:   
        !           779:   fallback: "symbol", // the default fallback method
        !           780: 
        !           781:   // the HTML for the missing font message
        !           782:   message:    
        !           783:     '<B>No TeX fonts found</B> -- using image fonts instead.<BR>\n'
        !           784:       + 'These may be slow and might not print well.<BR>\n'
        !           785:       + 'Use the jsMath control panel to get additional information.',
        !           786:       
        !           787:   extra_message:
        !           788:     'Extra TeX fonts not found: <B><SPAN ID="jsMath.ExtraFonts"></SPAN></B><BR>'
        !           789:       + 'Using image fonts instead.  This may be slow and might not print well.<BR>\n'
        !           790:       + 'Use the jsMath control panel to get additional information.',
        !           791:   
        !           792:   /*
        !           793:    *  Look to see if a font is found.  HACK!
        !           794:    *  Check the character in a given position, and see if it is
        !           795:    *  wider than the usual one in that position.
        !           796:    */
        !           797:   Test1: function (name,n,factor) {
        !           798:     if (n == null) {n = 124}; if (factor == null) {factor = 2}
        !           799:     var wh1 = jsMath.BBoxFor('<SPAN STYLE="font-family: '+name+', serif">'+jsMath.TeX[name][n].c+'</SPAN>');
        !           800:     var wh2 = jsMath.BBoxFor('<SPAN STYLE="font-family: serif">'+jsMath.TeX[name][n].c+'</SPAN>');
        !           801:     //alert([wh1.w,wh2.w,wh1.h,factor*wh2.w]);
        !           802:     return (wh1.w > factor*wh2.w && wh1.h != 0);
        !           803:   },
        !           804: 
        !           805:   Test2: function (name,n,factor) {
        !           806:     if (n == null) {n = 124}; if (factor == null) {factor = 2}
        !           807:     var wh1 = jsMath.BBoxFor('<SPAN STYLE="font-family: '+name+', serif">'+jsMath.TeX[name][n].c+'</SPAN>');
        !           808:     var wh2 = jsMath.BBoxFor('<SPAN STYLE="font-family: serif">'+jsMath.TeX[name][n].c+'</SPAN>');
        !           809:     //alert([wh2.w,wh1.w,wh1.h,factor*wh1.w]);
        !           810:     return (wh2.w > factor*wh1.w && wh1.h != 0);
        !           811:   },
        !           812:   
        !           813:   /*
        !           814:    *  Check for the availability of TeX fonts.  We do this by looking at
        !           815:    *  the width and height of a character in the cmex10 font.  The cmex10
        !           816:    *  font has depth considerably greater than most characters' widths (the
        !           817:    *  whole font has the depth of the character with greatest depth).  This
        !           818:    *  is not the case for most fonts, so if we can access cmex10, the
        !           819:    *  height of a character should be much bigger than the width.
        !           820:    *  Otherwise, if we don't have cmex10, we'll get a character in another
        !           821:    *  font with normal height and width.  In this case, we insert a message
        !           822:    *  pointing the user to the jsMath site, and load one of the fallback
        !           823:    *  definitions.
        !           824:    *  
        !           825:    */
        !           826:   Check: function () {
        !           827:     var cookie = jsMath.Controls.cookie;
        !           828:     var wh = jsMath.BBoxFor('<SPAN STYLE="font-family: cmex10">'+jsMath.TeX.cmex10[1].c+'</SPAN>');
        !           829:     jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10'));
        !           830:     if (jsMath.nofonts) {
        !           831:       if (cookie.autofont || cookie.font == 'tex') {
        !           832:         cookie.font = this.fallback;
        !           833:         if (cookie.warn) {
        !           834:           jsMath.nofontMessage = 1;
        !           835:           cookie.warn = 0; jsMath.Controls.SetCookie(0);
        !           836:           if (window.NoFontMessage) {window.NoFontMessage()}
        !           837:                                else {this.Message(this.message)}
        !           838:         }
        !           839:       }
        !           840:     } else {
        !           841:       if (cookie.autofont) {cookie.font = 'tex'}
        !           842:       if (cookie.font == 'tex') return;
1.1       albertel  843:     }
1.2     ! albertel  844:     if (jsMath.noImgFonts) {cookie.font = 'unicode'}
        !           845:     if (cookie.font == 'unicode') {
        !           846:       var platform = ({Win32: 'pc', MacPPC: 'mac'})[navigator.platform] || 'unix';
        !           847:       jsMath.Setup.Script('jsMath-fallback-'+platform+'.js');
        !           848:       return;
        !           849:     }
        !           850:     if (cookie.font == 'symbol') {
        !           851:       jsMath.Setup.Script('jsMath-fallback-symbols.js');
        !           852:       return;
        !           853:     }
        !           854:     jsMath.Img.SetFont({
        !           855:       cmr10:  ['all'], cmmi10: ['all'], cmsy10: ['all'],
        !           856:       cmex10: ['all'], cmbx10: ['all'], cmti10: ['all']
        !           857:     });
        !           858:     jsMath.Img.LoadFont('cm-fonts');
        !           859:   },
1.1       albertel  860: 
1.2     ! albertel  861:   /*
        !           862:    *  The message for when no TeX fonts.  You can eliminate this message
        !           863:    *  by including
        !           864:    *  
        !           865:    *      <SCRIPT>jsMath = {Font: {Message: function () {}}}</SCRIPT>
        !           866:    *
        !           867:    *  in your HTML file, before loading jsMath.js, if you want.  But this
        !           868:    *  means the user may not know that he or she can get a better version
        !           869:    *  of your page.
        !           870:    */
        !           871:   Message: function (message) {
        !           872:     if(jsMath.Element("Warning")) return;
        !           873:     var div = jsMath.Setup.TopHTML("Warning",{'class':'jsM_Warning'},{});
        !           874:     div.innerHTML = 
        !           875:       '<CENTER><TABLE><TR><TD>'
        !           876:       + '<DIV CLASS="jsM_noFont">' + message
        !           877:       + '<DIV STYLE="text-align:left"><SPAN STYLE="float:left; margin: 8px 0px 0px 20px">'
        !           878:       + '<A HREF="javascript:jsMath.Controls.Panel()" CLASS="jsM_fontLink">jsMath Control Panel</A>'
        !           879:       + '</SPAN><SPAN STYLE="margin: 8px 20px 0px 0px; float:right">'
        !           880:       + '<A HREF="javascript:jsMath.Font.HideMessage()" CLASS="jsM_fontLink">Hide this Message</A>'
        !           881:       + '</SPAN></DIV><BR CLEAR="ALL"></DIV>'
        !           882:       + '<DIV STYLE="width:22em; height:1px"></DIV>'
        !           883:       + '</TD></TR></TABLE></CENTER><HR>';
        !           884:   },
        !           885:   
        !           886:   HideMessage: function () {
        !           887:     var message = jsMath.Element("Warning");
        !           888:     if (message) {message.style.display = "none"}
        !           889:   },
        !           890:   
        !           891:   /*
        !           892:    *  Register an extra font so jsMath knows about it
        !           893:    */
        !           894:   Register: function (data) {
        !           895:     if (typeof(data) == 'string') {data = {name: data}}
        !           896:     var fontname = data.name; var name = fontname.replace(/10$/,'');
        !           897:     var fontfam = jsMath.TeX.fam.length;
        !           898:     if (!data.style) {data.style = "font-family: "+fontname+", serif"}
        !           899:     if (!data.styles) {data.styles = {}}
        !           900:     if (!data.macros) {data.macros = {}}
        !           901:     /*
        !           902:      *  Register font family
        !           903:      */
        !           904:     jsMath.TeX.fam[fontfam] = fontname;
        !           905:     data.macros[name] = ['HandleFont',fontfam];
        !           906:     jsMath.Add(jsMath.Parser.prototype.macros,data.macros);
        !           907:     /*
        !           908:      *  Set up styles
        !           909:      */
        !           910:     data.styles['.'+fontname] = data.style;
        !           911:     jsMath.Setup.Styles(data.styles);
        !           912:     jsMath.Setup.TeXfont(fontname);
        !           913:     /*
        !           914:      *  Check for font and give message if missing
        !           915:      */
        !           916:     var hasTeXfont = !jsMath.nofonts &&
        !           917:                       data.test(fontname,data.testChar,data.testFactor);
        !           918:     if (hasTeXfont && jsMath.Controls.cookie.font == 'tex') {
        !           919:       if (data.tex) {data.tex(fontname,fontfam)}
        !           920:       return;
        !           921:     }
        !           922:     if (!hasTeXfont && jsMath.Controls.cookie.warn &&
        !           923:         jsMath.Controls.cookie.font == 'tex' && !jsMath.nofonts) {
        !           924:       if (!jsMath.Element("Warning")) this.Message(this.extra_message);
        !           925:       var extra = jsMath.Element("ExtraFonts");
        !           926:       if (extra) {
        !           927:         if (extra.innerHTML != "") {extra.innerHTML += ','}
        !           928:         extra.innerHTML += " " + fontname;
        !           929:       }
        !           930:     }
        !           931:     if (jsMath.Controls.cookie.font == 'unicode') {
        !           932:       if (data.fallback) {data.fallback(fontname,fontfam)}
        !           933:       return;
        !           934:     }
        !           935:     //  Image fonts
        !           936:     var font = {}; font[fontname] = ['all'];
        !           937:     jsMath.Img.SetFont(font);
        !           938:     jsMath.Img.LoadFont(fontname);
        !           939:   },
        !           940: 
        !           941:   /*
        !           942:    *  Load a font
        !           943:    */
        !           944:   Load: function (name) {jsMath.Setup.Script("fonts/"+name+"/def.js")}
        !           945:   
        !           946: };
        !           947: 
        !           948: /***************************************************************************/
        !           949: 
        !           950: /*
        !           951:  *  Implements the jsMath control panel.
        !           952:  *  Much of the code is in jsMath-controls.html, which is
        !           953:  *  loaded into a hidden IFRAME on demand
        !           954:  */
        !           955: jsMath.Controls = {
        !           956: 
        !           957:   //  Data stored in the jsMath cookie
        !           958:   cookie: {
        !           959:     scale: 100,
        !           960:     font: 'tex', autofont: 1, scaleImg: 0, alpha: 1,
        !           961:     warn: 1, button: 1,
        !           962:     print: 0, keep: '0D'
        !           963:   },
        !           964:   
        !           965:   cookiePath: '/',  // can also set cookieDomain
        !           966:   
        !           967:   
        !           968:   /*
        !           969:    *  Load the control panel
        !           970:    */
        !           971:   Panel: function () {
        !           972:     if (!this.panel) {this.panel = jsMath.Element("Controls")}
        !           973:     if (this.loaded) {this.Main()} else {
        !           974:       this.openMain = 1;
        !           975:       if (!this.iframe) {this.iframe = jsMath.Element("Frame")}
        !           976:       this.iframe.src = jsMath.root+"jsMath-controls.html";
        !           977:     }
        !           978:   },
        !           979:   
        !           980:   /*
        !           981:    *  Create the control panel button
        !           982:    */
        !           983:   Button: function () {
        !           984:     var button = jsMath.Setup.TopHTML("jsMath",{'class':'jsM_button'},{});
        !           985:     button.innerHTML = 
        !           986:       '<A HREF="javascript:jsMath.Controls.Panel()" '+
        !           987:          'STYLE="text-decoration:inherit; color:inherit">' +
        !           988:       '<SPAN TITLE="Open jsMath Control Panel">jsMath</SPAN></A>'
        !           989:     if (!this.cookie.button) {button.style.display = "none"}
        !           990:   },
        !           991:   
        !           992:  /*
        !           993:   *  MSIE doesn't implement position:fixed, so redraw the button on scrolls.
        !           994:   */
        !           995:   MoveButton: function () {
        !           996:     if (!this.button) {this.button = jsMath.Element("jsMath")}
        !           997:     this.button.style.visibility = "hidden";
        !           998:     this.button.style.visibility = "visible";
        !           999:   },
        !          1000: 
        !          1001:   /*
        !          1002:    *  Create the HTML needed for control panel
        !          1003:    */
        !          1004:   Init: function () {
        !          1005:     this.document = document;
        !          1006:     this.panel = jsMath.Setup.TopHTML("Controls", {'class':"jsM_panel"},{display:'none'});
        !          1007:     if (!jsMath.Browser.msieButtonBug) {this.Button()}
        !          1008:       else {setTimeout("jsMath.Controls.Button()",500)}
        !          1009:     if (jsMath.Browser.safariIFRAMEbug) {
        !          1010:       document.write(
        !          1011:          '<IFRAME SRC="'+jsMath.root+'jsMath-controls.html" '
        !          1012:          + 'ID="jsMath.Frame" SCROLLING="no" '
        !          1013:          + 'STYLE="visibility:hidden; position:absolute; width:1em; height:1em;">'
        !          1014:          + '</IFRAME>\n');
        !          1015:       return;
        !          1016:     }
        !          1017:     try {
        !          1018:       var frame = document.createElement('iframe');
        !          1019:       frame.setAttribute('scrolling','no');
        !          1020:       frame.style.border = '0px';
        !          1021:       frame.style.width  = '0px';
        !          1022:       frame.style.height = '0px';
        !          1023:       document.body.insertBefore(frame,this.panel);
        !          1024:       this.iframe = frame;
        !          1025:     } catch (err) {
        !          1026:       document.write('<IFRAME SRC="" ID="jsMath.Frame" SCROLLING="no" '
        !          1027:          + 'STYLE="visibility:hidden; position:absolute; width:1em; height:1em;">'
        !          1028:          + '</IFRAME>\n');
        !          1029:     }
        !          1030:   },
        !          1031: 
        !          1032:   /*
        !          1033:    *  Get the cookie data from the browser
        !          1034:    *  (for file: references, use url '?' syntax)
        !          1035:    */
        !          1036:   GetCookie: function () {
        !          1037:     var cookies = document.cookie;
        !          1038:     if (window.location.protocol == 'file:') 
        !          1039:       {cookies = unescape(window.location.search.substr(1))}
        !          1040:     if (cookies.match(/jsMath=([^;]*)/)) {
        !          1041:       var data = RegExp.$1.split(/,/);
        !          1042:       for (var i = 0; i < data.length; i++) {
        !          1043:         var x = data[i].match(/(.*):(.*)/);
        !          1044:         if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string
        !          1045:         this.cookie[x[1]] = x[2];
        !          1046:       }
        !          1047:     }
        !          1048:   },
        !          1049:   
        !          1050:   /*
        !          1051:    *  Save the cookie data in the browser
        !          1052:    *  (for file: urls, append data like CGI reference)
        !          1053:    */
        !          1054:   SetCookie: function (warn) {
        !          1055:     var cookie = [];
        !          1056:     for (var id in this.cookie) {cookie[cookie.length] = id + ':' + this.cookie[id]}
        !          1057:     cookie = cookie.join(',');
        !          1058:     if (window.location.protocol == 'file:') {
        !          1059:       if (!warn) return;
        !          1060:       this.loaded = 0;
        !          1061:       var href = window.location.href;
        !          1062:       href = href.replace(/\?.*/,"") + '?jsMath=' + escape(cookie);
        !          1063:       if (href != window.location.href) {window.location.replace(href)}
1.1       albertel 1064:     } else {
1.2     ! albertel 1065:       if (this.cookiePath) {cookie += '; path='+this.cookiePath}
        !          1066:       if (this.cookieDomain) {cookie += '; domain='+this.cookieDomain}
        !          1067:       if (this.cookie.keep != '0D') {
        !          1068:         var ms = {
        !          1069:           D: 1000*60*60*24,
        !          1070:           W: 1000*60*60*24*7,
        !          1071:           M: 1000*60*60*24*30,
        !          1072:           Y: 1000*60*60*24*365
        !          1073:         };
        !          1074:         var exp = new Date;
        !          1075:         exp.setTime(exp.getTime() +
        !          1076:             this.cookie.keep.substr(0,1) * ms[this.cookie.keep.substr(1,1)]);
        !          1077:         cookie += '; expires=' + exp.toGMTString();
        !          1078:       }
        !          1079:       document.cookie = 'jsMath='+cookie;
        !          1080:       var cookies = document.cookie;
        !          1081:       if (warn && !cookies.match(/jsMath=/))
        !          1082:         {alert("Cookies must be enabled in order to save jsMath options")}
1.1       albertel 1083:     }
1.2     ! albertel 1084:   }
        !          1085: 
        !          1086: };
        !          1087: 
        !          1088: /***************************************************************************/
1.1       albertel 1089: 
1.2     ! albertel 1090: /*
        !          1091:  *  Implements the actions for clicking and double-clicking
        !          1092:  *  on math formulas
        !          1093:  */
        !          1094: jsMath.Click = {
        !          1095:   
        !          1096:   dragging: 0,
1.1       albertel 1097:   
                   1098:   /*
1.2     ! albertel 1099:    *  Create the hidden DIV used for the tex source window
1.1       albertel 1100:    */
1.2     ! albertel 1101:   Init: function () {
        !          1102:     this.source = jsMath.Setup.TopHTML("Source",{'class':'jsM_float'},{display:'none'});
        !          1103:     this.source.innerHTML =
        !          1104:       '<DIV CLASS="jsM_drag"><DIV CLASS="jsM_close"></DIV></DIV>'
        !          1105:       + '<DIV CLASS="jsM_source"><SPAN></SPAN></DIV>';
        !          1106:     this.drag = this.source.firstChild;
        !          1107:     this.tex  = this.drag.nextSibling.firstChild;
        !          1108:     this.drag.firstChild.onclick = jsMath.Click.CloseSource;
        !          1109:     this.drag.onmousedown = jsMath.Click.StartDragging;
        !          1110:     this.drag.ondragstart = jsMath.Click.False;
        !          1111:     this.drag.onselectstart = jsMath.Click.False;
        !          1112:     this.source.onclick = jsMath.Click.CheckClose;
1.1       albertel 1113:   },
1.2     ! albertel 1114:   False: function () {return false},
        !          1115: 
1.1       albertel 1116:   /*
1.2     ! albertel 1117:    *  Handle clicking on math to get control panel
1.1       albertel 1118:    */
1.2     ! albertel 1119:   CheckClick: function (event) {
        !          1120:     if (!event) {event = window.event}
        !          1121:     if (event.altKey) jsMath.Controls.Panel();
        !          1122:   },
1.1       albertel 1123:   
                   1124:   /*
1.2     ! albertel 1125:    *  Handle double-click for seeing TeX code
1.1       albertel 1126:    */
1.2     ! albertel 1127:   CheckDblClick: function (event) {
        !          1128:     if (!event) {event = window.event}
        !          1129:     var event = jsMath.Click.Event(event);
        !          1130: 
        !          1131:     var source = jsMath.Click.source
        !          1132:     var tex = jsMath.Click.tex;
        !          1133: 
        !          1134:     source.style.visibility = 'hidden';
        !          1135:     source.style.display = ''; source.style.width = '';
        !          1136:     source.style.left = ''; source.style.top = '';
        !          1137:     tex.innerHTML = '';
        !          1138: 
        !          1139:     var TeX = this.alt;
        !          1140:     TeX = TeX.replace(/^\s+|\s+$/g,'');
        !          1141:     TeX = TeX.replace(/&/g,'&amp;');
        !          1142:     TeX = TeX.replace(/</g,'&lt;');
        !          1143:     TeX = TeX.replace(/>/g,'&gt;');
        !          1144:     TeX = TeX.replace(/\n/g,'<BR>');
        !          1145:     tex.innerHTML = TeX;
        !          1146: 
        !          1147:     var h = source.offsetHeight; var w;
        !          1148:     if (jsMath.Browser.msieDivWidthBug) {
        !          1149:       tex.className = 'jsM_source';      // Work around MSIE bug where
        !          1150:       w = tex.offsetWidth + 5;           // DIV's don't collapse to
        !          1151:       tex.className = '';                // their natural widths
        !          1152:     } else {
        !          1153:       w = source.offsetWidth;
        !          1154:     }
        !          1155:     w = Math.max(50,Math.min(w,.8*event.W,event.W-40));
        !          1156:     var x = Math.floor(event.x-w/2); var y = Math.floor(event.y-h/2);
        !          1157:     x = event.X + Math.max(Math.min(x,event.W-w-20),20);
        !          1158:     y = event.Y + Math.max(Math.min(y,event.H-h-5),5);
        !          1159: 
        !          1160:     source.style.left = x+'px'; source.style.top = y+'px';
        !          1161:     source.style.width = w+'px';
        !          1162:     source.style.visibility = '';
        !          1163:     jsMath.Click.left = x + event.X; jsMath.Click.top = y + event.Y;
        !          1164:     jsMath.Click.w = w; jsMath.Click.h = source.offsetHeight;
        !          1165: 
        !          1166:     jsMath.Click.DeselectText(x,y);
        !          1167:     return false;
        !          1168:   },
        !          1169: 
        !          1170:   /*
        !          1171:    *  Get window width, height, and offsets plus
        !          1172:    *  position of pointer relative to the window
        !          1173:    */
        !          1174:   Event: function (event) {
        !          1175:     var W = window.innerWidth  || document.body.clientWidth;
        !          1176:     var H = window.innerHeight || document.body.clientHeight;
        !          1177:     var X = window.pageXOffset; var Y = window.pageYOffset;
        !          1178:     if (X == null) {X = document.body.clientLeft; Y = document.body.clientTop}
        !          1179:     var x = event.pageX; var y = event.pageY;
        !          1180:     if (x == null) {
        !          1181:       x = event.clientX; y = event.clientY;
        !          1182:       if (jsMath.browser == 'MSIE' && document.compatMode == 'CSS1Compat') {
        !          1183:         X = document.documentElement.scrollLeft;
        !          1184:         Y = document.documentElement.scrollTop;
        !          1185:         W = document.documentElement.clientWidth;
        !          1186:         H = document.documentElement.clientHeight;
        !          1187:       } else {
        !          1188:         X = document.body.scrollLeft;
        !          1189:         Y = document.body.scrollTop;
1.1       albertel 1190:       }
1.2     ! albertel 1191:     } else {x -= X; y -= Y}
        !          1192: 
        !          1193:     return {x: x, y: y, W: W, H: H, X: X, Y: Y};
1.1       albertel 1194:   },
                   1195:   
                   1196:   /*
1.2     ! albertel 1197:    *  Unselect whatever text is selected (since double-clicking
        !          1198:    *  usually selects something)
1.1       albertel 1199:    */
1.2     ! albertel 1200:   DeselectText: function (x,y) {
        !          1201:     if (window.getSelection && window.getSelection().removeAllRanges)
        !          1202:       {window.getSelection().removeAllRanges()}
        !          1203:     else if (document.getSelection && document.getSelection().removeAllRanges)
        !          1204:       {document.getSelection().removeAllRanges()}
        !          1205:     else if (document.selection && document.selection.empty)
        !          1206:       {document.selection.empty()}
        !          1207:     else {
        !          1208:       /* Hack to deselect the text in Opera and Safari */
        !          1209:       if (jsMath.browser == 'MSIE') return;  // don't try it if MISE on Mac
        !          1210:       jsMath.hiddenTop.innerHTML =
        !          1211:         '<textarea style="visibility:hidden" ROWS="1" COLS="1">a</textarea>';
        !          1212:       jsMath.hiddenTop.firstChild.style.position = 'absolute';
        !          1213:       jsMath.hiddenTop.firstChild.style.left = x+'px';
        !          1214:       jsMath.hiddenTop.firstChild.style.top  = y+'px';
        !          1215:       setTimeout(jsMath.Click.SelectHidden,1);
1.1       albertel 1216:     }
                   1217:   },
1.2     ! albertel 1218:   SelectHidden: function () {
        !          1219:     jsMath.hiddenTop.firstChild.focus();
        !          1220:     jsMath.hiddenTop.firstChild.select();
        !          1221:     jsMath.hiddenTop.innerHTML = '';
        !          1222:   },
        !          1223: 
        !          1224:   /*
        !          1225:    *  Close the TeX source window
        !          1226:    */
        !          1227:   CloseSource: function () {
        !          1228:     jsMath.Click.tex.innerHTML = '';
        !          1229:     jsMath.Click.source.style.display = 'none';
        !          1230:     jsMath.Click.source.style.visibility = 'hidden';
        !          1231:     jsMath.Click.StopDragging();
        !          1232:     return false;
        !          1233:   },
        !          1234:   CheckClose: function (event) {
        !          1235:     if (!event) {event = window.event}
        !          1236:     if (event.altKey) {jsMath.Click.CloseSource(); return false}
        !          1237:   },
1.1       albertel 1238:   
                   1239:   /*
1.2     ! albertel 1240:    *  Set up for dragging the source panel
1.1       albertel 1241:    */
1.2     ! albertel 1242:   StartDragging: function (event) {
        !          1243:     if (!event) {event = window.event}
        !          1244:     if (jsMath.Click.dragging) {jsMath.Click.StopDragging(event)}
        !          1245:     var event = jsMath.Click.Event(event);
        !          1246:     jsMath.Click.dragging = 1;
        !          1247:     jsMath.Click.x = event.x + 2*event.X - jsMath.Click.left;
        !          1248:     jsMath.Click.y = event.y + 2*event.Y - jsMath.Click.top;
        !          1249:     jsMath.Click.oldonmousemove = document.body.onmousemove;
        !          1250:     jsMath.Click.oldonmouseup = document.body.onmouseup;
        !          1251:     document.body.onmousemove = jsMath.Click.DragSource;
        !          1252:     document.body.onmouseup = jsMath.Click.StopDragging;
        !          1253:     return false;
1.1       albertel 1254:   },
1.2     ! albertel 1255:   
1.1       albertel 1256:   /*
1.2     ! albertel 1257:    *  Stop dragging the source window
1.1       albertel 1258:    */
1.2     ! albertel 1259:   StopDragging: function (event) {
        !          1260:     if (jsMath.Click.dragging) {
        !          1261:       document.body.onmousemove = jsMath.Click.oldonmousemove;
        !          1262:       document.body.onmouseup   = jsMath.Click.oldonmouseup;
        !          1263:       jsMath.Click.oldonmousemove = null;
        !          1264:       jsMath.Click.oldonmouseup   = null;
        !          1265:       jsMath.Click.dragging = 0;
        !          1266:     }
        !          1267:     return false;
        !          1268:   },
1.1       albertel 1269:   
1.2     ! albertel 1270:   /*
        !          1271:    *  Move the source window (but stay within the browser window)
        !          1272:    */
        !          1273:   DragSource: function (event) {
        !          1274:     if (!event) {event = window.event}
        !          1275:     if (jsMath.Browser.buttonCheck && !event.button) {return jsMath.Click.StopDragging(event)}
        !          1276:     event = jsMath.Click.Event(event);
        !          1277:     var x = event.x + event.X - jsMath.Click.x;
        !          1278:     var y = event.y + event.Y - jsMath.Click.y;
        !          1279:     x = Math.max(event.X,Math.min(event.W+event.X-jsMath.Click.w,x));
        !          1280:     y = Math.max(event.Y,Math.min(event.H+event.Y-jsMath.Click.h,y));
        !          1281:     jsMath.Click.source.style.left = x + 'px';
        !          1282:     jsMath.Click.source.style.top  = y + 'px';
        !          1283:     jsMath.Click.left = x + event.X; jsMath.Click.top = y + event.Y;
        !          1284:     return false;
        !          1285:   }
1.1       albertel 1286: 
1.2     ! albertel 1287: };
1.1       albertel 1288: 
                   1289: /***************************************************************************/
                   1290: 
1.2     ! albertel 1291: /*
        !          1292:  *  The TeX font information
        !          1293:  */
        !          1294: jsMath.TeX = {
1.1       albertel 1295: 
1.2     ! albertel 1296:   //
        !          1297:   //  The TeX font parameters
        !          1298:   //
        !          1299:   thinmuskip:   3/18,
        !          1300:   medmuskip:    4/18,
        !          1301:   thickmuskip:  5/18,
        !          1302: 
        !          1303:   x_height:    .430554,
        !          1304:   quad:        1,
        !          1305:   num1:        .676508,
        !          1306:   num2:        .393732,
        !          1307:   num3:        .44373,
        !          1308:   denom1:      .685951,
        !          1309:   denom2:      .344841,
        !          1310:   sup1:        .412892,
        !          1311:   sup2:        .362892,
        !          1312:   sup3:        .288888,
        !          1313:   sub1:        .15,
        !          1314:   sub2:        .247217,
        !          1315:   sup_drop:    .386108,
        !          1316:   sub_drop:    .05,
        !          1317:   delim1:     2.39,
        !          1318:   delim2:     1.0,
        !          1319:   axis_height: .25,
        !          1320:   default_rule_thickness: .04,
        !          1321:   big_op_spacing1:  .111111,
        !          1322:   big_op_spacing2:  .166666,
        !          1323:   big_op_spacing3:  .2,
        !          1324:   big_op_spacing4:  .6,
        !          1325:   big_op_spacing5:  .1,
        !          1326: 
        !          1327:   integer:          6553.6,     // conversion of em's to TeX internal integer
        !          1328:   scriptspace:         .05,
        !          1329:   nulldelimiterspace:  .12,
        !          1330:   delimiterfactor:     901,
        !          1331:   delimitershortfall:   .5,
        !          1332:   scale:                 1,     //  scaling factor for font dimensions
        !          1333:  
1.1       albertel 1334:   //  The TeX math atom types (see Appendix G of the TeXbook)
                   1335:   atom: ['ord', 'op', 'bin', 'rel', 'open', 'close', 'punct', 'ord'],
                   1336: 
                   1337:   //  The TeX font families
                   1338:   fam: ['cmr10','cmmi10','cmsy10','cmex10','cmti10','','cmbx10'],
                   1339: 
                   1340:   /*
                   1341:    *  The following are the TeX font mappings and metrics.  The metric
                   1342:    *  information comes directly from the TeX .tfm files, and the
                   1343:    *  character mappings are for the TrueType TeX fonts.  Browser-specific
1.2     ! albertel 1344:    *  adjustments are made to these tables in the Browser.Init() routine
1.1       albertel 1345:    */
                   1346:   cmr10: [
                   1347:     // 00 - 0F
                   1348:     {c: '&#xA1;', h: 0.683, w: 0.625},
                   1349:     {c: '&#xA2;', h: 0.683, w: 0.833},
                   1350:     {c: '&#xA3;', h: 0.683, w: 0.778},
                   1351:     {c: '&#xA4;', h: 0.683, w: 0.694},
                   1352:     {c: '&#xA5;', h: 0.683, w: 0.667},
                   1353:     {c: '&#xA6;', h: 0.683, w: 0.75},
                   1354:     {c: '&#xA7;', h: 0.683, w: 0.722},
                   1355:     {c: '&#xA8;', h: 0.683, w: 0.778},
                   1356:     {c: '&#xA9;', h: 0.683, w: 0.722},
                   1357:     {c: '&#xAA;', h: 0.683, w: 0.778},
                   1358:     {c: '&#xAD;', h: 0.683, w: 0.722},
                   1359:     {c: '&#xAE;', h: 0.694, w: 0.583, ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}},
                   1360:     {c: '&#xAF;', h: 0.694, w: 0.556},
                   1361:     {c: '&#xB0;', h: 0.694, w: 0.556},
                   1362:     {c: '&#xB1;', h: 0.694, w: 0.833},
                   1363:     {c: '&#xB2;', h: 0.694, w: 0.833},
                   1364:     // 10 - 1F
                   1365:     {c: '&#xB3;', h: 0.431, w: 0.278},
                   1366:     {c: '&#xB4;', h: 0.431, d: 0.194, w: 0.306},
                   1367:     {c: '&#xB5;', h: 0.694, w: 0.5},
                   1368:     {c: '&#xB6;', h: 0.694, w: 0.5},
                   1369:     {c: '&#x2219;', h: 0.628, w: 0.5},
                   1370:     {c: '&#xB8;', h: 0.694, w: 0.5},
                   1371:     {c: '&#xB9;', h: 0.568, w: 0.5},
                   1372:     {c: '&#xBA;', h: 0.694, w: 0.75},
                   1373:     {c: '&#xBB;', d: 0.17, w: 0.444},
                   1374:     {c: '&#xBC;', h: 0.694, w: 0.5},
                   1375:     {c: '&#xBD;', h: 0.431, w: 0.722},
                   1376:     {c: '&#xBE;', h: 0.431, w: 0.778},
                   1377:     {c: '&#xBF;', h: 0.528, d: 0.0972, w: 0.5},
                   1378:     {c: '&#xC0;', h: 0.683, w: 0.903},
                   1379:     {c: '&#xC1;', h: 0.683, w: 1.01},
                   1380:     {c: '&#xC2;', h: 0.732, d: 0.0486, w: 0.778},
                   1381:     // 20 - 2F
                   1382:     {c: '&#xC3;', h: 0.431, w: 0.278, krn: {'108': -0.278, '76': -0.319}},
                   1383:     {c: '!', h: 0.694, w: 0.278, lig: {'96': 60}},
                   1384:     {c: '"', h: 0.694, w: 0.5},
                   1385:     {c: '#', h: 0.694, d: 0.194, w: 0.833},
                   1386:     {c: '$', h: 0.75, d: 0.0556, w: 0.5},
                   1387:     {c: '%', h: 0.75, d: 0.0556, w: 0.833},
                   1388:     {c: '&#x26;', h: 0.694, w: 0.778},
                   1389:     {c: '\'', h: 0.694, w: 0.278, krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}},
                   1390:     {c: '(', h: 0.75, d: 0.25, w: 0.389},
                   1391:     {c: ')', h: 0.75, d: 0.25, w: 0.389},
                   1392:     {c: '*', h: 0.75, w: 0.5},
                   1393:     {c: '+', h: 0.583, d: 0.0833, w: 0.778},
                   1394:     {c: ',', h: 0.106, d: 0.194, w: 0.278},
                   1395:     {c: '-', h: 0.431, w: 0.333, lig: {'45': 123}},
                   1396:     {c: '.', h: 0.106, w: 0.278},
                   1397:     {c: '/', h: 0.75, d: 0.25, w: 0.5},
                   1398:     // 30 - 3F
                   1399:     {c: '0', h: 0.644, w: 0.5},
                   1400:     {c: '1', h: 0.644, w: 0.5},
                   1401:     {c: '2', h: 0.644, w: 0.5},
                   1402:     {c: '3', h: 0.644, w: 0.5},
                   1403:     {c: '4', h: 0.644, w: 0.5},
                   1404:     {c: '5', h: 0.644, w: 0.5},
                   1405:     {c: '6', h: 0.644, w: 0.5},
                   1406:     {c: '7', h: 0.644, w: 0.5},
                   1407:     {c: '8', h: 0.644, w: 0.5},
                   1408:     {c: '9', h: 0.644, w: 0.5},
                   1409:     {c: ':', h: 0.431, w: 0.278},
                   1410:     {c: ';', h: 0.431, d: 0.194, w: 0.278},
                   1411:     {c: '&#x3C;', h: 0.5, d: 0.194, w: 0.278},
                   1412:     {c: '=', h: 0.367, d: -0.133, w: 0.778},
                   1413:     {c: '&#x3E;', h: 0.5, d: 0.194, w: 0.472},
                   1414:     {c: '?', h: 0.694, w: 0.472, lig: {'96': 62}},
                   1415:     // 40 - 4F
                   1416:     {c: '@', h: 0.694, w: 0.778},
                   1417:     {c: 'A', h: 0.683, w: 0.75, krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}},
                   1418:     {c: 'B', h: 0.683, w: 0.708},
                   1419:     {c: 'C', h: 0.683, w: 0.722},
                   1420:     {c: 'D', h: 0.683, w: 0.764, krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}},
                   1421:     {c: 'E', h: 0.683, w: 0.681},
                   1422:     {c: 'F', h: 0.683, w: 0.653, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
                   1423:     {c: 'G', h: 0.683, w: 0.785},
                   1424:     {c: 'H', h: 0.683, w: 0.75},
                   1425:     {c: 'I', h: 0.683, w: 0.361, krn: {'73': 0.0278}},
                   1426:     {c: 'J', h: 0.683, w: 0.514},
                   1427:     {c: 'K', h: 0.683, w: 0.778, krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
                   1428:     {c: 'L', h: 0.683, w: 0.625, krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}},
                   1429:     {c: 'M', h: 0.683, w: 0.917},
                   1430:     {c: 'N', h: 0.683, w: 0.75},
                   1431:     {c: 'O', h: 0.683, w: 0.778, krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}},
                   1432:     // 50 - 5F
                   1433:     {c: 'P', h: 0.683, w: 0.681, krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}},
                   1434:     {c: 'Q', h: 0.683, d: 0.194, w: 0.778},
                   1435:     {c: 'R', h: 0.683, w: 0.736, krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}},
                   1436:     {c: 'S', h: 0.683, w: 0.556},
                   1437:     {c: 'T', h: 0.683, w: 0.722, krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}},
                   1438:     {c: 'U', h: 0.683, w: 0.75},
                   1439:     {c: 'V', h: 0.683, w: 0.75, ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
                   1440:     {c: 'W', h: 0.683, w: 1.03, ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
                   1441:     {c: 'X', h: 0.683, w: 0.75, krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
                   1442:     {c: 'Y', h: 0.683, w: 0.75, ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}},
                   1443:     {c: 'Z', h: 0.683, w: 0.611},
                   1444:     {c: '[', h: 0.75, d: 0.25, w: 0.278},
                   1445:     {c: '\\', h: 0.694, w: 0.5},
                   1446:     {c: ']', h: 0.75, d: 0.25, w: 0.278},
                   1447:     {c: '^', h: 0.694, w: 0.5},
                   1448:     {c: '_', h: 0.668, w: 0.278},
                   1449:     // 60 - 6F
                   1450:     {c: '&#x60;', h: 0.694, w: 0.278, lig: {'96': 92}},
                   1451:     {c: 'a', h: 0.431, w: 0.5, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
                   1452:     {c: 'b', h: 0.694, w: 0.556, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
                   1453:     {c: 'c', h: 0.431, w: 0.444, krn: {'104': -0.0278, '107': -0.0278}},
                   1454:     {c: 'd', h: 0.694, w: 0.556},
                   1455:     {c: 'e', h: 0.431, w: 0.444},
                   1456:     {c: 'f', h: 0.694, w: 0.306, ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}},
                   1457:     {c: 'g', h: 0.431, d: 0.194, w: 0.5, ic: 0.0139, krn: {'106': 0.0278}},
                   1458:     {c: 'h', h: 0.694, w: 0.556, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}},
                   1459:     {c: 'i', h: 0.668, w: 0.278},
                   1460:     {c: 'j', h: 0.668, d: 0.194, w: 0.306},
                   1461:     {c: 'k', h: 0.694, w: 0.528, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}},
                   1462:     {c: 'l', h: 0.694, w: 0.278},
                   1463:     {c: 'm', h: 0.431, w: 0.833, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}},
                   1464:     {c: 'n', h: 0.431, w: 0.556, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}},
                   1465:     {c: 'o', h: 0.431, w: 0.5, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
                   1466:     // 70 - 7F
                   1467:     {c: 'p', h: 0.431, d: 0.194, w: 0.556, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
                   1468:     {c: 'q', h: 0.431, d: 0.194, w: 0.528},
                   1469:     {c: 'r', h: 0.431, w: 0.392},
                   1470:     {c: 's', h: 0.431, w: 0.394},
                   1471:     {c: 't', h: 0.615, w: 0.389, krn: {'121': -0.0278, '119': -0.0278}},
                   1472:     {c: 'u', h: 0.431, w: 0.556, krn: {'119': -0.0278}},
                   1473:     {c: 'v', h: 0.431, w: 0.528, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}},
                   1474:     {c: 'w', h: 0.431, w: 0.722, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}},
                   1475:     {c: 'x', h: 0.431, w: 0.528},
                   1476:     {c: 'y', h: 0.431, d: 0.194, w: 0.528, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}},
                   1477:     {c: 'z', h: 0.431, w: 0.444},
                   1478:     {c: '&#x7B;', h: 0.431, w: 0.5, ic: 0.0278, lig: {'45': 124}},
                   1479:     {c: '&#x7C;', h: 0.431, w: 1, ic: 0.0278},
                   1480:     {c: '&#x7D;', h: 0.694, w: 0.5},
                   1481:     {c: '&#x7E;', h: 0.668, w: 0.5},
                   1482:     {c: '&#xC4;', h: 0.668, w: 0.5}
                   1483:   ],
                   1484:   
                   1485:   cmmi10: [
                   1486:     // 00 - 0F
                   1487:     {c: '&#xA1;', h: 0.683, w: 0.615, ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}},
                   1488:     {c: '&#xA2;', h: 0.683, w: 0.833, krn: {'127': 0.167}},
                   1489:     {c: '&#xA3;', h: 0.683, w: 0.763, ic: 0.0278, krn: {'127': 0.0833}},
                   1490:     {c: '&#xA4;', h: 0.683, w: 0.694, krn: {'127': 0.167}},
                   1491:     {c: '&#xA5;', h: 0.683, w: 0.742, ic: 0.0757, krn: {'127': 0.0833}},
                   1492:     {c: '&#xA6;', h: 0.683, w: 0.831, ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}},
                   1493:     {c: '&#xA7;', h: 0.683, w: 0.78, ic: 0.0576, krn: {'127': 0.0833}},
                   1494:     {c: '&#xA8;', h: 0.683, w: 0.583, ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0556}},
                   1495:     {c: '&#xA9;', h: 0.683, w: 0.667, krn: {'127': 0.0833}},
                   1496:     {c: '&#xAA;', h: 0.683, w: 0.612, ic: 0.11, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}},
                   1497:     {c: '&#xAD;', h: 0.683, w: 0.772, ic: 0.0502, krn: {'127': 0.0833}},
                   1498:     {c: '&#xAE;', h: 0.431, w: 0.64, ic: 0.0037, krn: {'127': 0.0278}},
                   1499:     {c: '&#xAF;', h: 0.694, d: 0.194, w: 0.566, ic: 0.0528, krn: {'127': 0.0833}},
                   1500:     {c: '&#xB0;', h: 0.431, d: 0.194, w: 0.518, ic: 0.0556},
                   1501:     {c: '&#xB1;', h: 0.694, w: 0.444, ic: 0.0378, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}},
                   1502:     {c: '&#xB2;', h: 0.431, w: 0.406, krn: {'127': 0.0556}},
                   1503:     // 10 - 1F
                   1504:     {c: '&#xB3;', h: 0.694, d: 0.194, w: 0.438, ic: 0.0738, krn: {'127': 0.0833}},
                   1505:     {c: '&#xB4;', h: 0.431, d: 0.194, w: 0.497, ic: 0.0359, krn: {'127': 0.0556}},
                   1506:     {c: '&#xB5;', h: 0.694, w: 0.469, ic: 0.0278, krn: {'127': 0.0833}},
                   1507:     {c: '&#xB6;', h: 0.431, w: 0.354, krn: {'127': 0.0556}},
                   1508:     {c: '&#x2219;', h: 0.431, w: 0.576},
                   1509:     {c: '&#xB8;', h: 0.694, w: 0.583},
                   1510:     {c: '&#xB9;', h: 0.431, d: 0.194, w: 0.603, krn: {'127': 0.0278}},
                   1511:     {c: '&#xBA;', h: 0.431, w: 0.494, ic: 0.0637, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}},
                   1512:     {c: '&#xBB;', h: 0.694, d: 0.194, w: 0.438, ic: 0.046, krn: {'127': 0.111}},
                   1513:     {c: '&#xBC;', h: 0.431, w: 0.57, ic: 0.0359},
                   1514:     {c: '&#xBD;', h: 0.431, d: 0.194, w: 0.517, krn: {'127': 0.0833}},
                   1515:     {c: '&#xBE;', h: 0.431, w: 0.571, ic: 0.0359, krn: {'59': -0.0556, '58': -0.0556}},
                   1516:     {c: '&#xBF;', h: 0.431, w: 0.437, ic: 0.113, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}},
                   1517:     {c: '&#xC0;', h: 0.431, w: 0.54, ic: 0.0359, krn: {'127': 0.0278}},
                   1518:     {c: '&#xC1;', h: 0.694, d: 0.194, w: 0.596, krn: {'127': 0.0833}},
                   1519:     {c: '&#xC2;', h: 0.431, d: 0.194, w: 0.626, krn: {'127': 0.0556}},
                   1520:     // 20 - 2F
                   1521:     {c: '&#xC3;', h: 0.694, d: 0.194, w: 0.651, ic: 0.0359, krn: {'127': 0.111}},
                   1522:     {c: '!', h: 0.431, w: 0.622, ic: 0.0359},
                   1523:     {c: '"', h: 0.431, w: 0.466, krn: {'127': 0.0833}},
                   1524:     {c: '#', h: 0.694, w: 0.591, krn: {'127': 0.0833}},
                   1525:     {c: '$', h: 0.431, w: 0.828, ic: 0.0278},
                   1526:     {c: '%', h: 0.431, d: 0.194, w: 0.517, krn: {'127': 0.0833}},
                   1527:     {c: '&#x26;', h: 0.431, d: 0.0972, w: 0.363, ic: 0.0799, krn: {'127': 0.0833}},
                   1528:     {c: '\'', h: 0.431, d: 0.194, w: 0.654, krn: {'127': 0.0833}},
                   1529:     {c: '(', h: 0.367, d: -0.133, w: 1},
                   1530:     {c: ')', h: 0.367, d: -0.133, w: 1},
                   1531:     {c: '*', h: 0.367, d: -0.133, w: 1},
                   1532:     {c: '+', h: 0.367, d: -0.133, w: 1},
                   1533:     {c: ',', h: 0.464, d: -0.0363, w: 0.278},
                   1534:     {c: '-', h: 0.464, d: -0.0363, w: 0.278},
                   1535:     {c: '.', h: 0.465, d: -0.0347, w: 0.5},
                   1536:     {c: '/', h: 0.465, d: -0.0347, w: 0.5},
                   1537:     // 30 - 3F
                   1538:     {c: '0', h: 0.431, w: 0.5},
                   1539:     {c: '1', h: 0.431, w: 0.5},
                   1540:     {c: '2', h: 0.431, w: 0.5},
                   1541:     {c: '3', h: 0.431, d: 0.194, w: 0.5},
                   1542:     {c: '4', h: 0.431, d: 0.194, w: 0.5},
                   1543:     {c: '5', h: 0.431, d: 0.194, w: 0.5},
                   1544:     {c: '6', h: 0.644, w: 0.5},
                   1545:     {c: '7', h: 0.431, d: 0.194, w: 0.5},
                   1546:     {c: '8', h: 0.644, w: 0.5},
                   1547:     {c: '9', h: 0.431, d: 0.194, w: 0.5},
                   1548:     {c: ':', h: 0.106, w: 0.278},
                   1549:     {c: ';', h: 0.106, d: 0.194, w: 0.278},
                   1550:     {c: '&#x3C;', h: 0.539, d: 0.0391, w: 0.778},
                   1551:     {c: '=', h: 0.75, d: 0.25, w: 0.5, krn: {'1': -0.0556, '65': -0.0556, '77': -0.0556, '78': -0.0556, '89': 0.0556, '90': -0.0556}},
                   1552:     {c: '&#x3E;', h: 0.539, d: 0.0391, w: 0.778},
                   1553:     {c: '?', h: 0.465, d: -0.0347, w: 0.5},
                   1554:     // 40 - 4F
                   1555:     {c: '@', h: 0.694, w: 0.531, ic: 0.0556, krn: {'127': 0.0833}},
                   1556:     {c: 'A', h: 0.683, w: 0.75, krn: {'127': 0.139}},
                   1557:     {c: 'B', h: 0.683, w: 0.759, ic: 0.0502, krn: {'127': 0.0833}},
                   1558:     {c: 'C', h: 0.683, w: 0.715, ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
                   1559:     {c: 'D', h: 0.683, w: 0.828, ic: 0.0278, krn: {'127': 0.0556}},
                   1560:     {c: 'E', h: 0.683, w: 0.738, ic: 0.0576, krn: {'127': 0.0833}},
                   1561:     {c: 'F', h: 0.683, w: 0.643, ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}},
                   1562:     {c: 'G', h: 0.683, w: 0.786, krn: {'127': 0.0833}},
                   1563:     {c: 'H', h: 0.683, w: 0.831, ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}},
                   1564:     {c: 'I', h: 0.683, w: 0.44, ic: 0.0785, krn: {'127': 0.111}},
                   1565:     {c: 'J', h: 0.683, w: 0.555, ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}},
                   1566:     {c: 'K', h: 0.683, w: 0.849, ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}},
                   1567:     {c: 'L', h: 0.683, w: 0.681, krn: {'127': 0.0278}},
                   1568:     {c: 'M', h: 0.683, w: 0.97, ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
                   1569:     {c: 'N', h: 0.683, w: 0.803, ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
                   1570:     {c: 'O', h: 0.683, w: 0.763, ic: 0.0278, krn: {'127': 0.0833}},
                   1571:     // 50 - 5F
                   1572:     {c: 'P', h: 0.683, w: 0.642, ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}},
                   1573:     {c: 'Q', h: 0.683, d: 0.194, w: 0.791, krn: {'127': 0.0833}},
                   1574:     {c: 'R', h: 0.683, w: 0.759, ic: 0.00773, krn: {'127': 0.0833}},
                   1575:     {c: 'S', h: 0.683, w: 0.613, ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
                   1576:     {c: 'T', h: 0.683, w: 0.584, ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
                   1577:     {c: 'U', h: 0.683, w: 0.683, ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}},
                   1578:     {c: 'V', h: 0.683, w: 0.583, ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}},
                   1579:     {c: 'W', h: 0.683, w: 0.944, ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}},
                   1580:     {c: 'X', h: 0.683, w: 0.828, ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
                   1581:     {c: 'Y', h: 0.683, w: 0.581, ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}},
                   1582:     {c: 'Z', h: 0.683, w: 0.683, ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
                   1583:     {c: '[', h: 0.75, w: 0.389},
                   1584:     {c: '\\', h: 0.694, d: 0.194, w: 0.389},
                   1585:     {c: ']', h: 0.694, d: 0.194, w: 0.389},
                   1586:     {c: '^', h: 0.358, d: -0.142, w: 1},
                   1587:     {c: '_', h: 0.358, d: -0.142, w: 1},
                   1588:     // 60 - 6F
                   1589:     {c: '&#x60;', h: 0.694, w: 0.417, krn: {'127': 0.111}},
                   1590:     {c: 'a', h: 0.431, w: 0.529},
                   1591:     {c: 'b', h: 0.694, w: 0.429},
                   1592:     {c: 'c', h: 0.431, w: 0.433, krn: {'127': 0.0556}},
                   1593:     {c: 'd', h: 0.694, w: 0.52, krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}},
                   1594:     {c: 'e', h: 0.431, w: 0.466, krn: {'127': 0.0556}},
                   1595:     {c: 'f', h: 0.694, d: 0.194, w: 0.49, ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}},
                   1596:     {c: 'g', h: 0.431, d: 0.194, w: 0.477, ic: 0.0359, krn: {'127': 0.0278}},
                   1597:     {c: 'h', h: 0.694, w: 0.576, krn: {'127': -0.0278}},
                   1598:     {c: 'i', h: 0.66, w: 0.345},
                   1599:     {c: 'j', h: 0.66, d: 0.194, w: 0.412, ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}},
                   1600:     {c: 'k', h: 0.694, w: 0.521, ic: 0.0315},
                   1601:     {c: 'l', h: 0.694, w: 0.298, ic: 0.0197, krn: {'127': 0.0833}},
                   1602:     {c: 'm', h: 0.431, w: 0.878},
                   1603:     {c: 'n', h: 0.431, w: 0.6},
                   1604:     {c: 'o', h: 0.431, w: 0.485, krn: {'127': 0.0556}},
                   1605:     // 70 - 7F
                   1606:     {c: 'p', h: 0.431, d: 0.194, w: 0.503, krn: {'127': 0.0833}},
                   1607:     {c: 'q', h: 0.431, d: 0.194, w: 0.446, ic: 0.0359, krn: {'127': 0.0833}},
                   1608:     {c: 'r', h: 0.431, w: 0.451, ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}},
                   1609:     {c: 's', h: 0.431, w: 0.469, krn: {'127': 0.0556}},
                   1610:     {c: 't', h: 0.615, w: 0.361, krn: {'127': 0.0833}},
                   1611:     {c: 'u', h: 0.431, w: 0.572, krn: {'127': 0.0278}},
                   1612:     {c: 'v', h: 0.431, w: 0.485, ic: 0.0359, krn: {'127': 0.0278}},
                   1613:     {c: 'w', h: 0.431, w: 0.716, ic: 0.0269, krn: {'127': 0.0833}},
                   1614:     {c: 'x', h: 0.431, w: 0.572, krn: {'127': 0.0278}},
                   1615:     {c: 'y', h: 0.431, d: 0.194, w: 0.49, ic: 0.0359, krn: {'127': 0.0556}},
                   1616:     {c: 'z', h: 0.431, w: 0.465, ic: 0.044, krn: {'127': 0.0556}},
                   1617:     {c: '&#x7B;', h: 0.431, w: 0.322, krn: {'127': 0.0278}},
                   1618:     {c: '&#x7C;', h: 0.431, d: 0.194, w: 0.384, krn: {'127': 0.0833}},
                   1619:     {c: '&#x7D;', h: 0.431, d: 0.194, w: 0.636, krn: {'127': 0.111}},
                   1620:     {c: '&#x7E;', h: 0.714, w: 0.5, ic: 0.154},
                   1621:     {c: '&#xC4;', h: 0.694, w: 0.278, ic: 0.399}
                   1622:   ],
                   1623: 
                   1624:   cmsy10: [
                   1625:     // 00 - 0F
                   1626:     {c: '&#xA1;', h: 0.583, d: 0.0833, w: 0.778},
                   1627:     {c: '&#xA2;', h: 0.444, d: -0.0556, w: 0.278},
                   1628:     {c: '&#xA3;', h: 0.583, d: 0.0833, w: 0.778},
                   1629:     {c: '&#xA4;', h: 0.465, d: -0.0347, w: 0.5},
                   1630:     {c: '&#xA5;', h: 0.583, d: 0.0833, w: 0.778},
                   1631:     {c: '&#xA6;', h: 0.444, d: -0.0556, w: 0.5},
                   1632:     {c: '&#xA7;', h: 0.583, d: 0.0833, w: 0.778},
                   1633:     {c: '&#xA8;', h: 0.583, d: 0.0833, w: 0.778},
                   1634:     {c: '&#xA9;', h: 0.583, d: 0.0833, w: 0.778},
                   1635:     {c: '&#xAA;', h: 0.583, d: 0.0833, w: 0.778},
                   1636:     {c: '&#xAD;', h: 0.583, d: 0.0833, w: 0.778},
                   1637:     {c: '&#xAE;', h: 0.583, d: 0.0833, w: 0.778},
                   1638:     {c: '&#xAF;', h: 0.583, d: 0.0833, w: 0.778},
                   1639:     {c: '&#xB0;', h: 0.694, d: 0.194, w: 1},
                   1640:     {c: '&#xB1;', h: 0.444, d: -0.0556, w: 0.5},
                   1641:     {c: '&#xB2;', h: 0.444, d: -0.0556, w: 0.5},
                   1642:     // 10 - 1F
                   1643:     {c: '&#xB3;', h: 0.464, d: -0.0363, w: 0.778},
                   1644:     {c: '&#xB4;', h: 0.464, d: -0.0363, w: 0.778},
                   1645:     {c: '&#xB5;', h: 0.636, d: 0.136, w: 0.778},
                   1646:     {c: '&#xB6;', h: 0.636, d: 0.136, w: 0.778},
                   1647:     {c: '&#x2219;', h: 0.636, d: 0.136, w: 0.778},
                   1648:     {c: '&#xB8;', h: 0.636, d: 0.136, w: 0.778},
                   1649:     {c: '&#xB9;', h: 0.636, d: 0.136, w: 0.778},
                   1650:     {c: '&#xBA;', h: 0.636, d: 0.136, w: 0.778},
                   1651:     {c: '&#xBB;', h: 0.367, d: -0.133, w: 0.778},
                   1652:     {c: '&#xBC;', h: 0.483, d: -0.0169, w: 0.778},
                   1653:     {c: '&#xBD;', h: 0.539, d: 0.0391, w: 0.778},
                   1654:     {c: '&#xBE;', h: 0.539, d: 0.0391, w: 0.778},
                   1655:     {c: '&#xBF;', h: 0.539, d: 0.0391, w: 1},
                   1656:     {c: '&#xC0;', h: 0.539, d: 0.0391, w: 1},
                   1657:     {c: '&#xC1;', h: 0.539, d: 0.0391, w: 0.778},
                   1658:     {c: '&#xC2;', h: 0.539, d: 0.0391, w: 0.778},
                   1659:     // 20 - 2F
                   1660:     {c: '&#xC3;', h: 0.367, d: -0.133, w: 1},
                   1661:     {c: '!', h: 0.367, d: -0.133, w: 1},
                   1662:     {c: '"', h: 0.694, d: 0.194, w: 0.5},
                   1663:     {c: '#', h: 0.694, d: 0.194, w: 0.5},
                   1664:     {c: '$', h: 0.367, d: -0.133, w: 1},
                   1665:     {c: '%', h: 0.694, d: 0.194, w: 1},
                   1666:     {c: '&#x26;', h: 0.694, d: 0.194, w: 1},
                   1667:     {c: '\'', h: 0.464, d: -0.0363, w: 0.778},
                   1668:     {c: '(', h: 0.367, d: -0.133, w: 1},
                   1669:     {c: ')', h: 0.367, d: -0.133, w: 1},
                   1670:     {c: '*', h: 0.694, d: 0.194, w: 0.611},
                   1671:     {c: '+', h: 0.694, d: 0.194, w: 0.611},
                   1672:     {c: ',', h: 0.367, d: -0.133, w: 1},
                   1673:     {c: '-', h: 0.694, d: 0.194, w: 1},
                   1674:     {c: '.', h: 0.694, d: 0.194, w: 1},
                   1675:     {c: '/', h: 0.431, w: 0.778},
                   1676:     // 30 - 3F
                   1677:     {c: '0', h: 0.556, w: 0.275},
                   1678:     {c: '1', h: 0.431, w: 1},
                   1679:     {c: '2', h: 0.539, d: 0.0391, w: 0.667},
                   1680:     {c: '3', h: 0.539, d: 0.0391, w: 0.667},
                   1681:     {c: '4', h: 0.694, d: 0.194, w: 0.889},
                   1682:     {c: '5', h: 0.694, d: 0.194, w: 0.889},
                   1683:     {c: '6', h: 0.694, d: 0.194, w: 0},
                   1684:     {c: '7', h: 0.367, d: -0.133, w: 0},
                   1685:     {c: '8', h: 0.694, w: 0.556},
                   1686:     {c: '9', h: 0.694, w: 0.556},
                   1687:     {c: ':', h: 0.431, w: 0.667},
                   1688:     {c: ';', h: 0.75, d: 0.0556, w: 0.5},
                   1689:     {c: '&#x3C;', h: 0.694, w: 0.722},
                   1690:     {c: '=', h: 0.694, w: 0.722},
                   1691:     {c: '&#x3E;', h: 0.694, w: 0.778},
                   1692:     {c: '?', h: 0.694, w: 0.778},
                   1693:     // 40 - 4F
                   1694:     {c: '@', h: 0.694, w: 0.611},
                   1695:     {c: 'A', h: 0.683, w: 0.798, krn: {'48': 0.194}},
                   1696:     {c: 'B', h: 0.683, w: 0.657, ic: 0.0304, krn: {'48': 0.139}},
                   1697:     {c: 'C', h: 0.683, w: 0.527, ic: 0.0583, krn: {'48': 0.139}},
                   1698:     {c: 'D', h: 0.683, w: 0.771, ic: 0.0278, krn: {'48': 0.0833}},
                   1699:     {c: 'E', h: 0.683, w: 0.528, ic: 0.0894, krn: {'48': 0.111}},
                   1700:     {c: 'F', h: 0.683, w: 0.719, ic: 0.0993, krn: {'48': 0.111}},
                   1701:     {c: 'G', h: 0.683, d: 0.0972, w: 0.595, ic: 0.0593, krn: {'48': 0.111}},
                   1702:     {c: 'H', h: 0.683, w: 0.845, ic: 0.00965, krn: {'48': 0.111}},
                   1703:     {c: 'I', h: 0.683, w: 0.545, ic: 0.0738, krn: {'48': 0.0278}},
                   1704:     {c: 'J', h: 0.683, d: 0.0972, w: 0.678, ic: 0.185, krn: {'48': 0.167}},
                   1705:     {c: 'K', h: 0.683, w: 0.762, ic: 0.0144, krn: {'48': 0.0556}},
                   1706:     {c: 'L', h: 0.683, w: 0.69, krn: {'48': 0.139}},
                   1707:     {c: 'M', h: 0.683, w: 1.2, krn: {'48': 0.139}},
                   1708:     {c: 'N', h: 0.683, w: 0.82, ic: 0.147, krn: {'48': 0.0833}},
                   1709:     {c: 'O', h: 0.683, w: 0.796, ic: 0.0278, krn: {'48': 0.111}},
                   1710:     // 50 - 5F
                   1711:     {c: 'P', h: 0.683, w: 0.696, ic: 0.0822, krn: {'48': 0.0833}},
                   1712:     {c: 'Q', h: 0.683, d: 0.0972, w: 0.817, krn: {'48': 0.111}},
                   1713:     {c: 'R', h: 0.683, w: 0.848, krn: {'48': 0.0833}},
                   1714:     {c: 'S', h: 0.683, w: 0.606, ic: 0.075, krn: {'48': 0.139}},
                   1715:     {c: 'T', h: 0.683, w: 0.545, ic: 0.254, krn: {'48': 0.0278}},
                   1716:     {c: 'U', h: 0.683, w: 0.626, ic: 0.0993, krn: {'48': 0.0833}},
                   1717:     {c: 'V', h: 0.683, w: 0.613, ic: 0.0822, krn: {'48': 0.0278}},
                   1718:     {c: 'W', h: 0.683, w: 0.988, ic: 0.0822, krn: {'48': 0.0833}},
                   1719:     {c: 'X', h: 0.683, w: 0.713, ic: 0.146, krn: {'48': 0.139}},
                   1720:     {c: 'Y', h: 0.683, d: 0.0972, w: 0.668, ic: 0.0822, krn: {'48': 0.0833}},
                   1721:     {c: 'Z', h: 0.683, w: 0.725, ic: 0.0794, krn: {'48': 0.139}},
                   1722:     {c: '[', h: 0.556, w: 0.667},
                   1723:     {c: '\\', h: 0.556, w: 0.667},
                   1724:     {c: ']', h: 0.556, w: 0.667},
                   1725:     {c: '^', h: 0.556, w: 0.667},
                   1726:     {c: '_', h: 0.556, w: 0.667},
                   1727:     // 60 - 6F
                   1728:     {c: '&#x60;', h: 0.694, w: 0.611},
                   1729:     {c: 'a', h: 0.694, w: 0.611},
                   1730:     {c: 'b', h: 0.75, d: 0.25, w: 0.444},
                   1731:     {c: 'c', h: 0.75, d: 0.25, w: 0.444},
                   1732:     {c: 'd', h: 0.75, d: 0.25, w: 0.444},
                   1733:     {c: 'e', h: 0.75, d: 0.25, w: 0.444},
                   1734:     {c: 'f', h: 0.75, d: 0.25, w: 0.5},
                   1735:     {c: 'g', h: 0.75, d: 0.25, w: 0.5},
                   1736:     {c: 'h', h: 0.75, d: 0.25, w: 0.389},
                   1737:     {c: 'i', h: 0.75, d: 0.25, w: 0.389},
                   1738:     {c: 'j', h: 0.75, d: 0.25, w: 0.278},
                   1739:     {c: 'k', h: 0.75, d: 0.25, w: 0.5},
                   1740:     {c: 'l', h: 0.75, d: 0.25, w: 0.5},
                   1741:     {c: 'm', h: 0.75, d: 0.25, w: 0.611},
                   1742:     {c: 'n', h: 0.75, d: 0.25, w: 0.5},
                   1743:     {c: 'o', h: 0.694, d: 0.194, w: 0.278},
                   1744:     // 70 - 7F
                   1745:     {c: 'p', h: 0.04, d: 0.96, w: 0.833},
                   1746:     {c: 'q', h: 0.683, w: 0.75},
                   1747:     {c: 'r', h: 0.683, w: 0.833},
                   1748:     {c: 's', h: 0.694, d: 0.194, w: 0.417, ic: 0.111},
                   1749:     {c: 't', h: 0.556, w: 0.667},
                   1750:     {c: 'u', h: 0.556, w: 0.667},
                   1751:     {c: 'v', h: 0.636, d: 0.136, w: 0.778},
                   1752:     {c: 'w', h: 0.636, d: 0.136, w: 0.778},
                   1753:     {c: 'x', h: 0.694, d: 0.194, w: 0.444},
                   1754:     {c: 'y', h: 0.694, d: 0.194, w: 0.444},
                   1755:     {c: 'z', h: 0.694, d: 0.194, w: 0.444},
                   1756:     {c: '&#x7B;', h: 0.694, d: 0.194, w: 0.611},
                   1757:     {c: '&#x7C;', h: 0.694, d: 0.13, w: 0.778},
                   1758:     {c: '&#x7D;', h: 0.694, d: 0.13, w: 0.778},
                   1759:     {c: '&#x7E;', h: 0.694, d: 0.13, w: 0.778},
                   1760:     {c: '&#xC4;', h: 0.694, d: 0.13, w: 0.778}
                   1761:   ],
                   1762: 
                   1763:   cmex10: [
                   1764:     // 00 - 0F
                   1765:     {c: '&#xA1;', h: 0.04, d: 1.16, w: 0.458, n: 16},
                   1766:     {c: '&#xA2;', h: 0.04, d: 1.16, w: 0.458, n: 17},
                   1767:     {c: '&#xA3;', h: 0.04, d: 1.16, w: 0.417, n: 104},
                   1768:     {c: '&#xA4;', h: 0.04, d: 1.16, w: 0.417, n: 105},
                   1769:     {c: '&#xA5;', h: 0.04, d: 1.16, w: 0.472, n: 106},
                   1770:     {c: '&#xA6;', h: 0.04, d: 1.16, w: 0.472, n: 107},
                   1771:     {c: '&#xA7;', h: 0.04, d: 1.16, w: 0.472, n: 108},
                   1772:     {c: '&#xA8;', h: 0.04, d: 1.16, w: 0.472, n: 109},
                   1773:     {c: '&#xA9;', h: 0.04, d: 1.16, w: 0.583, n: 110},
                   1774:     {c: '&#xAA;', h: 0.04, d: 1.16, w: 0.583, n: 111},
                   1775:     {c: '&#xAD;', h: 0.04, d: 1.16, w: 0.472, n: 68},
                   1776:     {c: '&#xAE;', h: 0.04, d: 1.16, w: 0.472, n: 69},
                   1777:     {c: '&#xAF;', d: 0.6, w: 0.333, delim: {rep: 12}},
                   1778:     {c: '&#xB0;', d: 0.6, w: 0.556, delim: {rep: 13}},
                   1779:     {c: '&#xB1;', h: 0.04, d: 1.16, w: 0.578, n: 46},
                   1780:     {c: '&#xB2;', h: 0.04, d: 1.16, w: 0.578, n: 47},
                   1781:     // 10 - 1F
                   1782:     {c: '&#xB3;', h: 0.04, d: 1.76, w: 0.597, n: 18},
                   1783:     {c: '&#xB4;', h: 0.04, d: 1.76, w: 0.597, n: 19},
                   1784:     {c: '&#xB5;', h: 0.04, d: 2.36, w: 0.736, n: 32},
                   1785:     {c: '&#xB6;', h: 0.04, d: 2.36, w: 0.736, n: 33},
                   1786:     {c: '&#x2219;', h: 0.04, d: 2.36, w: 0.528, n: 34},
                   1787:     {c: '&#xB8;', h: 0.04, d: 2.36, w: 0.528, n: 35},
                   1788:     {c: '&#xB9;', h: 0.04, d: 2.36, w: 0.583, n: 36},
                   1789:     {c: '&#xBA;', h: 0.04, d: 2.36, w: 0.583, n: 37},
                   1790:     {c: '&#xBB;', h: 0.04, d: 2.36, w: 0.583, n: 38},
                   1791:     {c: '&#xBC;', h: 0.04, d: 2.36, w: 0.583, n: 39},
                   1792:     {c: '&#xBD;', h: 0.04, d: 2.36, w: 0.75, n: 40},
                   1793:     {c: '&#xBE;', h: 0.04, d: 2.36, w: 0.75, n: 41},
                   1794:     {c: '&#xBF;', h: 0.04, d: 2.36, w: 0.75, n: 42},
                   1795:     {c: '&#xC0;', h: 0.04, d: 2.36, w: 0.75, n: 43},
                   1796:     {c: '&#xC1;', h: 0.04, d: 2.36, w: 1.04, n: 44},
                   1797:     {c: '&#xC2;', h: 0.04, d: 2.36, w: 1.04, n: 45},
                   1798:     // 20 - 2F
                   1799:     {c: '&#xC3;', h: 0.04, d: 2.96, w: 0.792, n: 48},
                   1800:     {c: '!', h: 0.04, d: 2.96, w: 0.792, n: 49},
                   1801:     {c: '"', h: 0.04, d: 2.96, w: 0.583, n: 50},
                   1802:     {c: '#', h: 0.04, d: 2.96, w: 0.583, n: 51},
                   1803:     {c: '$', h: 0.04, d: 2.96, w: 0.639, n: 52},
                   1804:     {c: '%', h: 0.04, d: 2.96, w: 0.639, n: 53},
                   1805:     {c: '&#x26;', h: 0.04, d: 2.96, w: 0.639, n: 54},
                   1806:     {c: '\'', h: 0.04, d: 2.96, w: 0.639, n: 55},
                   1807:     {c: '(', h: 0.04, d: 2.96, w: 0.806, n: 56},
                   1808:     {c: ')', h: 0.04, d: 2.96, w: 0.806, n: 57},
                   1809:     {c: '*', h: 0.04, d: 2.96, w: 0.806},
                   1810:     {c: '+', h: 0.04, d: 2.96, w: 0.806},
                   1811:     {c: ',', h: 0.04, d: 2.96, w: 1.28},
                   1812:     {c: '-', h: 0.04, d: 2.96, w: 1.28},
                   1813:     {c: '.', h: 0.04, d: 1.76, w: 0.811, n: 30},
                   1814:     {c: '/', h: 0.04, d: 1.76, w: 0.811, n: 31},
                   1815:     // 30 - 3F
                   1816:     {c: '0', h: 0.04, d: 1.76, w: 0.875, delim: {top: 48, bot: 64, rep: 66}},
                   1817:     {c: '1', h: 0.04, d: 1.76, w: 0.875, delim: {top: 49, bot: 65, rep: 67}},
                   1818:     {c: '2', h: 0.04, d: 1.76, w: 0.667, delim: {top: 50, bot: 52, rep: 54}},
                   1819:     {c: '3', h: 0.04, d: 1.76, w: 0.667, delim: {top: 51, bot: 53, rep: 55}},
                   1820:     {c: '4', h: 0.04, d: 1.76, w: 0.667, delim: {bot: 52, rep: 54}},
                   1821:     {c: '5', h: 0.04, d: 1.76, w: 0.667, delim: {bot: 53, rep: 55}},
                   1822:     {c: '6', d: 0.6, w: 0.667, delim: {top: 50, rep: 54}},
                   1823:     {c: '7', d: 0.6, w: 0.667, delim: {top: 51, rep: 55}},
                   1824:     {c: '8', d: 0.9, w: 0.889, delim: {top: 56, mid: 60, bot: 58, rep: 62}},
                   1825:     {c: '9', d: 0.9, w: 0.889, delim: {top: 57, mid: 61, bot: 59, rep: 62}},
                   1826:     {c: ':', d: 0.9, w: 0.889, delim: {top: 56, bot: 58, rep: 62}},
                   1827:     {c: ';', d: 0.9, w: 0.889, delim: {top: 57, bot: 59, rep: 62}},
                   1828:     {c: '&#x3C;', d: 1.8, w: 0.889, delim: {rep: 63}},
                   1829:     {c: '=', d: 1.8, w: 0.889, delim: {rep: 119}},
                   1830:     {c: '&#x3E;', d: 0.3, w: 0.889, delim: {rep: 62}},
                   1831:     {c: '?', d: 0.6, w: 0.667, delim: {top: 120, bot: 121, rep: 63}},
                   1832:     // 40 - 4F
                   1833:     {c: '@', h: 0.04, d: 1.76, w: 0.875, delim: {top: 56, bot: 59, rep: 62}},
                   1834:     {c: 'A', h: 0.04, d: 1.76, w: 0.875, delim: {top: 57, bot: 58, rep: 62}},
                   1835:     {c: 'B', d: 0.6, w: 0.875, delim: {rep: 66}},
                   1836:     {c: 'C', d: 0.6, w: 0.875, delim: {rep: 67}},
                   1837:     {c: 'D', h: 0.04, d: 1.76, w: 0.611, n: 28},
                   1838:     {c: 'E', h: 0.04, d: 1.76, w: 0.611, n: 29},
                   1839:     {c: 'F', d: 1, w: 0.833, n: 71},
                   1840:     {c: 'G', h: 0.1, d: 1.5, w: 1.11},
                   1841:     {c: 'H', d: 1.11, w: 0.472, ic: 0.194, n: 73},
                   1842:     {c: 'I', d: 2.22, w: 0.556, ic: 0.444},
                   1843:     {c: 'J', d: 1, w: 1.11, n: 75},
                   1844:     {c: 'K', h: 0.1, d: 1.5, w: 1.51},
                   1845:     {c: 'L', d: 1, w: 1.11, n: 77},
                   1846:     {c: 'M', h: 0.1, d: 1.5, w: 1.51},
                   1847:     {c: 'N', d: 1, w: 1.11, n: 79},
                   1848:     {c: 'O', h: 0.1, d: 1.5, w: 1.51},
                   1849:     // 50 - 5F
                   1850:     {c: 'P', d: 1, w: 1.06, n: 88},
                   1851:     {c: 'Q', d: 1, w: 0.944, n: 89},
                   1852:     {c: 'R', d: 1.11, w: 0.472, ic: 0.194, n: 90},
                   1853:     {c: 'S', d: 1, w: 0.833, n: 91},
                   1854:     {c: 'T', d: 1, w: 0.833, n: 92},
                   1855:     {c: 'U', d: 1, w: 0.833, n: 93},
                   1856:     {c: 'V', d: 1, w: 0.833, n: 94},
                   1857:     {c: 'W', d: 1, w: 0.833, n: 95},
                   1858:     {c: 'X', h: 0.1, d: 1.5, w: 1.44},
                   1859:     {c: 'Y', h: 0.1, d: 1.5, w: 1.28},
                   1860:     {c: 'Z', d: 2.22, w: 0.556, ic: 0.444},
                   1861:     {c: '[', h: 0.1, d: 1.5, w: 1.11},
                   1862:     {c: '\\', h: 0.1, d: 1.5, w: 1.11},
                   1863:     {c: ']', h: 0.1, d: 1.5, w: 1.11},
                   1864:     {c: '^', h: 0.1, d: 1.5, w: 1.11},
                   1865:     {c: '_', h: 0.1, d: 1.5, w: 1.11},
                   1866:     // 60 - 6F
                   1867:     {c: '&#x60;', d: 1, w: 0.944, n: 97},
                   1868:     {c: 'a', h: 0.1, d: 1.5, w: 1.28},
                   1869:     {c: 'b', h: 0.722, w: 0.556, n: 99},
                   1870:     {c: 'c', h: 0.75, w: 1, n: 100},
                   1871:     {c: 'd', h: 0.75, w: 1.44},
                   1872:     {c: 'e', h: 0.722, w: 0.556, n: 102},
                   1873:     {c: 'f', h: 0.75, w: 1, n: 103},
                   1874:     {c: 'g', h: 0.75, w: 1.44},
                   1875:     {c: 'h', h: 0.04, d: 1.76, w: 0.472, n: 20},
                   1876:     {c: 'i', h: 0.04, d: 1.76, w: 0.472, n: 21},
                   1877:     {c: 'j', h: 0.04, d: 1.76, w: 0.528, n: 22},
                   1878:     {c: 'k', h: 0.04, d: 1.76, w: 0.528, n: 23},
                   1879:     {c: 'l', h: 0.04, d: 1.76, w: 0.528, n: 24},
                   1880:     {c: 'm', h: 0.04, d: 1.76, w: 0.528, n: 25},
                   1881:     {c: 'n', h: 0.04, d: 1.76, w: 0.667, n: 26},
                   1882:     {c: 'o', h: 0.04, d: 1.76, w: 0.667, n: 27},
                   1883:     // 70 - 7F
                   1884:     {c: 'p', h: 0.04, d: 1.16, w: 1, n: 113},
                   1885:     {c: 'q', h: 0.04, d: 1.76, w: 1, n: 114},
                   1886:     {c: 'r', h: 0.04, d: 2.36, w: 1, n: 115},
                   1887:     {c: 's', h: 0.04, d: 2.96, w: 1, n: 116},
                   1888:     {c: 't', d: 1.8, w: 1.06, delim: {top: 118, bot: 116, rep: 117}},
                   1889:     {c: 'u', d: 0.6, w: 1.06},
                   1890:     {c: 'v', h: 0.04, d: 0.56, w: 1.06},
                   1891:     {c: 'w', d: 0.6, w: 0.778, delim: {top: 126, bot: 127, rep: 119}},
                   1892:     {c: 'x', d: 0.6, w: 0.667, delim: {top: 120, rep: 63}},
                   1893:     {c: 'y', d: 0.6, w: 0.667, delim: {bot: 121, rep: 63}},
                   1894:     {c: 'z', h: 0.12, w: 0.45},
                   1895:     {c: '&#x7B;', h: 0.12, w: 0.45},
                   1896:     {c: '&#x7C;', h: 0.12, w: 0.45},
                   1897:     {c: '&#x7D;', h: 0.12, w: 0.45},
                   1898:     {c: '&#x7E;', d: 0.6, w: 0.778, delim: {top: 126, rep: 119}},
                   1899:     {c: '&#xC4;', d: 0.6, w: 0.778, delim: {bot: 127, rep: 119}}
                   1900:   ],
                   1901:   
                   1902:   cmti10: [
                   1903:     // 00 - 0F
                   1904:     {c: '&#xA1;', h: 0.683, w: 0.627, ic: 0.133},
                   1905:     {c: '&#xA2;', h: 0.683, w: 0.818},
                   1906:     {c: '&#xA3;', h: 0.683, w: 0.767, ic: 0.094},
                   1907:     {c: '&#xA4;', h: 0.683, w: 0.692},
                   1908:     {c: '&#xA5;', h: 0.683, w: 0.664, ic: 0.153},
                   1909:     {c: '&#xA6;', h: 0.683, w: 0.743, ic: 0.164},
                   1910:     {c: '&#xA7;', h: 0.683, w: 0.716, ic: 0.12},
                   1911:     {c: '&#xA8;', h: 0.683, w: 0.767, ic: 0.111},
                   1912:     {c: '&#xA9;', h: 0.683, w: 0.716, ic: 0.0599},
                   1913:     {c: '&#xAA;', h: 0.683, w: 0.767, ic: 0.111},
                   1914:     {c: '&#xAD;', h: 0.683, w: 0.716, ic: 0.103},
                   1915:     {c: '&#xAE;', h: 0.694, d: 0.194, w: 0.613, ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 14, '108': 15}},
                   1916:     {c: '&#xAF;', h: 0.694, d: 0.194, w: 0.562, ic: 0.103},
                   1917:     {c: '&#xB0;', h: 0.694, d: 0.194, w: 0.588, ic: 0.103},
                   1918:     {c: '&#xB1;', h: 0.694, d: 0.194, w: 0.882, ic: 0.103},
                   1919:     {c: '&#xB2;', h: 0.694, d: 0.194, w: 0.894, ic: 0.103},
                   1920:     // 10 - 1F
                   1921:     {c: '&#xB3;', h: 0.431, w: 0.307, ic: 0.0767},
                   1922:     {c: '&#xB4;', h: 0.431, d: 0.194, w: 0.332, ic: 0.0374},
                   1923:     {c: '&#xB5;', h: 0.694, w: 0.511},
                   1924:     {c: '&#xB6;', h: 0.694, w: 0.511, ic: 0.0969},
                   1925:     {c: '&#x2219;', h: 0.628, w: 0.511, ic: 0.083},
                   1926:     {c: '&#xB8;', h: 0.694, w: 0.511, ic: 0.108},
                   1927:     {c: '&#xB9;', h: 0.562, w: 0.511, ic: 0.103},
                   1928:     {c: '&#xBA;', h: 0.694, w: 0.831},
                   1929:     {c: '&#xBB;', d: 0.17, w: 0.46},
                   1930:     {c: '&#xBC;', h: 0.694, d: 0.194, w: 0.537, ic: 0.105},
                   1931:     {c: '&#xBD;', h: 0.431, w: 0.716, ic: 0.0751},
                   1932:     {c: '&#xBE;', h: 0.431, w: 0.716, ic: 0.0751},
                   1933:     {c: '&#xBF;', h: 0.528, d: 0.0972, w: 0.511, ic: 0.0919},
                   1934:     {c: '&#xC0;', h: 0.683, w: 0.883, ic: 0.12},
                   1935:     {c: '&#xC1;', h: 0.683, w: 0.985, ic: 0.12},
                   1936:     {c: '&#xC2;', h: 0.732, d: 0.0486, w: 0.767, ic: 0.094},
                   1937:     // 20 - 2F
                   1938:     {c: '&#xC3;', h: 0.431, w: 0.256, krn: {'108': -0.256, '76': -0.321}},
                   1939:     {c: '!', h: 0.694, w: 0.307, ic: 0.124, lig: {'96': 60}},
                   1940:     {c: '"', h: 0.694, w: 0.514, ic: 0.0696},
                   1941:     {c: '#', h: 0.694, d: 0.194, w: 0.818, ic: 0.0662},
                   1942:     {c: '$', h: 0.694, w: 0.769},
                   1943:     {c: '%', h: 0.75, d: 0.0556, w: 0.818, ic: 0.136},
                   1944:     {c: '&#x26;', h: 0.694, w: 0.767, ic: 0.0969},
                   1945:     {c: '\'', h: 0.694, w: 0.307, ic: 0.124, krn: {'63': 0.102, '33': 0.102}, lig: {'39': 34}},
                   1946:     {c: '(', h: 0.75, d: 0.25, w: 0.409, ic: 0.162},
                   1947:     {c: ')', h: 0.75, d: 0.25, w: 0.409, ic: 0.0369},
                   1948:     {c: '*', h: 0.75, w: 0.511, ic: 0.149},
                   1949:     {c: '+', h: 0.562, d: 0.0567, w: 0.767, ic: 0.0369},
                   1950:     {c: ',', h: 0.106, d: 0.194, w: 0.307},
                   1951:     {c: '-', h: 0.431, w: 0.358, ic: 0.0283, lig: {'45': 123}},
                   1952:     {c: '.', h: 0.106, w: 0.307},
                   1953:     {c: '/', h: 0.75, d: 0.25, w: 0.511, ic: 0.162},
                   1954:     // 30 - 3F
                   1955:     {c: '0', h: 0.644, w: 0.511, ic: 0.136},
                   1956:     {c: '1', h: 0.644, w: 0.511, ic: 0.136},
                   1957:     {c: '2', h: 0.644, w: 0.511, ic: 0.136},
                   1958:     {c: '3', h: 0.644, w: 0.511, ic: 0.136},
                   1959:     {c: '4', h: 0.644, d: 0.194, w: 0.511, ic: 0.136},
                   1960:     {c: '5', h: 0.644, w: 0.511, ic: 0.136},
                   1961:     {c: '6', h: 0.644, w: 0.511, ic: 0.136},
                   1962:     {c: '7', h: 0.644, d: 0.194, w: 0.511, ic: 0.136},
                   1963:     {c: '8', h: 0.644, w: 0.511, ic: 0.136},
                   1964:     {c: '9', h: 0.644, w: 0.511, ic: 0.136},
                   1965:     {c: ':', h: 0.431, w: 0.307, ic: 0.0582},
                   1966:     {c: ';', h: 0.431, d: 0.194, w: 0.307, ic: 0.0582},
                   1967:     {c: '&#x3C;', h: 0.5, d: 0.194, w: 0.307, ic: 0.0756},
                   1968:     {c: '=', h: 0.367, d: -0.133, w: 0.767, ic: 0.0662},
                   1969:     {c: '&#x3E;', h: 0.5, d: 0.194, w: 0.511},
                   1970:     {c: '?', h: 0.694, w: 0.511, ic: 0.122, lig: {'96': 62}},
                   1971:     // 40 - 4F
                   1972:     {c: '@', h: 0.694, w: 0.767, ic: 0.096},
                   1973:     {c: 'A', h: 0.683, w: 0.743, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
                   1974:     {c: 'B', h: 0.683, w: 0.704, ic: 0.103},
                   1975:     {c: 'C', h: 0.683, w: 0.716, ic: 0.145},
                   1976:     {c: 'D', h: 0.683, w: 0.755, ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}},
                   1977:     {c: 'E', h: 0.683, w: 0.678, ic: 0.12},
                   1978:     {c: 'F', h: 0.683, w: 0.653, ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}},
                   1979:     {c: 'G', h: 0.683, w: 0.774, ic: 0.0872},
                   1980:     {c: 'H', h: 0.683, w: 0.743, ic: 0.164},
                   1981:     {c: 'I', h: 0.683, w: 0.386, ic: 0.158},
                   1982:     {c: 'J', h: 0.683, w: 0.525, ic: 0.14},
                   1983:     {c: 'K', h: 0.683, w: 0.769, ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}},
                   1984:     {c: 'L', h: 0.683, w: 0.627, krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
                   1985:     {c: 'M', h: 0.683, w: 0.897, ic: 0.164},
                   1986:     {c: 'N', h: 0.683, w: 0.743, ic: 0.164},
                   1987:     {c: 'O', h: 0.683, w: 0.767, ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}},
                   1988:     // 50 - 5F
                   1989:     {c: 'P', h: 0.683, w: 0.678, ic: 0.103, krn: {'65': -0.0767}},
                   1990:     {c: 'Q', h: 0.683, d: 0.194, w: 0.767, ic: 0.094},
                   1991:     {c: 'R', h: 0.683, w: 0.729, ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
                   1992:     {c: 'S', h: 0.683, w: 0.562, ic: 0.12},
                   1993:     {c: 'T', h: 0.683, w: 0.716, ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}},
                   1994:     {c: 'U', h: 0.683, w: 0.743, ic: 0.164},
                   1995:     {c: 'V', h: 0.683, w: 0.743, ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}},
                   1996:     {c: 'W', h: 0.683, w: 0.999, ic: 0.184, krn: {'65': -0.0767}},
                   1997:     {c: 'X', h: 0.683, w: 0.743, ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}},
                   1998:     {c: 'Y', h: 0.683, w: 0.743, ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}},
                   1999:     {c: 'Z', h: 0.683, w: 0.613, ic: 0.145},
                   2000:     {c: '[', h: 0.75, d: 0.25, w: 0.307, ic: 0.188},
                   2001:     {c: '\\', h: 0.694, w: 0.514, ic: 0.169},
                   2002:     {c: ']', h: 0.75, d: 0.25, w: 0.307, ic: 0.105},
                   2003:     {c: '^', h: 0.694, w: 0.511, ic: 0.0665},
                   2004:     {c: '_', h: 0.668, w: 0.307, ic: 0.118},
                   2005:     // 60 - 6F
                   2006:     {c: '&#x60;', h: 0.694, w: 0.307, ic: 0.124, lig: {'96': 92}},
                   2007:     {c: 'a', h: 0.431, w: 0.511, ic: 0.0767},
                   2008:     {c: 'b', h: 0.694, w: 0.46, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
                   2009:     {c: 'c', h: 0.431, w: 0.46, ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
                   2010:     {c: 'd', h: 0.694, w: 0.511, ic: 0.103, krn: {'108': 0.0511}},
                   2011:     {c: 'e', h: 0.431, w: 0.46, ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
                   2012:     {c: 'f', h: 0.694, d: 0.194, w: 0.307, ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}},
                   2013:     {c: 'g', h: 0.431, d: 0.194, w: 0.46, ic: 0.0885},
                   2014:     {c: 'h', h: 0.694, w: 0.511, ic: 0.0767},
                   2015:     {c: 'i', h: 0.655, w: 0.307, ic: 0.102},
                   2016:     {c: 'j', h: 0.655, d: 0.194, w: 0.307, ic: 0.145},
                   2017:     {c: 'k', h: 0.694, w: 0.46, ic: 0.108},
                   2018:     {c: 'l', h: 0.694, w: 0.256, ic: 0.103, krn: {'108': 0.0511}},
                   2019:     {c: 'm', h: 0.431, w: 0.818, ic: 0.0767},
                   2020:     {c: 'n', h: 0.431, w: 0.562, ic: 0.0767, krn: {'39': -0.102}},
                   2021:     {c: 'o', h: 0.431, w: 0.511, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
                   2022:     // 70 - 7F
                   2023:     {c: 'p', h: 0.431, d: 0.194, w: 0.511, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
                   2024:     {c: 'q', h: 0.431, d: 0.194, w: 0.46, ic: 0.0885},
                   2025:     {c: 'r', h: 0.431, w: 0.422, ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
                   2026:     {c: 's', h: 0.431, w: 0.409, ic: 0.0821},
                   2027:     {c: 't', h: 0.615, w: 0.332, ic: 0.0949},
                   2028:     {c: 'u', h: 0.431, w: 0.537, ic: 0.0767},
                   2029:     {c: 'v', h: 0.431, w: 0.46, ic: 0.108},
                   2030:     {c: 'w', h: 0.431, w: 0.664, ic: 0.108, krn: {'108': 0.0511}},
                   2031:     {c: 'x', h: 0.431, w: 0.464, ic: 0.12},
                   2032:     {c: 'y', h: 0.431, d: 0.194, w: 0.486, ic: 0.0885},
                   2033:     {c: 'z', h: 0.431, w: 0.409, ic: 0.123},
                   2034:     {c: '&#x7B;', h: 0.431, w: 0.511, ic: 0.0921, lig: {'45': 124}},
                   2035:     {c: '&#x7C;', h: 0.431, w: 1.02, ic: 0.0921},
                   2036:     {c: '&#x7D;', h: 0.694, w: 0.511, ic: 0.122},
                   2037:     {c: '&#x7E;', h: 0.668, w: 0.511, ic: 0.116},
                   2038:     {c: '&#xC4;', h: 0.668, w: 0.511, ic: 0.105}
                   2039:   ],
                   2040:   
                   2041:   cmbx10: [
                   2042:     // 00 - 0F
                   2043:     {c: '&#xA1;', h: 0.686, w: 0.692},
                   2044:     {c: '&#xA2;', h: 0.686, w: 0.958},
                   2045:     {c: '&#xA3;', h: 0.686, w: 0.894},
                   2046:     {c: '&#xA4;', h: 0.686, w: 0.806},
                   2047:     {c: '&#xA5;', h: 0.686, w: 0.767},
                   2048:     {c: '&#xA6;', h: 0.686, w: 0.9},
                   2049:     {c: '&#xA7;', h: 0.686, w: 0.831},
                   2050:     {c: '&#xA8;', h: 0.686, w: 0.894},
                   2051:     {c: '&#xA9;', h: 0.686, w: 0.831},
                   2052:     {c: '&#xAA;', h: 0.686, w: 0.894},
                   2053:     {c: '&#xAD;', h: 0.686, w: 0.831},
                   2054:     {c: '&#xAE;', h: 0.694, w: 0.671, ic: 0.109, krn: {'39': 0.109, '63': 0.109, '33': 0.109, '41': 0.109, '93': 0.109}, lig: {'105': 14, '108': 15}},
                   2055:     {c: '&#xAF;', h: 0.694, w: 0.639},
                   2056:     {c: '&#xB0;', h: 0.694, w: 0.639},
                   2057:     {c: '&#xB1;', h: 0.694, w: 0.958},
                   2058:     {c: '&#xB2;', h: 0.694, w: 0.958},
                   2059:     // 10 - 1F
                   2060:     {c: '&#xB3;', h: 0.444, w: 0.319},
                   2061:     {c: '&#xB4;', h: 0.444, d: 0.194, w: 0.351},
                   2062:     {c: '&#xB5;', h: 0.694, w: 0.575},
                   2063:     {c: '&#xB6;', h: 0.694, w: 0.575},
                   2064:     {c: '&#x2219;', h: 0.632, w: 0.575},
                   2065:     {c: '&#xB8;', h: 0.694, w: 0.575},
                   2066:     {c: '&#xB9;', h: 0.596, w: 0.575},
                   2067:     {c: '&#xBA;', h: 0.694, w: 0.869},
                   2068:     {c: '&#xBB;', d: 0.17, w: 0.511},
                   2069:     {c: '&#xBC;', h: 0.694, w: 0.597},
                   2070:     {c: '&#xBD;', h: 0.444, w: 0.831},
                   2071:     {c: '&#xBE;', h: 0.444, w: 0.894},
                   2072:     {c: '&#xBF;', h: 0.542, d: 0.0972, w: 0.575},
                   2073:     {c: '&#xC0;', h: 0.686, w: 1.04},
                   2074:     {c: '&#xC1;', h: 0.686, w: 1.17},
                   2075:     {c: '&#xC2;', h: 0.735, d: 0.0486, w: 0.894},
                   2076:     // 20 - 2F
                   2077:     {c: '&#xC3;', h: 0.444, w: 0.319, krn: {'108': -0.319, '76': -0.378}},
                   2078:     {c: '!', h: 0.694, w: 0.35, lig: {'96': 60}},
                   2079:     {c: '"', h: 0.694, w: 0.603},
                   2080:     {c: '#', h: 0.694, d: 0.194, w: 0.958},
                   2081:     {c: '$', h: 0.75, d: 0.0556, w: 0.575},
                   2082:     {c: '%', h: 0.75, d: 0.0556, w: 0.958},
                   2083:     {c: '&#x26;', h: 0.694, w: 0.894},
                   2084:     {c: '\'', h: 0.694, w: 0.319, krn: {'63': 0.128, '33': 0.128}, lig: {'39': 34}},
                   2085:     {c: '(', h: 0.75, d: 0.25, w: 0.447},
                   2086:     {c: ')', h: 0.75, d: 0.25, w: 0.447},
                   2087:     {c: '*', h: 0.75, w: 0.575},
                   2088:     {c: '+', h: 0.633, d: 0.133, w: 0.894},
                   2089:     {c: ',', h: 0.156, d: 0.194, w: 0.319},
                   2090:     {c: '-', h: 0.444, w: 0.383, lig: {'45': 123}},
                   2091:     {c: '.', h: 0.156, w: 0.319},
                   2092:     {c: '/', h: 0.75, d: 0.25, w: 0.575},
                   2093:     // 30 - 3F
                   2094:     {c: '0', h: 0.644, w: 0.575},
                   2095:     {c: '1', h: 0.644, w: 0.575},
                   2096:     {c: '2', h: 0.644, w: 0.575},
                   2097:     {c: '3', h: 0.644, w: 0.575},
                   2098:     {c: '4', h: 0.644, w: 0.575},
                   2099:     {c: '5', h: 0.644, w: 0.575},
                   2100:     {c: '6', h: 0.644, w: 0.575},
                   2101:     {c: '7', h: 0.644, w: 0.575},
                   2102:     {c: '8', h: 0.644, w: 0.575},
                   2103:     {c: '9', h: 0.644, w: 0.575},
                   2104:     {c: ':', h: 0.444, w: 0.319},
                   2105:     {c: ';', h: 0.444, d: 0.194, w: 0.319},
                   2106:     {c: '&#x3C;', h: 0.5, d: 0.194, w: 0.35},
                   2107:     {c: '=', h: 0.391, d: -0.109, w: 0.894},
                   2108:     {c: '&#x3E;', h: 0.5, d: 0.194, w: 0.543},
                   2109:     {c: '?', h: 0.694, w: 0.543, lig: {'96': 62}},
                   2110:     // 40 - 4F
                   2111:     {c: '@', h: 0.694, w: 0.894},
                   2112:     {c: 'A', h: 0.686, w: 0.869, krn: {'116': -0.0319, '67': -0.0319, '79': -0.0319, '71': -0.0319, '85': -0.0319, '81': -0.0319, '84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}},
                   2113:     {c: 'B', h: 0.686, w: 0.818},
                   2114:     {c: 'C', h: 0.686, w: 0.831},
                   2115:     {c: 'D', h: 0.686, w: 0.882, krn: {'88': -0.0319, '87': -0.0319, '65': -0.0319, '86': -0.0319, '89': -0.0319}},
                   2116:     {c: 'E', h: 0.686, w: 0.756},
                   2117:     {c: 'F', h: 0.686, w: 0.724, krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}},
                   2118:     {c: 'G', h: 0.686, w: 0.904},
                   2119:     {c: 'H', h: 0.686, w: 0.9},
                   2120:     {c: 'I', h: 0.686, w: 0.436, krn: {'73': 0.0319}},
                   2121:     {c: 'J', h: 0.686, w: 0.594},
                   2122:     {c: 'K', h: 0.686, w: 0.901, krn: {'79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}},
                   2123:     {c: 'L', h: 0.686, w: 0.692, krn: {'84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}},
                   2124:     {c: 'M', h: 0.686, w: 1.09},
                   2125:     {c: 'N', h: 0.686, w: 0.9},
                   2126:     {c: 'O', h: 0.686, w: 0.864, krn: {'88': -0.0319, '87': -0.0319, '65': -0.0319, '86': -0.0319, '89': -0.0319}},
                   2127:     // 50 - 5F
                   2128:     {c: 'P', h: 0.686, w: 0.786, krn: {'65': -0.0958, '111': -0.0319, '101': -0.0319, '97': -0.0319, '46': -0.0958, '44': -0.0958}},
                   2129:     {c: 'Q', h: 0.686, d: 0.194, w: 0.864},
                   2130:     {c: 'R', h: 0.686, w: 0.862, krn: {'116': -0.0319, '67': -0.0319, '79': -0.0319, '71': -0.0319, '85': -0.0319, '81': -0.0319, '84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}},
                   2131:     {c: 'S', h: 0.686, w: 0.639},
                   2132:     {c: 'T', h: 0.686, w: 0.8, krn: {'121': -0.0319, '101': -0.0958, '111': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.0958, '117': -0.0958}},
                   2133:     {c: 'U', h: 0.686, w: 0.885},
                   2134:     {c: 'V', h: 0.686, w: 0.869, ic: 0.016, krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}},
                   2135:     {c: 'W', h: 0.686, w: 1.19, ic: 0.016, krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}},
                   2136:     {c: 'X', h: 0.686, w: 0.869, krn: {'79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}},
                   2137:     {c: 'Y', h: 0.686, w: 0.869, ic: 0.0287, krn: {'101': -0.0958, '111': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.0958, '117': -0.0958}},
                   2138:     {c: 'Z', h: 0.686, w: 0.703},
                   2139:     {c: '[', h: 0.75, d: 0.25, w: 0.319},
                   2140:     {c: '\\', h: 0.694, w: 0.603},
                   2141:     {c: ']', h: 0.75, d: 0.25, w: 0.319},
                   2142:     {c: '^', h: 0.694, w: 0.575},
                   2143:     {c: '_', h: 0.694, w: 0.319},
                   2144:     // 60 - 6F
                   2145:     {c: '&#x60;', h: 0.694, w: 0.319, lig: {'96': 92}},
                   2146:     {c: 'a', h: 0.444, w: 0.559, krn: {'118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}},
                   2147:     {c: 'b', h: 0.694, w: 0.639, krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}},
                   2148:     {c: 'c', h: 0.444, w: 0.511, krn: {'104': -0.0319, '107': -0.0319}},
                   2149:     {c: 'd', h: 0.694, w: 0.639},
                   2150:     {c: 'e', h: 0.444, w: 0.527},
                   2151:     {c: 'f', h: 0.694, w: 0.351, ic: 0.109, krn: {'39': 0.109, '63': 0.109, '33': 0.109, '41': 0.109, '93': 0.109}, lig: {'105': 12, '102': 11, '108': 13}},
                   2152:     {c: 'g', h: 0.444, d: 0.194, w: 0.575, ic: 0.016, krn: {'106': 0.0319}},
                   2153:     {c: 'h', h: 0.694, w: 0.639, krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}},
                   2154:     {c: 'i', h: 0.694, w: 0.319},
                   2155:     {c: 'j', h: 0.694, d: 0.194, w: 0.351},
                   2156:     {c: 'k', h: 0.694, w: 0.607, krn: {'97': -0.0639, '101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}},
                   2157:     {c: 'l', h: 0.694, w: 0.319},
                   2158:     {c: 'm', h: 0.444, w: 0.958, krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}},
                   2159:     {c: 'n', h: 0.444, w: 0.639, krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}},
                   2160:     {c: 'o', h: 0.444, w: 0.575, krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}},
                   2161:     // 70 - 7F
                   2162:     {c: 'p', h: 0.444, d: 0.194, w: 0.639, krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}},
                   2163:     {c: 'q', h: 0.444, d: 0.194, w: 0.607},
                   2164:     {c: 'r', h: 0.444, w: 0.474},
                   2165:     {c: 's', h: 0.444, w: 0.454},
                   2166:     {c: 't', h: 0.635, w: 0.447, krn: {'121': -0.0319, '119': -0.0319}},
                   2167:     {c: 'u', h: 0.444, w: 0.639, krn: {'119': -0.0319}},
                   2168:     {c: 'v', h: 0.444, w: 0.607, ic: 0.016, krn: {'97': -0.0639, '101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}},
                   2169:     {c: 'w', h: 0.444, w: 0.831, ic: 0.016, krn: {'101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}},
                   2170:     {c: 'x', h: 0.444, w: 0.607},
                   2171:     {c: 'y', h: 0.444, d: 0.194, w: 0.607, ic: 0.016, krn: {'111': -0.0319, '101': -0.0319, '97': -0.0319, '46': -0.0958, '44': -0.0958}},
                   2172:     {c: 'z', h: 0.444, w: 0.511},
                   2173:     {c: '&#x7B;', h: 0.444, w: 0.575, ic: 0.0319, lig: {'45': 124}},
                   2174:     {c: '&#x7C;', h: 0.444, w: 1.15, ic: 0.0319},
                   2175:     {c: '&#x7D;', h: 0.694, w: 0.575},
                   2176:     {c: '&#x7E;', h: 0.694, w: 0.575},
                   2177:     {c: '&#xC4;', h: 0.694, w: 0.575}
                   2178:   ]
1.2     ! albertel 2179: };
        !          2180: 
        !          2181: /***************************************************************************/
        !          2182: 
        !          2183: /*
        !          2184:  *  Implement image-based fonts for fallback method
        !          2185:  */
        !          2186: jsMath.Img = {
        !          2187:   
        !          2188:   // font sizes available
        !          2189:   fonts: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249, 298, 358, 430],
        !          2190:     
        !          2191:   // em widths for the various font size directories
        !          2192:   w: {'50': 6.9, '60': 8.3, '70': 9.7, '85': 11.8, '100': 13.9,
        !          2193:       '120': 16.7, '144': 20.0, '173': 24.0, '207': 28.8, '249': 34.6,
        !          2194:       '298': 41.4, '358': 49.8, '430': 59.8},
        !          2195:         
        !          2196:   // index of best font size in the fonts list
        !          2197:   best: 4,
        !          2198:     
        !          2199:   // fonts to update (see UpdateFonts below)
        !          2200:   update: {},
        !          2201:     
        !          2202:   // factor by which to shrink images (for better printing)
        !          2203:   factor: 1,
        !          2204:   
        !          2205:   // image fonts are loaded
        !          2206:   loaded: 0,
        !          2207:   
        !          2208:   // add characters to be drawn using images
        !          2209:   SetFont: function (change) {
        !          2210:     for (var font in change) {
        !          2211:       if (!this.update[font]) {this.update[font] = []}
        !          2212:       this.update[font] = this.update[font].concat(change[font]);
        !          2213:     }
        !          2214:   },
        !          2215: 
        !          2216:   /*
        !          2217:    *  Called by the exta-font definition files to add an image font
        !          2218:    *  into the mix
        !          2219:    */
        !          2220:   AddFont: function (size,def) {
        !          2221:     if (!jsMath.Img[size]) {jsMath.Img[size] = {}};
        !          2222:     jsMath.Add(jsMath.Img[size],def);
        !          2223:   },
        !          2224:     
        !          2225:   /*
        !          2226:    *  Update font(s) to use image data rather than native fonts
        !          2227:    *  It looks in the jsMath.Img.update array to find the names
        !          2228:    *  of the fonts to udpate, and the arrays of character codes
        !          2229:    *  to set (or 'all' to change every character);
        !          2230:    */
        !          2231:   UpdateFonts: function () {
        !          2232:     var change = this.update; if (!this.loaded) return;
        !          2233:     var best = this[jsMath.Img.fonts[this.best]];
        !          2234:     for (var font in change) {
        !          2235:       for (var i = 0; i < change[font].length; i++) {
        !          2236:         var c = change[font][i];
        !          2237:         if (c == 'all') {for (c in jsMath.TeX[font]) {jsMath.TeX[font][c].img = {}}}
        !          2238:           else {jsMath.TeX[font][c].img = {}}
        !          2239:       }
        !          2240:     }
        !          2241:     this.update = {};
        !          2242:   },
        !          2243:   
        !          2244:   /*
        !          2245:    *  Find the font size that best fits our current font
        !          2246:    *  (this is the directory name for the img files used
        !          2247:    *  in some fallback modes).
        !          2248:    */
        !          2249:   BestSize: function () {
        !          2250:     var w = jsMath.em * this.factor;
        !          2251:     var m = this.w[this.fonts[0]];
        !          2252:     for (var i = 1; i < this.fonts.length; i++) {
        !          2253:       if (w < (this.w[this.fonts[i]] + 2*m) / 3) {return i-1}
        !          2254:       m = this.w[this.fonts[i]];
        !          2255:     }
        !          2256:     return i-1;
        !          2257:   },
        !          2258: 
        !          2259:   /*
        !          2260:    *  Get the scaling factor for the image fonts
        !          2261:    */
        !          2262:   Scale: function () {
        !          2263:     if (!this.loaded) return;
        !          2264:     this.best = this.BestSize();
        !          2265:     this.em = jsMath.Img.w[this.fonts[this.best]];
        !          2266:     this.scale = (jsMath.em/this.em);
        !          2267:     if (Math.abs(this.scale - 1) < .12) {this.scale = 1}
        !          2268:   },
        !          2269: 
        !          2270:   /*
        !          2271:    *  Get URL to directory for given font and size, based on the
        !          2272:    *  user's alpha/plain setting
        !          2273:    */
        !          2274:   URL: function (name,size,C) {
        !          2275:     var type = (jsMath.Controls.cookie.alpha) ? '/alpha/': '/plain/';
        !          2276:     if (C == null) {C = "def.js"} else {C = 'char'+C+'.png'}
        !          2277:     if (size != "") {size += '/'}
        !          2278:     return this.root+name+type+size+C;
        !          2279:   },
        !          2280: 
        !          2281:   /*
        !          2282:    *  Laod the data for an image font
        !          2283:    */
        !          2284:   LoadFont: function (name) {
        !          2285:     if (jsMath.Controls.cookie.print) {
        !          2286:       jsMath.Controls.cookie.print = 0;
        !          2287:       var button = jsMath.Element("jsMath");
        !          2288:       if (button) {button.style.display = "none"}
        !          2289:       this.factor *= 3;
        !          2290:       if (window.location.protocol != 'file:') {jsMath.Controls.SetCookie(0)}
        !          2291:       if (jsMath.Browser.alphaPrintBug) {jsMath.Controls.cookie.alpha = 0}
        !          2292:     }
        !          2293:     document.writeln('<SCRIPT SRC="'+this.URL(name,"")+'"></SCRIPT>');
        !          2294:     this.loaded = 1;
        !          2295:   }
        !          2296:   
        !          2297: };
1.1       albertel 2298: 
                   2299: /***************************************************************************/
                   2300: 
                   2301: /*
                   2302:  *  jsMath.HTML handles creation of most of the HTML needed for
                   2303:  *  presenting mathematics in HTML pages.
                   2304:  */
                   2305: 
                   2306: jsMath.HTML = {
                   2307:   
                   2308:   /*
                   2309:    *  produce a string version of a measurement in ems,
                   2310:    *  showing only a limited number of digits, and 
                   2311:    *  using 0 when the value is near zero.
                   2312:    */
                   2313:   Em: function (m) {
                   2314:     var n = 5; if (m < 0) {n++}
                   2315:     if (Math.abs(m) < .000001) {m = 0}
                   2316:     var s = String(m); s = s.replace(/(\.\d\d\d).+/,'$1');
                   2317:     return s+'em'
                   2318:   },
                   2319: 
                   2320:   /*
                   2321:    *  Create a horizontal space of width w
                   2322:    */
                   2323:   Spacer: function (w) {
                   2324:     if (w == 0) {return ''};
1.2     ! albertel 2325:     return jsMath.Browser.msieSpaceFix
        !          2326:       + '<SPAN STYLE="margin-left: '
        !          2327:       +    this.Em(w-jsMath.Browser.spaceWidth)+'">'
        !          2328:       + jsMath.Browser.hiddenSpace + '</SPAN>';
1.1       albertel 2329:   },
                   2330: 
                   2331:   /*
                   2332:    *  Create a colored frame (for debugging use)
                   2333:    */
                   2334:   Frame: function (x,y,w,h,c,pos) {
                   2335: 
                   2336:     h -= 2/jsMath.em; // use 2 pixels to compensate for border size
                   2337:     w -= 2/jsMath.em;
                   2338:     y -= 1/jsMath.em;
                   2339:     if (!c) {c = 'black'};
                   2340:     if (pos) {pos = 'absolute;'} else
                   2341:              {pos = 'relative; margin-right: '+this.Em(-(w+2/jsMath.em))+'; '}
                   2342:     return '<IMG SRC="'+jsMath.blank+'" STYLE="position:' + pos
                   2343:              + 'vertical-align: '+this.Em(y)+'; left: '+this.Em(x)+'; '
1.2     ! albertel 2344:              + 'width:' +this.Em(w*jsMath.Browser.imgScale)+'; '
        !          2345:              + 'height:'+this.Em(h*jsMath.Browser.imgScale)+'; '
        !          2346:              + 'border: 1px solid '+c+';">';
1.1       albertel 2347:   },
                   2348: 
                   2349:   /*
1.2     ! albertel 2350:    *  Create a rule line for fractions, etc.
1.1       albertel 2351:    *  Height is converted to pixels (with a minimum of 1), so that
                   2352:    *    the line will not disappear at small font sizes.  This means that
                   2353:    *    the thickness will not change if you change the font size, or
                   2354:    *    may not be correct within a header or other enlarged text.
                   2355:    */
                   2356:   Rule: function (w,h) {
                   2357:     if (h == null) {h = jsMath.TeX.default_rule_thickness}
                   2358:     if (w == 0 || h == 0) return;  // should make an invisible box?
1.2     ! albertel 2359:     w *= jsMath.Browser.imgScale;
        !          2360:     h = Math.round(h*jsMath.em*jsMath.Browser.imgScale+.25);
        !          2361:     if (h < 1) {h = 1};
1.1       albertel 2362:     return '<IMG SRC="'+jsMath.blank+'" HSPACE="0" VSPACE="0" '
1.2     ! albertel 2363:               + 'STYLE="width:'+this.Em(w)+'; height:1px; '
        !          2364:               + 'vertical-align:-1px; '
        !          2365:               + 'border:0px none; border-top:'+h+'px solid">';
1.1       albertel 2366:   },
1.2     ! albertel 2367:   
1.1       albertel 2368:   /*
                   2369:    *  Add a <SPAN> tag to activate a specific CSS class
                   2370:    */
                   2371:   Class: function (tclass,html) {
                   2372:     return '<SPAN CLASS="'+tclass+'">'+html+'</SPAN>';
                   2373:   },
                   2374:   
                   2375:   /*
                   2376:    *  Use a <SPAN> to place some HTML at a specific position.
                   2377:    *  (This can be replaced by the ones below to overcome
                   2378:    *   some browser-specific bugs.)
                   2379:    */
                   2380:   Place: function (html,x,y) {
                   2381:     if (Math.abs(x) < .0001) {x = 0}
                   2382:     if (Math.abs(y) < .0001) {y = 0}
                   2383:     if (x || y) {
                   2384:       var span = '<SPAN STYLE="position: relative;';
                   2385:       if (x) {span += ' margin-left:'+this.Em(x)+';'}
                   2386:       if (y) {span += ' top:'+this.Em(-y)+';'}
                   2387:       html = span + '">' + html + '</SPAN>';
                   2388:     }
                   2389:     return html;
                   2390:   },
                   2391:   
                   2392:   /*
                   2393:    *  For MSIE on Windows, backspacing must be done in a separate
1.2     ! albertel 2394:    *  <SPAN>, otherwise the contents will be clipped.  Netscape
        !          2395:    *  also doesn't combine vertical and horizontal spacing well.
        !          2396:    *  Here the x and y positioning are done in separate <SPAN> tags
1.1       albertel 2397:    */
                   2398:   PlaceSeparateSkips: function (html,x,y) {
                   2399:     if (Math.abs(x) < .0001) {x = 0}
                   2400:     if (Math.abs(y) < .0001) {y = 0}
                   2401:     if (y) {html = '<SPAN STYLE="position: relative; top:'+this.Em(-y)+';'
                   2402:                        + '">' + html + '</SPAN>'}
1.2     ! albertel 2403:     if (x) {html = jsMath.Browser.msieSpaceFix 
        !          2404:                        + '<SPAN STYLE="margin-left:'
        !          2405:                        +    this.Em(x-jsMath.Browser.spaceWidth)+';">'
        !          2406:                        +  jsMath.Browser.hiddenSpace + '</SPAN>' + html}
1.1       albertel 2407:     return html;
                   2408:   },
                   2409:   
                   2410:   /*
                   2411:    *  Place a SPAN with absolute coordinates
                   2412:    */
                   2413:   PlaceAbsolute: function (html,x,y) {
                   2414:     if (Math.abs(x) < .0001) {x = 0}
                   2415:     if (Math.abs(y) < .0001) {y = 0}
                   2416:     html = '<SPAN STYLE="position: absolute; left:'+this.Em(x)+'; '
                   2417:               + 'top:'+this.Em(y)+';">' + html + '&nbsp;</SPAN>';
                   2418:               //  space normalizes line height
                   2419:     return html;
                   2420:   },
                   2421: 
                   2422:   Absolute: function(html,w,h,d,y,H) {
                   2423:     var align = "";
1.2     ! albertel 2424:     if (d && d != "none") {align = ' vertical-align: '+jsMath.HTML.Em(-d)+';'}
1.1       albertel 2425:     if (y != "none") {
                   2426:       if (Math.abs(y) < .0001) {y = 0}
                   2427:       html = '<SPAN STYLE="position: absolute; '
                   2428:                + 'top:'+jsMath.HTML.Em(y)+'; left: 0em;">'
                   2429:                + html + '&nbsp;' // space normalizes line height in script styles
                   2430:              + '</SPAN>';
                   2431:     }
1.2     ! albertel 2432:     html += '<IMG SRC="'+jsMath.blank+'" STYLE="'
        !          2433:               + 'width:' +jsMath.HTML.Em(w*jsMath.Browser.imgScale)+'; '
        !          2434:               + 'height:'+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+';'+align+'">';
        !          2435:     if (jsMath.Browser.msieAbsoluteBug) {           // for MSIE (Mac)
1.1       albertel 2436:       html = '<SPAN STYLE="position: relative;">' + html + '</SPAN>';
                   2437:     }
                   2438:     html =   '<SPAN STYLE="position: relative;'
1.2     ! albertel 2439:            +     ' width: '+jsMath.HTML.Em(w)+';'   // for MSIE
1.1       albertel 2440:            +     ' height: '+jsMath.HTML.Em(H)+';'  // for MSIE
1.2     ! albertel 2441:            +     jsMath.Browser.msieInlineBlockFix  // for MSIE
1.1       albertel 2442:            +     '">'
                   2443:            +   html
                   2444:            + '</SPAN>';
                   2445:     return html;
                   2446:   }
                   2447: 
                   2448: };
                   2449: 
                   2450: 
                   2451: /***************************************************************************/
                   2452: 
                   2453: /*
                   2454:  *  jsMath.Box handles TeX's math boxes and jsMath's equivalent of hboxes.
                   2455:  */
                   2456: 
                   2457: jsMath.Box = function (format,text,w,h,d) {
                   2458:   if (d == null) {d = jsMath.d}
                   2459:   this.type = 'typeset';
                   2460:   this.w = w; this.h = h; this.d = d; this.bh = h; this.bd = d;
                   2461:   this.x = 0; this.y = 0;
                   2462:   this.html = text; this.format = format;
                   2463: };
                   2464: 
                   2465: 
                   2466: jsMath.Add(jsMath.Box,{
                   2467: 
                   2468:   /*
                   2469:    *  An empty box
                   2470:    */
                   2471:   Null: new jsMath.Box('null','',0,0,0),
                   2472: 
                   2473:   /*
                   2474:    *  A box containing only text whose class and style haven't been added
                   2475:    *  yet (so that we can combine ones with the same styles).  It gets
                   2476:    *  the text dimensions, if needed.  (In general, this has been
                   2477:    *  replaced by TeX() below, but is still used in fallback mode.)
                   2478:    */
                   2479:   Text: function (text,tclass,style,size,a,d) {
                   2480:     var html = jsMath.Typeset.AddClass(tclass,text);
                   2481:         html = jsMath.Typeset.AddStyle(style,size,html);
                   2482:     var BB = jsMath.EmBoxFor(html); var TeX = jsMath.Typeset.TeX(style,size);
                   2483:     var bd = ((tclass == 'cmsy10' || tclass == 'cmex10')? BB.h-TeX.h: TeX.d*BB.h/TeX.hd);
                   2484:     var box = new jsMath.Box('text',text,BB.w,BB.h-bd,bd);
                   2485:     box.style = style; box.size = size; box.tclass = tclass;
                   2486:     if (d != null) {if (d != 1) {box.d = d}} else {box.d = 0}
                   2487:     if (a == null || a == 1) {box.h = .9*TeX.M_height}
                   2488:       else {box.h = 1.1*TeX.x_height + 1*a}; // sometimes a is a string?
                   2489:     return box;
                   2490:   },
                   2491: 
                   2492:   /*
                   2493:    *  Produce a box containing a given TeX character from a given font.
                   2494:    *  The box is a text box (like the ones above), so that characters from
                   2495:    *  the same font can be combined.
                   2496:    */
1.2     ! albertel 2497:   TeX: function (C,font,style,size) {
        !          2498:     var c = jsMath.TeX[font][C];
1.1       albertel 2499:     if (c.d == null) {c.d = 0}; if (c.h == null) {c.h = 0}
1.2     ! albertel 2500:     if (c.img != null && c.c != '') this.TeXIMG(font,C,jsMath.Typeset.StyleSize(style,size));
1.1       albertel 2501:     var scale = jsMath.Typeset.TeX(style,size).scale;
                   2502:     var h = c.h + jsMath.TeX[font].dh
                   2503:     var box = new jsMath.Box('text',c.c,c.w*scale,h*scale,c.d*scale);
                   2504:     box.style = style; box.size = size;
                   2505:     if (c.tclass) {
                   2506:       box.tclass = c.tclass;
                   2507:       box.bh = scale*jsMath.h;
                   2508:       box.bd = scale*jsMath.d;
                   2509:     } else {
                   2510:       box.tclass = font;
                   2511:       box.bh = scale*jsMath.TeX[font].h;
                   2512:       box.bd = scale*jsMath.TeX[font].d;
1.2     ! albertel 2513:       if (jsMath.Browser.msieFontBug) {
1.1       albertel 2514:         // hack to avoid Font changing back to the default
                   2515:         // font when a unicode reference is not followed
                   2516:         // by a letter or number
                   2517:         box.html += '<SPAN STYLE="display: none">x</SPAN>'
                   2518:       }
                   2519:     }
1.2     ! albertel 2520:     if (c.img != null) {
        !          2521:       box.bh = c.img.bh; box.bd = c.img.bd;
        !          2522:       box.tclass = "normal";
        !          2523:     }
1.1       albertel 2524:     return box;
                   2525:   },
1.2     ! albertel 2526:   
        !          2527:   /*
        !          2528:    *  Set the character's string to the appropriate image file
        !          2529:    */
        !          2530:   TeXIMG: function (font,C,size) {
        !          2531:     var c = jsMath.TeX[font][C];
        !          2532:     if (c.img.size != null && c.img.size == size &&
        !          2533:         c.img.best != null && c.img.best == jsMath.Img.best) return;
        !          2534:     var mustScale = (jsMath.Img.scale != 1);
        !          2535:     var id = jsMath.Img.best + size - 4;
        !          2536:     if (id < 0) {id = 0; mustScale = 1} else
        !          2537:     if (id >= jsMath.Img.fonts.length) {id = jsMath.Img.fonts.length-1; mustScale = 1}
        !          2538:     var imgFont = jsMath.Img[jsMath.Img.fonts[id]];
        !          2539:     var img = imgFont[font][C];
        !          2540:     var scale = 1/jsMath.Img.w[jsMath.Img.fonts[id]];
        !          2541:     if (id != jsMath.Img.best + size - 4) {
        !          2542:       if (c.w != null) {scale = c.w/img[0]} else {
        !          2543:         scale *= jsMath.Img.fonts[size]/jsMath.Img.fonts[4]
        !          2544:               *  jsMath.Img.fonts[jsMath.Img.best]/jsMath.Img.fonts[id];
        !          2545:       }
        !          2546:     }
        !          2547:     var w = img[0]*scale; var h = img[1]*scale; var d = -img[2]*scale; var v;
        !          2548:     var wadjust = (c.w == null || Math.abs(c.w-w) < .01)? "" : " margin-right:"+jsMath.HTML.Em(c.w-w)+';';
        !          2549:     var resize = ""; C = this.HexCode(C);
        !          2550:     if (!mustScale && !jsMath.Controls.cookie.scaleImg) {
        !          2551:       if (2*w < h || (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha))
        !          2552:          {resize = "height:"+(img[1]*jsMath.Browser.imgScale)+'px;'}
        !          2553:       resize += " width:"+(img[0]*jsMath.Browser.imgScale)+'px;'
        !          2554:       v = -img[2]+'px';
        !          2555:     } else {
        !          2556:       if (2*w < h || (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha))
        !          2557:          {resize = "height:"+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+';'}
        !          2558:       resize += " width:"+jsMath.HTML.Em(w*jsMath.Browser.imgScale)+';'
        !          2559:       v = jsMath.HTML.Em(d);
        !          2560:     }
        !          2561:     var vadjust = (Math.abs(d) < .01 && !jsMath.Browser.valignBug)?
        !          2562:                          "": " vertical-align:"+v+';';
        !          2563:     var URL = jsMath.Img.URL(font,jsMath.Img.fonts[id],C);
        !          2564:     if (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha) {
        !          2565:       c.c = '<IMG SRC="'+jsMath.blank+'" '
        !          2566:                + 'STYLE="'+jsMath.Browser.msieCenterBugFix
        !          2567:                + resize + vadjust + wadjust
        !          2568:                + ' filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + "'"
        !          2569:                + URL + "', sizingMethod='scale'" + ');">';
        !          2570:     } else {
        !          2571:       c.c = '<IMG SRC="'+URL+'" STYLE="'+jsMath.Browser.msieCenterBugFix
        !          2572:                   + resize + vadjust + wadjust + '">';
        !          2573:     }
        !          2574:     c.tclass = "normal";
        !          2575:     c.img.bh = h+d; c.img.bd = -d;
        !          2576:     c.img.size = size; c.img.best = jsMath.Img.best;
        !          2577:   },
        !          2578:   
        !          2579:   /*
        !          2580:    *  Get a two-character hex code (some browsers don't know toString(16))
        !          2581:    */
        !          2582:   HexCode: function (C) {
        !          2583:     var codes = '0123456789ABCDEF';
        !          2584:     var h = Math.floor(C/16); var l = C - 16*h;
        !          2585:     return codes.charAt(h)+codes.charAt(l);
        !          2586:   },
1.1       albertel 2587: 
                   2588:   /*
                   2589:    *  A box containing a spacer of a specific width
                   2590:    */
                   2591:   Space: function (w) {
                   2592:     return new jsMath.Box('html',jsMath.HTML.Spacer(w),w,0,0);
                   2593:   },
                   2594: 
                   2595:   /*
                   2596:    *  A box containing a horizontal rule
                   2597:    */
                   2598:   Rule: function (w,h) {
                   2599:     if (h == null) {h = jsMath.TeX.default_rule_thickness}
                   2600:     html = jsMath.HTML.Rule(w,h);
                   2601:     return new jsMath.Box('html',html,w,h,0);
                   2602:   },
                   2603: 
                   2604:   /*
                   2605:    *  Get a character from a TeX font, and make sure that it has
                   2606:    *  its metrics specified.
                   2607:    */
                   2608:   GetChar: function (code,font) {
                   2609:     var c = jsMath.TeX[font][code];
1.2     ! albertel 2610:     if (c.img != null) {this.TeXIMG(font,code,4)}
1.1       albertel 2611:     if (c.tclass == null) {c.tclass = font}
                   2612:     if (!c.computedW) {
                   2613:       c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w;
                   2614:       if (c.h == null) {c.h = jsMath.defaultH}; if (c.d == null) {c.d = 0}
                   2615:       c.computedW = 1;
                   2616:     }
                   2617:     return c;
                   2618:   },
                   2619:   
                   2620:   /*
                   2621:    *  Locate the TeX delimiter character that matches a given height.
                   2622:    *  Return the character, font, style and actual height used.
                   2623:    */
                   2624:   DelimBestFit: function (H,c,font,style) {
                   2625:     if (c == 0 && font == 0) return;
                   2626:     var C; var h; font = jsMath.TeX.fam[font];
                   2627:     var isSS = (style.charAt(1) == 'S');
                   2628:     var isS  = (style.charAt(0) == 'S');
                   2629:     while (c != null) {
                   2630:       C = jsMath.TeX[font][c];
                   2631:       if (C.h == null) {C.h = jsMath.defaultH}; if (C.d == null) {C.d = 0}
                   2632:       h = C.h+C.d;
                   2633:       if (C.delim) {return [c,font,'',H]}
                   2634:       if (isSS && .5*h >= H) {return [c,font,'SS',.5*h]}
                   2635:       if (isS  && .7*h >= H) {return [c,font,'S',.7*h]}
                   2636:       if (h >= H || C.n == null) {return [c,font,'T',h]}
                   2637:       c = C.n
                   2638:     }
                   2639:   },
                   2640:   
                   2641:   /*
                   2642:    *  Create the HTML needed for a stretchable delimiter of a given height,
                   2643:    *  either centered or not.  This version uses relative placement (i.e.,
                   2644:    *  backspaces, not line-breaks).  This works with more browsers, but
                   2645:    *  if the font size changes, the backspacing may not be right, so the
                   2646:    *  delimiters may become jagged.
                   2647:    */
                   2648:   DelimExtendRelative: function (H,c,font,a,nocenter) {
                   2649:     var C = jsMath.TeX[font][c];
                   2650:     var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font);
                   2651:     var rep = this.GetChar(C.delim.rep,font);
                   2652:     var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font);
                   2653:     var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c);
                   2654:     var w = rep.w; var h = rep.h+rep.d
                   2655:     var y; var dx;
                   2656:     if (C.delim.mid) {// braces
                   2657:       var mid = this.GetChar(C.delim.mid,font);
                   2658:       var n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d)-(bot.h+bot.d))/(2*(rep.h+rep.d)));
                   2659:       H = 2*n*(rep.h+rep.d) + (top.h+top.d) + (mid.h+mid.d) + (bot.h+bot.d);
                   2660:       if (nocenter) {y = 0} else {y = H/2+a}; var Y = y;
                   2661:       var html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)
                   2662:                + jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(top.w+bot.w)/2,y-(H-bot.d))
                   2663:                + jsMath.HTML.Place(jsMath.Typeset.AddClass(mid.tclass,mid.c),-(bot.w+mid.w)/2,y-(H+mid.h-mid.d)/2);
                   2664:       dx = (w-mid.w)/2; if (Math.abs(dx) < .0001) {dx = 0}
                   2665:       if (dx) {html += jsMath.HTML.Spacer(dx)}
                   2666:       y -= top.h+top.d + rep.h;
                   2667:       for (var i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}
                   2668:       y -= H/2 - rep.h/2;
                   2669:       for (var i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}
                   2670:     } else {// everything else
                   2671:       var n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d))/(rep.h+rep.d));
                   2672:       // make sure two-headed arrows have an extender
                   2673:       if (top.h+top.d < .9*(rep.h+rep.d)) {n = Math.max(1,n)}
                   2674:       H = n*(rep.h+rep.d) + (top.h+top.d) + (bot.h+bot.d);
                   2675:       if (nocenter) {y = 0} else {y = H/2+a}; var Y = y;
                   2676:       var html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)
                   2677:       dx = (w-top.w)/2; if (Math.abs(dx) < .0001) {dx = 0}
                   2678:       if (dx) {html += jsMath.HTML.Spacer(dx)}
                   2679:       y -= top.h+top.d + rep.h;
                   2680:       for (var i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}
                   2681:       html += jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(w+bot.w)/2,Y-(H-bot.d));
                   2682:     }
                   2683:     if (nocenter) {h = top.h} else {h = H/2+a}
                   2684:     var box = new jsMath.Box('html',html,rep.w,h,H-h);
                   2685:     box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;
                   2686:     return box;
                   2687:   },
                   2688: 
                   2689:   /*
                   2690:    *  Create the HTML needed for a stretchable delimiter of a given height,
                   2691:    *  either centered or not.  This version uses absolute placement (i.e.,
                   2692:    *  line-breaks, not backspacing).  This gives more reliable results,
                   2693:    *  but doesn't work with all browsers.
                   2694:    */
                   2695:   DelimExtendAbsolute: function (H,c,font,a,nocenter) {
                   2696:     var Font = jsMath.TeX[font];
                   2697:     var C = Font[c];
                   2698:     var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font);
                   2699:     var rep = this.GetChar(C.delim.rep,font);
                   2700:     var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font);
                   2701:     
                   2702:     if (C.delim.mid) {// braces
                   2703:       var mid = this.GetChar(C.delim.mid,font);
                   2704:       var n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d-.05)-(bot.h+bot.d-.05))/(2*(rep.h+rep.d-.05)));
                   2705:       H = 2*n*(rep.h+rep.d-.05) + (top.h+top.d) + (mid.h+mid.d-.05) + (bot.h+bot.d-.05);
                   2706:       
                   2707:       html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0);
                   2708:       var h = rep.h+rep.d - .05; var y = top.d-.05 + rep.h;
                   2709:       var ext = jsMath.Typeset.AddClass(font,rep.c)
                   2710:       for (var i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}
                   2711:       html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(mid.tclass,mid.c),0,y+n*h-rep.h+mid.h);
                   2712:       y += n*h + mid.h+mid.d - .05;
                   2713:       for (var i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}
                   2714:       html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h);
                   2715:     } else {// all others
                   2716:       var n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d-.05))/(rep.h+rep.d-.05));
                   2717:       H = n*(rep.h+rep.d-.05) + (top.h+top.d) + (bot.h+bot.d-.05);
                   2718: 
                   2719:       html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0);
                   2720:       var h = rep.h+rep.d-.05; var y = top.d-.05 + rep.h;
                   2721:       var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c);
                   2722:       for (var i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}
                   2723:       html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h);
                   2724:     }
                   2725:     
                   2726:     var w = top.w;
                   2727:     if (nocenter) {h = top.h; y = 0} else {h = H/2 + a; y = h - top.h}
                   2728:     html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y,top.h);
                   2729:     var box = new jsMath.Box('html',html,rep.w,h,H-h);
                   2730:     box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;
                   2731:     return box;
                   2732:   },
                   2733:   
                   2734:   /*
                   2735:    *  Get the HTML for a given delimiter of a given height.
                   2736:    *  It will return either a single character, if one exists, or the
                   2737:    *  more complex HTML needed for a stretchable delimiter.
                   2738:    */
                   2739:   Delimiter: function (H,delim,style,nocenter) {
                   2740:     var size = 4;  //### pass this?
                   2741:     var TeX = jsMath.Typeset.TeX(style,size);
1.2     ! albertel 2742:     if (!delim) {return this.Space(TeX.nulldelimiterspace)}
        !          2743:     var CFSH = this.DelimBestFit(H,delim[2],delim[1],style);
1.1       albertel 2744:     if (CFSH == null || CFSH[3] < H) 
1.2     ! albertel 2745:       {CFSH = this.DelimBestFit(H,delim[4],delim[3],style)}
1.1       albertel 2746:     if (CFSH == null) {return this.Space(TeX.nulldelimiterspace)}
                   2747:     if (CFSH[2] == '')
                   2748:       {return this.DelimExtend(H,CFSH[0],CFSH[1],TeX.axis_height,nocenter)}
                   2749:     box = jsMath.Box.TeX(CFSH[0],CFSH[1],CFSH[2],size).Styled();
                   2750:     if (nocenter) {box.y = -jsMath.TeX[CFSH[1]].dh*TeX.scale}
                   2751:       else {box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height)}
                   2752:     if (Math.abs(box.y) < .0001) {box.y = 0}
                   2753:     if (box.y) {box = jsMath.Box.SetList([box],CFSH[2],size)}
                   2754:     return box;
                   2755:   },
                   2756:   
                   2757:   /*
                   2758:    *  Get a character by its TeX charcode, and make sure its width
                   2759:    *  is specified.
                   2760:    */
                   2761:   GetCharCode: function (code) {
1.2     ! albertel 2762:     var font = jsMath.TeX.fam[code[0]];
1.1       albertel 2763:     var Font = jsMath.TeX[font];
1.2     ! albertel 2764:     var c = Font[code[1]];
        !          2765:     if (c.img != null) {this.TeXIMG(font,code[1],4)}
1.1       albertel 2766:     if (c.w == null) {c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w}
                   2767:     if (c.font == null) {c.font = font}
                   2768:     return c;
                   2769:   },
                   2770: 
                   2771:   /*
                   2772:    * Add the class to the html, and use the font if there isn't one
                   2773:    * specified already
                   2774:    */
                   2775: 
                   2776:   AddClass: function (tclass,html,font) {
                   2777:     if (tclass == null) {tclass = font}
                   2778:     return jsMath.Typeset.AddClass(tclass,html);
                   2779:   },
                   2780:   
                   2781:   /*
                   2782:    *  Create a horizontally stretchable "delimiter" (like over- and
                   2783:    *  underbraces).
                   2784:    */
                   2785: //###  Add size?
                   2786:   Leaders: function (W,leader) {
                   2787:     var h; var d; var w; var html; var font;
                   2788:     if (leader.lmid) {// braces
1.2     ! albertel 2789:       font = jsMath.TeX.fam[leader.left[0]];
1.1       albertel 2790:       var left = this.GetCharCode(leader.left);
                   2791:       var right = this.GetCharCode(leader.right);
                   2792:       var lmid = this.GetCharCode(leader.lmid);
                   2793:       var rmid = this.GetCharCode(leader.rmid);
                   2794:       w = (W - left.w - right.w - lmid.w - rmid.w)/2 - .1; h = .4; d = .3;
                   2795:       if (w < 0) {w = 0}
                   2796:       html = this.AddClass(left.tclass,left.c,left.font) 
                   2797:            + jsMath.HTML.Rule(w,left.h)
                   2798:            + this.AddClass(lmid.tclass,lmid.c+rmid.c,lmid.font)
                   2799:            + jsMath.HTML.Rule(w,right.h)
                   2800:            + this.AddClass(right.tclass,right.c,right.font);
                   2801:     } else { //arrows
1.2     ! albertel 2802:       font = jsMath.TeX.fam[leader.rep[0]];
1.1       albertel 2803:       var left = this.GetCharCode(leader.left? leader.left: leader.rep);
                   2804:       var rep = this.GetCharCode(leader.rep);
                   2805:       var right = this.GetCharCode(leader.right? leader.right: leader.rep);
                   2806:       var n = Math.ceil((W - left.w - right.w + .4)/(rep.w - .3));
                   2807:       w = (W - left.w - right.w + .4 - n*(rep.w - .3));
                   2808:       if (leader.left) {h = left.h; d = left.d} else {h = right.h; d = right.d}
                   2809:       if (d == null) {d = 0}; if (h == null) {h = 0}
                   2810:       var html = this.AddClass(left.tclass,left.c,left.font); var m = Math.floor(n/2);
                   2811:       var ext = jsMath.HTML.Place(rep.c,-.3,0);
                   2812:       var ehtml = ''; for (var i = 0; i < m; i++) {ehtml += ext};
                   2813:       html += this.AddClass(rep.tclass,ehtml,rep.font) + jsMath.HTML.Spacer(w);
                   2814:       ehtml = ''; for (var i = m; i < n; i++) {ehtml += ext};
                   2815:       html += this.AddClass(rep.tclass,ehtml,rep.font);
1.2     ! albertel 2816:       if (jsMath.Browser.msieFontBug) {html += '<SPAN STYLE="display: none">x</SPAN>'}
1.1       albertel 2817:       html += jsMath.HTML.Place(this.AddClass(right.tclass,right.c,right.font),-.4,0);
                   2818:     }
                   2819:     w = jsMath.EmBoxFor(html).w;
                   2820:     if (w != W) {
                   2821:       w = jsMath.HTML.Spacer((W-w)/2);
                   2822:       html = w + html + w;
                   2823:     }
                   2824:     var box = new jsMath.Box('html',html,W,h,d);
                   2825:     box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;
                   2826:     return box;
                   2827:   },
                   2828:   
                   2829:   /*
                   2830:    *  Create the HTML for an alignment (e.g., array or matrix)
                   2831:    *  Since the widths are not really accurate (they are based on pixel
                   2832:    *  widths not the sub-pixel widths of the actual characters), there
                   2833:    *  is some drift involved.  We lay out the table column by column
                   2834:    *  to help reduce the problem.
                   2835:    *  
                   2836:    *  ###  still need to allow users to specify row and column attributes,
                   2837:    *       and do things like \span and \multispan  ###
                   2838:    */
                   2839:   LayoutRelative: function (size,table,align,cspacing) {
                   2840:     if (align == null) {align = []}
                   2841:     if (cspacing == null) {cspacing = []}
                   2842:     
                   2843:     // get row and column maximum dimensions
                   2844:     var scale = jsMath.sizes[size]/100;
                   2845:     var W = []; var H = []; var D = [];
                   2846:     var unset = -1000; var bh = unset; var bd = unset;
                   2847:     var i; var j; var row;
                   2848:     for (i = 0; i < table.length; i++) {
                   2849:       row = table[i]; H[i] = jsMath.h*scale; D[i] = jsMath.d*scale;
                   2850:       for (j = 0; j < row.length; j++) {
                   2851:         row[j] = row[j].Remeasured();
                   2852:         if (row[j].h > H[i]) {H[i] = row[j].h}
                   2853:         if (row[j].d > D[i]) {D[i] = row[j].d}
                   2854:         if (j >= W.length) {W[j] = row[j].w}
                   2855:         else if (row[j].w > W[j]) {W[j] = row[j].w}
                   2856:         if (row[j].bh > bh) {bh = row[j].bh}
                   2857:         if (row[j].bd > bd) {bd = row[j].bd}
                   2858:       }
                   2859:     }
                   2860:     if (bh == unset) {bh = 0}; if (bd == unset) {bd = 0}
                   2861: 
                   2862:     // lay out the columns
                   2863:     var HD = (jsMath.hd-.01)*scale;
                   2864:     var html = ''; var pW = 0; var cW = 0;
                   2865:     var w; var h; var y;
                   2866:     var box; var mlist; var entry;
                   2867:     for (j = 0; j < W.length; j++) {
                   2868:       mlist = []; y = -H[0]; pW = 0;
                   2869:       for (i = 0; i < table.length; i++) {
                   2870:         entry = table[i][j];
                   2871:         if (entry && entry.format != 'null') {
                   2872:           if (align[j] == 'l') {w = 0} else
                   2873:           if (align[j] == 'r') {w = W[j] - entry.w} else
                   2874:             {w = (W[j] - entry.w)/2}
                   2875:           entry.x = w - pW; pW = entry.w + w; entry.y = y;
                   2876:           mlist[mlist.length] = entry;
                   2877:         }
                   2878:         if (i == table.length-1) {y -= D[i]}
                   2879:         else {y -= Math.max(HD,D[i]+H[i+1]) + scale/10}
                   2880:       }
                   2881:       if (cspacing[j] == null) cspacing[j] = scale;
                   2882:       if (mlist.length > 0) {
                   2883:         box = jsMath.Box.SetList(mlist,'T',size);
                   2884:         html += jsMath.HTML.Place(box.html,cW,0);
                   2885:         cW = W[j] - box.w + cspacing[j];
                   2886:       } else {cW += cspacing[j]}
                   2887:     }
                   2888:     
                   2889:     // get the full width and height
                   2890:     w = -cspacing[W.length-1]; y = (H.length-1)*scale/10;
                   2891:     for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]}
                   2892:     for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i])}
                   2893:     h = y/2 + jsMath.TeX.axis_height; var d = y-h;
                   2894:     
                   2895:     // adjust the final row width, and vcenter the table
                   2896:     //   (add 1/6em at each side for the \,)
                   2897:     html += jsMath.HTML.Spacer(cW-cspacing[W.length-1] + scale/6);
                   2898:     html = jsMath.HTML.Place(html,scale/6,h);
                   2899:     box = new jsMath.Box('html',html,w+scale/3,h,d);
                   2900:     box.bh = bh; box.bd = bd;
                   2901:     return box;
                   2902:   },
                   2903: 
                   2904:   /*
                   2905:    *  Create the HTML for an alignment (e.g., array or matrix)
                   2906:    *  Use absolute position for elements in the array.
                   2907:    *  
                   2908:    *  ###  still need to allow users to specify row and column attributes,
                   2909:    *       and do things like \span and \multispan  ###
                   2910:    */
                   2911:   LayoutAbsolute: function (size,table,align,cspacing) {
                   2912:     if (align == null) {align = []}
                   2913:     if (cspacing == null) {cspacing = []}
                   2914:     
                   2915:     // get row and column maximum dimensions
                   2916:     var scale = jsMath.sizes[size]/100;
                   2917:     var HD = (jsMath.hd-.01)*scale;
                   2918:     var W = []; var H = []; var D = [];
                   2919:     var w = 0; var h; var x; var y;
                   2920:     var i; var j; var row;
                   2921:     for (i = 0; i < table.length; i++) {
                   2922:       row = table[i];
                   2923:       H[i] = jsMath.h*scale; D[i] = jsMath.d*scale;
                   2924:       for (j = 0; j < row.length; j++) {
                   2925:         row[j] = row[j].Remeasured();
                   2926:         if (row[j].h > H[i]) {H[i] = row[j].h}
                   2927:         if (row[j].d > D[i]) {D[i] = row[j].d}
                   2928:         if (j >= W.length) {W[j] = row[j].w}
                   2929:         else if (row[j].w > W[j]) {W[j] = row[j].w}
                   2930:       }
                   2931:     }
                   2932: 
                   2933:     // get the height and depth of the centered table
                   2934:     y = (H.length-1)*scale/6;
                   2935:     for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i])}
                   2936:     h = y/2 + jsMath.TeX.axis_height; var d = y - h;
                   2937: 
                   2938:     // lay out the columns
                   2939:     var html = ''; var entry; w = scale/6;
                   2940:     for (j = 0; j < W.length; j++) {
                   2941:       y = H[0]-h;
                   2942:       for (i = 0; i < table.length; i++) {
                   2943:         entry = table[i][j];
                   2944:         if (entry && entry.format != 'null') {
                   2945:           if (align[j] == 'l') {x = 0} else
                   2946:           if (align[j] == 'r') {x = W[j] - entry.w} else
                   2947:             {x = (W[j] - entry.w)/2}
                   2948:           html += jsMath.HTML.PlaceAbsolute(entry.html,w+x,
                   2949:                     y-Math.max(0,entry.bh-jsMath.h*scale));
                   2950:         }
                   2951:         if (i == table.length-1) {y += D[i]}
                   2952:         else {y += Math.max(HD,D[i]+H[i+1]) + scale/6}
                   2953:       }
                   2954:       if (cspacing[j] == null) cspacing[j] = scale;
                   2955:       w += W[j] + cspacing[j];
                   2956:     }
                   2957:     
                   2958:     // get the full width
                   2959:     w = -cspacing[W.length-1]+scale/3;
                   2960:     for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]}
                   2961: 
                   2962:     html = jsMath.HTML.Spacer(scale/6)+html+jsMath.HTML.Spacer(scale/6);
1.2     ! albertel 2963:     if (jsMath.Browser.spanHeightVaries) {y = h-jsMath.h} else {y = 0}
1.1       albertel 2964:     html = jsMath.HTML.Absolute(html,w,h+d,d,y,H[0]);
                   2965:     var box = new jsMath.Box('html',html,w+scale/3,h,d);
                   2966:     return box;
                   2967:   },
                   2968: 
                   2969:   /*
                   2970:    *  Look for math within \hbox and other non-math text
                   2971:    */
                   2972:   InternalMath: function (text,size) {
1.2     ! albertel 2973:     if (!text.match(/\$|\\\(/)) {return this.Text(text,'normal','T',size).Styled()}
1.1       albertel 2974:     
                   2975:     var i = 0; var k = 0; var c; var match = '';
                   2976:     var mlist = []; var parse; var html; var box;
                   2977:     while (i < text.length) {
                   2978:       c = text.charAt(i++);
                   2979:       if (c == '$') {
                   2980:         if (match == '$') {
                   2981:           parse = jsMath.Parse(text.slice(k,i-1),null,size);
                   2982:           if (parse.error) {
                   2983:             mlist[mlist.length] = this.Text(parse.error,'error','T',size,1,1);
                   2984:           } else {
                   2985:             parse.Atomize();
                   2986:             mlist[mlist.length] = parse.mlist.Typeset('T',size).Styled();
                   2987:           }
                   2988:           match = ''; k = i;
                   2989:         } else {
1.2     ! albertel 2990:           mlist[mlist.length] = this.Text(text.slice(k,i-1),'normal','T',size,1,1);
1.1       albertel 2991:           match = '$'; k = i;
                   2992:         }
                   2993:       } else if (c == '\\') {
                   2994:         c = text.charAt(i++);
                   2995:         if (c == '(' && match == '') {
1.2     ! albertel 2996:           mlist[mlist.length] = this.Text(text.slice(k,i-2),'normal','T',size,1,1);
1.1       albertel 2997:           match = ')'; k = i;
                   2998:         } else if (c == ')' && match == ')') {
                   2999:           parse = jsMath.Parse(text.slice(k,i-2),null,size);
                   3000:           if (parse.error) {
                   3001:             mlist[mlist.length] = this.Text(parse.error,'error','T',size,1,1);
                   3002:           } else {
                   3003:             parse.Atomize();
                   3004:             mlist[mlist.length] = parse.mlist.Typeset('T',size).Styled();
                   3005:           }
                   3006:           match = ''; k = i;
                   3007:         }
                   3008:       }
                   3009:     }
1.2     ! albertel 3010:     mlist[mlist.length] = this.Text(text.slice(k),'normal','T',size,1,1);
1.1       albertel 3011:     return this.SetList(mlist,'T',size);
                   3012:   },
                   3013:   
                   3014:   /*
                   3015:    *  Convert an abitrary box to a typeset box.  I.e., make an
                   3016:    *  HTML version of the contents of the box, at its desired (x,y)
                   3017:    *  position.
                   3018:    */
                   3019:   Set: function (box,style,size,addstyle) {
                   3020:     if (box) {
                   3021:       if (box.type == 'typeset') {return box}
                   3022:       if (box.type == 'mlist') {
                   3023:         box.mlist.Atomize(style,size);
                   3024:         return box.mlist.Typeset(style,size);
                   3025:       }
                   3026:       if (box.type == 'text') {
                   3027:         box = this.Text(box.text,box.tclass,style,size,box.ascend,box.descend);
                   3028:         if (addstyle != 0) {box.Styled()}
                   3029:         return box;
                   3030:       }
                   3031:       box = this.TeX(box.c,box.font,style,size);
                   3032:       if (addstyle != 0) {box.Styled()}
                   3033:       return box;
                   3034:     }
                   3035:     return jsMath.Box.Null;
                   3036:   },
                   3037: 
                   3038:   /*
                   3039:    *  Convert a list of boxes to a single typeset box.  I.e., finalize
                   3040:    *  the HTML for the list of boxes, properly spaced and positioned.
                   3041:    */
                   3042:   SetList: function (boxes,style,size) {
                   3043:     var mlist = []; var box;
                   3044:     for (var i = 0; i < boxes.length; i++) {
                   3045:       box = boxes[i];
                   3046:       if (box.type == 'typeset') {box = jsMath.mItem.Typeset(box)}
                   3047:       mlist[mlist.length] = box;
                   3048:     }
                   3049:     var typeset = new jsMath.Typeset(mlist);
                   3050:     return typeset.Typeset(style,size);
                   3051:   }
                   3052: 
                   3053: });
                   3054: 
                   3055: 
                   3056: jsMath.Package(jsMath.Box,{
                   3057: 
                   3058:   /*
                   3059:    *  Add the class and style to a text box (i.e., finalize the
                   3060:    *  unpositioned HTML for the box).
                   3061:    */
                   3062:   Styled: function () {
                   3063:     if (this.format == 'text') {
                   3064:       this.html = jsMath.Typeset.AddClass(this.tclass,this.html);
                   3065:       this.html = jsMath.Typeset.AddStyle(this.style,this.size,this.html);
                   3066:       delete this.tclass; delete this.style;
                   3067:       this.format = 'html';
                   3068:     }
                   3069:     return this;
                   3070:   },
                   3071:   
                   3072:   /*
                   3073:    *  Recompute the box width to make it more accurate.
                   3074:    */
                   3075:   Remeasured: function () {
1.2     ! albertel 3076:     if (this.w > 0 && !this.html.match(/position: ?absolute/))
        !          3077:       {this.w = jsMath.EmBoxFor(this.html).w}
1.1       albertel 3078:     return this;
                   3079:   }
                   3080: 
                   3081: });
                   3082: 
                   3083: 
                   3084: /***************************************************************************/
                   3085: 
                   3086: /*
1.2     ! albertel 3087:  *  mItems are the building blocks of mLists (math lists) used to
1.1       albertel 3088:  *  store the information about a mathematical expression.  These are
                   3089:  *  basically the items listed in the TeXbook in Appendix G (plus some
                   3090:  *  minor extensions).
                   3091:  */
                   3092: jsMath.mItem = function (type,def) {
                   3093:   this.type = type;
                   3094:   jsMath.Add(this,def);
                   3095: }
                   3096: 
                   3097: jsMath.Add(jsMath.mItem,{
                   3098: 
                   3099:   /*
                   3100:    *  a general atom (given a nucleus for the atom)
                   3101:    */
                   3102:   Atom: function (type,nucleus) {
                   3103:     return new jsMath.mItem(type,{atom: 1, nuc: nucleus});
                   3104:   },
                   3105: 
                   3106:   /*
                   3107:    *  An atom whose nucleus is a piece of text, in a given
                   3108:    *  class, with a given additional height and depth
                   3109:    */
                   3110:   TextAtom: function (type,text,tclass,a,d) {
                   3111:     var atom = new jsMath.mItem(type,{
                   3112:       atom: 1,
                   3113:       nuc: {
                   3114:         type: 'text',
                   3115:         text: text,
                   3116:         tclass: tclass
                   3117:       }
                   3118:     });
                   3119:     if (a != null) {atom.nuc.ascend = a}
                   3120:     if (d != null) {atom.nuc.descend = d}
                   3121:     return atom;
                   3122:   },
                   3123:   
                   3124:   /*
                   3125:    *  An atom whose nucleus is a TeX character in a specific font
                   3126:    */
                   3127:   TeXAtom: function (type,c,font) {
                   3128:     return new jsMath.mItem(type,{
                   3129:       atom: 1,
                   3130:       nuc: {
                   3131:         type: 'TeX',
                   3132:         c: c,
                   3133:         font: font
                   3134:       }
                   3135:     });
                   3136:   },
                   3137: 
                   3138:   /*
                   3139:    *  A generalized fraction atom, with given delimiters, rule
                   3140:    *  thickness, and a numerator and denominator.
                   3141:    */
                   3142:   Fraction: function (name,num,den,thickness,left,right) {
                   3143:     return new jsMath.mItem('fraction',{
                   3144:       from: name, num: num, den: den,
                   3145:       thickness: thickness, left: left, right: right
                   3146:     });
                   3147:   },
                   3148: 
                   3149:   /*
                   3150:    *  An atom that inserts some glue
                   3151:    */
                   3152:   Space: function (w) {return new jsMath.mItem('space',{w: w})},
                   3153: 
                   3154:   /*
                   3155:    *  An atom that contains a typeset box (like an hbox or vbox)
                   3156:    */
                   3157:   Typeset: function (box) {return new jsMath.mItem('box',{nuc: box})},
                   3158:   
                   3159:   /*
                   3160:    *  An atom that contains some finished HTML (acts like a typeset box)
                   3161:    */
                   3162:   HTML: function (html) {return new jsMath.mItem('html',{html: html})}
                   3163: 
                   3164: });
                   3165: 
                   3166: /***************************************************************************/
                   3167: 
                   3168: /*
                   3169:  *  mLists are lists of mItems, and encode the contents of
                   3170:  *  mathematical expressions and sub-expressions.  They act as
                   3171:  *  the expression "stack" as the mathematics is parsed, and
                   3172:  *  contain some state information, like the position of the
                   3173:  *  most recent open paren and \over command, and the current font.
                   3174:  */
                   3175: jsMath.mList = function (list,font,size,style) {
                   3176:   if (list) {this.mlist = list} else {this.mlist = []}
                   3177:   if (style == null) {style = 'T'}; if (size == null) {size = 4}
                   3178:   this.data = {openI: null, overI: null, overF: null,
                   3179:                font: font, size: size, style: style};
                   3180:   this.init = {size: size, style: style};
                   3181: }
                   3182: 
                   3183: jsMath.Package(jsMath.mList,{
                   3184: 
                   3185:   /*
                   3186:    *  Add an mItem to the list
                   3187:    */
                   3188:   Add: function (box) {return (this.mlist[this.mlist.length] = box)},
                   3189:   
                   3190:   /*
                   3191:    *  Get the i-th mItem from the list
                   3192:    */
                   3193:   Get: function (i) {return this.mlist[i]},
                   3194:   
                   3195:   /*
                   3196:    *  Get the length of the list
                   3197:    */
                   3198:   Length: function() {return this.mlist.length},
                   3199: 
                   3200:   /*
                   3201:    *  Get the tail mItem of the list
                   3202:    */
                   3203:   Last: function () {
                   3204:     if (this.mlist.length == 0) {return null}
                   3205:     return this.mlist[this.mlist.length-1]
                   3206:   },
                   3207: 
                   3208:   /*
                   3209:    *  Get a sublist of an mList
                   3210:    */
                   3211:   Range: function (i,j) {
                   3212:     if (j == null) {j = this.mlist.length}
                   3213:     return new jsMath.mList(this.mlist.slice(i,j+1));
                   3214:   },
                   3215: 
                   3216:   /*
                   3217:    *  Remove a range of mItems from the list.
                   3218:    */
                   3219:   Delete: function (i,j) {
                   3220:     if (j == null) {j = i}
                   3221:     if (this.mlist.splice) {this.mlist.splice(i,j-i+1)} else {
                   3222:       var mlist = [];
                   3223:       for (var k = 0; k < this.mlist.length; k++)
                   3224:         {if (k < i || k > j) {mlist[mlist.length] = this.mlist[k]}}
                   3225:       this.mlist = mlist;
                   3226:     }
                   3227:   },
                   3228: 
                   3229:   /*
                   3230:    *  Add an open brace and maintain the stack information
                   3231:    *  about the previous open brace so we can recover it
                   3232:    *  when this one os closed.
                   3233:    */
                   3234:   Open: function (left) {
                   3235:     var box = this.Add(new jsMath.mItem('boundary',{data: this.data}));
                   3236:     var olddata = this.data;
                   3237:     this.data = {}; for (var i in olddata) {this.data[i] = olddata[i]}
                   3238:     delete this.data.overI; delete this.data.overF;
                   3239:     this.data.openI = this.mlist.length-1;
                   3240:     if (left != null) {box.left = left}
                   3241:     return box;
                   3242:   },
                   3243: 
                   3244:   /*
                   3245:    *  Attempt to close a brace.  Recover the stack information
                   3246:    *  about previous open braces and \over commands.  If there was an
                   3247:    *  \over (or \above, etc) in this set of braces, create a fraction
                   3248:    *  atom from the two halves, otherwise create an inner or ord
                   3249:    *  from the contents of the braces.
                   3250:    *  Remove the braced material from the list and add the newly
                   3251:    *  created atom (the fraction, inner or ord).
                   3252:    */
                   3253:   Close: function (right) {
                   3254:     if (right != null) {right = new jsMath.mItem('boundary',{right: right})}
                   3255:     var atom; var open = this.data.openI;
                   3256:     var over = this.data.overI; var from = this.data.overF;
                   3257:     this.data  = this.mlist[open].data;
                   3258:     if (over) {
                   3259:       atom = jsMath.mItem.Fraction(from.name,
                   3260:         {type: 'mlist', mlist: this.Range(open+1,over-1)},
                   3261:         {type: 'mlist', mlist: this.Range(over)},
                   3262:         from.thickness,from.left,from.right);
                   3263:       if (right) {
                   3264:         var mlist = new jsMath.mList([this.mlist[open],atom,right]);
                   3265:         atom = jsMath.mItem.Atom('inner',{type: 'mlist', mlist: mlist});
                   3266:       }
                   3267:     } else {
                   3268:       var openI = open+1; if (right) {this.Add(right); openI--}
                   3269:       atom = jsMath.mItem.Atom((right)?'inner':'ord',
                   3270:                   {type: 'mlist', mlist: this.Range(openI)});
                   3271:     }
                   3272:     this.Delete(open,this.Length());
                   3273:     return this.Add(atom);
                   3274:   },
                   3275: 
                   3276:   /*
                   3277:    *  Create a generalized fraction from an mlist that
                   3278:    *  contains an \over (or \above, etc).
                   3279:    */
                   3280:   Over: function () {
                   3281:     var over = this.data.overI; var from = this.data.overF
                   3282:     var atom = jsMath.mItem.Fraction(from.name,
                   3283:       {type: 'mlist', mlist: this.Range(open+1,over-1)},
                   3284:       {type: 'mlist', mlist: this.Range(over)},
                   3285:       from.thickness,from.left,from.right);
                   3286:     this.mlist = [atom];
                   3287:   },
                   3288: 
                   3289:   /*
                   3290:    *  Take a raw mList (that has been produced by parsing some TeX
                   3291:    *  expression), and perform the modifications outlined in
                   3292:    *  Appendix G of the TeXbook.  
                   3293:    */
                   3294:   Atomize: function (style,size) {
                   3295:     var mitem; var prev = '';
                   3296:     this.style = style; this.size = size;
                   3297:     for (var i = 0; i < this.mlist.length; i++) {
                   3298:       mitem = this.mlist[i]; mitem.delta = 0;
                   3299:       if (mitem.type == 'choice') 
                   3300:         {this.mlist = this.Atomize.choice(this.style,mitem,i,this.mlist); i--}
                   3301:       else if (this.Atomize[mitem.type]) {
                   3302:         var f = this.Atomize[mitem.type]; // Opera needs separate name
                   3303:         f(this.style,this.size,mitem,prev,this,i);
                   3304:       }
                   3305:       prev = mitem;
                   3306:     }
                   3307:     if (mitem && mitem.type == 'bin') {mitem.type = 'ord'}
                   3308:     if (this.mlist.length >= 2 && mitem.type == 'boundary' &&
                   3309:         this.mlist[0].type == 'boundary') {this.AddDelimiters(style,size)}
                   3310:   },
                   3311: 
                   3312:   /*
                   3313:    *  For a list that has boundary delimiters as its first and last
                   3314:    *  entries, we replace the boundary atoms by open and close
1.2     ! albertel 3315:    *  atoms whose nuclii are the specified delimiters properly sized
1.1       albertel 3316:    *  for the contents of the list.  (Rule 19)
                   3317:    */
                   3318:   AddDelimiters: function(style,size) {
                   3319:     var unset = -10000; var h = unset; var d = unset;
                   3320:     for (var i = 0; i < this.mlist.length; i++) {
                   3321:       mitem = this.mlist[i];
                   3322:       if (mitem.atom || mitem.type == 'box') {
                   3323:         h = Math.max(h,mitem.nuc.h+mitem.nuc.y);
                   3324:         d = Math.max(d,mitem.nuc.d-mitem.nuc.y);
                   3325:       }
                   3326:     }
                   3327:     var TeX = jsMath.TeX; var a = jsMath.Typeset.TeX(style,size).axis_height;
                   3328:     var delta = Math.max(h-a,d+a);
                   3329:     var H =  Math.max(Math.floor(TeX.integer*delta/500)*TeX.delimiterfactor,
                   3330:                       TeX.integer*(2*delta-TeX.delimitershortfall))/TeX.integer;
                   3331:     var left = this.mlist[0]; var right = this.mlist[this.mlist.length-1];
                   3332:     left.nuc = jsMath.Box.Delimiter(H,left.left,style);
                   3333:     right.nuc = jsMath.Box.Delimiter(H,right.right,style);
                   3334:     left.type = 'open'; left.atom = 1; delete left.left;
                   3335:     right.type = 'close'; right.atom = 1; delete right.right;
                   3336:   },
                   3337:   
                   3338:   /*
                   3339:    *  Typeset a math list to produce final HTML for the list.
                   3340:    */
                   3341:   Typeset: function (style,size) {
                   3342:     var typeset = new jsMath.Typeset(this.mlist);
                   3343:     return typeset.Typeset(style,size);
                   3344:   }
                   3345: 
                   3346: });
                   3347: 
                   3348: 
                   3349: /*
                   3350:  *  These routines implement the main rules given in Appendix G of the
                   3351:  *  TeXbook
                   3352:  */
                   3353: 
                   3354: jsMath.Add(jsMath.mList.prototype.Atomize,{
                   3355: 
                   3356:   /*
                   3357:    *  Handle a 4-way choice atom.  (Rule 4)
                   3358:    */
                   3359:   choice: function (style,mitem,i,mlist) {
                   3360:     if (style.charAt(style.length-1) == "'") {style = style.slice(0,style.length-1)}
                   3361:     var nlist = []; var M = mitem[style]; if (!M) {M = {type: 'mlist', mlist: []}}
                   3362:     if (M.type == 'mlist') {
                   3363:       M = M.mlist.mlist;
                   3364:       for (var k = 0; k < i; k++) {nlist[k] = mlist[k]}
                   3365:       for (k = 0; k < M.length; k++) {nlist[i+k] = M[k]}
                   3366:       for (k = i+1; k < mlist.length; k++) {nlist[nlist.length] = mlist[k]}
                   3367:       return nlist;
                   3368:     } else {
                   3369:       mlist[i] = jsMath.mItem.Atom('ord',M);
                   3370:       return mlist;
                   3371:     }
                   3372:   },
                   3373:   
                   3374:   /*
                   3375:    *  Handle \displaystyle, \textstyle, etc.
                   3376:    */
                   3377:   style: function (style,size,mitem,prev,mlist) {
                   3378:     mlist.style = mitem.style;
                   3379:   },
                   3380:   
                   3381:   /*
                   3382:    *  Handle \tiny, \small, etc.
                   3383:    */
                   3384:   size: function (style,size,mitem,prev,mlist) {
                   3385:     mlist.size = mitem.size;
                   3386:   },
                   3387:   
                   3388:   /*
                   3389:    *  Create empty boxes of the proper sizes for the various
                   3390:    *  phantom-type commands
                   3391:    */
                   3392:   phantom: function (style,size,mitem) {
                   3393:     var box = mitem.nuc = jsMath.Box.Set(mitem.phantom,style,size);
                   3394:     if (mitem.h) {box.Remeasured(); box.html = jsMath.HTML.Spacer(box.w)}
                   3395:       else {box.html = '', box.w = 0}
                   3396:     if (!mitem.v) {box.h = box.d = 0}
                   3397:     box.bd = box.bh = 0;
                   3398:     delete mitem.phantom;
                   3399:     mitem.type = 'box';
                   3400:   },
                   3401:   
                   3402:   /*
                   3403:    *  Create a box of zero height and depth containing the
                   3404:    *  contents of the atom
                   3405:    */
                   3406:   smash: function (style,size,mitem) {
                   3407:     var box = mitem.nuc = jsMath.Box.Set(mitem.smash,style,size).Remeasured();
                   3408:     box.h = box.d = box.bd = box.bh = 0;
                   3409:     delete mitem.smash;
                   3410:     mitem.type = 'box';
                   3411:   },
                   3412: 
                   3413:   /*
                   3414:    *  Move a box up or down vertically
                   3415:    */
                   3416:   raise: function (style,size,mitem) {
                   3417:     mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size);
                   3418:     var y = mitem.raise;
                   3419:     mitem.nuc.html = jsMath.HTML.Place(mitem.nuc.html,0,y);
                   3420:     mitem.nuc.h += y; mitem.nuc.d -= y;
                   3421:     mitem.type = 'ord'; mitem.atom = 1;
                   3422:   },
                   3423: 
                   3424:   /*
                   3425:    *  Hide the size of a box so that it laps to the left or right, or
                   3426:    *  up or down.
                   3427:    */
                   3428:   lap: function (style,size,mitem) {
                   3429:     var box = jsMath.Box.Set(mitem.nuc,style,size).Remeasured();
                   3430:     var mlist = [box];
                   3431:     if (mitem.lap == 'llap') {box.x = -box.w} else
                   3432:     if (mitem.lap == 'rlap') {mlist[1] = jsMath.mItem.Space(-box.w)} else
                   3433:     if (mitem.lap == 'ulap') {box.y = box.d; box.h = box.d = 0} else
                   3434:     if (mitem.lap == 'dlap') {box.y = -box.h; box.h = box.d = 0}
                   3435:     mitem.nuc = jsMath.Box.SetList(mlist,style,size);
                   3436:     if (mitem.lap == 'ulap' || mitem.lap == 'dlap') {mitem.nuc.h = mitem.nuc.d = 0}
                   3437:     mitem.type = 'box'; delete mitem.atom;
                   3438:   },
                   3439: 
                   3440:   /*
                   3441:    *  Handle a Bin atom. (Rule 5)
                   3442:    */
                   3443:   bin: function (style,size,mitem,prev) {
                   3444:     if (prev) {
                   3445:       var type  = prev.type;
                   3446:       if (type == 'bin' || type == 'op' || type == 'rel' ||
                   3447:           type == 'open' || type == 'punct' || type == '' ||
                   3448:           (type == 'boundary' && prev.left != '')) {mitem.type = 'ord'}
                   3449:     } else {mitem.type = 'ord'}
                   3450:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3451:   },
                   3452: 
                   3453:   /*
                   3454:    *  Handle a Rel atom.  (Rule 6)
                   3455:    */
                   3456:   rel: function (style,size,mitem,prev) {
                   3457:     if (prev.type == 'bin') {prev.type = 'ord'}
                   3458:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3459:   },
                   3460: 
                   3461:   /*
                   3462:    *  Handle a Close atom.  (Rule 6)
                   3463:    */
                   3464:   close: function (style,size,mitem,prev) {
                   3465:     if (prev.type == 'bin') {prev.type = 'ord'}
                   3466:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3467:   },
                   3468: 
                   3469:   /*
                   3470:    *  Handle a Punct atom.  (Rule 6)
                   3471:    */
                   3472:   punct: function (style,size,mitem,prev) {
                   3473:     if (prev.type == 'bin') {prev.type = 'ord'}
                   3474:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3475:   },
                   3476: 
                   3477:   /*
                   3478:    *  Handle an Open atom.  (Rule 7)
                   3479:    */
                   3480:   open: function (style,size,mitem) {
                   3481:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3482:   },
                   3483: 
                   3484:   /*
                   3485:    *  Handle an Inner atom.  (Rule 7)
                   3486:    */
                   3487:   inner: function (style,size,mitem) {
                   3488:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3489:   },
                   3490: 
                   3491:   /*
                   3492:    *  Handle a Vcent atom.  (Rule 8)
                   3493:    */
                   3494:   vcenter: function (style,size,mitem) {
                   3495:     var box = jsMath.Box.Set(mitem.nuc,style,size);
                   3496:     var TeX = jsMath.Typeset.TeX(style,size);
                   3497:     box.y = TeX.axis_height - (box.h-box.d)/2;
                   3498:     mitem.nuc = box; mitem.type = 'ord';
                   3499:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3500:   },
                   3501: 
                   3502:   /*
                   3503:    *  Handle an Over atom.  (Rule 9)
                   3504:    */
                   3505:   overline: function (style,size,mitem) {
                   3506:     var TeX = jsMath.Typeset.TeX(style,size);
                   3507:     var box = jsMath.Box.Set(mitem.nuc,jsMath.Typeset.PrimeStyle(style),size).Remeasured();
                   3508:     var t = TeX.default_rule_thickness;
                   3509:     var rule = jsMath.Box.Rule(box.w,t);
                   3510:     rule.x = -rule.w; rule.y = box.h + 3*t;
                   3511:     mitem.nuc = jsMath.Box.SetList([box,rule],style,size);
                   3512:     mitem.nuc.h += t;
                   3513:     mitem.type = 'ord';
                   3514:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3515:   },
                   3516: 
                   3517:   /*
                   3518:    *  Handle an Under atom.  (Rule 10)
                   3519:    */
                   3520:   underline: function (style,size,mitem) {
                   3521:     var TeX = jsMath.Typeset.TeX(style,size);
                   3522:     var box = jsMath.Box.Set(mitem.nuc,jsMath.Typeset.PrimeStyle(style),size).Remeasured();
                   3523:     var t = TeX.default_rule_thickness;
                   3524:     var rule = jsMath.Box.Rule(box.w,t);
                   3525:     rule.x = -rule.w; rule.y = -box.d - 3*t - t;
                   3526:     mitem.nuc = jsMath.Box.SetList([box,rule],style,size);
                   3527:     mitem.nuc.d += t;
                   3528:     mitem.type = 'ord';
                   3529:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3530:   },
                   3531: 
                   3532:   /*
                   3533:    *  Handle a Rad atom.  (Rule 11 plus stuff for \root..\of)
                   3534:    */
                   3535:   radical: function (style,size,mitem) {
                   3536:     var TeX = jsMath.Typeset.TeX(style,size);
                   3537:     var Cp = jsMath.Typeset.PrimeStyle(style);
                   3538:     var box = jsMath.Box.Set(mitem.nuc,Cp,size).Remeasured();
                   3539:     var t = TeX.default_rule_thickness;
                   3540:     var p = t; if (style == 'D' || style == "D'") {p = TeX.x_height}
                   3541:     var r = t + p/4; 
1.2     ! albertel 3542:     var surd = jsMath.Box.Delimiter(box.h+box.d+r+t,[0,2,0x70,3,0x70],style,1);
1.1       albertel 3543:     t = surd.h; // thickness of rule is height of surd character
                   3544:     if (surd.d > box.h+box.d+r) {r = (r+surd.d-box.h-box.d)/2}
                   3545:     surd.y = box.h+r;
                   3546:     var rule = jsMath.Box.Rule(box.w,t);
                   3547:     rule.y = surd.y-t/2; rule.h += 3*t/2; box.x = -box.w;
                   3548:     var Cr = jsMath.Typeset.UpStyle(jsMath.Typeset.UpStyle(style));
                   3549:     var root = jsMath.Box.Set(mitem.root,Cr,size).Remeasured();
                   3550:     if (mitem.root) {
1.2     ! albertel 3551:       root.y = .55*(box.h+box.d+3*t+r)-box.d;
        !          3552:       surd.x = Math.max(root.w-(11/18)*surd.w,0);
        !          3553:       rule.x = (7/18)*surd.w;
        !          3554:       root.x = -(root.w+rule.x);
1.1       albertel 3555:     }
1.2     ! albertel 3556:     mitem.nuc = jsMath.Box.SetList([surd,root,rule,box],style,size);
1.1       albertel 3557:     mitem.type = 'ord';
                   3558:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3559:   },
                   3560: 
                   3561:   /*
                   3562:    *  Handle an Acc atom.  (Rule 12)
                   3563:    */
                   3564:   accent: function (style,size,mitem) {
                   3565:     var TeX = jsMath.Typeset.TeX(style,size);
                   3566:     var Cp = jsMath.Typeset.PrimeStyle(style);
                   3567:     var box = jsMath.Box.Set(mitem.nuc,Cp,size);
                   3568:     var u = box.w; var s; var Font;
                   3569:     if (mitem.nuc.type == 'TeX') {
                   3570:       Font = jsMath.TeX[mitem.nuc.font];
                   3571:       if (Font[mitem.nuc.c].krn && Font.skewchar)
                   3572:         {s = Font[mitem.nuc.c].krn[Font.skewchar]}
                   3573:     }
                   3574:     if (s == null) {s = 0}
                   3575:     
1.2     ! albertel 3576:     var c = mitem.accent[2];
        !          3577:     var font = jsMath.TeX.fam[mitem.accent[1]]; Font = jsMath.TeX[font];
1.1       albertel 3578:     while (Font[c].n && Font[Font[c].n].w <= u) {c = Font[c].n}
                   3579:     
                   3580:     var delta = Math.min(box.h,TeX.x_height);
                   3581:     if (mitem.nuc.type == 'TeX') {
                   3582:       var nitem = jsMath.mItem.Atom('ord',mitem.nuc);
                   3583:       nitem.sup = mitem.sup; nitem.sub = mitem.sub; nitem.delta = 0;
                   3584:       jsMath.mList.prototype.Atomize.SupSub(style,size,nitem);
                   3585:       delta += (nitem.nuc.h - box.h);
                   3586:       box = mitem.nuc = nitem.nuc;
                   3587:       delete mitem.sup; delete mitem.sub;
                   3588:     }
                   3589:     var acc = jsMath.Box.TeX(c,font,style,size);
                   3590:     acc.y = box.h - delta; acc.x = -box.w + s + (u-acc.w)/2;
                   3591:     if (Font[c].ic) {acc.x -= Font[c].ic * TeX.scale}
                   3592: 
                   3593:     mitem.nuc = jsMath.Box.SetList([box,acc],style,size);
                   3594:     if (mitem.nuc.w != box.w) {
                   3595:       var space = jsMath.mItem.Space(box.w-mitem.nuc.w);
                   3596:       mitem.nuc = jsMath.Box.SetList([mitem.nuc,space],style,size);
                   3597:     }
                   3598:     mitem.type = 'ord';
                   3599:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3600:   },
                   3601: 
                   3602:   /*
                   3603:    *  Handle an Op atom.  (Rules 13 and 13a)
                   3604:    */
                   3605:   op: function (style,size,mitem) {
                   3606:     var TeX = jsMath.Typeset.TeX(style,size); var box;
                   3607:     mitem.delta = 0; var isD = (style.charAt(0) == 'D');
                   3608:     if (mitem.limits == null && isD) {mitem.limits = 1}
                   3609: 
                   3610:     if (mitem.nuc.type == 'TeX') {
                   3611:       var C = jsMath.TeX[mitem.nuc.font][mitem.nuc.c];
                   3612:       if (isD && C.n) {mitem.nuc.c = C.n; C = jsMath.TeX[mitem.nuc.font][C.n]}
                   3613:       box = jsMath.Box.Set(mitem.nuc,style,size);
                   3614:       if (C.ic) {
                   3615:         mitem.delta = C.ic * TeX.scale;
1.2     ! albertel 3616:         if (mitem.limits || !mitem.sub || jsMath.Browser.msieIntegralBug) 
1.1       albertel 3617:           {box = jsMath.Box.SetList([box,jsMath.mItem.Space(mitem.delta)],style,size)}
                   3618:       }
                   3619:       box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height);
1.2     ! albertel 3620:       if (Math.abs(box.y) < .0001) {box.y = 0}
1.1       albertel 3621:     }
                   3622: 
                   3623:     if (!box) {box = jsMath.Box.Set(mitem.nuc,style,size).Remeasured()}
                   3624:     if (mitem.limits) {
                   3625:       var W = box.w; var x = box.w;
                   3626:       var mlist = [box]; var dh = 0; var dd = 0;
                   3627:       if (mitem.sup) {
                   3628:         var sup = jsMath.Box.Set(mitem.sup,jsMath.Typeset.UpStyle(style),size).Remeasured();
                   3629:         sup.x = ((box.w-sup.w)/2 + mitem.delta/2) - x; dh = TeX.big_op_spacing5;
                   3630:         W = Math.max(W,sup.w); x += sup.x + sup.w;
                   3631:         sup.y = box.h+sup.d + box.y +
                   3632:                     Math.max(TeX.big_op_spacing1,TeX.big_op_spacing3-sup.d);
                   3633:         mlist[mlist.length] = sup; delete mitem.sup;
                   3634:       }
                   3635:       if (mitem.sub) {
                   3636:         var sub = jsMath.Box.Set(mitem.sub,jsMath.Typeset.DownStyle(style),size).Remeasured();
                   3637:         sub.x = ((box.w-sub.w)/2 - mitem.delta/2) - x; dd = TeX.big_op_spacing5;
                   3638:         W = Math.max(W,sub.w); x += sub.x + sub.w;
                   3639:         sub.y = -box.d-sub.h + box.y -
                   3640:                    Math.max(TeX.big_op_spacing2,TeX.big_op_spacing4-sub.h);
                   3641:         mlist[mlist.length] = sub; delete mitem.sub;
                   3642:       }
                   3643:       if (W > box.w) {box.x = (W-box.w)/2; x += box.x}
                   3644:       if (x < W) {mlist[mlist.length] = jsMath.mItem.Space(W-x)}
                   3645:       mitem.nuc = jsMath.Box.SetList(mlist,style,size);
                   3646:       mitem.nuc.h += dh; mitem.nuc.d += dd;
                   3647:     } else {
1.2     ! albertel 3648:       if (jsMath.Browser.msieIntegralBug && mitem.sub && C && C.ic) 
1.1       albertel 3649:         {mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(-C.ic*TeX.scale)],style,size)}
                   3650:       else if (box.y) {mitem.nuc = jsMath.Box.SetList([box],style,size)}
                   3651:       jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3652:     }
                   3653:   },
                   3654: 
                   3655:   /*
                   3656:    *  Handle an Ord atom.  (Rule 14)
                   3657:    */
                   3658:   ord: function (style,size,mitem,prev,mList,i) {
                   3659:     if (mitem.nuc.type == 'TeX' && !mitem.sup && !mitem.sub) {
                   3660:       var nitem = mList.mlist[i+1];
                   3661:       if (nitem && nitem.atom && nitem.type &&
                   3662:           (nitem.type == 'ord' || nitem.type == 'op' || nitem.type == 'bin' ||
                   3663:            nitem.type == 'rel' || nitem.type == 'open' ||
                   3664:            nitem.type == 'close' || nitem.type == 'punct')) {
                   3665:         if (nitem.nuc.type == 'TeX' && nitem.nuc.font == mitem.nuc.font) {
                   3666:           mitem.textsymbol = 1;
                   3667:           var krn = jsMath.TeX[mitem.nuc.font][mitem.nuc.c].krn;
                   3668:           krn *= jsMath.Typeset.TeX(style,size).scale;
                   3669:           if (krn && krn[nitem.nuc.c]) {
                   3670:             for (var k = mList.mlist.length-1; k > i; k--)
                   3671:               {mList.mlist[k+1] = mList.mlist[k]}
                   3672:             mList.mlist[i+1] = jsMath.mItem.Space(krn[nitem.nuc.c]);
                   3673:           }
                   3674:         }
                   3675:       }
                   3676:     }
                   3677:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3678:   },
                   3679: 
                   3680:   /*
                   3681:    *  Handle a generalized fraction.  (Rules 15 to 15e)
                   3682:    */
                   3683:   fraction: function (style,size,mitem) {
                   3684:     var TeX = jsMath.Typeset.TeX(style,size); var t = 0;
                   3685:     if (mitem.thickness != null) {t = mitem.thickness}
                   3686:     else if (mitem.from.match(/over/)) {t = TeX.default_rule_thickness}
                   3687:     var isD = (style.charAt(0) == 'D');
                   3688:     var Cn = (style == 'D')? 'T': (style == "D'")? "T'": jsMath.Typeset.UpStyle(style);
                   3689:     var Cd = (isD)? "T'": jsMath.Typeset.DownStyle(style);
                   3690:     var num = jsMath.Box.Set(mitem.num,Cn,size).Remeasured();
                   3691:     var den = jsMath.Box.Set(mitem.den,Cd,size).Remeasured();
                   3692: 
                   3693:     var u; var v; var w;
                   3694:     var H = (isD)? TeX.delim1 : TeX.delim2;
                   3695:     var mlist = [jsMath.Box.Delimiter(H,mitem.left,style)]
                   3696:     var right = jsMath.Box.Delimiter(H,mitem.right,style);
                   3697: 
                   3698:     if (num.w < den.w) {
                   3699:       num.x = (den.w-num.w)/2;
                   3700:       den.x = -(num.w + num.x);
                   3701:       w = den.w; mlist[1] = num; mlist[2] = den;
                   3702:     } else {
                   3703:       den.x = (num.w-den.w)/2;
                   3704:       num.x = -(den.w + den.x);
                   3705:       w = num.w; mlist[1] = den; mlist[2] = num;
                   3706:     }
                   3707:     if (isD) {u = TeX.num1; v = TeX.denom1} else {
                   3708:       u = (t != 0)? TeX.num2: TeX.num3;
                   3709:       v = TeX.denom2;
                   3710:     }
                   3711:     if (t == 0) {// atop
                   3712:       var p = (isD)? 7*TeX.default_rule_thickness: 3*TeX.default_rule_thickness;
                   3713:       var r = (u - num.d) - (den.h - v);
                   3714:       if (r < p) {u += (p-r)/2; v += (p-r)/2}
                   3715:     } else {// over
                   3716:       var p = (isD)? 3*t: t; var a = TeX.axis_height;
                   3717:       var r = (u-num.d)-(a+t/2); if (r < p) {u += p-r}
                   3718:           r = (a-t/2)-(den.h-v); if (r < p) {v += p-r}
                   3719:       var rule = jsMath.Box.Rule(w,t); rule.x = -w; rule.y = a - t/2;
                   3720:       mlist[mlist.length] = rule;
                   3721:     }
                   3722:     num.y = u; den.y = -v;
                   3723: 
                   3724:     mlist[mlist.length] = right;
                   3725:     mitem.nuc = jsMath.Box.SetList(mlist,style,size);
                   3726:     mitem.type = 'ord'; mitem.atom = 1;
                   3727:     delete mitem.num; delete mitem.den;
                   3728:     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
                   3729:   },
                   3730: 
                   3731:   /*
                   3732:    *  Add subscripts and superscripts.  (Rules 17-18f)
                   3733:    */
                   3734:   SupSub: function (style,size,mitem) {
                   3735:     var TeX = jsMath.Typeset.TeX(style,size);
                   3736:     var nuc = mitem.nuc;
                   3737:     var box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size,0);
                   3738:     if (box.format == 'null') 
                   3739:       {box = mitem.nuc = jsMath.Box.Text('','normal',style,size)}
                   3740: 
                   3741:     if (nuc.type == 'TeX') {
                   3742:       if (!mitem.textsymbol) {
                   3743:         var C = jsMath.TeX[nuc.font][nuc.c];
                   3744:         if (C.ic) {
                   3745:           mitem.delta = C.ic * TeX.scale;
                   3746:           if (!mitem.sub) {
                   3747:             box = mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(mitem.delta)],style,size);
                   3748:             mitem.delta = 0;
                   3749:           }
                   3750:         }
                   3751:       } else {mitem.delta = 0}
                   3752:     }
                   3753: 
                   3754:     if (!mitem.sup && !mitem.sub) return;
                   3755:     mitem.nuc.Styled();
                   3756:     
                   3757:     var Cd = jsMath.Typeset.DownStyle(style);
                   3758:     var Cu = jsMath.Typeset.UpStyle(style);
                   3759:     var q = jsMath.Typeset.TeX(Cu,size).sup_drop;
                   3760:     var r = jsMath.Typeset.TeX(Cd,size).sub_drop;
                   3761:     var u = 0; var v = 0; var p;
                   3762:     if (nuc.type != 'text' && nuc.type != 'TeX' && nuc.type != 'null')
                   3763:       {u = box.h - q; v = box.d + r}
                   3764: 
                   3765:     if (mitem.sub) {
                   3766:       var sub = jsMath.Box.Set(mitem.sub,Cd,size);
                   3767:       sub = jsMath.Box.SetList([sub,jsMath.mItem.Space(TeX.scriptspace)],style,size);
                   3768:     }
                   3769: 
                   3770:     if (!mitem.sup) {
                   3771:       sub.y = -Math.max(v,TeX.sub1,sub.h-(4/5)*jsMath.Typeset.TeX(Cd,size).x_height);
                   3772:       mitem.nuc = jsMath.Box.SetList([box,sub],style,size).Styled(); delete mitem.sub;
                   3773:       return;
                   3774:     }
                   3775: 
                   3776:     var sup = jsMath.Box.Set(mitem.sup,Cu,size);
                   3777:     sup = jsMath.Box.SetList([sup,jsMath.mItem.Space(TeX.scriptspace)],style,size);
                   3778:     if (style == 'D') {p = TeX.sup1}
                   3779:     else if (style.charAt(style.length-1) == "'") {p = TeX.sup3}
                   3780:     else {p = TeX.sup2}
                   3781:     u = Math.max(u,p,sup.d+jsMath.Typeset.TeX(Cu,size).x_height/4);
                   3782: 
                   3783:     if (!mitem.sub) {
                   3784:       sup.y = u;
                   3785:       mitem.nuc = jsMath.Box.SetList([box,sup],style,size); delete mitem.sup;
                   3786:       return;
                   3787:     }
                   3788: 
                   3789:     v = Math.max(v,jsMath.Typeset.TeX(Cd,size).sub2);
                   3790:     var t = TeX.default_rule_thickness;
                   3791:     if ((u-sup.d) - (sub.h -v) < 4*t) {
                   3792:       v = 4*t + sub.h - (u-sup.d);
                   3793:       p = (4/5)*TeX.x_height - (u-sup.d);
                   3794:       if (p > 0) {u += p; v -= p}
                   3795:     }
                   3796:     sup.Remeasured(); sub.Remeasured();
                   3797:     sup.y = u; sub.y = -v; sup.x = mitem.delta;
                   3798:     if (sup.w+sup.x > sub.w)
                   3799:       {sup.x -= sub.w; mitem.nuc = jsMath.Box.SetList([box,sub,sup],style,size)} else
                   3800:       {sub.x -= (sup.w+sup.x); mitem.nuc = jsMath.Box.SetList([box,sup,sub],style,size)}
                   3801: 
                   3802:     delete mitem.sup; delete mitem.sub;
                   3803:   }
                   3804: 
                   3805: });
                   3806: 
                   3807: 
                   3808: /***************************************************************************/
                   3809: 
                   3810: /*
                   3811:  *  The Typeset object handles most of the TeX-specific processing
                   3812:  */
                   3813: 
                   3814: jsMath.Typeset = function (mlist) {
                   3815:   this.type = 'typeset';
                   3816:   this.mlist = mlist;
                   3817: }
                   3818: 
                   3819: jsMath.Add(jsMath.Typeset,{
                   3820: 
                   3821:   /*
                   3822:    *  The "C-uparrow" style table (TeXbook, p. 441)
                   3823:    */
                   3824:   upStyle: {
                   3825:     D: "S", T: "S",  "D'": "S'", "T'": "S'",
                   3826:     S: "SS",  SS: "SS",  "S'": "SS'", "SS'": "SS'"
                   3827:   },
                   3828: 
                   3829:   /*
                   3830:    *  The "C-downarrow" style table (TeXbook, p. 441)
                   3831:    */
                   3832:   downStyle: {
                   3833:     D: "S'", T: "S'",  "D'": "S'", "T'": "S'",
                   3834:     S: "SS'",  SS: "SS'",  "S'": "SS'", "SS'": "SS'"
                   3835:   },
                   3836: 
                   3837:   /*
                   3838:    *  Get the various styles given the current style
                   3839:    *  (see TeXbook, p. 441)
                   3840:    */
                   3841:   UpStyle: function (style) {return this.upStyle[style]},
                   3842:   DownStyle: function (style) {return this.downStyle[style]},
                   3843:   PrimeStyle: function (style) {
                   3844:     if (style.charAt(style.length-1) == "'") {return style}
                   3845:     return style + "'"
                   3846:   },
                   3847: 
                   3848:   /*
                   3849:    *  A value scaled to the appropriate size for scripts
                   3850:    */
                   3851:   StyleValue: function (style,v) {
                   3852:     if (style == "S" || style == "S'")   {return .7*v}
                   3853:     if (style == "SS" || style == "SS'") {return .5*v}
                   3854:     return v;
                   3855:   },
1.2     ! albertel 3856:   
        !          3857:   /*
        !          3858:    *  Return the size associated with a given style and size
        !          3859:    */
        !          3860:   StyleSize: function (style,size) {
        !          3861:     if      (style == "S" || style == "S'")   {size = Math.max(0,size-2)}
        !          3862:     else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)}
        !          3863:     return size;
        !          3864:   },
1.1       albertel 3865: 
                   3866:   /*
                   3867:    *  Return the font parameter table for the given style
                   3868:    */
                   3869:   TeX: function (style,size) {
                   3870:     if      (style == "S" || style == "S'")   {size = Math.max(0,size-2)}
                   3871:     else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)}
                   3872:     return jsMath.TeXparams[size];
                   3873:   },
                   3874: 
                   3875: 
                   3876:   /*
                   3877:    *  Add the CSS class for the given TeX style
                   3878:    */
                   3879:   AddStyle: function (style,size,html) {
                   3880:     if      (style == "S" || style == "S'")   {size = Math.max(0,size-2)}
                   3881:     else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)}
                   3882:     if (size != 4) {html = '<SPAN CLASS="size'+size+'">' + html + '</SPAN>'}
                   3883:     return html;
                   3884:   },
                   3885: 
                   3886:   /*
                   3887:    *  Add the font class, if needed
                   3888:    */
                   3889:   AddClass: function (tclass,html) {
                   3890:     if (tclass != '' && tclass != 'normal') {html = jsMath.HTML.Class(tclass,html)}
                   3891:     return html;
                   3892:   }
                   3893: 
                   3894: });
                   3895: 
                   3896: 
                   3897: jsMath.Package(jsMath.Typeset,{
                   3898:   
                   3899:   /*
                   3900:    *  The spacing tables for inter-atom spacing
                   3901:    *  (See rule 20, and Chapter 18, p 170)
                   3902:    */
                   3903:   DTsep: {
                   3904:     ord: {op: 1, bin: 2, rel: 3, inner: 1},
                   3905:     op:  {ord: 1, op: 1, rel: 3, inner: 1},
                   3906:     bin: {ord: 2, op: 2, open: 2, inner: 2},
                   3907:     rel: {ord: 3, op: 3, open: 3, inner: 3},
                   3908:     open: {},
                   3909:     close: {op: 1, bin:2, rel: 3, inner: 1},
                   3910:     punct: {ord: 1, op: 1, rel: 1, open: 1, close: 1, punct: 1, inner: 1},
                   3911:     inner: {ord: 1, op: 1, bin: 2, rel: 3, open: 1, punct: 1, inner: 1}
                   3912:   },
                   3913: 
                   3914:   SSsep: {
                   3915:     ord: {op: 1},
                   3916:     op:  {ord: 1, op: 1},
                   3917:     bin: {},
                   3918:     rel: {},
                   3919:     open: {},
                   3920:     close: {op: 1},
                   3921:     punct: {},
                   3922:     inner: {op: 1}
                   3923:   },
                   3924: 
                   3925:   /*
                   3926:    *  The sizes used in the tables above
                   3927:    */
                   3928:   sepW: ['','thinmuskip','medmuskip','thickmuskip'],
                   3929:   
                   3930:   
                   3931:   /*
                   3932:    *  Find the amount of separation to use between two adjacent
                   3933:    *  atoms in the given style
                   3934:    */
                   3935:   GetSeparation: function (l,r,style) {
                   3936:     if (l && l.atom && r.atom) {
                   3937:       var table = this.DTsep; if (style.charAt(0) == "S") {table = this.SSsep}
                   3938:       var row = table[l.type];
                   3939:       if (row && row[r.type] != null) {return jsMath.TeX[this.sepW[row[r.type]]]}
                   3940:     }
                   3941:     return 0;
                   3942:   },
                   3943: 
                   3944:   /*
                   3945:    *  Typeset an mlist (i.e., turn it into HTML).
                   3946:    *  Here, text items of the same class and style are combined
                   3947:    *  to reduce the number of <SPAN> tags used (though it is still
                   3948:    *  huge).  Spaces are combined, when possible.
                   3949:    *  ###  More needs to be done with that.  ###
                   3950:    *  The width of the final box is recomputed at the end, since
                   3951:    *  the final width is not necessarily the sum of the widths of
                   3952:    *  the individual parts (widths are in pixels, but the browsers
                   3953:    *  puts pieces together using sub-pixel accuracy).
                   3954:    */
                   3955:   Typeset: function (style,size) {
                   3956:     this.style = style; this.size = size; var unset = -10000
                   3957:     this.w = 0; this.h = unset; this.d = unset;
                   3958:     this.bh = this.h; this.bd = this.d;
                   3959:     this.tbuf = ''; this.tx = 0; this.tclass = '';
                   3960:     this.cbuf = ''; this.hbuf = ''; this.hx = 0;
                   3961:     var mitem = null; var prev; this.x = 0; this.dx = 0;
                   3962: 
                   3963:     for (var i = 0; i < this.mlist.length; i++) {
                   3964:       prev = mitem; mitem = this.mlist[i];
                   3965:       switch (mitem.type) {
                   3966: 
                   3967:         case 'size':
                   3968:           this.FlushClassed();
                   3969:           this.size = mitem.size;
                   3970:           mitem = prev; // hide this from TeX
                   3971:           break;
                   3972: 
                   3973:         case 'style':
                   3974:           this.FlushClassed();
                   3975:           if (this.style.charAt(this.style.length-1) == "'")
                   3976:             {this.style = mitem.style + "'"} else {this.style = mitem.style}
                   3977:           mitem = prev; // hide this from TeX
                   3978:           break;
                   3979: 
                   3980:         case 'space':
                   3981:           if (typeof(mitem.w) == 'object') {
                   3982:             if (this.style.charAt(1) == 'S') {mitem.w = .5*mitem.w[0]/18}
                   3983:             else if (this.style.charAt(0) == 'S') {mitem.w = .7*mitem.w[0]/18}
                   3984:             else {mitem.w = mitem.w[0]/18}
                   3985:           }
                   3986:           this.dx += mitem.w-0; // mitem.w is sometimes a string?
                   3987:           mitem = prev; // hide this from TeX
                   3988:           break;
                   3989:           
                   3990:         case 'html':
                   3991:           this.FlushClassed();
                   3992:           if (this.hbuf == '') {this.hx = this.x}
                   3993:           this.hbuf += mitem.html;
                   3994:           mitem = prev; // hide this from TeX
                   3995:           break;
                   3996:           
                   3997:         default:   // atom
                   3998:           if (!mitem.atom && mitem.type != 'box') break;
                   3999:           mitem.nuc.x += this.dx + this.GetSeparation(prev,mitem,this.style);
                   4000:           if (mitem.nuc.y || mitem.nuc.x) mitem.nuc.Styled();
                   4001:           this.dx = 0; this.x = this.x + this.w;
                   4002:           this.w += mitem.nuc.w + mitem.nuc.x;
                   4003:           if (mitem.nuc.format == 'text') {
                   4004:             if (this.tclass != mitem.nuc.tclass && this.tclass != '') this.FlushText();
                   4005:             if (this.tbuf == '' && this.cbuf == '') {this.tx = this.x}
                   4006:             this.tbuf += mitem.nuc.html; this.tclass = mitem.nuc.tclass;
                   4007:           } else  {
                   4008:             this.FlushClassed();
                   4009:             if (mitem.nuc.x || mitem.nuc.y) this.Place(mitem.nuc);
                   4010:             if (this.hbuf == '') {this.hx = this.x}
                   4011:             this.hbuf += mitem.nuc.html;
                   4012:           }
                   4013:           this.h = Math.max(this.h,mitem.nuc.h+mitem.nuc.y); this.bh = Math.max(this.bh,mitem.nuc.bh);
                   4014:           this.d = Math.max(this.d,mitem.nuc.d-mitem.nuc.y); this.bd = Math.max(this.bd,mitem.nuc.bd);
                   4015:           break;
                   4016:       }
                   4017:     }
                   4018:     
                   4019:     this.FlushClassed(); // make sure scaling is included
1.2     ! albertel 4020:     if (this.dx) {this.hbuf += jsMath.HTML.Spacer(this.dx); this.w += this.dx}
1.1       albertel 4021:     if (this.hbuf == '') {return jsMath.Box.Null}
                   4022:     if (this.h == unset) {this.h = 0}
                   4023:     if (this.d == unset) {this.d = 0}
                   4024:     var box = new jsMath.Box('html',this.hbuf,this.w,this.h,this.d);
                   4025:     box.bh = this.bh; box.bd = this.bd;
                   4026:     return box;
                   4027:   },
                   4028: 
                   4029:   /*
                   4030:    *  Add the font to the buffered text and move it to the
                   4031:    *  classed-text buffer.
                   4032:    */
                   4033:   FlushText: function () {
                   4034:     if (this.tbuf == '') return;
                   4035:     this.cbuf += jsMath.Typeset.AddClass(this.tclass,this.tbuf);
                   4036:     this.tbuf = ''; this.tclass = '';
                   4037:   },
                   4038: 
                   4039:   /*
                   4040:    *  Add the script or scriptscript style to the text and
                   4041:    *  move it to the HTML buffer
                   4042:    */
                   4043:   FlushClassed: function () {
                   4044:     this.FlushText();
                   4045:     if (this.cbuf == '') return;
                   4046:     if (this.hbuf == '') {this.hx = this.tx}
                   4047:     this.hbuf += jsMath.Typeset.AddStyle(this.style,this.size,this.cbuf);
                   4048:     this.cbuf = '';
                   4049:   },
                   4050: 
                   4051:   /*
                   4052:    *  Add a <SPAN> to position an item's HTML, and
1.2     ! albertel 4053:    *  adjust the item's height and depth.
1.1       albertel 4054:    *  (This may be replaced buy one of the following browser-specific
1.2     ! albertel 4055:    *   versions by Browser.Init().)
1.1       albertel 4056:    */
                   4057:   Place: function (item) {
                   4058:     var html = '<SPAN STYLE="position: relative;';
                   4059:     if (item.x) {html += ' margin-left:'+jsMath.HTML.Em(item.x)+';'}
                   4060:     if (item.y) {html += ' top:'+jsMath.HTML.Em(-item.y)+';'}
                   4061:     item.html = html + '">' + item.html + '</SPAN>';
                   4062:     item.h += item.y; item.d -= item.y;
                   4063:     item.x = 0; item.y = 0;
                   4064:   },
                   4065:   
                   4066:   /*
1.2     ! albertel 4067:    *  For MSIE on Windows, backspacing must be done in a separate
        !          4068:    *  <SPAN>, otherwise the contents will be clipped.  Netscape
        !          4069:    *  also doesn't combine vertical and horizontal spacing well.
        !          4070:    *  Here, the horizontal and vertical spacing are done separately.
1.1       albertel 4071:    */
                   4072:   PlaceSeparateSkips: function (item) {
1.2     ! albertel 4073:     if (item.y) {
        !          4074:       if (item.html.match(/^<IMG[^>]*>(<SPAN STYLE="margin-left: [-0-9.]*em"><\/SPAN>)?$/i) && !item.html.match(/top:/)) {
        !          4075:         item.html = item.html.replace(/STYLE="/,
        !          4076:             'STYLE="position:relative; top:'+jsMath.HTML.Em(-item.y)+';');
        !          4077:       } else {
        !          4078:         item.html = '<SPAN STYLE="position: relative; '
        !          4079:                        + 'top:'+jsMath.HTML.Em(-item.y)+';'
        !          4080:                        + '">' + item.html + '</SPAN>'
        !          4081:       }
        !          4082:     }
1.1       albertel 4083:     if (item.x) 
1.2     ! albertel 4084:       {item.html = jsMath.Browser.msieSpaceFix
        !          4085:                        + '<SPAN STYLE="margin-left:'
        !          4086:                        +    jsMath.HTML.Em(item.x-jsMath.Browser.spaceWidth)+';">'
        !          4087:                        + jsMath.Browser.hiddenSpace + '</SPAN>' + item.html}
1.1       albertel 4088:     item.h += item.y; item.d -= item.y;
                   4089:     item.x = 0; item.y = 0;
                   4090:   }
                   4091:   
                   4092: });
                   4093: 
                   4094: 
                   4095: 
                   4096: /***************************************************************************/
                   4097: 
                   4098: /*
                   4099:  *  The Parse object handles the parsing of the TeX input string, and creates
                   4100:  *  the mList to be typeset by the Typeset object above.
                   4101:  */
                   4102: 
                   4103: jsMath.Parse = function (s,font,size,style) {
                   4104:   var parse = new jsMath.Parser(s,font,size,style);
                   4105:   parse.Parse();
                   4106:   return parse;
                   4107: }
                   4108: 
                   4109: jsMath.Parser = function (s,font,size,style) {
                   4110:   this.string = s; this.i = 0;
                   4111:   this.mlist = new jsMath.mList(null,font,size,style);
                   4112: }
                   4113: 
                   4114: jsMath.Package(jsMath.Parser,{
                   4115:   
                   4116:   // special characters
                   4117:   cmd:   '\\',
                   4118:   open:  '{',
                   4119:   close: '}',
                   4120: 
                   4121:   // patterns for letters and numbers
                   4122:   letter:  /[a-z]/i,
                   4123:   number:  /[0-9]/,
                   4124:   
                   4125:   //  the \mathchar definitions (see Appendix B of the TeXbook).
                   4126:   mathchar: {
1.2     ! albertel 4127:     '!': [5,0,0x21],
        !          4128:     '(': [4,0,0x28],
        !          4129:     ')': [5,0,0x29],
        !          4130:     '*': [2,2,0x03], // \ast
        !          4131:     '+': [2,0,0x2B],
        !          4132:     ',': [6,1,0x3B],
        !          4133:     '-': [2,2,0x00],
        !          4134:     '.': [0,1,0x3A],
        !          4135:     '/': [0,1,0x3D],
        !          4136:     ':': [3,0,0x3A],
        !          4137:     ';': [6,0,0x3B],
        !          4138:     '<': [3,1,0x3C],
        !          4139:     '=': [3,0,0x3D],
        !          4140:     '>': [3,1,0x3E],
        !          4141:     '?': [5,0,0x3F],
        !          4142:     '[': [4,0,0x5B],
        !          4143:     ']': [5,0,0x5D],
        !          4144: //  '{': [4,2,0x66],
        !          4145: //  '}': [5,2,0x67],
        !          4146:     '|': [0,2,0x6A]
1.1       albertel 4147:   },
                   4148: 
                   4149:   //  handle special \catcode characters
                   4150:   special: {
                   4151:     '^':   'HandleSuperscript',
                   4152:     '_':   'HandleSubscript',
                   4153:     ' ':   'Space',
                   4154:     "\t":  'Space',
                   4155:     "\r":  'Space',
                   4156:     "\n":  'Space',
                   4157:     "'":   'Prime',
                   4158:     '%':   'HandleComment',
                   4159:     '&':   'HandleEntry'
                   4160:   },
                   4161: 
                   4162:   // the \mathchardef table (see Appendix B of the TeXbook).
                   4163:   mathchardef: {
                   4164:   // brace parts
1.2     ! albertel 4165:     braceld:      [0,3,0x7A],
        !          4166:     bracerd:      [0,3,0x7B],
        !          4167:     bracelu:      [0,3,0x7C],
        !          4168:     braceru:      [0,3,0x7D],
1.1       albertel 4169: 
                   4170:   // Greek letters
1.2     ! albertel 4171:     alpha:        [0,1,0x0B],
        !          4172:     beta:         [0,1,0x0C],
        !          4173:     gamma:        [0,1,0x0D],
        !          4174:     delta:        [0,1,0x0E],
        !          4175:     epsilon:      [0,1,0x0F],
        !          4176:     zeta:         [0,1,0x10],
        !          4177:     eta:          [0,1,0x11],
        !          4178:     theta:        [0,1,0x12],
        !          4179:     iota:         [0,1,0x13],
        !          4180:     kappa:        [0,1,0x14],
        !          4181:     lambda:       [0,1,0x15],
        !          4182:     mu:           [0,1,0x16],
        !          4183:     nu:           [0,1,0x17],
        !          4184:     xi:           [0,1,0x18],
        !          4185:     pi:           [0,1,0x19],
        !          4186:     rho:          [0,1,0x1A],
        !          4187:     sigma:        [0,1,0x1B],
        !          4188:     tau:          [0,1,0x1C],
        !          4189:     upsilon:      [0,1,0x1D],
        !          4190:     phi:          [0,1,0x1E],
        !          4191:     chi:          [0,1,0x1F],
        !          4192:     psi:          [0,1,0x20],
        !          4193:     omega:        [0,1,0x21],
        !          4194:     varepsilon:   [0,1,0x22],
        !          4195:     vartheta:     [0,1,0x23],
        !          4196:     varpi:        [0,1,0x24],
        !          4197:     varrho:       [0,1,0x25],
        !          4198:     varsigma:     [0,1,0x26],
        !          4199:     varphi:       [0,1,0x27],
1.1       albertel 4200:     
1.2     ! albertel 4201:     Gamma:        [7,0,0x00],
        !          4202:     Delta:        [7,0,0x01],
        !          4203:     Theta:        [7,0,0x02],
        !          4204:     Lambda:       [7,0,0x03],
        !          4205:     Xi:           [7,0,0x04],
        !          4206:     Pi:           [7,0,0x05],
        !          4207:     Sigma:        [7,0,0x06],
        !          4208:     Upsilon:      [7,0,0x07],
        !          4209:     Phi:          [7,0,0x08],
        !          4210:     Psi:          [7,0,0x09],
        !          4211:     Omega:        [7,0,0x0A],
1.1       albertel 4212: 
                   4213:   // Ord symbols
1.2     ! albertel 4214:     aleph:        [0,2,0x40],
        !          4215:     imath:        [0,1,0x7B],
        !          4216:     jmath:        [0,1,0x7C],
        !          4217:     ell:          [0,1,0x60],
        !          4218:     wp:           [0,1,0x7D],
        !          4219:     Re:           [0,2,0x3C],
        !          4220:     Im:           [0,2,0x3D],
        !          4221:     partial:      [0,1,0x40],
        !          4222:     infty:        [0,2,0x31],
        !          4223:     prime:        [0,2,0x30],
        !          4224:     emptyset:     [0,2,0x3B],
        !          4225:     nabla:        [0,2,0x72],
        !          4226:     surd:         [1,2,0x70],
        !          4227:     top:          [0,2,0x3E],
        !          4228:     bot:          [0,2,0x3F],
        !          4229:     triangle:     [0,2,0x34],
        !          4230:     forall:       [0,2,0x38],
        !          4231:     exists:       [0,2,0x39],
        !          4232:     neg:          [0,2,0x3A],
        !          4233:     lnot:         [0,2,0x3A],
        !          4234:     flat:         [0,1,0x5B],
        !          4235:     natural:      [0,1,0x5C],
        !          4236:     sharp:        [0,1,0x5D],
        !          4237:     clubsuit:     [0,2,0x7C],
        !          4238:     diamondsuit:  [0,2,0x7D],
        !          4239:     heartsuit:    [0,2,0x7E],
        !          4240:     spadesuit:    [0,2,0x7F],
1.1       albertel 4241: 
                   4242:   // big ops
1.2     ! albertel 4243:     coprod:      [1,3,0x60],
        !          4244:     bigvee:      [1,3,0x57],
        !          4245:     bigwedge:    [1,3,0x56],
        !          4246:     biguplus:    [1,3,0x55],
        !          4247:     bigcap:      [1,3,0x54],
        !          4248:     bigcup:      [1,3,0x53],
        !          4249:     intop:       [1,3,0x52], 
        !          4250:     prod:        [1,3,0x51],
        !          4251:     sum:         [1,3,0x50],
        !          4252:     bigotimes:   [1,3,0x4E],
        !          4253:     bigoplus:    [1,3,0x4C],
        !          4254:     bigodot:     [1,3,0x4A],
        !          4255:     ointop:      [1,3,0x48],
        !          4256:     bigsqcup:    [1,3,0x46],
        !          4257:     smallint:    [1,2,0x73],
1.1       albertel 4258: 
                   4259:   // binary operations
1.2     ! albertel 4260:     triangleleft:      [2,1,0x2F],
        !          4261:     triangleright:     [2,1,0x2E],
        !          4262:     bigtriangleup:     [2,2,0x34],
        !          4263:     bigtriangledown:   [2,2,0x35],
        !          4264:     wedge:       [2,2,0x5E],
        !          4265:     land:        [2,2,0x5E],
        !          4266:     vee:         [2,2,0x5F],
        !          4267:     lor:         [2,2,0x5F],
        !          4268:     cap:         [2,2,0x5C],
        !          4269:     cup:         [2,2,0x5B],
        !          4270:     ddagger:     [2,2,0x7A],
        !          4271:     dagger:      [2,2,0x79],
        !          4272:     sqcap:       [2,2,0x75],
        !          4273:     sqcup:       [2,2,0x74],
        !          4274:     uplus:       [2,2,0x5D],
        !          4275:     amalg:       [2,2,0x71],
        !          4276:     diamond:     [2,2,0x05],
        !          4277:     bullet:      [2,2,0x0F],
        !          4278:     wr:          [2,2,0x6F],
        !          4279:     div:         [2,2,0x04],
        !          4280:     odot:        [2,2,0x0C],
        !          4281:     oslash:      [2,2,0x0B],
        !          4282:     otimes:      [2,2,0x0A],
        !          4283:     ominus:      [2,2,0x09],
        !          4284:     oplus:       [2,2,0x08],
        !          4285:     mp:          [2,2,0x07],
        !          4286:     pm:          [2,2,0x06],
        !          4287:     circ:        [2,2,0x0E],
        !          4288:     bigcirc:     [2,2,0x0D],
        !          4289:     setminus:    [2,2,0x6E], // for set difference A\setminus B
        !          4290:     cdot:        [2,2,0x01],
        !          4291:     ast:         [2,2,0x03],
        !          4292:     times:       [2,2,0x02],
        !          4293:     star:        [2,1,0x3F],
1.1       albertel 4294: 
                   4295:   // Relations
1.2     ! albertel 4296:     propto:      [3,2,0x2F],
        !          4297:     sqsubseteq:  [3,2,0x76],
        !          4298:     sqsupseteq:  [3,2,0x77],
        !          4299:     parallel:    [3,2,0x6B],
        !          4300:     mid:         [3,2,0x6A],
        !          4301:     dashv:       [3,2,0x61],
        !          4302:     vdash:       [3,2,0x60],
        !          4303:     leq:         [3,2,0x14],
        !          4304:     le:          [3,2,0x14],
        !          4305:     geq:         [3,2,0x15],
        !          4306:     ge:          [3,2,0x15],
        !          4307:     succ:        [3,2,0x1F],
        !          4308:     prec:        [3,2,0x1E],
        !          4309:     approx:      [3,2,0x19],
        !          4310:     succeq:      [3,2,0x17],
        !          4311:     preceq:      [3,2,0x16],
        !          4312:     supset:      [3,2,0x1B],
        !          4313:     subset:      [3,2,0x1A],
        !          4314:     supseteq:    [3,2,0x13],
        !          4315:     subseteq:    [3,2,0x12],
        !          4316:     'in':        [3,2,0x32],
        !          4317:     ni:          [3,2,0x33],
        !          4318:     owns:        [3,2,0x33],
        !          4319:     gg:          [3,2,0x1D],
        !          4320:     ll:          [3,2,0x1C],
        !          4321:     not:         [3,2,0x36],
        !          4322:     sim:         [3,2,0x18],
        !          4323:     simeq:       [3,2,0x27],
        !          4324:     perp:        [3,2,0x3F],
        !          4325:     equiv:       [3,2,0x11],
        !          4326:     asymp:       [3,2,0x10],
        !          4327:     smile:       [3,1,0x5E],
        !          4328:     frown:       [3,1,0x5F],
1.1       albertel 4329: 
                   4330:   // Arrows
1.2     ! albertel 4331:     Leftrightarrow:   [3,2,0x2C],
        !          4332:     Leftarrow:        [3,2,0x28],
        !          4333:     Rightarrow:       [3,2,0x29],
        !          4334:     leftrightarrow:   [3,2,0x24],
        !          4335:     leftarrow:        [3,2,0x20],
        !          4336:     gets:             [3,2,0x20],
        !          4337:     rightarrow:       [3,2,0x21],
        !          4338:     to:               [3,2,0x21],
        !          4339:     mapstochar:       [3,2,0x37],
        !          4340:     leftharpoonup:    [3,1,0x28],
        !          4341:     leftharpoondown:  [3,1,0x29],
        !          4342:     rightharpoonup:   [3,1,0x2A],
        !          4343:     rightharpoondown: [3,1,0x2B],
        !          4344:     nearrow:          [3,2,0x25],
        !          4345:     searrow:          [3,2,0x26],
        !          4346:     nwarrow:          [3,2,0x2D],
        !          4347:     swarrow:          [3,2,0x2E],
        !          4348: 
        !          4349:     hbarchar:   [0,0,0x16], // for \hbar
        !          4350:     lhook:      [3,1,0x2C],
        !          4351:     rhook:      [3,1,0x2D],
        !          4352: 
        !          4353:     ldotp:      [6,1,0x3A], // ldot as a punctuation mark
        !          4354:     cdotp:      [6,2,0x01], // cdot as a punctuation mark
        !          4355:     colon:      [6,0,0x3A], // colon as a punctuation mark
        !          4356: 
        !          4357:     '#':        [7,0,0x23],
        !          4358:     '$':        [7,0,0x24],
        !          4359:     '%':        [7,0,0x25],
        !          4360:     '&':        [7,0,0x26]
1.1       albertel 4361:   },
                   4362:   
                   4363:   // The delimiter table (see Appendix B of the TeXbook)
                   4364:   delimiter: {
1.2     ! albertel 4365:     '(':                [0,0,0x28,3,0x00],
        !          4366:     ')':                [0,0,0x29,3,0x01],
        !          4367:     '[':                [0,0,0x5B,3,0x02],
        !          4368:     ']':                [0,0,0x5D,3,0x03],
        !          4369:     '<':                [0,2,0x68,3,0x0A],
        !          4370:     '>':                [0,2,0x69,3,0x0B],
        !          4371:     '/':                [0,0,0x2F,3,0x0E],
        !          4372:     '|':                [0,2,0x6A,3,0x0C],
        !          4373:     '.':                [0,0,0x00,0,0x00],
        !          4374:     '\\':               [0,2,0x6E,3,0x0F],
        !          4375:     '\\lmoustache':     [4,3,0x7A,3,0x40],  // top from (, bottom from )
        !          4376:     '\\rmoustache':     [5,3,0x7B,3,0x41],  // top from ), bottom from (
        !          4377:     '\\lgroup':         [4,6,0x28,3,0x3A],  // extensible ( with sharper tips
        !          4378:     '\\rgroup':         [5,6,0x29,3,0x3B],  // extensible ) with sharper tips
        !          4379:     '\\arrowvert':      [0,2,0x6A,3,0x3C],  // arrow without arrowheads
        !          4380:     '\\Arrowvert':      [0,2,0x6B,3,0x3D],  // double arrow without arrowheads
        !          4381: //  '\\bracevert':      [0,7,0x7C,3,0x3E],  // the vertical bar that extends braces
        !          4382:     '\\bracevert':      [0,2,0x6A,3,0x3E],  // we don't load tt, so use | instead
        !          4383:     '\\Vert':           [0,2,0x6B,3,0x0D],
        !          4384:     '\\|':              [0,2,0x6B,3,0x0D],
        !          4385:     '\\vert':           [0,2,0x6A,3,0x0C],
        !          4386:     '\\uparrow':        [3,2,0x22,3,0x78],
        !          4387:     '\\downarrow':      [3,2,0x23,3,0x79],
        !          4388:     '\\updownarrow':    [3,2,0x6C,3,0x3F],
        !          4389:     '\\Uparrow':        [3,2,0x2A,3,0x7E],
        !          4390:     '\\Downarrow':      [3,2,0x2B,3,0x7F],
        !          4391:     '\\Updownarrow':    [3,2,0x6D,3,0x77],
        !          4392:     '\\backslash':      [0,2,0x6E,3,0x0F],  // for double coset G\backslash H
        !          4393:     '\\rangle':         [5,2,0x69,3,0x0B],
        !          4394:     '\\langle':         [4,2,0x68,3,0x0A],
        !          4395:     '\\rbrace':         [5,2,0x67,3,0x09],
        !          4396:     '\\lbrace':         [4,2,0x66,3,0x08],
        !          4397:     '\\}':              [5,2,0x67,3,0x09],
        !          4398:     '\\{':              [4,2,0x66,3,0x08],
        !          4399:     '\\rceil':          [5,2,0x65,3,0x07],
        !          4400:     '\\lceil':          [4,2,0x64,3,0x06],
        !          4401:     '\\rfloor':         [5,2,0x63,3,0x05],
        !          4402:     '\\lfloor':         [4,2,0x62,3,0x04]
1.1       albertel 4403:   },
                   4404: 
                   4405:   /*
                   4406:    *  The basic macros for plain TeX.
                   4407:    *
                   4408:    *  When the control sequence on the left is called, the JavaScript
                   4409:    *  funtion on the right is called, with the name of the control sequence
                   4410:    *  as its first parameter (this way, the same function can be called by
                   4411:    *  several different control sequences to do similar actions, and the
                   4412:    *  function can still tell which TeX command was issued).  If the right
                   4413:    *  is an array, the first entry is the routine to call, and the
                   4414:    *  remaining entries in the array are parameters to pass to the function
                   4415:    *  as the second parameter (they are in an array reference).
                   4416:    *  
                   4417:    *  Note:  TeX macros as defined by the user are discussed below.
                   4418:    */
                   4419:   macros: {
                   4420:     displaystyle:      ['HandleStyle','D'],
                   4421:     textstyle:         ['HandleStyle','T'],
                   4422:     scriptstyle:       ['HandleStyle','S'],
                   4423:     scriptscriptstyle: ['HandleStyle','SS'],
                   4424:     
                   4425:     rm:                ['HandleFont',0],
                   4426:     mit:               ['HandleFont',1],
                   4427:     oldstyle:          ['HandleFont',1],
                   4428:     cal:               ['HandleFont',2],
                   4429:     it:                ['HandleFont',4],
                   4430:     bf:                ['HandleFont',6],
                   4431:     
                   4432:     left:              'HandleLeft',
                   4433:     right:             'HandleRight',
                   4434: 
                   4435:     arcsin:       ['NamedOp',0],
                   4436:     arccos:       ['NamedOp',0],
                   4437:     arctan:       ['NamedOp',0],
                   4438:     arg:          ['NamedOp',0],
                   4439:     cos:          ['NamedOp',0],
                   4440:     cosh:         ['NamedOp',0],
                   4441:     cot:          ['NamedOp',0],
                   4442:     coth:         ['NamedOp',0],
                   4443:     csc:          ['NamedOp',0],
                   4444:     deg:          ['NamedOp',0],
                   4445:     det:           'NamedOp',
                   4446:     dim:          ['NamedOp',0],
                   4447:     exp:          ['NamedOp',0],
                   4448:     gcd:           'NamedOp',
                   4449:     hom:          ['NamedOp',0],
                   4450:     inf:           'NamedOp',
                   4451:     ker:          ['NamedOp',0],
                   4452:     lg:           ['NamedOp',0],
                   4453:     lim:           'NamedOp',
                   4454:     liminf:       ['NamedOp',null,'lim<SPAN STYLE="margin-left: '+1/6+'em"></SPAN>inf'],
                   4455:     limsup:       ['NamedOp',null,'lim<SPAN STYLE="margin-left: '+1/6+'em"></SPAN>sup'],
                   4456:     ln:           ['NamedOp',0],
                   4457:     log:          ['NamedOp',0],
                   4458:     max:           'NamedOp',
                   4459:     min:           'NamedOp',
                   4460:     Pr:            'NamedOp',
                   4461:     sec:          ['NamedOp',0],
                   4462:     sin:          ['NamedOp',0],
                   4463:     sinh:         ['NamedOp',0],
                   4464:     sup:           'NamedOp',
                   4465:     tan:          ['NamedOp',0],
                   4466:     tanh:         ['NamedOp',0],
                   4467: 
                   4468:     vcenter:        ['HandleAtom','vcenter'],
                   4469:     overline:       ['HandleAtom','overline'],
                   4470:     underline:      ['HandleAtom','underline'],
                   4471:     over:            'HandleOver',
                   4472:     overwithdelims:  'HandleOver',
                   4473:     atop:            'HandleOver',
                   4474:     atopwithdelims:  'HandleOver',
                   4475:     above:           'HandleOver',
                   4476:     abovewithdelims: 'HandleOver',
                   4477:     brace:           ['HandleOver','\\{','\\}'],
                   4478:     brack:           ['HandleOver','[',']'],
                   4479:     choose:          ['HandleOver','(',')'],
                   4480:     
                   4481:     overbrace:       ['HandleLeaders','downbrace',1],
                   4482:     underbrace:      ['HandleLeaders','upbrace',1,1],
                   4483:     overrightarrow:  ['HandleLeaders','rightarrow'],
                   4484:     overleftarrow:   ['HandleLeaders','leftarrow'],
                   4485: 
                   4486:     llap:            'HandleLap',
                   4487:     rlap:            'HandleLap',
                   4488:     ulap:            'HandleLap',
                   4489:     dlap:            'HandleLap',
                   4490:     raise:           'RaiseLower',
                   4491:     lower:           'RaiseLower',
                   4492:     moveleft:        'MoveLeftRight',
                   4493:     moveright:       'MoveLeftRight',
                   4494: 
                   4495:     frac:            'Frac',
                   4496:     root:            'Root',
                   4497:     sqrt:            'Sqrt',
                   4498: 
                   4499:     //  TeX substitution macros
                   4500:     hbar:               ['Macro','\\hbarchar\\kern-.5em h'],
                   4501:     ne:                 ['Macro','\\not='],
                   4502:     neq:                ['Macro','\\not='],
                   4503:     notin:              ['Macro','\\mathrel{\\rlap{\\kern2mu/}}\\in'],
                   4504:     cong:               ['Macro','\\mathrel{\\lower2mu{\\mathrel{{\\rlap{=}\\raise6mu\\sim}}}}'],
                   4505:     bmod:               ['Macro','\\mathbin{\\rm mod}'],
                   4506:     pmod:               ['Macro','\\kern 18mu ({\\rm mod}\\,\\,#1)',1],
                   4507:     'int':              ['Macro','\\intop\\nolimits'],
                   4508:     oint:               ['Macro','\\ointop\\nolimits'],
                   4509:     doteq:              ['Macro','\\buildrel\\textstyle.\\over='],
                   4510:     ldots:              ['Macro','\\mathinner{\\ldotp\\ldotp\\ldotp}'],
                   4511:     cdots:              ['Macro','\\mathinner{\\cdotp\\cdotp\\cdotp}'],
1.2     ! albertel 4512:     vdots:              ['Macro','\\mathinner{\\rlap{\\raise8pt{.\\rule 0pt 6pt 0pt}}\\rlap{\\raise4pt{.}}.}'],
1.1       albertel 4513:     ddots:              ['Macro','\\mathinner{\\kern1mu\\raise7pt{\\rule 0pt 7pt 0pt .}\\kern2mu\\raise4pt{.}\\kern2mu\\raise1pt{.}\\kern1mu}'],
                   4514:     joinrel:            ['Macro','\\mathrel{\\kern-4mu}'],
                   4515:     relbar:             ['Macro','\\mathrel{\\smash-}'], // \smash, because - has the same height as +
                   4516:     Relbar:             ['Macro','\\mathrel='],
                   4517:     bowtie:             ['Macro','\\mathrel\\triangleright\\joinrel\\mathrel\\triangleleft'],
                   4518:     models:             ['Macro','\\mathrel|\\joinrel='],
                   4519:     mapsto:             ['Macro','\\mapstochar\\rightarrow'],
                   4520:     rightleftharpoons:  ['Macro','\\vcenter{\\mathrel{\\rlap{\\raise3mu{\\rightharpoonup}}}\\leftharpoondown}'],
                   4521:     hookrightarrow:     ['Macro','\\lhook\\joinrel\\rightarrow'],
                   4522:     hookleftarrow:      ['Macro','\\leftarrow\\joinrel\\rhook'],
                   4523:     Longrightarrow:     ['Macro','\\Relbar\\joinrel\\Rightarrow'],
                   4524:     longrightarrow:     ['Macro','\\relbar\\joinrel\\rightarrow'],
                   4525:     longleftarrow:      ['Macro','\\leftarrow\\joinrel\\relbar'],
                   4526:     Longleftarrow:      ['Macro','\\Leftarrow\\joinrel\\Relbar'],
                   4527:     longmapsto:         ['Macro','\\mapstochar\\char{cmsy10}{0}\\joinrel\\rightarrow'],
                   4528:     longleftrightarrow: ['Macro','\\leftarrow\\joinrel\\rightarrow'],
                   4529:     Longleftrightarrow: ['Macro','\\Leftarrow\\joinrel\\Rightarrow'],
                   4530:     iff:                ['Macro','\\;\\Longleftrightarrow\\;'],
                   4531:     mathrm:             ['Macro','{\\rm #1}',1],
                   4532:     mathbf:             ['Macro','{\\bf #1}',1],
                   4533:     mathbb:             ['Macro','{\\bf #1}',1],
                   4534:     mathit:             ['Macro','{\\it #1}',1],
                   4535: 
                   4536:     TeX:                ['Macro','T\\kern-.1667em\\lower.5ex{E}\\kern-.125em X'],
                   4537: 
                   4538:     limits:       ['Limits',1],
                   4539:     nolimits:     ['Limits',0],
                   4540: 
                   4541:     ',':          ['Spacer',1/6],
                   4542:     ':':          ['Spacer',1/6],  // for LaTeX
                   4543:     '>':          ['Spacer',2/9],
                   4544:     ';':          ['Spacer',5/18],
                   4545:     '!':          ['Spacer',-1/6],
                   4546:     enspace:      ['Spacer',1/2],
                   4547:     quad:         ['Spacer',1],
                   4548:     qquad:        ['Spacer',2],
                   4549:     thinspace:    ['Spacer',1/6],
                   4550:     negthinspace: ['Spacer',-1/6],
                   4551:     
                   4552:     hskip:         'Hskip',
                   4553:     kern:          'Hskip',
1.2     ! albertel 4554:     rule:          ['Rule','colored'],
1.1       albertel 4555:     space:         ['Rule','blank'],
                   4556:     
                   4557:     big:        ['MakeBig','ord',0.85],
                   4558:     Big:        ['MakeBig','ord',1.15],
                   4559:     bigg:       ['MakeBig','ord',1.45],
                   4560:     Bigg:       ['MakeBig','ord',1.75],
                   4561:     bigl:       ['MakeBig','open',0.85],
                   4562:     Bigl:       ['MakeBig','open',1.15],
                   4563:     biggl:      ['MakeBig','open',1.45],
                   4564:     Biggl:      ['MakeBig','open',1.75],
                   4565:     bigr:       ['MakeBig','close',0.85],
                   4566:     Bigr:       ['MakeBig','close',1.15],
                   4567:     biggr:      ['MakeBig','close',1.45],
                   4568:     Biggr:      ['MakeBig','close',1.75],
                   4569:     bigm:       ['MakeBig','rel',0.85],
                   4570:     Bigm:       ['MakeBig','rel',1.15],
                   4571:     biggm:      ['MakeBig','rel',1.45],
                   4572:     Biggm:      ['MakeBig','rel',1.75],
                   4573:     
                   4574:     mathord:    ['HandleAtom','ord'],
                   4575:     mathop:     ['HandleAtom','op'],
                   4576:     mathopen:   ['HandleAtom','open'],
                   4577:     mathclose:  ['HandleAtom','close'],
                   4578:     mathbin:    ['HandleAtom','bin'],
                   4579:     mathrel:    ['HandleAtom','rel'],
                   4580:     mathpunct:  ['HandleAtom','punct'],
                   4581:     mathinner:  ['HandleAtom','inner'],
                   4582:     
                   4583:     mathchoice: 'MathChoice',
                   4584:     buildrel:   'BuildRel',
                   4585:     
                   4586:     hbox:       'HBox',
                   4587:     text:       'HBox',
                   4588:     mbox:       'HBox',
                   4589:     fbox:       'FBox',
                   4590: 
                   4591:     strut:      'Strut',
                   4592:     mathstrut:  ['Macro','\\vphantom{(}'],
                   4593:     phantom:    ['Phantom',1,1],
                   4594:     vphantom:   ['Phantom',1,0],
                   4595:     hphantom:   ['Phantom',0,1],
                   4596:     smash:      'Smash',
                   4597:     
1.2     ! albertel 4598:     acute:      ['MathAccent', [7,0,0x13]],
        !          4599:     grave:      ['MathAccent', [7,0,0x12]],
        !          4600:     ddot:       ['MathAccent', [7,0,0x7F]],
        !          4601:     tilde:      ['MathAccent', [7,0,0x7E]],
        !          4602:     bar:        ['MathAccent', [7,0,0x16]],
        !          4603:     breve:      ['MathAccent', [7,0,0x15]],
        !          4604:     check:      ['MathAccent', [7,0,0x14]],
        !          4605:     hat:        ['MathAccent', [7,0,0x5E]],
        !          4606:     vec:        ['MathAccent', [0,1,0x7E]],
        !          4607:     dot:        ['MathAccent', [7,0,0x5F]],
        !          4608:     widetilde:  ['MathAccent', [0,3,0x65]],
        !          4609:     widehat:    ['MathAccent', [0,3,0x62]],
1.1       albertel 4610: 
                   4611:     '_':        ['Replace','ord','_','normal',-.4,.1],
                   4612:     ' ':        ['Replace','ord','&nbsp;','normal'],
                   4613:     angle:      ['Replace','ord','&#x2220;','normal'],
                   4614:         
                   4615:     matrix:     'Matrix',
                   4616:     array:      'Matrix',  // ### still need to do alignment options ###
                   4617:     pmatrix:    ['Matrix','(',')','c'],
                   4618:     cases:      ['Matrix','\\{','.',['l','l']],
                   4619:     cr:         'HandleRow',
                   4620:     '\\':       'HandleRow',
                   4621:     
                   4622:     //  LaTeX
                   4623:     begin:      'Begin',
                   4624:     end:        'End',
                   4625:     tiny:       ['HandleSize',0],
                   4626:     Tiny:       ['HandleSize',1],  // non-standard
                   4627:     scriptsize: ['HandleSize',2],
                   4628:     small:      ['HandleSize',3],
                   4629:     normalsize: ['HandleSize',4],
                   4630:     large:      ['HandleSize',5],
                   4631:     Large:      ['HandleSize',6],
                   4632:     LARGE:      ['HandleSize',7],
                   4633:     huge:       ['HandleSize',8],
                   4634:     Huge:       ['HandleSize',9],
                   4635:     dots:       ['Macro','\\ldots'],
                   4636: 
                   4637:     //  Extensions to TeX
                   4638:     color:      'Color',
                   4639:     href:       'Href',
                   4640:     'class':    'Class',
                   4641:     style:      'Style',
                   4642:     unicode:    'Unicode',
                   4643: 
                   4644:     //  debugging and test routines
1.2     ! albertel 4645:     'char':     'Char'
1.1       albertel 4646:   },
                   4647:   
                   4648:   /*
                   4649:    *  LaTeX environments
                   4650:    */
                   4651:   environments: {
                   4652:     array:      'Array',
                   4653:     matrix:     ['Array',null,null,'c'],
                   4654:     pmatrix:    ['Array','(',')','c'],
                   4655:     bmatrix:    ['Array','[',']','c'],
                   4656:     Bmatrix:    ['Array','\\{','\\}','c'],
                   4657:     vmatrix:    ['Array','\\vert','\\vert','c'],
                   4658:     Vmatrix:    ['Array','\\Vert','\\Vert','c'],
                   4659:     cases:      ['Array','\\{','.','ll'],
                   4660:     eqnarray:   ['Array',null,null,'rcl',[5/18,5/18]]
                   4661:   },
                   4662: 
                   4663:   /*
                   4664:    *  The horizontally stretchable delimiters
                   4665:    */
                   4666:   leaders: {
1.2     ! albertel 4667:     downbrace:  {left: [3,0x7A], lmid: [3,0x7D], rmid: [3,0x7C], right: [3,0x7B]},
        !          4668:     upbrace:    {left: [3,0x7C], lmid: [3,0x7B], rmid: [3,0x7A], right: [3,0x7D]},
        !          4669:     leftarrow:  {left: [2,0x20], rep:  [2,0x00]},
        !          4670:     rightarrow: {rep:  [2,0x00], right: [2,0x21]}
1.1       albertel 4671:   },
                   4672: 
                   4673: 
                   4674:   /***************************************************************************/
                   4675: 
                   4676:   /*
                   4677:    *  Add special characters to list above.  (This makes it possible
                   4678:    *  to define them in a variable that the user can change.)
                   4679:    */
                   4680:   AddSpecial: function (obj) {
                   4681:     for (var id in obj) {
                   4682:       jsMath.Parser.prototype.special[jsMath.Parser.prototype[id]] = obj[id];
                   4683:     }
                   4684:   },
                   4685: 
                   4686:   /*
                   4687:    *  Throw an error
                   4688:    */
                   4689:   Error: function (s) {
                   4690:    this.i = this.string.length;
                   4691:     if (s.error) {this.error = s.error} else {
                   4692:       if (!this.error) {this.error = s}
                   4693:     }
                   4694:   },
                   4695: 
                   4696:   /***************************************************************************/
                   4697: 
                   4698:   /*
                   4699:    *  Check if the next character is a space
                   4700:    */
                   4701:   nextIsSpace: function () {
                   4702:     return this.string.charAt(this.i) == ' ';
                   4703:   },
                   4704: 
                   4705:   /*
                   4706:    *  Parse a substring to get its mList, and return it.
                   4707:    *  Check that no errors occured
                   4708:    */
                   4709:   Process: function (arg) {
                   4710:     var data = this.mlist.data;
                   4711:     arg = jsMath.Parse(arg,data.font,data.size,data.style);
                   4712:       if (arg.error) {this.Error(arg); return}
                   4713:     if (arg.mlist.Length() == 0) {return null}
                   4714:     if (arg.mlist.Length() == 1) {
                   4715:       var atom = arg.mlist.Last();
                   4716:       if (atom.atom && atom.type == 'ord' && atom.nuc &&
                   4717:          !atom.sub && !atom.sup && (atom.nuc.type == 'text' || atom.nuc.type == 'TeX'))
                   4718:              {return atom.nuc}
                   4719:     }
                   4720:     return {type: 'mlist', mlist: arg.mlist};
                   4721:   },
                   4722: 
                   4723:   /*
                   4724:    *  Get and return a control-sequence name from the TeX string
                   4725:    */
                   4726:   GetCommand: function () {
                   4727:     var letter = /^([a-z]+|.) ?/i;
                   4728:     var cmd = letter.exec(this.string.slice(this.i));
                   4729:     if (cmd) {this.i += cmd[1].length; return cmd[1]}
                   4730:     this.Error("Missing control sequnece name at end of string or argument"); return
                   4731:   },
                   4732: 
                   4733:   /*
                   4734:    *  Get and return a TeX argument (either a single character or control sequence,
                   4735:    *  or the contents of the next set of braces).
                   4736:    */
                   4737:   GetArgument: function (name,noneOK) {
                   4738:     while (this.nextIsSpace()) {this.i++}
                   4739:     if (this.i >= this.string.length) {if (!noneOK) this.Error("Missing argument for "+name); return}
                   4740:     if (this.string.charAt(this.i) == this.close) {if (!noneOK) this.Error("Extra close brace"); return}
                   4741:     if (this.string.charAt(this.i) == this.cmd) {this.i++; return this.cmd+this.GetCommand()}
                   4742:     if (this.string.charAt(this.i) != this.open) {return this.string.charAt(this.i++)}
                   4743:     var j = ++this.i; var pcount = 1; var c = '';
                   4744:     while (this.i < this.string.length) {
                   4745:       c = this.string.charAt(this.i++);
                   4746:       if (c == this.cmd) {this.i++}
                   4747:       else if (c == this.open) {pcount++}
                   4748:       else if (c == this.close) {
                   4749:         if (pcount == 0) {this.Error("Extra close brace"); return}
                   4750:         if (--pcount == 0) {return this.string.slice(j,this.i-1)}
                   4751:       }
                   4752:     }
                   4753:     this.Error("Missing close brace");
                   4754:   },
                   4755: 
                   4756:   /*
                   4757:    *  Get an argument and process it into an mList
                   4758:    */
                   4759:   ProcessArg: function (name) {
                   4760:     var arg = this.GetArgument(name); if (this.error) return;
                   4761:     return this.Process(arg);
                   4762:   },
                   4763: 
                   4764:   /*
                   4765:    *  Get the name of a delimiter (check it in the delimiter list).
                   4766:    */
                   4767:   GetDelimiter: function (name) {
                   4768:     while (this.nextIsSpace()) {this.i++}
                   4769:     var c = this.string.charAt(this.i);
                   4770:     if (this.i < this.string.length) {
                   4771:       this.i++;
                   4772:       if (c == this.cmd) {c = '\\'+this.GetCommand(name); if (this.error) return}
                   4773:       if (this.delimiter[c] != null) {return this.delimiter[c]}
                   4774:     }
                   4775:     this.Error("Missing or unrecognized delimiter for "+name);
                   4776:   },
                   4777:   
                   4778:   /*
                   4779:    *  Get a dimension (including its units).
                   4780:    *  Convert the dimen to em's, except for mu's, which must be
                   4781:    *  converted when typeset.
                   4782:    */
                   4783:   GetDimen: function (name,nomu) {
1.2     ! albertel 4784:     var rest; var advance = 0;
        !          4785:     if (this.nextIsSpace()) {this.i++}
        !          4786:     if (this.string.charAt(this.i) == '{') {
        !          4787:       rest = this.GetArgument(name);
        !          4788:     } else {
        !          4789:       rest = this.string.slice(this.i);
        !          4790:       advance = 1;
        !          4791:     }
1.1       albertel 4792:     var match = rest.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/);
                   4793:     if (!match) {this.Error("Missing dimension or its units for "+name); return}
1.2     ! albertel 4794:     if (advance) {
        !          4795:       this.i += match[0].length;
        !          4796:       if (this.nextIsSpace()) {this.i++}
        !          4797:     }
1.1       albertel 4798:     var d = match[1]-0;
                   4799:     if (match[4] == 'px') {d /= jsMath.em}
                   4800:     else if (match[4] == 'pt') {d /= 10}
                   4801:     else if (match[4] == 'ex') {d *= jsMath.TeX.x_height}
                   4802:     else if (match[4] == 'mu') {if (nomu) {d = d/18} else {d = [d,'mu']}}
                   4803:     return d;
                   4804:   },
                   4805: 
                   4806:   /*
                   4807:    *  Get the next non-space character
                   4808:    */
                   4809:   GetNext: function () {
                   4810:     while (this.nextIsSpace()) {this.i++}
                   4811:     return this.string.charAt(this.i);
                   4812:   },
                   4813:   
                   4814:   /*
                   4815:    *  Get an optional LaTeX argument in brackets
                   4816:    */
                   4817:   GetBrackets: function (name) {
                   4818:     var c = this.GetNext(); if (c != '[') return '';
                   4819:     var start = ++this.i; var pcount = 0;
                   4820:     while (this.i < this.string.length) {
                   4821:       var c = this.string.charAt(this.i++);
                   4822:       if (c == '{') {pcount++}
                   4823:       else if (c == '}') {
                   4824:         if (pcount == 0)
                   4825:           {this.Error("Extra close brace while looking for ']'"); return}
                   4826:         pcount --;
                   4827:       } else if (c == this.cmd) {
                   4828:         this.i++;
                   4829:       } else if (c == ']') {
                   4830:         if (pcount == 0) {return this.string.slice(start,this.i-1)}
                   4831:       }
                   4832:     }
                   4833:     this.Error("Couldn't find closing ']' for argument to "+this.cmd+name);
                   4834:   },
                   4835:   
                   4836:   /*
                   4837:    *  Get everything up to the given control sequence name (token)
                   4838:    */
                   4839:   GetUpto: function (name,token) {
                   4840:     while (this.nextIsSpace()) {this.i++}
                   4841:     var start = this.i; var pcount = 0;
                   4842:     while (this.i < this.string.length) {
                   4843:       var c = this.string.charAt(this.i++);
                   4844:       if (c == '{') {pcount++}
                   4845:       else if (c == '}') {
                   4846:         if (pcount == 0)
                   4847:           {this.Error("Extra close brace while looking for "+this.cmd+token); return}
                   4848:         pcount --;
                   4849:       } else if (c == this.cmd) {
                   4850:         // really need separate counter for begin/end
                   4851:         // and it should really be a stack (new pcount for each begin)
                   4852:         if (this.string.slice(this.i,this.i+5) == "begin") {pcount++; this.i+=4}
                   4853:         else if (this.string.slice(this.i,this.i+3) == "end") {
                   4854:           if (pcount > 0) {pcount--; this.i += 2}
                   4855:         }
                   4856:         if (pcount == 0)  {
                   4857:           if (this.string.slice(this.i,this.i+token.length) == token) {
                   4858:             c = this.string.charAt(this.i+token.length);
                   4859:             if (c.match(/[^a-z]/i) || !token.match(/[a-z]/i)) {
                   4860:               var arg = this.string.slice(start,this.i-1);
                   4861:               this.i += token.length;
                   4862:               return arg;
                   4863:             }
                   4864:           }
                   4865:         }
                   4866:         this.i++;
                   4867:       }
                   4868:     }
                   4869:     this.Error("Couldn't find "+this.cmd+token+" for "+name);
                   4870:   },
                   4871: 
                   4872:   /*
                   4873:    *  Get a parameter delimited by a control sequence, and
                   4874:    *  process it to get its mlist
                   4875:    */
                   4876:   ProcessUpto: function (name,token) {
                   4877:     var arg = this.GetUpto(name,token); if (this.error) return;
                   4878:     return this.Process(arg);
                   4879:   },
                   4880: 
                   4881:   /*
                   4882:    *  Get everything up to \end{env}
                   4883:    */
                   4884:   GetEnd: function (env) {
                   4885:     var body = ''; var name = '';
                   4886:     while (name != env) {
                   4887:       body += this.GetUpto('begin{'+env+'}','end'); if (this.error) return;
                   4888:       name = this.GetArgument(this.cmd+'end'); if (this.error) return;
                   4889:     }
                   4890:     return body;
                   4891:   },
                   4892:   
                   4893: 
                   4894:   /***************************************************************************/
                   4895: 
                   4896: 
                   4897:   /*
                   4898:    *  Ignore spaces
                   4899:    */
                   4900:   Space: function () {},
                   4901: 
                   4902:   /*
                   4903:    *  Collect together any primes and convert them to a superscript
                   4904:    */
                   4905:   Prime: function (c) {
                   4906:     var base = this.mlist.Last();
                   4907:     if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))
                   4908:        {base = this.mlist.Add(jsMath.mItem.Atom('ord',null))}
                   4909:     if (base.sup) {this.Error("Prime causes double exponent: use braces to clarify"); return}
                   4910:     var sup = '';
                   4911:     while (c == "'") {sup += '\\prime'; c = this.GetNext(); if (c == "'") {this.i++}}
                   4912:     base.sup = this.Process(sup);
                   4913:   },
                   4914: 
                   4915:   /*
                   4916:    *  Raise or lower its parameter by a given amount
                   4917:    *  @@@ Note that this is different from TeX, which requires an \hbox @@@
                   4918:    *  ### make this work with mu's ###
                   4919:    */
                   4920:   RaiseLower: function (name) {
                   4921:     var h = this.GetDimen(this.cmd+name,1); if (this.error) return;
                   4922:     var box = this.ProcessArg(this.cmd+name); if (this.error) return;
                   4923:     if (name == 'lower') {h = -h}
                   4924:     this.mlist.Add(new jsMath.mItem('raise',{nuc: box, raise: h}));
                   4925:   },
                   4926:   
                   4927:   /*
                   4928:    *  Shift an expression to the right or left
                   4929:    *  @@@ Note that this is different from TeX, which requires a \vbox @@@
                   4930:    *  ### make this work with mu's ###
                   4931:    */
                   4932:   MoveLeftRight: function (name) {
                   4933:     var x = this.GetDimen(this.cmd+name,1); if (this.error) return;
                   4934:     var box = this.ProcessArg(this.cmd+name); if (this.error) return;
                   4935:     if (name == 'moveleft') {x = -x}
                   4936:     this.mlist.Add(jsMath.mItem.Space(x));
                   4937:     this.mlist.Add(jsMath.mItem.Atom('ord',box));
                   4938:     this.mlist.Add(jsMath.mItem.Space(-x));
                   4939:   },
                   4940: 
                   4941:   /*
                   4942:    *  Show the argument in a particular color
                   4943:    *  ### doesn't affect horizontal rules; can we fix that? ###
                   4944:    */
                   4945:   Color: function (name) {
                   4946:     var color = this.GetArgument(this.cmd+name); if (this.error) return;
                   4947:     // check that it looks like a color?
                   4948:     this.AddHTML(name,['<SPAN STYLE="color: '+color+'">','</SPAN>']);
                   4949:   },
                   4950:   
                   4951:   /*
                   4952:    *  Make the argument be a link
                   4953:    */
                   4954:   Href: function (name) {
                   4955:     var href = this.GetArgument(this.cmd+name); if (this.error) return;
                   4956:     this.AddHTML(name,['<A CLASS="mathlink" HREF="'+href+'">','</A>']);
                   4957:   },
                   4958:   
                   4959:   /*
                   4960:    *  Apply a CSS class to the argument
                   4961:    */
                   4962:   Class: function (name) {
                   4963:     var clss = this.GetArgument(this.cmd+name); if (this.error) return;
                   4964:     this.AddHTML(name,['<SPAN CLASS="'+clss+'">','</SPAN>']);
                   4965:   },
                   4966:   
                   4967:   /*
                   4968:    *  Apply a CSS style to the argument
                   4969:    */
                   4970:   Style: function (name) {
                   4971:     var style = this.GetArgument(this.cmd+name); if (this.error) return;
                   4972:     this.AddHTML(name,['<SPAN STYLE="'+style+'">','</SPAN>']);
                   4973:   },
                   4974:   
                   4975:   /*
                   4976:    *  Insert some raw HTML around the argument (this will not affect
                   4977:    *  the spacing or other TeX features)
                   4978:    */
                   4979:   AddHTML: function (name,params) {
                   4980:     var data = this.mlist.data;
                   4981:     var arg = this.GetArgument(this.cmd+name); if (this.error) return;
                   4982:     arg = jsMath.Parse(arg,data.font,data.size,data.style);
                   4983:       if (arg.error) {this.Error(arg); return}
                   4984:     this.mlist.Add(jsMath.mItem.HTML(params[0]));
                   4985:     for (var i = 0; i < arg.mlist.Length(); i++) {this.mlist.Add(arg.mlist.Get(i))}
                   4986:     this.mlist.Add(jsMath.mItem.HTML(params[1]));
                   4987:   },
                   4988:   
                   4989:   /*
                   4990:    *  Insert a unicode reference as an Ord atom.  Its argument should
                   4991:    *  be the unicode code point, e.g. \unicode{8211}, or \unicode{x203F}.
                   4992:    *  You can also specify the height and depth in ems, e.g.,
                   4993:    *  \unicode{8211,.6,-.3}
                   4994:    */
                   4995:   Unicode: function (name) {
                   4996:     var arg = this.GetArgument(this.cmd+name); if (this.error) return;
                   4997:     arg = arg.split(','); arg[0] = '&#'+arg[0]+';';
                   4998:     if (!arg[1]) {arg[1] = 'normal'}
                   4999:     this.mlist.Add(jsMath.mItem.TextAtom('ord',arg[0],arg[1],arg[2],arg[3]));
                   5000:   },
                   5001:   
                   5002:   /*
                   5003:    *  Implements \frac{num}{den}
                   5004:    */
                   5005:   Frac: function (name) {
                   5006:     var num = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5007:     var den = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5008:     this.mlist.Add(jsMath.mItem.Fraction('over',num,den));
                   5009:   },
                   5010:   
                   5011:   /*
                   5012:    *  Implements \sqrt[n]{...}
                   5013:    */
                   5014:   Sqrt: function (name) {
                   5015:     var n = this.GetBrackets(this.cmd+name); if (this.error) return;
                   5016:     var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5017:     box = jsMath.mItem.Atom('radical',arg);
                   5018:     if (this.n != '') {box.root = this.Process(n); if (this.error) return}
                   5019:     this.mlist.Add(box);
                   5020:   },
                   5021: 
                   5022:   /*
                   5023:    *  Implements \root...\of{...}
                   5024:    */
                   5025:   Root: function (name) {
                   5026:     var n = this.ProcessUpto(this.cmd+name,'of'); if (this.error) return;
                   5027:     var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5028:     box = jsMath.mItem.Atom('radical',arg);
                   5029:     box.root = n; this.mlist.Add(box);
                   5030:   },
                   5031:   
                   5032: 
                   5033:   /*
                   5034:    *  Implements \mathchoice{}{}{}{}
                   5035:    */
                   5036:   MathChoice: function (name) {
                   5037:     var D  = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5038:     var T  = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5039:     var S  = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5040:     var SS = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5041:     var box = new jsMath.mItem('choice',{D: D, T: T, S: S, SS: SS});
                   5042:     this.mlist.Add(new jsMath.mItem('choice',{D: D, T: T, S: S, SS: SS}));
                   5043:   },
                   5044:   
                   5045:   /*
                   5046:    *  Implements \buildrel...\over{...}
                   5047:    */
                   5048:   BuildRel: function (name) {
                   5049:     var top = this.ProcessUpto(this.cmd+name,'over'); if (this.error) return;
                   5050:     var bot = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5051:     var op = jsMath.mItem.Atom('op',bot);
                   5052:     op.limits = 1; op.sup = top;
                   5053:     this.mlist.Add(op);
                   5054:   },
                   5055: 
                   5056:   /*
                   5057:    *  Create a delimiter of the type and size specified in the parameters
                   5058:    */
                   5059:   MakeBig: function (name,data) {
                   5060:     var type = data[0]; var h = data[1] * jsMath.p_height;
                   5061:     var delim = this.GetDelimiter(this.cmd+name); if (this.error) return;
                   5062:     this.mlist.Add(jsMath.mItem.Atom(type,jsMath.Box.Delimiter(h,delim,'T')));
                   5063:   },
                   5064:   
                   5065:   /*
                   5066:    *  Insert the specified character in the given font.
                   5067:    */
                   5068:   Char: function (name) {
                   5069:     var font = this.GetArgument(this.cmd+name); if (this.error) return;
                   5070:     var n = this.GetArgument(this.cmd+name); if (this.error) return;
                   5071:     this.mlist.Add(jsMath.mItem.Typeset(jsMath.Box.TeX(n-0,font,'T',this.mlist.data.size)));
                   5072:     return;
                   5073:   },
                   5074:   
                   5075:   /*
                   5076:    *  Create an array or matrix.
                   5077:    */
                   5078:   Matrix: function (name,delim) {
                   5079:     var data = this.mlist.data;
                   5080:     var arg = this.GetArgument(this.cmd+name); if (this.error) return;
                   5081:     var parse = new jsMath.Parser(arg+'\\\\',null,data.size);
                   5082:     parse.matrix = name; parse.row = []; parse.table = [];
                   5083:     parse.Parse(); if (parse.error) {this.Error(parse); return}
                   5084:     parse.HandleRow(name,1);  // be sure the last row is recorded
                   5085:     var box = jsMath.Box.Layout(data.size,parse.table,delim[2]);
                   5086:     // Add parentheses, if needed
                   5087:     if (delim[0] && delim[1]) {
                   5088:       var left  = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[0]],'T');
                   5089:       var right = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[1]],'T');
                   5090:       box = jsMath.Box.SetList([left,box,right],data.style,data.size);
                   5091:     }
                   5092:     this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));
                   5093:   },
                   5094:   
                   5095:   /*
                   5096:    *  When we see an '&', try to add a matrix entry to the row data.
                   5097:    *  (Use all the data in the current mList, and then clear it)
                   5098:    */
                   5099:   HandleEntry: function (name) {
                   5100:     if (!this.matrix) 
                   5101:       {this.Error(name+" can only appear in a matrix or array"); return}
                   5102:     if (this.mlist.data.openI != null) {
                   5103:       var open = this.mlist.Get(this.mlist.data.openI);
                   5104:       if (open.left) {this.Error("Missing "+this.cmd+"right")}
                   5105:         else {this.Error("Missing close brace")}
                   5106:     }
                   5107:     if (this.mlist.data.overI != null) {this.mlist.Over()}
                   5108:     var data = this.mlist.data;
                   5109:     this.mlist.Atomize('T',data.size); var box = this.mlist.Typeset('T',data.size);
                   5110:     this.row[this.row.length] = box;
                   5111:     this.mlist = new jsMath.mList(null,null,data.size); 
                   5112:   },
                   5113:   
                   5114:   /*
                   5115:    *  When we see a \cr or \\, try to add a row to the table
                   5116:    */
                   5117:   HandleRow: function (name,last) {
                   5118:     if (!this.matrix)
                   5119:       {this.Error(this.cmd+name+" can only appear in a matrix or array"); return}
                   5120:     this.HandleEntry(name);
                   5121:     if (!last || this.row.length > 1 || this.row[0].format != 'null')
                   5122:       {this.table[this.table.length] = this.row}
                   5123:     this.row = [];
                   5124:   },
                   5125:   
                   5126:   /*
                   5127:    *  LaTeX array environment
                   5128:    */
                   5129:   Array: function (name,delim) {
                   5130:     var columns = delim[2]; var cspacing = delim[3];
                   5131:     if (!columns) {
                   5132:       columns = this.GetArgument(this.cmd+'begin{'+name+'}');
                   5133:       if (this.error) return;
                   5134:     }
                   5135:     columns = columns.replace(/[^clr]/g,'');
                   5136:     columns = columns.split('');
                   5137:     var data = this.mlist.data;
                   5138:     var arg = this.GetEnd(name); if (this.error) return;
                   5139:     var parse = new jsMath.Parser(arg+'\\\\',null,data.size);
                   5140:     parse.matrix = name; parse.row = []; parse.table = [];
                   5141:     parse.Parse(); if (parse.error) {this.Error(parse); return}
                   5142:     parse.HandleRow(name,1);  // be sure the last row is recorded
                   5143:     var box = jsMath.Box.Layout(data.size,parse.table,columns,cspacing);
                   5144:     // Add parentheses, if needed
                   5145:     if (delim[0] && delim[1]) {
                   5146:       var left  = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[0]],'T');
                   5147:       var right = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[1]],'T');
                   5148:       box = jsMath.Box.SetList([left,box,right],data.style,data.size);
                   5149:     }
                   5150:     this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));
                   5151:   },
                   5152:   
                   5153:   /*
                   5154:    *  LaTeX \begin{env}
                   5155:    */
                   5156:   Begin: function (name) {
                   5157:     var env = this.GetArgument(this.cmd+name); if (this.error) return;
                   5158:     if (env.match(/[^a-z*]/i)) {this.Error('Invalid environment name "'+env+'"'); return}
                   5159:     if (!this.environments[env]) {this.Error('Unknown environment "'+env+'"'); return}
                   5160:     var cmd = this.environments[env];
                   5161:     if (typeof(cmd) == "string") {cmd = [cmd]}
                   5162:     this[cmd[0]](env,cmd.slice(1));
                   5163:   },
                   5164:   
                   5165:   /*
                   5166:    *  LaTeX \end{env}
                   5167:    */
                   5168:   End: function (name) {
                   5169:     var env = this.GetArgument(this.cmd+name); if (this.error) return;
                   5170:     this.Error(this.cmd+name+'{'+env+'} without matching '+this.cmd+'begin');
                   5171:   },
                   5172: 
                   5173:   /*
                   5174:    *  Add a fixed amount of horizontal space
                   5175:    */
                   5176:   Spacer: function (name,w) {
                   5177:     this.mlist.Add(jsMath.mItem.Space(w-0));
                   5178:   },
                   5179:   
                   5180:   /*
                   5181:    *  Add horizontal space given by the argument
                   5182:    */
                   5183:   Hskip: function (name) {
                   5184:     var w = this.GetDimen(this.cmd+name); if (this.error) return;
                   5185:     this.mlist.Add(jsMath.mItem.Space(w));
                   5186:   },
                   5187: 
                   5188:   /*
                   5189:    *  Typeset the argument as plain text rather than math.
                   5190:    */
                   5191:   HBox: function (name) {
                   5192:     var text = this.GetArgument(this.cmd+name); if (this.error) return;
                   5193:     var box = jsMath.Box.InternalMath(text,this.mlist.data.size);
                   5194:     this.mlist.Add(jsMath.mItem.Typeset(box));
                   5195:   },
                   5196:   
                   5197:   /*
                   5198:    *  Implement \fbox{...}
                   5199:    */
                   5200:   FBox: function (name) {
                   5201:     var text = this.GetArgument(this.cmd+name); if (this.error) return;
                   5202:     var arg = jsMath.Box.InternalMath(text,this.mlist.data.size);
                   5203:     var f = 0.25 * jsMath.sizes[this.mlist.data.size]/100;
                   5204:     var box = jsMath.Box.Set(arg,this.mlist.data.style,this.mlist.data.size,1).Remeasured();
                   5205:     var frame = jsMath.HTML.Frame(-f,-box.d-f,box.w+2*f,box.h+box.d+2*f);
                   5206:     box.html = frame + box.html + jsMath.HTML.Spacer(f);
                   5207:     box.h += f; box.d += f; box.w +=2*f; box.x += f;
                   5208:     box.bh = Math.max(box.bh,box.h); box.bd = Math.max(box.bd,box.d);
                   5209:     this.mlist.Add(jsMath.mItem.Atom('ord',box));
                   5210:   },
                   5211:   
                   5212:   /*
                   5213:    *  Insert a rule of a particular width, height and depth
                   5214:    *  This replaces \hrule and \vrule
                   5215:    *  @@@ not a standard TeX command, and all three parameters must be given @@@
                   5216:    */
1.2     ! albertel 5217:   Rule: function (name,style) {
1.1       albertel 5218:     var w = this.GetDimen(this.cmd+name,1); if (this.error) return;
                   5219:     var h = this.GetDimen(this.cmd+name,1); if (this.error) return;
                   5220:     var d = this.GetDimen(this.cmd+name,1); if (this.error) return;
1.2     ! albertel 5221:     h += d; var html;
1.1       albertel 5222:     if (h != 0) {h = Math.max(1.05/jsMath.em,h)}
1.2     ! albertel 5223:     if (h == 0 || w == 0) {style = "blank"}
        !          5224:     if (w == 0) {
        !          5225:       html = '<IMG SRC="'+jsMath.blank+'" STYLE="'
        !          5226:                 + 'border:0px none; width:1px; margin-right:-1px; '
        !          5227:                 + 'height:'+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+'">';
        !          5228:     } else if (style == "blank") {
        !          5229:       html = '<IMG SRC="'+jsMath.blank+'" STYLE="border:0px none; '
        !          5230:                 + 'height:'+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+'; '
        !          5231:                 + 'width:' +jsMath.HTML.Em(w*jsMath.Browser.imgScale)+'">';
        !          5232:     } else {
        !          5233:       html = '<IMG SRC="'+jsMath.blank+'" STYLE="'
        !          5234:                 + 'position: relative; top:1px; height:1px; border:0px none; '
        !          5235:                 + 'border-top:'+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+' solid; '
        !          5236:                 + 'width:' +jsMath.HTML.Em(w*jsMath.Browser.imgScale)+'">';
        !          5237:     }
1.1       albertel 5238:     if (d) {
                   5239:       html = '<SPAN STYLE="vertical-align:'+jsMath.HTML.Em(-d)+'">'
                   5240:            +  html + '</SPAN>';
                   5241:     }
                   5242:     this.mlist.Add(jsMath.mItem.Typeset(new jsMath.Box('html',html,w,h-d,d)));
                   5243:   },
                   5244:   
                   5245:   /*
                   5246:    *  Inserts an empty box of a specific height and depth
                   5247:    */
                   5248:   Strut: function () {
                   5249:     var size = this.mlist.data.size;
                   5250:     var box = jsMath.Box.Text('','normal','T',size).Styled();
                   5251:     box.bh = box.bd = 0; box.h = .8; box.d = .3; box.w = 0;
                   5252:     this.mlist.Add(jsMath.mItem.Typeset(box));
                   5253:   },
                   5254:   
                   5255:   /*
                   5256:    *  Handles \phantom, \vphantom and \hphantom
                   5257:    */
                   5258:   Phantom: function (name,data) {
                   5259:     var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5260:     this.mlist.Add(new jsMath.mItem('phantom',{phantom: arg, v: data[0], h: data[1]}));
                   5261:   },
                   5262:   
                   5263:   /*
                   5264:    *  Implements \smash
                   5265:    */
                   5266:   Smash: function (name,data) {
                   5267:     var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5268:     this.mlist.Add(new jsMath.mItem('smash',{smash: arg}));
                   5269:   },
                   5270:   
                   5271:   /*
                   5272:    *  Puts an accent on the following argument
                   5273:    */
                   5274:   MathAccent: function (name,accent) {
                   5275:     var c = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5276:     var atom = jsMath.mItem.Atom('accent',c); atom.accent = accent[0];
                   5277:     this.mlist.Add(atom);
                   5278:   },
                   5279: 
                   5280:   /*
                   5281:    *  Handles functions and operators like sin, cos, sum, etc.
                   5282:    */
                   5283:   NamedOp: function (name,data) {
                   5284:     var a = (name.match(/[^acegm-su-z]/)) ? 1: 0;
                   5285:     var d = (name.match(/[gjpqy]/)) ? 1: 0;
                   5286:     if (data[1]) {name = data[1]}
                   5287:     var box = jsMath.mItem.TextAtom('op',name,'cmr10',a,d);
                   5288:     if (data[0] != null) {box.limits = data[0]}
                   5289:     this.mlist.Add(box);
                   5290:   },
                   5291: 
                   5292:   /*
                   5293:    *  Implements \limits
                   5294:    */
                   5295:   Limits: function (name,data) {
                   5296:     var atom = this.mlist.Last();
                   5297:     if (!atom || atom.type != 'op') 
                   5298:       {this.Error(this.cmd+name+" is allowed only on operators"); return}
                   5299:     atom.limits = data[0];
                   5300:   },
                   5301: 
                   5302:   /*
                   5303:    *  Implements macros like those created by \def.  The named control
                   5304:    *  sequence is replaced by the string given as the first data value.
                   5305:    *  If there is a second data value, this specifies how many arguments
                   5306:    *  the macro uses, and in this case, those arguments are substituted
                   5307:    *  for #1, #2, etc. within the replacement string.
                   5308:    *  
                   5309:    *  See the jsMath.Macro() command below for more details.
                   5310:    */
                   5311:   Macro: function (name,data) {
                   5312:     var text = data[0]
                   5313:     if (data[1]) {
                   5314:       var args = [];
                   5315:       for (var i = 0; i < data[1]; i++) 
                   5316:         {args[args.length] = this.GetArgument(this.cmd+name); if (this.error) return}
                   5317:       text = ''; var c; var i = 0;
                   5318:       while (i < data[0].length) {
                   5319:         c = data[0].charAt(i++);
                   5320:         if (c == '\\') {text += c + data[0].charAt(i++)}
                   5321:         else if (c == '#') {
                   5322:           c = data[0].charAt(i++);
                   5323:           if (c == "#") {text += c} else {
                   5324:             if (!c.match(/[1-9]/) || c > args.length)
                   5325:               {this.Error("Illegal macro argument reference"); return}
                   5326:             text += args[c-1];
                   5327:           }
                   5328:         } else {text += c}
                   5329:       }
                   5330:     }
                   5331:     this.string = text + this.string.slice(this.i);
                   5332:     this.i = 0;
                   5333:   },
                   5334:   
                   5335:   /*
                   5336:    *  Replace the control sequence with the given text
                   5337:    */
                   5338:   Replace: function (name,data) {
                   5339:     this.mlist.Add(jsMath.mItem.TextAtom(data[0],data[1],data[2],data[3]));
                   5340:   },
                   5341: 
                   5342:   /*
                   5343:    *  Implements \overbrace, \underbrace, etc.
                   5344:    */
                   5345:   HandleLeaders: function (name,data) {
                   5346:     var box = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5347:     box = jsMath.Box.Set(box,'D',this.mlist.data.size).Remeasured();
                   5348:     var leader = jsMath.Box.Leaders(box.w,this.leaders[data[0]]);
                   5349:     if (data[2]) {leader.y = -leader.h - box.d} else {leader.y = box.h + leader.d}
                   5350:     leader.x = -(leader.w + box.w)/2;
                   5351:     box = jsMath.mItem.Atom(data[1]? 'op': 'inner',
                   5352:       jsMath.Box.SetList([box,leader],'T',this.mlist.data.size));
                   5353:     box.limits = (data[1]? 1: 0);
                   5354:     this.mlist.Add(box);
                   5355:   },
                   5356:   
                   5357:   /*
                   5358:    *  Implements \llap, \rlap, etc.
                   5359:    */
                   5360:   HandleLap: function (name) {
                   5361:     var box = this.ProcessArg(); if (this.error) return;
                   5362:     box = this.mlist.Add(new jsMath.mItem('lap',{nuc: box, lap: name}));
                   5363:   },
                   5364: 
                   5365:   /*
                   5366:    *  Adds the argument as a specific type of atom (for commands like
                   5367:    *  \overline, etc.)
                   5368:    */
                   5369:   HandleAtom: function (name,data) {
                   5370:     var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
                   5371:     this.mlist.Add(jsMath.mItem.Atom(data,arg));
                   5372:   },
                   5373: 
                   5374: 
                   5375:   /*
                   5376:    *  Process the character associated with a specific \mathcharcode
                   5377:    */
                   5378:   HandleMathCode: function (name,code) {
1.2     ! albertel 5379:     this.HandleTeXchar(code[0],code[1],code[2]);
1.1       albertel 5380:   },
                   5381:   
                   5382:   /*
                   5383:    *  Add a specific character from a TeX font (use the current
                   5384:    *  font if the type is 7 (variable) or the font is not specified)
                   5385:    */
                   5386:   HandleTeXchar: function (type,font,code) {
                   5387:     if (type == 7 && this.mlist.data.font != null) {font = this.mlist.data.font}
                   5388:     font = jsMath.TeX.fam[font];
                   5389:     this.mlist.Add(jsMath.mItem.TeXAtom(jsMath.TeX.atom[type],code,font));
                   5390:   },
                   5391: 
                   5392:   /*
                   5393:    *  Add a TeX variable character or number
                   5394:    */
                   5395:   HandleVariable: function (c) {this.HandleTeXchar(7,1,c.charCodeAt(0))},
                   5396:   HandleNumber: function (c) {this.HandleTeXchar(7,0,c.charCodeAt(0))},
                   5397: 
                   5398:   /*
                   5399:    *  For unmapped characters, just add them in as normal
                   5400:    *  (non-TeX) characters
                   5401:    */
                   5402:   HandleOther: function (c) {
                   5403:     this.mlist.Add(jsMath.mItem.TextAtom('ord',c,'normal'));
                   5404:   },
                   5405:   
                   5406:   /*
                   5407:    *  Ignore comments in TeX data
                   5408:    *  ### Some browsers remove the newlines, so this might cause
                   5409:    *      extra stuff to be ignored; look into this ###
                   5410:    */
                   5411:   HandleComment: function () {
                   5412:     var c;
                   5413:     while (this.i < this.string.length) {
                   5414:       c = this.string.charAt(this.i++);
                   5415:       if (c == "\r" || c == "\n") return;
                   5416:     }
                   5417:   },
                   5418: 
                   5419:   /*
                   5420:    *  Add a style change (e.g., \displaystyle, etc)
                   5421:    */
                   5422:   HandleStyle: function (name,style) {
                   5423:     this.mlist.data.style = style[0];
                   5424:     this.mlist.Add(new jsMath.mItem('style',{style: style[0]}));
                   5425:   },
                   5426:   
                   5427:   /*
                   5428:    *  Implements \small, \large, etc.
                   5429:    */
                   5430:   HandleSize: function (name,size) {
                   5431:     this.mlist.data.size = size[0];
                   5432:     this.mlist.Add(new jsMath.mItem('size',{size: size[0]}));
                   5433:   },
                   5434: 
                   5435:   /*
                   5436:    *  Set the current font (e.g., \rm, etc)
                   5437:    */
                   5438:   HandleFont: function (name,font) {
                   5439:     this.mlist.data.font = font[0];
                   5440:   },
                   5441: 
                   5442:   /*
                   5443:    *  Look for and process a control sequence
                   5444:    */
                   5445:   HandleCS: function () {
                   5446:     var cmd = this.GetCommand(); if (this.error) return;
                   5447:     if (this.macros[cmd]) {
                   5448:       var macro = this.macros[cmd];
                   5449:       if (typeof(macro) == "string") {macro = [macro]}
                   5450:       this[macro[0]](cmd,macro.slice(1)); return;
                   5451:     }
                   5452:     if (this.mathchardef[cmd]) {
                   5453:       this.HandleMathCode(cmd,this.mathchardef[cmd]);
                   5454:       return;
                   5455:     }
                   5456:     if (this.delimiter[this.cmd+cmd]) {
1.2     ! albertel 5457:       this.HandleMathCode(cmd,this.delimiter[this.cmd+cmd].slice(0,3))
1.1       albertel 5458:       return;
                   5459:     }
                   5460:     this.Error("Unknown control sequence '"+this.cmd+cmd+"'");
                   5461:   },
                   5462: 
                   5463:   /*
                   5464:    *  Process open and close braces
                   5465:    */
                   5466:   HandleOpen: function () {this.mlist.Open()},
                   5467:   HandleClose: function () {
                   5468:     if (this.mlist.data.openI == null) {this.Error("Extra close brace"); return}
                   5469:     var open = this.mlist.Get(this.mlist.data.openI);
                   5470:     if (!open || open.left == null) {this.mlist.Close()}
                   5471:       else {this.Error("Extra close brace or missing "+this.cmd+"right"); return}
                   5472:   },
                   5473: 
                   5474:   /*
                   5475:    *  Implements \left
                   5476:    */
                   5477:   HandleLeft: function (name) {
                   5478:     var left = this.GetDelimiter(this.cmd+name); if (this.error) return;
                   5479:     this.mlist.Open(left);
                   5480:   },
                   5481: 
                   5482:   /*
                   5483:    *  Implements \right
                   5484:    */
                   5485:   HandleRight: function (name) {
                   5486:     var right = this.GetDelimiter(this.cmd+name); if (this.error) return;
                   5487:     var open = this.mlist.Get(this.mlist.data.openI);
                   5488:     if (open && open.left != null) {this.mlist.Close(right)}
                   5489:       else {this.Error("Extra open brace or missing "+this.cmd+"left");}
                   5490:   },
                   5491: 
                   5492:   /*
                   5493:    *  Implements generalized fractions (\over, \above, etc.)
                   5494:    */
                   5495:   HandleOver: function (name,data) {
                   5496:     if (this.mlist.data.overI != null) 
                   5497:       {this.Error('Ambiguous use of '+this.cmd+name); return}
                   5498:     this.mlist.data.overI = this.mlist.Length();
                   5499:     this.mlist.data.overF = {name: name};
                   5500:     if (data.length > 0) {
                   5501:       this.mlist.data.overF.left  = this.delimiter[data[0]];
                   5502:       this.mlist.data.overF.right = this.delimiter[data[1]];
                   5503:     } else if (name.match(/withdelims$/)) {
                   5504:       this.mlist.data.overF.left  = this.GetDelimiter(this.cmd+name); if (this.error) return;
                   5505:       this.mlist.data.overF.right = this.GetDelimiter(this.cmd+name); if (this.error) return;
                   5506:     }
                   5507:     if (name.match(/^above/))
                   5508:     {
                   5509:       this.mlist.data.overF.thickness = this.GetDimen(this.cmd.name,1);
                   5510:       if (this.error) return;
                   5511:     }
                   5512:   },
                   5513: 
                   5514:   /*
                   5515:    *  Add a superscript to the preceeding atom
                   5516:    */
                   5517:   HandleSuperscript: function () {
                   5518:     var base = this.mlist.Last();
                   5519:     if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))
                   5520:        {base = this.mlist.Add(jsMath.mItem.Atom('ord',null))}
                   5521:     if (base.sup) {this.Error("Double exponent: use braces to clarify"); return}
                   5522:     base.sup = this.ProcessArg('superscript'); if (this.error) return;
                   5523:   },
                   5524: 
                   5525:   /*
                   5526:    *  Adda subscript to the preceeding atom
                   5527:    */
                   5528:   HandleSubscript: function () {
                   5529:     var base = this.mlist.Last();
                   5530:     if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))
                   5531:        {base = this.mlist.Add(jsMath.mItem.Atom('ord',null))}
                   5532:     if (base.sub) {this.Error("Double subscripts: use braces to clarify"); return}
                   5533:     base.sub = this.ProcessArg('subscript'); if (this.error) return;
                   5534:   },
                   5535: 
                   5536:   /*
                   5537:    *  Parse a TeX math string, handling macros, etc.
                   5538:    */
                   5539:   Parse: function () {
                   5540:     var c;
                   5541:     while (this.i < this.string.length) {
                   5542:       c = this.string.charAt(this.i++);
                   5543:       if (this.mathchar[c]) {this.HandleMathCode(c,this.mathchar[c])}
                   5544:       else if (this.special[c]) {this[this.special[c]](c)}
                   5545:       else if (this.letter.test(c)) {this.HandleVariable(c)}
                   5546:       else if (this.number.test(c)) {this.HandleNumber(c)}
                   5547:       else {this.HandleOther(c)}
                   5548:     }
                   5549:     if (this.mlist.data.openI != null) {
                   5550:       var open = this.mlist.Get(this.mlist.data.openI);
                   5551:       if (open.left) {this.Error("Missing "+this.cmd+"right")}
                   5552:         else {this.Error("Missing close brace")}
                   5553:     }
                   5554:     if (this.mlist.data.overI != null) {this.mlist.Over()}
                   5555:   },
                   5556: 
                   5557:   /*
                   5558:    *  Perform the processing of Appendix G
                   5559:    */
                   5560:   Atomize: function () {
                   5561:     var data = this.mlist.init;
                   5562:     if (!this.error) this.mlist.Atomize(data.style,data.size)
                   5563:   },
                   5564: 
                   5565:   /*
                   5566:    *  Produce the final HTML.
                   5567:    *  
                   5568:    *  We have to wrap the HTML it appropriate <SPAN> tags to hide its
                   5569:    *  actual dimensions when these don't match the TeX dimensions of the
                   5570:    *  results.  We also include an image to force the results to take up
                   5571:    *  the right amount of space.  The results may need to be vertically
                   5572:    *  adjusted to make the baseline appear in the correct place.
                   5573:    */
                   5574:   Typeset: function () {
                   5575:     var data = this.mlist.init;
                   5576:     var box = this.typeset = this.mlist.Typeset(data.style,data.size);
                   5577:     if (this.error) {return '<SPAN CLASS="error">'+this.error+'</SPAN>'}
                   5578:     if (box.format == 'null') {return ''};
                   5579: 
                   5580:     box.Styled().Remeasured(); var isSmall = 0; var isBig = 0;
                   5581:     if (box.bh > box.h && box.bh > jsMath.h+.001) {isSmall = 1}
                   5582:     if (box.bd > box.d && box.bd > jsMath.d+.001) {isSmall = 1}
1.2     ! albertel 5583:     if (box.h > jsMath.h || box.d > jsMath.d) {isBig = 1}
1.1       albertel 5584: 
1.2     ! albertel 5585:     var html = box.html;
1.1       albertel 5586:     if (isSmall) {// hide the extra size
1.2     ! albertel 5587:       if (jsMath.Browser.allowAbsolute) {
        !          5588:         var y = 0;
        !          5589:         if (box.bh > jsMath.h+.001) {y = jsMath.h - box.bh}
        !          5590:         html = jsMath.HTML.Absolute(html,box.w,jsMath.h,0,y,jsMath.h);
        !          5591:       } else if (!jsMath.Browser.valignBug) {
        !          5592:         // remove line height and try to hide the depth
1.1       albertel 5593:         var dy = jsMath.HTML.Em(Math.max(0,box.bd-jsMath.hd)/3);
                   5594:         html = '<SPAN STYLE="line-height: 0;'
1.2     ! albertel 5595:                + ' position:relative; top:'+dy+'; vertical-align:'+dy
        !          5596:                + '">' + html + '</SPAN>';
1.1       albertel 5597:       }
1.2     ! albertel 5598:       isBig = 1;
1.1       albertel 5599:     }
                   5600:     if (isBig) {// add height and depth to the line (force a little
                   5601:                 //    extra to separate lines if needed)
1.2     ! albertel 5602:       html += '<IMG SRC="'+jsMath.blank+'" CLASS="mathHD" STYLE="'
        !          5603:                + 'height:'+jsMath.HTML.Em((box.h+box.d+.1)*jsMath.Browser.imgScale)+'; '
        !          5604:                + 'vertical-align:'+jsMath.HTML.Em(-box.d-.05)+';">'
1.1       albertel 5605:     }
1.2     ! albertel 5606:     return '<NOBR><SPAN CLASS="jsM_scale">'+html+'</SPAN></NOBR>';
1.1       albertel 5607:   }
                   5608: 
                   5609: });
                   5610: 
                   5611: /*
                   5612:  *  Make these characters special (and call the given routines)
                   5613:  */
                   5614: jsMath.Parser.prototype.AddSpecial({
                   5615:   cmd:   'HandleCS',
                   5616:   open:  'HandleOpen',
                   5617:   close: 'HandleClose'
                   5618: });
                   5619: 
                   5620: 
                   5621: /*
                   5622:  *  The web-page author can call jsMath.Macro to create additional
                   5623:  *  TeX macros for use within his or her mathematics.  jsMath.Macro
                   5624:  *  has two required and one optional parameter.  The first parameter
                   5625:  *  is the control sequence name that will trigger the macro, and the
                   5626:  *  second is the replacement string for that control sequence.
                   5627:  *  NOTE:  since the backslash (\) has special meaning in JavaScript,
                   5628:  *  you must double the backslash in order to include control sequences
                   5629:  *  within your replacement string.  E.g., 
                   5630:  *  
                   5631:  *      <SCRIPT> jsMath.Macro('R','{\\rm R}') </SCRIPT>
                   5632:  * 
                   5633:  *  would make \R produce a bold-faced R.
                   5634:  *  
                   5635:  *  The optional parameter tells how many arguments the macro
                   5636:  *  requires.  These are substituted for #1, #2, etc. within the 
                   5637:  *  replacement string of the macro.  For example
                   5638:  *  
1.2     ! albertel 5639:  *      <SCRIPT> jsMath.Macro('x','{\\vec x}_{#1}',1) </SCRIPT>
1.1       albertel 5640:  *  
                   5641:  *  would make \x1 produce {\vec x}_{1} and \x{i+1} produce {\vec x}_{i+1}.
                   5642:  *
                   5643:  *  You can put several jsMath.Macro calls together into one .js file, and
                   5644:  *  then include that into your web page using a command of the form
                   5645:  *  
                   5646:  *      <SCRIPT SRC="..."></SCRIPT>
                   5647:  *  
                   5648:  *  in your main HTML page.  This way you can include the same macros
                   5649:  *  into several web pages, for example.
                   5650:  */
                   5651: 
                   5652: jsMath.Add(jsMath,{
                   5653:   Macro: function (name) {
                   5654:     var macro = jsMath.Parser.prototype.macros;
                   5655:     macro[name] = ['Macro'];
                   5656:     for (var i = 1; i < arguments.length; i++) 
                   5657:       {macro[name][macro[name].length] = arguments[i]}
                   5658:   }
                   5659: });
                   5660: 
                   5661: 
                   5662: /***************************************************************************/
                   5663: 
                   5664: /*
                   5665:  *  These routines look through the web page for math elements to process.
                   5666:  *  There are two main entry points you can call:
                   5667:  *  
                   5668:  *      <SCRIPT> jsMath.Process() </SCRIPT>
                   5669:  *  or
                   5670:  *      <SCRIPT> jsMath.ProcessBeforeShowing() </SCRIPT>
                   5671:  *
                   5672:  *  The first will process the page asynchronously (so the user can start
                   5673:  *  reading the top of the file while jsMath is still processing the bottom)
                   5674:  *  while the second does not update until all the mathematics is typeset.
                   5675:  */
                   5676: 
                   5677: jsMath.Add(jsMath,{
                   5678: 
                   5679:   /*
                   5680:    *  Typeset a string in \textstyle and return the HTML for it
                   5681:    */
                   5682:   TextMode: function (s) {
                   5683:     var parse = jsMath.Parse(s,null,null,'T');
                   5684:     parse.Atomize();
                   5685:     var html = parse.Typeset();
                   5686:     return html;
                   5687:   },
                   5688: 
                   5689:   /*
                   5690:    *  Typeset a string in \displaystyle and return the HTML for it
                   5691:    */
                   5692:   DisplayMode: function (s) {
                   5693:     var parse = jsMath.Parse(s,null,null,'D');
                   5694:     parse.Atomize();
                   5695:     var html = parse.Typeset();
                   5696:     return html;
                   5697:   },
                   5698:   
                   5699:   /*
                   5700:    *  Return the text of a given DOM element
                   5701:    */
                   5702:   GetElementText: function (element) {
                   5703:     var text = element.innerText;
1.2     ! albertel 5704:     if (text == null || text == "") {
        !          5705:       try {text = element.textContent} catch (err) {}
        !          5706:       if (text == null || text == "") {text = element.innerHTML}
1.1       albertel 5707:     }
1.2     ! albertel 5708:     if (text.search('&') >= 0) {
1.1       albertel 5709:       text = text.replace(/&lt;/g,'<');
                   5710:       text = text.replace(/&gt;/g,'>');
                   5711:       text = text.replace(/&quot;/g,'"');
                   5712:       text = text.replace(/&amp;/g,'&');
                   5713:     }
                   5714:     return text;
                   5715:   },
                   5716:   
                   5717:   /*
1.2     ! albertel 5718:    *  Move hidden to the location of the math element to be
        !          5719:    *  processed and reinitialize sizes for that location.
        !          5720:    */
        !          5721:   ResetHidden: function (element) {
        !          5722:     element.innerHTML =
        !          5723:       '<SPAN CLASS="normal" STYLE="position:absolute; top:0px;left:0px;"></SPAN>'
        !          5724:         + jsMath.Browser.operaHiddenFix; // needed by Opera in tables
        !          5725:     element.className='';
        !          5726:     jsMath.hidden = element.firstChild;
        !          5727:     jsMath.ReInit();
        !          5728:   },
        !          5729: 
        !          5730:   
        !          5731:   /*
1.1       albertel 5732:    *  Typeset the contents of an element in \textstyle
                   5733:    */
                   5734:   ConvertText: function (element) {
                   5735:     var text = this.GetElementText(element);
1.2     ! albertel 5736:     this.ResetHidden(element);
1.1       albertel 5737:     element.innerHTML = this.TextMode(text);
                   5738:     element.className = 'typeset';
1.2     ! albertel 5739:     element.alt = text;
1.1       albertel 5740:   },
                   5741:   
                   5742:   /*
                   5743:    *  Typeset the contents of an element in \displaystyle
                   5744:    */
                   5745:   ConvertDisplay: function (element) {
                   5746:     var text = this.GetElementText(element);
1.2     ! albertel 5747:     this.ResetHidden(element);
1.1       albertel 5748:     element.innerHTML = this.DisplayMode(text);
                   5749:     element.className = 'typeset';
1.2     ! albertel 5750:     element.alt = text;
1.1       albertel 5751:   },
                   5752:   
                   5753:   /*
                   5754:    *  Process a math element
                   5755:    */
                   5756:   ProcessElement: function (element) {
1.2     ! albertel 5757:     try {
        !          5758:       if (element.tagName == 'DIV') {
        !          5759:         this.ConvertDisplay(element);
        !          5760:       } else if (element.tagName == 'SPAN') {
        !          5761:         this.ConvertText(element);
        !          5762:         //
        !          5763:         // Overcome a bug in MSIE where were tex2math can't insert DIV's inside
        !          5764:         // some elements, so fake it with SPANs, but can't fake the centering,
        !          5765:         // so do that here.
        !          5766:         //
        !          5767:         if (element.parentNode.className == 'jsMath.recenter') {
        !          5768:           element.parentNode.style.marginLeft =
        !          5769:             Math.floor((element.parentNode.offsetWidth - element.offsetWidth)/2)+"px";
        !          5770:         }
        !          5771:       }
        !          5772:       element.onclick = jsMath.Click.CheckClick;
        !          5773:       element.ondblclick = jsMath.Click.CheckDblClick;
        !          5774:     } catch (err) {}
1.1       albertel 5775:   },
                   5776: 
                   5777:   /*
                   5778:    *  Asynchronously process all the math elements starting with
                   5779:    *  the k-th one
                   5780:    */
                   5781:   ProcessElements: function (k) {
                   5782:     if (k >= this.element.length) {
                   5783:       this.ProcessComplete();
                   5784:     } else {
                   5785:       this.ProcessElement(this.element[k])
1.2     ! albertel 5786:       setTimeout('jsMath.ProcessElements('+(k+1)+')',jsMath.Browser.delay);
1.1       albertel 5787:     }
                   5788:   },
                   5789: 
                   5790:   /*
                   5791:    *  Call this at the bottom of your HTML page to have the
                   5792:    *  mathematics typeset asynchronously.  This lets the user
                   5793:    *  start reading the mathematics while the rest of the page
                   5794:    *  is being processed.
                   5795:    */
1.2     ! albertel 5796:   Process: function (obj) {
        !          5797:     if (!jsMath.initialized) {jsMath.Init()}
        !          5798:     this.element = this.GetMathElements(obj);
        !          5799:     window.status = 'Processing Math...';
        !          5800:     setTimeout('jsMath.ProcessElements(0)',jsMath.Browser.delay);
        !          5801:   },
        !          5802:   
        !          5803:   /*
        !          5804:    *  Call this at the bottom of your HTML page to have the
        !          5805:    *  mathematics typeset before the page is displayed.
        !          5806:    *  This can take a long time, so the user could cancel the
        !          5807:    *  page before it is complete; use it with caution, and only
        !          5808:    *  when there is a relatively small amount of math on the page.
        !          5809:    */
        !          5810:   ProcessBeforeShowing: function (obj) {
1.1       albertel 5811:     if (!jsMath.initialized) {jsMath.Init()}
1.2     ! albertel 5812:     var element = jsMath.GetMathElements(obj);
1.1       albertel 5813:     window.status = 'Processing Math...';
1.2     ! albertel 5814:     for (var i = 0; i < element.length; i++)
        !          5815:       {jsMath.ProcessElement(element[i])}
        !          5816:     jsMath.ProcessComplete();
1.1       albertel 5817:   },
                   5818:   
                   5819:   element: [],  // the list of math elements on the page
                   5820: 
                   5821:   /*
                   5822:    *  Look up all the math elements on the page and
                   5823:    *  put them in a list sorted from top to bottom of the page
                   5824:    */
1.2     ! albertel 5825:   GetMathElements: function (obj) {
1.1       albertel 5826:     var element = [];
1.2     ! albertel 5827:     if (!obj) {obj = document}
        !          5828:     if (typeof(obj) == 'string') {obj = document.getElementById(obj)}
        !          5829:     if (!obj.getElementsByTagName) return
        !          5830:     var math = obj.getElementsByTagName('DIV');
1.1       albertel 5831:     for (var k = 0; k < math.length; k++) {
                   5832:       if (math[k].className == 'math') {
1.2     ! albertel 5833:         if (jsMath.Browser.renameOK && obj.getElementsByName) 
        !          5834:                {math[k].setAttribute('NAME','_jsMath_')}
1.1       albertel 5835:           else {element[element.length] = math[k]}
                   5836:       }
                   5837:     }
1.2     ! albertel 5838:     math = obj.getElementsByTagName('SPAN');
1.1       albertel 5839:     for (var k = 0; k < math.length; k++) {
                   5840:       if (math[k].className == 'math') {
1.2     ! albertel 5841:         if (jsMath.Browser.renameOK && obj.getElementsByName) 
        !          5842:                {math[k].setAttribute('NAME','_jsMath_')}
1.1       albertel 5843:           else {element[element.length] = math[k]}
                   5844:       }
                   5845:     }
                   5846:     // this gets the SPAN and DIV elements interleaved in order
1.2     ! albertel 5847:     if (jsMath.Browser.renameOK && obj.getElementsByName) {
        !          5848:       element = obj.getElementsByName('_jsMath_');
1.1       albertel 5849:     } else if (jsMath.hidden.sourceIndex) {
                   5850:       element.sort(function (a,b) {return a.sourceIndex - b.sourceIndex});
                   5851:     }
                   5852:     return element;
                   5853:   },
                   5854: 
                   5855:   /*
                   5856:    *  Remove the window message about processing math
                   5857:    *  and clean up any marked <SPAN> or <DIV> tags
                   5858:    */
                   5859:   ProcessComplete: function () {
1.2     ! albertel 5860:     if (jsMath.Browser.renameOK) {
1.1       albertel 5861:       var element = document.getElementsByName('_jsMath_');
                   5862:       for (var i = element.length-1; i >= 0; i--) {
                   5863:         element[i].removeAttribute('NAME');
                   5864:       }
                   5865:     }
1.2     ! albertel 5866:     jsMath.hidden = jsMath.hiddenTop;
1.1       albertel 5867:     jsMath.element = [];
                   5868:     window.status = 'Done';
1.2     ! albertel 5869:     if (jsMath.Browser.safariImgBug &&
        !          5870:         (jsMath.Controls.cookie.font == 'symbol' ||
        !          5871:          jsMath.Controls.cookie.font == 'image')) {
        !          5872:       //
        !          5873:       //  For Safari, the images don't always finish
        !          5874:       //  updating, so nudge the window to cause a
        !          5875:       //  redraw.  (Hack!)
        !          5876:       //
        !          5877:       setTimeout("window.resizeBy(-1,0); window.resizeBy(1,0);",2000);
        !          5878:     }
        !          5879:   },
        !          5880:   
        !          5881:   Element: function (name) {return document.getElementById('jsMath.'+name)}
        !          5882:   
        !          5883: });
1.1       albertel 5884: 
                   5885: 
                   5886: /***************************************************************************/
                   5887: 
                   5888: /*
                   5889:  *  Initialize everything
                   5890:  */
1.2     ! albertel 5891: jsMath.Loaded();
        !          5892: jsMath.Controls.GetCookie();
        !          5893: if (document.body) {jsMath.Setup.Body()}
1.1       albertel 5894: 
1.2     ! albertel 5895: }}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>