// TAB render engine (c) 2009-2003 Robert Gatliff     robert(at)flutetree.com

var gNoteLength=3*16;     // in 64th
var gMeasureLength=3*64;  // in 64th
var gWidthInBars=3;
var gFundamental=54;    // F#

var gfLandscape=((document.location+'').indexOf('?landscape')>0);
var gfExtrawide=((document.location+'').indexOf('?width=')>0);
var gfDiatonic=((document.location+'').indexOf('/diatonic/')>0); 
var gfScales=((document.location+'').indexOf('/scales/')>0);
var gfTools=((document.location+'').indexOf('/tools/')>0);

var gPercentWidth=90;
var gWidth=(gfLandscape?896:640);

if (gfExtrawide)
{
  gWidth=Number((document.location+'').substr((document.location+'').indexOf('?width=')+7));
  if (gWidth<640) gWidth=640;
  if (gWidth>2500) gWidth=2500;
}

var gPercent=0;
var gRhythm=0;
var gnStaff=0;
var gFingerStyle=(gfDiatonic?'RP1':'P14');

var gFormat="TB1";
var gfPopup=false;
var gfRhythm=true;
var gfLyrics=true;
var gfAlternateFingering=false;
var gfError=false;
var gGoBack="";
var gGoBackDesc="";
var gfSlide="";
var gfTriplet=0;

function OutputHandler() {
  this.doc = null;
}
OutputHandler.prototype.write = function(s) {
  if (s==null) s="";
  if (this.doc==null)
    document.write(s);
  else
    this.doc.write(s);
}
OutputHandler.prototype.writeln = function(s) {
  if (s==null) s="";
  if (this.doc==null)
    document.writeln(s);
  else
    this.doc.writeln(s);
}
OutputHandler.prototype.close = function() {
  if (this.doc!=null)
  {
    this.doc.close();
    this.doc=null;
  }
}
var output = new OutputHandler();

function setGoBack(back,desc)
{
  gGoBack=back;
  gGoBackDesc=desc;
}

function showRhythm(flag)
{
  gfRhythm=flag;
}

function showAlternateFingering(flag)
{
  gfAlternateFingering=flag;
}

function popup()
{
  var w=Math.floor(window.screen.width*0.8);
  if (w>680) w=680;
  var h=Math.floor(window.screen.height-180);
  if (h<300) h=300;
  var t=0;
  var l=Math.floor(w/8);

  gfPopup = true;
  var newwin=window.open('empty.html','_blank','toolbar,menubar,scrollbars,resizable,location,status,width='+w+',height='+h+',top='+t+',left='+l,true);
  output = new OutputHandler();
  output.doc=newwin.document.open("text/html","replace");
  newwin=null;
}

function webHeader()
{  
  output.writeln('<html>');
  output.writeln('<head>');
  output.writeln('<title>Melodies for Native American Flute - Flutetree.com</title>');
  output.writeln('<link rel="stylesheet" type="text/css" href="../../flutetree.css"></link>');
  output.writeln('<script language="javascript" src="setup.js" type="text/javascript"></script>');
  output.writeln('</head>');
  output.writeln('<body>');
}

function lyricStart()
{
  if (gFormatDB[gFormat].lyrics) { 
    output.writeln('<div class="LYRICBOX">'); 
  }
  else
  {
    output.writeln('<div class="HIDDEN">'); 
  }
}

function lyricFinish()
{
  output.writeln('</div>');
}

function footer()
{
  if (gfError)
  {
    output.writeln('<p>'+imgError('Other problem alerts exist in this screen.')+'The black alert triangle announces a problem exist.  The details of the problem are accessible by hovering your cursor over each triangle.</p>'); 
  }
  output.writeln('<br>');
}

function webFooter()
{
  output.writeln('</body>');
  output.writeln('</html>');
  output.close();
}

function windowWidth()
{
  if (parseInt(navigator.appVersion)>3)
  {
    if (navigator.appName=="Netscape")
    {
      return window.innerWidth-24;
    } else if (navigator.appName.indexOf("Microsoft")!=-1)
    {
      return document.body.offsetWidth-30;
    }
  }
  return 640;
}

function header(title,remark1,remark2,remark3)
{
  var i=(gfDiatonic?document.cookie.indexOf('fd='):document.cookie.indexOf('fs='));
  if (i>=0) gFingerStyle=document.cookie.substr(i+3,3);
  if (!(gFingerStyle in gFingerDB)) gFingerStyle=(gfDiatonic?'RP1':'P14');
  i=document.cookie.indexOf('fm=');
  if (i>=0) gFormat=document.cookie.substr(i+3,3);
  if (!(gFormat in gFormatDB)) gFormat='TB1';

  output.writeln('<form name="settings">');

  if (!gfExtrawide && !gfTools)
  {
    if (windowWidth()>830)
    {
      output.writeln('<div class="noprint" style="z-index:5;position:absolute;right:0px;"><b>:</b>&nbsp;<a class="LINK" href="javascript:changeWidth();">widescreen</a>&nbsp;</div>');
    }
  }

  output.writeln('<table width="'+gWidth+'" border="0" cellspacing="0" cellpadding="0">');
  output.writeln('  <tr class="HEADER">');
  output.writeln('    <td align="left" valign="middle">');
  if (gfPopup)
  {  
    output.writeln('<a class="LINK" href="javascript:close();">Formated by Flutetree.com</a>');
  }
  else
  {
    output.writeln('<a class="LINK" href="http://www.flutetree.com">Flutetree</a>&nbsp;<b>:</b>');
    output.writeln('<a class="LINK" href="../index.html">Songbook</a>&nbsp;<b>:</b>');
    output.writeln(' <a class="LINK" href="index.html">'+(gfDiatonic?'Diatonic&nbsp;Flutes':(gfScales?'Flute&nbsp;Scales':(gfTools?'Tools&nbsp;for&nbsp;Transposing':'Contemporary&nbsp;Native&nbsp;American&nbsp;Flute')))+'</a>&nbsp;<b>:</b>');
    if (gGoBackDesc.length>0) output.writeln('<a class="LINK" href="'+gGoBack+'">'+gGoBackDesc+'</a>&nbsp;<b>:');
  }
  output.writeln('    </td>');
  output.writeln('    <td align="right" valign="top">');
  output.writeln('      <font size="-2">Customized Fingering&nbsp;&amp;&nbsp;Format&nbsp;&darr;&nbsp;&nbsp;<br></font><select name="finger" style="width:280px;" onchange="changeFS(this);"'+((gfPopup)?" disabled":"")+'>');
  var option;
  for (option in gFingerDB)
  {
    output.write('           <option value="'+option+'"');
    if (option==gFingerStyle) output.write(' selected');
    output.writeln('>'+gFingerDB[option].name+'</option>');  
  }
  output.writeln('      </select>');
  output.writeln('    </td>');
  output.writeln('  </tr>');
  output.writeln('  <tr class="HEADER">');
  output.writeln('    <td align="left" valign="top" nowrap>');
  output.write('<big><b>'+title+'</b></big><br>');
  output.writeln();
  output.writeln('    </td>');
  output.writeln('    <td align="right" valign="top">');
  output.writeln('      <select name="format" style="width:280px;" onchange="changeFM(this);"'+((gfPopup)?" disabled":"")+'>');
  for (option in gFormatDB)
  {
    if (gfDiatonic && option=="TB0") continue;
    output.write('           <option value="'+option+'"');
    if (option==gFormat) output.write(' selected');
    output.writeln('>'+gFormatDB[option].name+'</option>');  
  }
  output.writeln('      </select>');
  output.writeln('    </td>');
  output.writeln('  </tr>');
  output.writeln('  <tr class="REMARKS">');
  output.writeln('    <td colspan="2" align="left" valign="top" nowrap>');
  if (remark1) output.write('&nbsp;&nbsp;&bull;&nbsp;&nbsp;'+remark1);
  if (remark2) output.write('&nbsp;&nbsp;&bull;&nbsp;&nbsp;'+remark2);
  if (remark3) output.write('&nbsp;&nbsp;&bull;&nbsp;&nbsp;'+remark3);
  output.writeln();
  output.writeln('    </td>');
  output.writeln('  </tr>');
  output.writeln('</table>');
  output.writeln('</form>');
}

function changeFS(chooser)
{
  gFingerStyle=chooser[chooser.selectedIndex].value;
  resetFS(gFingerStyle);
}

function resetFS(fingerStyle,fAlert,fDisableReload)
{
  var nDays = 365
  var today = new Date();
  var nextYear = new Date(today.getTime() + nDays*24*60*60*1000);

  if (fingerStyle in gFingerDB)
  {
    var topDomain=document.domain;
    if (topDomain.substr(0,4)=="www.") topDomain = topDomain.substr(4)
    if (topDomain.indexOf('\.')<0) topDomain='';
    if (topDomain.length>0) topDomain=topDomain='; domain='+topDomain;
    if (fAlert) alert('Changing fingering to '+gFingerDB[fingerStyle].name);
    document.cookie=(gfDiatonic?'fd=':'fs=')+fingerStyle+'; expires='+nextYear.toGMTString()+topDomain;
    if (document.cookie.length==0)
    {
      alert("Unable to set a finger style because you have disabled your browser's ability to accept cookies.");
    }
    if (!fDisableReload) document.location.reload();
  }
  else
  {
    alert('Unsupported finger style');
  }
}

function checkFSonload()
{
  var i=(document.location+'').indexOf(gfDiatonic?'?fd=':'?fs=');
  if (i>0)
  {
    var fingerStyle=(document.location+'').substr(i+4,3);
    resetFS(fingerStyle,false,true);
    document.location.replace((document.location+'').substr(0,i));
  }
}

