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

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

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