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

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

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