function changeFSlink(option)
{
  if (option==gFingerStyle)
  {
    output.writeln(gFingerDB[option].name);
  }
  else if (option in gFingerDB)
  {
    output.writeln(wrapTag('a class="LINK" onMouseOver="status=\'Change fingering\';return true" onMouseOut="status=\'\';return true" href="javascript:resetFS(\''+option+'\',true);" title="Change to: '+gFingerDB[option].name+'"',gFingerDB[option].name));
  }
  else
  {
    output.writeln(wrapTag('b','BAD OPTION: '+option));
  }
}

function changeFM(chooser)
{
  gFormat=chooser[chooser.selectedIndex].value;
  
  var nDays = 365
  var today = new Date();
  var nextYear = new Date(today.getTime() + nDays*24*60*60*1000);
  var topDomain=document.domain;
  if (topDomain.substr(0,4)=="www.") topDomain = topDomain.substr(4)
  if (topDomain.indexOf('\.')<0) topDomain='';
  if (topDomain.length>0) topDomain=topDomain='; domain='+topDomain;
  document.cookie='fm='+gFormat+'; expires='+nextYear.toGMTString()+topDomain;
  if (document.cookie.length==0)
  {
    alert("Unable to set a format because you have disabled your browser's ability to accept cookies.");
  }
  document.location.reload();
}

function changeWidth()
{
  document.location.href=document.location+'?width='+windowWidth();
}

var gFormatDB = {
TB0:{name:"Melody, Rhythm, Fingering, and Lyrics",
     rows:4,tab:false,rhythm:true,fingering:true,lyrics:true},
TB1:{name:"Tablature, Rhythm, Fingering, and Lyrics",
     rows:4,tab:true,rhythm:true,fingering:true,lyrics:true},
TB2:{name:"Tablature, Fingering, and Lyrics",
     rows:4,tab:true,rhythm:false,fingering:true,lyrics:true},
TB3:{name:"Tablature, Rhythm, and Fingering",
     rows:4,tab:true,rhythm:true,fingering:true,lyrics:false},
TB4:{name:"Tablature, and Fingering",
     rows:5,tab:true,rhythm:false,fingering:true,lyrics:false},
TB5:{name:"Tablature, and Lyrics",
     rows:9,tab:true,rhythm:false,fingering:false,lyrics:true},
TB6:{name:"Tablature only",
     rows:11,tab:true,rhythm:false,fingering:false,lyrics:false}     
};

var gFingerDB = {
BH4:{name:"Barry Higgins (White Crow) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxg"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxx"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xoxxxo"],
  ["6xoxooo"],
  ["6oxxooo"],
  ["6ooxooo"],
  ["6ooxxxx"],
  ["6hxxxxg"],
  ["6hxxxxo"],
  ["6hxxxgo"],
  ["6hxxxoo"]
]},
BH7:{name:"Brent Haines (Woodsounds) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo","6xoxxoo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo","6oxoooo"],
  ["6oooooo"],
  ["6ooxxox"],
  ["6ooxxho"]
]},
BH6:{name:"Butch Hall (Standard fingering) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo","6xoxxoo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo","6oxoooo"],
  ["6oooooo"],
  ["6oxxxxx"],
  ["6oxxxxo"]
]},
BH1: { name: "Butch Hall (Classic fingering) 6-hole", fingering: [
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo", "6xoxxoo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxxoo"],
  ["6oooxoo", "6ooxooo"],
  ["6oooooo", "6oxxxxx"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
BH2: { name: "Butch Hall (Classic Alternative) 6-hole", fingering: [
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo", "6xoxxoo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6oxxooo"],
  ["6oooxoo", "6ooxooo"],
  ["6oxxxxx", "6oooooo"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
BH5: { name: "Butch Hall (Classic Bugle fingering) 6-hole", fingering: [
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xoxxoo","6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxxoo"],
  ["6oooxoo","6ooxooo"],
  ["6oooooo","6oxxxxx"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
BH3:{name:"Butch Hall (Older C-minor &amp; flute kit) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo","6xoxxoo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo","6oxoooo"],
  ["6oooooo"],
  ["6oxxxxx"],
  ["6oxxxxo"]
]},
EH1:{name:"Ed Hrebec (Spirit of the Woods Flutes) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oxxxxx"],
  ["6oxxxxh"],
  ["6oxxxxo"],
  ["6oxxxho"]
]},
JS1:{name:"John Sarantos (Songbooks) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oooooo"],
  ["6oxxxox"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
JP1:{name:"J.P. Gomez (Heartsong) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oxxxxx"],
  ["6oxxxox"],
  ["6oxxxxo"]
]},
KL1:{name:"Ken Light (Amon Olorin) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6oxoooo"],
  ["6oooooo"],
  ["6oxxxox"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
MA2:{name:"Michael Graham Allen (Coyote Oldman) 5-hole",fingering:[
  ["5xxwxxx"],
  ["5xxwxxq"],
  ["5xxwxxh"],
  ["5xxwxxo"],
  ["5xxwxox"],
  ["5xxwxoo"],
  ["5xxwoxo"],
  ["5xxwooo"],
  ["5xowxxo","5xowxho"],
  ["5xowxoo"],
  ["5xowooo"],
  ["5oxwooo","5oowxoo"],
  ["5oowooo"],
  ["5oxwxxx"],
  ["5oxwxox"],
  ["5oxwxxo"],
  ["5oxwxoo"]
]},
MA1:{name:"Michael Graham Allen (Coyote Oldman) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oxxxxx","6ooxxxx"],
  ["6oxxxox","6ooxxox"],
  ["6oxxxxo","6ooxxxo"],
  ["6oxxxoo"]
]},
MG1:{name:"Michael Gulino (Moonlight Creek) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oxxxxx","6ooxxxx"],
  ["6oxxxox","6ooxxox"],
  ["6oxxxxo","6ooxxxo"]
]},
HS1:{name:"Odell Borg (High Spirits) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oxxxxx","6ooxxxx"],
  ["6oxxxox","6ooxxox"],
  ["6oxxxxo","6ooxxxo"],
  ["6oxxxoo"]
]},
PH1:{name:"Pat Haran (Minor Key) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oooooo"],
  ["6oxxxxx"],
  ["6oxxxxo"]
]},
PH2:{name:"Pat Haran (Multi-Mode: Mode 1) 6-hole",fingering:[
  ["6xxxxxo"],
  ["6xxxxqo"],
  ["6xxxxho"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxxoo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxoox","6ooxoox"],
  ["6oooooo"],
  ["6oxxxxo"],
  ["6oxxxox"],
  ["6oxxxoo"]
]},
PH3:{name:"Pat Haran (Multi-Mode: Mode 5) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxqo"],
  ["6xxxxho"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxxoo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxoox","6ooxoox"],
  ["6oooooo"],
  ["6oxxxxo"],
  ["6oxxxox"],
  ["6oxxxoo"]
]},
FH2:{name:"Pentatonic (Mode 1) 5-large-hole",fingering:[
  ["5xxwxxx"],
  ["5xxwxxq"],
  ["5xxwxxh"],
  ["5xxwxxo"],
  ["5xxwxox"],
  ["5xxwxoo"],
  ["5xxwoxo"],
  ["5xxwooo"],
  ["5xowxox","5xowoxx"],
  ["5xowxoo"],
  ["5xowooo"],
  ["5oowxoo","5ohwooo"],
  ["5oowooo"],
  ["5oxwxxx","5xowxxx"],
  ["5oxwxox","5oowxxx"],
  ["5oxwxxo","5oowxxo"],
  ["5oxwxoo"]
]},
P41:{name:"Pentatonic (Mode 4) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxoxox"],
  ["6xxoxoo"],
  ["6xoxxoo"],
  ["6xooxoo"],
  ["6ooxxoo"],
  ["6oooxoo"],
  ["6xoxxxx"],
  ["6ooxxox"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
FH1:{name:"Popular Pentatonic (Mode 1) 5-small-hole",fingering:[
  ["5xxwxxx"],
  ["5xxwxxq"],
  ["5xxwxxh"],
  ["5xxwxxo"],
  ["5xxwxox"],
  ["5xxwxoo"],
  ["5xxwoxo"],
  ["5xxwooo"],
  ["5xowxxo","5xowxho"],
  ["5xowxoo"],
  ["5xowooo"],
  ["5oxwooo","5oowxoo"],
  ["5oowooo"],
  ["5oxwxxx"],
  ["5oxwxox"],
  ["5oxwxxo"],
  ["5oxwxoo"]
]},
P14:{name:"Popular Pentatonic (Mode 1) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oxxxxx","6ooxxxx"],
  ["6oxxxox","6ooxxox"],
  ["6oxxxxo","6ooxxxo"],
  ["6oxxxoo"]
]},
RC1:{name:"R. Carlos Nakai 6-hole tablature",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6oxoooo"],
  ["6oooooo"],
  ["6oxxxox"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
RH1:{name:"Rich Halliburton (Querencia Flutes) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oxxxxx"],
  ["6oxxxox"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
RV1:{name:"Russ Venable (Mode 1) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oxxxxx","6ooxxxx"],
  ["6oxxxox","6ooxxox"],
  ["6oxxxxo","6ooxxxo"],
  ["6oxxxoo"]
]},
WS1:{name:"Stephen O'Donnell (Watershed) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo","6xoxxoo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6oxxooo"],
  ["6oxoooo","6ooxooo"],
  ["6oxxxxx","6oooooo"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
TS1:{name:"Tom Stewart (Stellar) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxhoo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6ooxooo"],
  ["6oooooo"],
  ["6ooooxx"],
  ["6oooxxo"],
  ["6ooxxoo"]
]},
TS2:{name:"Tony Sawyer (NeoTraditional) 6-hole",fingering:[
  ["6xxxxxx"],
  ["6xxxxxq"],
  ["6xxxxxh"],
  ["6xxxxxo"],
  ["6xxxxox"],
  ["6xxxxoo"],
  ["6xxxoxo"],
  ["6xxxooo"],
  ["6xxoxoo"],
  ["6xxoooo"],
  ["6xoxooo"],
  ["6xooooo"],
  ["6oxoooo"],
  ["6ooxxoo"],
  ["6oxxxxx"],
  ["6oxxxxo"],
  ["6oxxxoo"]
]},
EX6:{name:"Blank for printing tablature exercises",fingering:[
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"],
  ["6bbbbbb"]
]}
};
if (gfDiatonic)
{
  gFingerDB = {
  RP1:{name:"Richard Payne (Toubat) 6-hole",fingering:[
    ["6xxxxxx"],
    ["6xxxxxh"],
    ["6xxxxxo"],
    ["6xxxxox"],
    ["6xxxxoo"],
    ["6xxxooo"],
    ["6xxoxxo","6xxoxoo"],
    ["6xxoooo"],
    ["6xoxooo"],
    ["6xooooo"],
    ["6oxoooo"],
    ["6oooooo"],
    ["6oxxxxx"],
    ["6hxxxxx"],
    ["6hxxxxo"],
    ["6hxxxox"],
    ["6hxxxoo"]
  ]},
    D51:{name:"Diatonic 5-hole",fingering:[
    ["5xxxxx"],
    ["5xxxxh"],
    ["5xxxxo"],
    ["5xxxox"],
    ["5xxxoo"],
    ["5xxoxo"],
    ["5xxooo"],
    ["5xoxxo"],
    ["5xoxoo"],
    ["5xoooo"],
    ["5oxooo"],
    ["5ooooo"],
    ["5hxxxxp"],
    ["5hxxxhp"],
    ["5hxxxop"],
    ["5hxxoop"]
  ]},
    PH4:{name:"Pat Haran (Multi-Mode: Major) 6-hole",fingering:[
    ["6xxxxoo"],
    ["6xxxoxo"],
    ["6xxxooo"],
    ["6xxoxoo"],
    ["6xxoooo"],
    ["6xoxxoo"],
    ["6xoxooo"],
    ["6xooooo"],
    ["6ooxoox","6ooxoxo"],
    ["6oooooo"],
    ["6oxxxxo"],
    ["6oxxxox"],
    ["6oxxxoo"]
  ]},
    PH5:{name:"Pat Haran (Multi-Mode: Mode 5) 6-hole",fingering:[
    ["6xxxxxx"],
    ["6xxxxxh"],
    ["6xxxxxo"],
    ["6xxxxqo"],
    ["6xxxxho"],
    ["6xxxxoo"],
    ["6xxxoxo"],
    ["6xxxooo"],
    ["6xxoxoo"],
    ["6xxoooo"],
    ["6xoxxoo"],
    ["6xoxooo"],
    ["6xooooo"],
    ["6ooxoox","6ooxoox"],
    ["6oooooo"],
    ["6oxxxxo"],
    ["6oxxxox"],
    ["6oxxxoo"]
  ]},
  RV2:{name:"Russ Venable Diatonic 6-hole",fingering:[
    ["6xxxxxx"],
    ["6xxxxxh"],
    ["6xxxxxo"],
    ["6xxxxox"],
    ["6xxxxoo"],
    ["6xxxooo"],
    ["6xxoxoo","6xxoxxo"],
    ["6xxoooo"],
    ["6xoxooo"],
    ["6xooooo"],
    ["6oxoooo"],
    ["6oooooo"],
    ["6oxxxxx"],
    ["6hxxxxx"],
    ["6hxxxxo"],
    ["6hxxxox"],
    ["6hxxxoo"]
  ]},
  EX6:{name:"Blank for printing tablature exercises",fingering:[
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"],
    ["6bbbbbb"]
  ]}
  };
}

