function specialDays()
{
    /****
     **** Do not change anything inside this funciton specialDays!
     ****/
    this.MONTH=0; /* array index constant */
    this.DAY=1;   /* array index constant */
    this.YEAR=2;  /* array index constant */
    this.LINK=3;  /* array index constant */
    this.HTML=4;  /* array index constant */
    this.DATA = null; /* hold the data as it is added */
    this.init=function(){this.DATA=new Array();}
    this.length = function(){return this.DATA.length?this.DATA.length:0; }
    this.add = function(D,M,Y,L,HTML)
    {
        if(!this.DATA){alert("Init not called.");return;}
        var i=this.length();
        this.DATA[i]=new Array();
        this.DATA[i][this.MONTH]=M;
        this.DATA[i][this.DAY]=D;
        this.DATA[i][this.YEAR]=Y;
        this.DATA[i][this.LINK]=L;
        this.DATA[i][this.HTML]=HTML;
    }
    this.isSpecial=function(M,D,Y)
    {
        for(var j=0;j<this.length();j++)
        {
            if(D==this.DATA[j][this.DAY] && M==this.DATA[j][this.MONTH] && Y==this.DATA[j][this.YEAR])
            {
                return true;
            }
        }
        return false;
    }
    this.linkIs=function(M,D,Y)
    {
        for(var j=0;j<this.length();j++)
        {
            if(D==this.DATA[j][this.DAY] && M==this.DATA[j][this.MONTH] && Y==this.DATA[j][this.YEAR])
            {
                return this.DATA[j][this.LINK];
            }
        }
        return "ERROR: "+M+","+D+", "+Y;
    }
    this.messageIs=function(M,D,Y)
    {
        for(var j=0;j<this.length();j++)
        {
            if(D==this.DATA[j][this.DAY] && M==this.DATA[j][this.MONTH] && Y==this.DATA[j][this.YEAR])
            {
                return this.DATA[j][this.HTML];
            }
        }
        return "ERROR: "+M+","+D+", "+Y;
    }
}
var DATES=new specialDays();
DATES.init();

function isSpecialDay(_m,_d,_y)  {return DATES.isSpecial(_m,_d,_y);}
function specialMessage(_m,_d,_y){return DATES.messageIs(_m,_d,_y);}
function specialLink(_m,_d,_y){return DATES.linkIs(_m,_d,_y);}


var isIE=(document.all);
var isNS4=document.layers?true:false;
var isNS6=navigator.userAgent.indexOf("Gecko")!=-1?true:false;
/* old is set to be not IE, NS4 or NS6 or DOM */
var old = !(isIE||isNS4||isNS6||isDOM);
var yyy=+10;
var skn; /* holds the div/layer object */
function initPopup()
{
if(!old)
{
  if(isNS4) skn=document.d11;
  else if(isNS6) skn=document.getElementById("d11");
  else if(isIE) skn=document.all.d11.style;
  if(isNS4)
    document.captureEvents(Event.MOUSEMOVE);
  if(isNS6)
    document.addEventListener("mousemove", get_mouse, true);
  if(isNS4||isIE)
    document.onmousemove=get_mouse;
}
}
function popup(_m,_b)
{
  if(!skn)initPopup();
  var content ="<TABLE  WIDTH="+MESSAGE_WIDTH+" BORDER="+MESSAGE_BORDER_SIZE+" BORDERCOLOR="+MESSAGE_BORDER+" CELLPADDING="+MESSAGE_PADDING+" CELLSPACING=0 "+"BGCOLOR="+_b+">";
      content+="<TD ALIGN=center><span style='font-size:"+MESSAGE_FONT_SIZE+"'>";
      content+=_m;
      content+="</span></TD></TABLE>";
  if(old)
  {
    alert(_m);
    return;
  }
  else
  {
    yyy=Yoffset;
    if(isNS4)
    {
      skn.document.open();
      skn.document.write(content);
      skn.document.close();
      skn.visibility="visible";
    }
    else if(isNS6)
    {
      skn.innerHTML=content;
      skn.style.visibility="visible";
    }
    else if(isIE)
    {
      document.all("d11").innerHTML=content;
      skn.visibility="visible";
    }
  }
}

