// Free Calendar

var MonthNumArray = new initArray("1","2","3","4","5","6","7","8","9","10","11","12");
var DAYShortArray = new initArray("S","M","T","W","T","F","S");

// option set 
var FAVOURITE_VIEW     =  1 ;
var COL_ROW            =  2 ;
var FONT_SIZE          =  3 ;
var TABLE_SIZE         =  4 ;
var TABLE_DENSE        =  5 ;
var DAY_NAME           =  6 ;
var MONTH_NAME         =  7 ;
var COLOR_FORMAT       =  8 ;
var BACKGROUND_IMAGE   =  9 ;
var SHOW_WEEK_HEADER   =  10;
var SHOW_MONTH         =  11;
var YEAR_VIEW          =  12;
var SHOW_OPTION        =  13;
var SHOW_TOOLBAR       =  14;

// language should be the last one
var VIEW_LANGUAGE      =  15;

// eval(string) should be used here

var OptionSetArrayName = new initArray ("favouriteViewArray","colXRowArray","fontSizeArray","sizeArray",
    "tableDenseArray","dayNameArray","monthNameArray","colorFormatArray","backgroundImageArray",
    "showWeekHeaderArray","showMonthArray","yearViewArray","showOptionArray",
    "showToolbarArray","languageArray");

// eval(string) should be used here,

var OptionIDVarName = new initArray ("favouriteView","colXRow","fontSize","tableSize",
    "tableDense","dayName","monthName","colorFormat","backgroundImage",
    "showWeekHeader","showMonth","yearView","showOption",
    "showToolbar","viewLanguage");

var  NON_FAVOURITE = 0,
  SMALLEST_DENSEST = 1,
          SMALLEST = 2,
       SMALL_DENSE = 3,
  SMALL_WITH_MONTH = 4,
   MIDDLE_3_MONTHS = 5,
      MIDDLE_DENSE = 6,
   BIGGEST_1_MONTH = 7,
BIG_WITH_SHORT_DAY = 8,
MIDDLE_B_W_NO_TOOL = 9;
// below donot includes favouriteView & language option
var FVA1 = new initArray(2,0,0,4,1,0,0,0,0,1,10,1,0);
var FVA2 = new initArray(0,0,0,0,0,0,0,0,1,1, 0,1,0);
var FVA3 = new initArray(0,0,0,2,1,0,0,0,1,1, 0,1,0);
var FVA4 = new initArray(0,0,0,0,1,0,0,2,1,0, 0,1,0);
var FVA5 = new initArray(0,1,0,0,0,0,0,2,1,0, 3,1,0);
var FVA6 = new initArray(0,1,0,2,0,0,0,0,1,1, 6,1,0);
var FVA7 = new initArray(0,2,2,0,2,0,0,1,1,0, 1,1,0);
var FVA8 = new initArray(0,2,2,0,0,0,0,1,1,0, 2,1,0);
var FVA9 = new initArray(0,2,0,0,0,0,1,2,1,0, 4,1,1);

// language
var ENGLISH = 0, CHINESE_CN = 1, CHINESE_TW = 2;

// fontSize/tableSize/backgroundImageSize
var SMALL = 0, MIDDLE = 1, LARGE = 2, EXTRA_LARGE = 3;

// tableDense
var NO_DENSE = 0, SLIGHT_DENSE = 1, V_DENSE = 2, H_DENSE = 3, ALL_DENSE = 4;

//display whole year in a table
var FULL_YEAR = 0, DISPLAY_1_MONTHS = 1, DISPLAY_2_MONTHS = 2, DISPLAY_3_MONTHS = 3,
DISPLAY_4_MONTHS = 4, DISPLAY_5_MONTHS = 5, DISPLAY_6_MONTHS = 6, DISPLAY_8_MONTHS = 7,
DISPLAY_9_MONTHS = 8, DISPLAY_10_MONTHS = 9, TWO_YEARS= 10;

//black/white view for print;
var COLOR_VIEW = 0, BLACK_WHITE = 1;

// show month header
var SHOW = 0, UN_SHOW = 1;

// show week header
var SHOW_ALL_HEADER = 0, TOP_HEADER_ONLY = 1;