var gImageDB = {
  attention:{w:20, h:20, title:"Error!"},
  dfermata:{w:18, h:8, title:"A fermata indicates holding the note much longer."},
  dig0:{w:11, h:15, title:""},
  dig1:{w:11, h:15, title:""},
  dig2:{w:11, h:15, title:""},
  dig3:{w:11, h:15, title:""},
  dig4:{w:11, h:15, title:""},
  dig5:{w:11, h:15, title:""},
  dig6:{w:11, h:15, title:""},
  dig7:{w:11, h:15, title:""},
  dig8:{w:11, h:15, title:""},
  dig9:{w:11, h:15, title:""},
  dot:{w:9, h:55, title:"Dotted notes are played 50% longer."},
  dotl:{w:9, h:55, title:"Dotted notes are played 50% longer."},
  dotr:{w:9, h:63, title:"Dotted rest are held 50% longer."},
  Dmaj:{w:37, h:63, title:"Toubat Tablature for the native american flute is denoted with the 2 sharps (key of D Major) and TAB."},
  Emaj:{w:37, h:63, title:"Nakai Tablature for the native american flute is denoted with the 4 sharps (key of E Major) and TAB."},
  f5hxxoop:{w:13, h:86, title:""},
  f5hxxxop:{w:13, h:86, title:""},
  f5hxxxhp:{w:13, h:86, title:""},
  f5hxxxxp:{w:13, h:86, title:""},
  f5ooooo:{w:13, h:86, title:""},
  f5oxooo:{w:13, h:86, title:""},
  f5oxxoo:{w:13, h:86, title:""},
  f5oxxoop:{w:13, h:86, title:""},
  f5oxxxo:{w:13, h:86, title:""},
  f5oxxxop:{w:13, h:86, title:""},
  f5oxxxh:{w:13, h:86, title:""},
  f5oxxxhp:{w:13, h:86, title:""},
  f5oxxxx:{w:13, h:86, title:""},
  f5oxxxxp:{w:13, h:86, title:""},
  f5xoooo:{w:13, h:86, title:""},
  f5xoxoo:{w:13, h:86, title:""},
  f5xoxxo:{w:13, h:86, title:""},
  f5xxooo:{w:13, h:86, title:""},
  f5xxoxo:{w:13, h:86, title:""},
  f5xxxoo:{w:13, h:86, title:""},
  f5xxxox:{w:13, h:86, title:""},
  f5xxxxo:{w:13, h:86, title:""},
  f5xxxxh:{w:13, h:86, title:""},
  f5xxxxhp:{w:13, h:86, title:""},
  f5xxxxx:{w:13, h:86, title:""},
  f5hxwxoo:{w:13, h:86, title:""},
  f5hxwxxh:{w:13, h:86, title:"Half-holing the bottom hole is difficult and unreliable.  Recommend trilling through the note or substituting another note."},
  f5hxwxxo:{w:13, h:86, title:""},
  f5hxwxxx:{w:13, h:86, title:""},
  f5ohwooo:{w:13, h:86, title:"Half-holing is difficult and unreliable.  Recommend an alternate fingering."},
  f5oowooo:{w:13, h:86, title:""},
  f5oowoxx:{w:13, h:86, title:""},
  f5oowxoo:{w:13, h:86, title:""},
  f5oowxox:{w:13, h:86, title:""},
  f5oowxxo:{w:13, h:86, title:""},
  f5oowxxx:{w:13, h:86, title:""},
  f5oxwooo:{w:13, h:86, title:""},
  f5oxwxoo:{w:13, h:86, title:""},
  f5oxwxox:{w:13, h:86, title:""},
  f5oxwxxo:{w:13, h:86, title:""},
  f5oxwxxx:{w:13, h:86, title:""},
  f5xowooo:{w:13, h:86, title:""},
  f5xowoxx:{w:13, h:86, title:""},
  f5xowxho:{w:13, h:86, title:"Half-holing the lower hole is difficult and unreliable.  Recommend an alternate fingering."},
  f5xowxoo:{w:13, h:86, title:""},
  f5xowxox:{w:13, h:86, title:""},
  f5xowxxo:{w:13, h:86, title:""},
  f5xowxxx:{w:13, h:86, title:""},
  f5xxwhoo:{w:13, h:86, title:"Half-holing the lower hole is difficult and unreliable.  Recommend an alternate fingering."},
  f5xxwooo:{w:13, h:86, title:""},
  f5xxwoxo:{w:13, h:86, title:""},
  f5xxwxoo:{w:13, h:86, title:""},
  f5xxwxox:{w:13, h:86, title:""},
  f5xxwxxh:{w:13, h:86, title:"Half-holing the bottom hole is difficult and unreliable.  Recommend trilling through the note or substituting another note."},
  f5xxwxxo:{w:13, h:86, title:""},
  f5xxwxxq:{w:13, h:86, title:"Quarter-holing the bottom hole is difficult to impossible on most flutes.  Recommend trilling through the note or substituting another note."},
  f5xxwxxt:{w:13, h:86, title:"Bottom hole is trilled, i.e., opened and closed repeatedly."},
  f5xxwxxx:{w:13, h:86, title:""},
  f6bbbbbb:{w:13, h:86, title:"Blank finger guide for Exercises."},
  f6hxxxgo:{w:13, h:86, title:""},
  f6hxxxho:{w:13, h:86, title:"Half-holing the lower hole is difficult and not reliable on many flutes."},
  f6hxxxoo:{w:13, h:86, title:""},
  f6hxxxox:{w:13, h:86, title:""},
  f6hxxxxg:{w:13, h:86, title:""},
  f6hxxxxh:{w:13, h:86, title:"Half-holing the bottom hole is difficult and not reliable on many flutes."},
  f6hxxxxo:{w:13, h:86, title:""},
  f6hxxxxx:{w:13, h:86, title:""},
  f6oooooo:{w:13, h:86, title:""},
  f6ooooxx:{w:13, h:86, title:""},
  f6oooxoo:{w:13, h:86, title:""},
  f6oooxox:{w:13, h:86, title:""},
  f6oooxxo:{w:13, h:86, title:""},
  f6ooxooo:{w:13, h:86, title:""},
  f6ooxoox:{w:13, h:86, title:""},
  f6ooxoxo:{w:13, h:86, title:""},
  f6ooxxoo:{w:13, h:86, title:""},
  f6ooxxho:{w:13, h:86, title:""},
  f6ooxxox:{w:13, h:86, title:""},
  f6ooxxxo:{w:13, h:86, title:""},
  f6ooxxxx:{w:13, h:86, title:""},
  f6oxoooo:{w:13, h:86, title:""},
  f6oxoxoo:{w:13, h:86, title:""},
  f6oxxooo:{w:13, h:86, title:""},
  f6oxxxho:{w:13, h:86, title:"Half-holing the lower hole may be difficult."},
  f6oxxxoo:{w:13, h:86, title:""},
  f6oxxxox:{w:13, h:86, title:""},
  f6oxxxxh:{w:13, h:86, title:"Half-holing the lower hole may be difficult."},
  f6oxxxxo:{w:13, h:86, title:""},
  f6oxxxxx:{w:13, h:86, title:""},
  f6xooooo:{w:13, h:86, title:""},
  f6xooxoo:{w:13, h:86, title:""},
  f6xoxooo:{w:13, h:86, title:""},
  f6xoxxoo:{w:13, h:86, title:""},
  f6xoxxxo:{w:13, h:86, title:""},
  f6xoxxxx:{w:13, h:86, title:""},
  f6xxhooo:{w:13, h:86, title:"Half-holing the lower hole is difficult and unreliable.  Recommend an alternate fingering."},
  f6xxoooo:{w:13, h:86, title:""},
  f6xxoxoo:{w:13, h:86, title:""},
  f6xxoxox:{w:13, h:86, title:""},
  f6xxoxxo:{w:13, h:86, title:""},
  f6xxtooo:{w:13, h:86, title:""},
  f6xxxhoo:{w:13, h:86, title:"Half-holing the lower hole is difficult and unreliable.  Recommend an alternate fingering."},
  f6xxxooo:{w:13, h:86, title:""},
  f6xxxoxo:{w:13, h:86, title:""},
  f6xxxoxx:{w:13, h:86, title:""},
  f6xxxxho:{w:13, h:86, title:"Half-holing the lower hole is difficult and unreliable.  Recommend an alternate fingering."},
  f6xxxxoo:{w:13, h:86, title:""},
  f6xxxxox:{w:13, h:86, title:""},
  f6xxxxqo:{w:13, h:86, title:"Quarter-holing is difficult and unreliable. Recommend trilling through the note or substituting another note."},
  f6xxxxto:{w:13, h:86, title:""},
  f6xxxxxg:{w:13, h:86, title:""},
  f6xxxxxh:{w:13, h:86, title:"Half-holing the bottom hole is difficult and unreliable.  Recommend trilling through the note or substituting another note."},
  f6xxxxxo:{w:13, h:86, title:""},
  f6xxxxxq:{w:13, h:86, title:"Quarter-holing the bottom hole is difficult to impossible on most flutes.  Recommend trilling through the note or substituting another note."},
  f6xxxxxt:{w:13, h:86, title:"Bottom hole is trilled, i.e., opened and closed repeatedly."},
  f6xxxxxx:{w:13, h:86, title:""},
  graphbarbar:{w:6, h:63, title:""},
  graphend:{w:9, h:63, title:"End"},
  graphNote:{w:1, h:3, title:""},
  graphrboth:{w:28, h:63, title:""},
  graphrend:{w:16, h:63, title:"Repeat"},
  graphrest:{w:11, h:63, title:"Rest"},
  graphrstart:{w:16, h:63, title:""},
  graphSpace:{w:2, h:2, title:""},
  graphStaff:{w:640, h:63, title:""},
  graphStaffExtrawide:{w:1250, h:63, title:""},
  graphStaffLandscape:{w:896, h:63, title:""},
  graphstart:{w:9, h:63, title:""},
  mbar:{w:2, h:63, title:""},
  mbarbar:{w:6, h:63, title:""},
  mend:{w:9, h:63, title:"End"},
  mpad:{w:4, h:63, title:""},
  mrboth:{w:28, h:63, title:""},
  mrend:{w:16, h:63, title:"Repeat"},
  mrstart:{w:16, h:63, title:""},
  msbar:{w:2, h:63, title:""},
  mstart:{w:9, h:63, title:""},
  n0d:{w:11, h:55, title:"Grace note, very short and optional."},
  n0dl:{w:11, h:55, title:"Grace note, very short and optional."},
  n0u:{w:11, h:55, title:"Grace note, very short and optional."},
  n0n:{w:7, h:55, title:"Denotes the following note is Natural."},
  n0s:{w:8, h:55, title:"Denotes the following note is Sharp."},
  n0ul:{w:11, h:55, title:"Grace note, very short and optional."},
  n1d:{w:17, h:55, title:"Whole note"},
  n1dl:{w:17, h:55, title:"Whole note"},
  n1u:{w:17, h:55, title:"Whole note"},
  n1ul:{w:17, h:55, title:"Whole note"},
  n2d:{w:17, h:55, title:"Half note"},
  n2dl:{w:17, h:55, title:"Half note"},
  n2u:{w:17, h:55, title:"Half note"},
  n2ul:{w:17, h:55, title:"Half note"},
  n4d:{w:17, h:55, title:"Quarter note"},
  n4dl:{w:17, h:55, title:"Quarter note"},
  n4u:{w:17, h:55, title:"Quarter note"},
  n4ul:{w:17, h:55, title:"Quarter note"},
  n8d:{w:17, h:55, title:"Eighth note"},
  n8dl:{w:17, h:55, title:"Eighth note"},
  n8u:{w:21, h:55, title:"Eighth note"},
  n8ul:{w:21, h:55, title:"Eighth note"},
  n16d:{w:17, h:55, title:"Sixteenth note"},
  n16dl:{w:17, h:55, title:"Sixteenth note"},
  n16u:{w:21, h:55, title:"Sixteenth note"},
  n16ul:{w:21, h:55, title:"Sixteenth note"},
  nn:{w:11, h:55, title:"Denotes the following note is Natural."},
  ns:{w:11, h:55, title:"Denotes the following note is Sharp."},
  r1:{w:11, h:63, title:"Whole rest"},
  r2:{w:11, h:63, title:"Half rest"},
  r4:{w:11, h:63, title:"Quarter rest"},
  r8:{w:11, h:63, title:"Eighth rest"},
  r16:{w:13, h:63, title:"Sixteenth rest"},
  rbreath:{w:11, h:63, title:"Breath marks are hints for where to take a slight pause and catch your breath."},
  rcaesura:{w:15, h:63, title:"A caesura indicates a long pause or waiting for the right time to continue when playing with others."},
  slided:{w:12, h:55, title:"Slide down to this note."},
  slideu:{w:12, h:55, title:"Slide up to this note."},
  staff:{w:640, h:63, title:""},
  staffExtrawide:{w:1250, h:63, title:""},
  staffLandscape:{w:896, h:63, title:""},
  template:{w:13, h:86, title:""},
  tied:{w:30, h:8, title:"These consecutive notes are tied together. Notes of the same pitch are played as one note that is extra long.  Notes of different pitches are slurred together."},
  tieu:{w:30, h:8, title:"These consecutive notes are tied together. Notes of the same pitch are played as one note that is extra long.  Notes of different pitches are slurred together."},
  TrebleClef:{w:25, h:63, title:"Treble Clef"},
  triplet1:{w:15, h:8, title:""},
  triplet2:{w:15, h:8, title:""},
  triplet3:{w:15, h:8, title:""},
  trill:{w:15, h:8, title:"Trilled note are played by rapidly opening and closing one of the normally closed holes for this note."},
  ts2x2:{w:17, h:63, title:""},
  ts2x4:{w:17, h:63, title:"2 beats per measure and a beat is a quarter note in duration."},
  ts3x2:{w:17, h:63, title:"2 beats per measure and a beat is a half note in duration."},
  ts3x4:{w:17, h:63, title:"3 beats per measure and a beat is a quarter note in duration."},
  ts3x8:{w:17, h:63, title:"3 beats per measure and a beat is an eighth note in duration."},
  ts4x4:{w:17, h:63, title:"4 beats per measure and a beat is a quarter note in duration."},
  ts5x4:{w:17, h:63, title:"5 beats per measure and a beat is a quarter note in duration."},
  ts6x2:{w:17, h:63, title:"6 beats per measure and a beat is a half note in duration."},
  ts6x4:{w:17, h:63, title:"6 beats per measure and a beat is a quarter note in duration."},
  ts6x8:{w:17, h:63, title:"6 beats per measure and a beat is an eighth note in duration."},
  ts7x8:{w:17, h:63, title:"7 beats per measure and a beat is an eighth note in duration."},
  ts8x2:{w:17, h:63, title:"8 beats per measure and a beat is a half note in duration."},
  ts9x4:{w:17, h:63, title:"9 beats per measure and a beat is a quarter note in duration."},
  ts9x8:{w:17, h:63, title:"9 beats per measure and a beat is an eighth note in duration."},
  ts12x8:{w:17, h:63, title:"12 beats per measure and a beat is an eighth note in duration."},
  tspad:{w:17, h:63, title:""}
};

