Diff for /loncom/html/adm/jsMath/uncompressed/jsMath.js between versions 1.1 and 1.3

version 1.1, 2006/03/27 19:32:36 version 1.3, 2007/10/09 21:29:34
Line 10 Line 10
  *   *
  *  for the latest version, and for documentation on how to use jsMath.   *  for the latest version, and for documentation on how to use jsMath.
  *   *
  *  Copyright 2004-2006 by Davide P. Cervone   *  Copyright 2004-2007 by Davide P. Cervone
  *    * 
  *  Licensed under the Apache License, Version 2.0 (the "License");   *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.   *  you may not use this file except in compliance with the License.
Line 29 Line 29
 /*  /*
  *  Prevent running everything again if this file is loaded twice   *  Prevent running everything again if this file is loaded twice
  */   */
   
 if (!window.jsMath || !window.jsMath.loaded) {  if (!window.jsMath || !window.jsMath.loaded) {
   
 // handle bug in MSIE/Mac in autoload  
 if (window.parent && window.parent.jsMath) {jsMath = window.parent.jsMath}  
   
 var jsMath_old = window.jsMath;  // save user customizations  var jsMath_old = window.jsMath;  // save user customizations
   
   
 //  //
 // debugging routine  // debugging routine
 //   // 
Line 70  if (!document.getElementById || !documen Line 65  if (!document.getElementById || !documen
   
 /***************************************************************************/  /***************************************************************************/
   
 jsMath = {  window.jsMath = {
       
   version: "3.2",  // change this if you edit the file    version: "3.4e",  // change this if you edit the file, but don't edit this file
       
   document: document,  // the document loading jsMath    document: document,  // the document loading jsMath
   window: window,      // the window of the of loading document    window: window,      // the window of the of loading document
       
     platform: (navigator.platform.match(/Mac/) ? "mac" :
                navigator.platform.match(/Win/) ? "pc" : "unix"),
     
   // Font sizes for \tiny, \small, etc. (must match styles below)    // Font sizes for \tiny, \small, etc. (must match styles below)
   sizes: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249],    sizes: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249],
   
Line 84  jsMath = { Line 82  jsMath = {
   //  The styles needed for the TeX fonts    //  The styles needed for the TeX fonts
   //    //
   styles: {    styles: {
     '.math':              'font-family: serif; font-style: normal; font-weight: normal',      '.math':              'font-family:serif; font-style:normal; font-weight:normal',
   
     '.typeset':           'font-family: serif; font-style: normal; font-weight: normal',      '.typeset':           'font-family:serif; font-style:normal; font-weight:normal; line-height:normal',
     'div.typeset':        'text-align: center; margin: 1em 0px;',      'div.typeset':        'text-align:center; margin:1em 0px;',
     'span.typeset':       'text-align: left',      'span.typeset':       'text-align:left',
     '.typeset span':      'text-align: left; border:0px; margin:0px; padding:0px',      '.typeset span':      'text-align:left; border:0px; margin:0px; padding:0px',
           
     '.typeset .normal':   'font-family: serif; font-style: normal; font-weight: normal',      '.typeset .normal':   'font-family:serif; font-style:normal; font-weight:normal',
       
     '.typeset .size0':    'font-size: 50%',  // tiny (\scriptscriptsize)      '.typeset .size0':    'font-size:50%',  // tiny (\scriptscriptsize)
     '.typeset .size1':    'font-size: 60%',  //       (50% of \large for consistency)      '.typeset .size1':    'font-size:60%',  //       (50% of \large for consistency)
     '.typeset .size2':    'font-size: 70%',  // scriptsize      '.typeset .size2':    'font-size:70%',  // scriptsize
     '.typeset .size3':    'font-size: 85%',  // small (70% of \large for consistency)      '.typeset .size3':    'font-size:85%',  // small (70% of \large for consistency)
     '.typeset .size4':    'font-size: 100%', // normalsize      '.typeset .size4':    'font-size:100%', // normalsize
     '.typeset .size5':    'font-size: 120%', // large      '.typeset .size5':    'font-size:120%', // large
     '.typeset .size6':    'font-size: 144%', // Large      '.typeset .size6':    'font-size:144%', // Large
     '.typeset .size7':    'font-size: 173%', // LARGE      '.typeset .size7':    'font-size:173%', // LARGE
     '.typeset .size8':    'font-size: 207%', // huge      '.typeset .size8':    'font-size:207%', // huge
     '.typeset .size9':    'font-size: 249%', // Huge      '.typeset .size9':    'font-size:249%', // Huge
       
     '.typeset .cmr10':    'font-family: jsMath-cmr10, serif',      '.typeset .cmr10':    'font-family:jsMath-cmr10, serif',
     '.typeset .cmbx10':   'font-family: jsMath-cmbx10, jsMath-cmr10',      '.typeset .cmbx10':   'font-family:jsMath-cmbx10, jsMath-cmr10',
     '.typeset .cmti10':   'font-family: jsMath-cmti10, jsMath-cmr10',      '.typeset .cmti10':   'font-family:jsMath-cmti10, jsMath-cmr10',
     '.typeset .cmmi10':   'font-family: jsMath-cmmi10',      '.typeset .cmmi10':   'font-family:jsMath-cmmi10',
     '.typeset .cmsy10':   'font-family: jsMath-cmsy10',      '.typeset .cmsy10':   'font-family:jsMath-cmsy10',
     '.typeset .cmex10':   'font-family: jsMath-cmex10',      '.typeset .cmex10':   'font-family:jsMath-cmex10',
           
     '.typeset .textit':   'font-family: serif; font-style:italic',      '.typeset .textit':   'font-family:serif; font-style:italic',
     '.typeset .textbf':   'font-family: serif; font-weight:bold',      '.typeset .textbf':   'font-family:serif; font-weight:bold',
           
     '.typeset .link':     'text-decoration: none',      '.typeset .link':     'text-decoration:none',
     '.typeset .error':    'font-size: 10pt; font-style: italic; '      '.typeset .error':    'font-size:10pt; font-style:italic; '
                              + 'background-color: #FFFFCC; padding: 1px; '                               + 'background-color:#FFFFCC; padding:1px; '
                              + 'border: 1px solid #CC0000',                               + 'border:1px solid #CC0000',
   
     '.typeset .blank':    'display:inline-block; overflow:hidden; border:0px none; width:0px; height:0px;',      '.typeset .blank':    'display:inline-block; overflow:hidden; border:0px none; width:0px; height:0px;',
     '.typeset .spacer':   'display:inline-block',      '.typeset .spacer':   'display:inline-block',
       
       '#jsMath_hiddenSpan':      'visibility:hidden; position:absolute; top:0px;left:0px; '
                                     + 'line-height:normal; text-indent:0px',
   
     '#jsMath_message':        'position:fixed; bottom:1px; left:2px; background-color:#E6E6E6; '      '#jsMath_message':         'position:fixed; bottom:1px; left:2px; background-color:#E6E6E6; '
                                 + 'border: solid 1px #959595; margin:0px; padding: 1px 8px; '                                   + 'border:solid 1px #959595; margin:0px; padding:1px 8px; '
                                 + 'z-index:102; color: black; font-size:small; width:auto;',                                   + 'z-index:102; color: black; font-size:small; width:auto;',
     '#jsMath_panel':          'position:fixed; bottom:1.5em; right:1.5em; padding: 10px 20px; '      '#jsMath_panel':           'position:fixed; bottom:1.5em; right:1.5em; padding:.8em 1.6em; '
                                 + 'background-color:#DDDDDD; border: outset 2px; '                                   + 'background-color:#DDDDDD; border:outset 2px; '
                                 + 'z-index:103; width:auto;',                                   + 'z-index:103; width:auto; color:black; font-size:10pt; font-style:normal',
     '#jsMath_button':         'position:fixed; bottom:1px; right:2px; background-color:white; '      '#jsMath_panel .disabled': 'color:#888888',
                                 + 'border: solid 1px #959595; margin:0px; padding: 0px 3px 1px 3px; '      '#jsMath_panel .infoLink': 'font-size:85%',
                                 + 'z-index:102; color:black; text-decoration:none; font-size:x-small; '      '#jsMath_panel *':         'font-size:inherit; font-style:inherit; font-family:inherit; line-height:normal',
                                 + 'width:auto; cursor:pointer; cursor:hand;',      '#jsMath_panel div':       'background-color:inherit; color:inherit;',
     '#jsMath_float':          'position:absolute; top:0px; left:0px; max-width:80%; '      '#jsMath_panel span':      'background-color:inherit; color:inherit;',
                                 + 'z-index:101; width:auto; height:auto;',      '#jsMath_panel td':        'border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;',
     '#jsMath_float .drag':    'background-color:#DDDDDD; border: outset 1px; height:12px; font-size: 1px;',      '#jsMath_panel tr':        'border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;',
     '#jsMath_float .close':   'background-color:#E6E6E6; border: inset 1px; width:8px; height:8px; margin: 1px 2px;',      '#jsMath_panel table':     'border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;',
     '#jsMath_float .source':  'background-color:#E2E2E2; border: outset 1px; '      
                                 + 'width:auto; height:auto; padding: 8px 15px; '      '#jsMath_button':          'position:fixed; bottom:1px; right:2px; background-color:white; '
                                 + 'font-family: courier, fixed; font-size: 90%',                                   + 'border:solid 1px #959595; margin:0px; padding:0px 3px 1px 3px; '
     '#jsMath_noFont':         'text-align: center; padding: 10px 20px; border: 3px solid #DD0000; '                                   + 'z-index:102; color:black; text-decoration:none; font-size:x-small; '
                                 + 'background-color: #FFF8F8; color: #AA0000; font-size:small; width:auto;',                                   + 'width:auto; cursor:hand;',
     '#jsMath_noFont .link':   'padding: 0px 5px 2px 5px; border: 2px outset; background-color:#E8E8E8; '      '#jsMath_button *':        'padding:0px; border:0px; margin:0px; line-height:normal; '
                                 + 'color:black; font-size:80%; width:auto; cursor:pointer; cursor:hand;',                                   + 'font-size:inherit; font-style:inherit; font-family:inherit',
       
     '@media print': '#jsMath_button {display:none}'      '#jsMath_global':          'font-style:italic;',
       '#jsMath_float':           'position:absolute; top:0px; left:0px; max-width:80%; '
                                    + 'z-index:101; width:auto; height:auto;',
       '#jsMath_float .drag':     'background-color:#DDDDDD; border:outset 1px; height:12px; font-size:1px;',
       '#jsMath_float .close':    'background-color:#E6E6E6; border:inset 1px; width:8px; height:8px; margin:1px 2px;',
       '#jsMath_float .source':   'background-color:#E2E2E2; border:outset 1px; '
                                    + 'width:auto; height:auto; padding:8px 15px; '
                                    + 'font-family:courier, fixed; font-size:90%',
   
       '#jsMath_noFont .message': 'text-align: center; padding:.8em 1.6em; border:3px solid #DD0000; '
                                     + 'background-color:#FFF8F8; color: #AA0000; font-size:small; width:auto;',
       '#jsMath_noFont .link':    'padding:0px 5px 2px 5px; border:2px outset; background-color:#E8E8E8; '
                                     + 'color:black; font-size:80%; width:auto; cursor:hand;',
   
       '#jsMath_PrintWarning .message':
                                    'text-align:center; padding:.8em 1.6em; border:3px solid #DD0000; '
                                      + 'background-color: #FFF8F8; color: #AA0000; font-size:x-small; width:auto;',
   
       '@media print':      '#jsMath_button {display:none}\n' +
                            '#jsMath_Warning {display:none}',
                            
       '@media screen':     '#jsMath_PrintWarning {display:none}'
   
   },    },
       
Line 168  jsMath = { Line 190  jsMath = {
   },    },
   
   /*    /*
    *  Get the width and height (in ems) of an HTML string     *  Get the width and height (in ems) of an HTML string.
      *  Check the cache first to see if we've already measured it.
    */     */
   EmBoxFor: function (s) {    EmBoxFor: function (s) {
     var bbox = this.BBoxFor(s);      var cache = jsMath.Global.cache.R;
     return {w: bbox.w/this.em, h: bbox.h/this.em};      if (!cache[this.em]) {cache[this.em] = {}}
       if (!cache[this.em][s]) {
         var bbox = this.BBoxFor(s);
         cache[this.em][s] = {w: bbox.w/this.em, h: bbox.h/this.em};
       }
       return cache[this.em][s];
   },    },
   
   /*    /*
    *  For browsers that don't handle sizes of italics properly (MSIE)     *  For browsers that don't handle sizes of italics properly (MSIE).
      *  Check the cache first to see if we've already measured it.
    */     */
   EmBoxForItalics: function (s) {    EmBoxForItalics: function (s) {
     var bbox = this.BBoxFor(s);      var cache = jsMath.Global.cache.R;
     if (s.match(/<i>|class=\"(icm|italic|igreek|iaccent)/i)) {      if (!cache[this.em]) {cache[this.em] = {}}
       bbox.w = this.BBoxFor(s+jsMath.Browser.italicString).w      if (!cache[this.em][s]) {
                 - jsMath.Browser.italicCorrection;        var bbox = this.BBoxFor(s);
         if (s.match(/<i>|class=\"(icm|italic|igreek|iaccent)/i)) {
           bbox.w = bbox.Mw = this.BBoxFor(s+jsMath.Browser.italicString).w
                                - jsMath.Browser.italicCorrection;
         }
         cache[this.em][s] = {w: bbox.w/this.em, h: bbox.h/this.em};
     }      }
     return {w: bbox.w/this.em, h: bbox.h/this.em};      return cache[this.em][s];
   },    },
   
   /*    /*
Line 193  jsMath = { Line 227  jsMath = {
    */     */
   Init: function () {    Init: function () {
     if (jsMath.Setup.inited != 1) {      if (jsMath.Setup.inited != 1) {
       if (jsMath.Setup.inited) {        if (!jsMath.Setup.inited) {jsMath.Setup.Body()}
         if (jsMath.Setup.inited != 1) {
           if (jsMath.Setup.inited == -100) return;
         alert("It looks like jsMath failed to set up properly (error code "          alert("It looks like jsMath failed to set up properly (error code "
                + jsMath.Setup.inited + ").  "                 + jsMath.Setup.inited + ").  "
                + "I'll will try to keep going, but it could get ugly.");                 + "I will try to keep going, but it could get ugly.");
         jsMath.Setup.inited = 1;          jsMath.Setup.inited = 1;
       } else {  
         alert("You must call jsMath.Setup.Body() explicitly when jsMath is" +  
               "loaded as part of the <HEAD> section");  
       }        }
       jsMath.Setup.Body(); // may fail to load fallback files properly  
     }      }
     this.em = this.BBoxFor('<span style="'+jsMath.Browser.block+';width:10em;height:1em"></span>').w/10;      this.em = this.BBoxFor('<span style="'+jsMath.Browser.block+';width:13em;height:1em"></span>').w/13;
     if (this.em == 0) {      if (this.em == 0) {
       // handle older browsers        // handle older browsers
       this.em = this.BBoxFor('<img src="'+jsMath.blank+'" style="width:10em;height:1em"/>').w/10;        this.em = this.BBoxFor('<img src="'+jsMath.blank+'" style="width:13em;height:1em"/>').w/13;
     }      }
     if (jsMath.Browser.italicString)       var cache = jsMath.Global.cache.B;
       jsMath.Browser.italicCorrection = jsMath.BBoxFor(jsMath.Browser.italicString).w;      if (!cache[this.em]) {
     var bb = this.BBoxFor('x'); var h = bb.h;        cache[this.em] = {};
     var d = this.BBoxFor('x'+jsMath.HTML.Rule(1,h/jsMath.em)).h - h;        cache[this.em].bb = this.BBoxFor('x'); var hh = cache[this.em].bb.h;
         cache[this.em].d = this.BBoxFor('x'+jsMath.HTML.Rule(1,hh/jsMath.em)).h - hh;
         if (jsMath.Browser.italicString) 
           {cache[this.em].ic = jsMath.BBoxFor(jsMath.Browser.italicString).w}
       }
       jsMath.Browser.italicCorrection = cache[this.em].ic;
       var bb = cache[this.em].bb; var h = bb.h; var d = cache[this.em].d
     this.h = (h-d)/this.em; this.d = d/this.em;      this.h = (h-d)/this.em; this.d = d/this.em;
     this.hd = this.h + this.d;      this.hd = this.h + this.d;
     this.xWidth = bb.w;  // used to tell if scale has changed      this.xWidth = bb.w;  // used to tell if scale has changed
Line 252  jsMath = { Line 290  jsMath = {
         'ConvertTeX','ConvertTeX2','ConvertLaTeX','ConvertCustom',          'ConvertTeX','ConvertTeX2','ConvertLaTeX','ConvertCustom',
         'CustomSearch', 'Synchronize', 'Macro', 'document'];          'CustomSearch', 'Synchronize', 'Macro', 'document'];
       for (var i = 0; i < override.length; i++) {        for (var i = 0; i < override.length; i++) {
         if (jsMath_old[override[i]]) {jsMath_old[override[i]] = null}          if (jsMath_old[override[i]]) {delete jsMath_old[override[i]]}
       }        }
     }      }
     if (jsMath_old) {this.Insert(jsMath,jsMath_old)}      if (jsMath_old) {this.Insert(jsMath,jsMath_old)}
Line 281  jsMath = { Line 319  jsMath = {
   },    },
   Package: function (obj,def) {this.Insert(obj.prototype,def)}    Package: function (obj,def) {this.Insert(obj.prototype,def)}
   
 }  };
   
   
   /***************************************************************************/
   
     /*
      *  Implements items associated with the global cache.
      *
      *  This object will be replaced by a global version when 
      *  (and if) jsMath-global.html is loaded.
      */
   jsMath.Global = {
       isLocal: 1,  // a local copy if jsMath-global.html hasn't been loaded
       cache: {T: {}, D: {}, R: {}, B: {}},
   
       /*
        *  Clear the global (or local) cache
        */
       ClearCache: function () {jsMath.Global.cache = {T: {}, D: {}, R: {}, B: {}}},
   
       /*
        *  Initiate global mode
        */
       GoGlobal: function (cookie) {
         var url = String(jsMath.window.location);
         var c = (jsMath.isCHMmode ? '#' : '?');
         if (cookie) {url = url.replace(/\?.*/,'') + '?' + cookie}
         jsMath.Controls.Reload(jsMath.root + "jsMath-global.html" + c +escape(url));
       },
   
       /*
        *  Check if we need to go to global mode
        */
       Init: function () {
         if (jsMath.Controls.cookie.global == "always" && !jsMath.noGoGlobal) {
           if (navigator.accentColorName) return; // OmniWeb crashes on GoGlobal
           if (!jsMath.window) {jsMath.window = window}
           jsMath.Controls.loaded = 1;
           jsMath.Controls.defaults.hiddenGlobal = null;
           this.GoGlobal(jsMath.Controls.SetCookie(2));
         }
       },
   
       /*
        *  Try to register with a global.html window that contains us
        */
       Register: function () {
         var parent = jsMath.window.parent;
         if (!jsMath.isCHMode)
           {jsMath.isCHMmode = (jsMath.window.location.protocol == 'mk:')}
         try {
           if (!jsMath.isCHMmode) this.Domain();
           if (parent.jsMath && parent.jsMath.isGlobal)
             {parent.jsMath.Register(jsMath.window)}
         } catch (err) {jsMath.noGoGlobal = 1}
       },
   
       /*
        *  If we're not the parent window, try to set the domain to
        *  match the parent's domain (so we can use the Global data
        *  if the surrounding frame is a Global frame.
        */
       Domain: function () {
         // MSIE/Mac can't do domain changes, so don't bother trying
         if (navigator.appName == 'Microsoft Internet Explorer' &&
             jsMath.platform == 'mac' && navigator.userProfile != null) return;
         if (window == parent) return;
         var oldDomain = jsMath.document.domain;
         try {
           while (true) {
             try {if (parent.document.title != null) return} catch (err) {}
             if (!document.domain.match(/\..*\./)) break;
             jsMath.document.domain = jsMath.document.domain.replace(/^[^.]*\./,'');
           }
         } catch (err) {}
         jsMath.document.domain = oldDomain;
       }
   
   };
     
   
   
 /***************************************************************************/  /***************************************************************************/
   
Line 304  jsMath.Script = { Line 422  jsMath.Script = {
    */     */
   Init: function () {    Init: function () {
     if (!(jsMath.Controls.cookie.asynch && jsMath.Controls.cookie.progress)) {      if (!(jsMath.Controls.cookie.asynch && jsMath.Controls.cookie.progress)) {
       if (window.XMLHttpRequest) {        if (window.XMLHttpRequest && 
         this.request = new XMLHttpRequest;           // MSIE can't use xmlRequest on local files, but we don't have 
       } else if (window.ActiveXObject) {           // jsMath.browser yet to tell, so use this check
         try {this.request = new ActiveXObject("Microsoft.XMLHTTP")} catch (err) {}           !(jsMath.document.URL && jsMath.document.URL.match(/^file:\/\/.*\\/))) {
                try {this.request = new XMLHttpRequest} catch (err) {}
         }
         if (!this.request && window.ActiveXObject) {
           var xml = ["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0",
                      "MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
           for (var i = 0; i < xml.length && !this.request; i++) {
             try {this.request = new ActiveXObject(xml[i])} catch (err) {}
           }
       }        }
     }      }
     //      //
Line 336  jsMath.Script = { Line 462  jsMath.Script = {
    *  Load a URL and run the contents of the file     *  Load a URL and run the contents of the file
    */     */
   xmlRequest: function (url) {    xmlRequest: function (url) {
     this.debug('xmlRequest: '+url);      this.blocking = 1;
   //    this.debug('xmlRequest: '+url);
     try {      try {
       this.request.open("GET",url,false);        this.request.open("GET",url,false);
       this.request.send(null);        this.request.send(null);
     } catch (err) {      } catch (err) {
         this.blocking = 0;
         if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""}
       throw "jsMath can't load the file '"+url+"'\n"        throw "jsMath can't load the file '"+url+"'\n"
           + "Message: "+err.message;            + "Message: "+err.message;
     }      }
     if (this.request.status && this.request.status >= 400) {      if (this.request.status && this.request.status >= 400) {
       // Do we need to deal with redirected links?        // Do we need to deal with redirected links?
         this.blocking = 0;
         if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""}
       throw "jsMath can't load the file '"+url+"'\n"        throw "jsMath can't load the file '"+url+"'\n"
           + "Error status: "+this.request.status;            + "Error status: "+this.request.status;
     }      }
     this.Start(); this.blocking = 1;      if (!url.match(/\.js$/)) {return(this.request.responseText)}
       var tmpQueue = this.queue; this.queue = [];
   //    this.debug('xml Eval ['+tmpQueue.length+']');
     jsMath.window.eval(this.request.responseText);      jsMath.window.eval(this.request.responseText);
     this.End(); this.blocking = 0;  //    this.debug('xml Done ['+this.queue.length+' + '+tmpQueue.length+']');
       this.blocking = 0; this.queue = this.queue.concat(tmpQueue);
     this.Process();      this.Process();
       return "";
   },    },
   
   /********************************************************************    /********************************************************************
Line 371  jsMath.Script = { Line 506  jsMath.Script = {
   needsBody: 0,      // true if loading files requires BODY to be present    needsBody: 0,      // true if loading files requires BODY to be present
       
   queue: [],         // the stack of pending actions    queue: [],         // the stack of pending actions
   queueAt: 0,  
   
   /*    /*
    *  Provide mechanism for synchronizing with the asynchronous jsMath     *  Provide mechanism for synchronizing with the asynchronous jsMath
Line 387  jsMath.Script = { Line 521  jsMath.Script = {
    *  If nothing is being loaded, do the pending commands.     *  If nothing is being loaded, do the pending commands.
    */     */
   Push: function (object,method,data) {    Push: function (object,method,data) {
     this.debug('Pushing: '+method+' at '+this.queueAt);  //  this.debug('Pushing: '+method+' at '+this.queue.length); // debug
     this.queue = [].concat(this.queue.slice(0,this.queueAt),[[object,method,data]],this.queue.slice(this.queueAt));      this.queue[this.queue.length] = [object,method,data];
     this.queueAt++;  
     if (!(this.blocking || (this.needsBody && !jsMath.document.body))) this.Process();      if (!(this.blocking || (this.needsBody && !jsMath.document.body))) this.Process();
   },    },
   
Line 398  jsMath.Script = { Line 531  jsMath.Script = {
    */     */
   Process: function () {    Process: function () {
     while (this.queue.length && !this.blocking) {      while (this.queue.length && !this.blocking) {
       this.Start();  
       var call = this.queue[0]; this.queue = this.queue.slice(1);        var call = this.queue[0]; this.queue = this.queue.slice(1);
         var savedQueue = this.SaveQueue();
       var object = call[0]; var method = call[1]; var data = call[2];        var object = call[0]; var method = call[1]; var data = call[2];
       this.debug('Calling: '+method);  //    this.debug('Calling: '+method+' ['+savedQueue.length+']'); // debug
       if (object) {object[method](data)} else if (method) {method(data)}        if (object) {object[method](data)} else if (method) {method(data)}
       this.debug('Done:    '+method);  //    this.debug('Done:    '+method+' ['+this.queue.length+' + '+savedQueue.length+'] ('+this.blocking+')'); // debug
         this.RestoreQueue(savedQueue);
     }      }
     this.End();  
   },    },
       
   Start: function () {this.queueAt = 0},    /*
   End:   function () {this.queueAt = this.queue.length},     *  Allows pushes to occur at the FRONT of the queue
      *  (so a command acts as a single unit, including anything
      *  that it pushes on to the command stack)
      */
     SaveQueue: function () {
       var queue = this.queue;
       this.queue = [];
       return queue;
     },
     RestoreQueue: function (queue) {
       this.queue = this.queue.concat(queue);
     },
     
   /*    /*
    *  Handle loading of scripts that run asynchronously     *  Handle loading of scripts that run asynchronously
    */     */
   delayedLoad: function (url) {    delayedLoad: function (url) {
     this.debug('Loading: '+url);  //    this.debug('Loading: '+url);
     this.Push(this,'startLoad',url);      this.Push(this,'startLoad',url);
   },    },
   startLoad: function (url) {    startLoad: function (url) {
Line 435  jsMath.Script = { Line 579  jsMath.Script = {
     if (url.substr(0,jsMath.root.length) == jsMath.root)      if (url.substr(0,jsMath.root.length) == jsMath.root)
       {url = url.substr(jsMath.root.length)}        {url = url.substr(jsMath.root.length)}
     jsMath.Message.Set("Loading "+url);      jsMath.Message.Set("Loading "+url);
     this.debug('Starting: '+url);  
     this.cancelTimer = setTimeout('jsMath.Script.cancelLoad()',this.cancelTimeout);      this.cancelTimer = setTimeout('jsMath.Script.cancelLoad()',this.cancelTimeout);
   },    },
   endLoad: function (action) {    endLoad: function (action) {
     this.debug('Ending: '+this.url);  
     if (this.cancelTimer) {clearTimeout(this.cancelTimer); this.cancelTimer = null;}      if (this.cancelTimer) {clearTimeout(this.cancelTimer); this.cancelTimer = null;}
     jsMath.Message.Clear();      jsMath.Message.Clear();
     if (action != 'cancel') {this.blocking = 0; this.Process()}      if (action != 'cancel') {this.blocking = 0; this.Process()}
   },    },
     
     Start: function () {
   //    this.debug('Starting: ['+this.queue.length+'] '+this.url);
       this.tmpQueue = this.queue; this.queue = [];
     },
     End:   function () {
   //    this.debug('Ending:   ['+this.queue.length+' + '+this.tmpQueue.length+'] '+this.url);
       this.queue = this.queue.concat(this.tmpQueue); delete this.tmpQueue;
     },
   
   /*    /*
    *  If the loading takes too long, cancel it and end the load.     *  If the loading takes too long, cancel it and end the load.
Line 461  jsMath.Script = { Line 612  jsMath.Script = {
     this.blocking = 1;      this.blocking = 1;
     setTimeout('jsMath.Script.endDelay()',time);      setTimeout('jsMath.Script.endDelay()',time);
   },    },
   endDelay: function () {this.debug('endDelay'); this.blocking = 0; this.Process()},    endDelay: function () {
   //    this.debug('endDelay');
       this.blocking = 0;
       this.Process();
     },
       
   /*    /*
    *  Load an image and wait for it     *  Load an image and wait for it
    *  (so MSIE won't load extra copies of it)     *  (so MSIE won't load extra copies of it)
    */     */
     imageCount: 0,
   WaitForImage: function (file) {    WaitForImage: function (file) {
     this.blocking = 1; if (this.img == null) {this.img = []}      this.blocking = 1; this.imageCount++;
       if (this.img == null) {this.img = []}
     var img = new Image(); this.img[this.img.length] = img;      var img = new Image(); this.img[this.img.length] = img;
     img.onload = function () {jsMath.Script.endDelay()}      img.onload = function () {if (--jsMath.Script.imageCount == 0) jsMath.Script.endDelay()}
     img.onerror = img.onload; img.onabort = img.onload;      img.onerror = img.onload; img.onabort = img.onload;
     img.src = file;      img.src = file;
   },    },
Line 485  jsMath.Script = { Line 642  jsMath.Script = {
       data[k] = d.join('');        data[k] = d.join('');
     }      }
     window.eval(data.join(''));      window.eval(data.join(''));
   },    }
       
   /*    /*
    *  for debugging the event queue     *  for debugging the event queue
    */     */
   debug: function (message) {    /* 
 //    if (jsMath.document.body && jsMath.window.debug) {jsMath.window.debug(message)}     * ,debug: function (message) {
 //      else {alert(message)}     *   if (jsMath.document.body && jsMath.window.debug) {jsMath.window.debug(message)}
   }     *     else {alert(message)}
      * }
      */
   
 };  };
   
Line 545  jsMath.Message = { Line 704  jsMath.Message = {
         if (!this.message.style.cursor) {this.message.style.cursor = 'hand'}          if (!this.message.style.cursor) {this.message.style.cursor = 'hand'}
         this.message.title = ' Cancel Processing of Math ';          this.message.title = ' Cancel Processing of Math ';
       } else {        } else {
         this.message.style.cursor;          this.message.style.cursor = '';
         this.message.title = '';          this.message.title = '';
       }        }
     } else {      } else {
Line 622  jsMath.Setup = { Line 781  jsMath.Setup = {
    */     */
   Script: function (file,show) {    Script: function (file,show) {
     if (this.loaded[file]) {return} else {this.loaded[file] = 1}      if (this.loaded[file]) {return} else {this.loaded[file] = 1}
     if (!file.match('^([a-zA-Z]+:/)?/')) {file = jsMath.root + file}      if (!file.match('^([a-zA-Z]+:/?)?/')) {file = jsMath.root + file}
     jsMath.Script.Load(file,show);      jsMath.Script.Load(file,show);
   },    },
       
Line 651  jsMath.Setup = { Line 810  jsMath.Setup = {
       if (script) {        if (script) {
         for (var i = 0; i < script.length; i++) {          for (var i = 0; i < script.length; i++) {
           var src = script[i].src;            var src = script[i].src;
           if (src && src.match('(^|/)jsMath.js$')) {            if (src && src.match('(^|/|\\\\)jsMath.js$')) {
             jsMath.root = src.replace(/jsMath.js$/,'');              jsMath.root = src.replace(/jsMath.js$/,'');
             if (jsMath.root.charAt(0) == '/') {              break;
               jsMath.root = jsMath.document.location.protocol + '//'  
                           + jsMath.document.location.host + jsMath.root;  
             } else if (!jsMath.root.match(/^[a-z]+:/i)) {  
       src = new String(jsMath.document.location);  
       jsMath.root = src.replace(new RegExp('[^/]*$'),'') + jsMath.root;  
       while (jsMath.root.match('/[^/]*/\\.\\./')) {  
         jsMath.root = jsMath.root.replace(new RegExp('/[^/]*/\\.\\./'),'/');  
       }  
     }  
             i = script.length;  
           }            }
         }          }
       }        }
     }      }
       if (jsMath.root.charAt(0) == '\\') {jsMath.root = jsMath.root.replace(/\\/g,'/')}
       if (jsMath.root.charAt(0) == '/') {
         if (jsMath.root.charAt(1) != '/') {
           if (jsMath.document.location.port)
             {jsMath.root = ':' + jsMath.document.location.port + jsMath.root}
           jsMath.root = '//' + jsMath.document.location.host + jsMath.root;
         }
         jsMath.root = jsMath.document.location.protocol + jsMath.root;
       } else if (!jsMath.root.match(/^[a-z]+:/i)) {
         var src = new String(jsMath.document.location);
         var pattern = new RegExp('/[^/]*/\\.\\./')
         jsMath.root = src.replace(new RegExp('[^/]*$'),'') + jsMath.root;
         while (jsMath.root.match(pattern))
           {jsMath.root = jsMath.root.replace(pattern,'/')}
       }
     jsMath.Img.root = jsMath.root + "fonts/";      jsMath.Img.root = jsMath.root + "fonts/";
     jsMath.blank = jsMath.root + "blank.gif";      jsMath.blank = jsMath.root + "blank.gif";
     this.Domain();      this.Domain();
Line 679  jsMath.Setup = { Line 843  jsMath.Setup = {
    *  the domain of the calling page.     *  the domain of the calling page.
    */     */
   Domain: function () {    Domain: function () {
       try {jsMath.document.domain} catch (err) {return}
     var jsDomain = ''; var pageDomain = jsMath.document.domain;      var jsDomain = ''; var pageDomain = jsMath.document.domain;
     if (jsMath.root.match('://([^/]*)/')) {jsDomain = RegExp.$1}      if (jsMath.root.match('://([^/]*)/')) {jsDomain = RegExp.$1}
     jsDomain = jsDomain.replace(/:\d+$/,'');      jsDomain = jsDomain.replace(/:\d+$/,'');
Line 688  jsMath.Setup = { Line 853  jsMath.Setup = {
     //   catch the error (Grrr!), so exit for them.      //   catch the error (Grrr!), so exit for them.
     //      //
     if (navigator.appName == 'Microsoft Internet Explorer' &&      if (navigator.appName == 'Microsoft Internet Explorer' &&
         navigator.platform == 'MacPPC' && navigator.onLine &&          jsMath.platform == 'mac' && navigator.onLine &&
         navigator.userProfile && jsMath.document.all) return;          navigator.userProfile && jsMath.document.all) return;
     jsDomain = jsDomain.split(/\./); pageDomain = pageDomain.split(/\./);      jsDomain = jsDomain.split(/\./); pageDomain = pageDomain.split(/\./);
     if (jsDomain.length < 2 || pageDomain.length < 2 ||      if (jsDomain.length < 2 || pageDomain.length < 2 ||
Line 766  jsMath.Setup = { Line 931  jsMath.Setup = {
    *  Compute font parameters for various sizes     *  Compute font parameters for various sizes
    */     */
   Sizes: function () {    Sizes: function () {
     jsMath.TeXparams = [];      jsMath.TeXparams = []; var i; var j;
     for (var j=0; j < jsMath.sizes.length; j++) {jsMath.TeXparams[j] = {}}      for (j=0; j < jsMath.sizes.length; j++) {jsMath.TeXparams[j] = {}}
     for (var i in jsMath.TeX) {      for (i in jsMath.TeX) {
       if (typeof(jsMath.TeX[i]) != 'object') {        if (typeof(jsMath.TeX[i]) != 'object') {
         for (var j=0; j < jsMath.sizes.length; j++) {          for (j=0; j < jsMath.sizes.length; j++) {
           jsMath.TeXparams[j][i] = jsMath.sizes[j]*jsMath.TeX[i]/100;            jsMath.TeXparams[j][i] = jsMath.sizes[j]*jsMath.TeX[i]/100;
         }          }
       }        }
Line 796  jsMath.Setup = { Line 961  jsMath.Setup = {
     var string = ''; for (var id in styles) {string += id + ' {'+styles[id]+"}\n"}      var string = ''; for (var id in styles) {string += id + ' {'+styles[id]+"}\n"}
     if (jsMath.document.createStyleSheet) {// check for MSIE      if (jsMath.document.createStyleSheet) {// check for MSIE
       head.insertAdjacentHTML('beforeEnd',        head.insertAdjacentHTML('beforeEnd',
           '<span style="display:none">x</span><style type="text/css">'+string+'</style>');            '<span style="display:none">x</span>'  // MSIE needs this for some reason
             + '<style type="text/css">'+string+'</style>');
     } else {      } else {
       var style = jsMath.document.createElement('style'); style.type = "text/css";        var style = jsMath.document.createElement('style'); style.type = "text/css";
       style.appendChild(jsMath.document.createTextNode(string));        style.appendChild(jsMath.document.createTextNode(string));
Line 809  jsMath.Setup = { Line 975  jsMath.Setup = {
    */     */
   Body: function () {    Body: function () {
     if (this.inited) return;      if (this.inited) return;
       
     this.inited = -1;      this.inited = -1;
   
     jsMath.Setup.Hidden(); this.inited = -2;      jsMath.Setup.Hidden(); this.inited = -2;
Line 826  jsMath.Setup = { Line 992  jsMath.Setup = {
   
     // make sure browser-specific loads are done before this      // make sure browser-specific loads are done before this
     jsMath.Script.Push(jsMath.Font,'Check');      jsMath.Script.Push(jsMath.Font,'Check');
           if (jsMath.Font.register.length)
         {jsMath.Script.Push(jsMath.Font,'LoadRegistered')}
   
     this.inited = 1;      this.inited = 1;
   },    },
       
   /*    /*
    *  Web page author can override this to do initialization     *  Web page author can override the entries to the UserEvent hash 
    *  that must be done before the font check is performed, or     *  functions that will be run at various times during jsMath's setup
    *  at other times (as indicated by the value of the parameter).     *  process.
    */     */
   User: function (when) {}    User: function (when) {
       if (jsMath.Setup.UserEvent[when]) {(jsMath.Setup.UserEvent[when])()}
     },
     
     UserEvent: {
       "pre-font": null,  // after browser is set up but before fonts are tested
       "onload": null     // after jsMath.js is loaded and finished running
     }
       
 };  };
   
Line 886  jsMath.Browser = { Line 1061  jsMath.Browser = {
   operaHiddenFix: '',         // for Opera to fix bug with math in tables    operaHiddenFix: '',         // for Opera to fix bug with math in tables
   msieCenterBugFix: '',       // for MSIE centering bug with image fonts    msieCenterBugFix: '',       // for MSIE centering bug with image fonts
   msieInlineBlockFix: '',     // for MSIE alignment bug in non-quirks mode    msieInlineBlockFix: '',     // for MSIE alignment bug in non-quirks mode
     msieSpaceFix: '',           // for MSIE to avoid dropping empty spans
   imgScale: 1,                // MSI scales images for 120dpi screens, so compensate    imgScale: 1,                // MSI scales images for 120dpi screens, so compensate
   
   renameOK: 1,                // tells if brower will find a tag whose name    renameOK: 1,                // tells if brower will find a tag whose name
Line 915  jsMath.Browser = { Line 1091  jsMath.Browser = {
    *  and decide whether to use spans or images for spacing     *  and decide whether to use spans or images for spacing
    */     */
   TestInlineBlock: function () {    TestInlineBlock: function () {
     this.block = "display:inline-block";      this.block = "display:-moz-inline-box";
     this.hasInlineBlock = jsMath.BBoxFor('<span style="'+this.block+';width:10px;height:5px"></span>').w > 0;      this.hasInlineBlock = jsMath.BBoxFor('<span style="'+this.block+';width:10px;height:5px"></span>').w > 0;
     if (!this.hasInlineBlock) {      if (this.hasInlineBlock) {
       this.block = "display:-moz-inline-box";        jsMath.styles['.typeset .blank']  = jsMath.styles['.typeset .blank'].replace(/display:inline-block/,this.block);
         jsMath.styles['.typeset .spacer'] = jsMath.styles['.typeset .spacer'].replace(/display:inline-block/,'');
       } else {
         this.block = "display:inline-block";
       this.hasInlineBlock = jsMath.BBoxFor('<span style="'+this.block+';width:10px;height:5px"></span>').w > 0;        this.hasInlineBlock = jsMath.BBoxFor('<span style="'+this.block+';width:10px;height:5px"></span>').w > 0;
       if (!this.hasInlineBlock) return;        if (!this.hasInlineBlock) return;
       jsMath.styles['.typeset .blank']  = jsMath.styles['.typeset .blank'].replace(/display:inline-block/,this.block);  
     }      }
     this.block += ';overflow:hidden';      this.block += ';overflow:hidden';
     var h = jsMath.BBoxFor('x').h;      var h = jsMath.BBoxFor('x').h;
Line 1013  jsMath.Browser = { Line 1191  jsMath.Browser = {
   MSIE: function () {    MSIE: function () {
     if (this.spanHeightVaries && !this.spanHeightTooBig) {      if (this.spanHeightVaries && !this.spanHeightTooBig) {
       jsMath.browser = 'MSIE';        jsMath.browser = 'MSIE';
       if (navigator.platform == 'Win32') {        if (jsMath.platform == 'pc') {
           this.IE7 = (window.XMLHttpRequest != null);
           this.quirks = (jsMath.document.compatMode == "BackCompat");
           this.msieStandard6 = !this.quirks && !this.IE7;
         this.allowAbsoluteDelim = 1; this.separateSkips = 1;          this.allowAbsoluteDelim = 1; this.separateSkips = 1;
         this.buttonCheck = 1; this.msieBlankBug = 1;          this.buttonCheck = 1; this.msieBlankBug = 1;
           this.msieAccentBug = 1; this.msieRelativeClipBug = 1;
         this.msieDivWidthBug = 1; this.msiePositionFixedBug = 1;          this.msieDivWidthBug = 1; this.msiePositionFixedBug = 1;
         this.msieIntegralBug = 1; this.waitForImages = 1;          this.msieIntegralBug = 1; this.waitForImages = 1;
         this.msieAlphaBug = 1; this.alphaPrintBug = 1;          this.msieAlphaBug = !this.IE7; this.alphaPrintBug = !this.IE7;
         this.msieCenterBugFix = 'position:relative; ';          this.msieCenterBugFix = 'position:relative; ';
         this.msieInlineBlockFix = ' display:inline-block;';          this.msieInlineBlockFix = ' display:inline-block;';
           this.msieTeXfontBaselineBug = !jsMath.Browser.quirks;
           if (!this.IE7) {this.msieSpaceFix = '<span style="display:inline-block"></span>'}
         jsMath.Macro('joinrel','\\mathrel{\\kern-5mu}'),          jsMath.Macro('joinrel','\\mathrel{\\kern-5mu}'),
           jsMath.Parser.prototype.mathchardef.mapstocharOrig = jsMath.Parser.prototype.mathchardef.mapstochar;
           delete jsMath.Parser.prototype.mathchardef.mapstochar;
           jsMath.Macro('mapstochar','\\rlap{\\mapstocharOrig\\,}\\kern1mu'),
         jsMath.styles['.typeset .arial'] = "font-family: 'Arial unicode MS'";          jsMath.styles['.typeset .arial'] = "font-family: 'Arial unicode MS'";
         // MSIE doesn't implement fixed positioning, so use absolute          if (!this.IE7 || this.quirks) {
         jsMath.styles['#jsMath_message'] =            // MSIE doesn't implement fixed positioning, so use absolute
             jsMath.styles['#jsMath_message'] =
               jsMath.styles['#jsMath_message'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");                jsMath.styles['#jsMath_message'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
         jsMath.styles['#jsMath_panel'] =            jsMath.styles['#jsMath_panel'] =
               jsMath.styles['#jsMath_panel'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");                jsMath.styles['#jsMath_panel'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
         jsMath.styles['#jsMath_button'] = 'width:1px; '            jsMath.styles['#jsMath_button'] = 'width:1px; '
             + jsMath.styles['#jsMath_button'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");              + jsMath.styles['#jsMath_button'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
         jsMath.window.onscroll = jsMath.Controls.MoveButton;            jsMath.window.attachEvent("onscroll",jsMath.Controls.MoveButton);
             if (this.IE7) jsMath.window.attachEvent("onresize",jsMath.Controls.MoveButton);
     this.msieMoveButtonHack = this.IE7;
    }
           // Make MSIE put borders around the whole button
           jsMath.styles['#jsMath_noFont .link'] += " display: inline-block;";
         // MSIE needs this NOT to be inline-block          // MSIE needs this NOT to be inline-block
         jsMath.styles['.typeset .spacer'] =          jsMath.styles['.typeset .spacer'] =
               jsMath.styles['.typeset .spacer'].replace(/display:inline-block/,'');                jsMath.styles['.typeset .spacer'].replace(/display:inline-block/,'');
           // MSIE can't insert DIV's into text nodes, so tex2math must use SPAN's to fake DIV's
           jsMath.styles['.tex2math_div'] = jsMath.styles['div.typeset'] + '; width: 100%; display: inline-block';
         // MSIE will rescale images if the DPIs differ          // MSIE will rescale images if the DPIs differ
         if (screen.deviceXDPI && screen.logicalXDPI           if (screen.deviceXDPI && screen.logicalXDPI 
              && screen.deviceXDPI != screen.logicalXDPI) {               && screen.deviceXDPI != screen.logicalXDPI) {
Line 1043  jsMath.Browser = { Line 1238  jsMath.Browser = {
         // Handle bug with getting width of italic text          // Handle bug with getting width of italic text
         this.italicString = '<i>x</i>';          this.italicString = '<i>x</i>';
         jsMath.EmBoxFor = jsMath.EmBoxForItalics;          jsMath.EmBoxFor = jsMath.EmBoxForItalics;
       } else if (navigator.platform == 'MacPPC') {        } else if (jsMath.platform == 'mac') {
         this.msieAbsoluteBug = 1; this.msieButtonBug = 1;          this.msieAbsoluteBug = 1; this.msieButtonBug = 1;
         this.msieDivWidthBug = 1; this.msieBlankBug = 1;          this.msieDivWidthBug = 1; this.msieBlankBug = 1;
           this.quirks = 1;
         jsMath.Setup.Script('jsMath-msie-mac.js');          jsMath.Setup.Script('jsMath-msie-mac.js');
         jsMath.Parser.prototype.macros.angle = ['Replace','ord','<font face="Symbol">&#x8B;</font>','normal'];          jsMath.Parser.prototype.macros.angle = ['Replace','ord','<font face="Symbol">&#x8B;</font>','normal'];
         jsMath.styles['#jsMath_panel']  = 'width:25em; ' + jsMath.styles['#jsMath_panel'].replace(/width:auto/,"");          jsMath.styles['#jsMath_panel']  = 'width:42em; ' + jsMath.styles['#jsMath_panel'].replace(/width:auto/,"");
         jsMath.styles['#jsMath_button'] = 'width:1px; ' + jsMath.styles['#jsMath_button'].replace(/width:auto/,"");          jsMath.Controls.cookie.printwarn = 0; // MSIE/Mac doesn't handle '@media screen'
       }        }
       jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');        jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');
     }      }
Line 1061  jsMath.Browser = { Line 1257  jsMath.Browser = {
   Mozilla: function () {    Mozilla: function () {
     if (jsMath.hidden.ATTRIBUTE_NODE) {      if (jsMath.hidden.ATTRIBUTE_NODE) {
       jsMath.browser = 'Mozilla';        jsMath.browser = 'Mozilla';
       if (navigator.platform == 'Win32') {this.alphaPrintBug = 1}        if (jsMath.platform == 'pc') {this.alphaPrintBug = 1}
       this.allowAbsoluteDelim = 1; // this.separateSkips = 1; // no longer needed?        this.allowAbsoluteDelim = 1;
         jsMath.styles['#jsMath_button'] = jsMath.styles['#jsMath_button'].replace(/cursor:hand/,'cursor:pointer');
         jsMath.styles['#jsMath_noFont .link'] = jsMath.styles['#jsMath_noFont .link'].replace(/cursor:hand/,'cursor:pointer');
       jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');        jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');
       if (navigator.vendor == 'Firefox') {        if (navigator.vendor == 'Firefox') {
         jsMath.Browser.version = navigator.vendorSub;          this.version = navigator.vendorSub;
       } else if (navigator.userAgent.match(' Firefox/([0-9.]+)( |$)')) {        } else if (navigator.userAgent.match(' Firefox/([0-9.]+)( |$)')) {
         jsMath.Browser.version = RegExp.$1;          this.version = RegExp.$1;
       }        }
     }      }
   },    },
Line 1080  jsMath.Browser = { Line 1278  jsMath.Browser = {
       jsMath.browser = 'OmniWeb';        jsMath.browser = 'OmniWeb';
       this.allowAbsolute = this.hasInlineBlock;        this.allowAbsolute = this.hasInlineBlock;
       this.allowAbsoluteDelim = this.allowAbsolute;        this.allowAbsoluteDelim = this.allowAbsolute;
       this.valignBug = this.allowAbsolute;        this.valignBug = !this.allowAbsolute;
       this.buttonCheck = 1; this.textNodeBug = 1;        this.buttonCheck = 1; this.textNodeBug = 1;
         jsMath.noChangeGlobal = 1; // OmniWeb craches on GoGlobal
       if (!this.hasInlineBlock) {jsMath.Setup.Script('jsMath-old-browsers.js')}        if (!this.hasInlineBlock) {jsMath.Setup.Script('jsMath-old-browsers.js')}
     }      }
   },    },
Line 1108  jsMath.Browser = { Line 1307  jsMath.Browser = {
       jsMath.browser = 'Safari';        jsMath.browser = 'Safari';
       var version = navigator.userAgent.match("Safari/([0-9]+)");        var version = navigator.userAgent.match("Safari/([0-9]+)");
       version = (version)? version[1] : 400;        version = (version)? version[1] : 400;
       for (var i = 0; i < jsMath.TeX.fam.length; i++)        for (var i = 0; i < jsMath.TeX.fam.length; i++) {
         {if (jsMath.TeX.fam[i]) {jsMath.TeX[jsMath.TeX.fam[i]].dh = .1}}          if (jsMath.TeX.fam[i] && jsMath.TeX[jsMath.TeX.fam[i]])
             {jsMath.TeX[jsMath.TeX.fam[i]].dh = .1}
         }
       jsMath.TeX.axis_height += .05;        jsMath.TeX.axis_height += .05;
         jsMath.TeX.default_rule_thickness += .025;
       this.allowAbsoluteDelim = version >= 125;        this.allowAbsoluteDelim = version >= 125;
       this.safariIFRAMEbug = version >= 312 && version < 412;        this.safariIFRAMEbug = version >= 312 && version < 412;
         this.safariButtonBug = version < 412;
       this.safariImgBug = 1; this.textNodeBug = 1;        this.safariImgBug = 1; this.textNodeBug = 1;
       this.buttonCheck = 1;        this.buttonCheck = 1;
       this.styleChangeDelay = 1;        this.styleChangeDelay = 1;
Line 1134  jsMath.Browser = { Line 1337  jsMath.Browser = {
           jsMath.Setup.Script('jsMath-old-browsers.js');            jsMath.Setup.Script('jsMath-old-browsers.js');
         }          }
       }        }
         //  Apparently, Konqueror wants the names without the hyphen
         jsMath.Add(jsMath.styles,{
           '.typeset .cmr10':    'font-family: jsMath-cmr10, jsMath cmr10, serif',
           '.typeset .cmbx10':   'font-family: jsMath-cmbx10, jsMath cmbx10, jsMath-cmr10, jsMath cmr10',
           '.typeset .cmti10':   'font-family: jsMath-cmti10, jsMath cmti10, jsMath-cmr10, jsMath cmr10',
           '.typeset .cmmi10':   'font-family: jsMath-cmmi10, jsMath cmmi10',
           '.typeset .cmsy10':   'font-family: jsMath-cmsy10, jsMath cmsy10',
           '.typeset .cmex10':   'font-family: jsMath-cmex10, jsMath cmex10'
         });
         jsMath.Font.testFont = "jsMath-cmex10, jsMath cmex10";
     }      }
   }    }
   
Line 1146  jsMath.Browser = { Line 1359  jsMath.Browser = {
  */   */
 jsMath.Font = {  jsMath.Font = {
       
     testFont: "jsMath-cmex10",
   fallback: "symbol", // the default fallback method    fallback: "symbol", // the default fallback method
     register: [],       // list of fonts registered before jsMath.Init()
   
   // the HTML for the missing font message    // the HTML for the missing font message
   message:        message:    
Line 1158  jsMath.Font = { Line 1373  jsMath.Font = {
     'Extra TeX fonts not found: <b><span id="jsMath_ExtraFonts"></span></b><br/>'      'Extra TeX fonts not found: <b><span id="jsMath_ExtraFonts"></span></b><br/>'
       + 'Using image fonts instead.  This may be slow and might not print well.<br/>\n'        + 'Using image fonts instead.  This may be slow and might not print well.<br/>\n'
       + 'Use the jsMath control panel to get additional information.',        + 'Use the jsMath control panel to get additional information.',
   
     print_message:
       'To print higher-resolution math symbols, click the<br/>\n'
          + '<b>Hi-Res Fonts for Printing</b> button on the jsMath control panel.<br/>\n',
   
     alpha_message:
       'If the math symbols print as black boxes, turn off <b>image alpha channels</b><br/>\n'
          + 'using the <B>Options</B> pane of the jsMath control panel.<br/>\n',
       
   /*    /*
    *  Look to see if a font is found.     *  Look to see if a font is found.
Line 1186  jsMath.Font = { Line 1409  jsMath.Font = {
    *  If they are found, load the BaKoMa encoding information.     *  If they are found, load the BaKoMa encoding information.
    */     */
   CheckTeX: function () {    CheckTeX: function () {
     var wh = jsMath.BBoxFor('<span style="font-family: jsMath-cmex10, serif">'+jsMath.TeX.cmex10[1].c+'</span>');      var wh = jsMath.BBoxFor('<span style="font-family: '+jsMath.Font.testFont+', serif">'+jsMath.TeX.cmex10[1].c+'</span>');
     jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10',null,null,'jsMath-'));      jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10',null,null,'jsMath-'));
     if (jsMath.nofonts && (navigator.platform != "MacPPC" ||      if (jsMath.nofonts && (jsMath.platform != "mac" ||
         jsMath.browser != 'Mozilla' || !jsMath.Browser.VersionAtLeast(1.5))) {          jsMath.browser != 'Mozilla' || !jsMath.Browser.VersionAtLeast(1.5))) {
       wh = jsMath.BBoxFor('<span style="font-family: cmex10, serif">'+jsMath.TeX.cmex10[1].c+'</span>');        wh = jsMath.BBoxFor('<span style="font-family: cmex10, serif">'+jsMath.TeX.cmex10[1].c+'</span>');
       jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10'));        jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10'));
Line 1228  jsMath.Font = { Line 1451  jsMath.Font = {
     }      }
     if (jsMath.noImgFonts) {cookie.font = 'unicode'}      if (jsMath.noImgFonts) {cookie.font = 'unicode'}
     if (cookie.font == 'unicode') {      if (cookie.font == 'unicode') {
       var platform = ({Win32: 'pc', MacPPC: 'mac'})[navigator.platform] || 'unix';        jsMath.Setup.Script('jsMath-fallback-'+jsMath.platform+'.js');
       jsMath.Setup.Script('jsMath-fallback-'+platform+'.js');  
       jsMath.Box.TeXnonfallback = jsMath.Box.TeX;        jsMath.Box.TeXnonfallback = jsMath.Box.TeX;
       jsMath.Box.TeX = jsMath.Box.TeXfallback;        jsMath.Box.TeX = jsMath.Box.TeXfallback;
       return;        return;
     }      }
       if (!cookie.print && cookie.printwarn) {
         this.PrintMessage(
           (jsMath.Browser.alphaPrintBug && jsMath.Controls.cookie.alpha) ?
             this.print_message + this.alpha_message : this.print_message);
       }
     if (jsMath.Browser.waitForImages) {      if (jsMath.Browser.waitForImages) {
       jsMath.Script.Push(jsMath.Script,"WaitForImage",jsMath.blank);        jsMath.Script.Push(jsMath.Script,"WaitForImage",jsMath.blank);
     }      }
Line 1261  jsMath.Font = { Line 1488  jsMath.Font = {
    *  of your page.     *  of your page.
    */     */
   Message: function (message) {    Message: function (message) {
     if(jsMath.Element("Warning")) return;      if (jsMath.Element("Warning")) return;
     var div = jsMath.Setup.DIV("Warning",{});      var div = jsMath.Setup.DIV("Warning",{});
     div.innerHTML =       div.innerHTML = 
       '<center><table><tr><td>'        '<center><table><tr><td>'
       + '<div id="jsMath_noFont">' + message        + '<div id="jsMath_noFont"><div class="message">' + message
       + '<div style="text-align:left"><span style="float:left; margin: 8px 0px 0px 20px">'        + '<div style="text-align:left"><span style="float:left; margin: 8px 0px 0px 20px">'
       + '<span onclick="jsMath.Controls.Panel()" title=" Open the jsMath Control Panel " class="link">jsMath Control Panel</span>'        + '<span onclick="jsMath.Controls.Panel()" title=" Open the jsMath Control Panel " class="link">jsMath Control Panel</span>'
       + '</span><span style="margin: 8px 20px 0px 0px; float:right">'        + '</span><span style="margin: 8px 20px 0px 0px; float:right">'
       + '<span onclick="jsMath.Font.HideMessage()" title=" Remove this font warning message " class="link">Hide this Message</span>'        + '<span onclick="jsMath.Font.HideMessage()" title=" Remove this font warning message " class="link">Hide this Message</span>'
       + '</span></div><div style="height:6px"></div><br clear="all"/></div>'        + '</span></div><div style="height:6px"></div><br clear="all"/></div></div>'
       + '<div style="width:22em; height:1px"></div>'        + '<div style="width:22em; height:1px"></div>'
       + '</td></tr></table></center><hr/>';        + '</td></tr></table></center><hr/>';
   },    },
Line 1280  jsMath.Font = { Line 1507  jsMath.Font = {
     if (message) {message.style.display = "none"}      if (message) {message.style.display = "none"}
   },    },
       
     PrintMessage: function (message) {
       if (jsMath.Element("PrintWarning")) return;
       var div = jsMath.Setup.DIV("PrintWarning",{});
       div.innerHTML = 
         '<center><table><tr><td>'
         + '<div class="message">' + message + '</div>'
         + '<div style="width:22em; height:1px"></div>'
         + '</td></tr></table></center><hr/>';
     },
     
   /*    /*
    *  Register an extra font so jsMath knows about it     *  Register an extra font so jsMath knows about it
    */     */
   Register: function (data) {    Register: function (data,force) {
     jsMath.Script.Start();  
     if (typeof(data) == 'string') {data = {name: data}}      if (typeof(data) == 'string') {data = {name: data}}
       if (!jsMath.Setup.inited && !force) {
         this.register[this.register.length] = data;
         return;
       }
     var fontname = data.name; var name = fontname.replace(/10$/,'');      var fontname = data.name; var name = fontname.replace(/10$/,'');
     var fontfam = jsMath.TeX.fam.length;      var fontfam = jsMath.TeX.fam.length;
     if (data.prefix == null) {data.prefix = ""}      if (data.prefix == null) {data.prefix = ""}
Line 1304  jsMath.Font = { Line 1544  jsMath.Font = {
      */       */
     data.styles['.typeset .'+fontname] = data.style;      data.styles['.typeset .'+fontname] = data.style;
     jsMath.Setup.Styles(data.styles);      jsMath.Setup.Styles(data.styles);
     jsMath.Script.Push(jsMath.Setup,'TeXfont',fontname);      if (jsMath.initialized) {jsMath.Script.Push(jsMath.Setup,'TeXfont',fontname)}
     /*      /*
      *  Check for font and give message if missing       *  Check for font and give message if missing
      */       */
       var cookie = jsMath.Controls.cookie;
     var hasTeXfont = !jsMath.nofonts &&      var hasTeXfont = !jsMath.nofonts &&
                       data.test(fontname,data.testChar,data.testFactor,data.prefix);                        data.test(fontname,data.testChar,data.testFactor,data.prefix);
     if (hasTeXfont && jsMath.Controls.cookie.font == 'tex') {      if (hasTeXfont && cookie.font == 'tex') {
       if (data.tex) {data.tex(fontname,fontfam,data)}        if (data.tex) {data.tex(fontname,fontfam,data)}
       jsMath.Script.End();  
       return;        return;
     }      }
     if (!hasTeXfont && jsMath.Controls.cookie.warn &&      if (!hasTeXfont && cookie.warn && cookie.font == 'tex' && !jsMath.nofonts) {
         jsMath.Controls.cookie.font == 'tex' && !jsMath.nofonts) {        if (!cookie.fonts.match("/"+fontname+"/")) {
       if (!jsMath.Element("Warning")) this.Message(this.extra_message);          cookie.fonts += fontname + "/"; jsMath.Controls.SetCookie(0);
       var extra = jsMath.Element("ExtraFonts");          if (!jsMath.Element("Warning")) this.Message(this.extra_message);
       if (extra) {          var extra = jsMath.Element("ExtraFonts");
         if (extra.innerHTML != "") {extra.innerHTML += ','}          if (extra) {
         extra.innerHTML += " " + data.prefix+fontname;            if (extra.innerHTML != "") {extra.innerHTML += ','}
             extra.innerHTML += " " + data.prefix+fontname;
           }
       }        }
     }      }
     if (jsMath.Controls.cookie.font == 'unicode') {      if (cookie.font == 'unicode' || jsMath.noImgFonts) {
       if (data.fallback) {data.fallback(fontname,fontfam,data)}        if (data.fallback) {data.fallback(fontname,fontfam,data)}
       jsMath.Script.End();  
       return;        return;
     }      }
     //  Image fonts      //  Image fonts
     var font = {}; font[fontname] = ['all'];      var font = {}; font[fontname] = ['all'];
     jsMath.Img.SetFont(font);      jsMath.Img.SetFont(font);
     jsMath.Img.LoadFont(fontname);      jsMath.Img.LoadFont(fontname);
     jsMath.Script.Push(jsMath.Img,'Scale');      if (jsMath.initialized) {
     jsMath.Script.Push(jsMath.Img,'UpdateFonts');        jsMath.Script.Push(jsMath.Img,'Scale');
     jsMath.Script.End();        jsMath.Script.Push(jsMath.Img,'UpdateFonts');
       }
     },
     /*
      *  If fonts are registered before jsMath.Init() is called, jsMath.em
      *  will not be available, so they need to be delayed.
      */
     LoadRegistered: function () {
       var i = 0;
       while (i < this.register.length) {this.Register(this.register[i++],1)}
       this.register = [];
   },    },
   
   /*    /*
Line 1359  jsMath.Controls = { Line 1610  jsMath.Controls = {
   cookie: {    cookie: {
     scale: 100,      scale: 100,
     font: 'tex', autofont: 1, scaleImg: 0, alpha: 1,      font: 'tex', autofont: 1, scaleImg: 0, alpha: 1,
     warn: 1, button: 1, progress: 1, asynch: 0, blank: 0,      warn: 1, fonts: '/', printwarn: 1, stayhires: 0,
     print: 0, keep: '0D'      button: 1, progress: 1, asynch: 0, blank: 0,
       print: 0, keep: '0D', global: 'auto', hiddenGlobal: 1
   },    },
       
   cookiePath: '/',  // can also set cookieDomain    cookiePath: '/',  // can also set cookieDomain
     noCookiePattern: /^(file|mk):$/,  // pattern for handling cookies locally
       
       
   /*    /*
Line 1390  jsMath.Controls = { Line 1643  jsMath.Controls = {
   Button: function () {    Button: function () {
     var button = jsMath.Setup.DIV("button",{});      var button = jsMath.Setup.DIV("button",{});
     button.title = ' Open jsMath Control Panel ';      button.title = ' Open jsMath Control Panel ';
     button.innerHTML = 'jsMath';      button.innerHTML = 
     if (button.offsetWidth < 2*jsMath.em) {button.style.width = "auto"}        '<span onclick="jsMath.Controls.Panel()">jsMath</span>';
     button.onclick = new Function("jsMath.Controls.Panel()");      if (!jsMath.Global.isLocal && !jsMath.noShowGlobal) {
         button.innerHTML +=
           '<span id="jsMath_global" title=" Open jsMath Global Panel " '
             + 'onclick="jsMath.Global.Show(1)">Global&nbsp;</span>';
       }
       if (button.offsetWidth < 30) {button.style.width = "auto"}
     if (!this.cookie.button) {button.style.display = "none"}      if (!this.cookie.button) {button.style.display = "none"}
   },    },
       
  /*    /*
   *  MSIE doesn't implement position:fixed, so redraw the button on scrolls.     *  Since MSIE doesn't handle position:float, we need to have the
   */     *  window repositioned every time the window scrolls.  We do that
      *  by hiding then showing the window, which apparently causes MSIE
      *  to recompute its location.  In MSIE7, that doesn't work anymore,
      *  so we have to move the window by hand.
      */
   MoveButton: function () {    MoveButton: function () {
     if (!this.button) {this.button = jsMath.Element("button")}      var controls = jsMath.Controls;
     this.button.style.visibility = "hidden";      if (!controls.button) {controls.button = jsMath.Element("button")}
     this.button.style.visibility = "visible";      if (controls.button) controls.MoveElement(controls.button,3,2);
       var dx = 20; var dy = 20;
       if (controls.button) {dy = controls.button.offsetHeight + 6; dx = dy + 5}
       if (controls.panel)  controls.MoveElement(controls.panel,dx,dy);
     },
     MoveElement: function (obj,dx,dy) {
       if (jsMath.Browser.IE7) {
         var body = document.body;
         obj.style.right = "auto";
         obj.style.bottom = "auto";
         //
         // This position can't be overridden by CSS (grr)
         // (Perhaps we can look up the current position and which sides it's 
         // attached to and use those.  What a pain.)
         //
         obj.style.left = body.clientWidth + body.scrollLeft - obj.offsetWidth - dx + "px";
         obj.style.top = body.clientHeight + body.scrollTop -  obj.offsetHeight - dy + "px";
       } else {
         obj.style.visibility = "hidden";
         obj.style.visibility = "visible";
       }
   },    },
   
   /*    /*
Line 1410  jsMath.Controls = { Line 1692  jsMath.Controls = {
    *  (for file: references, use url '?' syntax)     *  (for file: references, use url '?' syntax)
    */     */
   GetCookie: function () {    GetCookie: function () {
       // save the current cookie settings as the defaults
       if (this.defaults == null) {this.defaults = {}}
       jsMath.Add(this.defaults,this.cookie); this.userSet = {};
       // get the browser's cookie data
     var cookies = jsMath.document.cookie;      var cookies = jsMath.document.cookie;
     if (jsMath.window.location.protocol == 'file:')       if (jsMath.window.location.protocol.match(this.noCookiePattern)) {
       {cookies = unescape(jsMath.window.location.search.substr(1))}        cookies = this.localGetCookie();
     if (cookies.match(/jsMath=([^;]*)/)) {        this.isLocalCookie = 1;
       var data = RegExp.$1.split(/,/);      }
       if (cookies.match(/jsMath=([^;]+)/)) {
         var data = unescape(RegExp.$1).split(/,/);
       for (var i = 0; i < data.length; i++) {        for (var i = 0; i < data.length; i++) {
         var x = data[i].match(/(.*):(.*)/);          var x = data[i].match(/(.*):(.*)/);
         if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string          if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string
         this.cookie[x[1]] = x[2];          this.cookie[x[1]] = x[2];
           this.userSet[x[1]] = 1;
       }        }
     }      }
   },    },
     localGetCookie: function () {
       return jsMath.window.location.search.substr(1);
     },
       
   /*    /*
    *  Save the cookie data in the browser     *  Save the cookie data in the browser
Line 1429  jsMath.Controls = { Line 1721  jsMath.Controls = {
    */     */
   SetCookie: function (warn) {    SetCookie: function (warn) {
     var cookie = [];      var cookie = [];
     for (var id in this.cookie) {cookie[cookie.length] = id + ':' + this.cookie[id]}      for (var id in this.cookie) {
         if (this.defaults[id] == null || this.cookie[id] != this.defaults[id])
           {cookie[cookie.length] = id + ':' + this.cookie[id]}
       }
     cookie = cookie.join(',');      cookie = cookie.join(',');
     if (jsMath.window.location.protocol == 'file:') {      if (this.isLocalCookie) {
       if (!warn) return;        if (warn == 2) {return 'jsMath='+escape(cookie)}
       this.loaded = 0;        this.localSetCookie(cookie,warn);
       var href = jsMath.window.location.href;  
       href = href.replace(/\?.*/,"") + '?jsMath=' + escape(cookie);  
       if (href != jsMath.window.location.href) {jsMath.window.location.replace(href)}  
     } else {      } else {
         cookie = escape(cookie);
         if (cookie == '') {warn = 0}
       if (this.cookiePath) {cookie += '; path='+this.cookiePath}        if (this.cookiePath) {cookie += '; path='+this.cookiePath}
       if (this.cookieDomain) {cookie += '; domain='+this.cookieDomain}        if (this.cookieDomain) {cookie += '; domain='+this.cookieDomain}
       if (this.cookie.keep != '0D') {        if (this.cookie.keep != '0D') {
Line 1452  jsMath.Controls = { Line 1746  jsMath.Controls = {
             this.cookie.keep.substr(0,1) * ms[this.cookie.keep.substr(1,1)]);              this.cookie.keep.substr(0,1) * ms[this.cookie.keep.substr(1,1)]);
         cookie += '; expires=' + exp.toGMTString();          cookie += '; expires=' + exp.toGMTString();
       }        }
       jsMath.document.cookie = 'jsMath='+cookie;        if (cookie != '') {
       var cookies = jsMath.document.cookie;          jsMath.document.cookie = 'jsMath='+cookie;
       if (warn && !cookies.match(/jsMath=/))          var cookies = jsMath.document.cookie;
         {alert("Cookies must be enabled in order to save jsMath options")}          if (warn && !cookies.match(/jsMath=/))
             {alert("Cookies must be enabled in order to save jsMath options")}
         }
     }      }
       return null;
     },
     localSetCookie: function (cookie,warn) {
       if (!warn) return;
       var href = String(jsMath.window.location).replace(/\?.*/,"");
       if (cookie != '') {href += '?jsMath=' + escape(cookie)}
       if (href != jsMath.window.location.href) {this.Reload(href)}
     },
     
     /*
      *  Reload the page (with the given URL)
      */
     Reload: function (url) {
       if (!this.loaded) return;
       this.loaded = 0; jsMath.Setup.inited = -100;
       jsMath.Global.ClearCache();
       if (url) {jsMath.window.location.replace(url)}
           else {jsMath.window.location.reload()}
   }    }
     
 };  };
   
 /***************************************************************************/  /***************************************************************************/
Line 1525  jsMath.TeX = { Line 1839  jsMath.TeX = {
   delim1:     2.39,    delim1:     2.39,
   delim2:     1.0,    delim2:     1.0,
   axis_height: .25,    axis_height: .25,
   default_rule_thickness: .04,    default_rule_thickness: .06,
   big_op_spacing1:  .111111,    big_op_spacing1:  .111111,
   big_op_spacing2:  .166666,    big_op_spacing2:  .166666,
   big_op_spacing3:  .2,    big_op_spacing3:  .2,
Line 2124  jsMath.Img = { Line 2438  jsMath.Img = {
    */     */
   UpdateFonts: function () {    UpdateFonts: function () {
     var change = this.update; if (!this.loaded) return;      var change = this.update; if (!this.loaded) return;
     var best = this[jsMath.Img.fonts[this.best]];  
     for (var font in change) {      for (var font in change) {
       for (var i = 0; i < change[font].length; i++) {        for (var i = 0; i < change[font].length; i++) {
         var c = change[font][i];          var c = change[font][i];
Line 2184  jsMath.Img = { Line 2497  jsMath.Img = {
    *  Setup for print mode, and create the hex code table     *  Setup for print mode, and create the hex code table
    */     */
   Init: function () {    Init: function () {
     if (jsMath.Controls.cookie.print) {      if (jsMath.Controls.cookie.print || jsMath.Controls.cookie.stayhires) {
       jsMath.Controls.cookie.print = 0;        jsMath.Controls.cookie.print = jsMath.Controls.cookie.stayhires;
       this.factor *= 3;        this.factor *= 3;
       if (jsMath.window.location.protocol != 'file:') {jsMath.Controls.SetCookie(0)}        if (!jsMath.Controls.isLocalCookie || !jsMath.Global.isLocal) {jsMath.Controls.SetCookie(0)}
       if (jsMath.Browser.alphaPrintBug) {jsMath.Controls.cookie.alpha = 0}        if (jsMath.Browser.alphaPrintBug) {jsMath.Controls.cookie.alpha = 0}
     }      }
     var codes = '0123456789ABCDEF';      var codes = '0123456789ABCDEF';
Line 2227  jsMath.HTML = { Line 2540  jsMath.HTML = {
    */     */
   Spacer: function (w) {    Spacer: function (w) {
     if (w == 0) {return ''};      if (w == 0) {return ''};
     return '<span class="spacer" style="margin-left:'+this.Em(w)+'"></span>';      return jsMath.Browser.msieSpaceFix+'<span class="spacer" style="margin-left:'+this.Em(w)+'"></span>';
   },    },
       
   /*    /*
Line 2251  jsMath.HTML = { Line 2564  jsMath.HTML = {
     if (d == null) {d = 0}      if (d == null) {d = 0}
     if (h) {      if (h) {
       var H = this.Em(h+d);        var H = this.Em(h+d);
       if (isRule && h > 0 && h*jsMath.em < 1.5) {H = "1px"; h = 1/jsMath.em}        if (isRule && h*jsMath.em < 1.5) {H = "1px"; h = 1/jsMath.em}
       style += 'height:'+H+';';        style += 'height:'+H+';';
     }      }
     if (jsMath.Browser.mozInlineBlockBug) {d = -h}      if (jsMath.Browser.mozInlineBlockBug) {d = -h}
Line 2298  jsMath.HTML = { Line 2611  jsMath.HTML = {
    *  also doesn't combine vertical and horizontal spacing well.     *  also doesn't combine vertical and horizontal spacing well.
    *  Here the x and y positioning are done in separate <SPAN> tags     *  Here the x and y positioning are done in separate <SPAN> tags
    */     */
   PlaceSeparateSkips: function (html,x,y) {    PlaceSeparateSkips: function (html,x,y,mw,Mw,w) {
     if (Math.abs(x) < .0001) {x = 0}      if (Math.abs(x) < .0001) {x = 0}
     if (Math.abs(y) < .0001) {y = 0}      if (Math.abs(y) < .0001) {y = 0}
     if (y) {html = '<span style="position: relative; top:'+this.Em(-y)+';'      if (y) {
                        + '">' + html + '</span>'}        var lw = 0; var rw = 0; var width = "";
         if (mw != null) {
           rw = Mw - w; lw = mw;
           width = ' width:'+this.Em(Mw-mw)+';';
         }
         html = 
           this.Spacer(lw-rw) +
           '<span style="position: relative; '
               + 'top:'+this.Em(-y)+';'
               + 'left:'+this.Em(rw)+';'
               + width + '">' +
             this.Spacer(-lw) +
             html +
             this.Spacer(rw) +
           '</span>'
       }
     if (x) {html = this.Spacer(x) + html}      if (x) {html = this.Spacer(x) + html}
     return html;      return html;
   },    },
Line 2310  jsMath.HTML = { Line 2638  jsMath.HTML = {
   /*    /*
    *  Place a SPAN with absolute coordinates     *  Place a SPAN with absolute coordinates
    */     */
   PlaceAbsolute: function (html,x,y) {    PlaceAbsolute: function (html,x,y,mw,Mw,w) {
     if (Math.abs(x) < .0001) {x = 0}      if (Math.abs(x) < .0001) {x = 0}
     if (Math.abs(y) < .0001) {y = 0}      if (Math.abs(y) < .0001) {y = 0}
     html = '<span style="position:absolute; left:'+this.Em(x)+'; '      var leftSpace = ""; var rightSpace = "";
               + 'top:'+this.Em(y)+';">' + html + '&nbsp;</span>';      if (jsMath.Browser.msieRelativeClipBug && mw != null) {
               //  space normalizes line height in script styles        leftSpace  = this.Spacer(-mw); x += mw;
         rightSpace = this.Spacer(Mw-w);
       }
       html =
         '<span style="position:absolute; left:'+this.Em(x)+'; '
               + 'top:'+this.Em(y)+';">' +
           leftSpace + html + rightSpace +
           '&nbsp;' + //  space normalizes line height in script styles
         '</span>';
     return html;      return html;
   },    },
   
Line 2332  jsMath.HTML = { Line 2668  jsMath.HTML = {
     if (jsMath.Browser.msieAbsoluteBug) {           // for MSIE (Mac)      if (jsMath.Browser.msieAbsoluteBug) {           // for MSIE (Mac)
       html = '<span style="position:relative;">' + html + '</span>';        html = '<span style="position:relative;">' + html + '</span>';
     }      }
     html =   '<span style="position:relative;'      if (jsMath.Browser.spanHeightVaries) {
            +     ' width: '+jsMath.HTML.Em(w)+';'   // for MSIE        html = '<span style="position:relative;'
            +     ' height: '+jsMath.HTML.Em(H)+';'  // for MSIE             +   ' width:'+jsMath.HTML.Em(w)+';'
            +     jsMath.Browser.msieInlineBlockFix  // for MSIE             +   ' height:'+jsMath.HTML.Em(H)+';'
            +     '">'             +   jsMath.Browser.msieInlineBlockFix
              + '">'
            +   html             +   html
            + '</span>';             + '</span>';
       } else {
         html = '<span style="position:relative">' + html + '</span>';
       }
     return html;      return html;
   }    }
   
Line 2355  jsMath.Box = function (format,text,w,h,d Line 2695  jsMath.Box = function (format,text,w,h,d
   if (d == null) {d = jsMath.d}    if (d == null) {d = jsMath.d}
   this.type = 'typeset';    this.type = 'typeset';
   this.w = w; this.h = h; this.d = d; this.bh = h; this.bd = d;    this.w = w; this.h = h; this.d = d; this.bh = h; this.bd = d;
   this.x = 0; this.y = 0;    this.x = 0; this.y = 0; this.mw = 0; this.Mw = w;
   this.html = text; this.format = format;    this.html = text; this.format = format;
 };  };
   
Line 2367  jsMath.Add(jsMath.Box,{ Line 2707  jsMath.Add(jsMath.Box,{
   /*    /*
    *  An empty box     *  An empty box
    */     */
   Null: new jsMath.Box('null','',0,0,0),    Null: function () {return new jsMath.Box('null','',0,0,0)},
   
   /*    /*
    *  A box containing only text whose class and style haven't been added     *  A box containing only text whose class and style haven't been added
Line 2413  jsMath.Add(jsMath.Box,{ Line 2753  jsMath.Add(jsMath.Box,{
         // hack to avoid font changing back to the default          // hack to avoid font changing back to the default
         // font when a unicode reference is not followed          // font when a unicode reference is not followed
         // by a letter or number          // by a letter or number
         box.html += '<span style="display: none">x</span>';          box.html += '<span style="display:none">x</span>';
       }        }
     }      }
     return box;      return box;
Line 2424  jsMath.Add(jsMath.Box,{ Line 2764  jsMath.Add(jsMath.Box,{
    *  sizes of the characters precomputed     *  sizes of the characters precomputed
    */     */
   TeXfallback: function (C,font,style,size) {    TeXfallback: function (C,font,style,size) {
     c = jsMath.TeX[font][C]; if (!c.tclass) {c.tclass = font}      var c = jsMath.TeX[font][C]; if (!c.tclass) {c.tclass = font}
     if (c.img != null) {return this.TeXnonfallback(C,font,style,size)}      if (c.img != null) {return this.TeXnonfallback(C,font,style,size)}
     if (c.h != null && c.a == null) {c.a = c.h-1.1*jsMath.TeX.x_height}      if (c.h != null && c.a == null) {c.a = c.h-1.1*jsMath.TeX.x_height}
     var box = this.Text(c.c,c.tclass,style,size,c.a,c.d);      var a = c.a; var d = c.d; // avoid Firefox warnings
       var box = this.Text(c.c,c.tclass,style,size,a,d);
     var scale = jsMath.Typeset.TeX(style,size).scale;      var scale = jsMath.Typeset.TeX(style,size).scale;
     if (c.bh != null) {      if (c.bh != null) {
       box.bh = c.bh*scale;        box.bh = c.bh*scale;
Line 2565  jsMath.Add(jsMath.Box,{ Line 2906  jsMath.Add(jsMath.Box,{
     var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font);      var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font);
     var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c);      var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c);
     var w = rep.w; var h = rep.h+rep.d      var w = rep.w; var h = rep.h+rep.d
     var y; var dx;      var y; var Y; var html; var dx; var i; var n;
     if (C.delim.mid) {// braces      if (C.delim.mid) {// braces
       var mid = this.GetChar(C.delim.mid,font);        var mid = this.GetChar(C.delim.mid,font);
       var n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d)-(bot.h+bot.d))/(2*(rep.h+rep.d)));        n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d)-(bot.h+bot.d))/(2*(rep.h+rep.d)));
       H = 2*n*(rep.h+rep.d) + (top.h+top.d) + (mid.h+mid.d) + (bot.h+bot.d);        H = 2*n*(rep.h+rep.d) + (top.h+top.d) + (mid.h+mid.d) + (bot.h+bot.d);
       if (nocenter) {y = 0} else {y = H/2+a}; var Y = y;        if (nocenter) {y = 0} else {y = H/2+a}; Y = y;
       var html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)        html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)
                + jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(top.w+bot.w)/2,y-(H-bot.d))             + jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(top.w+bot.w)/2,y-(H-bot.d))
                + jsMath.HTML.Place(jsMath.Typeset.AddClass(mid.tclass,mid.c),-(bot.w+mid.w)/2,y-(H+mid.h-mid.d)/2);             + jsMath.HTML.Place(jsMath.Typeset.AddClass(mid.tclass,mid.c),-(bot.w+mid.w)/2,y-(H+mid.h-mid.d)/2);
       dx = (w-mid.w)/2; if (Math.abs(dx) < .0001) {dx = 0}        dx = (w-mid.w)/2; if (Math.abs(dx) < .0001) {dx = 0}
       if (dx) {html += jsMath.HTML.Spacer(dx)}        if (dx) {html += jsMath.HTML.Spacer(dx)}
       y -= top.h+top.d + rep.h;        y -= top.h+top.d + rep.h;
       for (var i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}        for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}
       y -= H/2 - rep.h/2;        y -= H/2 - rep.h/2;
       for (var i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}        for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}
     } else {// everything else      } else {// everything else
       var n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d))/(rep.h+rep.d));        n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d))/(rep.h+rep.d));
       // make sure two-headed arrows have an extender        // make sure two-headed arrows have an extender
       if (top.h+top.d < .9*(rep.h+rep.d)) {n = Math.max(1,n)}        if (top.h+top.d < .9*(rep.h+rep.d)) {n = Math.max(1,n)}
       H = n*(rep.h+rep.d) + (top.h+top.d) + (bot.h+bot.d);        H = n*(rep.h+rep.d) + (top.h+top.d) + (bot.h+bot.d);
       if (nocenter) {y = 0} else {y = H/2+a}; var Y = y;        if (nocenter) {y = 0} else {y = H/2+a}; Y = y;
       var html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)        html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)
       dx = (w-top.w)/2; if (Math.abs(dx) < .0001) {dx = 0}        dx = (w-top.w)/2; if (Math.abs(dx) < .0001) {dx = 0}
       if (dx) {html += jsMath.HTML.Spacer(dx)}        if (dx) {html += jsMath.HTML.Spacer(dx)}
       y -= top.h+top.d + rep.h;        y -= top.h+top.d + rep.h;
       for (var i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}        for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}
       html += jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(w+bot.w)/2,Y-(H-bot.d));        html += jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(w+bot.w)/2,Y-(H-bot.d));
     }      }
     if (nocenter) {h = top.h} else {h = H/2+a}      if (nocenter) {h = top.h} else {h = H/2+a}
Line 2607  jsMath.Add(jsMath.Box,{ Line 2948  jsMath.Add(jsMath.Box,{
    */     */
   DelimExtendAbsolute: function (H,c,font,a,nocenter) {    DelimExtendAbsolute: function (H,c,font,a,nocenter) {
     var Font = jsMath.TeX[font];      var Font = jsMath.TeX[font];
     var C = Font[c];      var C = Font[c]; var html;
     var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font);      var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font);
     var rep = this.GetChar(C.delim.rep,font);      var rep = this.GetChar(C.delim.rep,font);
     var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font);      var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font);
       var n; var h; var y; var ext; var i;
           
     if (C.delim.mid) {// braces      if (C.delim.mid) {// braces
       var mid = this.GetChar(C.delim.mid,font);        var mid = this.GetChar(C.delim.mid,font);
       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)));        n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d-.05)-(bot.h+bot.d-.05))/(2*(rep.h+rep.d-.05)));
       H = 2*n*(rep.h+rep.d-.05) + (top.h+top.d) + (mid.h+mid.d-.05) + (bot.h+bot.d-.05);        H = 2*n*(rep.h+rep.d-.05) + (top.h+top.d) + (mid.h+mid.d-.05) + (bot.h+bot.d-.05);
               
       html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0);        html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0);
       var h = rep.h+rep.d - .05; var y = top.d-.05 + rep.h;        h = rep.h+rep.d - .05; y = top.d-.05 + rep.h;
       var ext = jsMath.Typeset.AddClass(font,rep.c)        ext = jsMath.Typeset.AddClass(font,rep.c)
       for (var i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}        for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}
       html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(mid.tclass,mid.c),0,y+n*h-rep.h+mid.h);        html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(mid.tclass,mid.c),0,y+n*h-rep.h+mid.h);
       y += n*h + mid.h+mid.d - .05;        y += n*h + mid.h+mid.d - .05;
       for (var i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}        for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}
       html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h);        html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h);
     } else {// all others      } else {// all others
       var n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d-.05))/(rep.h+rep.d-.05));        n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d-.05))/(rep.h+rep.d-.05));
       H = n*(rep.h+rep.d-.05) + (top.h+top.d) + (bot.h+bot.d-.05);        H = n*(rep.h+rep.d-.05) + (top.h+top.d) + (bot.h+bot.d-.05);
   
       html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0);        html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0);
       var h = rep.h+rep.d-.05; var y = top.d-.05 + rep.h;        h = rep.h+rep.d-.05; y = top.d-.05 + rep.h;
       var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c);        ext = jsMath.Typeset.AddClass(rep.tclass,rep.c);
       for (var i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}        for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}
       html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h);        html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h);
     }      }
           
     var w = top.w;      var w = top.w;
     if (nocenter) {h = top.h; y = 0} else {h = H/2 + a; y = h - top.h}      if (nocenter) {h = top.h; y = 0} else {h = H/2 + a; y = h - top.h}
     html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y,top.h);  //    html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y,top.h);
       html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y,jsMath.h);
     var box = new jsMath.Box('html',html,rep.w,h,H-h);      var box = new jsMath.Box('html',html,rep.w,h,H-h);
     box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;      box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;
     return box;      return box;
Line 2659  jsMath.Add(jsMath.Box,{ Line 3002  jsMath.Add(jsMath.Box,{
     if (CFSH == null) {return this.Space(TeX.nulldelimiterspace)}      if (CFSH == null) {return this.Space(TeX.nulldelimiterspace)}
     if (CFSH[2] == '')      if (CFSH[2] == '')
       {return this.DelimExtend(H,CFSH[0],CFSH[1],TeX.axis_height,nocenter)}        {return this.DelimExtend(H,CFSH[0],CFSH[1],TeX.axis_height,nocenter)}
     box = jsMath.Box.TeX(CFSH[0],CFSH[1],CFSH[2],size).Styled();      var box = jsMath.Box.TeX(CFSH[0],CFSH[1],CFSH[2],size).Styled();
     if (nocenter) {box.y = -jsMath.TeX[CFSH[1]].dh*TeX.scale}      if (nocenter) {box.y = -jsMath.TeX[CFSH[1]].dh*TeX.scale}
       else {box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height)}        else {box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height)}
     if (Math.abs(box.y) < .0001) {box.y = 0}      if (Math.abs(box.y) < .0001) {box.y = 0}
Line 2701  jsMath.Add(jsMath.Box,{ Line 3044  jsMath.Add(jsMath.Box,{
    *  ###  still need to allow users to specify row and column attributes,     *  ###  still need to allow users to specify row and column attributes,
    *       and do things like \span and \multispan  ###     *       and do things like \span and \multispan  ###
    */     */
   LayoutRelative: function (size,table,align,cspacing) {    LayoutRelative: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) {
     if (align == null) {align = []}      if (align == null) {align = []}
     if (cspacing == null) {cspacing = []}      if (cspacing == null) {cspacing = []}
       if (rspacing == null) {rspacing = []}
       if (useStrut == null) {useStrut = 1}
       if (addWidth == null) {addWidth = 1}
           
     // get row and column maximum dimensions      // get row and column maximum dimensions
     var scale = jsMath.sizes[size]/100;      var scale = jsMath.sizes[size]/100;
Line 2711  jsMath.Add(jsMath.Box,{ Line 3057  jsMath.Add(jsMath.Box,{
     var unset = -1000; var bh = unset; var bd = unset;      var unset = -1000; var bh = unset; var bd = unset;
     var i; var j; var row;      var i; var j; var row;
     for (i = 0; i < table.length; i++) {      for (i = 0; i < table.length; i++) {
       row = table[i]; H[i] = jsMath.h*scale; D[i] = jsMath.d*scale;        if (rspacing[i] == null) {rspacing[i] = 0}
         row = table[i];
         H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale;
       for (j = 0; j < row.length; j++) {        for (j = 0; j < row.length; j++) {
         row[j] = row[j].Remeasured();          row[j] = row[j].Remeasured();
         if (row[j].h > H[i]) {H[i] = row[j].h}          if (row[j].h > H[i]) {H[i] = row[j].h}
Line 2722  jsMath.Add(jsMath.Box,{ Line 3070  jsMath.Add(jsMath.Box,{
         if (row[j].bd > bd) {bd = row[j].bd}          if (row[j].bd > bd) {bd = row[j].bd}
       }        }
     }      }
       if (rspacing[table.length] == null) {rspacing[table.length] = 0}
     if (bh == unset) {bh = 0}; if (bd == unset) {bd = 0}      if (bh == unset) {bh = 0}; if (bd == unset) {bd = 0}
   
     // lay out the columns      // lay out the columns
     var HD = (jsMath.hd-.01)*scale;      var HD = useStrut*(jsMath.hd-.01)*scale;
       var dy = (vspace || 1) * scale/6;
     var html = ''; var pW = 0; var cW = 0;      var html = ''; var pW = 0; var cW = 0;
     var w; var h; var y;      var w; var h; var y;
     var box; var mlist; var entry;      var box; var mlist; var entry;
     for (j = 0; j < W.length; j++) {      for (j = 0; j < W.length; j++) {
       mlist = []; y = -H[0]; pW = 0;        mlist = []; y = -H[0]-rspacing[0]; pW = 0;
       for (i = 0; i < table.length; i++) {        for (i = 0; i < table.length; i++) {
         entry = table[i][j];          entry = table[i][j];
         if (entry && entry.format != 'null') {          if (entry && entry.format != 'null') {
Line 2740  jsMath.Add(jsMath.Box,{ Line 3090  jsMath.Add(jsMath.Box,{
           entry.x = w - pW; pW = entry.w + w; entry.y = y;            entry.x = w - pW; pW = entry.w + w; entry.y = y;
           mlist[mlist.length] = entry;            mlist[mlist.length] = entry;
         }          }
         if (i == table.length-1) {y -= D[i]}          if (i+1 < table.length) {y -= Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]}
         else {y -= Math.max(HD,D[i]+H[i+1]) + scale/10}  
       }        }
       if (cspacing[j] == null) cspacing[j] = scale;        if (cspacing[j] == null) cspacing[j] = scale;
       if (mlist.length > 0) {        if (mlist.length > 0) {
Line 2752  jsMath.Add(jsMath.Box,{ Line 3101  jsMath.Add(jsMath.Box,{
     }      }
           
     // get the full width and height      // get the full width and height
     w = -cspacing[W.length-1]; y = (H.length-1)*scale/10;      w = -cspacing[W.length-1]; y = (H.length-1)*dy + rspacing[0];
     for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]}      for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]}
     for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i])}      for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]}
     h = y/2 + jsMath.TeX.axis_height; var d = y-h;      h = y/2 + jsMath.TeX.axis_height; var d = y-h;
           
     // adjust the final row width, and vcenter the table      // adjust the final row width, and vcenter the table
     //   (add 1/6em at each side for the \,)      //   (add 1/6em at each side for the \,)
     html += jsMath.HTML.Spacer(cW-cspacing[W.length-1] + scale/6);      html += jsMath.HTML.Spacer(cW-cspacing[W.length-1] + addWidth*scale/6);
     html = jsMath.HTML.Place(html,scale/6,h);      html = jsMath.HTML.Place(html,addWidth*scale/6,h);
     box = new jsMath.Box('html',html,w+scale/3,h,d);      box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d);
     box.bh = bh; box.bd = bd;      box.bh = bh; box.bd = bd;
     return box;      return box;
   },    },
Line 2773  jsMath.Add(jsMath.Box,{ Line 3122  jsMath.Add(jsMath.Box,{
    *  ###  still need to allow users to specify row and column attributes,     *  ###  still need to allow users to specify row and column attributes,
    *       and do things like \span and \multispan  ###     *       and do things like \span and \multispan  ###
    */     */
   LayoutAbsolute: function (size,table,align,cspacing) {    LayoutAbsolute: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) {
     if (align == null) {align = []}      if (align == null) {align = []}
     if (cspacing == null) {cspacing = []}      if (cspacing == null) {cspacing = []}
       if (rspacing == null) {rspacing = []}
       if (useStrut == null) {useStrut = 1}
       if (addWidth == null) {addWidth = 1}
           
     // get row and column maximum dimensions      // get row and column maximum dimensions
     var scale = jsMath.sizes[size]/100;      var scale = jsMath.sizes[size]/100;
     var HD = (jsMath.hd-.01)*scale;      var HD = useStrut*(jsMath.hd-.01)*scale;
       var dy = (vspace || 1) * scale/6;
     var W = []; var H = []; var D = [];      var W = []; var H = []; var D = [];
     var w = 0; var h; var x; var y;      var w = 0; var h; var x; var y;
     var i; var j; var row;      var i; var j; var row;
     for (i = 0; i < table.length; i++) {      for (i = 0; i < table.length; i++) {
         if (rspacing[i] == null) {rspacing[i] = 0}
       row = table[i];        row = table[i];
       H[i] = jsMath.h*scale; D[i] = jsMath.d*scale;        H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale;
       for (j = 0; j < row.length; j++) {        for (j = 0; j < row.length; j++) {
         row[j] = row[j].Remeasured();          row[j] = row[j].Remeasured();
         if (row[j].h > H[i]) {H[i] = row[j].h}          if (row[j].h > H[i]) {H[i] = row[j].h}
Line 2794  jsMath.Add(jsMath.Box,{ Line 3148  jsMath.Add(jsMath.Box,{
         else if (row[j].w > W[j]) {W[j] = row[j].w}          else if (row[j].w > W[j]) {W[j] = row[j].w}
       }        }
     }      }
       if (rspacing[table.length] == null) {rspacing[table.length] = 0}
   
     // get the height and depth of the centered table      // get the height and depth of the centered table
     y = (H.length-1)*scale/6;      y = (H.length-1)*dy + rspacing[0];
     for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i])}      for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]}
     h = y/2 + jsMath.TeX.axis_height; var d = y - h;      h = y/2 + jsMath.TeX.axis_height; var d = y - h;
   
     // lay out the columns      // lay out the columns
     var html = ''; var entry; w = scale/6;      var html = ''; var entry; w = addWidth*scale/6;
     for (j = 0; j < W.length; j++) {      for (j = 0; j < W.length; j++) {
       y = H[0]-h;        y = H[0]-h + rspacing[0];
       for (i = 0; i < table.length; i++) {        for (i = 0; i < table.length; i++) {
         entry = table[i][j];          entry = table[i][j];
         if (entry && entry.format != 'null') {          if (entry && entry.format != 'null') {
           if (align[j] == 'l') {x = 0} else            if (align[j] && align[j] == 'l') {x = 0} else
           if (align[j] == 'r') {x = W[j] - entry.w} else            if (align[j] && align[j] == 'r') {x = W[j] - entry.w} else
             {x = (W[j] - entry.w)/2}              {x = (W[j] - entry.w)/2}
           html += jsMath.HTML.PlaceAbsolute(entry.html,w+x,            html += jsMath.HTML.PlaceAbsolute(entry.html,w+x,
                     y-Math.max(0,entry.bh-jsMath.h*scale));                      y-Math.max(0,entry.bh-jsMath.h*scale),
                       entry.mw,entry.Mw,entry.w);
         }          }
         if (i == table.length-1) {y += D[i]}          if (i+1 < table.length) {y += Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]}
         else {y += Math.max(HD,D[i]+H[i+1]) + scale/6}  
       }        }
       if (cspacing[j] == null) cspacing[j] = scale;        if (cspacing[j] == null) cspacing[j] = scale;
       w += W[j] + cspacing[j];        w += W[j] + cspacing[j];
     }      }
           
     // get the full width      // get the full width
     w = -cspacing[W.length-1]+scale/3;      w = -cspacing[W.length-1]+addWidth*scale/3;
     for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]}      for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]}
   
     html = jsMath.HTML.Spacer(scale/6)+html+jsMath.HTML.Spacer(scale/6);      html = jsMath.HTML.Spacer(addWidth*scale/6)+html+jsMath.HTML.Spacer(addWidth*scale/6);
     if (jsMath.Browser.spanHeightVaries) {y = h-jsMath.h} else {y = 0}      if (jsMath.Browser.spanHeightVaries) {y = h-jsMath.h} else {y = 0}
     html = jsMath.HTML.Absolute(html,w,h+d,d,y,H[0]);  //    html = jsMath.HTML.Absolute(html,w,h+d,d,y,H[0]);
     var box = new jsMath.Box('html',html,w+scale/3,h,d);      html = jsMath.HTML.Absolute(html,w,h+d,d,y,h);
       var box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d);
     return box;      return box;
   },    },
   
Line 2835  jsMath.Add(jsMath.Box,{ Line 3191  jsMath.Add(jsMath.Box,{
    *  Look for math within \hbox and other non-math text     *  Look for math within \hbox and other non-math text
    */     */
   InternalMath: function (text,size) {    InternalMath: function (text,size) {
       text = text.replace(/@\(([^)]*)\)/g,'<$1>');
     if (!text.match(/\$|\\\(/)) {return this.Text(text,'normal','T',size).Styled()}      if (!text.match(/\$|\\\(/)) {return this.Text(text,'normal','T',size).Styled()}
           
     var i = 0; var k = 0; var c; var match = '';      var i = 0; var k = 0; var c; var match = '';
     var mlist = []; var parse; var html; var box;      var mlist = []; var parse;
     while (i < text.length) {      while (i < text.length) {
       c = text.charAt(i++);        c = text.charAt(i++);
       if (c == '$') {        if (c == '$') {
Line 2889  jsMath.Add(jsMath.Box,{ Line 3246  jsMath.Add(jsMath.Box,{
         return box.mlist.Typeset(style,size);          return box.mlist.Typeset(style,size);
       }        }
       if (box.type == 'text') {        if (box.type == 'text') {
         box = this.Text(box.text,box.tclass,style,size,box.ascend,box.descend);          box = this.Text(box.text,box.tclass,style,size,box.ascend||null,box.descend||null);
         if (addstyle != 0) {box.Styled()}          if (addstyle != 0) {box.Styled()}
         return box;          return box;
       }        }
Line 2897  jsMath.Add(jsMath.Box,{ Line 3254  jsMath.Add(jsMath.Box,{
       if (addstyle != 0) {box.Styled()}        if (addstyle != 0) {box.Styled()}
       return box;        return box;
     }      }
     return jsMath.Box.Null;      return jsMath.Box.Null();
   },    },
   
   /*    /*
Line 2938  jsMath.Package(jsMath.Box,{ Line 3295  jsMath.Package(jsMath.Box,{
    *  Recompute the box width to make it more accurate.     *  Recompute the box width to make it more accurate.
    */     */
   Remeasured: function () {    Remeasured: function () {
     if (this.w > 0 && !this.html.match(/position: ?absolute/))      if (this.w > 0) {this.w = jsMath.EmBoxFor(this.html).w}
       {this.w = jsMath.EmBoxFor(this.html).w}  
     return this;      return this;
   }    }
   
Line 3183  jsMath.Package(jsMath.mList,{ Line 3539  jsMath.Package(jsMath.mList,{
   AddDelimiters: function(style,size) {    AddDelimiters: function(style,size) {
     var unset = -10000; var h = unset; var d = unset;      var unset = -10000; var h = unset; var d = unset;
     for (var i = 0; i < this.mlist.length; i++) {      for (var i = 0; i < this.mlist.length; i++) {
       mitem = this.mlist[i];        var mitem = this.mlist[i];
       if (mitem.atom || mitem.type == 'box') {        if (mitem.atom || mitem.type == 'box') {
         h = Math.max(h,mitem.nuc.h+mitem.nuc.y);          h = Math.max(h,mitem.nuc.h+mitem.nuc.y);
         d = Math.max(d,mitem.nuc.d-mitem.nuc.y);          d = Math.max(d,mitem.nuc.d-mitem.nuc.y);
Line 3239  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3595  jsMath.Add(jsMath.mList.prototype.Atomiz
   phantom: function (style,size,mitem) {    phantom: function (style,size,mitem) {
     var box = mitem.nuc = jsMath.Box.Set(mitem.phantom,style,size);      var box = mitem.nuc = jsMath.Box.Set(mitem.phantom,style,size);
     if (mitem.h) {box.Remeasured(); box.html = jsMath.HTML.Spacer(box.w)}      if (mitem.h) {box.Remeasured(); box.html = jsMath.HTML.Spacer(box.w)}
       else {box.html = '', box.w = 0}        else {box.html = '', box.w = box.Mw = box.mw = 0;}
     if (!mitem.v) {box.h = box.d = 0}      if (!mitem.v) {box.h = box.d = 0}
     box.bd = box.bh = 0;      box.bd = box.bh = 0;
     delete mitem.phantom;      delete mitem.phantom;
Line 3252  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3608  jsMath.Add(jsMath.mList.prototype.Atomiz
    */     */
   smash: function (style,size,mitem) {    smash: function (style,size,mitem) {
     var box = mitem.nuc = jsMath.Box.Set(mitem.smash,style,size).Remeasured();      var box = mitem.nuc = jsMath.Box.Set(mitem.smash,style,size).Remeasured();
     box.h = box.d = box.bd = box.bh = 0;      box.h = box.d = 0;
     delete mitem.smash;      delete mitem.smash;
     mitem.type = 'box';      mitem.type = 'box';
   },    },
Line 3263  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3619  jsMath.Add(jsMath.mList.prototype.Atomiz
   raise: function (style,size,mitem) {    raise: function (style,size,mitem) {
     mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size);      mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size);
     var y = mitem.raise;      var y = mitem.raise;
     mitem.nuc.html = jsMath.HTML.Place(mitem.nuc.html,0,y);      mitem.nuc.html =
         jsMath.HTML.Place(mitem.nuc.html,0,y,mitem.nuc.mw,mitem.nuc.Mw,mitem.nuc.w);
     mitem.nuc.h += y; mitem.nuc.d -= y;      mitem.nuc.h += y; mitem.nuc.d -= y;
     mitem.type = 'ord'; mitem.atom = 1;      mitem.type = 'ord'; mitem.atom = 1;
   },    },
Line 3288  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3645  jsMath.Add(jsMath.mList.prototype.Atomiz
    *  Handle a Bin atom. (Rule 5)     *  Handle a Bin atom. (Rule 5)
    */     */
   bin: function (style,size,mitem,prev) {    bin: function (style,size,mitem,prev) {
     if (prev) {      if (prev && prev.type) {
       var type  = prev.type;        var type  = prev.type;
       if (type == 'bin' || type == 'op' || type == 'rel' ||        if (type == 'bin' || type == 'op' || type == 'rel' ||
           type == 'open' || type == 'punct' || type == '' ||            type == 'open' || type == 'punct' || type == '' ||
Line 3301  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3658  jsMath.Add(jsMath.mList.prototype.Atomiz
    *  Handle a Rel atom.  (Rule 6)     *  Handle a Rel atom.  (Rule 6)
    */     */
   rel: function (style,size,mitem,prev) {    rel: function (style,size,mitem,prev) {
     if (prev.type == 'bin') {prev.type = 'ord'}      if (prev.type && prev.type == 'bin') {prev.type = 'ord'}
     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);      jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
   },    },
   
Line 3309  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3666  jsMath.Add(jsMath.mList.prototype.Atomiz
    *  Handle a Close atom.  (Rule 6)     *  Handle a Close atom.  (Rule 6)
    */     */
   close: function (style,size,mitem,prev) {    close: function (style,size,mitem,prev) {
     if (prev.type == 'bin') {prev.type = 'ord'}      if (prev.type && prev.type == 'bin') {prev.type = 'ord'}
     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);      jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
   },    },
   
Line 3317  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3674  jsMath.Add(jsMath.mList.prototype.Atomiz
    *  Handle a Punct atom.  (Rule 6)     *  Handle a Punct atom.  (Rule 6)
    */     */
   punct: function (style,size,mitem,prev) {    punct: function (style,size,mitem,prev) {
     if (prev.type == 'bin') {prev.type = 'ord'}      if (prev.type && prev.type == 'bin') {prev.type = 'ord'}
     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);      jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
   },    },
   
Line 3387  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3744  jsMath.Add(jsMath.mList.prototype.Atomiz
     var p = t; if (style == 'D' || style == "D'") {p = TeX.x_height}      var p = t; if (style == 'D' || style == "D'") {p = TeX.x_height}
     var r = t + p/4;       var r = t + p/4; 
     var surd = jsMath.Box.Delimiter(box.h+box.d+r+t,[0,2,0x70,3,0x70],style,1);      var surd = jsMath.Box.Delimiter(box.h+box.d+r+t,[0,2,0x70,3,0x70],style,1);
     t = surd.h; // thickness of rule is height of surd character  //    if (surd.h > 0) {t = surd.h} // thickness of rule is height of surd character
     if (surd.d > box.h+box.d+r) {r = (r+surd.d-box.h-box.d)/2}      if (surd.d > box.h+box.d+r) {r = (r+surd.d-box.h-box.d)/2}
     surd.y = box.h+r;      surd.y = box.h+r;
     var rule = jsMath.Box.Rule(box.w,t);      var rule = jsMath.Box.Rule(box.w,t);
     rule.y = surd.y-t/2; rule.h += 3*t/2; box.x = -box.w;      rule.y = surd.y-t/2; rule.h += 3*t/2; box.x = -box.w;
     var Cr = jsMath.Typeset.UpStyle(jsMath.Typeset.UpStyle(style));      var Cr = jsMath.Typeset.UpStyle(jsMath.Typeset.UpStyle(style));
     var root = jsMath.Box.Set(mitem.root,Cr,size).Remeasured();      var root = jsMath.Box.Set(mitem.root || null,Cr,size).Remeasured();
     if (mitem.root) {      if (mitem.root) {
       root.y = .55*(box.h+box.d+3*t+r)-box.d;        root.y = .55*(box.h+box.d+3*t+r)-box.d;
       surd.x = Math.max(root.w-(11/18)*surd.w,0);        surd.x = Math.max(root.w-(11/18)*surd.w,0);
Line 3412  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3769  jsMath.Add(jsMath.mList.prototype.Atomiz
     var TeX = jsMath.Typeset.TeX(style,size);      var TeX = jsMath.Typeset.TeX(style,size);
     var Cp = jsMath.Typeset.PrimeStyle(style);      var Cp = jsMath.Typeset.PrimeStyle(style);
     var box = jsMath.Box.Set(mitem.nuc,Cp,size);      var box = jsMath.Box.Set(mitem.nuc,Cp,size);
     var u = box.w; var s; var Font;      var u = box.w; var s; var Font; var ic = 0;
     if (mitem.nuc.type == 'TeX') {      if (mitem.nuc.type == 'TeX') {
       Font = jsMath.TeX[mitem.nuc.font];        Font = jsMath.TeX[mitem.nuc.font];
       if (Font[mitem.nuc.c].krn && Font.skewchar)        if (Font[mitem.nuc.c].krn && Font.skewchar)
         {s = Font[mitem.nuc.c].krn[Font.skewchar]}          {s = Font[mitem.nuc.c].krn[Font.skewchar]}
         ic = Font[mitem.nuc.c].ic; if (ic == null) {ic = 0}
     }      }
     if (s == null) {s = 0}      if (s == null) {s = 0}
           
Line 3435  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3793  jsMath.Add(jsMath.mList.prototype.Atomiz
     }      }
     var acc = jsMath.Box.TeX(c,font,style,size);      var acc = jsMath.Box.TeX(c,font,style,size);
     acc.y = box.h - delta; acc.x = -box.w + s + (u-acc.w)/2;      acc.y = box.h - delta; acc.x = -box.w + s + (u-acc.w)/2;
     if (Font[c].ic) {acc.x -= Font[c].ic * TeX.scale}      if (jsMath.Browser.msieAccentBug) 
         {acc.html += jsMath.HTML.Spacer(.1); acc.w += .1; acc.Mw += .1}
       if (Font[c].ic || ic) {acc.x += (ic - (Font[c].ic||0)) * TeX.scale}
   
     mitem.nuc = jsMath.Box.SetList([box,acc],style,size);      mitem.nuc = jsMath.Box.SetList([box,acc],style,size);
     if (mitem.nuc.w != box.w) {      if (mitem.nuc.w != box.w) {
Line 3457  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3817  jsMath.Add(jsMath.mList.prototype.Atomiz
     if (mitem.nuc.type == 'TeX') {      if (mitem.nuc.type == 'TeX') {
       var C = jsMath.TeX[mitem.nuc.font][mitem.nuc.c];        var C = jsMath.TeX[mitem.nuc.font][mitem.nuc.c];
       if (isD && C.n) {mitem.nuc.c = C.n; C = jsMath.TeX[mitem.nuc.font][C.n]}        if (isD && C.n) {mitem.nuc.c = C.n; C = jsMath.TeX[mitem.nuc.font][C.n]}
       box = jsMath.Box.Set(mitem.nuc,style,size);        box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size);
       if (C.ic) {        if (C.ic) {
         mitem.delta = C.ic * TeX.scale;          mitem.delta = C.ic * TeX.scale;
         if (mitem.limits || !mitem.sub || jsMath.Browser.msieIntegralBug)           if (mitem.limits || !mitem.sub || jsMath.Browser.msieIntegralBug) {
           {box = jsMath.Box.SetList([box,jsMath.mItem.Space(mitem.delta)],style,size)}            box = mitem.nuc = jsMath.Box.SetList([box,jsMath.mItem.Space(mitem.delta)],style,size);
           }
       }        }
       box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height);        box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height);
       if (Math.abs(box.y) < .0001) {box.y = 0}        if (Math.abs(box.y) < .0001) {box.y = 0}
     }      }
       
     if (!box) {box = jsMath.Box.Set(mitem.nuc,style,size).Remeasured()}      if (!box) {box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size).Remeasured()}
     if (mitem.limits) {      if (mitem.limits) {
       var W = box.w; var x = box.w;        var W = box.w; var x = box.w;
       var mlist = [box]; var dh = 0; var dd = 0;        var mlist = [box]; var dh = 0; var dd = 0;
Line 3537  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3898  jsMath.Add(jsMath.mList.prototype.Atomiz
     var num = jsMath.Box.Set(mitem.num,Cn,size).Remeasured();      var num = jsMath.Box.Set(mitem.num,Cn,size).Remeasured();
     var den = jsMath.Box.Set(mitem.den,Cd,size).Remeasured();      var den = jsMath.Box.Set(mitem.den,Cd,size).Remeasured();
   
     var u; var v; var w;      var u; var v; var w; var p; var r;
     var H = (isD)? TeX.delim1 : TeX.delim2;      var H = (isD)? TeX.delim1 : TeX.delim2;
     var mlist = [jsMath.Box.Delimiter(H,mitem.left,style)]      var mlist = [jsMath.Box.Delimiter(H,mitem.left,style)]
     var right = jsMath.Box.Delimiter(H,mitem.right,style);      var right = jsMath.Box.Delimiter(H,mitem.right,style);
Line 3556  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3917  jsMath.Add(jsMath.mList.prototype.Atomiz
       v = TeX.denom2;        v = TeX.denom2;
     }      }
     if (t == 0) {// atop      if (t == 0) {// atop
       var p = (isD)? 7*TeX.default_rule_thickness: 3*TeX.default_rule_thickness;        p = (isD)? 7*TeX.default_rule_thickness: 3*TeX.default_rule_thickness;
       var r = (u - num.d) - (den.h - v);        r = (u - num.d) - (den.h - v);
       if (r < p) {u += (p-r)/2; v += (p-r)/2}        if (r < p) {u += (p-r)/2; v += (p-r)/2}
     } else {// over      } else {// over
       var p = (isD)? 3*t: t; var a = TeX.axis_height;        p = (isD)? 3*t: t; var a = TeX.axis_height;
       var r = (u-num.d)-(a+t/2); if (r < p) {u += p-r}        r = (u-num.d)-(a+t/2); if (r < p) {u += p-r}
           r = (a-t/2)-(den.h-v); if (r < p) {v += p-r}        r = (a-t/2)-(den.h-v); if (r < p) {v += p-r}
       var rule = jsMath.Box.Rule(w,t); rule.x = -w; rule.y = a - t/2;        var rule = jsMath.Box.Rule(w,t); rule.x = -w; rule.y = a - t/2;
       mlist[mlist.length] = rule;        mlist[mlist.length] = rule;
     }      }
Line 3801  jsMath.Package(jsMath.Typeset,{ Line 4162  jsMath.Package(jsMath.Typeset,{
    */     */
   Typeset: function (style,size) {    Typeset: function (style,size) {
     this.style = style; this.size = size; var unset = -10000      this.style = style; this.size = size; var unset = -10000
     this.w = 0; this.h = unset; this.d = unset;      this.w = 0; this.mw = 0; this.Mw = 0;
       this.h = unset; this.d = unset;
     this.bh = this.h; this.bd = this.d;      this.bh = this.h; this.bd = this.d;
     this.tbuf = ''; this.tx = 0; this.tclass = '';      this.tbuf = ''; this.tx = 0; this.tclass = '';
     this.cbuf = ''; this.hbuf = ''; this.hx = 0;      this.cbuf = ''; this.hbuf = ''; this.hx = 0;
Line 3844  jsMath.Package(jsMath.Typeset,{ Line 4206  jsMath.Package(jsMath.Typeset,{
         default:   // atom          default:   // atom
           if (!mitem.atom && mitem.type != 'box') break;            if (!mitem.atom && mitem.type != 'box') break;
           mitem.nuc.x += this.dx + this.GetSeparation(prev,mitem,this.style);            mitem.nuc.x += this.dx + this.GetSeparation(prev,mitem,this.style);
           if (mitem.nuc.y || mitem.nuc.x) mitem.nuc.Styled();            if (mitem.nuc.x || mitem.nuc.y) mitem.nuc.Styled();
           this.dx = 0; this.x = this.x + this.w;            this.dx = 0; this.x = this.x + this.w;
             if (this.x + mitem.nuc.x + mitem.nuc.mw < this.mw) 
               {this.mw = this.x + mitem.nuc.x + mitem.nuc.mw}
             if (this.w + mitem.nuc.x + mitem.nuc.Mw > this.Mw)
               {this.Mw = this.w + mitem.nuc.x + mitem.nuc.Mw}
           this.w += mitem.nuc.w + mitem.nuc.x;            this.w += mitem.nuc.w + mitem.nuc.x;
           if (mitem.nuc.format == 'text') {            if (mitem.nuc.format == 'text') {
             if (this.tclass != mitem.nuc.tclass && this.tclass != '') this.FlushText();              if (this.tclass != mitem.nuc.tclass && this.tclass != '') this.FlushText();
Line 3862  jsMath.Package(jsMath.Typeset,{ Line 4228  jsMath.Package(jsMath.Typeset,{
           break;            break;
       }        }
     }      }
       
     this.FlushClassed(); // make sure scaling is included      this.FlushClassed(); // make sure scaling is included
     if (this.dx) {this.hbuf += jsMath.HTML.Spacer(this.dx); this.w += this.dx}      if (this.dx) {
     if (this.hbuf == '') {return jsMath.Box.Null}        this.hbuf += jsMath.HTML.Spacer(this.dx); this.w += this.dx;
         if (this.w > this.Mw) {this.Mw = this.w}
         if (this.w < this.mw) {this.mw = this.w}
       }
       if (this.hbuf == '') {return jsMath.Box.Null()}
     if (this.h == unset) {this.h = 0}      if (this.h == unset) {this.h = 0}
     if (this.d == unset) {this.d = 0}      if (this.d == unset) {this.d = 0}
     var box = new jsMath.Box('html',this.hbuf,this.w,this.h,this.d);      var box = new jsMath.Box('html',this.hbuf,this.w,this.h,this.d);
     box.bh = this.bh; box.bd = this.bd;      box.bh = this.bh; box.bd = this.bd;
       box.mw = this.mw; box.Mw = this.Mw;
     return box;      return box;
   },    },
   
Line 3916  jsMath.Package(jsMath.Typeset,{ Line 4287  jsMath.Package(jsMath.Typeset,{
    *  also doesn't combine vertical and horizontal spacing well.     *  also doesn't combine vertical and horizontal spacing well.
    *  Here, the horizontal and vertical spacing are done separately.     *  Here, the horizontal and vertical spacing are done separately.
    */     */
   
   PlaceSeparateSkips: function (item) {    PlaceSeparateSkips: function (item) {
     if (item.y) {      if (item.y) {
       item.html = '<span style="position: relative; '        var rw = item.Mw - item.w; var lw = item.mw;
                      + 'top:'+jsMath.HTML.Em(-item.y)+';'        var W = item.Mw - item.mw;
                      + '">' + item.html + '</span>'        item.html = 
           jsMath.HTML.Spacer(lw-rw) +
           '<span style="position: relative; '
               + 'top:'+jsMath.HTML.Em(-item.y)+';'
               + 'left:'+jsMath.HTML.Em(rw)+'; width:'+jsMath.HTML.Em(W)+';">' +
             jsMath.HTML.Spacer(-lw) +
             item.html +
             jsMath.HTML.Spacer(rw) + 
           '</span>'
     }      }
     if (item.x) {item.html = jsMath.HTML.Spacer(item.x) + item.html}      if (item.x) {item.html = jsMath.HTML.Spacer(item.x) + item.html}
     item.h += item.y; item.d -= item.y;      item.h += item.y; item.d -= item.y;
     item.x = 0; item.y = 0;      item.x = 0; item.y = 0;
   }    }
     
 });  });
   
   
Line 3960  jsMath.Package(jsMath.Parser,{ Line 4340  jsMath.Package(jsMath.Parser,{
   letter:  /[a-z]/i,    letter:  /[a-z]/i,
   number:  /[0-9]/,    number:  /[0-9]/,
   //  pattern for macros to ^ and _ that should be read with arguments    //  pattern for macros to ^ and _ that should be read with arguments
   scriptargs: /^((math|text)..|mathcal)$/,    scriptargs: /^((math|text)..|mathcal|[hm]box)$/,
       
   //  the \mathchar definitions (see Appendix B of the TeXbook).    //  the \mathchar definitions (see Appendix B of the TeXbook).
   mathchar: {    mathchar: {
Line 3998  jsMath.Package(jsMath.Parser,{ Line 4378  jsMath.Package(jsMath.Parser,{
     "\n":  'Space',      "\n":  'Space',
     "'":   'Prime',      "'":   'Prime',
     '%':   'HandleComment',      '%':   'HandleComment',
     '&':   'HandleEntry'      '&':   'HandleEntry',
       '#':   'Hash'
   },    },
   
   // the \mathchardef table (see Appendix B of the TeXbook).    // the \mathchardef table (see Appendix B of the TeXbook).
Line 4146  jsMath.Package(jsMath.Parser,{ Line 4527  jsMath.Package(jsMath.Parser,{
     le:          [3,2,0x14],      le:          [3,2,0x14],
     geq:         [3,2,0x15],      geq:         [3,2,0x15],
     ge:          [3,2,0x15],      ge:          [3,2,0x15],
       lt:          [3,1,0x3C],  // extra since < and > are hard
       gt:          [3,1,0x3E],  //   to get in HTML
     succ:        [3,2,0x1F],      succ:        [3,2,0x1F],
     prec:        [3,2,0x1E],      prec:        [3,2,0x1E],
     approx:      [3,2,0x19],      approx:      [3,2,0x19],
Line 4188  jsMath.Package(jsMath.Parser,{ Line 4571  jsMath.Package(jsMath.Parser,{
     nwarrow:          [3,2,0x2D],      nwarrow:          [3,2,0x2D],
     swarrow:          [3,2,0x2E],      swarrow:          [3,2,0x2E],
   
       minuschar:  [3,2,0x00], // for longmapsto
     hbarchar:   [0,0,0x16], // for \hbar      hbarchar:   [0,0,0x16], // for \hbar
     lhook:      [3,1,0x2C],      lhook:      [3,1,0x2C],
     rhook:      [3,1,0x2D],      rhook:      [3,1,0x2D],
Line 4210  jsMath.Package(jsMath.Parser,{ Line 4594  jsMath.Package(jsMath.Parser,{
     ']':                [0,0,0x5D,3,0x03],      ']':                [0,0,0x5D,3,0x03],
     '<':                [0,2,0x68,3,0x0A],      '<':                [0,2,0x68,3,0x0A],
     '>':                [0,2,0x69,3,0x0B],      '>':                [0,2,0x69,3,0x0B],
       '\\lt':             [0,2,0x68,3,0x0A],  // extra since < and > are
       '\\gt':             [0,2,0x69,3,0x0B],  //  hard to get in HTML
     '/':                [0,0,0x2F,3,0x0E],      '/':                [0,0,0x2F,3,0x0E],
     '|':                [0,2,0x6A,3,0x0C],      '|':                [0,2,0x6A,3,0x0C],
     '.':                [0,0,0x00,0,0x00],      '.':                [0,0,0x00,0,0x00],
Line 4273  jsMath.Package(jsMath.Parser,{ Line 4659  jsMath.Package(jsMath.Parser,{
     it:                ['HandleFont',4],      it:                ['HandleFont',4],
     bf:                ['HandleFont',6],      bf:                ['HandleFont',6],
           
       font:              ['Extension','font'],
       
     left:              'HandleLeft',      left:              'HandleLeft',
     right:             'HandleRight',      right:             'HandleRight',
   
Line 4325  jsMath.Package(jsMath.Parser,{ Line 4713  jsMath.Package(jsMath.Parser,{
     overbrace:       ['Extension','leaders'],      overbrace:       ['Extension','leaders'],
     underbrace:      ['Extension','leaders'],      underbrace:      ['Extension','leaders'],
     overrightarrow:  ['Extension','leaders'],      overrightarrow:  ['Extension','leaders'],
       underrightarrow: ['Extension','leaders'],
     overleftarrow:   ['Extension','leaders'],      overleftarrow:   ['Extension','leaders'],
       underleftarrow:  ['Extension','leaders'],
       overleftrightarrow:  ['Extension','leaders'],
       underleftrightarrow: ['Extension','leaders'],
     overset:         ['Extension','underset-overset'],      overset:         ['Extension','underset-overset'],
     underset:        ['Extension','underset-overset'],      underset:        ['Extension','underset-overset'],
   
Line 4362  jsMath.Package(jsMath.Parser,{ Line 4754  jsMath.Package(jsMath.Parser,{
     Relbar:             ['Macro','\\mathrel='],      Relbar:             ['Macro','\\mathrel='],
     bowtie:             ['Macro','\\mathrel\\triangleright\\joinrel\\mathrel\\triangleleft'],      bowtie:             ['Macro','\\mathrel\\triangleright\\joinrel\\mathrel\\triangleleft'],
     models:             ['Macro','\\mathrel|\\joinrel='],      models:             ['Macro','\\mathrel|\\joinrel='],
     mapsto:             ['Macro','\\mapstochar\\rightarrow'],      mapsto:             ['Macro','\\mathrel{\\mapstochar\\rightarrow}'],
     rightleftharpoons:  ['Macro','\\vcenter{\\mathrel{\\rlap{\\raise3mu{\\rightharpoonup}}}\\leftharpoondown}'],      rightleftharpoons:  ['Macro','\\vcenter{\\mathrel{\\rlap{\\raise3mu{\\rightharpoonup}}}\\leftharpoondown}'],
     hookrightarrow:     ['Macro','\\lhook\\joinrel\\rightarrow'],      hookrightarrow:     ['Macro','\\lhook\\joinrel\\rightarrow'],
     hookleftarrow:      ['Macro','\\leftarrow\\joinrel\\rhook'],      hookleftarrow:      ['Macro','\\leftarrow\\joinrel\\rhook'],
Line 4370  jsMath.Package(jsMath.Parser,{ Line 4762  jsMath.Package(jsMath.Parser,{
     longrightarrow:     ['Macro','\\relbar\\joinrel\\rightarrow'],      longrightarrow:     ['Macro','\\relbar\\joinrel\\rightarrow'],
     longleftarrow:      ['Macro','\\leftarrow\\joinrel\\relbar'],      longleftarrow:      ['Macro','\\leftarrow\\joinrel\\relbar'],
     Longleftarrow:      ['Macro','\\Leftarrow\\joinrel\\Relbar'],      Longleftarrow:      ['Macro','\\Leftarrow\\joinrel\\Relbar'],
     longmapsto:         ['Macro','\\mapstochar\\char{cmsy10}{0}\\joinrel\\rightarrow'],      longmapsto:         ['Macro','\\mathrel{\\mapstochar\\minuschar\\joinrel\\rightarrow}'],
     longleftrightarrow: ['Macro','\\leftarrow\\joinrel\\rightarrow'],      longleftrightarrow: ['Macro','\\leftarrow\\joinrel\\rightarrow'],
     Longleftrightarrow: ['Macro','\\Leftarrow\\joinrel\\Rightarrow'],      Longleftrightarrow: ['Macro','\\Leftarrow\\joinrel\\Rightarrow'],
     iff:                ['Macro','\\;\\Longleftrightarrow\\;'],      iff:                ['Macro','\\;\\Longleftrightarrow\\;'],
Line 4382  jsMath.Package(jsMath.Parser,{ Line 4774  jsMath.Package(jsMath.Parser,{
     textrm:             ['Macro','\\mathord{\\hbox{#1}}',1],      textrm:             ['Macro','\\mathord{\\hbox{#1}}',1],
     textit:             ['Macro','\\mathord{\\class{textit}{\\hbox{#1}}}',1],      textit:             ['Macro','\\mathord{\\class{textit}{\\hbox{#1}}}',1],
     textbf:             ['Macro','\\mathord{\\class{textbf}{\\hbox{#1}}}',1],      textbf:             ['Macro','\\mathord{\\class{textbf}{\\hbox{#1}}}',1],
       pmb:                ['Macro','\\rlap{#1}\\kern1px{#1}',1],
   
     TeX:                ['Macro','T\\kern-.1667em\\lower.5ex{E}\\kern-.125em X'],      TeX:                ['Macro','T\\kern-.1667em\\lower.5ex{E}\\kern-.125em X'],
   
Line 4465  jsMath.Package(jsMath.Parser,{ Line 4858  jsMath.Package(jsMath.Parser,{
     matrix:     'Matrix',      matrix:     'Matrix',
     array:      'Matrix',  // ### still need to do alignment options ###      array:      'Matrix',  // ### still need to do alignment options ###
     pmatrix:    ['Matrix','(',')','c'],      pmatrix:    ['Matrix','(',')','c'],
     cases:      ['Matrix','\\{','.',['l','l']],      cases:      ['Matrix','\\{','.',['l','l'],null,2],
       eqalign:    ['Matrix',null,null,['r','l'],[5/18],3,'D'],
       displaylines: ['Matrix',null,null,['c'],null,3,'D'],
     cr:         'HandleRow',      cr:         'HandleRow',
     '\\':       'HandleRow',      '\\':       'HandleRow',
       newline:    'HandleRow',
       noalign:    'HandleNoAlign',
       eqalignno:  ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'],
       leqalignno: ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'],
           
     //  LaTeX      //  LaTeX
     begin:      'Begin',      begin:      'Begin',
Line 4484  jsMath.Package(jsMath.Parser,{ Line 4883  jsMath.Package(jsMath.Parser,{
     Huge:       ['HandleSize',9],      Huge:       ['HandleSize',9],
     dots:       ['Macro','\\ldots'],      dots:       ['Macro','\\ldots'],
           
     newcommand: ['Extension','newcommand'],      newcommand:     ['Extension','newcommand'],
     def:        ['Extension','newcommand'],      newenvironment: ['Extension','newcommand'],
       def:            ['Extension','newcommand'],
   
     //  Extensions to TeX      //  Extensions to TeX
     color:      ['Extension','HTML'],      color:      ['Extension','HTML'],
Line 4494  jsMath.Package(jsMath.Parser,{ Line 4894  jsMath.Package(jsMath.Parser,{
     style:      ['Extension','HTML'],      style:      ['Extension','HTML'],
     cssId:      ['Extension','HTML'],      cssId:      ['Extension','HTML'],
     unicode:    ['Extension','HTML'],      unicode:    ['Extension','HTML'],
       bbox:       ['Extension','bbox'],
           
     require:    'Require',      require:    'Require',
           
Line 4505  jsMath.Package(jsMath.Parser,{ Line 4906  jsMath.Package(jsMath.Parser,{
    *  LaTeX environments     *  LaTeX environments
    */     */
   environments: {    environments: {
     array:      'Array',      array:        'Array',
     matrix:     ['Array',null,null,'c'],      matrix:       ['Array',null,null,'c'],
     pmatrix:    ['Array','(',')','c'],      pmatrix:      ['Array','(',')','c'],
     bmatrix:    ['Array','[',']','c'],      bmatrix:      ['Array','[',']','c'],
     Bmatrix:    ['Array','\\{','\\}','c'],      Bmatrix:      ['Array','\\{','\\}','c'],
     vmatrix:    ['Array','\\vert','\\vert','c'],      vmatrix:      ['Array','\\vert','\\vert','c'],
     Vmatrix:    ['Array','\\Vert','\\Vert','c'],      Vmatrix:      ['Array','\\Vert','\\Vert','c'],
     cases:      ['Array','\\{','.','ll'],      cases:        ['Array','\\{','.','ll',null,2],
     eqnarray:   ['Array',null,null,'rcl',[5/18,5/18],'D']      eqnarray:     ['Array',null,null,'rcl',[5/18,5/18],3,'D'],
   
       align:        ['Extension','AMSmath'],
       'align*':     ['Extension','AMSmath'],
       multline:     ['Extension','AMSmath'],
       'multline*':  ['Extension','AMSmath'],
       split:        ['Extension','AMSmath'],
       gather:       ['Extension','AMSmath'],
       'gather*':    ['Extension','AMSmath']
   },    },
   
   
Line 4581  jsMath.Package(jsMath.Parser,{ Line 4990  jsMath.Package(jsMath.Parser,{
     var letter = /^([a-z]+|.) ?/i;      var letter = /^([a-z]+|.) ?/i;
     var cmd = letter.exec(this.string.slice(this.i));      var cmd = letter.exec(this.string.slice(this.i));
     if (cmd) {this.i += cmd[1].length; return cmd[1]}      if (cmd) {this.i += cmd[1].length; return cmd[1]}
     this.Error("Missing control sequnece name at end of string or argument");      this.i++; return " ";
     return null;  
   },    },
   
   /*    /*
Line 4627  jsMath.Package(jsMath.Parser,{ Line 5035  jsMath.Package(jsMath.Parser,{
   ProcessScriptArg: function (name) {    ProcessScriptArg: function (name) {
     var arg = this.GetArgument(name); if (this.error) {return null}      var arg = this.GetArgument(name); if (this.error) {return null}
     if (arg.charAt(0) == this.cmd) {      if (arg.charAt(0) == this.cmd) {
       csname = arg.substr(1);        var csname = arg.substr(1);
       if (csname == "frac") {        if (csname == "frac") {
         arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null}          arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null}
         arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null}          arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null}
Line 4670  jsMath.Package(jsMath.Parser,{ Line 5078  jsMath.Package(jsMath.Parser,{
       rest = this.string.slice(this.i);        rest = this.string.slice(this.i);
       advance = 1;        advance = 1;
     }      }
     var match = rest.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/);      return this.ParseDimen(rest,name,advance,nomu);
     },
     
     ParseDimen: function (dimen,name,advance,nomu) {
       var match = dimen.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/);
     if (!match) {this.Error("Missing dimension or its units for "+name); return null}      if (!match) {this.Error("Missing dimension or its units for "+name); return null}
     if (advance) {      if (advance) {
       this.i += match[0].length;        this.i += match[0].length;
Line 4699  jsMath.Package(jsMath.Parser,{ Line 5111  jsMath.Package(jsMath.Parser,{
     var c = this.GetNext(); if (c != '[') return '';      var c = this.GetNext(); if (c != '[') return '';
     var start = ++this.i; var pcount = 0;      var start = ++this.i; var pcount = 0;
     while (this.i < this.string.length) {      while (this.i < this.string.length) {
       var c = this.string.charAt(this.i++);        c = this.string.charAt(this.i++);
       if (c == '{') {pcount++}        if (c == '{') {pcount++}
       else if (c == '}') {        else if (c == '}') {
         if (pcount == 0)          if (pcount == 0)
Line 4803  jsMath.Package(jsMath.Parser,{ Line 5215  jsMath.Package(jsMath.Parser,{
    */     */
   RaiseLower: function (name) {    RaiseLower: function (name) {
     var h = this.GetDimen(this.cmd+name,1); if (this.error) return;      var h = this.GetDimen(this.cmd+name,1); if (this.error) return;
     var box = this.ProcessArg(this.cmd+name); if (this.error) return;      var box = this.ProcessScriptArg(this.cmd+name); if (this.error) return;
     if (name == 'lower') {h = -h}      if (name == 'lower') {h = -h}
     this.mlist.Add(new jsMath.mItem('raise',{nuc: box, raise: h}));      this.mlist.Add(new jsMath.mItem('raise',{nuc: box, raise: h}));
   },    },
Line 4838  jsMath.Package(jsMath.Parser,{ Line 5250  jsMath.Package(jsMath.Parser,{
   Extension: function (name,data) {    Extension: function (name,data) {
     jsMath.Translate.restart = 1;      jsMath.Translate.restart = 1;
     if (name != null) {delete jsMath.Parser.prototype[data[1]||'macros'][name]}      if (name != null) {delete jsMath.Parser.prototype[data[1]||'macros'][name]}
     jsMath.Script.Start();  
     jsMath.Extension.Require(data[0],jsMath.Translate.asynchronous);      jsMath.Extension.Require(data[0],jsMath.Translate.asynchronous);
     throw "restart";      throw "restart";
   },    },
Line 4858  jsMath.Package(jsMath.Parser,{ Line 5269  jsMath.Package(jsMath.Parser,{
   Sqrt: function (name) {    Sqrt: function (name) {
     var n = this.GetBrackets(this.cmd+name); if (this.error) return;      var n = this.GetBrackets(this.cmd+name); if (this.error) return;
     var arg = this.ProcessArg(this.cmd+name); if (this.error) return;      var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
     box = jsMath.mItem.Atom('radical',arg);      var box = jsMath.mItem.Atom('radical',arg);
     if (this.n != '') {box.root = this.Process(n); if (this.error) return}      if (n != '') {box.root = this.Process(n); if (this.error) return}
     this.mlist.Add(box);      this.mlist.Add(box);
   },    },
   
Line 4869  jsMath.Package(jsMath.Parser,{ Line 5280  jsMath.Package(jsMath.Parser,{
   Root: function (name) {    Root: function (name) {
     var n = this.ProcessUpto(this.cmd+name,'of'); if (this.error) return;      var n = this.ProcessUpto(this.cmd+name,'of'); if (this.error) return;
     var arg = this.ProcessArg(this.cmd+name); if (this.error) return;      var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
     box = jsMath.mItem.Atom('radical',arg);      var box = jsMath.mItem.Atom('radical',arg);
     box.root = n; this.mlist.Add(box);      box.root = n; this.mlist.Add(box);
   },    },
       
Line 4915  jsMath.Package(jsMath.Parser,{ Line 5326  jsMath.Package(jsMath.Parser,{
   Matrix: function (name,delim) {    Matrix: function (name,delim) {
     var data = this.mlist.data;      var data = this.mlist.data;
     var arg = this.GetArgument(this.cmd+name); if (this.error) return;      var arg = this.GetArgument(this.cmd+name); if (this.error) return;
     var parse = new jsMath.Parser(arg+'\\\\',null,data.size);      var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,delim[5] || 'T');
     parse.matrix = name; parse.row = []; parse.table = [];      parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = [];
     parse.Parse(); if (parse.error) {this.Error(parse); return}      parse.Parse(); if (parse.error) {this.Error(parse); return}
     parse.HandleRow(name,1);  // be sure the last row is recorded      parse.HandleRow(name,1);  // be sure the last row is recorded
     var box = jsMath.Box.Layout(data.size,parse.table,delim[2]);      var box = jsMath.Box.Layout(data.size,parse.table,delim[2]||null,delim[3]||null,parse.rspacing,delim[4]||null);
     // Add parentheses, if needed      // Add parentheses, if needed
     if (delim[0] && delim[1]) {      if (delim[0] && delim[1]) {
       var left  = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[0]],'T');        var left  = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T');
       var right = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[1]],'T');        var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T');
       box = jsMath.Box.SetList([left,box,right],data.style,data.size);        box = jsMath.Box.SetList([left,box,right],data.style,data.size);
     }      }
     this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));      this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));
Line 4945  jsMath.Package(jsMath.Parser,{ Line 5356  jsMath.Package(jsMath.Parser,{
     var data = this.mlist.data;      var data = this.mlist.data;
     this.mlist.Atomize(data.style,data.size);      this.mlist.Atomize(data.style,data.size);
     var box = this.mlist.Typeset(data.style,data.size);      var box = this.mlist.Typeset(data.style,data.size);
       box.entry = data.entry; delete data.entry; if (!box.entry) {box.entry = {}};
     this.row[this.row.length] = box;      this.row[this.row.length] = box;
     this.mlist = new jsMath.mList(null,null,data.size,data.style);       this.mlist = new jsMath.mList(null,null,data.size,data.style); 
   },    },
Line 4953  jsMath.Package(jsMath.Parser,{ Line 5365  jsMath.Package(jsMath.Parser,{
    *  When we see a \cr or \\, try to add a row to the table     *  When we see a \cr or \\, try to add a row to the table
    */     */
   HandleRow: function (name,last) {    HandleRow: function (name,last) {
     if (!this.matrix)      var dimen;
       {this.Error(this.cmd+name+" can only appear in a matrix or array"); return}      if (!this.matrix) {this.Error(this.cmd+name+" can only appear in a matrix or array"); return}
       if (name == "\\") {
         dimen = this.GetBrackets(this.cmd+name); if (this.error) return;
         if (dimen) {dimen = this.ParseDimen(dimen,this.cmd+name,0,1)}
       }
     this.HandleEntry(name);      this.HandleEntry(name);
     if (!last || this.row.length > 1 || this.row[0].format != 'null')      if (!last || this.row.length > 1 || this.row[0].format != 'null')
       {this.table[this.table.length] = this.row}        {this.table[this.table.length] = this.row}
       if (dimen) {this.rspacing[this.table.length] = dimen}
     this.row = [];      this.row = [];
   },    },
       
   /*    /*
      *  Look for \vskip or \vspace in \noalign parameters
      */
     HandleNoAlign: function (name) {
       var arg = this.GetArgument(this.cmd+name); if (this.error) return;
       var skip = arg.replace(/^.*(vskip|vspace)([^a-z])/i,'$2');
       if (skip.length == arg.length) return;
       var d = this.ParseDimen(skip,this.cmd+RegExp.$1,0,1); if (this.error) return;
       this.rspacing[this.table.length] = (this.rspacing[this.table.length] || 0) + d;
     },
     
     /*
    *  LaTeX array environment     *  LaTeX array environment
    */     */
   Array: function (name,delim) {    Array: function (name,delim) {
Line 4972  jsMath.Package(jsMath.Parser,{ Line 5400  jsMath.Package(jsMath.Parser,{
     }      }
     columns = columns.replace(/[^clr]/g,'');      columns = columns.replace(/[^clr]/g,'');
     columns = columns.split('');      columns = columns.split('');
     var data = this.mlist.data; var style = delim[4] || 'T';      var data = this.mlist.data; var style = delim[5] || 'T';
     var arg = this.GetEnd(name); if (this.error) return;      var arg = this.GetEnd(name); if (this.error) return;
     var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,style);      var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,style);
     parse.matrix = name; parse.row = []; parse.table = [];      parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = [];
     parse.Parse(); if (parse.error) {this.Error(parse); return}      parse.Parse(); if (parse.error) {this.Error(parse); return}
     parse.HandleRow(name,1);  // be sure the last row is recorded      parse.HandleRow(name,1);  // be sure the last row is recorded
     var box = jsMath.Box.Layout(data.size,parse.table,columns,cspacing);      var box = jsMath.Box.Layout(data.size,parse.table,columns,cspacing,parse.rspacing,delim[4],delim[6],delim[7]);
     // Add parentheses, if needed      // Add parentheses, if needed
     if (delim[0] && delim[1]) {      if (delim[0] && delim[1]) {
       var left  = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[0]],'T');        var left  = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T');
       var right = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[1]],'T');        var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T');
       box = jsMath.Box.SetList([left,box,right],data.style,data.size);        box = jsMath.Box.SetList([left,box,right],data.style,data.size);
     }      }
     this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));      this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));
Line 5058  jsMath.Package(jsMath.Parser,{ Line 5486  jsMath.Package(jsMath.Parser,{
   Strut: function () {    Strut: function () {
     var size = this.mlist.data.size;      var size = this.mlist.data.size;
     var box = jsMath.Box.Text('','normal','T',size).Styled();      var box = jsMath.Box.Text('','normal','T',size).Styled();
     box.bh = box.bd = 0; box.h = .8; box.d = .3; box.w = 0;      box.bh = box.bd = 0; box.h = .8; box.d = .3; box.w = box.Mw = 0;
     this.mlist.Add(jsMath.mItem.Typeset(box));      this.mlist.Add(jsMath.mItem.Typeset(box));
   },    },
       
Line 5144  jsMath.Package(jsMath.Parser,{ Line 5572  jsMath.Package(jsMath.Parser,{
         c = string.charAt(i++);          c = string.charAt(i++);
         if (c == "#") {text += c} else {          if (c == "#") {text += c} else {
           if (!c.match(/[1-9]/) || c > args.length)            if (!c.match(/[1-9]/) || c > args.length)
             {this.Error("Illegal macro parameter reference"); return}              {this.Error("Illegal macro parameter reference"); return null}
           newstring = this.AddArgs(this.AddArgs(newstring,text),args[c-1]);            newstring = this.AddArgs(this.AddArgs(newstring,text),args[c-1]);
           text = '';            text = '';
         }          }
Line 5170  jsMath.Package(jsMath.Parser,{ Line 5598  jsMath.Package(jsMath.Parser,{
   },    },
       
   /*    /*
      *  Error for # (must use \#)
      */
     Hash: function (name) {
       this.Error("You can't use 'macro parameter character #' in math mode");
     },
     
     /*
    *  Insert space for ~     *  Insert space for ~
    */     */
   Tilde: function (name) {    Tilde: function (name) {
Line 5190  jsMath.Package(jsMath.Parser,{ Line 5625  jsMath.Package(jsMath.Parser,{
    */     */
   HandleAtom: function (name,data) {    HandleAtom: function (name,data) {
     var arg = this.ProcessArg(this.cmd+name); if (this.error) return;      var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
     this.mlist.Add(jsMath.mItem.Atom(data,arg));      this.mlist.Add(jsMath.mItem.Atom(data[0],arg));
   },    },
   
   
Line 5336  jsMath.Package(jsMath.Parser,{ Line 5771  jsMath.Package(jsMath.Parser,{
       this.mlist.data.overF.right = null;        this.mlist.data.overF.right = null;
     }      }
     if (name.match(/^above/)) {      if (name.match(/^above/)) {
       this.mlist.data.overF.thickness = this.GetDimen(this.cmd.name,1);        this.mlist.data.overF.thickness = this.GetDimen(this.cmd+name,1);
       if (this.error) return;        if (this.error) return;
     } else {      } else {
       this.mlist.data.overF.thickness = null;         this.mlist.data.overF.thickness = null; 
Line 5348  jsMath.Package(jsMath.Parser,{ Line 5783  jsMath.Package(jsMath.Parser,{
    */     */
   HandleSuperscript: function () {    HandleSuperscript: function () {
     var base = this.mlist.Last();      var base = this.mlist.Last();
       if (this.mlist.data.overI == this.mlist.Length()) {base = null}
     if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))      if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))
        {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))}         {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))}
     if (base.sup) {      if (base.sup) {
Line 5362  jsMath.Package(jsMath.Parser,{ Line 5798  jsMath.Package(jsMath.Parser,{
    */     */
   HandleSubscript: function () {    HandleSubscript: function () {
     var base = this.mlist.Last();      var base = this.mlist.Last();
       if (this.mlist.data.overI == this.mlist.Length()) {base = null}
     if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))      if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))
        {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))}         {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))}
     if (base.sub) {this.Error("Double subscripts: use braces to clarify"); return}      if (base.sub) {this.Error("Double subscripts: use braces to clarify"); return}
Line 5422  jsMath.Package(jsMath.Parser,{ Line 5859  jsMath.Package(jsMath.Parser,{
       if (jsMath.Browser.allowAbsolute) {        if (jsMath.Browser.allowAbsolute) {
         var y = 0;          var y = 0;
         if (box.bh > jsMath.h+.001) {y = jsMath.h - box.bh}          if (box.bh > jsMath.h+.001) {y = jsMath.h - box.bh}
           if (jsMath.Browser.msieTeXfontBaselineBug &&
               jsMath.Controls.cookie.font == 'tex') {y -= jsMath.d}
         html = jsMath.HTML.Absolute(html,box.w,jsMath.h,0,y,jsMath.h);          html = jsMath.HTML.Absolute(html,box.w,jsMath.h,0,y,jsMath.h);
       } else if (!jsMath.Browser.valignBug) {        } else if (jsMath.Browser.valignBug) {
           // remove line height
           html = '<span style="line-height:'+jsMath.HTML.Em(jsMath.d)+';">'
                +    html + '</span>';
         } else {
         // remove line height and try to hide the depth          // remove line height and try to hide the depth
         var dy = jsMath.HTML.Em(Math.max(0,box.bd-jsMath.hd)/3);          var dy = jsMath.HTML.Em(Math.max(0,box.bd-jsMath.hd)/3);
         html = '<span style="line-height: 0px;'          html = '<span style="line-height:'+jsMath.HTML.Em(jsMath.d)+';'
                + ' position:relative; top:'+dy+'; vertical-align:'+dy                 + ' position:relative; top:'+dy+'; vertical-align:'+dy
                + '">' + html + '</span>';                 + '">' + html + '</span>';
       }        }
Line 5574  jsMath.Translate = { Line 6017  jsMath.Translate = {
   
   element: [],  // the list of math elements on the page    element: [],  // the list of math elements on the page
   cancel: 0,    // set to 1 to cancel asynchronous processing    cancel: 0,    // set to 1 to cancel asynchronous processing
     
   /*    /*
    *  Typeset a string in \textstyle and return the HTML for it     *  Parse a TeX string in Text or Display mode and return
      *  the HTML for it (taking it from the cache, if available)
    */     */
   TextMode: function (s) {    Parse: function (style,s,noCache) {
     var parse = jsMath.Parse(s,null,null,'T');      var cache = jsMath.Global.cache[style];
     parse.Atomize();      if (!cache[jsMath.em]) {cache[jsMath.em] = {}}
     var html = parse.Typeset();      var HTML = cache[jsMath.em][s];
     return html;      if (!HTML || noCache) {
         var parse = jsMath.Parse(s,null,null,style);
         parse.Atomize(); HTML = parse.Typeset();
         if (!noCache) {cache[jsMath.em][s] = HTML}
       }
       return HTML;
   },    },
   
   /*    TextMode:    function (s,noCache) {this.Parse('T',s,noCache)},
    *  Typeset a string in \displaystyle and return the HTML for it    DisplayMode: function (s,noCache) {this.Parse('D',s,noCache)},
    */  
   DisplayMode: function (s) {  
     var parse = jsMath.Parse(s,null,null,'D');  
     parse.Atomize();  
     var html = parse.Typeset();  
     return html;  
   },  
       
   /*    /*
    *  Return the text of a given DOM element     *  Return the text of a given DOM element
Line 5624  jsMath.Translate = { Line 6066  jsMath.Translate = {
    */     */
   ResetHidden: function (element) {    ResetHidden: function (element) {
     element.innerHTML =      element.innerHTML =
       '<span style="visibility: hidden; position:absolute; top:0px;left:0px;"></span>'        '<span class="jsMath_hiddenSpan" style="position:absolute"></span>'
         + jsMath.Browser.operaHiddenFix; // needed by Opera in tables          + jsMath.Browser.operaHiddenFix; // needed by Opera in tables
     element.className='';      element.className = '';
     jsMath.hidden = element.firstChild;      jsMath.hidden = element.firstChild;
     if (!jsMath.BBoxFor("x").w) {jsMath.hidden = jsMath.hiddenTop}      if (!jsMath.BBoxFor("x").w) {jsMath.hidden = jsMath.hiddenTop}
     jsMath.ReInit();      jsMath.ReInit();
Line 5636  jsMath.Translate = { Line 6078  jsMath.Translate = {
   /*    /*
    *  Typeset the contents of an element in \textstyle     *  Typeset the contents of an element in \textstyle
    */     */
   ConvertText: function (element) {    ConvertText: function (element,noCache) {
     var text = this.GetElementText(element);      var text = this.GetElementText(element);
     this.ResetHidden(element);      this.ResetHidden(element);
     text = this.TextMode(text);      if (text.match(/^\s*\\nocache([^a-zA-Z])/))
         {noCache = true; text = text.replace(/\s*\\nocache/,'')}
       text = this.Parse('T',text,noCache);
     element.className = 'typeset';      element.className = 'typeset';
     element.innerHTML = text;      element.innerHTML = text;
   },    },
Line 5647  jsMath.Translate = { Line 6091  jsMath.Translate = {
   /*    /*
    *  Typeset the contents of an element in \displaystyle     *  Typeset the contents of an element in \displaystyle
    */     */
   ConvertDisplay: function (element) {    ConvertDisplay: function (element,noCache) {
     var text = this.GetElementText(element);      var text = this.GetElementText(element);
     this.ResetHidden(element);      this.ResetHidden(element);
     text = this.DisplayMode(text);      if (text.match(/^\s*\\nocache([^a-zA-Z])/))
         {noCache = true; text = text.replace(/\s*\\nocache/,'')}
       text = this.Parse('D',text,noCache);
     element.className = 'typeset';      element.className = 'typeset';
     element.innerHTML = text;      element.innerHTML = text;
   },    },
Line 5660  jsMath.Translate = { Line 6106  jsMath.Translate = {
    */     */
   ProcessElement: function (element) {    ProcessElement: function (element) {
     this.restart = 0;      this.restart = 0;
       if (!element.className.match(/(^| )math( |$)/)) return; // don't reprocess elements
       var noCache = (element.className.toLowerCase().match(/(^| )nocache( |$)/) != null);
     try {      try {
       if (element.tagName.toLowerCase() == 'div') {        if (element.tagName.toLowerCase() == 'div') {
         this.ConvertDisplay(element);          this.ConvertDisplay(element,noCache);
         element.onclick = jsMath.Click.CheckClick;          element.onclick = jsMath.Click.CheckClick;
         element.ondblclick = jsMath.Click.CheckDblClick;          element.ondblclick = jsMath.Click.CheckDblClick;
       } else if (element.tagName.toLowerCase() == 'span') {        } else if (element.tagName.toLowerCase() == 'span') {
         this.ConvertText(element);          this.ConvertText(element,noCache);
         element.onclick = jsMath.Click.CheckClick;          element.onclick = jsMath.Click.CheckClick;
         element.ondblclick = jsMath.Click.CheckDblClick;          element.ondblclick = jsMath.Click.CheckDblClick;
       }        }
Line 5677  jsMath.Translate = { Line 6125  jsMath.Translate = {
         tex = tex.replace(/</g,'&lt;');          tex = tex.replace(/</g,'&lt;');
         tex = tex.replace(/>/g,'&gt;');          tex = tex.replace(/>/g,'&gt;');
         element.innerHTML = tex;          element.innerHTML = tex;
           element.className = 'math';
           if (noCache) {element.className += ' nocache'}
       }        }
       jsMath.hidden = jsMath.hiddenTop;        jsMath.hidden = jsMath.hiddenTop;
     }      }
Line 5697  jsMath.Translate = { Line 6147  jsMath.Translate = {
       jsMath.Script.blocking = 0;        jsMath.Script.blocking = 0;
       jsMath.Script.Process();        jsMath.Script.Process();
     } else {      } else {
         var savedQueue = jsMath.Script.SaveQueue();
       this.ProcessElement(this.element[k]);        this.ProcessElement(this.element[k]);
         jsMath.Script.RestoreQueue(savedQueue);
       if (this.restart) {        if (this.restart) {
         jsMath.Script.Push(this,'ProcessElements',k);          jsMath.Script.Push(this,'ProcessElements',k);
         jsMath.Script.blocking = 0;          jsMath.Script.blocking = 0;
Line 5716  jsMath.Translate = { Line 6168  jsMath.Translate = {
   Asynchronous: function (obj) {    Asynchronous: function (obj) {
     if (!jsMath.initialized) {jsMath.Init()}      if (!jsMath.initialized) {jsMath.Init()}
     this.element = this.GetMathElements(obj);      this.element = this.GetMathElements(obj);
     this.cancel = 0; this.asynchronous = 1;  
     jsMath.Script.blocking = 1;      jsMath.Script.blocking = 1;
       this.cancel = 0; this.asynchronous = 1;
     jsMath.Message.Set('Processing Math: 0%',1);      jsMath.Message.Set('Processing Math: 0%',1);
     setTimeout('jsMath.Translate.ProcessElements(0)',jsMath.Browser.delay);      setTimeout('jsMath.Translate.ProcessElements(0)',jsMath.Browser.delay);
   },    },
Line 5749  jsMath.Translate = { Line 6201  jsMath.Translate = {
    *  put them in a list sorted from top to bottom of the page     *  put them in a list sorted from top to bottom of the page
    */     */
   GetMathElements: function (obj) {    GetMathElements: function (obj) {
     var element = [];      var element = []; var k;
     if (!obj) {obj = jsMath.document}      if (!obj) {obj = jsMath.document}
     if (typeof(obj) == 'string') {obj = jsMath.document.getElementById(obj)}      if (typeof(obj) == 'string') {obj = jsMath.document.getElementById(obj)}
     if (!obj.getElementsByTagName) return null;      if (!obj.getElementsByTagName) return null;
     var math = obj.getElementsByTagName('div');      var math = obj.getElementsByTagName('div');
     for (var k = 0; k < math.length; k++) {      for (k = 0; k < math.length; k++) {
       if (math[k].className == 'math') {        if (math[k].className && math[k].className.match(/(^| )math( |$)/)) {
         if (jsMath.Browser.renameOK && obj.getElementsByName)           if (jsMath.Browser.renameOK && obj.getElementsByName) 
                {math[k].setAttribute('name','_jsMath_')}                 {math[k].setAttribute('name','_jsMath_')}
           else {element[element.length] = math[k]}            else {element[element.length] = math[k]}
       }        }
     }      }
     math = obj.getElementsByTagName('span');      math = obj.getElementsByTagName('span');
     for (var k = 0; k < math.length; k++) {      for (k = 0; k < math.length; k++) {
       if (math[k].className == 'math') {        if (math[k].className && math[k].className.match(/(^| )math( |$)/)) {
         if (jsMath.Browser.renameOK && obj.getElementsByName)           if (jsMath.Browser.renameOK && obj.getElementsByName) 
                {math[k].setAttribute('name','_jsMath_')}                 {math[k].setAttribute('name','_jsMath_')}
           else {element[element.length] = math[k]}            else {element[element.length] = math[k]}
Line 5790  jsMath.Translate = { Line 6242  jsMath.Translate = {
       }        }
     }      }
     jsMath.hidden = jsMath.hiddenTop;      jsMath.hidden = jsMath.hiddenTop;
     this.element = [];      this.element = []; this.restart = null;
     if (!noMessage) {      if (!noMessage) {
       jsMath.Message.Set('Processing Math: Done');        jsMath.Message.Set('Processing Math: Done');
       jsMath.Message.Clear();        jsMath.Message.Clear();
Line 5842  jsMath.Synchronize = jsMath.Script.Synch Line 6294  jsMath.Synchronize = jsMath.Script.Synch
   
 /***************************************************************************/  /***************************************************************************/
   
   
 /*  /*
  *  Initialize things   *  Initialize things
  */   */
 if (window.parent != window) {  try {
   window.parent.jsMath = jsMath;    if (window.parent != window && window.jsMathAutoload) {
   jsMath.document = window.parent.document;      window.parent.jsMath = jsMath;
   jsMath.window = window.parent;      jsMath.document = window.parent.document;
 }      jsMath.window = window.parent;
     }
   } catch (err) {}
   
   jsMath.Global.Register();
 jsMath.Loaded();  jsMath.Loaded();
 jsMath.Controls.GetCookie();  jsMath.Controls.GetCookie();
 jsMath.Setup.Source();  jsMath.Setup.Source();
   jsMath.Global.Init();
 jsMath.Script.Init();  jsMath.Script.Init();
 jsMath.Setup.Fonts();  jsMath.Setup.Fonts();
 if (jsMath.document.body) {jsMath.Setup.Body()}  if (jsMath.document.body) {jsMath.Setup.Body()}
   jsMath.Setup.User("onload");
   
 }}  }}

Removed from v.1.1  
changed lines
  Added in v.1.3


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