// background image
var WORD_IMAGE = 0, NUMBER_IMAGE = 1, NO_IMAGE = 2;

// month name
var SHOW_LONG_NAME = 0, SHOW_SHORT_NAME = 1, SHOW_NUMBER = 2;

// dayName
var SHOW_LONG_NAME = 0, SHOW_SHORT_NAME = 1, SHOW_WHOLE_WORD = 2;

// number of months in each line
var V4X3 = 0, V3X4 = 1, V6X2 = 2, V2X6 = 3, V12X1 = 4, V1X12 = 5;

//initial

var bgPath = "images/";

var fontClassDate = "date";
var fontClassDateGray = "dategray";
var fontClassDateGrayInBlackWhiteView = "dategrayinbw";
var fontClassSunday = "datesunday";
var fontClassSaturday = "datesaturday";
var fontClassWeekendInBlackWhiteView = "dateweekendinbw";

var fontClassWeek = "week";
var fontClassWeekSunday = "week0";
var fontClassWeekSaturday = "week6";

var toYear = (new Date()).getYear();
var toMonth = (new Date()).getMonth();
var toDay = (new Date()).getDate();

var outOfMonth = false; // for columnNo = 5 & >7
var monthNameID = 0;
var dateMonthTableID = 0;
var weekNameID = 0;

// reserved option, all should be reset while reloading

var lastChangedOptionSet = 0;

var backgroundImageSize = MIDDLE;

var columnNo = 1;

var DAYa = DAYLongArray;
var MONTHa = MonthArray;

var startMonthNo = 0;
var monthLength = 12;

var highLightToday = false;


// --------------------------------------------------------------- function 

// called from html file
function gotoYear(yn) {

  if ((yn == "") || (yn == yearNo)) return;

  var yni = yn - yn;
  if (yni != 0) { alert("Please Input a Nubmer!"); return; }

  yn = toInteger(yn);
  yn = removePlus(yn);

  if (!confirm("View Calendar of Year " + yn + " ?")) return;

  yearNo = yn;
  writeFile();
}

function nextMonth() {

  monthNo++;
  if (monthNo > 11) {
    monthNo = monthNo - 12;
    yearNo++;
  }
  writeFile();
}

function lastMonth() {

  monthNo--;
  if (monthNo < 0) {
    monthNo = monthNo + 12;
    yearNo--;
  }
  writeFile();
}

function nextYear() { yearNo++; writeFile(); }
function lastYear() { yearNo--; writeFile(); }

function changeOption(seti, opti) {

  seti++;

  if (getSelectedOptionID(seti) != opti) {

    eval(OptionIDVarName[seti] + '= opti;');
    lastChangedOptionSet = seti;
    viewCalendar();
    return;
  }

  alert("View NO Changed!");
}

// ----------------------------------------------------- private function

function setOptions() {

  if (fontSize == EXTRA_LARGE) setFontSize(extraBigFontMap);
  else if (fontSize == LARGE) setFontSize(bigFontMap);
  else if (fontSize == SMALL) setFontSize(smallFontMap);
  else setFontSize(middleFontMap);
 
  var id = "";

  // for a css bug, should reset the style here instead of in css file
  for (var j = 1; j < dateMonthTableID + 1; j++) {

    if ((showWeekHeader == TOP_HEADER_ONLY) && ((j/columnNo) > 1)) break;

    id = "mt" + j;
    document.getElementById(id).style.backgroundPosition = "50% 66%";
  }

  var tableheight = "";

  if (tableSize == EXTRA_LARGE) tableheight = "1.8em";
  else if (tableSize == LARGE) tableheight = "1.6em";
  else if (tableSize == SMALL) tableheight = "1.2em";
  else tableheight = "1.35em";

  if ((tableDense == V_DENSE) || (tableDense == ALL_DENSE)) tableheight = "1.0em";
  else if (tableDense == SLIGHT_DENSE) tableheight = "1.1em";

  setAllTableHeight(tableheight);
}

function setFontSize (fontmap) {
  setFontSizeTo(fontmap[1], fontmap[2], fontmap[3], fontmap[4]);
}