function wrapTag(tag,content)
{
  var patTag=/^([a-zA-Z][a-zA-Z0-9]*)/;
  var parse = tag.match(patTag);
  if (parse)
  {
    return '<'+tag+'>'+content+'</'+parse[1]+'>';
  }
  return imgError('Bad tag: '+tag);
}

function loneTag(tag)
{
  return '<'+tag+' />'
}

function htmlImage(name,width,height,title,attributes)
{
  if (attributes) attributes=' '+attributes;
  if (title) return loneTag('img src="'+imgPath+name+'.gif" border="0" width="'+width+'" height="'+height+'" title="'+title+'"'+attributes);
  return loneTag('img src="'+imgPath+name+'.gif" border="0" width="'+width+'" height="'+height+'"'+attributes);
}

function img(name,width,height,title,attributes)
{
  if (name in gImageDB)
  {
    width = width || gImageDB[name].w;
    height = height || gImageDB[name].h;
    title = title || gImageDB[name].title;
    attributes = attributes || '';
    return htmlImage(name,width,height,title,attributes);
  }
  return imgError('Unknown image:'+name);
}

function imgError(msg)
{
  gfError=true;
  return img('attention',null,null,msg);
}

function imgWide(name)
{
  return img(name,'100%');
}

function imgRight(name)
{
  return img(name,null,null,null,'align="right"');
}