function get_mouse(e)
{
  if(!skn)initPopup();
  var x=(isNS4||isNS6)?e.pageX:event.x+document.body.scrollLeft;
  if(isNS4||isNS6)
    var y=e.pageY;
  if(isIE)
  {
    y=event.y;
    if(navigator.appVersion.indexOf("MSIE 4")==-1)
      y+=document.body.scrollTop;
  }
  if(isIE||isNS4)
  {
    skn.top=y+yyy;
    skn.left=x+Xoffset;
  }
  if(isNS6)
  {
    skn.style.top=y+yyy;
    skn.style.left=x+Xoffset;
  }
}


function removeBox()
{
  if(!skn)initPopup();
  if(!old)
  {
    if(isNS4)
    {
      skn.document.open();
      skn.document.write("");
      skn.document.close();
    }
    else if(isNS6)
    {
      skn.innerHTML="";
    }
    else if(isIE)
    {
      document.all("d11").innerHTML="";
    }
    yyy=-1000;
    skn.visibility="hidden";
  }
}

function showMessage(fld, msg)
{
      popup("<font color="+MESSAGE_FONT_COLOR+">"+msg+"</font>",MESSAGE_BACKGROUND);
}


var CURRENT_DATE_SHOWN=new Date();

function leapYear(year) {
  return (!(year % 4) && year % 100);
}

function getDays(month, year) {
  var ar = new Array(12);
  ar[0]  = 31; // January
  ar[1]  = (leapYear(year)) ? 29 : 28; // February
  ar[2]  = 31; // March
  ar[3]  = 30; // April
  ar[4]  = 31; // May
  ar[5]  = 30; // June
  ar[6]  = 31; // July
  ar[7]  = 31; // August
  ar[8]  = 30; // September
  ar[9]  = 31; // October
  ar[10] = 30; // November
  ar[11] = 31; // December
  return ar[month];
}

function getMonthName(month) {
  var ar = new Array(12)
  ar[0] = "January";
  ar[1] = "February";
  ar[2] = "March";
  ar[3] = "April";
  ar[4] = "May";
  ar[5] = "June";
  ar[6] = "July";
  ar[7] = "August";
  ar[8] = "September";
  ar[9] = "October";
  ar[10] = "November";
  ar[11] = "December";
  return ar[month];
}

function nextMonth()
{
  CURRENT_DATE_SHOWN.setDate(1);
  var pmonth=CURRENT_DATE_SHOWN.getMonth()+1;
  var pyear=CURRENT_DATE_SHOWN.getYear();
  if(pmonth>11)
  {
    pmonth=0;
    pyear=1+pyear;
  }
  if(pyear<1900)pyear+=1900;
  CURRENT_DATE_SHOWN.setYear(pyear);
  CURRENT_DATE_SHOWN.setMonth(pmonth);
}

/*
 * if _tf is true - set to current year january
 */
function setCal(_tf) {
  var now,year,month,date;
  now   = CURRENT_DATE_SHOWN;
  year  = now.getFullYear();
  month = now.getMonth();
  if(_tf){month=0;CURRENT_DATE_SHOWN.setMonth(month);}
  date  = now.getDate();
  now   = null;

  var firstDayInstance = new Date(year, month, 1);
  var firstDay         = firstDayInstance.getDay();
      firstDayInstance = null;

  var days = getDays(month, year);
  /*
   * return drawCal(firstDay, days, date, month, year);
   *
   * Plus 1 is required to get the dates (1,2,3,...) to be on the proper
   * day of the week.
   */
  return drawCal(firstDay + 1, days, date, month, year);
}