function setFontSizeTo (ynof, mnf, df, dtf) {

  var id = "";

  if ((yearView == FULL_YEAR) || (yearView == TWO_YEARS)) {

    for (var i = yearNo; i < yearNo + 2; i++) {
      id = "yth" + i;
      document.getElementById(id).style.fontSize = ynof;
      if (yearView < TWO_YEARS) break;
    }
  }

  if (showMonth == SHOW) {
    for (var j = 1; j < monthNameID + 1; j++) {
      id = j + "m";
      document.getElementById(id).style.fontSize = mnf;
    }
  }

  for (var j = 1; j < weekNameID + 1; j++) {
    id = "w" + j;
    document.getElementById(id).style.fontSize = df;
  }

  for (var j = 1; j < dateMonthTableID + 1; j++) {
    id = "mt" + j;
    document.getElementById(id).style.fontSize = dtf;
  }
}

function setAllTableHeight (lh) {

  var id = "";

  if ((yearView == FULL_YEAR) || (yearView == TWO_YEARS)) {

    for (var i = yearNo; i < yearNo + 2; i++) {
      id = "yth" + i;
      document.getElementById(id).style.lineHeight = lh;
      if (yearView == FULL_YEAR) break;
    }
  }

//alert("monthNameID = " + monthNameID);//debug
  if (showMonth == SHOW) {
    for (var j = 1; j < monthNameID + 1; j++) {
      id = j + "m";
      document.getElementById(id).style.lineHeight = lh;
    }
  }

//alert("weekNameID = " + weekNameID);//debug
  for (var j = 1; j < weekNameID + 1; j++) {
    id = "w" + j;
    document.getElementById(id).style.lineHeight = lh;
  }

//alert("dateMonthTableID = " + dateMonthTableID);//debug
  for (var j = 1; j < dateMonthTableID + 1; j++) {
    id = "mt" + j;
    document.getElementById(id).style.lineHeight = lh;
  }
}

function checkOptions() {

  if (viewLanguage == ENGLISH) styleSheetFile = "normal";
  else if (viewLanguage == CHINESE_CN) styleSheetFile = "normal";
  else if (viewLanguage == CHINESE_TW) styleSheetFile = "normal";

  while (favouriteView > 0) {

    // just change language
    if (lastChangedOptionSet == VIEW_LANGUAGE) break;

    if ((lastChangedOptionSet != FAVOURITE_VIEW) && (lastChangedOptionSet != 0)) {
      favouriteView = NON_FAVOURITE;
      break;
    }

    var fvsettings = eval("FVA" + favouriteView);
    for (var i = 2; i < OptionIDVarName.length; i++) {  // donot change language here!!!
      eval(OptionIDVarName[i] + " = FVA" + favouriteView + "[i - 1];");
    }
    break;
  }

  if ((tableDense != NO_DENSE) && ((dayName == SHOW_WHOLE_WORD) || (dayName == SHOW_LONG_NAME))) {
    alert ("Whole or long name of day may be not displaying well in dense view! Please reset the options to narrow down the Day Name!");
  }

  if (yearView != FULL_YEAR) {

    if (lastChangedOptionSet == COL_ROW) {
      alert("This option can not be changed in month view! It can only be changed in Full Year view.");
      return false;
    }
  }

  return true;
}