function dups(occurence,str)
{
  var result="";
  var i;
  for (i=0; i<occurence; i++) result=result+str;
  return result;
}      

function percentRound(percent)
{
  gPercent=gPercent+percent;
  percent=Math.round(percent);
  gPercent=gPercent-percent;
  return percent;
}

var noteOffset     = [0,0,1,1,2,3,3,4,4,5,5,6];
var noteAccidental = [0,0,0,0,0,0,0,0,0,0,0,0];
var noteSharp      = [0,0,0,0,0,0,0,0,0,0,1,0];
var noteNatural    = [1,0,1,0,0,1,0,1,0,0,0,0];
var noteSharpOrNatural = ['x','s','x','s','x','x','s','x','s','n','x','x'];

if (gfDiatonic)
{
//                    C C#D D#E F F#G G#A A#B 
    noteSharp      = [0,0,0,1,0,0,0,0,1,0,1,0];
    noteNatural    = [1,0,0,0,0,1,0,0,0,0,0,0];
  //noteSharpOrNatural = ['n','x','x','s','x','n','x','x','s','x','s','x'];
    noteSharpOrNatural = ['n','s','n','s','n','n','s','n','s','n','s','n'];
//                         C   C#  D   D#  E   F   F#  G   G#  A   A#  B 
//                         Cn                  Fn
};

function clearAccidentals()
{
  var i;
  for (i in noteAccidental) noteAccidental[i]=0;
}

function yOffsetNote(note)
{
  return 144-28*Math.floor(note/12)-4*noteOffset[note % 12];
}

function yOffsetGraph(note)
{
  return 56-3*(note-54);
}

function ledgerNote(note)
{
  return (((yOffsetNote(note)/4+10)%2)==0) ? "l" : "";
}

function directionNote(note,noteAhead)
{
  //noteAhead=noteAhead||note;
  if (note==59) return (noteAhead<59) ? "u": "d";
  return (note<59) ? "u": "d";
}