function drawCal(firstDay, lastDate, date, month, year) {
  var monthName=getMonthName(month);

  // create basic table structure
  var text  = "";             // initialize accumulative variable to empty string
      text += '<TABLE ALIGN="CENTER" BORDER=' + border + ' CELLSPACING=' + cellspacing + '>';
      text += '<tr><TH COLSPAN=7 HEIGHT=' + headerHeight + '>';
      text += "<span style='font-weight:"+headerWeight+";color:"+headerColor+";font-size:"+headerSize+"'>";
      text += monthName + '&nbsp;' + year;
      text += "</span>";
      text += '</TH></tr>';

  // variables to hold constant settings
  var openCol  = '<TD WIDTH=' + colWidth + ' HEIGHT=' + dayCellHeight + '>';
      openCol += "<span style='font-weight:"+dayWeight+";color:"+dayColor+";font-size:"+daySize+"'>";
  var closeCol = '</span></TD>';

  // create array of abbreviated day names
  var weekDay = new Array(7);
      weekDay[0] = "Sun";
      weekDay[1] = "Mon";
      weekDay[2] = "Tue";
      weekDay[3] = "Wed";
      weekDay[4] = "Thu";
      weekDay[5] = "Fri";
      weekDay[6] = "Sat";

 // create first row of table to set column width and specify week day
 text += '<TR ALIGN="center" VALIGN="center">';
 for (var dayNum = 0; dayNum < 7; ++dayNum)
 {
   text += openCol + weekDay[dayNum] + closeCol;
 }
 text += '</TR>'
 // declaration and initialization of two variables to help with tables
 var digit   = 1;
 var curCell = 1;
 for (var row = 1; row <= Math.ceil((lastDate + firstDay - 1) / 7); ++row)
 {
   text += '<TR HEIGHT="+todaycellHeight+" ALIGN="right" VALIGN="top">'
   for (var col = 1; col <= 7; ++col)
   {
     if (digit > lastDate)
     {
       for(var a=0;a<=(7-col);a++)
       {
         text += '<TD BGCOLOR="'+nottodayBGColor+'" >';
         text += "<span style='font-weight:"+nottodayWeight+";color:"+nottodayColor+";font-size:"+todaySize+"'>";
         text += '&nbsp;';
         text += "</span>";
         text += '</TD>';
       }
       break;
     }
     if (curCell < firstDay)
     {
       text += '<TD BGCOLOR="'+nottodayBGColor+'" >';
       text += "<span style='font-weight:"+nottodayWeight+";color:"+nottodayColor+";font-size:"+todaySize+"'>";
       text += '&nbsp;';
       text += "</span>";
       text += '</TD>';
       curCell++;
     } else {
       if(isSpecialDay(month,digit,year)){
         text += '<TD ONMOUSEOVER="showMessage(\'txt1\', \''+specialMessage(month,digit,year)+'\')" ONMOUSEOUT="removeBox()" BGCOLOR="'+specialBGColor+'">';
         text += "<span style='font-weight:"+specialWeight+";color:"+specialColor+";font-size:"+todaySize+"' ";
         text += '>';
         var _sl=specialLink(month,digit,year);
         if(_sl)text += '<a href='+_sl+'>';
         text += digit;
         if(_sl)text += '</a>';
         text += "</span>";
         text += '</a>';
         text += '</TD>';
       } else if (digit == date && month==(new Date()).getMonth())
       { // current cell represent today's date
         text += '<TD BGCOLOR="'+todayBGColor+'">';
         text += "<span style='font-weight:"+todayWeight+";color:"+todayColor+";font-size:"+todaySize+"'>";
         text += digit;
         text += "</span>";
         text += '</TD>';
       } else {
         text += '<TD>';
         text += "<span style='font-weight:"+nottodayWeight+";color:"+nottodayColor+";font-size:"+todaySize+"'>";
         text += digit;
         text += "</span>";
         text += '</TD>';
       }
       digit++;
     }
   }
   text += '</TR>';
 }
 // close all basic table tags
 text += '</TABLE>';
 return (text);
}