function setReservedOptions() {

  if (yearView != FULL_YEAR) {

    if      (yearView == DISPLAY_1_MONTHS)  { columnNo = 1; startMonthNo = monthNo;     monthLength = 1;}
    else if (yearView == DISPLAY_2_MONTHS)  { columnNo = 2; startMonthNo = monthNo;     monthLength = 2;}
    else if (yearView == DISPLAY_3_MONTHS)  { columnNo = 3; startMonthNo = monthNo - 1; monthLength = 3;}
    else if (yearView == DISPLAY_4_MONTHS)  { columnNo = 2; startMonthNo = monthNo - 1; monthLength = 4;}
    else if (yearView == DISPLAY_5_MONTHS)  { columnNo = 5; startMonthNo = monthNo - 2; monthLength = 5;}
    else if (yearView == DISPLAY_6_MONTHS)  { columnNo = 3; startMonthNo = monthNo - 2; monthLength = 6;}
    else if (yearView == DISPLAY_8_MONTHS)  { columnNo = 4; startMonthNo = monthNo - 3; monthLength = 8;}
    else if (yearView == DISPLAY_9_MONTHS)  { columnNo = 3; startMonthNo = monthNo - 4; monthLength = 9;}
    else if (yearView == DISPLAY_10_MONTHS) { columnNo = 5; startMonthNo = monthNo - 4; monthLength = 10;}

  } else {

    if (colXRow == V3X4) columnNo = 3;
    else if (colXRow == V6X2) columnNo = 6;
    else if (colXRow == V2X6) columnNo = 2;
    else if (colXRow == V12X1) columnNo = 12;
    else if (colXRow == V1X12) columnNo = 1;
    else columnNo = 4;

    startMonthNo = 0;
    monthLength = 12;

  }

//alert("columnNo="+columnNo);//debug

  if (dayName == SHOW_SHORT_NAME) DAYa = DAYShortArray;
  else if (dayName == SHOW_WHOLE_WORD) DAYa = DAYArray;
  else DAYa = DAYLongArray;
  
  if (monthName == SHOW_SHORT_NAME) MONTHa = MonthShortArray;
  else if (monthName == SHOW_NUMBER) MONTHa = MonthNumArray;
  else MONTHa = MonthArray;

  if (yearView < TWO_YEARS) highLightToday = true;
  else  highLightToday = false;

  if (backgroundImage != NO_IMAGE) {

    var bgims = ((tableSize * 0.35 + fontSize * 0.70) - ((tableDense + 1) * 0.15));
    if (bgims < 0) bgims = bgims * (-1);
    var bgimsstr = bgims + ".0";
    bgimsstr = bgimsstr.substring(0, bgimsstr.indexOf("."));
    backgroundImageSize = Number(bgimsstr);
  }
}

function viewCalendar() {

  if (!checkOptions()) return;
  writeFile();

}

function writeFile() {

  setReservedOptions();

  document.close();

  monthNameID = 0;
  dateMonthTableID = 0;
  weekNameID = 0;

  writeFileHeader();
  writeCalendar(yearNo);

  if (yearView == TWO_YEARS) writeCalendar(Number(yearNo) + 1);

  if (showToolbar == SHOW) writeToolbar();
  else document.writeln('<br>&nbsp&nbsp<font class=back><a href="calendar.html" title="' +
                         uiStrings[10] + '">' + uiStrings[11] + '</a></font><br><br>');

  if (showOption == SHOW) writeOptions();

  document.writeln('</body></html>');

  setOptions();

  if (lastChangedOptionSet == VIEW_LANGUAGE) {

    alert("This option will take effect at next change of view!");
  }
}

function writeOptions() {

    document.writeln('<font class=back>' + uiStrings[8] + '<br>');

    for (var i = 1; i < OptionSetNameArray.length + 1; i++) {

      var optionid = 0;
      eval ("optionid = " + OptionIDVarName[i] + " + 1;");
      var optionname = "";
      eval ("optionname = " + OptionSetArrayName[i] + "[optionid];");

      document.writeln("&nbsp&nbsp" + OptionSetNameArray[i] + " = " + optionname + "<br>");
    }

    document.writeln('</font>');

}

// file header

function writeFileHeader() {

  document.write('<html><head><meta http-equiv="Content-Type" content="text/html; charset=');
  if (viewLanguage == CHINESE_CN) document.writeln('iso-8859-1">');
  else if (viewLanguage == CHINESE_TW) document.writeln('iso-8859-1">');
  else document.writeln('iso-8859-1">');
  document.writeln();
  document.writeln('<Script Language="JavaScript">');
  document.writeln('var yearNo = ' + yearNo + ';');
  document.writeln('var monthNo = ' + monthNo + ';');
  
  for (var i = 1; i < OptionSetNameArray.length + 1; i++) {
    var id = 0;
    eval("id = " + OptionIDVarName[i] + ";");
    document.writeln('var ' + OptionIDVarName[i] + " = " + id + ';');
  }
  
  document.writeln('var styleSheetFile = "' + styleSheetFile + '";');

  document.writeln('</SCRIPT>');
  document.writeln();
  document.write('<Script Language="JavaScript" SRC="');
  if (viewLanguage == CHINESE_CN) document.writeln('strings.js"></SCRIPT>');
  else if (viewLanguage == CHINESE_TW) document.writeln('strings.js"></SCRIPT>');
  else document.writeln('strings.js"></SCRIPT>');

  document.writeln('<Script Language="JavaScript" SRC="calendar.js"></SCRIPT>');

  document.write('<title>Calendar Of Year ' + yearNo);
  if (yearView == TWO_YEARS) document.write('/' + (Number(yearNo) + 1));
  document.writeln('</title>');
  document.writeln('<LINK rel="STYLESHEET" href="' + styleSheetFile + '.css" type="text/css">');

  document.writeln('</head><body class=calendar>');

}