function parseNote(desc)
{
  var patNote=/^([a-gA-G])([\#b',]*)/;
  var parse = desc.match(patNote);
  if (parse)
  {
    var lettername=parse[1] || "C";
    var modifiers=parse[2] || "";
    var octave=4;
    var note="ABCDEFG".indexOf(lettername);
    if (note<0) 
    {
      note="abcdefg".indexOf(lettername);
      octave++;
    }
    if (note<0) return 0;
    
    note=((note+5)%7)*2;
    if (note>5) note--;

    var i;
    for (i=0;i<modifiers.length;i++) switch (modifiers.charAt(i))
    {
      case "#": note++; break;  
      case "b": note--; break;
      case "'": octave++; break;
      case ",": octave--; break;
    }
    note=note+octave*12;  
    return note;
  }
  return 0;
}

function parseLength(desc)
{
  var patDuration=/^([0-9]*)(\/?)([0-9]*)/;
  var parse = desc.match( patDuration );
  if (parse)
  {
    var numerator = parse[1] || "1";
    var denominator = parse[3] || "4";
    gNoteLength=Math.round(3*64*Number(numerator)/Number(denominator)); 
    return gNoteLength
  }
  return 0;
}

function parseMeter(desc)
{
  var patDuration=/^([0-9]*)(\/?)([0-9]*)/;
  var parse = desc.match( patDuration );
  if (parse)
  {
    var numerator = parse[1] || "4";
    var denominator = parse[3] || "4";
    gMeasureLength=Math.round(3*64*Number(numerator)/Number(denominator)); 

    if (gMeasureLength<3*48)
    {
      gNoteLength=3*8;
    }
    else
    {
      gNoteLength=3*16;
    }
    return "ts"+numerator+"x"+denominator;
  }
  return 0;
}

function parseWidth(desc)
{
  var patWidth=/^([0-9]+)/;
  var parse = desc.match(patWidth);
  if (parse)
  {
    gWidthInBars=Number(parse[1]);

    if (gfExtrawide)
    {
      gWidthInBars=Math.floor(gWidthInBars*((gWidth-87)/(640.0-87)));
    }
    else if (gfLandscape)
    {
      gWidthInBars=Math.floor(gWidthInBars*1.4);
    }

    return gWidthInBars;
  }
  return 0;
}

function parseFundamental(desc)
{
  gFundamental=parseNote(desc)||gFundamental;
  return gFundamental;
}

function parseDuration(desc)
{
  var patDuration=/([0-9]*)(\/?)([0-9]*)/;
  var parse = desc.match( patDuration );
  if (parse)
  {
    var numerator = parse[1] || "1";
    var denominator = "1"
    if (parse[2]) denominator = parse[3] || "2";
    return Math.round(gNoteLength*Number(numerator)/Number(denominator)); 
  }
  return 0;
}

function imgSlide()
{
  var temp;

  if (gfSlide.length==0)
  {
    temp="";
  }
  else
  {
    
    temp=img("slide"+gfSlide);
    gfSlide="";
  }

 return temp;
}

function imgAccidental(note,duration)
{
  if (Math.floor(duration)>=1)
  {
    if (noteAccidental[note%12])
    {
      noteAccidental[note%12]=0;
      return img("n"+noteSharpOrNatural[note%12]);
    }
    if (noteSharp[note%12])
    {
      if (noteAccidental[note%12-1]) return ""; //img("n0s");
      noteAccidental[note%12-1]=1;
      return img("ns");
    }
    if (noteNatural[note%12])
    {
      if (noteAccidental[note%12+1]) return ""; //img("n0n");
      noteAccidental[note%12+1]=1;
      return img("nn");
    }
  }
  else
  {
    if (noteAccidental[note%12])
    {
      noteAccidental[note%12]=0;
      return img("n0"+noteSharpOrNatural[note%12]);
    }
    if (noteSharp[note%12])
    {
      if (noteAccidental[note%12-1]) return ""; //img("n0s");
      noteAccidental[note%12-1]=1;
      return img("n0s");
    }
    if (noteNatural[note%12])
    {
      if (noteAccidental[note%12+1]) return ""; //img("n0n");
      noteAccidental[note%12+1]=1;
      return img("n0n");
    }
  }
  return "";
}

function fTripletDuration(duration)
{
  return (duration==4 || duration==8 || duration==16 || duration==32 || duration==64 || duration==128 || duration==256 || duration==512 || duration==1024)
}

function glyphForDuration(duration)
{
  duration=Math.floor(duration);
  
  if (fTripletDuration(duration)) duration=duration*3/2;
  
  if (duration>=3)
  {
    var reduce=3*64;
    while (reduce>duration)
    {
      reduce=reduce/2;
    }
    return 3*64/reduce;
  }
  return 0;
}

function dotsForDuration(duration)
{
  duration=Math.floor(duration);
  if (duration>=1)
  {
    var reduce=3*64;
    while (reduce>duration)
    {
      reduce=reduce/2;
    }
    var fraction=duration-reduce*Math.floor(duration/reduce);
    var dots=0;
    reduce=reduce/2;
    while (fraction>=reduce)
    {
      fraction=fraction-reduce;
      reduce=reduce/2;
      dots++;
    }
    return dots;
  }
  return 0;
}

function countRhythm(duration)
{
  var element="";
  var halfNote=gNoteLength/2;
  var beat=2;
  if (halfNote<3*8) beat=3;
  var i;
  if (duration<halfNote)
  {
    gRhythm+=duration;
    return element;
  }
  for (i=0; i<duration; i+=halfNote)
  {
    if (Math.floor(gRhythm/halfNote)%beat)
    {
      element=element+'<font color="#00004f">/</font>';
    }
    else
    {
      element=element+Math.floor(gRhythm/halfNote/beat+1);
    }
    gRhythm+=halfNote;
  }
  return element;
}


function formatLyric(str)
{
  var patLyric=/^([-_]*)([^-_]*)(.*)/;
  var parse;
  
  if (parse=str.match(patLyric))
  {
    str=wrapTag('table CLASS="LYRICS" width="100%" border="0" cellspacing="0" cellpadding="0"',
          wrapTag('tr',
                  ((parse[1].length>0)?wrapTag('td',parse[1]):'')+
                  wrapTag('td',parse[2])+
                  ((parse[3].length>0)?wrapTag('td',parse[3]):'')
                 )
               );          
  }
  return str;
}

function Symbols()
{
  this.list = new Array();
}

Symbols.prototype.add = function(strType,nNote,strStaff,strGraph,strAnnotation,strFinger,strRhythm,strLyric)
{
  strType=strType||"blank";
  nNote=nNote||0;
  strStaff=strStaff||"";
  strAnnotation=strAnnotation||"<td></td>";
  strFinger=strFinger||"<td></td>";
  strRhythm=strRhythm||"<td></td>";
  strLyric=strLyric||"";
  strGraph=strGraph||"<td></td>";
  this.list[this.list.length]={type:strType,note:nNote,staff:strStaff,graph:strGraph,annotation:strAnnotation,finger:strFinger,rhythm:strRhythm,lyric:strLyric};
}

function parseSong(desc,lyrics)
{
  desc = desc || '|';
  lyrics = lyrics || '';
  gfLyrics=(lyrics.length>0);
  gRound=0;
  gfSlide="";
  gfTriplet=0;
    
  var patLyrics=/^([^\/]*)(\/?)(.*)/;
  var patNote=/^([a-gA-G][\#b',]*)([0-9]*\/?[0-9]*)([\+\~\^]*)(.*)/;
  var patNoteAhead=/^\s*([a-gA-G][\#b',]*)/;
  var patGraceLookahead=/^\s*[a-gA-G][\#b',]*0/;
  var patSleep=/^z([0-9]*\/?[0-9]*)(.*)/;
  var patRest=/^r([0-9]*\/?[0-9]*)(.*)/;
  var patMeter=/^\[M\:([0-9]*\/?[0-9]*)\](.*)/;
  var patLength=/^\[L\:([0-9]*\/?[0-9]*)\](.*)/;
  var patBeats=/^\[B\:([0-9]*)\](.*)/;
  var patWidth=/^\[W\:([0-9]*)\](.*)/;
  var patDebug=/^\[D\:([0-9]*)\](.*)/;
  var patFundamental=/^\[F\:([a-gA-G][\#b',]*)\](.*)/;
  var patBarThickRepeat=/^\[\:(.*)/;
  var patBarThinThick=/^\|\](.*)/;
  var patBarThinThin=/^\|\|(.*)/;
  var patBarThin=/^\|(.*)/;
  var patLookheadForBar=/\s*|/;
  var patBarThickThin=/^\[\|(.*)/;
  var patBarRepeatThinRepeat=/^\:\|\:(.*)/;
  var patBarRepeatThick=/^\:\](.*)/;
  var patWhitespace=/^\s+(.*)/;
  var patBreath=/^,(.*)/;
  var patCaesura=/^\/\/(.*)/;
  var patSlideUp=/^\/(.*)/;
  var patSlideDown=/^\\(.*)/;
  var patDiscard=/^.(.*)/;
  var parse;
  var parseAhead;
  var parseLyrics;
  var symbols = new Symbols();
  var duration;
  var nBar=0;
  var nMeasure=1;
  gnStaff=0;
  var blankElement="<td></td>";
  var xOffset=0;
  var nParseLimit=0;
  var fContinue=0;
  var nInc=0;
  var fRest=false;
  clearAccidentals();
  
  while (desc.length>0 && nParseLimit<1000)
  {
    nParseLimit++;

    if (parse=desc.match(patNote))
    {
      nInc=1;
      fRest=false;
      var note=parseNote(parse[1])+54-gFundamental;  // Transpose to F#
      if (gfDiatonic) note=note-4; // Transpose to D
      var textAhead=parse[4];
      var noteNext=0;
      var noteAhead=note;
      while ((noteNext==0 || noteAhead==59) && textAhead.length >0)
      {
        if (parseAhead=textAhead.match(patNoteAhead))
        {
          noteAhead=parseNote(parseAhead[1])+54-gFundamental;  // Transpose to F#
          if (gfDiatonic) noteAhead=noteAhead-4;  // Transpose to D
          if (noteNext==0) noteNext=noteAhead;
        }
        textAhead=textAhead.substr(1);
      }
      var duration=parseDuration(parse[2]);
      var width=percentRound(gPercentWidth*duration/(gMeasureLength*gWidthInBars));
      if (parse[4].match(patGraceLookahead)) width=width-1;
      if (width<1) width=1;
      xOffset = 0;
      if (noteSharp[note%12] || noteNatural[note%12] || noteAccidental[note%12]) xOffset=xOffset-4;
      var staffElement=
        wrapTag('td valign="top" nowrap width="'+width+'%"',
          wrapTag('div style="z-index:4;position:relative;left:'+xOffset+';top:'+yOffsetNote(note)+';"',
            imgSlide()+
            imgAccidental(note,duration)+
            img('n'+glyphForDuration(duration)+directionNote(note,noteAhead)+ledgerNote(note))+
            dups(dotsForDuration(duration),img('dot'+ledgerNote(note)))
          )     
        );
      var graphElement=
        wrapTag('td valign="top" nowrap width="'+width+'%"',
          wrapTag('table width="100%" border="0" cellspacing="0" cellpadding="0"',
            wrapTag('tr',
              wrapTag('td',wrapTag('div style="z-index:4;position:relative;left:0;top:'+yOffsetGraph(note)+';"',imgWide('graphNote')))+
              ((parse[3].indexOf("+")>=0)?"":wrapTag('td width=2',img('graphSpace')))
            )
          )     
        );
 
      var annotationElement='<td>';
      var trillOffset=0;
      var tieOffset=0;
      if (gFormatDB[gFormat].tab)
      {
        if (noteSharp[note%12] || noteNatural[note%12] || noteAccidental[note%12]) xOffset=xOffset+8;
        if (parse[4].match(patLookheadForBar)) tieOffset=4;

        
        if (parse[3].indexOf("+")>=0)
        {
          if (directionNote(note,noteAhead)=="d")
          {
            annotationElement+=wrapTag('div style="z-index:2;position:relative;width:100%;left:'+(xOffset+7+tieOffset)+';top:'+(yOffsetNote(note)-54)+';"',imgWide('tieu'));
          }
          else
          {
            annotationElement+=wrapTag('div style="z-index:2;position:relative;width:100%;left:'+(xOffset+7+tieOffset)+';top:'+(yOffsetNote(note)-29)+';"',imgWide('tied'));
          }
          if (note<=63) trillOffset= -8;
          else if (note<=64) trillOffset= -12;
          else trillOffset= -16;
        }

        if (note<=66)
        {
          trillOffset=trillOffset-63+5;
        }
        else
        {
          trillOffset=trillOffset-71+5;
        }

        if (parse[3].indexOf("~")>=0)
        {
          annotationElement+=wrapTag('div style="z-index:5;position:relative;left:'+(xOffset+3)+';top:'+trillOffset+';"',img('trill'));
          trillOffset=trillOffset-15;
        }
        else if (parse[3].indexOf("^")>=0)
        {
          annotationElement+=wrapTag('div style="z-index:5;position:relative;left:'+(xOffset)+';top:'+trillOffset+';"',img('dfermata'));
          trillOffset=trillOffset-15;
        }
        
        if (fTripletDuration(duration))
        {
          gfTriplet=gfTriplet+1;
          
          annotationElement+=wrapTag('div style="z-index:5;position:relative;left:'+(xOffset+3)+';top:'+trillOffset+';"',img('triplet'+gfTriplet));
          
          if (gfTriplet==3) gfTriplet=0;
        }
      }
      else
      {
        if (parse[3].length>0)
        {
          if (parse[3].indexOf("+")>=0)
          {
            if (note!=noteNext)
            {
              annotationElement+=wrapTag('div style="z-index:2;position:relative;width:100%;left:'+(16)+';top:'+(yOffsetGraph(Math.max(note,noteNext))-73)+';"',imgRight('tieu'));
              trillOffset= -8;
            }
          }
          if (parse[3].indexOf("~")>=0)
          {
            annotationElement+=wrapTag('div style="z-index:5;position:relative;left:'+(0)+';top:'+(trillOffset+yOffsetGraph(note)-73)+';"',img('trill'));
            trillOffset= -8;
          }
          else if (parse[3].indexOf("^")>=0)
          {
            annotationElement+=wrapTag('div style="z-index:5;position:relative;left:'+(0)+';top:'+(trillOffset+yOffsetGraph(note)-73)+';"',img('dfermata'));
          }
        }
      }
      annotationElement+='</td>';
      var fingerElement;
      var fingerFundamental=(gfDiatonic?50:54); 
      if (note>=fingerFundamental && note<fingerFundamental+gFingerDB[gFingerStyle].fingering.length)
      {
        fingerElement='';
        var iFingering;
        for (iFingering=0; iFingering<gFingerDB[gFingerStyle].fingering[note-fingerFundamental].length;iFingering++)
        {
          if (gfAlternateFingering && iFingering>0) fingerElement+='<br>';
          var fingerPic=gFingerDB[gFingerStyle].fingering[note-fingerFundamental][iFingering];
          if (parse[3].indexOf('~')>=0) fingerPic=fingerPic.replace(/h/g,"t");
          fingerElement+=img('f'+fingerPic);
          if (!gfAlternateFingering) break;
        }
        if (fContinue==note)
        {
          fingerElement=wrapTag('td','');
        }
        else
        {
          fingerElement=wrapTag('td',fingerElement);
        }
        fContinue=(parse[3].indexOf("+")>=0)?note:0;
      }
      else
      {
        fingerElement=wrapTag('td',imgError('This note is outside the range of the selected instrument and its fingering.')); 
      }
      var rhythmElement=wrapTag('td',wrapTag('div style="z-index:2;position:relative;left:4;"',countRhythm(duration)));

      var lyricElement='';
      if (parseLyrics=lyrics.match(patLyrics))
      {
        lyricElement=formatLyric(parseLyrics[1]);
        lyrics=parseLyrics[3];
      }

      symbols.add('note',note,staffElement,graphElement,annotationElement,fingerElement,rhythmElement, lyricElement);

      desc=parse[4];
    }
    else if (parse=desc.match(patSleep))
    {
      var duration=parseDuration(parse[1]);
      var width=percentRound(gPercentWidth*duration/(gMeasureLength*gWidthInBars));
      width=Math.round(10*width)/10;
      if (width<1) width=1;
      var rhythmElement=wrapTag('td',countRhythm(duration));

      symbols.add('sleep',0,wrapTag('td valign="top" nowrap width="'+width+'%"',img('mpad')),wrapTag('td valign="top" nowrap width="'+width+'%"',img('graphSpace')));
      desc=parse[2];
    }
    else if (parse=desc.match(patRest))
    {
      nInc=1; // BUGFIX: measures with rest should be counted
      var duration=parseDuration(parse[1]);
      var width=percentRound(gPercentWidth*duration/(gMeasureLength*gWidthInBars));
      width=Math.round(10*width)/10;
      if (width<1) width=1;
      var staffElement=
        wrapTag('td valign="top" nowrap width="'+width+'%"',
          img('r'+glyphForDuration(duration))+
            dups(dotsForDuration(duration),img('dotr'))
        );
      var graphElement;
      if (fRest)
      {
        graphElement=wrapTag('td valign="top" nowrap width="'+width+'%"','');
      }
      else
      {
        graphElement=wrapTag('td valign="top" nowrap width="'+width+'%"',img('graphrest'));
      }
      fRest=true;
      var rhythmElement=wrapTag('td',countRhythm(duration));

      var lyricElement='';
      if (parseLyrics=lyrics.match(patLyrics))
      {
        lyricElement=formatLyric(parseLyrics[1]);
        lyrics=parseLyrics[3];
      }
      
      symbols.add('rest',0,staffElement,graphElement,"","",rhythmElement,lyricElement);
      desc=parse[2];
    }
    else if (parse=desc.match(patMeter))
    {
      var timeSig = parseMeter(parse[1]);     
      var staffElement=
        wrapTag('td valign="top" nowrap',
          wrapTag('div style="z-index:2;position:relative;top:0;width:22;"',
            img(timeSig)
          )
        );
      symbols.add('time',0,staffElement,staffElement);
      desc=parse[2];
    }
    else if (parse=desc.match(patBeats))
    {
      gMeasureLength=Math.round(3*64*Number(parse[1])/(gNoteLength || 16)); 
      showRhythm(false);

      var timeSig = parseMeter(parse[1]);     
      var staffElement=
        wrapTag('td valign="top" nowrap',
          wrapTag('div style="z-index:2;position:relative;top:0;width:22;"',
            ""
          )
        );
      symbols.add('time',0,staffElement,staffElement);
      desc=parse[2];
    }
    else if (parse=desc.match(patLength))
    {
      parseLength(parse[1]);
      desc=parse[2];
    }
    else if (parse=desc.match(patWidth))
    {
      nBar=nBar%gWidthInBars;
      parseWidth(parse[1]);
      desc=parse[2];
    }
    else if (parse=desc.match(patFundamental))
    {
      parseFundamental(parse[1]);
      desc=parse[2];
    }
    else if (parse=desc.match(patBarThickRepeat))
    { 
      clearAccidentals();
      gRhythm=0;
      nBar+=nInc;nMeasure+=nInc;
      if ((nInc==0)||(nBar % gWidthInBars))
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mrstart')),wrapTag('td valign="top" nowrap align="right"',img('graphrstart')));
        if (parse[1].length>0) symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
      }
      else
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mbar')));
        if (parse[1].length>0) 
        {
          symbols.add('break',0,wrapTag('td valign="top" nowrap',''));
          //symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
          symbols.add('bar0',0,wrapTag('td valign="top" nowrap align="right"',img('mrstart')),wrapTag('td valign="top" nowrap align="right"',img('graphrstart')));
          if (!parse[1].match(patMeter))
            symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
        }
      }      
      desc=parse[1];
    }
    else if (parse=desc.match(patBarThinThick))
    { 
      clearAccidentals();
      gRhythm=0;
      nBar+=nInc;nMeasure+=nInc;
      if ((nInc==0)||(nBar % gWidthInBars))
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mend')),wrapTag('td valign="top" nowrap align="right"',img('graphend')));
        if (parse[1].length>0) 
        {
          symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
        }
        else
        {
          symbols.add('pad',0,wrapTag('td valign="top" nowrap width="'+Math.round(gPercentWidth*(gWidthInBars-(nBar % gWidthInBars))/gWidthInBars)+'%"',img('mpad')),wrapTag('td valign="top" nowrap width="'+Math.round(gPercentWidth*(gWidthInBars-(nBar % gWidthInBars))/gWidthInBars)+'%"',img('graphSpace')));
          symbols.add('bar0',0,wrapTag('td valign="top" nowrap align="right"',img('mbar')));
        }
      }
      else
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mend')),wrapTag('td valign="top" nowrap align="right"',img('graphend')));
        if (parse[1].length>0) 
        {
          symbols.add('break',0,wrapTag('td valign="top" nowrap',''));
          if (!parse[1].match(patMeter))
            symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
        }
      }      
      desc=parse[1];
    }
    else if (parse=desc.match(patBarThinThin))
    { 
      clearAccidentals();
      gRhythm=0;
      nBar+=nInc;nMeasure+=nInc;
      if ((nInc==0)||(nBar % gWidthInBars))
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mbarbar')),wrapTag('td valign="top" nowrap align="right"',img('graphbarbar')));
        if (parse[1].length>0) symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
      }
      else
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mbarbar')),wrapTag('td valign="top" nowrap align="right"',img('graphbarbar')));
        if (parse[1].length>0) 
        {
          symbols.add('break',0,wrapTag('td valign="top" nowrap',''));
          if (!parse[1].match(patMeter))
            symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
        }
      }      
      desc=parse[1];
    }
    else if (parse=desc.match(patBarThin))
    { 
      clearAccidentals();
      gRhythm=0;
      nBar+=nInc;nMeasure+=nInc;
      if ((nInc==0)||(nBar % gWidthInBars))
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mbar')));
        if (parse[1].length>0) symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
      }
      else
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mbar')));
        if (parse[1].length>0) 
        {
          symbols.add('break',0,wrapTag('td valign="top" nowrap',''));
          if (!parse[1].match(patMeter))
            symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
        }
      }      
      desc=parse[1];
    }
    else if (parse=desc.match(patBarThickThin))
    { 
      clearAccidentals();
      gRhythm=0;
      nBar+=nInc;nMeasure+=nInc;
      if ((nInc==0)||(nBar % gWidthInBars))
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mstart')),wrapTag('td valign="top" nowrap align="right"',img('graphstart')));
        if (parse[1].length>0) symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
      }
      else
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mbar')));
        if (parse[1].length>0) 
        {
          symbols.add('break',0,wrapTag('td valign="top" nowrap',''));
          //symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
          symbols.add('bar0',0,wrapTag('td valign="top" nowrap align="right"',img('mstart')),wrapTag('td valign="top" nowrap align="right"',img('graphstart')));
          if (!parse[1].match(patMeter))
            symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
        }
      }      
      desc=parse[1];
    }
    else if (parse=desc.match(patBarRepeatThinRepeat))
    { 
      clearAccidentals();
      gRhythm=0;
      nBar+=nInc;nMeasure+=nInc;
      if ((nInc==0)||(nBar % gWidthInBars))
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mrboth')),wrapTag('td valign="top" nowrap align="right"',img('graphrboth')));
        if (parse[1].length>0) symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
      }
      else
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mrend')),wrapTag('td valign="top" nowrap align="right"',img('graphrend')));
        if (parse[1].length>0) 
        {
          symbols.add('break',0,wrapTag('td valign="top" nowrap',''));
          //symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
          symbols.add('bar0',0,wrapTag('td valign="top" nowrap align="right"',img('mrstart')),wrapTag('td valign="top" nowrap align="right"',img('graphrstart')));
          if (!parse[1].match(patMeter))
            symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
        }
      }      
      desc=parse[1];
    }
    else if (parse=desc.match(patBarRepeatThick))
    {
      clearAccidentals();
      gRhythm=0;
      nBar+=nInc;nMeasure+=nInc;
      if ((nInc==0)||(nBar % gWidthInBars))
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mrend')),wrapTag('td valign="top" nowrap align="right"',img('graphrend')));
        if (parse[1].length>0) 
        {
          symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
        }
        else
        {
          symbols.add('pad',0,wrapTag('td valign="top" nowrap width="'+Math.round(gPercentWidth*(gWidthInBars-(nBar % gWidthInBars))/gWidthInBars)+'%"',img('mpad')),wrapTag('td valign="top" nowrap width="'+Math.round(gPercentWidth*(gWidthInBars-(nBar % gWidthInBars))/gWidthInBars)+'%"',img('graphSpace')));
          symbols.add('bar0',0,wrapTag('td valign="top" nowrap align="right"',img('mbar')));
        }
      }
      else
      {
        symbols.add('bar'+nInc,0,wrapTag('td valign="top" nowrap align="right"',img('mrend')),wrapTag('td valign="top" nowrap align="right"',img('graphrend')));
        if (parse[1].length>0) 
        {
          symbols.add('break',0,wrapTag('td valign="top" nowrap',''));
          if (!parse[1].match(patMeter))
            symbols.add('pad',0,wrapTag('td valign="top" nowrap',img('mpad')));
        }
      }      
      desc=parse[1];
    }
    else if (parse=desc.match(patWhitespace))
    { 
      //ignore whitespace
      desc=parse[1];
    }
    else if (parse=desc.match(patBreath))
    {
      symbols.add('breath',0,wrapTag('td valign="top" nowrap',img('rbreath')),wrapTag('td valign="top" nowrap',img('rbreath')));
      desc=parse[1];
    }
    else if (parse=desc.match(patCaesura))
    {
      symbols.add('rest',0,wrapTag('td valign="top" nowrap',img('rcaesura')),wrapTag('td valign="top" nowrap',img('rcaesura')));
      desc=parse[1];
    }
    else if (parse=desc.match(patSlideUp))
    {
      gfSlide="u";
      desc=parse[1];
    }
    else if (parse=desc.match(patSlideDown))
    {
      gfSlide="d";
      desc=parse[1];
    }
    else
    {
      parse=desc.match(patDiscard);
      symbols.add('error',0,wrapTag('td valign="top" nowrap',imgError('Measure '+(nMeasure)+' - Discarding unexpected symbol: '+desc.charAt(0))),wrapTag('td valign="top" nowrap',imgError('Measure '+(nMeasure)+' - Discarding unexpected symbol: '+desc.charAt(0))));
      desc=parse[1];
    }
  }
  symbols.add('end');
  
  return symbols;
}

