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

version 1.1, 2005/02/25 04:57:49 version 1.2, 2005/12/07 18:57:45
Line 2 Line 2
  *    * 
  *  jsMath: Mathematics on the Web   *  jsMath: Mathematics on the Web
  *     *  
  *  Version: 1.7e  
  *    
  *  This jsMath package makes it possible to display mathematics in HTML pages   *  This jsMath package makes it possible to display mathematics in HTML pages
  *  that are viewable by a wide range of browsers on both the Mac and the IBM PC,   *  that are viewable by a wide range of browsers on both the Mac and the IBM PC,
  *  including browsers that don't process MathML.  See   *  including browsers that don't process MathML.  See
Line 33 Line 31
 /*  /*
  *  Prevent running everything again if this file is loaded twice   *  Prevent running everything again if this file is loaded twice
  */   */
 if (!window.jsMath) {  if (!jsMath || !jsMath.loaded) {
   var jsMath_old = jsMath;  // save user customizations
   
 //  //
 // debugging routine  // debugging routine
Line 66  if (!document.getElementById || !documen Line 65  if (!document.getElementById || !documen
 /***************************************************************************/  /***************************************************************************/
   
 var jsMath = {  var jsMath = {
     
     version: "2.4b",  // change this if you edit the file
     
   //    //
   //  Name of image files    //  Name of image files
   //    //
   blank: "blank.gif",    blank: "blank.gif",
   black: "black.gif",  
     
   //  
   //  The TeX font parameters  
   //  
   TeX: {  
     thinmuskip:   3/18,  
     medmuskip:    4/18,  
     thickmuskip:  5/18,  
   
     x_height:    .430554,  
     quad:        1,  
     num1:        .676508,  
     num2:        .393732,  
     num3:        .44373,  
     denom1:      .685951,  
     denom2:      .344841,  
     sup1:        .412892,  
     sup2:        .362892,  
     sup3:        .288888,  
     sub1:        .15,  
     sub2:        .247217,  
     sup_drop:    .386108,  
     sub_drop:    .05,  
     delim1:     2.39,  
     delim2:     1.0,  
     axis_height: .25,  
     default_rule_thickness: .04,  
     big_op_spacing1:  .111111,  
     big_op_spacing2:  .166666,  
     big_op_spacing3:  .2,  
     big_op_spacing4:  .6,  
     big_op_spacing5:  .1,  
   
     integer:          6553.6,     // conversion of em's to TeX internal integer  
     scriptspace:         .05,  
     nulldelimiterspace:  .12,  
     delimiterfactor:     901,  
     delimitershortfall:   .5,  
     scale:                 1      //  scaling factor for font dimensions  
   },  
       
     defaultH: 0, // default height for characters with none specified
   
   // 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],
   
   allowAbsolute: 1,           // tells if browser can nest absolutely positioned  
                               //   SPANs inside relative SPANs  
   absoluteOffsetY: 0,         // vertical adjustment when absolute position is used  
   allowAbsoluteDelim: 0,      // OK to use absolute placement for building delims?  
   renameOK: 1,                // tells if brower will find a tag whose name  
                               //   has been set via setAttributes  
   separateNetgativeSkips: 0,  // MSIE doesn't do negative left margins  
   separateSkips: 0,           // Netscape doesn't combine skips well  
   noEmptySpans: 0,            // empty spans are/aren't allowed  
   msieSpaceFix: '',           // for MSIE spacing bug fix  
   
   delay: 1,       // delay for asynchronous math processing  
     
   defaultH: 0,    // default height for characters with no height specified  
   
   //  
   //  Debugging flags  
   //  
   show: {  
     BBox:           false,  
     Baseline:       false,  
     Top:            false  
   },  
     
   //    //
   //  The styles needed for the TeX fonts    //  The styles needed for the TeX fonts
   //    //
Line 155  var jsMath = { Line 93  var jsMath = {
     '.size8':          'font-size: 207%', // huge      '.size8':          'font-size: 207%', // huge
     '.size9':          'font-size: 249%', // Huge      '.size9':          'font-size: 249%', // Huge
       
     '.cmr10':          'font-family: cmr10',      '.cmr10':          'font-family: cmr10, serif',
     '.cmbx10':         'font-family: cmbx10, cmr10',      '.cmbx10':         'font-family: cmbx10, cmr10',
     '.cmti10':         'font-family: cmti10, cmr10',      '.cmti10':         'font-family: cmti10, cmr10',
     '.cmmi10':         'font-family: cmmi10',      '.cmmi10':         'font-family: cmmi10',
     '.cmsy10':         'font-family: cmsy10',      '.cmsy10':         'font-family: cmsy10',
     '.cmex10':         'font-family: cmex10',      '.cmex10':         'font-family: cmex10',
     '.arial':          'font-family: Arial unicode MS', // for MSIE      
       '.math':           'font-family: serif; font-style: normal; font-weight: normal',
     '.normal':         'font-family: serif; font-style: normal',      '.typeset':        'font-family: serif; font-style: normal; font-weight: normal',
     '.math':           'font-family: serif; font-style: normal',      '.normal':         'font-family: serif; font-style: normal; font-weight: normal; '
     '.typeset':        'font-family: serif; font-style: normal',                            + 'padding:0px; border:0px; margin:0px;',
     'span.typeset':    'font-family: serif; font-style: normal',      'span.typeset':    '',
     'div.typeset':     'font-family: serif; font-style: normal; text-align: center; margin-top: 1em; margin-bottom: 1em',      'div.typeset':     'text-align: center; margin: 1em 0px;',
     '.mathlink':       'text-decoration: none',      '.mathlink':       'text-decoration: none',
     '.mathHD':         'border-width: 0; width: 1px; margin-right: -1px',      '.mathHD':         'border-width:0px; width: 1px; margin-right: -1px',
       
     '.error':          'font-size: 10pt; font-style: italic; '      '.error':          'font-size: 10pt; font-style: italic; '
                          + 'background-color: #FFFFCC; padding: 1; '                           + 'background-color: #FFFFCC; padding: 1px; '
                          + 'border-width: 1; border-style: solid; border-color: #CC0000'                           + 'border: 1px solid #CC0000',
   },  
   
       '.jsM_panel':      'position:fixed; bottom:1.5em; right:1.5em; padding: 10px 20px; '
                            + 'background-color:#DDDDDD; border: outset 2px; '
                            + 'z-index:103; width:auto;',
       '.jsM_button':     'position:fixed; bottom:1px; right:2px; background-color:white; '
                            + 'border: solid 1px #959595; margin:0px; padding: 0px 3px 1px 3px; '
                            + 'z-index:102; color:black; text-decoration:none; font-size:x-small; width:auto;',
       '.jsM_float':      'position:absolute; top:0px; left:0px; max-width:80%; '
                            + 'z-index:101; width:auto; height:auto;',
       '.jsM_drag':       'background-color:#DDDDDD; border: outset 1px; height:12px; font-size: 1px;',
       '.jsM_close':      'background-color:#E6E6E6; border: inset 1px; width:8px; height:8px; margin: 1px 2px;',
       '.jsM_source':     'background-color:#E2E2E2; border: outset 1px; '
                            + 'width:auto; height:auto; padding: 8px 15px; '
                            + 'font-family: courier, fixed; font-size: 90%',
       '.jsM_noFont':     'text-align: center; padding: 10px 20px; border: 3px solid #DD0000; '
                            + ' background-color: #FFF8F8; color: #AA0000; font-size:small; width:auto;',
       '.jsM_fontLink':   'padding: 0px 5px 2px 5px; text-decoration:none; color:black;'
                            + ' border: 2px outset; background-color:#E8E8E8; font-size:80%; width:auto;'
     },
       
   
   /***************************************************************************/    /***************************************************************************/
   
   /*    /*
    *  Get the width and height (in pixels) of an HTML string     *  Get the width and height (in pixels) of an HTML string
    */     */
   BBoxFor: function (s) {    BBoxFor: function (s) {
     this.hidden.innerHTML = s;      this.hidden.innerHTML = '<NOBR><SPAN CLASS="jsM_scale">'+s+'</SPAN></NOBR>';
     var bbox = {w: this.hidden.offsetWidth, h: this.hidden.offsetHeight};      var bbox = {w: this.hidden.offsetWidth, h: this.hidden.offsetHeight};
     this.hidden.innerHTML = '';    // avoid MSIE bug on the Mac      this.hidden.innerHTML = '';
     return bbox;      return bbox;
   },    },
   
Line 198  var jsMath = { Line 154  var jsMath = {
   },    },
   
   /*    /*
    *  Determine if the "top" of a <SPAN> is always at the same height     *  For browsers that don't handle sizes of italics properly (MSIE)
    *  or varies with the height of the rest of the line (MSIE).  
    */     */
   TestSpanHeight: function () {    EmBoxForItalics: function (s) {
     this.hidden.innerHTML = '<SPAN><IMG SRC="'+jsMath.blank+'" STYLE="height: 2em"></SPAN>';      var bbox = this.BBoxFor(s);
     var span = this.hidden.getElementsByTagName('SPAN')[0];      if (s.match(/<I>|CLASS="icm/i)) {
     var img  = this.hidden.getElementsByTagName('IMG')[0];        bbox.w = this.BBoxFor(s+jsMath.Browser.italicString).w
     this.spanHeightVaries = (span.offsetHeight == img.offsetHeight);                  - jsMath.Browser.italicCorrection;
     this.hidden.innerHTML = '';      }
       return {w: bbox.w/this.em, h: bbox.h/this.em};
   },    },
     
   /*    /*
    *  Determine if the NAME attribute of a tag can be changed     *  Initialize jsMath.  This determines the em size, and a variety
    *  using the setAttribute function, and then be properly     *  of other parameters used throughout jsMath.
    *  returned by getElementByName.  
    */     */
   TestRenameOK: function () {    Init: function () {
     this.hidden.innerHTML = '<SPAN ID="jsMath.test"></SPAN>';      if (jsMath.Setup.inited != 1) {
     var test = document.getElementById('jsMath.test');        if (jsMath.Setup.inited) {
     test.setAttribute('NAME','jsMath_test');          alert("It looks like jsMath failed to set up properly.");
     this.renameOK = (document.getElementsByName('jsMath_test').length > 0);        } else {
     this.hidden.innerHTML = '';          alert("You must call jsMath.Setup.Body() explicitly when jsMath is" +
   },                "loaded as part of the <HEAD> section");
         }
         jsMath.Setup.Init(); // may fail to load fallback files properly
       }
       this.em = this.BBoxFor('<IMG SRC="'+jsMath.blank+'" STYLE="width:10em; height:1em">').w/10;
       if (jsMath.Browser.italicString) 
         jsMath.Browser.italicCorrection = jsMath.BBoxFor(jsMath.Browser.italicString).w;
       if (jsMath.Browser.hiddenSpace != '') {
         jsMath.Browser.spaceWidth =
           this.EmBoxFor(jsMath.Browser.hiddenSpace +
                         jsMath.Browser.hiddenSpace +
                         jsMath.Browser.hiddenSpace +
                         jsMath.Browser.hiddenSpace +
                         jsMath.Browser.hiddenSpace).w/5;
       }
       var bb = this.BBoxFor('x'); var h = bb.h;
       var d = this.BBoxFor('x<IMG SRC="'+jsMath.blank+'" HEIGHT="'+(h*jsMath.Browser.imgScale)+'" WIDTH="1">').h - h;
       this.h = (h-d)/this.em; this.d = d/this.em;
       this.hd = this.h + this.d;
       this.xWidth = bb.w;  // used to tell if scale has changed
       
       this.Setup.TeXfonts();
       
       var x_height = this.EmBoxFor('<SPAN CLASS="cmr10">M</SPAN>').w/2;
       this.TeX.M_height = x_height*(26/14);
       this.TeX.h = this.h; this.TeX.d = this.d; this.TeX.hd = this.hd;
       
       this.Img.Scale();
       if (!this.initialized) {
         this.Setup.Sizes();
         this.Img.UpdateFonts();
       }
   
       // factor for \big and its brethren
       this.p_height = (this.TeX.cmex10[0].h + this.TeX.cmex10[0].d) / .85;
   
       this.initialized = 1;
     },
     
   /*    /*
    *  Look to see if a font is found.  HACK!     *  Get the xWidth size and if it has changed, reinitialize the sizes
    *  Check the character in the '|' position, and see if it is  
    *  wider than the usual '|'.  
    */     */
   TestFont: function (name,n,factor) {    ReInit: function () {
     if (n == null) {n = 124}; if (factor == null) {factor = 2}      var w = this.BBoxFor('x').w;
     var wh1 = this.BBoxFor('<SPAN STYLE="font-family: '+name+', serif">'+this.TeX[name][n].c+'</SPAN>');      if (w != this.xWidth) {this.Init()}
     var wh2 = this.BBoxFor('<SPAN STYLE="font-family: serif">'+this.TeX[name][n].c+'</SPAN>');  
     return (wh1.w > factor*wh2.w && wh1.h != 0);  
   },    },
     
   TestFont2: function (name,n,factor) {    /*
     if (n == null) {n = 124}; if (factor == null) {factor = 2}     *  Mark jsMath as loaded and copy any user-provided overrides
     var wh1 = this.BBoxFor('<SPAN STYLE="font-family: '+name+', serif">'+this.TeX[name][n].c+'</SPAN>');     */
     var wh2 = this.BBoxFor('<SPAN STYLE="font-family: serif">'+this.TeX[name][n].c+'</SPAN>');    Loaded: function () {
     return (wh2.w > factor*wh1.w && wh1.h != 0);      this.Insert(jsMath,jsMath_old);
       jsMath_old = null;
       jsMath.loaded = 1;
   },    },
       
   /*    /*
    *  Check for the availability of TeX fonts.  We do this by looking at     *  Manage JavaScript objects:
    *  the width and height of a character in the cmex10 font.  The cmex10  
    *  font has depth considerably greater than most characters' widths (the  
    *  whole font has the depth of the character with greatest depth).  This  
    *  is not the case for most fonts, so if we can access cmex10, the  
    *  height of a character should be much bigger than the width.  
    *  Otherwise, if we don't have cmex10, we'll get a character in another  
    *  font with normal height and width.  In this case, we insert a message  
    *  pointing the user to the jsMath site, and load one of the fallback  
    *  definitions.  
    *       *  
    */     *      Add:        add/replace items in an object
   CheckFonts: function () {     *      Insert:     add items to an object
     jsMath.nofonts = 0;     *      Package:    add items to an object prototype
     var wh = this.BBoxFor('<SPAN STYLE="font-family: cmex10">'+this.TeX.cmex10[1].c+'</SPAN>');     */
     if (wh.w*3 < wh.h && wh.h != 0) return;    Add: function (dst,src) {for (var id in src) {dst[id] = src[id]}},
     if (this.TestFont('cmr10')) return;    Insert: function (dst,src) {
     if (window.NoFontMessage) {window.NoFontMessage()} else {this.NoFontMessage()}      for (var id in src) {
     if (navigator.platform == 'Win32') {        if (dst[id] && typeof(src[id]) == 'object'
       document.writeln('<SCRIPT SRC="'+this.root+'jsMath-fallback-pc.js"></SCRIPT>');                    && (typeof(dst[id]) == 'object'
     } else if (navigator.platform == 'MacPPC') {                    ||  typeof(dst[id]) == 'function')) {
       document.writeln('<SCRIPT SRC="'+this.root+'jsMath-fallback-mac.js"></SCRIPT>');          this.Insert(dst[id],src[id]);
     } else {        } else {
       // default to unix?  Is there a better way to tell if unix?          dst[id] = src[id];
       document.writeln('<SCRIPT SRC="'+this.root+'jsMath-fallback-unix.js"></SCRIPT>');        }
     }      }
     jsMath.nofonts = 1;  
   },    },
     Package: function (obj,def) {this.Insert(obj.prototype,def)}
   
   }
   
   /***************************************************************************/
   
   /*
    *  Miscellaneous setup and initialization
    */
   jsMath.Setup = {
     
   /*    /*
    *  The message for when no TeX fonts.  You can eliminate this message     *  Insert a DIV at the top of the page with given ID,
    *  by including     *  attributes, and style settings
    *    
    *      <SCRIPT>function NoFontMessage() {}</SCRIPT>  
    *  
    *  in your HTML file, if you want.  But this means the user may not know  
    *  that he or she can get a better version of your page.  
    */     */
   NoFontMessage: function () {    TopHTML: function (id,attributes,styles) {
     document.writeln      try {
       ('<CENTER><DIV STYLE="padding: 10; border-style: solid; border-width:3;'        var div = document.createElement('div');
       +' border-color: #DD0000; background-color: #FFF8F8; width: 75%; text-align: left">'        div.setAttribute("id",'jsMath.'+id);
       +'<SMALL><FONT COLOR="#AA0000"><B>Warning:</B>\n'        for (var i in attributes) {
       +'It looks like you don\'t have the TeX math fonts installed.\n'          div.setAttribute(i,attributes[i]);
       +'The mathematics on this page may not look right without them.\n'          if (i == "class") {div.setAttribute('className',attributes[i])} // MSIE
       +'The <A HREF="http://www.math.union.edu/locate/jsMath/" TARGET="_blank">'        }
       +'jsMath Home Page</A> has information on how to download the\n'        for (var i in styles) {div.style[i]= styles[i]}
       +'needed fonts.  In the meantime, we will do the best we can\n'        if (!document.body.hasChildNodes) {document.body.appendChild(div)}
       +'with the fonts you have, but it may not be pretty and some equations\n'          else {document.body.insertBefore(div,document.body.firstChild)}
       +'may not be rendered correctly.\n'      } catch (err) {
       +'</FONT></SMALL></DIV></CENTER><p><HR><p>');        var html = '<DIV ID="jsMath.'+id+'"';
         for (var id in attributes) {html += ' '+id+'="'+attributes[id]+'"'}
         if (styles) {
           html += ' STYLE="';
           for (var id in styles) {html += ' '+id+':'+styles[id]+';'}
           html += '"';
         }
         html += '</DIV>';
         if (!document.body.insertAdjacentHTML) {document.write(html)}
           else {document.body.insertAdjacentHTML('AfterBegin',html)}
         div = jsMath.Element(id);
       }
       return div;
   },    },
       
   /*    /*
    *  Initialize jsMath.  This determines the em size, and a variety     *  Source a jsMath JavaScript file
    *  of other parameters used throughout jsMath.  
    */     */
   Init: function() {    Script: function (file) {
     this.em = this.BBoxFor('<DIV STYLE="width: 20em; height: 1em"></DIV>').w/20;      if (!file.match('^([a-zA-Z]+:/)?/')) {file = jsMath.root + file}
     var h = this.BBoxFor('x').h;    // Line height and depth to baseline      document.write('<SCRIPT SRC="'+file+'"></SCRIPT>');
     var d = this.BBoxFor('x<IMG SRC="'+jsMath.black+'" HEIGHT="'+h+'" WIDTH="1">').h - h;    },
     this.h = (h-d)/this.em; this.d = d/this.em;    
     this.hd = this.h + this.d;    /*
     this.ph = h-d; this.pd = d;     *  Use a hidden <DIV> for measuring the BBoxes of things
          */
     this.InitTeXfonts();    HTML: function () {
           jsMath.hidden = this.TopHTML("Hidden",{'class':"normal"},{
     var x_height = this.EmBoxFor('<SPAN CLASS="cmr10">M</SPAN>').w/2;        position:"absolute", top:0, left:0, border:0, padding:0, margin:0
     this.TeX.M_height = x_height*(26/14);      });
     this.TeX.h = this.h; this.TeX.d = this.d; this.TeX.hd = this.hd;      jsMath.hiddenTop = jsMath.hidden;
     // factor for \big and its brethren      return;
     this.p_height = (this.TeX.cmex10[0].h+this.TeX.cmex10[0].d) / .85;  
   
     this.InitSizes();  
       
     this.initialized = 1;  
   },    },
   
   /*    /*
    *  Find the root URL for the jsMath files (so we can load     *  Find the root URL for the jsMath files (so we can load
    *  the other .js and .gif files     *  the other .js and .gif files)
    */     */
   InitSource: function () {    Source: function () {
     var script = document.getElementsByTagName('SCRIPT');      var script = document.getElementsByTagName('SCRIPT');
     var src = script[script.length-1].getAttribute('SRC');      if (script) {
     if (src.match('(^|/)jsMath.js$')) {        for (var i = 0; i < script.length; i++) {
       this.root = src.replace(/jsMath.js$/,'');          var src = script[i].src;
       this.blank = this.root + this.blank;          if (src && src.match('(^|/)jsMath.js$')) {
       this.black = this.root + this.black;            jsMath.root = src.replace(/jsMath.js$/,'');
             jsMath.Img.root = jsMath.root + "fonts/";
             jsMath.blank = jsMath.root + jsMath.blank;
             this.Domain();
             return;
           }
         }
       }
       jsMath.root = ''; jsMath.Img.root = "fonts/";
     },
     
     /*
      *  Find the most restricted common domain for the main
      *  page and jsMath.  Report an error if jsMath is outside
      *  the domain of the calling page.
      */
     Domain: function () {
       var jsDomain = ''; var pageDomain = document.domain;
       if (jsMath.root.match('://([^/]*)/')) {jsDomain = RegExp.$1}
       jsDomain = jsDomain.replace(/:\d+$/,'');
       if (jsDomain == "" || jsDomain == pageDomain) return;
       //
       // MSIE on the Mac can't change document.domain and 'try' won't
       //   catch the error (Grrr!), so exit for them
       //
       if (navigator.appName == 'Microsoft Internet Explorer' &&
           navigator.platform == 'MacPPC' && navigator.onLine &&
           navigator.userProfile && document.all) return;
       jsDomain = jsDomain.split(/\./); pageDomain = pageDomain.split(/\./);
       if (jsDomain.length < 2 || pageDomain.length < 2 ||
           jsDomain[jsDomain.length-1] != pageDomain[pageDomain.length-1] ||
           jsDomain[jsDomain.length-2] != pageDomain[pageDomain.length-2]) {
         this.DomainWarning();
         return;
     }      }
       var domain = jsDomain[jsDomain.length-2] + '.' + jsDomain[jsDomain.length-1];
       for (var i = 3; i <= jsDomain.length && i <= pageDomain.length; i++) {
         if (jsDomain[jsDomain.length-i] != pageDomain[pageDomain.length-i]) break;
         domain = jsDomain[jsDomain.length-i] + '.' + domain;
       }
       document.domain = domain;
     },
   
     DomainWarning: function () {
       alert("In order for jsMath to be able to load the additional "
           + "components that it may need, the jsMath.js file must be "
           + "loaded from a server in the same domain as the page that "
           + "contains it.  Because that is not the case for this page, "
           + "the mathematics displayed here may not appear correctly.");
   },    },
       
   /*    /*
    *  Look up the default height and depth for a TeX font     *  Look up the default height and depth for a TeX font
    *  and set the skewchar     *  and set the skewchar
    */     */
   InitTeXfont: function (name) {    TeXfont: function (name) {
     var font = this.TeX[name];      var font = jsMath.TeX[name];
     var WH = this.EmBoxFor('<SPAN CLASS="'+name+'">'+font[65].c+'</SPAN>');      var WH = jsMath.EmBoxFor('<SPAN CLASS="'+name+'">'+font[65].c+'</SPAN>');
     font.hd = WH.h;      font.hd = WH.h;
     font.d = this.EmBoxFor('<SPAN CLASS="'+name+'">'+ font[65].c +      font.d = jsMath.EmBoxFor('<SPAN CLASS="'+name+'">'+ font[65].c +
       '<IMG SRC="'+jsMath.black+'" STYLE="height:'+font.hd+'em; width:1"></SPAN>').h         '<IMG SRC="'+jsMath.blank+'" STYLE="height:'+(font.hd*jsMath.Browser.imgScale)+'em; width:1px;"></SPAN>').h
       - font.hd;        - font.hd;
     font.h = font.hd - font.d;      font.h = font.hd - font.d;
     font.dh = .05;      font.dh = .05; if (jsMath.browser == 'Safari') {font.hd *= 2};
     if (name == 'cmmi10') {font.skewchar = 0177}       if (name == 'cmmi10') {font.skewchar = 0177} 
     else if (name == 'cmsy10') {font.skewchar = 060}      else if (name == 'cmsy10') {font.skewchar = 060}
   },    },
Line 354  var jsMath = { Line 392  var jsMath = {
   /*    /*
    *  Init all the TeX fonts     *  Init all the TeX fonts
    */     */
   InitTeXfonts: function () {    TeXfonts: function () {
     for (var i = 0; i < this.TeX.fam.length; i++)       for (var i = 0; i < jsMath.TeX.fam.length; i++) 
       {if (this.TeX.fam[i]) {this.InitTeXfont(this.TeX.fam[i])}}        {if (jsMath.TeX.fam[i]) {this.TeXfont(jsMath.TeX.fam[i])}}
   },    },
   
   /*    /*
    *  Compute font parameters for various sizes     *  Compute font parameters for various sizes
    */     */
   InitSizes: function () {    Sizes: function () {
     this.TeXparams = [];      jsMath.TeXparams = [];
     for (var j=0; j < this.sizes.length; j++) {this.TeXparams[j] = {}}      for (var j=0; j < jsMath.sizes.length; j++) {jsMath.TeXparams[j] = {}}
     for (var i in this.TeX) {      for (var i in jsMath.TeX) {
       if (typeof(this.TeX[i]) != 'object') {        if (typeof(jsMath.TeX[i]) != 'object') {
         for (var j=0; j < this.sizes.length; j++) {          for (var j=0; j < jsMath.sizes.length; j++) {
           this.TeXparams[j][i] = this.sizes[j]*this.TeX[i]/100;            jsMath.TeXparams[j][i] = jsMath.sizes[j]*jsMath.TeX[i]/100;
         }          }
       }        }
     }      }
   },    },
   
     
   /*    /*
    *  Test for browser characteristics, and adjust the font table     *  Send the style definitions to the browser (these may be adjusted
      *  by the browser-specific code)
      */
     Styles: function (styles) {
       if (!styles) {
         styles = jsMath.styles;
         styles['.jsM_scale'] = 'font-size:'+jsMath.Controls.cookie.scale+'%';
       }
       document.writeln('<STYLE TYPE="text/css" ID="jsMath.styles">');
       for (var id in styles) {document.writeln('  '+id+'  {'+styles[id]+'}')}
       document.writeln('</STYLE>');
     },
     
     /*
      *  Do the initialization that requires the BODY to be in place.
      *  (called automatically if the jsMath.js file is loaded in the
      *  BODY, but must be called explicitly if it is in the HEAD).
      */
     Body: function () {
       if (this.inited) return;
   
       this.inited = -1;
   
       jsMath.Setup.HTML();
       jsMath.Setup.Source();
       jsMath.Browser.Init();
       jsMath.Controls.Init();
       jsMath.Click.Init();
       jsMath.Setup.Styles();
       
       jsMath.Setup.User();  //  do user-specific initialization
   
       //make sure browser-specific loads are done before this
       document.write('<SCRIPT>jsMath.Font.Check()</SCRIPT>');
       
       this.inited = 1;
     },
     
     /*
      *  Web page author can override this to do initialization
      *  that must be done before the font check is performed
      */
     User: function () {}
     
   };
   
   jsMath.Update = {
   
     /*
      *  Update specific parameters for a limited number of font entries
      */
     TeXfonts: function (change) {
       for (var font in change) {
         for (var code in change[font]) {
           for (var id in change[font][code]) {
             jsMath.TeX[font][code][id] = change[font][code][id];
           }
         }
       }
     },
     
     /*
      *  Update the character code for every character in a list
      *  of fonts
      */
     TeXfontCodes: function (change) {
       for (var font in change) {
         for (var i = 0; i < change[font].length; i++) {
           jsMath.TeX[font][i].c = change[font][i];
         }
       }
     },
   
     /*
      *  Add a collection of styles to the style list
      */
     Styles: function (styles) {
       for (var i in styles) {jsMath.styles[i] = styles[i]}
     }
     
   };
   
   /***************************************************************************/
   
   /*
    *  Implement browser-specific checks
    */
   
   jsMath.Browser = {
   
     allowAbsolute: 1,           // tells if browser can nest absolutely positioned
                                 //   SPANs inside relative SPANs
     allowAbsoluteDelim: 0,      // OK to use absolute placement for building delims?
     separateSkips: 0,           // MSIE doesn't do negative left margins, and
                                 //   Netscape doesn't combine skips well
   
     msieSpaceFix: '',           // for MSIE spacing bug fix
     msieCenterBugFix: '',       // for MSIE centering bug with image fonts
     msieInlineBlockFix: '',     // for MSIE alignment bug in non-quirks mode
     imgScale: 1,                // MSI scales images for 120dpi screens, so compensate
   
     renameOK: 1,                // tells if brower will find a tag whose name
                                 //   has been set via setAttributes
   
     delay: 1,                   // delay for asynchronous math processing
     
     spaceWidth: 0,              // Konqueror space fix
     hiddenSpace: "",            // ditto
     valignBug: 0,               // Konqueror doesn't nest vertical-align
   
     operaHiddenFix: '',         // for Opera to fix bug with math in tables
   
     /*
      *  Determine if the "top" of a <SPAN> is always at the same height
      *  or varies with the height of the rest of the line (MSIE).
      */
     TestSpanHeight: function () {
       jsMath.hidden.innerHTML = '<SPAN><IMG SRC="'+jsMath.blank+'" STYLE="height: 2em"></SPAN>';
       var span = jsMath.hidden.getElementsByTagName('SPAN')[0];
       var img  = jsMath.hidden.getElementsByTagName('IMG')[0];
       this.spanHeightVaries = (span.offsetHeight == img.offsetHeight);
       jsMath.hidden.innerHTML = '';
     },
     
     /*
      *  Determine if the NAME attribute of a tag can be changed
      *  using the setAttribute function, and then be properly
      *  returned by getElementByName.
      */
     TestRenameOK: function () {
       jsMath.hidden.innerHTML = '<SPAN ID="jsMath.test"></SPAN>';
       var test = document.getElementById('jsMath.test');
       test.setAttribute('NAME','jsMath_test');
       this.renameOK = (document.getElementsByName('jsMath_test').length > 0);
       jsMath.hidden.innerHTML = '';
     },
   
     /*
      *  Test for browser characteristics, and adjust things
    *  to overcome specific browser bugs     *  to overcome specific browser bugs
    */     */
   InitBrowser: function () {    Init: function () {
     jsMath.browser = 'unknown';      jsMath.browser = 'unknown';
     this.isSafari = navigator.userAgent.match(/Safari/);  
     this.TestSpanHeight();      this.TestSpanHeight();
     this.TestRenameOK();      this.TestRenameOK();
   
       this.MSIE();
       this.Mozilla();
       this.Opera();
       this.OmniWeb();
       this.Safari();
       this.Konqueror();
       
     //      //
     //  Check for bug-filled Internet Explorer      // Change some routines depending on the browser
     //      // 
       if (this.allowAbsoluteDelim) {
         jsMath.Box.DelimExtend = jsMath.Box.DelimExtendAbsolute;
         jsMath.Box.Layout = jsMath.Box.LayoutAbsolute;
       } else {
         jsMath.Box.DelimExtend = jsMath.Box.DelimExtendRelative;
         jsMath.Box.Layout = jsMath.Box.LayoutRelative;
       }
       
       if (this.separateSkips) {
         jsMath.HTML.Place = jsMath.HTML.PlaceSeparateSkips;
         jsMath.Typeset.prototype.Place = jsMath.Typeset.prototype.PlaceSeparateSkips;
       }
     },
     
     //
     //  Handle bug-filled Internet Explorer
     //
     MSIE: function () {
     if (this.spanHeightVaries) {      if (this.spanHeightVaries) {
       jsMath.browser = 'MSIE';        jsMath.browser = 'MSIE';
       if (navigator.platform == 'Win32') {        if (navigator.platform == 'Win32') {
         this.UpdateTeXfonts({          jsMath.Update.TeXfonts({
           cmr10:  {'10': {c: '&Omega;', tclass: 'normal'}},            cmr10:  {'10': {c: '&Omega;', tclass: 'normal'}},
           cmmi10: {            cmmi10: {
      '10':  {c: '<I>&Omega;</I>', tclass: 'normal'},               '10':  {c: '<I>&Omega;</I>', tclass: 'normal'},
      '126': {c: '&#x7E;<SPAN STYLE="margin-left:.1em"></SPAN>'}               '126': {c: '&#x7E;<SPAN STYLE="margin-left:.1em"></SPAN>'}
   },            },
           cmsy10: {'10': {c: '&#x2297;', tclass: 'arial'}},            cmsy10: {
               '10': {c: '&#x2297;', tclass: 'arial'},
               '55': {c: '<SPAN STYLE="margin-right:-.54em">7</SPAN>'}
             },
           cmex10: {'10': {c: '<SPAN STYLE="font-size: 67%">D</SPAN>'}},            cmex10: {'10': {c: '<SPAN STYLE="font-size: 67%">D</SPAN>'}},
           cmti10: {'10': {c: '<I>&Omega;</I>', tclass: 'normal'}},            cmti10: {'10': {c: '<I>&Omega;</I>', tclass: 'normal'}},
           cmbx10: {'10': {c: '<B>&Omega;</B>', tclass: 'normal'}}            cmbx10: {'10': {c: '<B>&Omega;</B>', tclass: 'normal'}}
         });          });
         this.allowAbsoluteDelim = 1;          this.allowAbsoluteDelim = 1;
  this.separateSkips = 1;          this.separateSkips = 1;
           this.buttonCheck = 1;
           this.msieDivWidthBug = 1;
         this.msieFontBug = 1; this.msieIntegralBug = 1;          this.msieFontBug = 1; this.msieIntegralBug = 1;
           this.msieAlphaBug = 1; this.alphaPrintBug = 1;
           this.msieCenterBugFix = 'position:relative; ';
         this.msieSpaceFix = '<IMG SRC="'+jsMath.blank+'" CLASS="mathHD">';          this.msieSpaceFix = '<IMG SRC="'+jsMath.blank+'" CLASS="mathHD">';
           this.msieInlineBlockFix = ' display: inline-block;';
         jsMath.Macro('joinrel','\\mathrel{\\kern-5mu}'),          jsMath.Macro('joinrel','\\mathrel{\\kern-5mu}'),
         jsMath.Macro('mapsto','\\mapstochar\\kern-.54em\\rightarrow');          jsMath.styles['.arial'] = "font-family: 'Arial unicode MS'";
         jsMath.Macro('longmapsto','\\mapstochar\\kern-.54em\\char{cmsy10}{0}\\joinrel\\rightarrow');          // MSIE doesn't implement fixed positioning, so use absolute
           jsMath.styles['.jsM_panel'] =
                 jsMath.styles['.jsM_panel'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
           jsMath.styles['.jsM_button'] = 'width:1px; '
               + jsMath.styles['.jsM_button'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
           window.onscroll = jsMath.Controls.MoveButton;
           // MSIE will rescale images if the DPIs differ
           if (screen.deviceXDPI && screen.logicalXDPI 
                && screen.deviceXDPI != screen.logicalXDPI) {
             this.imgScale *= screen.logicalXDPI/screen.deviceXDPI;
             jsMath.Controls.cookie.alpha = 0;
           }
           // Handle bug with getting width of italic text
           this.italicString = '<I>x</I>';
           jsMath.EmBoxFor = jsMath.EmBoxForItalics;
       } else if (navigator.platform == 'MacPPC') {        } else if (navigator.platform == 'MacPPC') {
         document.writeln('<SCRIPT SRC="'+this.root+'jsMath-msie-mac.js"></SCRIPT>');          this.msieAbsoluteBug = 1; this.msieButtonBug = 1;
           this.msieDivWidthBug = 1;
           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.msieAbsoluteBug = 1;          jsMath.styles['.jsM_panel'] = 'width:25em; ' + jsMath.styles['.jsM_panel'].replace(/width:auto/,"");
           jsMath.styles['.jsM_button'] = 'width:1px; ' + jsMath.styles['.jsM_button'].replace(/width:auto/,"");
       }        }
       jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');        jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');
     }      }
     },
   
     //    //
     //  Look for Netscape/Mozilla (any flavor)    //  Handle Netscape/Mozilla (any flavor)
     //    //
     if (this.hidden.ATTRIBUTE_NODE) {    Mozilla: function () {
       if (jsMath.hidden.ATTRIBUTE_NODE) {
       jsMath.browser = 'Mozilla';        jsMath.browser = 'Mozilla';
       if (navigator.platform == 'MacPPC') {        if (navigator.platform == 'MacPPC') {
         this.UpdateTeXfonts({          jsMath.Update.TeXfonts({
           cmr10:  {'10': {c: '&Omega;', tclass: 'normal'}},            cmr10:  {'10': {c: '&Omega;', tclass: 'normal'}},
           cmmi10: {'10': {c: '<I>&Omega;</I>', tclass: 'normal'}},            cmmi10: {'10': {c: '<I>&Omega;</I>', tclass: 'normal'}},
           cmsy10: {'10': {c: '&otimes;', tclass: 'normal'}},            cmsy10: {'10': {c: '&otimes;', tclass: 'normal'}},
Line 431  var jsMath = { Line 659  var jsMath = {
           cmbx10: {'10': {c: '<B>&Omega;</B>', tclass: 'normal'}}            cmbx10: {'10': {c: '<B>&Omega;</B>', tclass: 'normal'}}
         });          });
       } else {        } else {
         document.writeln('<SCRIPT SRC="'+this.root+'jsMath-mozilla.js"></SCRIPT>');          jsMath.Setup.Script('jsMath-mozilla.js');
           this.alphaPrintBug = 1;
       }        }
       for (var i = 0; i < this.TeX.fam.length; i++) {        for (var i = 0; i < jsMath.TeX.fam.length; i++) {
         if (this.TeX.fam[i])           if (jsMath.TeX.fam[i]) 
           {this.styles['.'+this.TeX.fam[i]] += '; position: relative'}            {jsMath.styles['.'+jsMath.TeX.fam[i]] += '; position: relative'}
       }        }
       this.allowAbsoluteDelim = 1;        this.allowAbsoluteDelim = 1;
       this.separateSkips = 1;        this.separateSkips = 1;
       jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');        jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');
     }      }
     },
     //    
     //  Look for OmniWeb    //
     //    //  Handle OmniWeb
     //
     OmniWeb: function () {
     if (navigator.accentColorName) {      if (navigator.accentColorName) {
       jsMath.browser = 'OmniWeb';        jsMath.browser = 'OmniWeb';
       this.allowAbsolute = 0;        this.allowAbsolute = !navigator.userAgent.match("OmniWeb/v4");
         this.allowAbsoluteDelim = this.allowAbsolute;
         this.buttonCheck = 1;
     }      }
     },
           
     //    //
     //  Look for Opera    //  Handle Opera
     //    //
     if (navigator.userAgent.search(" Opera ") >= 0) {    Opera: function () {
       if (navigator.appName == 'Opera' || navigator.userAgent.match(" Opera ")) {
       jsMath.browser = 'Opera';        jsMath.browser = 'Opera';
       this.isOpera = 1;        jsMath.Update.TeXfonts({
       this.UpdateTeXfonts({  
         cmr10:  {          cmr10:  {
           '10': {c: '&Omega;', tclass: 'normal'},            '10': {c: '&Omega;', tclass: 'normal'},
           '20': {c: '&#x2C7;', tclass: 'normal'}            '20': {c: '&#x2C7;', tclass: 'normal'}
Line 483  var jsMath = { Line 717  var jsMath = {
         }          }
       });        });
       this.allowAbsolute = 0;        this.allowAbsolute = 0;
       jsMath.delay = 10;        this.delay = 10;
         this.operaHiddenFix = '[Processing Math]';
     }      }
     },
   
     //    //
     //  Look for Safari    //  Handle Safari
     //    //
     if (this.isSafari) {    Safari: function () {
       if (navigator.appVersion.match(/Safari\//)) {
       jsMath.browser = 'Safari';        jsMath.browser = 'Safari';
       var version = navigator.userAgent.match("Safari/([0-9]+)")[1];        var version = navigator.userAgent.match("Safari/([0-9]+)");
       if (version < 125) {this.allowAbsolute = 0; this.oldSafari = 1}        version = (version)? version[1] : 200;  // FIXME: hack until I get Tiger
       for (var i = 0; i < this.TeX.fam.length; i++)        for (var i = 0; i < jsMath.TeX.fam.length; i++)
         {if (this.TeX.fam[i] != '') {this.TeX[this.TeX.fam[i]].dh = .1}}          {if (jsMath.TeX.fam[i]) {jsMath.TeX[jsMath.TeX.fam[i]].dh = .1}}
       this.absoluteOffsetY = -.05;        jsMath.TeX.axis_height += .05;
       this.TeX.axis_height += .05;        this.allowAbsoluteDelim = version >= 125;
       this.allowAbsoluteDelim = ! this.oldSafari;        this.safariIFRAMEbug = version >= 312;  // FIXME: find out if they fixed it
         this.safariImgBug = 1;
         this.buttonCheck = 1;
       }
     },
     
     //
     //  Handle Konqueror
     //
     Konqueror: function () {
       if (navigator.product && navigator.product.match("Konqueror")) {
         jsMath.browser = 'Konqueror';
         jsMath.Update.TeXfonts({
           cmr10:  {'20': {c: '&#x2C7;', tclass: 'normal'}},
           cmmi10: {'20': {c: '&kappa;', tclass: 'normal'}},
           cmsy10: {'20': {c: '&#x2264;', tclass: 'normal'}},
           cmex10: {'20': {c: '<SPAN STYLE="font-size: 84%">"</SPAN>'}},
           cmti10: {'20': {c: '<I>&#x2C7;</I>', tclass: 'normal'}},
           cmbx10: {'20': {c: '<B>&#x2C7;</B>', tclass: 'normal'}}
         });
         this.allowAbsolute = 0;
         this.allowAbsoluteDelim = 0;
         if (navigator.userAgent.match(/Konqueror\/(\d+)\.(\d+)/)) {
           if (RegExp.$1 < 3 || (RegExp.$1 == 3 && RegExp.$2 < 3)) {
             this.separateSkips = 1;
             this.valignBug = 1;
             this.hiddenSpace = '&nbsp;';
             jsMath.Box.prototype.Remeasured = function () {return this};
           }
         }
     }      }
     }
   
     //  };
     // Change some routines depending on the browser  
     //   /***************************************************************************/
     if (this.allowAbsoluteDelim) {  
       jsMath.Box.DelimExtend = jsMath.Box.DelimExtendAbsolute;  /*
       jsMath.Box.Layout = jsMath.Box.LayoutAbsolute;   *  Implement font check and messages
    */
   jsMath.Font = {
     
     fallback: "symbol", // the default fallback method
   
     // the HTML for the missing font message
     message:    
       '<B>No TeX fonts found</B> -- using image fonts instead.<BR>\n'
         + 'These may be slow and might not print well.<BR>\n'
         + 'Use the jsMath control panel to get additional information.',
         
     extra_message:
       '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'
         + 'Use the jsMath control panel to get additional information.',
     
     /*
      *  Look to see if a font is found.  HACK!
      *  Check the character in a given position, and see if it is
      *  wider than the usual one in that position.
      */
     Test1: function (name,n,factor) {
       if (n == null) {n = 124}; if (factor == null) {factor = 2}
       var wh1 = jsMath.BBoxFor('<SPAN STYLE="font-family: '+name+', serif">'+jsMath.TeX[name][n].c+'</SPAN>');
       var wh2 = jsMath.BBoxFor('<SPAN STYLE="font-family: serif">'+jsMath.TeX[name][n].c+'</SPAN>');
       //alert([wh1.w,wh2.w,wh1.h,factor*wh2.w]);
       return (wh1.w > factor*wh2.w && wh1.h != 0);
     },
   
     Test2: function (name,n,factor) {
       if (n == null) {n = 124}; if (factor == null) {factor = 2}
       var wh1 = jsMath.BBoxFor('<SPAN STYLE="font-family: '+name+', serif">'+jsMath.TeX[name][n].c+'</SPAN>');
       var wh2 = jsMath.BBoxFor('<SPAN STYLE="font-family: serif">'+jsMath.TeX[name][n].c+'</SPAN>');
       //alert([wh2.w,wh1.w,wh1.h,factor*wh1.w]);
       return (wh2.w > factor*wh1.w && wh1.h != 0);
     },
     
     /*
      *  Check for the availability of TeX fonts.  We do this by looking at
      *  the width and height of a character in the cmex10 font.  The cmex10
      *  font has depth considerably greater than most characters' widths (the
      *  whole font has the depth of the character with greatest depth).  This
      *  is not the case for most fonts, so if we can access cmex10, the
      *  height of a character should be much bigger than the width.
      *  Otherwise, if we don't have cmex10, we'll get a character in another
      *  font with normal height and width.  In this case, we insert a message
      *  pointing the user to the jsMath site, and load one of the fallback
      *  definitions.
      *  
      */
     Check: function () {
       var cookie = jsMath.Controls.cookie;
       var wh = jsMath.BBoxFor('<SPAN STYLE="font-family: cmex10">'+jsMath.TeX.cmex10[1].c+'</SPAN>');
       jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10'));
       if (jsMath.nofonts) {
         if (cookie.autofont || cookie.font == 'tex') {
           cookie.font = this.fallback;
           if (cookie.warn) {
             jsMath.nofontMessage = 1;
             cookie.warn = 0; jsMath.Controls.SetCookie(0);
             if (window.NoFontMessage) {window.NoFontMessage()}
                                  else {this.Message(this.message)}
           }
         }
     } else {      } else {
       jsMath.Box.DelimExtend = jsMath.Box.DelimExtendRelative;        if (cookie.autofont) {cookie.font = 'tex'}
       jsMath.Box.Layout = jsMath.Box.LayoutRelative;        if (cookie.font == 'tex') return;
     }      }
           if (jsMath.noImgFonts) {cookie.font = 'unicode'}
     if (this.separateNegativeSkips) {      if (cookie.font == 'unicode') {
       jsMath.HTML.Place = jsMath.HTML.PlaceSeparateNegative;        var platform = ({Win32: 'pc', MacPPC: 'mac'})[navigator.platform] || 'unix';
       jsMath.Typeset.prototype.Place = jsMath.Typeset.prototype.PlaceSeparateNegative;        jsMath.Setup.Script('jsMath-fallback-'+platform+'.js');
     } else if (this.separateSkips) {        return;
       jsMath.HTML.Place = jsMath.HTML.PlaceSeparateSkips;  
       jsMath.Typeset.prototype.Place = jsMath.Typeset.prototype.PlaceSeparateSkips;  
     }      }
           if (cookie.font == 'symbol') {
     if (this.noEmptySpans) {jsMath.HTML.Spacer = jsMath.HTML.SpacerImage}        jsMath.Setup.Script('jsMath-fallback-symbols.js');
         return;
       }
       jsMath.Img.SetFont({
         cmr10:  ['all'], cmmi10: ['all'], cmsy10: ['all'],
         cmex10: ['all'], cmbx10: ['all'], cmti10: ['all']
       });
       jsMath.Img.LoadFont('cm-fonts');
     },
   
     /*
      *  The message for when no TeX fonts.  You can eliminate this message
      *  by including
      *  
      *      <SCRIPT>jsMath = {Font: {Message: function () {}}}</SCRIPT>
      *
      *  in your HTML file, before loading jsMath.js, if you want.  But this
      *  means the user may not know that he or she can get a better version
      *  of your page.
      */
     Message: function (message) {
       if(jsMath.Element("Warning")) return;
       var div = jsMath.Setup.TopHTML("Warning",{'class':'jsM_Warning'},{});
       div.innerHTML = 
         '<CENTER><TABLE><TR><TD>'
         + '<DIV CLASS="jsM_noFont">' + message
         + '<DIV STYLE="text-align:left"><SPAN STYLE="float:left; margin: 8px 0px 0px 20px">'
         + '<A HREF="javascript:jsMath.Controls.Panel()" CLASS="jsM_fontLink">jsMath Control Panel</A>'
         + '</SPAN><SPAN STYLE="margin: 8px 20px 0px 0px; float:right">'
         + '<A HREF="javascript:jsMath.Font.HideMessage()" CLASS="jsM_fontLink">Hide this Message</A>'
         + '</SPAN></DIV><BR CLEAR="ALL"></DIV>'
         + '<DIV STYLE="width:22em; height:1px"></DIV>'
         + '</TD></TR></TABLE></CENTER><HR>';
     },
     
     HideMessage: function () {
       var message = jsMath.Element("Warning");
       if (message) {message.style.display = "none"}
   },    },
       
   /*    /*
    *  Define some styles     *  Register an extra font so jsMath knows about it
      */
     Register: function (data) {
       if (typeof(data) == 'string') {data = {name: data}}
       var fontname = data.name; var name = fontname.replace(/10$/,'');
       var fontfam = jsMath.TeX.fam.length;
       if (!data.style) {data.style = "font-family: "+fontname+", serif"}
       if (!data.styles) {data.styles = {}}
       if (!data.macros) {data.macros = {}}
       /*
        *  Register font family
        */
       jsMath.TeX.fam[fontfam] = fontname;
       data.macros[name] = ['HandleFont',fontfam];
       jsMath.Add(jsMath.Parser.prototype.macros,data.macros);
       /*
        *  Set up styles
        */
       data.styles['.'+fontname] = data.style;
       jsMath.Setup.Styles(data.styles);
       jsMath.Setup.TeXfont(fontname);
       /*
        *  Check for font and give message if missing
        */
       var hasTeXfont = !jsMath.nofonts &&
                         data.test(fontname,data.testChar,data.testFactor);
       if (hasTeXfont && jsMath.Controls.cookie.font == 'tex') {
         if (data.tex) {data.tex(fontname,fontfam)}
         return;
       }
       if (!hasTeXfont && jsMath.Controls.cookie.warn &&
           jsMath.Controls.cookie.font == 'tex' && !jsMath.nofonts) {
         if (!jsMath.Element("Warning")) this.Message(this.extra_message);
         var extra = jsMath.Element("ExtraFonts");
         if (extra) {
           if (extra.innerHTML != "") {extra.innerHTML += ','}
           extra.innerHTML += " " + fontname;
         }
       }
       if (jsMath.Controls.cookie.font == 'unicode') {
         if (data.fallback) {data.fallback(fontname,fontfam)}
         return;
       }
       //  Image fonts
       var font = {}; font[fontname] = ['all'];
       jsMath.Img.SetFont(font);
       jsMath.Img.LoadFont(fontname);
     },
   
     /*
      *  Load a font
    */     */
   WriteStyles: function (styles) {    Load: function (name) {jsMath.Setup.Script("fonts/"+name+"/def.js")}
     document.writeln('<STYLE TYPE="text/css">');    
     for (var id in styles) {document.writeln('  '+id+'  {'+styles[id]+'}')}  };
     document.writeln('</STYLE>');  
   /***************************************************************************/
   
   /*
    *  Implements the jsMath control panel.
    *  Much of the code is in jsMath-controls.html, which is
    *  loaded into a hidden IFRAME on demand
    */
   jsMath.Controls = {
   
     //  Data stored in the jsMath cookie
     cookie: {
       scale: 100,
       font: 'tex', autofont: 1, scaleImg: 0, alpha: 1,
       warn: 1, button: 1,
       print: 0, keep: '0D'
   },    },
       
     cookiePath: '/',  // can also set cookieDomain
     
     
   /*    /*
    *  Send the style definitions to the browser (these may be adjusted     *  Load the control panel
    *  by the browser-specific code)  
    */     */
   InitStyles: function () {this.WriteStyles(this.styles)},    Panel: function () {
       if (!this.panel) {this.panel = jsMath.Element("Controls")}
       if (this.loaded) {this.Main()} else {
         this.openMain = 1;
         if (!this.iframe) {this.iframe = jsMath.Element("Frame")}
         this.iframe.src = jsMath.root+"jsMath-controls.html";
       }
     },
       
   /*    /*
    *  Update specific parameters for a limited number of font entries     *  Create the control panel button
    */     */
   UpdateTeXfonts: function (change) {    Button: function () {
     for (var font in change) {      var button = jsMath.Setup.TopHTML("jsMath",{'class':'jsM_button'},{});
       for (var code in change[font]) {      button.innerHTML = 
         for (var id in change[font][code]) {        '<A HREF="javascript:jsMath.Controls.Panel()" '+
           this.TeX[font][code][id] = change[font][code][id];           'STYLE="text-decoration:inherit; color:inherit">' +
         }        '<SPAN TITLE="Open jsMath Control Panel">jsMath</SPAN></A>'
       if (!this.cookie.button) {button.style.display = "none"}
     },
     
    /*
     *  MSIE doesn't implement position:fixed, so redraw the button on scrolls.
     */
     MoveButton: function () {
       if (!this.button) {this.button = jsMath.Element("jsMath")}
       this.button.style.visibility = "hidden";
       this.button.style.visibility = "visible";
     },
   
     /*
      *  Create the HTML needed for control panel
      */
     Init: function () {
       this.document = document;
       this.panel = jsMath.Setup.TopHTML("Controls", {'class':"jsM_panel"},{display:'none'});
       if (!jsMath.Browser.msieButtonBug) {this.Button()}
         else {setTimeout("jsMath.Controls.Button()",500)}
       if (jsMath.Browser.safariIFRAMEbug) {
         document.write(
            '<IFRAME SRC="'+jsMath.root+'jsMath-controls.html" '
            + 'ID="jsMath.Frame" SCROLLING="no" '
            + 'STYLE="visibility:hidden; position:absolute; width:1em; height:1em;">'
            + '</IFRAME>\n');
         return;
       }
       try {
         var frame = document.createElement('iframe');
         frame.setAttribute('scrolling','no');
         frame.style.border = '0px';
         frame.style.width  = '0px';
         frame.style.height = '0px';
         document.body.insertBefore(frame,this.panel);
         this.iframe = frame;
       } catch (err) {
         document.write('<IFRAME SRC="" ID="jsMath.Frame" SCROLLING="no" '
            + 'STYLE="visibility:hidden; position:absolute; width:1em; height:1em;">'
            + '</IFRAME>\n');
       }
     },
   
     /*
      *  Get the cookie data from the browser
      *  (for file: references, use url '?' syntax)
      */
     GetCookie: function () {
       var cookies = document.cookie;
       if (window.location.protocol == 'file:') 
         {cookies = unescape(window.location.search.substr(1))}
       if (cookies.match(/jsMath=([^;]*)/)) {
         var data = RegExp.$1.split(/,/);
         for (var i = 0; i < data.length; i++) {
           var x = data[i].match(/(.*):(.*)/);
           if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string
           this.cookie[x[1]] = x[2];
       }        }
     }      }
   },    },
       
   /*    /*
    *  Update the character code for every character in a list     *  Save the cookie data in the browser
    *  of fonts     *  (for file: urls, append data like CGI reference)
    */     */
   UpdateTeXfontCodes: function (change) {    SetCookie: function (warn) {
     for (var font in change) {      var cookie = [];
       for (var i = 0; i < change[font].length; i++) {      for (var id in this.cookie) {cookie[cookie.length] = id + ':' + this.cookie[id]}
         this.TeX[font][i].c = change[font][i];      cookie = cookie.join(',');
       if (window.location.protocol == 'file:') {
         if (!warn) return;
         this.loaded = 0;
         var href = window.location.href;
         href = href.replace(/\?.*/,"") + '?jsMath=' + escape(cookie);
         if (href != window.location.href) {window.location.replace(href)}
       } else {
         if (this.cookiePath) {cookie += '; path='+this.cookiePath}
         if (this.cookieDomain) {cookie += '; domain='+this.cookieDomain}
         if (this.cookie.keep != '0D') {
           var ms = {
             D: 1000*60*60*24,
             W: 1000*60*60*24*7,
             M: 1000*60*60*24*30,
             Y: 1000*60*60*24*365
           };
           var exp = new Date;
           exp.setTime(exp.getTime() +
               this.cookie.keep.substr(0,1) * ms[this.cookie.keep.substr(1,1)]);
           cookie += '; expires=' + exp.toGMTString();
       }        }
         document.cookie = 'jsMath='+cookie;
         var cookies = document.cookie;
         if (warn && !cookies.match(/jsMath=/))
           {alert("Cookies must be enabled in order to save jsMath options")}
       }
     }
   
   };
   
   /***************************************************************************/
   
   /*
    *  Implements the actions for clicking and double-clicking
    *  on math formulas
    */
   jsMath.Click = {
     
     dragging: 0,
     
     /*
      *  Create the hidden DIV used for the tex source window
      */
     Init: function () {
       this.source = jsMath.Setup.TopHTML("Source",{'class':'jsM_float'},{display:'none'});
       this.source.innerHTML =
         '<DIV CLASS="jsM_drag"><DIV CLASS="jsM_close"></DIV></DIV>'
         + '<DIV CLASS="jsM_source"><SPAN></SPAN></DIV>';
       this.drag = this.source.firstChild;
       this.tex  = this.drag.nextSibling.firstChild;
       this.drag.firstChild.onclick = jsMath.Click.CloseSource;
       this.drag.onmousedown = jsMath.Click.StartDragging;
       this.drag.ondragstart = jsMath.Click.False;
       this.drag.onselectstart = jsMath.Click.False;
       this.source.onclick = jsMath.Click.CheckClose;
     },
     False: function () {return false},
   
     /*
      *  Handle clicking on math to get control panel
      */
     CheckClick: function (event) {
       if (!event) {event = window.event}
       if (event.altKey) jsMath.Controls.Panel();
     },
     
     /*
      *  Handle double-click for seeing TeX code
      */
     CheckDblClick: function (event) {
       if (!event) {event = window.event}
       var event = jsMath.Click.Event(event);
   
       var source = jsMath.Click.source
       var tex = jsMath.Click.tex;
   
       source.style.visibility = 'hidden';
       source.style.display = ''; source.style.width = '';
       source.style.left = ''; source.style.top = '';
       tex.innerHTML = '';
   
       var TeX = this.alt;
       TeX = TeX.replace(/^\s+|\s+$/g,'');
       TeX = TeX.replace(/&/g,'&amp;');
       TeX = TeX.replace(/</g,'&lt;');
       TeX = TeX.replace(/>/g,'&gt;');
       TeX = TeX.replace(/\n/g,'<BR>');
       tex.innerHTML = TeX;
   
       var h = source.offsetHeight; var w;
       if (jsMath.Browser.msieDivWidthBug) {
         tex.className = 'jsM_source';      // Work around MSIE bug where
         w = tex.offsetWidth + 5;           // DIV's don't collapse to
         tex.className = '';                // their natural widths
       } else {
         w = source.offsetWidth;
     }      }
       w = Math.max(50,Math.min(w,.8*event.W,event.W-40));
       var x = Math.floor(event.x-w/2); var y = Math.floor(event.y-h/2);
       x = event.X + Math.max(Math.min(x,event.W-w-20),20);
       y = event.Y + Math.max(Math.min(y,event.H-h-5),5);
   
       source.style.left = x+'px'; source.style.top = y+'px';
       source.style.width = w+'px';
       source.style.visibility = '';
       jsMath.Click.left = x + event.X; jsMath.Click.top = y + event.Y;
       jsMath.Click.w = w; jsMath.Click.h = source.offsetHeight;
   
       jsMath.Click.DeselectText(x,y);
       return false;
     },
   
     /*
      *  Get window width, height, and offsets plus
      *  position of pointer relative to the window
      */
     Event: function (event) {
       var W = window.innerWidth  || document.body.clientWidth;
       var H = window.innerHeight || document.body.clientHeight;
       var X = window.pageXOffset; var Y = window.pageYOffset;
       if (X == null) {X = document.body.clientLeft; Y = document.body.clientTop}
       var x = event.pageX; var y = event.pageY;
       if (x == null) {
         x = event.clientX; y = event.clientY;
         if (jsMath.browser == 'MSIE' && document.compatMode == 'CSS1Compat') {
           X = document.documentElement.scrollLeft;
           Y = document.documentElement.scrollTop;
           W = document.documentElement.clientWidth;
           H = document.documentElement.clientHeight;
         } else {
           X = document.body.scrollLeft;
           Y = document.body.scrollTop;
         }
       } else {x -= X; y -= Y}
   
       return {x: x, y: y, W: W, H: H, X: X, Y: Y};
   },    },
       
   /*    /*
    *  Add a collection of styles to the style list     *  Unselect whatever text is selected (since double-clicking
      *  usually selects something)
    */     */
   UpdateStyles: function (styles) {    DeselectText: function (x,y) {
     for (var i in styles) {this.styles[i] = styles[i]}      if (window.getSelection && window.getSelection().removeAllRanges)
         {window.getSelection().removeAllRanges()}
       else if (document.getSelection && document.getSelection().removeAllRanges)
         {document.getSelection().removeAllRanges()}
       else if (document.selection && document.selection.empty)
         {document.selection.empty()}
       else {
         /* Hack to deselect the text in Opera and Safari */
         if (jsMath.browser == 'MSIE') return;  // don't try it if MISE on Mac
         jsMath.hiddenTop.innerHTML =
           '<textarea style="visibility:hidden" ROWS="1" COLS="1">a</textarea>';
         jsMath.hiddenTop.firstChild.style.position = 'absolute';
         jsMath.hiddenTop.firstChild.style.left = x+'px';
         jsMath.hiddenTop.firstChild.style.top  = y+'px';
         setTimeout(jsMath.Click.SelectHidden,1);
       }
     },
     SelectHidden: function () {
       jsMath.hiddenTop.firstChild.focus();
       jsMath.hiddenTop.firstChild.select();
       jsMath.hiddenTop.innerHTML = '';
   },    },
   
   /*    /*
    *  Manage JavaScript objects:     *  Close the TeX source window
    *    
    *      Add:      simply add items to an object  
    *      Package:  add items to an object prototype  
    */     */
   Add: function (obj,def) {for (var id in def) {obj[id] = def[id]}},    CloseSource: function () {
   Package: function (obj,def) {this.Add(obj.prototype,def)}      jsMath.Click.tex.innerHTML = '';
       jsMath.Click.source.style.display = 'none';
       jsMath.Click.source.style.visibility = 'hidden';
       jsMath.Click.StopDragging();
       return false;
     },
     CheckClose: function (event) {
       if (!event) {event = window.event}
       if (event.altKey) {jsMath.Click.CloseSource(); return false}
     },
       
 }    /*
      *  Set up for dragging the source panel
      */
     StartDragging: function (event) {
       if (!event) {event = window.event}
       if (jsMath.Click.dragging) {jsMath.Click.StopDragging(event)}
       var event = jsMath.Click.Event(event);
       jsMath.Click.dragging = 1;
       jsMath.Click.x = event.x + 2*event.X - jsMath.Click.left;
       jsMath.Click.y = event.y + 2*event.Y - jsMath.Click.top;
       jsMath.Click.oldonmousemove = document.body.onmousemove;
       jsMath.Click.oldonmouseup = document.body.onmouseup;
       document.body.onmousemove = jsMath.Click.DragSource;
       document.body.onmouseup = jsMath.Click.StopDragging;
       return false;
     },
     
     /*
      *  Stop dragging the source window
      */
     StopDragging: function (event) {
       if (jsMath.Click.dragging) {
         document.body.onmousemove = jsMath.Click.oldonmousemove;
         document.body.onmouseup   = jsMath.Click.oldonmouseup;
         jsMath.Click.oldonmousemove = null;
         jsMath.Click.oldonmouseup   = null;
         jsMath.Click.dragging = 0;
       }
       return false;
     },
     
     /*
      *  Move the source window (but stay within the browser window)
      */
     DragSource: function (event) {
       if (!event) {event = window.event}
       if (jsMath.Browser.buttonCheck && !event.button) {return jsMath.Click.StopDragging(event)}
       event = jsMath.Click.Event(event);
       var x = event.x + event.X - jsMath.Click.x;
       var y = event.y + event.Y - jsMath.Click.y;
       x = Math.max(event.X,Math.min(event.W+event.X-jsMath.Click.w,x));
       y = Math.max(event.Y,Math.min(event.H+event.Y-jsMath.Click.h,y));
       jsMath.Click.source.style.left = x + 'px';
       jsMath.Click.source.style.top  = y + 'px';
       jsMath.Click.left = x + event.X; jsMath.Click.top = y + event.Y;
       return false;
     }
   
   };
   
 /***************************************************************************/  /***************************************************************************/
   
 jsMath.Add(jsMath.TeX,{  /*
    *  The TeX font information
    */
   jsMath.TeX = {
   
     //
     //  The TeX font parameters
     //
     thinmuskip:   3/18,
     medmuskip:    4/18,
     thickmuskip:  5/18,
   
     x_height:    .430554,
     quad:        1,
     num1:        .676508,
     num2:        .393732,
     num3:        .44373,
     denom1:      .685951,
     denom2:      .344841,
     sup1:        .412892,
     sup2:        .362892,
     sup3:        .288888,
     sub1:        .15,
     sub2:        .247217,
     sup_drop:    .386108,
     sub_drop:    .05,
     delim1:     2.39,
     delim2:     1.0,
     axis_height: .25,
     default_rule_thickness: .04,
     big_op_spacing1:  .111111,
     big_op_spacing2:  .166666,
     big_op_spacing3:  .2,
     big_op_spacing4:  .6,
     big_op_spacing5:  .1,
   
     integer:          6553.6,     // conversion of em's to TeX internal integer
     scriptspace:         .05,
     nulldelimiterspace:  .12,
     delimiterfactor:     901,
     delimitershortfall:   .5,
     scale:                 1,     //  scaling factor for font dimensions
    
   //  The TeX math atom types (see Appendix G of the TeXbook)    //  The TeX math atom types (see Appendix G of the TeXbook)
   atom: ['ord', 'op', 'bin', 'rel', 'open', 'close', 'punct', 'ord'],    atom: ['ord', 'op', 'bin', 'rel', 'open', 'close', 'punct', 'ord'],
   
Line 596  jsMath.Add(jsMath.TeX,{ Line 1341  jsMath.Add(jsMath.TeX,{
    *  The following are the TeX font mappings and metrics.  The metric     *  The following are the TeX font mappings and metrics.  The metric
    *  information comes directly from the TeX .tfm files, and the     *  information comes directly from the TeX .tfm files, and the
    *  character mappings are for the TrueType TeX fonts.  Browser-specific     *  character mappings are for the TrueType TeX fonts.  Browser-specific
    *  adjustments are made to these tables in the InitBrowser() routine     *  adjustments are made to these tables in the Browser.Init() routine
    */     */
   cmr10: [    cmr10: [
     // 00 - 0F      // 00 - 0F
Line 1431  jsMath.Add(jsMath.TeX,{ Line 2176  jsMath.Add(jsMath.TeX,{
     {c: '&#x7E;', h: 0.694, w: 0.575},      {c: '&#x7E;', h: 0.694, w: 0.575},
     {c: '&#xC4;', h: 0.694, w: 0.575}      {c: '&#xC4;', h: 0.694, w: 0.575}
   ]    ]
 });  };
   
   /***************************************************************************/
   
   /*
    *  Implement image-based fonts for fallback method
    */
   jsMath.Img = {
     
     // font sizes available
     fonts: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249, 298, 358, 430],
       
     // em widths for the various font size directories
     w: {'50': 6.9, '60': 8.3, '70': 9.7, '85': 11.8, '100': 13.9,
         '120': 16.7, '144': 20.0, '173': 24.0, '207': 28.8, '249': 34.6,
         '298': 41.4, '358': 49.8, '430': 59.8},
           
     // index of best font size in the fonts list
     best: 4,
       
     // fonts to update (see UpdateFonts below)
     update: {},
       
     // factor by which to shrink images (for better printing)
     factor: 1,
     
     // image fonts are loaded
     loaded: 0,
     
     // add characters to be drawn using images
     SetFont: function (change) {
       for (var font in change) {
         if (!this.update[font]) {this.update[font] = []}
         this.update[font] = this.update[font].concat(change[font]);
       }
     },
   
     /*
      *  Called by the exta-font definition files to add an image font
      *  into the mix
      */
     AddFont: function (size,def) {
       if (!jsMath.Img[size]) {jsMath.Img[size] = {}};
       jsMath.Add(jsMath.Img[size],def);
     },
       
     /*
      *  Update font(s) to use image data rather than native fonts
      *  It looks in the jsMath.Img.update array to find the names
      *  of the fonts to udpate, and the arrays of character codes
      *  to set (or 'all' to change every character);
      */
     UpdateFonts: function () {
       var change = this.update; if (!this.loaded) return;
       var best = this[jsMath.Img.fonts[this.best]];
       for (var font in change) {
         for (var i = 0; i < change[font].length; i++) {
           var c = change[font][i];
           if (c == 'all') {for (c in jsMath.TeX[font]) {jsMath.TeX[font][c].img = {}}}
             else {jsMath.TeX[font][c].img = {}}
         }
       }
       this.update = {};
     },
     
     /*
      *  Find the font size that best fits our current font
      *  (this is the directory name for the img files used
      *  in some fallback modes).
      */
     BestSize: function () {
       var w = jsMath.em * this.factor;
       var m = this.w[this.fonts[0]];
       for (var i = 1; i < this.fonts.length; i++) {
         if (w < (this.w[this.fonts[i]] + 2*m) / 3) {return i-1}
         m = this.w[this.fonts[i]];
       }
       return i-1;
     },
   
     /*
      *  Get the scaling factor for the image fonts
      */
     Scale: function () {
       if (!this.loaded) return;
       this.best = this.BestSize();
       this.em = jsMath.Img.w[this.fonts[this.best]];
       this.scale = (jsMath.em/this.em);
       if (Math.abs(this.scale - 1) < .12) {this.scale = 1}
     },
   
     /*
      *  Get URL to directory for given font and size, based on the
      *  user's alpha/plain setting
      */
     URL: function (name,size,C) {
       var type = (jsMath.Controls.cookie.alpha) ? '/alpha/': '/plain/';
       if (C == null) {C = "def.js"} else {C = 'char'+C+'.png'}
       if (size != "") {size += '/'}
       return this.root+name+type+size+C;
     },
   
     /*
      *  Laod the data for an image font
      */
     LoadFont: function (name) {
       if (jsMath.Controls.cookie.print) {
         jsMath.Controls.cookie.print = 0;
         var button = jsMath.Element("jsMath");
         if (button) {button.style.display = "none"}
         this.factor *= 3;
         if (window.location.protocol != 'file:') {jsMath.Controls.SetCookie(0)}
         if (jsMath.Browser.alphaPrintBug) {jsMath.Controls.cookie.alpha = 0}
       }
       document.writeln('<SCRIPT SRC="'+this.URL(name,"")+'"></SCRIPT>');
       this.loaded = 1;
     }
     
   };
   
 /***************************************************************************/  /***************************************************************************/
   
Line 1459  jsMath.HTML = { Line 2322  jsMath.HTML = {
    */     */
   Spacer: function (w) {    Spacer: function (w) {
     if (w == 0) {return ''};      if (w == 0) {return ''};
     return jsMath.msieSpaceFix      return jsMath.Browser.msieSpaceFix
       + '<SPAN STYLE="margin-left: '+this.Em(w)+'"></SPAN>';        + '<SPAN STYLE="margin-left: '
   },        +    this.Em(w-jsMath.Browser.spaceWidth)+'">'
         + jsMath.Browser.hiddenSpace + '</SPAN>';
   /*  
    *  Use an image to create a horizontal space of width w  
    */  
   SpacerImage: function (w) {  
     if (w == 0) {return ''};  
     return '<IMG SRC="'+jsMath.blank+'" STYLE="'  
              + ' width: 0; margin-left: '+this.Em(w)+'">';  
   },    },
   
   /*    /*
Line 1485  jsMath.HTML = { Line 2341  jsMath.HTML = {
              {pos = 'relative; margin-right: '+this.Em(-(w+2/jsMath.em))+'; '}               {pos = 'relative; margin-right: '+this.Em(-(w+2/jsMath.em))+'; '}
     return '<IMG SRC="'+jsMath.blank+'" STYLE="position:' + pos      return '<IMG SRC="'+jsMath.blank+'" STYLE="position:' + pos
              + 'vertical-align: '+this.Em(y)+'; left: '+this.Em(x)+'; '               + 'vertical-align: '+this.Em(y)+'; left: '+this.Em(x)+'; '
              + 'width:'+this.Em(w)+'; height: '+this.Em(h)+'; '               + 'width:' +this.Em(w*jsMath.Browser.imgScale)+'; '
              + 'border-color: '+c+'; border-style: solid; border-width: 1px;">';               + 'height:'+this.Em(h*jsMath.Browser.imgScale)+'; '
   },               + 'border: 1px solid '+c+';">';
   
   /*  
    *  Create a 1-pixel-high horizontal line at a particular  
    *  position, width and color.  
    */  
   Line: function (x,y,w,c,pos) {  
     if (!c) {c = 'black'};  
     if (pos) {pos = 'absolute;'} else  
              {pos = 'relative; margin-right: '+this.Em(-w)+'; '}  
     return '<IMG SRC="'+jsMath.blank+'" STYLE="position:'+pos  
              + 'top: '+this.Em(-y)+'; left:'+this.Em(x)+'; '  
              + 'width:'+this.Em(w)+'; height:1px; background-color: '+c+';">';  
   },    },
   
   /*    /*
    *  Create a black rule line for fractions, etc.     *  Create a rule line for fractions, etc.
    *  Height is converted to pixels (with a minimum of 1), so that     *  Height is converted to pixels (with a minimum of 1), so that
    *    the line will not disappear at small font sizes.  This means that     *    the line will not disappear at small font sizes.  This means that
    *    the thickness will not change if you change the font size, or     *    the thickness will not change if you change the font size, or
Line 1512  jsMath.HTML = { Line 2356  jsMath.HTML = {
   Rule: function (w,h) {    Rule: function (w,h) {
     if (h == null) {h = jsMath.TeX.default_rule_thickness}      if (h == null) {h = jsMath.TeX.default_rule_thickness}
     if (w == 0 || h == 0) return;  // should make an invisible box?      if (w == 0 || h == 0) return;  // should make an invisible box?
     h = Math.round(h*jsMath.em);      w *= jsMath.Browser.imgScale;
     if (h < 1) {h = 1}      h = Math.round(h*jsMath.em*jsMath.Browser.imgScale+.25);
     return '<IMG SRC="'+jsMath.black+'" HSPACE="0" VSPACE="0" '      if (h < 1) {h = 1};
               + 'STYLE="width:'+this.Em(w)+'; height: '+h+'px">';  
   },  
   
   /*  
    *  Create a colored block of a specific size (won't always print  
    *  correctly).  
    */  
   Block: function (w,h,c) {  
     if (c == null) {c = 'black'}  
     return '<IMG SRC="'+jsMath.blank+'" HSPACE="0" VSPACE="0" '      return '<IMG SRC="'+jsMath.blank+'" HSPACE="0" VSPACE="0" '
             +      'STYLE="width:'+this.Em(w)+'; height: '+this.Em(h)+'; '                + 'STYLE="width:'+this.Em(w)+'; height:1px; '
             +      'background-color: '+c+'">';                + 'vertical-align:-1px; '
                 + 'border:0px none; border-top:'+h+'px solid">';
   },    },
     
   /*    /*
    *  Add a <SPAN> tag to activate a specific CSS class     *  Add a <SPAN> tag to activate a specific CSS class
    */     */
Line 1555  jsMath.HTML = { Line 2391  jsMath.HTML = {
       
   /*    /*
    *  For MSIE on Windows, backspacing must be done in a separate     *  For MSIE on Windows, backspacing must be done in a separate
    *  <SPAN>, otherwise the contents will be clipped.     *  <SPAN>, otherwise the contents will be clipped.  Netscape
    */     *  also doesn't combine vertical and horizontal spacing well.
   PlaceSeparateNegative: function (html,x,y) {     *  Here the x and y positioning are done in separate <SPAN> tags
     if (Math.abs(x) < .0001) {x = 0}  
     if (Math.abs(y) < .0001) {y = 0}  
     if (x > 0 || y) {  
       var span = '<SPAN STYLE="position: relative;';  
       if (x > 0) {span += ' margin-left:'+this.Em(x)+';'}  
       if (y) {span += ' top:'+this.Em(-y)+';'}  
       html = span + '">' + html + '</SPAN>';  
     }  
     if (x < 0) {  
       html = jsMath.msieSpaceFix  
                + '<SPAN STYLE="margin-left:'+this.Em(x)+';"></SPAN>' + html;  
     }  
     return html;  
   },  
   
   /*  
    *  Here the x and y positioning is done in separate <SPAN> tags  
    */     */
   PlaceSeparateSkips: function (html,x,y) {    PlaceSeparateSkips: function (html,x,y) {
     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 STYLE="position: relative; top:'+this.Em(-y)+';'
                        + '">' + html + '</SPAN>'}                         + '">' + html + '</SPAN>'}
     if (x) {html = jsMath.msieSpaceFix       if (x) {html = jsMath.Browser.msieSpaceFix 
                        + '<SPAN STYLE="margin-left:'+this.Em(x)+';"></SPAN>' + html}                         + '<SPAN STYLE="margin-left:'
                          +    this.Em(x-jsMath.Browser.spaceWidth)+';">'
                          +  jsMath.Browser.hiddenSpace + '</SPAN>' + html}
     return html;      return html;
   },    },
       
Line 1600  jsMath.HTML = { Line 2421  jsMath.HTML = {
   
   Absolute: function(html,w,h,d,y,H) {    Absolute: function(html,w,h,d,y,H) {
     var align = "";      var align = "";
     if (d) {align = ' vertical-align: '+jsMath.HTML.Em(-d)+';'}      if (d && d != "none") {align = ' vertical-align: '+jsMath.HTML.Em(-d)+';'}
     if (y != "none") {      if (y != "none") {
       if (Math.abs(y) < .0001) {y = 0}        if (Math.abs(y) < .0001) {y = 0}
       html = '<SPAN STYLE="position: absolute; '        html = '<SPAN STYLE="position: absolute; '
Line 1608  jsMath.HTML = { Line 2429  jsMath.HTML = {
                + html + '&nbsp;' // space normalizes line height in script styles                 + html + '&nbsp;' // space normalizes line height in script styles
              + '</SPAN>';               + '</SPAN>';
     }      }
     html += '<IMG SRC="'+jsMath.blank+'" STYLE="width: '+jsMath.HTML.Em(w)+'; '      html += '<IMG SRC="'+jsMath.blank+'" STYLE="'
                         + 'height: '+jsMath.HTML.Em(h)+';'+align+'">';                + 'width:' +jsMath.HTML.Em(w*jsMath.Browser.imgScale)+'; '
     if (jsMath.msieAbsoluteBug) {// for MSIE (Mac)                + 'height:'+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+';'+align+'">';
       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;'      html =   '<SPAN STYLE="position: relative;'
            +     ' width: '+jsMath.HTML.Em(w)+';'       // for MSIE             +     ' width: '+jsMath.HTML.Em(w)+';'   // for MSIE
            +     ' height: '+jsMath.HTML.Em(H)+';'  // for MSIE             +     ' height: '+jsMath.HTML.Em(H)+';'  // for MSIE
              +     jsMath.Browser.msieInlineBlockFix  // for MSIE
            +     '">'             +     '">'
            +   html             +   html
            + '</SPAN>';             + '</SPAN>';
Line 1671  jsMath.Add(jsMath.Box,{ Line 2494  jsMath.Add(jsMath.Box,{
    *  The box is a text box (like the ones above), so that characters from     *  The box is a text box (like the ones above), so that characters from
    *  the same font can be combined.     *  the same font can be combined.
    */     */
   TeX: function (c,font,style,size) {    TeX: function (C,font,style,size) {
     c = jsMath.TeX[font][c];      var c = jsMath.TeX[font][C];
     if (c.d == null) {c.d = 0}; if (c.h == null) {c.h = 0}      if (c.d == null) {c.d = 0}; if (c.h == null) {c.h = 0}
       if (c.img != null && c.c != '') this.TeXIMG(font,C,jsMath.Typeset.StyleSize(style,size));
     var scale = jsMath.Typeset.TeX(style,size).scale;      var scale = jsMath.Typeset.TeX(style,size).scale;
     var h = c.h + jsMath.TeX[font].dh      var h = c.h + jsMath.TeX[font].dh
     var box = new jsMath.Box('text',c.c,c.w*scale,h*scale,c.d*scale);      var box = new jsMath.Box('text',c.c,c.w*scale,h*scale,c.d*scale);
Line 1686  jsMath.Add(jsMath.Box,{ Line 2510  jsMath.Add(jsMath.Box,{
       box.tclass = font;        box.tclass = font;
       box.bh = scale*jsMath.TeX[font].h;        box.bh = scale*jsMath.TeX[font].h;
       box.bd = scale*jsMath.TeX[font].d;        box.bd = scale*jsMath.TeX[font].d;
       if (jsMath.msieFontBug) {        if (jsMath.Browser.msieFontBug) {
         // 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>'
       }        }
     }      }
       if (c.img != null) {
         box.bh = c.img.bh; box.bd = c.img.bd;
         box.tclass = "normal";
       }
     return box;      return box;
   },    },
     
     /*
      *  Set the character's string to the appropriate image file
      */
     TeXIMG: function (font,C,size) {
       var c = jsMath.TeX[font][C];
       if (c.img.size != null && c.img.size == size &&
           c.img.best != null && c.img.best == jsMath.Img.best) return;
       var mustScale = (jsMath.Img.scale != 1);
       var id = jsMath.Img.best + size - 4;
       if (id < 0) {id = 0; mustScale = 1} else
       if (id >= jsMath.Img.fonts.length) {id = jsMath.Img.fonts.length-1; mustScale = 1}
       var imgFont = jsMath.Img[jsMath.Img.fonts[id]];
       var img = imgFont[font][C];
       var scale = 1/jsMath.Img.w[jsMath.Img.fonts[id]];
       if (id != jsMath.Img.best + size - 4) {
         if (c.w != null) {scale = c.w/img[0]} else {
           scale *= jsMath.Img.fonts[size]/jsMath.Img.fonts[4]
                 *  jsMath.Img.fonts[jsMath.Img.best]/jsMath.Img.fonts[id];
         }
       }
       var w = img[0]*scale; var h = img[1]*scale; var d = -img[2]*scale; var v;
       var wadjust = (c.w == null || Math.abs(c.w-w) < .01)? "" : " margin-right:"+jsMath.HTML.Em(c.w-w)+';';
       var resize = ""; C = this.HexCode(C);
       if (!mustScale && !jsMath.Controls.cookie.scaleImg) {
         if (2*w < h || (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha))
            {resize = "height:"+(img[1]*jsMath.Browser.imgScale)+'px;'}
         resize += " width:"+(img[0]*jsMath.Browser.imgScale)+'px;'
         v = -img[2]+'px';
       } else {
         if (2*w < h || (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha))
            {resize = "height:"+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+';'}
         resize += " width:"+jsMath.HTML.Em(w*jsMath.Browser.imgScale)+';'
         v = jsMath.HTML.Em(d);
       }
       var vadjust = (Math.abs(d) < .01 && !jsMath.Browser.valignBug)?
                            "": " vertical-align:"+v+';';
       var URL = jsMath.Img.URL(font,jsMath.Img.fonts[id],C);
       if (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha) {
         c.c = '<IMG SRC="'+jsMath.blank+'" '
                  + 'STYLE="'+jsMath.Browser.msieCenterBugFix
                  + resize + vadjust + wadjust
                  + ' filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + "'"
                  + URL + "', sizingMethod='scale'" + ');">';
       } else {
         c.c = '<IMG SRC="'+URL+'" STYLE="'+jsMath.Browser.msieCenterBugFix
                     + resize + vadjust + wadjust + '">';
       }
       c.tclass = "normal";
       c.img.bh = h+d; c.img.bd = -d;
       c.img.size = size; c.img.best = jsMath.Img.best;
     },
     
     /*
      *  Get a two-character hex code (some browsers don't know toString(16))
      */
     HexCode: function (C) {
       var codes = '0123456789ABCDEF';
       var h = Math.floor(C/16); var l = C - 16*h;
       return codes.charAt(h)+codes.charAt(l);
     },
   
   /*    /*
    *  A box containing a spacer of a specific width     *  A box containing a spacer of a specific width
Line 1713  jsMath.Add(jsMath.Box,{ Line 2602  jsMath.Add(jsMath.Box,{
   },    },
   
   /*    /*
    *  A box containing a colored block  
    */  
   Block: function (w,h,c) {  
     return new jsMath.Box('html',jsMath.HTML.Block(w,h,c),w,h,0);  
   },  
     
   /*  
    *  Get a character from a TeX font, and make sure that it has     *  Get a character from a TeX font, and make sure that it has
    *  its metrics specified.     *  its metrics specified.
    */     */
   GetChar: function (code,font) {    GetChar: function (code,font) {
     var c = jsMath.TeX[font][code];      var c = jsMath.TeX[font][code];
       if (c.img != null) {this.TeXIMG(font,code,4)}
     if (c.tclass == null) {c.tclass = font}      if (c.tclass == null) {c.tclass = font}
     if (!c.computedW) {      if (!c.computedW) {
       c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w;        c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w;
Line 1856  jsMath.Add(jsMath.Box,{ Line 2739  jsMath.Add(jsMath.Box,{
   Delimiter: function (H,delim,style,nocenter) {    Delimiter: function (H,delim,style,nocenter) {
     var size = 4;  //### pass this?      var size = 4;  //### pass this?
     var TeX = jsMath.Typeset.TeX(style,size);      var TeX = jsMath.Typeset.TeX(style,size);
     var CFSH = this.DelimBestFit(H,(delim&0xFF000)>>12,(delim&0xF00000)>>20,style);      if (!delim) {return this.Space(TeX.nulldelimiterspace)}
       var CFSH = this.DelimBestFit(H,delim[2],delim[1],style);
     if (CFSH == null || CFSH[3] < H)       if (CFSH == null || CFSH[3] < H) 
       {CFSH = this.DelimBestFit(H,(delim&0xFF),(delim&0xF00)>>8,style)}        {CFSH = this.DelimBestFit(H,delim[4],delim[3],style)}
     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)}
Line 1875  jsMath.Add(jsMath.Box,{ Line 2759  jsMath.Add(jsMath.Box,{
    *  is specified.     *  is specified.
    */     */
   GetCharCode: function (code) {    GetCharCode: function (code) {
     var font = jsMath.TeX.fam[(code&0xF00)>>8];      var font = jsMath.TeX.fam[code[0]];
     var Font = jsMath.TeX[font];      var Font = jsMath.TeX[font];
     var c = Font[code & 0xFF];      var c = Font[code[1]];
       if (c.img != null) {this.TeXIMG(font,code[1],4)}
     if (c.w == null) {c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w}      if (c.w == null) {c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w}
     if (c.font == null) {c.font = font}      if (c.font == null) {c.font = font}
     return c;      return c;
Line 1901  jsMath.Add(jsMath.Box,{ Line 2786  jsMath.Add(jsMath.Box,{
   Leaders: function (W,leader) {    Leaders: function (W,leader) {
     var h; var d; var w; var html; var font;      var h; var d; var w; var html; var font;
     if (leader.lmid) {// braces      if (leader.lmid) {// braces
       font = jsMath.TeX.fam[(leader.left & 0xF00) >> 8];        font = jsMath.TeX.fam[leader.left[0]];
       var left = this.GetCharCode(leader.left);        var left = this.GetCharCode(leader.left);
       var right = this.GetCharCode(leader.right);        var right = this.GetCharCode(leader.right);
       var lmid = this.GetCharCode(leader.lmid);        var lmid = this.GetCharCode(leader.lmid);
Line 1914  jsMath.Add(jsMath.Box,{ Line 2799  jsMath.Add(jsMath.Box,{
            + jsMath.HTML.Rule(w,right.h)             + jsMath.HTML.Rule(w,right.h)
            + this.AddClass(right.tclass,right.c,right.font);             + this.AddClass(right.tclass,right.c,right.font);
     } else { //arrows      } else { //arrows
       font = jsMath.TeX.fam[(leader.rep &0xF00) >> 8];        font = jsMath.TeX.fam[leader.rep[0]];
       var left = this.GetCharCode(leader.left? leader.left: leader.rep);        var left = this.GetCharCode(leader.left? leader.left: leader.rep);
       var rep = this.GetCharCode(leader.rep);        var rep = this.GetCharCode(leader.rep);
       var right = this.GetCharCode(leader.right? leader.right: leader.rep);        var right = this.GetCharCode(leader.right? leader.right: leader.rep);
Line 1928  jsMath.Add(jsMath.Box,{ Line 2813  jsMath.Add(jsMath.Box,{
       html += this.AddClass(rep.tclass,ehtml,rep.font) + jsMath.HTML.Spacer(w);        html += this.AddClass(rep.tclass,ehtml,rep.font) + jsMath.HTML.Spacer(w);
       ehtml = ''; for (var i = m; i < n; i++) {ehtml += ext};        ehtml = ''; for (var i = m; i < n; i++) {ehtml += ext};
       html += this.AddClass(rep.tclass,ehtml,rep.font);        html += this.AddClass(rep.tclass,ehtml,rep.font);
       if (jsMath.msieFontBug) {html += '<SPAN STYLE="display: none">x</SPAN>'}        if (jsMath.Browser.msieFontBug) {html += '<SPAN STYLE="display: none">x</SPAN>'}
       html += jsMath.HTML.Place(this.AddClass(right.tclass,right.c,right.font),-.4,0);        html += jsMath.HTML.Place(this.AddClass(right.tclass,right.c,right.font),-.4,0);
     }      }
     w = jsMath.EmBoxFor(html).w;      w = jsMath.EmBoxFor(html).w;
Line 2075  jsMath.Add(jsMath.Box,{ Line 2960  jsMath.Add(jsMath.Box,{
     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(scale/6)+html+jsMath.HTML.Spacer(scale/6);
     if (jsMath.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);      var box = new jsMath.Box('html',html,w+scale/3,h,d);
     return box;      return box;
Line 2085  jsMath.Add(jsMath.Box,{ Line 2970  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) {
     if (!text.match(/\$|\\\(/)) {return this.Text(text,'nonmath','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; var html; var box;
Line 2102  jsMath.Add(jsMath.Box,{ Line 2987  jsMath.Add(jsMath.Box,{
           }            }
           match = ''; k = i;            match = ''; k = i;
         } else {          } else {
           mlist[mlist.length] = this.Text(text.slice(k,i-1),'nonmath','T',size,1,1);            mlist[mlist.length] = this.Text(text.slice(k,i-1),'normal','T',size,1,1);
           match = '$'; k = i;            match = '$'; k = i;
         }          }
       } else if (c == '\\') {        } else if (c == '\\') {
         c = text.charAt(i++);          c = text.charAt(i++);
         if (c == '(' && match == '') {          if (c == '(' && match == '') {
           mlist[mlist.length] = this.Text(text.slice(k,i-2),'nonmath','T',size,1,1);            mlist[mlist.length] = this.Text(text.slice(k,i-2),'normal','T',size,1,1);
           match = ')'; k = i;            match = ')'; k = i;
         } else if (c == ')' && match == ')') {          } else if (c == ')' && match == ')') {
           parse = jsMath.Parse(text.slice(k,i-2),null,size);            parse = jsMath.Parse(text.slice(k,i-2),null,size);
Line 2122  jsMath.Add(jsMath.Box,{ Line 3007  jsMath.Add(jsMath.Box,{
         }          }
       }        }
     }      }
     mlist[mlist.length] = this.Text(text.slice(k),'nonmath','T',size,1,1);      mlist[mlist.length] = this.Text(text.slice(k),'normal','T',size,1,1);
     return this.SetList(mlist,'T',size);      return this.SetList(mlist,'T',size);
   },    },
       
Line 2188  jsMath.Package(jsMath.Box,{ Line 3073  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) {      if (this.w > 0 && !this.html.match(/position: ?absolute/))
       if (!jsMath.spanHeightVaries || !this.html.match(/position: ?absolute/))        {this.w = jsMath.EmBoxFor(this.html).w}
         {this.w = jsMath.EmBoxFor(this.html).w}  
     }  
     return this;      return this;
   }    }
   
Line 2201  jsMath.Package(jsMath.Box,{ Line 3084  jsMath.Package(jsMath.Box,{
 /***************************************************************************/  /***************************************************************************/
   
 /*  /*
  *  mItems are the buiulding blocks of mLists (math lists) used to   *  mItems are the building blocks of mLists (math lists) used to
  *  store the information about a mathematical expression.  These are   *  store the information about a mathematical expression.  These are
  *  basically the items listed in the TeXbook in Appendix G (plus some   *  basically the items listed in the TeXbook in Appendix G (plus some
  *  minor extensions).   *  minor extensions).
Line 2429  jsMath.Package(jsMath.mList,{ Line 3312  jsMath.Package(jsMath.mList,{
   /*    /*
    *  For a list that has boundary delimiters as its first and last     *  For a list that has boundary delimiters as its first and last
    *  entries, we replace the boundary atoms by open and close     *  entries, we replace the boundary atoms by open and close
    *  atoms whose nuclei are the specified delimiters properly sized     *  atoms whose nuclii are the specified delimiters properly sized
    *  for the contents of the list.  (Rule 19)     *  for the contents of the list.  (Rule 19)
    */     */
   AddDelimiters: function(style,size) {    AddDelimiters: function(style,size) {
Line 2656  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3539  jsMath.Add(jsMath.mList.prototype.Atomiz
     var t = TeX.default_rule_thickness;      var t = TeX.default_rule_thickness;
     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,0x270370,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      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;
Line 2665  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3548  jsMath.Add(jsMath.mList.prototype.Atomiz
     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,Cr,size).Remeasured();
     if (mitem.root) {      if (mitem.root) {
       root.y = .55*(box.h+box.d+3*t+r)-box.d; surd.x = -(11/18)*surd.w;        root.y = .55*(box.h+box.d+3*t+r)-box.d;
       root.x = Math.max((11/18)*surd.w - root.w, 0);        surd.x = Math.max(root.w-(11/18)*surd.w,0);
         rule.x = (7/18)*surd.w;
         root.x = -(root.w+rule.x);
     }      }
     mitem.nuc = jsMath.Box.SetList([root,surd,rule,box],style,size);      mitem.nuc = jsMath.Box.SetList([surd,root,rule,box],style,size);
     mitem.type = 'ord';      mitem.type = 'ord';
     jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);      jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
   },    },
Line 2688  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3573  jsMath.Add(jsMath.mList.prototype.Atomiz
     }      }
     if (s == null) {s = 0}      if (s == null) {s = 0}
           
     var c = mitem.accent & 0xFF;      var c = mitem.accent[2];
     var font = jsMath.TeX.fam[(mitem.accent&0xF00)>>8]; Font = jsMath.TeX[font];      var font = jsMath.TeX.fam[mitem.accent[1]]; Font = jsMath.TeX[font];
     while (Font[c].n && Font[Font[c].n].w <= u) {c = Font[c].n}      while (Font[c].n && Font[Font[c].n].w <= u) {c = Font[c].n}
           
     var delta = Math.min(box.h,TeX.x_height);      var delta = Math.min(box.h,TeX.x_height);
Line 2728  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3613  jsMath.Add(jsMath.mList.prototype.Atomiz
       box = jsMath.Box.Set(mitem.nuc,style,size);        box = 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.msieIntegralBug)           if (mitem.limits || !mitem.sub || jsMath.Browser.msieIntegralBug) 
           {box = jsMath.Box.SetList([box,jsMath.mItem.Space(mitem.delta)],style,size)}            {box = 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 = jsMath.Box.Set(mitem.nuc,style,size).Remeasured()}
Line 2760  jsMath.Add(jsMath.mList.prototype.Atomiz Line 3645  jsMath.Add(jsMath.mList.prototype.Atomiz
       mitem.nuc = jsMath.Box.SetList(mlist,style,size);        mitem.nuc = jsMath.Box.SetList(mlist,style,size);
       mitem.nuc.h += dh; mitem.nuc.d += dd;        mitem.nuc.h += dh; mitem.nuc.d += dd;
     } else {      } else {
       if (jsMath.msieIntegralBug && mitem.sub && C && C.ic)         if (jsMath.Browser.msieIntegralBug && mitem.sub && C && C.ic) 
         {mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(-C.ic*TeX.scale)],style,size)}          {mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(-C.ic*TeX.scale)],style,size)}
       else if (box.y) {mitem.nuc = jsMath.Box.SetList([box],style,size)}        else if (box.y) {mitem.nuc = jsMath.Box.SetList([box],style,size)}
       jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);        jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
Line 2968  jsMath.Add(jsMath.Typeset,{ Line 3853  jsMath.Add(jsMath.Typeset,{
     if (style == "SS" || style == "SS'") {return .5*v}      if (style == "SS" || style == "SS'") {return .5*v}
     return v;      return v;
   },    },
     
     /*
      *  Return the size associated with a given style and size
      */
     StyleSize: function (style,size) {
       if      (style == "S" || style == "S'")   {size = Math.max(0,size-2)}
       else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)}
       return size;
     },
   
   /*    /*
    *  Return the font parameter table for the given style     *  Return the font parameter table for the given style
Line 3123  jsMath.Package(jsMath.Typeset,{ Line 4017  jsMath.Package(jsMath.Typeset,{
     }      }
           
     this.FlushClassed(); // make sure scaling is included      this.FlushClassed(); // make sure scaling is included
     if (this.dx) {this.hbuf += jsMath.HTML.Spacer(this.dx)}      if (this.dx) {this.hbuf += jsMath.HTML.Spacer(this.dx); this.w += this.dx}
     if (this.hbuf == '') {return jsMath.Box.Null}      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}
Line 3156  jsMath.Package(jsMath.Typeset,{ Line 4050  jsMath.Package(jsMath.Typeset,{
   
   /*    /*
    *  Add a <SPAN> to position an item's HTML, and     *  Add a <SPAN> to position an item's HTML, and
    *  adjust the items height and depth.     *  adjust the item's height and depth.
    *  (This may be replaced buy one of the following browser-specific     *  (This may be replaced buy one of the following browser-specific
    *   versions by InitBrowser().)     *   versions by Browser.Init().)
    */     */
   Place: function (item) {    Place: function (item) {
     var html = '<SPAN STYLE="position: relative;';      var html = '<SPAN STYLE="position: relative;';
Line 3170  jsMath.Package(jsMath.Typeset,{ Line 4064  jsMath.Package(jsMath.Typeset,{
   },    },
       
   /*    /*
    *  A replacement for Place() above that fixes a bug in MSIE.     *  For MSIE on Windows, backspacing must be done in a separate
    *  (A separate <SPAN> is used to backspace, otherwise the     *  <SPAN>, otherwise the contents will be clipped.  Netscape
    *   contents are clipped incorrectly.)     *  also doesn't combine vertical and horizontal spacing well.
    */     *  Here, the horizontal and vertical spacing are done separately.
   PlaceSeparateNegative: function (item) {  
     var html = '<SPAN STYLE="position: relative;';  
     // MSIE needs backspacing as separate SPAN  
     if (item.x < 0)   
       {html = '<SPAN STYLE="margin-left:'+jsMath.HTML.Em(item.x)+';"></SPAN>'+html}  
     if (item.x > 0) {html += ' margin-left:'+jsMath.HTML.Em(item.x)+';'}  
     if (item.y) {html += ' top:'+jsMath.HTML.Em(-item.y)+';'}  
     item.html = html + '">' + item.html + '</SPAN>';  
     item.h += item.y; item.d -= item.y;  
     item.x = 0; item.y = 0;  
   },  
   
   /*  
    *  Here, the horizontal spacing is always done separately.  
    */     */
   PlaceSeparateSkips: function (item) {    PlaceSeparateSkips: function (item) {
     if (item.y)       if (item.y) {
       {item.html = '<SPAN STYLE="position: relative; top:'+jsMath.HTML.Em(-item.y)+';'        if (item.html.match(/^<IMG[^>]*>(<SPAN STYLE="margin-left: [-0-9.]*em"><\/SPAN>)?$/i) && !item.html.match(/top:/)) {
                        + '">' + item.html + '</SPAN>'}          item.html = item.html.replace(/STYLE="/,
               'STYLE="position:relative; top:'+jsMath.HTML.Em(-item.y)+';');
         } else {
           item.html = '<SPAN STYLE="position: relative; '
                          + 'top:'+jsMath.HTML.Em(-item.y)+';'
                          + '">' + item.html + '</SPAN>'
         }
       }
     if (item.x)       if (item.x) 
       {item.html = jsMath.msieSpaceFix        {item.html = jsMath.Browser.msieSpaceFix
                        + '<SPAN STYLE="margin-left:'+jsMath.HTML.Em(item.x)+';">'                         + '<SPAN STYLE="margin-left:'
                        + '</SPAN>' + item.html}                         +    jsMath.HTML.Em(item.x-jsMath.Browser.spaceWidth)+';">'
                          + jsMath.Browser.hiddenSpace + '</SPAN>' + 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 3236  jsMath.Package(jsMath.Parser,{ Line 4124  jsMath.Package(jsMath.Parser,{
       
   //  the \mathchar definitions (see Appendix B of the TeXbook).    //  the \mathchar definitions (see Appendix B of the TeXbook).
   mathchar: {    mathchar: {
     '!': 0x5021,      '!': [5,0,0x21],
     '(': 0x4028,      '(': [4,0,0x28],
     ')': 0x5029,      ')': [5,0,0x29],
     '*': 0x2203, // \ast      '*': [2,2,0x03], // \ast
     '+': 0x202B,      '+': [2,0,0x2B],
     ',': 0x613B,      ',': [6,1,0x3B],
     '-': 0x2200,      '-': [2,2,0x00],
     '.': 0x013A,      '.': [0,1,0x3A],
     '/': 0x013D,      '/': [0,1,0x3D],
     ':': 0x303A,      ':': [3,0,0x3A],
     ';': 0x603B,      ';': [6,0,0x3B],
     '<': 0x313C,      '<': [3,1,0x3C],
     '=': 0x303D,      '=': [3,0,0x3D],
     '>': 0x313E,      '>': [3,1,0x3E],
     '?': 0x503F,      '?': [5,0,0x3F],
     '[': 0x405B,      '[': [4,0,0x5B],
     ']': 0x505D,      ']': [5,0,0x5D],
 //  '{': 0x4266,  //  '{': [4,2,0x66],
 //  '}': 0x5267,  //  '}': [5,2,0x67],
     '|': 0x026A      '|': [0,2,0x6A]
   },    },
   
   //  handle special \catcode characters    //  handle special \catcode characters
Line 3274  jsMath.Package(jsMath.Parser,{ Line 4162  jsMath.Package(jsMath.Parser,{
   // the \mathchardef table (see Appendix B of the TeXbook).    // the \mathchardef table (see Appendix B of the TeXbook).
   mathchardef: {    mathchardef: {
   // brace parts    // brace parts
     braceld:      0x37A,      braceld:      [0,3,0x7A],
     bracerd:      0x37B,      bracerd:      [0,3,0x7B],
     bracelu:      0x37C,      bracelu:      [0,3,0x7C],
     braceru:      0x37D,      braceru:      [0,3,0x7D],
   
   // Greek letters    // Greek letters
     alpha:        0x010B,      alpha:        [0,1,0x0B],
     beta:         0x010C,      beta:         [0,1,0x0C],
     gamma:        0x010D,      gamma:        [0,1,0x0D],
     delta:        0x010E,      delta:        [0,1,0x0E],
     epsilon:      0x010F,      epsilon:      [0,1,0x0F],
     zeta:         0x0110,      zeta:         [0,1,0x10],
     eta:          0x0111,      eta:          [0,1,0x11],
     theta:        0x0112,      theta:        [0,1,0x12],
     iota:         0x0113,      iota:         [0,1,0x13],
     kappa:        0x0114,      kappa:        [0,1,0x14],
     lambda:       0x0115,      lambda:       [0,1,0x15],
     mu:           0x0116,      mu:           [0,1,0x16],
     nu:           0x0117,      nu:           [0,1,0x17],
     xi:           0x0118,      xi:           [0,1,0x18],
     pi:           0x0119,      pi:           [0,1,0x19],
     rho:          0x011A,      rho:          [0,1,0x1A],
     sigma:        0x011B,      sigma:        [0,1,0x1B],
     tau:          0x011C,      tau:          [0,1,0x1C],
     upsilon:      0x011D,      upsilon:      [0,1,0x1D],
     phi:          0x011E,      phi:          [0,1,0x1E],
     chi:          0x011F,      chi:          [0,1,0x1F],
     psi:          0x0120,      psi:          [0,1,0x20],
     omega:        0x0121,      omega:        [0,1,0x21],
     varepsilon:   0x0122,      varepsilon:   [0,1,0x22],
     vartheta:     0x0123,      vartheta:     [0,1,0x23],
     varpi:        0x0124,      varpi:        [0,1,0x24],
     varrho:       0x0125,      varrho:       [0,1,0x25],
     varsigma:     0x0126,      varsigma:     [0,1,0x26],
     varphi:       0x0127,      varphi:       [0,1,0x27],
           
     Gamma:        0x7000,      Gamma:        [7,0,0x00],
     Delta:        0x7001,      Delta:        [7,0,0x01],
     Theta:        0x7002,      Theta:        [7,0,0x02],
     Lambda:       0x7003,      Lambda:       [7,0,0x03],
     Xi:           0x7004,      Xi:           [7,0,0x04],
     Pi:           0x7005,      Pi:           [7,0,0x05],
     Sigma:        0x7006,      Sigma:        [7,0,0x06],
     Upsilon:      0x7007,      Upsilon:      [7,0,0x07],
     Phi:          0x7008,      Phi:          [7,0,0x08],
     Psi:          0x7009,      Psi:          [7,0,0x09],
     Omega:        0x700A,      Omega:        [7,0,0x0A],
   
   // Ord symbols    // Ord symbols
     aleph:        0x0240,      aleph:        [0,2,0x40],
     imath:        0x017B,      imath:        [0,1,0x7B],
     jmath:        0x017C,      jmath:        [0,1,0x7C],
     ell:          0x0160,      ell:          [0,1,0x60],
     wp:           0x017D,      wp:           [0,1,0x7D],
     Re:           0x023C,      Re:           [0,2,0x3C],
     Im:           0x023D,      Im:           [0,2,0x3D],
     partial:      0x0140,      partial:      [0,1,0x40],
     infty:        0x0231,      infty:        [0,2,0x31],
     prime:        0x0230,      prime:        [0,2,0x30],
     emptyset:     0x023B,      emptyset:     [0,2,0x3B],
     nabla:        0x0272,      nabla:        [0,2,0x72],
     surd:         0x1270,      surd:         [1,2,0x70],
     top:          0x023E,      top:          [0,2,0x3E],
     bot:          0x023F,      bot:          [0,2,0x3F],
     triangle:     0x0234,      triangle:     [0,2,0x34],
     forall:       0x0238,      forall:       [0,2,0x38],
     exists:       0x0239,      exists:       [0,2,0x39],
     neg:          0x023A,      neg:          [0,2,0x3A],
     lnot:         0x023A,      lnot:         [0,2,0x3A],
     flat:         0x015B,      flat:         [0,1,0x5B],
     natural:      0x015C,      natural:      [0,1,0x5C],
     sharp:        0x015D,      sharp:        [0,1,0x5D],
     clubsuit:     0x027C,      clubsuit:     [0,2,0x7C],
     diamondsuit:  0x027D,      diamondsuit:  [0,2,0x7D],
     heartsuit:    0x027E,      heartsuit:    [0,2,0x7E],
     spadesuit:    0x027F,      spadesuit:    [0,2,0x7F],
   
   // big ops    // big ops
     coprod:      0x1360,      coprod:      [1,3,0x60],
     bigvee:      0x1357,      bigvee:      [1,3,0x57],
     bigwedge:    0x1356,      bigwedge:    [1,3,0x56],
     biguplus:    0x1355,      biguplus:    [1,3,0x55],
     bigcap:      0x1354,      bigcap:      [1,3,0x54],
     bigcup:      0x1353,      bigcup:      [1,3,0x53],
     intop:       0x1352,       intop:       [1,3,0x52], 
     prod:        0x1351,      prod:        [1,3,0x51],
     sum:         0x1350,      sum:         [1,3,0x50],
     bigotimes:   0x134E,      bigotimes:   [1,3,0x4E],
     bigoplus:    0x134C,      bigoplus:    [1,3,0x4C],
     bigodot:     0x134A,      bigodot:     [1,3,0x4A],
     ointop:      0x1348,      ointop:      [1,3,0x48],
     bigsqcup:    0x1346,      bigsqcup:    [1,3,0x46],
     smallint:    0x1273,      smallint:    [1,2,0x73],
   
   // binary operations    // binary operations
     triangleleft:      0x212F,      triangleleft:      [2,1,0x2F],
     triangleright:     0x212E,      triangleright:     [2,1,0x2E],
     bigtriangleup:     0x2234,      bigtriangleup:     [2,2,0x34],
     bigtriangledown:   0x2235,      bigtriangledown:   [2,2,0x35],
     wedge:       0x225E,      wedge:       [2,2,0x5E],
     land:        0x225E,      land:        [2,2,0x5E],
     vee:         0x225F,      vee:         [2,2,0x5F],
     lor:         0x225F,      lor:         [2,2,0x5F],
     cap:         0x225C,      cap:         [2,2,0x5C],
     cup:         0x225B,      cup:         [2,2,0x5B],
     ddagger:     0x227A,      ddagger:     [2,2,0x7A],
     dagger:      0x2279,      dagger:      [2,2,0x79],
     sqcap:       0x2275,      sqcap:       [2,2,0x75],
     sqcup:       0x2274,      sqcup:       [2,2,0x74],
     uplus:       0x225D,      uplus:       [2,2,0x5D],
     amalg:       0x2271,      amalg:       [2,2,0x71],
     diamond:     0x2205,      diamond:     [2,2,0x05],
     bullet:      0x220F,      bullet:      [2,2,0x0F],
     wr:          0x226F,      wr:          [2,2,0x6F],
     div:         0x2204,      div:         [2,2,0x04],
     odot:        0x220C,      odot:        [2,2,0x0C],
     oslash:      0x220B,      oslash:      [2,2,0x0B],
     otimes:      0x220A,      otimes:      [2,2,0x0A],
     ominus:      0x2209,      ominus:      [2,2,0x09],
     oplus:       0x2208,      oplus:       [2,2,0x08],
     mp:          0x2207,      mp:          [2,2,0x07],
     pm:          0x2206,      pm:          [2,2,0x06],
     circ:        0x220E,      circ:        [2,2,0x0E],
     bigcirc:     0x220D,      bigcirc:     [2,2,0x0D],
     setminus:    0x226E, // for set difference A\setminus B      setminus:    [2,2,0x6E], // for set difference A\setminus B
     cdot:        0x2201,      cdot:        [2,2,0x01],
     ast:         0x2203,      ast:         [2,2,0x03],
     times:       0x2202,      times:       [2,2,0x02],
     star:        0x213F,      star:        [2,1,0x3F],
   
   // Relations    // Relations
     propto:      0x322F,      propto:      [3,2,0x2F],
     sqsubseteq:  0x3276,      sqsubseteq:  [3,2,0x76],
     sqsupseteq:  0x3277,      sqsupseteq:  [3,2,0x77],
     parallel:    0x326B,      parallel:    [3,2,0x6B],
     mid:         0x326A,      mid:         [3,2,0x6A],
     dashv:       0x3261,      dashv:       [3,2,0x61],
     vdash:       0x3260,      vdash:       [3,2,0x60],
     leq:         0x3214,      leq:         [3,2,0x14],
     le:          0x3214,      le:          [3,2,0x14],
     geq:         0x3215,      geq:         [3,2,0x15],
     ge:          0x3215,      ge:          [3,2,0x15],
     succ:        0x321F,      succ:        [3,2,0x1F],
     prec:        0x321E,      prec:        [3,2,0x1E],
     approx:      0x3219,      approx:      [3,2,0x19],
     succeq:      0x3217,      succeq:      [3,2,0x17],
     preceq:      0x3216,      preceq:      [3,2,0x16],
     supset:      0x321B,      supset:      [3,2,0x1B],
     subset:      0x321A,      subset:      [3,2,0x1A],
     supseteq:    0x3213,      supseteq:    [3,2,0x13],
     subseteq:    0x3212,      subseteq:    [3,2,0x12],
     'in':        0x3232,      'in':        [3,2,0x32],
     ni:          0x3233,      ni:          [3,2,0x33],
     owns:        0x3233,      owns:        [3,2,0x33],
     gg:          0x321D,      gg:          [3,2,0x1D],
     ll:          0x321C,      ll:          [3,2,0x1C],
     not:         0x3236,      not:         [3,2,0x36],
     sim:         0x3218,      sim:         [3,2,0x18],
     simeq:       0x3227,      simeq:       [3,2,0x27],
     perp:        0x323F,      perp:        [3,2,0x3F],
     equiv:       0x3211,      equiv:       [3,2,0x11],
     asymp:       0x3210,      asymp:       [3,2,0x10],
     smile:       0x315E,      smile:       [3,1,0x5E],
     frown:       0x315F,      frown:       [3,1,0x5F],
   
   // Arrows    // Arrows
     Leftrightarrow:   0x322C,      Leftrightarrow:   [3,2,0x2C],
     Leftarrow:        0x3228,      Leftarrow:        [3,2,0x28],
     Rightarrow:       0x3229,      Rightarrow:       [3,2,0x29],
     leftrightarrow:   0x3224,      leftrightarrow:   [3,2,0x24],
     leftarrow:        0x3220,      leftarrow:        [3,2,0x20],
     gets:             0x3220,      gets:             [3,2,0x20],
     rightarrow:       0x3221,      rightarrow:       [3,2,0x21],
     to:               0x3221,      to:               [3,2,0x21],
     mapstochar:       0x3237,      mapstochar:       [3,2,0x37],
     leftharpoonup:    0x3128,      leftharpoonup:    [3,1,0x28],
     leftharpoondown:  0x3129,      leftharpoondown:  [3,1,0x29],
     rightharpoonup:   0x312A,      rightharpoonup:   [3,1,0x2A],
     rightharpoondown: 0x312B,      rightharpoondown: [3,1,0x2B],
     nearrow:          0x3225,      nearrow:          [3,2,0x25],
     searrow:          0x3226,      searrow:          [3,2,0x26],
     nwarrow:          0x322D,      nwarrow:          [3,2,0x2D],
     swarrow:          0x322E,      swarrow:          [3,2,0x2E],
   
     hbarchar:   0x0016, // for \hbar      hbarchar:   [0,0,0x16], // for \hbar
     lhook:      0x312C,      lhook:      [3,1,0x2C],
     rhook:      0x312D,      rhook:      [3,1,0x2D],
   
     ldotp:      0x613A, // ldot as a punctuation mark      ldotp:      [6,1,0x3A], // ldot as a punctuation mark
     cdotp:      0x6201, // cdot as a punctuation mark      cdotp:      [6,2,0x01], // cdot as a punctuation mark
     colon:      0x603A, // colon as a punctuation mark      colon:      [6,0,0x3A], // colon as a punctuation mark
   
     '#':        0x7023,      '#':        [7,0,0x23],
     '$':        0x7024,      '$':        [7,0,0x24],
     '%':        0x7025,      '%':        [7,0,0x25],
     '&':        0x7026      '&':        [7,0,0x26]
   },    },
       
   // The delimiter table (see Appendix B of the TeXbook)    // The delimiter table (see Appendix B of the TeXbook)
   delimiter: {    delimiter: {
     '(':                0x0028300,      '(':                [0,0,0x28,3,0x00],
     ')':                0x0029301,      ')':                [0,0,0x29,3,0x01],
     '[':                0x005B302,      '[':                [0,0,0x5B,3,0x02],
     ']':                0x005D303,      ']':                [0,0,0x5D,3,0x03],
     '<':                0x026830A,      '<':                [0,2,0x68,3,0x0A],
     '>':                0x026930B,      '>':                [0,2,0x69,3,0x0B],
     '/':                0x002F30E,      '/':                [0,0,0x2F,3,0x0E],
     '|':                0x026A30C,      '|':                [0,2,0x6A,3,0x0C],
     '.':                0x0000000,      '.':                [0,0,0x00,0,0x00],
     '\\':               0x026E30F,      '\\':               [0,2,0x6E,3,0x0F],
     '\\lmoustache':     0x437A340,  // top from (, bottom from )      '\\lmoustache':     [4,3,0x7A,3,0x40],  // top from (, bottom from )
     '\\rmoustache':     0x537B341,  // top from ), bottom from (      '\\rmoustache':     [5,3,0x7B,3,0x41],  // top from ), bottom from (
     '\\lgroup':         0x462833A,  // extensible ( with sharper tips      '\\lgroup':         [4,6,0x28,3,0x3A],  // extensible ( with sharper tips
     '\\rgroup':         0x562933B,  // extensible ) with sharper tips      '\\rgroup':         [5,6,0x29,3,0x3B],  // extensible ) with sharper tips
     '\\arrowvert':      0x026A33C,  // arrow without arrowheads      '\\arrowvert':      [0,2,0x6A,3,0x3C],  // arrow without arrowheads
     '\\Arrowvert':      0x026B33D,  // double arrow without arrowheads      '\\Arrowvert':      [0,2,0x6B,3,0x3D],  // double arrow without arrowheads
 //  '\\bracevert':      0x077C33E,  // the vertical bar that extends braces  //  '\\bracevert':      [0,7,0x7C,3,0x3E],  // the vertical bar that extends braces
     '\\bracevert':      0x026A33E,  // we don't load tt, so use | instead      '\\bracevert':      [0,2,0x6A,3,0x3E],  // we don't load tt, so use | instead
     '\\Vert':           0x026B30D,      '\\Vert':           [0,2,0x6B,3,0x0D],
     '\\|':              0x026B30D,      '\\|':              [0,2,0x6B,3,0x0D],
     '\\vert':           0x026A30C,      '\\vert':           [0,2,0x6A,3,0x0C],
     '\\uparrow':        0x3222378,      '\\uparrow':        [3,2,0x22,3,0x78],
     '\\downarrow':      0x3223379,      '\\downarrow':      [3,2,0x23,3,0x79],
     '\\updownarrow':    0x326C33F,      '\\updownarrow':    [3,2,0x6C,3,0x3F],
     '\\Uparrow':        0x322A37E,      '\\Uparrow':        [3,2,0x2A,3,0x7E],
     '\\Downarrow':      0x322B37F,      '\\Downarrow':      [3,2,0x2B,3,0x7F],
     '\\Updownarrow':    0x326D377,      '\\Updownarrow':    [3,2,0x6D,3,0x77],
     '\\backslash':      0x026E30F,  // for double coset G\backslash H      '\\backslash':      [0,2,0x6E,3,0x0F],  // for double coset G\backslash H
     '\\rangle':         0x526930B,      '\\rangle':         [5,2,0x69,3,0x0B],
     '\\langle':         0x426830A,      '\\langle':         [4,2,0x68,3,0x0A],
     '\\rbrace':         0x5267309,      '\\rbrace':         [5,2,0x67,3,0x09],
     '\\lbrace':         0x4266308,      '\\lbrace':         [4,2,0x66,3,0x08],
     '\\}':              0x5267309,      '\\}':              [5,2,0x67,3,0x09],
     '\\{':              0x4266308,      '\\{':              [4,2,0x66,3,0x08],
     '\\rceil':          0x5265307,      '\\rceil':          [5,2,0x65,3,0x07],
     '\\lceil':          0x4264306,      '\\lceil':          [4,2,0x64,3,0x06],
     '\\rfloor':         0x5263305,      '\\rfloor':         [5,2,0x63,3,0x05],
     '\\lfloor':         0x4262304      '\\lfloor':         [4,2,0x62,3,0x04]
   },    },
   
   /*    /*
Line 3621  jsMath.Package(jsMath.Parser,{ Line 4509  jsMath.Package(jsMath.Parser,{
     doteq:              ['Macro','\\buildrel\\textstyle.\\over='],      doteq:              ['Macro','\\buildrel\\textstyle.\\over='],
     ldots:              ['Macro','\\mathinner{\\ldotp\\ldotp\\ldotp}'],      ldots:              ['Macro','\\mathinner{\\ldotp\\ldotp\\ldotp}'],
     cdots:              ['Macro','\\mathinner{\\cdotp\\cdotp\\cdotp}'],      cdots:              ['Macro','\\mathinner{\\cdotp\\cdotp\\cdotp}'],
     vdots:              ['Macro','\\mathinner{\\rlap{\\raise8pt{\\rule 0pt 6pt 0pt .}}\\rlap{\\raise4pt{.}}.}'],      vdots:              ['Macro','\\mathinner{\\rlap{\\raise8pt{.\\rule 0pt 6pt 0pt}}\\rlap{\\raise4pt{.}}.}'],
     ddots:              ['Macro','\\mathinner{\\kern1mu\\raise7pt{\\rule 0pt 7pt 0pt .}\\kern2mu\\raise4pt{.}\\kern2mu\\raise1pt{.}\\kern1mu}'],      ddots:              ['Macro','\\mathinner{\\kern1mu\\raise7pt{\\rule 0pt 7pt 0pt .}\\kern2mu\\raise4pt{.}\\kern2mu\\raise1pt{.}\\kern1mu}'],
     joinrel:            ['Macro','\\mathrel{\\kern-4mu}'],      joinrel:            ['Macro','\\mathrel{\\kern-4mu}'],
     relbar:             ['Macro','\\mathrel{\\smash-}'], // \smash, because - has the same height as +      relbar:             ['Macro','\\mathrel{\\smash-}'], // \smash, because - has the same height as +
Line 3663  jsMath.Package(jsMath.Parser,{ Line 4551  jsMath.Package(jsMath.Parser,{
           
     hskip:         'Hskip',      hskip:         'Hskip',
     kern:          'Hskip',      kern:          'Hskip',
     rule:          ['Rule','black'],      rule:          ['Rule','colored'],
     space:         ['Rule','blank'],      space:         ['Rule','blank'],
           
     big:        ['MakeBig','ord',0.85],      big:        ['MakeBig','ord',0.85],
Line 3707  jsMath.Package(jsMath.Parser,{ Line 4595  jsMath.Package(jsMath.Parser,{
     hphantom:   ['Phantom',0,1],      hphantom:   ['Phantom',0,1],
     smash:      'Smash',      smash:      'Smash',
           
     acute:      ['MathAccent', 0x7013],      acute:      ['MathAccent', [7,0,0x13]],
     grave:      ['MathAccent', 0x7012],      grave:      ['MathAccent', [7,0,0x12]],
     ddot:       ['MathAccent', 0x707F],      ddot:       ['MathAccent', [7,0,0x7F]],
     tilde:      ['MathAccent', 0x707E],      tilde:      ['MathAccent', [7,0,0x7E]],
     bar:        ['MathAccent', 0x7016],      bar:        ['MathAccent', [7,0,0x16]],
     breve:      ['MathAccent', 0x7015],      breve:      ['MathAccent', [7,0,0x15]],
     check:      ['MathAccent', 0x7014],      check:      ['MathAccent', [7,0,0x14]],
     hat:        ['MathAccent', 0x705E],      hat:        ['MathAccent', [7,0,0x5E]],
     vec:        ['MathAccent', 0x017E],      vec:        ['MathAccent', [0,1,0x7E]],
     dot:        ['MathAccent', 0x705F],      dot:        ['MathAccent', [7,0,0x5F]],
     widetilde:  ['MathAccent', 0x0365],      widetilde:  ['MathAccent', [0,3,0x65]],
     widehat:    ['MathAccent', 0x0362],      widehat:    ['MathAccent', [0,3,0x62]],
   
     '_':        ['Replace','ord','_','normal',-.4,.1],      '_':        ['Replace','ord','_','normal',-.4,.1],
     ' ':        ['Replace','ord','&nbsp;','normal'],      ' ':        ['Replace','ord','&nbsp;','normal'],
Line 3754  jsMath.Package(jsMath.Parser,{ Line 4642  jsMath.Package(jsMath.Parser,{
     unicode:    'Unicode',      unicode:    'Unicode',
   
     //  debugging and test routines      //  debugging and test routines
     'char':     'Char',      'char':     'Char'
     test:       'Test'  
   },    },
       
   /*    /*
Line 3777  jsMath.Package(jsMath.Parser,{ Line 4664  jsMath.Package(jsMath.Parser,{
    *  The horizontally stretchable delimiters     *  The horizontally stretchable delimiters
    */     */
   leaders: {    leaders: {
     downbrace:  {left: 0x37A, lmid: 0x37D, rmid: 0x37C, right: 0x37B},      downbrace:  {left: [3,0x7A], lmid: [3,0x7D], rmid: [3,0x7C], right: [3,0x7B]},
     upbrace:    {left: 0x37C, lmid: 0x37B, rmid: 0x37A, right: 0x37D},      upbrace:    {left: [3,0x7C], lmid: [3,0x7B], rmid: [3,0x7A], right: [3,0x7D]},
     leftarrow:  {left: 0x220, rep: 0x200},      leftarrow:  {left: [2,0x20], rep:  [2,0x00]},
     rightarrow: {rep: 0x200, right: 0x221}      rightarrow: {rep:  [2,0x00], right: [2,0x21]}
   },    },
   
   
Line 3894  jsMath.Package(jsMath.Parser,{ Line 4781  jsMath.Package(jsMath.Parser,{
    *  converted when typeset.     *  converted when typeset.
    */     */
   GetDimen: function (name,nomu) {    GetDimen: function (name,nomu) {
     var rest = this.string.slice(this.i);      var rest; var advance = 0;
       if (this.nextIsSpace()) {this.i++}
       if (this.string.charAt(this.i) == '{') {
         rest = this.GetArgument(name);
       } else {
         rest = this.string.slice(this.i);
         advance = 1;
       }
     var match = rest.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/);      var match = rest.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/);
     if (!match) {this.Error("Missing dimension or its units for "+name); return}      if (!match) {this.Error("Missing dimension or its units for "+name); return}
     this.i += match[0].length;      if (advance) {
     if (this.nextIsSpace()) {this.i++}        this.i += match[0].length;
         if (this.nextIsSpace()) {this.i++}
       }
     var d = match[1]-0;      var d = match[1]-0;
     if (match[4] == 'px') {d /= jsMath.em}      if (match[4] == 'px') {d /= jsMath.em}
     else if (match[4] == 'pt') {d /= 10}      else if (match[4] == 'pt') {d /= 10}
Line 4275  jsMath.Package(jsMath.Parser,{ Line 5171  jsMath.Package(jsMath.Parser,{
   },    },
   
   /*    /*
    *  Debugging routine to test stretchable delimiters  
    */  
   Test: function () {  
     var delim = this.GetDelimiter(this.cmd+'test'); if (this.error) return;  
     var H = this.GetArgument(this.cmd+'test'); if (this.error) return;  
     this.mlist.Add(jsMath.mItem.Typeset(jsMath.Box.Delimiter(H,delim,'T')));  
     return;  
   
     var leader = this.GetArgument(this.cmd+'test'); if (this.error) return;  
     var W = this.GetArgument(this.cmd+'test'); if (this.error) return;  
     if (this.leaders[leader] == null)   
       {this.Error('Unknown leaders "'+leader+'"'); return}  
     this.mlist.Add(jsMath.mItem.Typeset(jsMath.Box.Leaders(W,this.leaders[leader])));  
     return;  
   },  
     
   /*  
    *  Add a fixed amount of horizontal space     *  Add a fixed amount of horizontal space
    */     */
   Spacer: function (name,w) {    Spacer: function (name,w) {
Line 4335  jsMath.Package(jsMath.Parser,{ Line 5214  jsMath.Package(jsMath.Parser,{
    *  This replaces \hrule and \vrule     *  This replaces \hrule and \vrule
    *  @@@ not a standard TeX command, and all three parameters must be given @@@     *  @@@ not a standard TeX command, and all three parameters must be given @@@
    */     */
   Rule: function (name,gif) {    Rule: function (name,style) {
     var w = this.GetDimen(this.cmd+name,1); if (this.error) return;      var w = this.GetDimen(this.cmd+name,1); if (this.error) return;
     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 d = this.GetDimen(this.cmd+name,1); if (this.error) return;      var d = this.GetDimen(this.cmd+name,1); if (this.error) return;
     h += d;       h += d; var html;
     if (h != 0) {h = Math.max(1.05/jsMath.em,h)}      if (h != 0) {h = Math.max(1.05/jsMath.em,h)}
     if (h == 0 || w == 0) {gif = "blank"}      if (h == 0 || w == 0) {style = "blank"}
     var html = '<IMG SRC="'+jsMath[gif]+'" STYLE="height: '+jsMath.HTML.Em(h)+'; '      if (w == 0) {
                 + 'width: '+jsMath.HTML.Em(w)+'">';        html = '<IMG SRC="'+jsMath.blank+'" STYLE="'
                   + 'border:0px none; width:1px; margin-right:-1px; '
                   + 'height:'+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+'">';
       } else if (style == "blank") {
         html = '<IMG SRC="'+jsMath.blank+'" STYLE="border:0px none; '
                   + 'height:'+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+'; '
                   + 'width:' +jsMath.HTML.Em(w*jsMath.Browser.imgScale)+'">';
       } else {
         html = '<IMG SRC="'+jsMath.blank+'" STYLE="'
                   + 'position: relative; top:1px; height:1px; border:0px none; '
                   + 'border-top:'+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+' solid; '
                   + 'width:' +jsMath.HTML.Em(w*jsMath.Browser.imgScale)+'">';
       }
     if (d) {      if (d) {
       html = '<SPAN STYLE="vertical-align:'+jsMath.HTML.Em(-d)+'">'        html = '<SPAN STYLE="vertical-align:'+jsMath.HTML.Em(-d)+'">'
            +  html + '</SPAN>';             +  html + '</SPAN>';
Line 4485  jsMath.Package(jsMath.Parser,{ Line 5376  jsMath.Package(jsMath.Parser,{
    *  Process the character associated with a specific \mathcharcode     *  Process the character associated with a specific \mathcharcode
    */     */
   HandleMathCode: function (name,code) {    HandleMathCode: function (name,code) {
     var type = (code & 0xF000) >> 12;      this.HandleTeXchar(code[0],code[1],code[2]);
     var font = (code & 0x0F00) >> 8;  
     var code = code & 0x00FF;  
     this.HandleTeXchar(type,font,code);  
   },    },
       
   /*    /*
Line 4566  jsMath.Package(jsMath.Parser,{ Line 5454  jsMath.Package(jsMath.Parser,{
       return;        return;
     }      }
     if (this.delimiter[this.cmd+cmd]) {      if (this.delimiter[this.cmd+cmd]) {
       this.HandleMathCode(cmd,this.delimiter[this.cmd+cmd]>>12)        this.HandleMathCode(cmd,this.delimiter[this.cmd+cmd].slice(0,3))
       return;        return;
     }      }
     this.Error("Unknown control sequence '"+this.cmd+cmd+"'");      this.Error("Unknown control sequence '"+this.cmd+cmd+"'");
Line 4682  jsMath.Package(jsMath.Parser,{ Line 5570  jsMath.Package(jsMath.Parser,{
    *  results.  We also include an image to force the results to take up     *  results.  We also include an image to force the results to take up
    *  the right amount of space.  The results may need to be vertically     *  the right amount of space.  The results may need to be vertically
    *  adjusted to make the baseline appear in the correct place.     *  adjusted to make the baseline appear in the correct place.
    *    
    *  This is where the touchiest browser-dependent code appears.  
    */     */
   Typeset: function () {    Typeset: function () {
     var data = this.mlist.init;      var data = this.mlist.init;
     var box = this.typeset = this.mlist.Typeset(data.style,data.size);      var box = this.typeset = this.mlist.Typeset(data.style,data.size);
     if (this.error) {return '<SPAN CLASS="error">'+this.error+'</SPAN>'}      if (this.error) {return '<SPAN CLASS="error">'+this.error+'</SPAN>'}
     if (box.format == 'null') {return ''};      if (box.format == 'null') {return ''};
     var rules = ''; var html  
   
     box.Styled().Remeasured(); var isSmall = 0; var isBig = 0;      box.Styled().Remeasured(); var isSmall = 0; var isBig = 0;
     var w = box.w; var h = box.bh; var d = box.bd;  
     if (box.bh > box.h && box.bh > jsMath.h+.001) {isSmall = 1}      if (box.bh > box.h && box.bh > jsMath.h+.001) {isSmall = 1}
     if (box.bd > box.d && box.bd > jsMath.d+.001) {isSmall = 1}      if (box.bd > box.d && box.bd > jsMath.d+.001) {isSmall = 1}
     if (box.h > jsMath.h) {isBig = 1; h = box.h}      if (box.h > jsMath.h || box.d > jsMath.d) {isBig = 1}
     if (box.d > jsMath.d) {isBig = 1; d = box.d}  
   
     if (jsMath.show.BBox) {rules += jsMath.HTML.Frame(0,-box.d,w,box.h+box.d,'green')}      var html = box.html;
     if (jsMath.show.Top) {rules += jsMath.HTML.Line(0,box.h,w,'red')}  
     if (jsMath.show.Baseline) {rules += jsMath.HTML.Line(0,0,w,'blue')}  
   
     html = box.html;  
     if (isSmall) {// hide the extra size      if (isSmall) {// hide the extra size
       if (jsMath.allowAbsolute) {        if (jsMath.Browser.allowAbsolute) {
         var y = jsMath.absoluteOffsetY;          var y = 0;
         if (jsMath.absoluteHeightVaries || box.bh > jsMath.h+.001) {y += (jsMath.h - box.bh)}          if (box.bh > jsMath.h+.001) {y = jsMath.h - box.bh}
         html = jsMath.HTML.Absolute(html,w,jsMath.h,0,y,jsMath.h);          html = jsMath.HTML.Absolute(html,box.w,jsMath.h,0,y,jsMath.h);
  isBig = 1; h = box.h; d = box.d;         } else if (!jsMath.Browser.valignBug) {
       } 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: 0;'          html = '<SPAN STYLE="line-height: 0;'
                + ' position: relative; top: '+dy+'; vertical-align: '+dy                 + ' position:relative; top:'+dy+'; vertical-align:'+dy
                + '">'                 + '">' + html + '</SPAN>';
                + html  
                + '</SPAN>';  
       }        }
         isBig = 1;
     }      }
     html = '<NOBR>' + rules + html;  
     if (isBig) {// add height and depth to the line (force a little      if (isBig) {// add height and depth to the line (force a little
                 //    extra to separate lines if needed)                  //    extra to separate lines if needed)
       html += '<IMG SRC="'+jsMath.blank+'" CLASS="mathHD" '        html += '<IMG SRC="'+jsMath.blank+'" CLASS="mathHD" STYLE="'
                +   'STYLE="height: '+jsMath.HTML.Em(h+d+.2)+'; '                 + 'height:'+jsMath.HTML.Em((box.h+box.d+.1)*jsMath.Browser.imgScale)+'; '
                +   'vertical-align: '+jsMath.HTML.Em(-d-.1)+';">'                 + 'vertical-align:'+jsMath.HTML.Em(-box.d-.05)+';">'
     }      }
     html += '<NOBR>'      return '<NOBR><SPAN CLASS="jsM_scale">'+html+'</SPAN></NOBR>';
     return html;  
   }    }
   
 });  });
Line 4760  jsMath.Parser.prototype.AddSpecial({ Line 5636  jsMath.Parser.prototype.AddSpecial({
  *  requires.  These are substituted for #1, #2, etc. within the    *  requires.  These are substituted for #1, #2, etc. within the 
  *  replacement string of the macro.  For example   *  replacement string of the macro.  For example
  *     *  
  *      <SCRIPT> jsMath.Macro('x','{\vec x}_{#1}',1) </SCRIPT>   *      <SCRIPT> jsMath.Macro('x','{\\vec x}_{#1}',1) </SCRIPT>
  *     *  
  *  would make \x1 produce {\vec x}_{1} and \x{i+1} produce {\vec x}_{i+1}.   *  would make \x1 produce {\vec x}_{1} and \x{i+1} produce {\vec x}_{i+1}.
  *   *
Line 4812  jsMath.Add(jsMath,{ Line 5688  jsMath.Add(jsMath,{
   
   /*    /*
    *  Typeset a string in \displaystyle and return the HTML for it     *  Typeset a string in \displaystyle and return the HTML for it
    *  ### need to give more control over whether to center, etc. ###  
    */     */
   DisplayMode: function (s) {    DisplayMode: function (s) {
     var parse = jsMath.Parse(s,null,null,'D');      var parse = jsMath.Parse(s,null,null,'D');
Line 4826  jsMath.Add(jsMath,{ Line 5701  jsMath.Add(jsMath,{
    */     */
   GetElementText: function (element) {    GetElementText: function (element) {
     var text = element.innerText;      var text = element.innerText;
     if (text == null) {      if (text == null || text == "") {
       text = element.textContent;        try {text = element.textContent} catch (err) {}
       if (text == null) {        if (text == null || text == "") {text = element.innerHTML}
         text = element.innerHTML;  
       }  
     }      }
     if (text.search('&')) {      if (text.search('&') >= 0) {
       text = text.replace(/&lt;/g,'<');        text = text.replace(/&lt;/g,'<');
       text = text.replace(/&gt;/g,'>');        text = text.replace(/&gt;/g,'>');
       text = text.replace(/&quot;/g,'"');        text = text.replace(/&quot;/g,'"');
Line 4842  jsMath.Add(jsMath,{ Line 5715  jsMath.Add(jsMath,{
   },    },
       
   /*    /*
      *  Move hidden to the location of the math element to be
      *  processed and reinitialize sizes for that location.
      */
     ResetHidden: function (element) {
       element.innerHTML =
         '<SPAN CLASS="normal" STYLE="position:absolute; top:0px;left:0px;"></SPAN>'
           + jsMath.Browser.operaHiddenFix; // needed by Opera in tables
       element.className='';
       jsMath.hidden = element.firstChild;
       jsMath.ReInit();
     },
   
     
     /*
    *  Typeset the contents of an element in \textstyle     *  Typeset the contents of an element in \textstyle
    */     */
   ConvertText: function (element) {    ConvertText: function (element) {
     var text = this.GetElementText(element);      var text = this.GetElementText(element);
       this.ResetHidden(element);
     element.innerHTML = this.TextMode(text);      element.innerHTML = this.TextMode(text);
     element.className = 'typeset';      element.className = 'typeset';
       element.alt = text;
   },    },
       
   /*    /*
Line 4855  jsMath.Add(jsMath,{ Line 5744  jsMath.Add(jsMath,{
    */     */
   ConvertDisplay: function (element) {    ConvertDisplay: function (element) {
     var text = this.GetElementText(element);      var text = this.GetElementText(element);
       this.ResetHidden(element);
     element.innerHTML = this.DisplayMode(text);      element.innerHTML = this.DisplayMode(text);
     element.className = 'typeset';      element.className = 'typeset';
   },      element.alt = text;
     
   /*  
    *  Call this at the bottom of your HTML page to have the  
    *  mathematics typeset before the page is displayed.  
    *  This can take a long time, so the user could cancel the  
    *  page before it is complete; use it with caution, and only  
    *  when there is a relatively small amount of math on the page.  
    */  
   ProcessBeforeShowing: function () {  
     if (!jsMath.initialized) {jsMath.Init()}  
     var element = jsMath.GetMathElements();  
     for (var i = 0; i < element.length; i++)  
       {jsMath.ProcessElement(element[i])}  
     jsMath.ProcessComplete();  
   },    },
       
   /*    /*
    *  Process a math element     *  Process a math element
    */     */
   ProcessElement: function (element) {    ProcessElement: function (element) {
     window.status = 'Processing Math...';      try {
     if (element.tagName == 'DIV') {        if (element.tagName == 'DIV') {
       this.ConvertDisplay(element);          this.ConvertDisplay(element);
     } else if (element.tagName == 'SPAN') {        } else if (element.tagName == 'SPAN') {
       this.ConvertText(element);          this.ConvertText(element);
     }          //
           // Overcome a bug in MSIE where were tex2math can't insert DIV's inside
           // some elements, so fake it with SPANs, but can't fake the centering,
           // so do that here.
           //
           if (element.parentNode.className == 'jsMath.recenter') {
             element.parentNode.style.marginLeft =
               Math.floor((element.parentNode.offsetWidth - element.offsetWidth)/2)+"px";
           }
         }
         element.onclick = jsMath.Click.CheckClick;
         element.ondblclick = jsMath.Click.CheckDblClick;
       } catch (err) {}
   },    },
   
   /*    /*
Line 4895  jsMath.Add(jsMath,{ Line 5783  jsMath.Add(jsMath,{
       this.ProcessComplete();        this.ProcessComplete();
     } else {      } else {
       this.ProcessElement(this.element[k])        this.ProcessElement(this.element[k])
       setTimeout('jsMath.ProcessElements('+(k+1)+')',jsMath.delay);        setTimeout('jsMath.ProcessElements('+(k+1)+')',jsMath.Browser.delay);
     }      }
   },    },
   
Line 4905  jsMath.Add(jsMath,{ Line 5793  jsMath.Add(jsMath,{
    *  start reading the mathematics while the rest of the page     *  start reading the mathematics while the rest of the page
    *  is being processed.     *  is being processed.
    */     */
   Process: function () {    Process: function (obj) {
     if (!jsMath.initialized) {jsMath.Init()}      if (!jsMath.initialized) {jsMath.Init()}
     this.element = this.GetMathElements();      this.element = this.GetMathElements(obj);
     window.status = 'Processing Math...';      window.status = 'Processing Math...';
     setTimeout('jsMath.ProcessElements(0)',jsMath.delay);      setTimeout('jsMath.ProcessElements(0)',jsMath.Browser.delay);
     },
     
     /*
      *  Call this at the bottom of your HTML page to have the
      *  mathematics typeset before the page is displayed.
      *  This can take a long time, so the user could cancel the
      *  page before it is complete; use it with caution, and only
      *  when there is a relatively small amount of math on the page.
      */
     ProcessBeforeShowing: function (obj) {
       if (!jsMath.initialized) {jsMath.Init()}
       var element = jsMath.GetMathElements(obj);
       window.status = 'Processing Math...';
       for (var i = 0; i < element.length; i++)
         {jsMath.ProcessElement(element[i])}
       jsMath.ProcessComplete();
   },    },
       
   element: [],  // the list of math elements on the page    element: [],  // the list of math elements on the page
Line 4918  jsMath.Add(jsMath,{ Line 5822  jsMath.Add(jsMath,{
    *  Look up all the math elements on the page and     *  Look up all the math elements on the page and
    *  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 () {    GetMathElements: function (obj) {
     var element = [];      var element = [];
     var math = document.getElementsByTagName('DIV');      if (!obj) {obj = document}
       if (typeof(obj) == 'string') {obj = document.getElementById(obj)}
       if (!obj.getElementsByTagName) return
       var math = obj.getElementsByTagName('DIV');
     for (var k = 0; k < math.length; k++) {      for (var k = 0; k < math.length; k++) {
       if (math[k].className == 'math') {        if (math[k].className == 'math') {
         if (jsMath.renameOK) {math[k].setAttribute('NAME','_jsMath_')}          if (jsMath.Browser.renameOK && obj.getElementsByName) 
                  {math[k].setAttribute('NAME','_jsMath_')}
           else {element[element.length] = math[k]}            else {element[element.length] = math[k]}
       }        }
     }      }
     math = document.getElementsByTagName('SPAN');      math = obj.getElementsByTagName('SPAN');
     for (var k = 0; k < math.length; k++) {      for (var k = 0; k < math.length; k++) {
       if (math[k].className == 'math') {        if (math[k].className == 'math') {
         if (jsMath.renameOK) {math[k].setAttribute('NAME','_jsMath_')}          if (jsMath.Browser.renameOK && obj.getElementsByName) 
                  {math[k].setAttribute('NAME','_jsMath_')}
           else {element[element.length] = math[k]}            else {element[element.length] = math[k]}
       }        }
     }      }
     // this gets the SPAN and DIV elements interleaved in order      // this gets the SPAN and DIV elements interleaved in order
     if (jsMath.renameOK) {      if (jsMath.Browser.renameOK && obj.getElementsByName) {
       element = document.getElementsByName('_jsMath_')        element = obj.getElementsByName('_jsMath_');
     } else if (jsMath.hidden.sourceIndex) {      } else if (jsMath.hidden.sourceIndex) {
       element.sort(function (a,b) {return a.sourceIndex - b.sourceIndex});        element.sort(function (a,b) {return a.sourceIndex - b.sourceIndex});
     }      }
Line 4948  jsMath.Add(jsMath,{ Line 5857  jsMath.Add(jsMath,{
    *  and clean up any marked <SPAN> or <DIV> tags     *  and clean up any marked <SPAN> or <DIV> tags
    */     */
   ProcessComplete: function () {    ProcessComplete: function () {
     if (jsMath.renameOK) {      if (jsMath.Browser.renameOK) {
       var element = document.getElementsByName('_jsMath_');        var element = document.getElementsByName('_jsMath_');
       for (var i = element.length-1; i >= 0; i--) {        for (var i = element.length-1; i >= 0; i--) {
         element[i].removeAttribute('NAME');          element[i].removeAttribute('NAME');
       }        }
     }      }
       jsMath.hidden = jsMath.hiddenTop;
     jsMath.element = [];      jsMath.element = [];
     window.status = 'Done';      window.status = 'Done';
   }      if (jsMath.Browser.safariImgBug &&
           (jsMath.Controls.cookie.font == 'symbol' ||
            jsMath.Controls.cookie.font == 'image')) {
         //
         //  For Safari, the images don't always finish
         //  updating, so nudge the window to cause a
         //  redraw.  (Hack!)
         //
         setTimeout("window.resizeBy(-1,0); window.resizeBy(1,0);",2000);
       }
     },
     
     Element: function (name) {return document.getElementById('jsMath.'+name)}
     
 });  });
   
 /***************************************************************************/  
   
 /*  /***************************************************************************/
  *  We use a hidden <DIV> for measuring the BBoxes of things  
  */  
 jsMath.hidden = '<DIV CLASS="normal" ID="jsMath.Hidden" ' +   
       'STYLE="position:absolute; top:0 left:0;"></DIV>';  
 if (document.body.insertAdjacentHTML) {  
    document.body.insertAdjacentHTML('AfterBegin',jsMath.hidden);  
 } else {  
    document.write(jsMath.hidden);  
 }  
 jsMath.hidden = document.getElementById("jsMath.Hidden");  
   
 /*  /*
  *  Initialize everything   *  Initialize everything
  */   */
 jsMath.InitSource();  jsMath.Loaded();
 jsMath.InitBrowser();  jsMath.Controls.GetCookie();
 jsMath.InitStyles();  if (document.body) {jsMath.Setup.Body()}
   
 //make sure browser-specific loads are done before this  }}
 document.write('<SCRIPT>jsMath.CheckFonts()</SCRIPT>');  
   
 }  
   
 }  

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


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