// file footer

function writeToolbar() {

  document.writeln();
  document.write('<form name="bar">');
  
  if (yearView != FULL_YEAR) document.writeln('<INPUT class=button TYPE="button" NAME="last" VALUE="' +
                                               uiStrings[4] + '" onClick="lastMonth()">');
  else document.writeln('<INPUT class=button TYPE="button" NAME="last" VALUE="' +
                         uiStrings[6] + '" onClick="lastYear()">');
  
  if (yearView != FULL_YEAR) document.writeln('<INPUT class=button TYPE="button" NAME="next" VALUE="' +
                                               uiStrings[5] + '" onClick="nextMonth()">');
  else document.writeln('<INPUT class=button TYPE="button" NAME="next" VALUE="' +
                         uiStrings[7] + '" onClick="nextYear()">');
  
  document.writeln(uiStrings[1] + '&nbsp&nbsp<INPUT class=text TYPE="text" NAME="Year" VALUE="' +
                   yearNo + '" size=4 onBlur="gotoYear(this.value)">');
  document.writeln(uiStrings[2]);
  document.writeln('<Select type="menus" name="optionset" onChange="showOptionSet(this.selectedIndex, this.form)">');
  
  for (var i = 1; i < OptionSetNameArray.length + 1; i++) {
    document.writeln('<OPTION value="set' + i + '">' + OptionSetNameArray[i] + '</OPTION>');
  }
  
  document.writeln('</SELECT>');
  
  document.writeln(uiStrings[3]);
  
  document.writeln('<Select type="menus" name="viewoption" onChange="changeOption(optionset.selectedIndex, this.selectedIndex)">');
  
  var selectedidofoptionset1 = getSelectedOptionID(1) + 1;
  var optionset1 = eval(OptionSetArrayName[1]);
  for (var i = 1; i < optionset1.length + 1; i++) {
    document.write('<OPTION ');
    if (i == selectedidofoptionset1) document.write('selected ');
    document.writeln('value="' + i + '">' + optionset1[i] + '</OPTION>');
  }
  
  document.writeln('</SELECT>&nbsp&nbsp');
  document.writeln('</form>');

}

function showOptionSet(idx, inForm) {

  if ((showMonth == UN_SHOW) && (idx + 1) == MONTH_NAME) {
    alert("Month Name option only function while month name is displaying.");
    return;
  }

  var optionText = new initArray();
  eval("optionText = " + OptionSetArrayName[idx + 1] + ";");

  var selectedOptionID = getSelectedOptionID(idx + 1);

  var optionArray = new initArray();

  for (var i = 0; i < optionText.length; i++) {
    optionArray[i] = new Option(optionText[i + 1], i);
    inForm.viewoption.options[i] = optionArray[i];

  }

  inForm.viewoption.options.length = optionText.length;
  inForm.viewoption.options[selectedOptionID].selected = true;

}


function getSelectedOptionID(seti) {

  var id = -1;
  eval("id = (" + OptionIDVarName[seti] + ");");
//alert(OptionIDVarName[seti]+"="+id);//debug
  return id;

}