function emitStaffStart(output)
{
  var maxRows=gFormatDB[gFormat].rows;
  if (gfLandscape || gfExtrawide)
  {
    maxRows=Math.round(maxRows/1.5);
  }
  if (gnStaff>0 && gnStaff%maxRows==0) output.writeln('<div class="PAGEBREAK">&nbsp;</div>');
  gnStaff++;
  output.writeln('<div style="position:relative;">');
  output.writeln('  <div style="z-index:0;position:absolute;">');
  if (gFormatDB[gFormat].tab)
  {
    if (gfExtrawide)
    {
      output.writeln('    '+img('staffExtrawide',gWidth));
    }  
    else if (gfLandscape)
    {
      output.writeln('    '+img('staffLandscape'));
    }  
    else
    {
      output.writeln('    '+img('staff'));
    }
  }
  else
  {
    if (gfExtrawide)
    {
      output.writeln('    '+img('graphStaffExtrawide',gWidth));
    }  
    else if (gfLandscape)
    {
      output.writeln('    '+img('graphStaffLandscape'));
    }  
    else
    {
      output.writeln('    '+img('graphStaff'));
    }
  }
  output.writeln('  </div>');
}

var gMeasureCount=0;

function emitStaffEnd(output,staffLine,graphLine,annotationLine,fingerLine,rhythmLine,lyricLine)
{
  output.writeln('  <div style="z-index:1;position:relative;left:0;top:0;width:'+gWidth+';">');
  output.writeln('    <table class="STAFF" width="'+gWidth+'" border="0" cellspacing="0" cellpadding="0">');
  
  if (gFormatDB[gFormat].tab)
  {
    output.writeln('      <tr height="63">');
    output.writeln('        '+wrapTag('td valign="top" nowrap',wrapTag('div style="z-index:2;position:relative;left:0;top:0;width:3"',img('msbar'))));
    output.writeln('        '+wrapTag('td valign="top" nowrap',wrapTag('div style="z-index:2;position:relative;left:0;top:0;width:25;"',img('TrebleClef'))));
    output.writeln('        '+wrapTag('td valign="top" nowrap',wrapTag('div style="z-index:2;position:relative;top:0;width:37;"',(gfDiatonic?img('Dmaj'):img('Emaj')))));
    output.write(staffLine);
    output.writeln('      </tr>');
  }
  else
  {
    output.writeln('      <tr height="63">');
    output.writeln('        '+wrapTag('td valign="top" nowrap',wrapTag('div style="z-index:2;position:relative;left:0;top:0;width:3"',img('graphSpace'))));
    output.writeln('        '+wrapTag('td valign="top" nowrap',wrapTag('div style="z-index:2;position:relative;left:0;top:0;width:25;"',img('graphSpace'))));
    output.writeln('        '+wrapTag('td valign="top" nowrap',wrapTag('div style="z-index:2;position:relative;top:0;width:37;"',img('graphSpace'))));
    output.write(graphLine);
    output.writeln('      </tr>');
  }
  
  output.writeln('      <tr class="ANNOTATION" height="8">');
  output.writeln('        <td><div style="z-index:0;position:absolute;"><small>&nbsp;&nbsp;&nbsp;&nbsp;'+(gMeasureCount>0?gMeasureCount:'')+'</small></div></td>');
  output.writeln('        <td></td>');
  output.writeln('        <td></td>');

  output.write(annotationLine);
  output.writeln('      </tr>');
  
  if (gfRhythm && gFormatDB[gFormat].rhythm)
  {
    output.writeln('      <tr class="RHYTHM">');
    output.writeln('        <td></td>');
    output.writeln('        <td></td>');
    output.writeln('        <td></td>');
    output.write(rhythmLine);
    output.writeln('      </tr>');
  }

  if (gFormatDB[gFormat].fingering)
  {
    output.writeln('      <tr class="FINGERING" height="86">');
    output.writeln('        <td></td>');
    output.writeln('        <td></td>');
    output.writeln('        <td></td>');
    output.write(fingerLine);
    output.writeln('      </tr>');
  }
  
  if (gFormatDB[gFormat].lyrics && gfLyrics)
  {
    output.writeln('      <tr class="LYRICS" height="24">');
    output.writeln('        <td></td>');
    output.writeln('        <td></td>');
    output.writeln('        <td>&nbsp;</td>');
    output.write(lyricLine);
    output.writeln('      </tr>');
  }
  
  output.writeln('    </table>');
  output.writeln('  </div>');
  output.writeln('</div>');
}

function emit(symbols)
{
  var i=0;
  var fStaffStarted=false;
  var staffLine="";
  var annotationLine="";
  var fingerLine="";
  var rhythmLine="";
  var lyricLine="";
  var graphLine="";
  var measureCount=1;
      
  while (i<symbols.list.length)
  {
    if (!fStaffStarted)
    {
      fStaffStarted=true;
      staffLine="";
      annotationLine="";
      fingerLine="";
      rhythmLine="";
      lyricLine="";
      graphLine="";

      emitStaffStart(output);
      gMeasureCount=measureCount;
    }
    if (symbols.list[i].type=="bar1")
    {
      measureCount=measureCount+1;
    }
    if (symbols.list[i].type=="break")
    {
      if ((gMeasureCount==1) && ((i+1)>=symbols.list.length)) gMeasureCount=0;

      emitStaffEnd(output,staffLine,graphLine,annotationLine,fingerLine,rhythmLine,lyricLine);
      fStaffStarted=false;
    }
    else
    {
      staffLine += '        '+symbols.list[i].staff+'\r';
      annotationLine += '        '+symbols.list[i].annotation+'\r';
      fingerLine += '        '+symbols.list[i].finger+'\r';
      rhythmLine += '        '+symbols.list[i].rhythm+'\r';
      lyricLine += '        <td>'+symbols.list[i].lyric+'</td>\r';
      graphLine += '        '+symbols.list[i].graph+'\r';
    }  
    i++;
  }
  if (fStaffStarted)
  {
    if ((gMeasureCount==1) && ((i+1)>=symbols.list.length)) gMeasureCount=0;

    emitStaffEnd(output,staffLine,graphLine,annotationLine,fingerLine,rhythmLine,lyricLine);
    fStaffStarted=false;
  }
}

function fixup(symbols)
{
  var i=0;
  var fStaffStarted=false;
  var fTie=false;

  while (i<symbols.list.length)
  {
    if (!fStaffStarted)
    {
      fStaffStarted=true;
      if  (symbols.list[i].type=="pad")
      {
        symbols.list[i].staff=wrapTag('td valign="top" nowrap',wrapTag('div style="z-index:2;position:relative;top:0;width:22;"',img('tspad')));
        symbols.list[i].graph=wrapTag('td valign="top" nowrap',wrapTag('div style="z-index:2;position:relative;top:0;width:22;"',img('graphSpace')));
        var note=symbols.list[i+1].note;
        if (fTie && note>0)
        {
          if (gFormatDB[gFormat].tab)
          {
            if (directionNote(note)=="d")
            {
              symbols.list[i].annotation=wrapTag('td',wrapTag('div style="z-index:2;position:relative;left:4;top:'+(yOffsetNote(note)-54)+';"',imgWide('tieu')));
            }
            else
            {
              symbols.list[i].annotation=wrapTag('td',wrapTag('div style="z-index:2;position:relative;left:4;top:'+(yOffsetNote(note)-34)+';"',imgWide('tied')));
            }
          }
          else
          {
            symbols.list[i].annotation=wrapTag('td',wrapTag('div style="z-index:2;position:relative;left:8;top:'+(yOffsetGraph(note)-73)+';"',img('tieu')));         
          }
          
        }      
        
        i++;
      }
    }
    if (symbols.list[i].type=="break")
    {
      fStaffStarted=false;
    }
    else if ((symbols.list[i].type.substr(0,3)!=="bar0")||(symbols.list[i].type.substr(0,3)!=="bar1"))
    {
      fTie=(symbols.list[i].annotation.indexOf("tie")>=0);
    }
    i++;
  }
}

function render(desc,lyrics)
{
  desc=desc.replace(/\r/g," ");
  desc=desc.replace(/\n/g," ");
  desc=desc.replace(/\t/g," ");
  desc=desc.replace(/\s*$/g,"");
  var symbols=parseSong(desc,lyrics);
  fixup(symbols);
  emit(symbols);
}

checkFSonload();