function writeCalendar(y) {
  
  // start write calendar

  document.writeln();
  document.write('<table id="yt' + y + '" name=' + y + ' class=year align=top>');

  writeYearHeader(y);

  for (var i = 1; i < (monthLength/columnNo + 1); i++) {

    if (showMonth == SHOW) {
      document.write('<tr>');
      writeMonthName(i);
      document.writeln('</tr>');
    }

    var max = 0;
    if (outOfMonth) {
      max = monthLength - (monthLength/columnNo) * columnNo - 1;
    }

    document.writeln('<tr><td></td>');
    for (j = 0; j < columnNo; j++) {

      if ((outOfMonth) && (i > max)) break;

      document.writeln('<td colspan=7>');
      writeDateOfMonth(startMonthNo + ((i - 1) * columnNo) + j);
      document.writeln('</td><td></td>');
    }
    document.writeln('</tr>');

  }

  document.writeln('</table>');

} //finish ........... 


function writeDateOfMonth(m) {

  var y = yearNo;

  if (yearView == FULL_YEAR) {

    if (m > 11) return;

  } else {

    if (m > 11) {
      m = m - 12;
      y++;
    } else if (m < 0) {
      m = m + 12;
      y--;
    }
  }

  var fclass = fontClassDate;

  var d = 1;
  var dt = new Date(y, m, d); //first day of year
  var currentDate = getLastDayDate(dt, dt.getDay()); //first day to write
  var yearOfCurrentDate = y;
  var monthOfCurrentDate = m;

  d = currentDate.getDate();

  document.writeln();

  dateMonthTableID++;
  document.write('<table id="mt' + dateMonthTableID + '" name=m' + (m + 1) + ' class=month');

  if (backgroundImage != NO_IMAGE) {

    bgFile = bgPath + (m + 1);

    if (backgroundImage == NUMBER_IMAGE) bgFile = bgFile + "n";

    if (backgroundImageSize == SMALL) bgFile = bgFile + 's.gif';
    else if (backgroundImageSize == LARGE) bgFile = bgFile + 'b.gif';
    else bgFile = bgFile + '.gif';

    document.write(' background="' + bgFile + '">');

  } else document.write('>');

  if ((showWeekHeader == SHOW_ALL_HEADER) || ((showWeekHeader == TOP_HEADER_ONLY) && ((weekNameID/columnNo) < 1))) {
    weekNameID++;
    document.write('<tr id="w' + weekNameID + '">');
    writeWeekHeader();
    document.writeln('</tr>');
  }

  if (tableDense != NO_DENSE) document.writeln('<tr><td colspan=7>');

  for (var i = 1; i < 7; i++) { // week loop, max = 6

    if (tableDense == NO_DENSE) document.writeln('<tr>');

    for (var j = 1; j < 8; j++) { // day loop, 7 days

      if ((d > 23) || (d == 1) || ((monthOfCurrentDate == 2) && (d > 20))) {

        yearOfCurrentDate = currentDate.getYear();
        monthOfCurrentDate = currentDate.getMonth();
        if ((yearOfCurrentDate < 100) && (y > 100)) yearOfCurrentDate = yearOfCurrentDate + 1900;
      }


      if ((monthOfCurrentDate != m) || yearOfCurrentDate != y) {
      
        fclass = fontClassDateGray;
        if (colorFormat == BLACK_WHITE) fclass = fontClassDateGrayInBlackWhiteView;
      
      } else if (j == 1) {

        fclass = fontClassSunday;
        if (colorFormat == BLACK_WHITE) fclass = fontClassWeekendInBlackWhiteView;

      } else if (j == 7) {

        fclass = fontClassSaturday;
        if (colorFormat == BLACK_WHITE) fclass = fontClassWeekendInBlackWhiteView;

      } else {

        fclass = fontClassDate;

      }

      if ((highLightToday) && ((yearOfCurrentDate == toYear) &&
                               (monthOfCurrentDate == toMonth) &&
                               (d == toDay) )) fclass = "datetoday";

      // write a date here
      if (tableDense == NO_DENSE) document.write('<td>&nbsp<font class=' + fclass + '>' + d + '</font></td>');
      else document.write('&nbsp<font class=' + fclass + '>' + dateString(d, j) + '</font>');

      // calculate next day
      if ((d > 23) || (d == 1) || ((monthOfCurrentDate == 2) && (d > 20))) {
        currentDate = getNextDayDate(new Date(yearOfCurrentDate, monthOfCurrentDate, d), 1);
        d = currentDate.getDate();
      } else d++;


    } // end of day loop

    if (tableDense == NO_DENSE) document.writeln('</tr>');
    else document.writeln('<br>');

    if ((currentDate.getMonth() > m) || currentDate.getYear() > y) break;

  } // end of week loop
  
  if (tableDense == NO_DENSE) document.writeln('</table>');
  else document.writeln('</tr></table>');

  document.writeln();

} // end of write date


function writeYearHeader(year) {

  if ((yearView != FULL_YEAR) && (yearView != FULL_YEAR)) return;
  var colspannum = columnNo * 8 + 1;

  var yearstr = "";
  if (viewLanguage == ENGLISH) yearstr = uiStrings[9] + year;
  else yearstr = year + uiStrings[9];

  document.writeln();
  document.writeln('<tr><th id="yth' + year + '" colspan=' + colspannum + '><font class=year>' + yearstr + '</font></th></tr>');

}

function writeMonthName(q) {

  document.write('<td></td>');

  var m = startMonthNo + (Number(q) - 1) * columnNo; // m: 0 ... 11
  var y = yearNo;

  if (m < 0) {
    m = m + 12;
    y--;
  }

  for (var i = 1; i < (columnNo + 1); i++) {
//alert("mn="+(m+1));//debug

    if (m > 11) {

      if (yearView == FULL_YEAR) { outOfMonth = true; break; }
      else {
        m = m - 12;
        y++;
        if (m > (startMonthNo + monthLength - 1)){ outOfMonth = true; break; }
      }
    }

    m++;
    monthNameID++;
    document.write('<td id=' + monthNameID + 'm colspan=7><font class=month>');
    if (yearView != FULL_YEAR) document.write(y + ' - ');
    document.write(MONTHa[m] + '</font></td>');
    document.writeln('<td></td>');
  }

}

function writeWeekHeader() {

  var fclass = fontClassWeek;

  if (((tableDense == H_DENSE) || (tableDense == ALL_DENSE)) &&
      (dayName == SHOW_SHORT_NAME)) document.write('<th>');

  for (var j = 1; j < 8; j++) {

    if ((j == 1) && (colorFormat != BLACK_WHITE)) fclass = fontClassWeekSunday;
    else if ((j == 7) && (colorFormat != BLACK_WHITE)) fclass = fontClassWeekSaturday;
    else fclass = fontClassWeek;

    if (((tableDense == H_DENSE) || (tableDense == ALL_DENSE)) &&
      (dayName == SHOW_SHORT_NAME)) {

      document.write('<font class=' + fclass + '>');
      if (j != 1) document.write('&nbsp');
      document.write(DAYa[j] + '</font>');

    } else document.write('<th><font class=' + fclass + '>' + DAYa[j] + '</font></th>');

  }

  if (((tableDense == H_DENSE) || (tableDense == ALL_DENSE)) &&
      (dayName == SHOW_SHORT_NAME)) document.write('</th>');

}

function getNextDayDate(dt, n) {

  return new Date(dt.getYear(), dt.getMonth(), dt.getDate() + n);

}

function getLastDayDate(dt, n) {

  return new Date(dt.getYear(), dt.getMonth(), dt.getDate() - n);

}

function getArrayIDOf(value, a) {

  for (var i = 1; i < a.length; i++) {if (a[i] == v) return i;}
  return -1;

}

function toInteger(k) {
  idot = k.indexOf(".");
  if (idot < 0) return k;
  else return k.substring(0, idot);
}

function removePlus(k) {
  if (k.substring(0,1) == "+") return k.substring(1);
  else return k;
}

function dateString(dn, d) {

  var dd = dn;

  if ((tableDense == H_DENSE) || (tableDense == ALL_DENSE)){

    if (dn < 10) dd = "&nbsp" + dd ;

  } else {

    if (d == 1) { // Sunday

      if (dn < 10) dd = dd + "&nbsp";

    } else {

      if (dn < 10) dd = "&nbsp" + dd + "&nbsp";
      else dd = "&nbsp" + dd;
    }

  }

  return dd;
}