// Constants should be UPPERCASE

// *************************************************************************************
// Basic utility functions
// *************************************************************************************
var IsNav = (navigator.appName == "Netscape");
var IsIE  = !IsNav;
var WindowWidth = window.screen.width;

function IsFramed()
{ return(top.frames.length > 0); }

function WriteStatusClock()
{
  var Today   = new Date();
  window.status = FormatDate(Today, DATETIME);
}
// *************************************************************************************
// from: http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287171
// *************************************************************************************
function MaxWindow()
{
  window.moveTo(0,0);

  if (document.all)
    { top.window.resizeTo(screen.availWidth, screen.availHeight); }

  else if (document.layers||document.getElementById)
    {
//      if ((top.window.outerHeight < screen.availHeight) ||
//          (top.window.outerWidth  < screen.availWidth))
        {
          top.window.outerHeight = screen.availHeight;
          top.window.outerWidth  = screen.availWidth;
        }
    }
}

// *************************************************************************************
// AssignArray(InArray)
//   returns a copy of the InArray (to avoid potential pass by value/reference problems)
// *************************************************************************************
function AssignArray(InArray)
{
  var RetVal = new Array();

  for (var Ix = 0; Ix < InArray.length; Ix++)
    RetVal[RetVal.length] = InArray[Ix];

  return(RetVal);
}

// *************************************************************************************
// *************************************************************************************
function WriteBody(Doc, MenuId, MenuItemIx)
{ 
  if (arguments.length == 2)
    Doc.write("<BODY " + top.GetBodyInfo(MenuId) + ">");
  else
    Doc.write("<BODY " + top.GetBodyInfo(MenuId) + 
              " ONLOAD=\"javascript:top.SetCurrSelected(" + MenuId + ", " + MenuItemIx + ");\">");
}

// *************************************************************************************
// Constants for Menu routines
// *************************************************************************************
var NOMENUIX        = -1;
var CURRSELECTEDIX  = 0;
var DEFAULTIX       = 1;
var OVERRIDEIX      = 2;
var CONTROLFRAMEIX  = 3;
var TARGETFRAMEIX   = 4;
var MENULAYOUTIX    = 5;
var MENUFILLERIX    = 6;

// Sub-indices into MenuItems
var HTMFILENAME         = 0;
var IMGFILENAME         = 1;
var DISPLAYNAME         = 2;
var HEIGHT              = 3;
var WIDTH               = 4;
var ALIGN               = 5;
var IMGIX               = 6;

var HORIZ = 0;
var VERT  = 1;

// *************************************************************************************
// Shortcut functions to get at items in MenuItems array.
//
// File names must be "images/<IMGNAME>[Selected|On|Off].gif" and be of the same size for Selected/On/Off files.
// Targets must be named <HTMFILENAME>.htm.

// Each menu item is configured:
//  [0] <HTMFILENAME> => the "<HTMLFILENAME>.htm" file loaded when menu item is selected
//  [1] <IMGFILENAME> => the "images/<IMAGEFILENAME[Selected|On|Off].gif files load when
//                       the menuitem is Selected, RolledOver, MouseOut conditions, respectively,
//  [2] <DISPLAYNAME> => the "ALT" name displayed when the menuitem is hovered over,
//  [3] <HEIGHT>      => the height in pixels of the menu image
//  [4] <WIDTH>       => the width in pixels of the menu image
//  [5] <ALIGN>       => LEFT or RIGHT (not implemented yet - LEFT only)
//  [6] <IMGIX>       => the internal index of the image, set internally

// Last item in each menu array is for general information for the menu, and is configured:
//  [0] CURRSELECTEDIX => internal use to store currently selected item, should be set to NOMENUIX here
//  [1] DEFAULTIX      => Default selection when menu is drawn
//  [2] OVERRIDEIX     => Override the default to jump to any page, should be set to NOMENUIX here
//  [3] CONTROLFRAME   => Frame to draw menu
//  [4] TARGETFRAME    => Frame to draw page
//  [5] MENULAYOUTIX   => HORIZ or VERT for horizontal or vertical (column) layout, respectively
//
// GetMenuLength(MenuId)
//   returns number of menu items (the menu info item is not counted)
//
// GetMenuInfo(MenuId)
//   returns the MenuInfo item
//
// GetCurrSelected(MenuId) 
//   returns the index of the currently selected item for MenuId
//
// SetCurrSelected(MenuId, MenuItemIx) 
//   sets index of the currently selected item for MenuId
//
// GetDefaultMenuIx(MenuId)
//   returns the default menu (starting) index
//
// GetOverrideMenuIx(MenuId)
//   returns the override menu (overriding default) index
//
// SetOverrideMenuIx(MenuId, MenuItemIx)
//   sets the override menu index
//
// GetInitialMenuIx(MenuId)
//   returns the override menu (overriding default) index, if set,
//     otherwise the default ix.
//     resets the override to default
//
// GetControlFrame(MenuId)
//   returns the control frame array
//
// GetTargetFrame(MenuId)
//   returns the target frame array
//
// GetMenuLayout(MenuId)
//   returns the menu layout (HORIZ/VERT)
//
// GetMenuFiler(MenuId)
//   returns the menu filler
// *************************************************************************************
function GetMenuLength(MenuId)
{ return(top.MenuItems[MenuId].length - 1); }

function GetMenuInfo(MenuId)
{ return(top.MenuItems[MenuId][top.GetMenuLength(MenuId)]); }

function GetCurrSelected(MenuId)
{ return(top.MenuItems[MenuId][top.GetMenuLength(MenuId)][CURRSELECTEDIX]); }

function SetCurrSelected(MenuId, MenuItemIx)
{
  var ControlDoc = top.GetControlDoc(MenuId);
  var CurrSelected = top.GetCurrSelected(MenuId);
    
  if (CurrSelected != top.NOMENUIX) //reset old image
    { ControlDoc.images[top.GetImageIx(MenuId, CurrSelected)].src = top.GetCurrentImageFileName(MenuId, "Off"); }
    
  if (MenuItemIx != top.NOMENUIX)
    ControlDoc.images[top.GetImageIx(MenuId, MenuItemIx)].src =
      top.GetImageFileName(MenuId, MenuItemIx, "Selected");

  top.MenuItems[MenuId][top.GetMenuLength(MenuId)][CURRSELECTEDIX] = MenuItemIx; 
}
    
function GetDefaultMenuIx(MenuId)
{ return(top.MenuItems[MenuId][top.GetMenuLength(MenuId)][DEFAULTIX]); }

function GetOverrideMenuIx(MenuId)
{ return(top.MenuItems[MenuId][top.GetMenuLength(MenuId)][OVERRIDEIX]); }

function SetOverrideMenuIx(MenuId, MenuItemIx)
{ top.MenuItems[MenuId][top.GetMenuLength(MenuId)][OVERRIDEIX] = MenuItemIx; }

function GetInitialMenuIx(MenuId)
{ 
  var Override = top.GetOverrideMenuIx(MenuId);

  if (Override == NOMENUIX)
    return(top.GetDefaultMenuIx(MenuId));

  top.SetOverrideMenuIx(MenuId, top.GetDefaultMenuIx(MenuId)); // reset Override
  return(Override);
}

function GetControlFrame(MenuId)
{ return(top.MenuItems[MenuId][top.GetMenuLength(MenuId)][CONTROLFRAMEIX]); }

function GetTargetFrame(MenuId)
{ return(top.MenuItems[MenuId][top.GetMenuLength(MenuId)][TARGETFRAMEIX]); }

function GetMenuLayout(MenuId)
{ return top.MenuItems[MenuId][top.GetMenuLength(MenuId)][MENULAYOUTIX]; }

function GetMenuFiller(MenuId)
{ return top.MenuItems[MenuId][top.GetMenuLength(MenuId)][MENUFILLERIX]; }

// *************************************************************************************
// GetHTMFileName(MenuId, MenuItemIx)
//   returns the HTM filename for this menu item
//
// GetImageName(MenuId, MenuItemIx)
//   returns the filename for this menu item
//
// GetImageFileName(MenuId, MenuItemIx, State)
//   returns the filename for this menu item and State where State is [On|Off|Selected]
//     filenames are in the format "images/<file> + State + ".gif"
//
// GetDisplayName(MenuId, MenuItemIx) 
//   returns the "ALT" of the image file
//
// GetCurrentImageName(MenuId) 
//   returns the name of the image file that is selected 
//
// GetCurrentImageFileName(MenuId, State)
//   returns the full file name for the currently selected item, State as above
// *************************************************************************************
function GetHTMFileName(MenuId, MenuItemIx)
{ return top.MenuItems[MenuId][MenuItemIx][HTMFILENAME] + ".htm"; }

function GetImageName(MenuId, MenuItemIx)
{ return top.MenuItems[MenuId][MenuItemIx][IMGFILENAME]; }

function GetMenuImageFileExt()
{ 
  var RetVal = ".jpg";
  if (top.OverrideMenuImageDefaultExt) RetVal = top.OverrideMenuImageDefaultExt();
  return(RetVal);
}

function GetImageFileName(MenuId, MenuItemIx, State)
//GIF/JPG{ return "images/" + top.MenuItems[MenuId][MenuItemIx][IMGFILENAME] + State + ".gif"; }
{ return "images/" + top.MenuItems[MenuId][MenuItemIx][IMGFILENAME] + State + GetMenuImageFileExt(); }

function GetDisplayName(MenuId, MenuItemIx)
{ return top.MenuItems[MenuId][MenuItemIx][DISPLAYNAME]; }

function GetImageIx(MenuId, MenuItemIx)
//{ return(top.MenuItems[MenuId][MenuItemIx][IMGIX]); }
{ return(top.MenuItems[MenuId][MenuItemIx][IMGFILENAME]); }

function SetImageIx(MenuId, MenuItemIx, Ix)
{ top.MenuItems[MenuId][MenuItemIx][IMGIX] = Ix; }

function GetCurrentImageName(MenuId)
{ return top.MenuItems[MenuId][GetCurrSelected(MenuId)][IMGFILENAME]; }

function GetCurrentImageFileName(MenuId, State)
//GIF/JPG{ return "images/" + MenuItems[MenuId][GetCurrSelected(MenuId)][IMGFILENAME] + State + ".gif"; }
{ return "images/" + MenuItems[MenuId][GetCurrSelected(MenuId)][IMGFILENAME] + State + GetMenuImageFileExt(); }

// *************************************************************************************
// If Menus are implemented as frames, the is a "Control" Frame (where the selection
//   items are) and a "Target" frame where the selection windows are drawn
//
// GetControlDoc(MenuId)
//   returns the document for the menu ("Control")
//
// GetTargetDoc(MenuId)
//   returns the document for the target frame
// *************************************************************************************
function GetControlDoc(MenuId)
{
  if (!IsFramed()) return(document);

  FrameData = top.GetControlFrame(MenuId);

  if (!isNaN(FrameData))
    return(top.frames[FrameData].document);

  var Frame = top;

  for (var Ix=0; Ix < FrameData.length; Ix++)
    { Frame = Frame.frames[FrameData[Ix]]; }

  return(Frame.document);
}

function GetTargetDoc(MenuId)
{
  if (!IsFramed()) return(document);

  FrameData = top.GetTargetFrame(MenuId);

  if (!isNaN(FrameData))
    return(top.frames[FrameData].document);

  var Frame = top;

  for (var Ix=0; Ix < FrameData.length; Ix++)
    { Frame = Frame.frames[FrameData[Ix]]; }

  return(Frame.document);
}

function MouseEvent(MenuId, MenuItemIx, OnOff) 
{
  var Doc = top.GetControlDoc(MenuId);

  if (MenuItemIx != top.GetCurrSelected(MenuId))
    Doc.images[top.GetImageIx(MenuId, MenuItemIx)].src = top.GetImageFileName(MenuId, MenuItemIx, OnOff);
}

// *************************************************************************************
// LoadMenu(MenuId)
//   Description :
//   MenuId      : Menu index into MenuItems 
//   Returns     : none
// *************************************************************************************
// Hack to fix problem in Navigator not rerunning JS code on resize
var ResizeMenuId;
function ResizeHandler()
{ 
  var MenuId = ResizeMenuId;
  var Doc = top.GetControlDoc(MenuId);

  for (var Ix = 0; Ix < top.GetMenuLength(MenuId); Ix++)
    { Doc.images[top.GetImageName(MenuId, Ix)].src = top.GetImageFileName(MenuId, Ix, "Off"); }

  top.SetCurrSelected(MenuId, top.GetCurrSelected(MenuId));
}

function LoadMenu(MenuId, MenuItemIx)
{
  var Doc = top.GetControlDoc(MenuId);
  var Ix;
  var MenuItemString  = ""; // a "<BR>" is written for vertical menus

  top.PreMenuData(Doc, MenuId);
 
  if (GetMenuLayout(MenuId) == HORIZ)
    {
      Doc.write("<TABLE BORDER=0 WIDTH=100%><TR><TD WIDTH=80% ALIGN=CENTER>");
    }
  else //VERT
    {
      //Change to "Filler" later Doc.write("<TABLE BORDER=0><TR><TD ALIGN=LEFT>");
      Doc.write("<BR><BR><TABLE BORDER=0><TR><TD ALIGN=LEFT>");
      MenuItemString = "<BR>";
      if (GetMenuFiller(MenuId) > 0)
        MenuItemString += "<IMG SRC=images/ClearPixel.gif WIDTH=1 HEIGHT=" + GetMenuFiller(MenuId) + "><BR>";
    }

  for (Ix = 0; Ix < top.GetMenuLength(MenuId); Ix++)
    {
      AnchorOn(Doc, MenuId, Ix);
      Doc.write(MenuItemString);
    }

  Doc.write("</TD></TR></TABLE>");
  top.PostMenuData(Doc, MenuId);

  for (Ix = 0; Ix < top.GetMenuLength(MenuId); Ix++)
    { Doc.images[top.GetImageName(MenuId, Ix)].src = top.GetImageFileName(MenuId, Ix, "Off"); }

  if (arguments.length > 1) top.SetCurrSelected(MenuId, MenuItemIx);

  if (IsNav) // hack for Navigator problem not rerunning JS code.
    {
      window.onresize = ResizeHandler;
      ResizeMenuId = MenuId;
    }
}

// *************************************************************************************
// MenuItemSelected(MenuId, MenuItemIx)
//   Description : Routine called when a MenuItem is selected. This routine updates
//                 the menu images, and calls a user-defined function "MenuItemAction"
//                 to perform whatever actions are required when a menu item is
//                 selected.
//   MenuId      : Menu index into MenuItems 
//   MenuItemIx  : Index of the item selected
//   Returns     : none
// *************************************************************************************
function MenuItemSelected(MenuId, MenuItemIx)
{
  if (top.GetCurrSelected(MenuId) == MenuItemIx) return;

  top.SetCurrSelected(MenuId, MenuItemIx);
  top.LoadDocument(MenuId, top.GetHTMFileName(MenuId, MenuItemIx));
}

// *************************************************************************************
// *************************************************************************************
function LoadDocument(MenuId, HTMFname)
{
  var TargetDoc  = top.GetTargetDoc(MenuId);

  //TargetDoc.location.replace(HTMFname);
  TargetDoc.location.href = HTMFname;
}

// *************************************************************************************
// *************************************************************************************
function MenuPageLoader(MenuId)
{
  var MenuItemIx = top.GetInitialMenuIx(MenuId);
  var Doc        = top.GetTargetDoc(MenuId);

  if (isNaN(MenuItemIx))
    Doc.location.replace(MenuItemIx);
  else
    Doc.location.replace(top.GetHTMFileName(MenuId, MenuItemIx));
}

// *************************************************************************************
// AnchorOn(Doc, MenuId, MenuItemIx)
//   Description :
//   MenuId      : Menu index into MenuItems 
//   MenuItemIx  : 
//   Returns     : none
// *************************************************************************************
function AnchorOn(Doc, MenuId, MenuItemIx)
{
  Doc.write("<A HREF='javascript:top." +
                "MenuItemSelected(" + MenuId + ", " + MenuItemIx + ");'" +
                "  ONMOUSEOUT = 'top.MouseEvent("   + MenuId + ", " + MenuItemIx + ", \"Off\");'" +
                "  ONMOUSEOVER= 'top.MouseEvent("   + MenuId + ", " + MenuItemIx + ", \"On\");'>");

  Doc.write("<IMG BORDER=0 HSPACE=0" +
            " ALT =\""  + top.GetDisplayName(MenuId, MenuItemIx)         + "\"" +
            " NAME=\""  + top.GetImageName(MenuId, MenuItemIx)           + "\"" +
            " SRC =\""  + top.GetImageFileName(MenuId, MenuItemIx, "On") + "\">");

  Doc.write("</A>");
//  top.SetImageIx(MenuId, MenuItemIx, Doc.images.length - 1);
}

// *************************************************************************************
// *************************************************************************************
function JumpTo(MenuId, MenuItemIx) // arg pairs in arguments[...]
{

  for (var Ix = 0; Ix < arguments.length; Ix += 2)
    { top.SetOverrideMenuIx(arguments[Ix], arguments[Ix + 1]); }

  top.MenuItemSelected(MenuId, MenuItemIx);
}

// *************************************************************************************
// *************************************************************************************
function FooterItem(MenuId, MenuItemIx, MenuSelectedIx)
{
  var AOpenStr  = "<A HREF=\"javascript:top.MenuItemSelected(" +
                          MenuId + ", " + MenuItemIx + ");\">";
  var ACloseStr = "</A>";

  if (MenuItemIx == MenuSelectedIx)
    {
      AOpenStr  = "";
      ACloseStr = ""; 
    }
  document.write(AOpenStr + "<B>" + top.GetDisplayName(MenuId, MenuItemIx) + "</B>" + ACloseStr);
}

function Footer(MenuId, MenuItemIx)
{
  var Doc = top.GetControlDoc(MenuId);

  top.PreFooterData(Doc, MenuId);

  document.write("<CENTER><FONT FACE=VERDANA, ARIAL, HELVETICA SIZE=2>");

  FooterItem(MenuId, 0, MenuItemIx);
  for (var Ix = 1; Ix < top.GetMenuLength(MenuId); Ix++)
    { 
      Doc.write(" | ");
      FooterItem(MenuId, Ix, MenuItemIx);
    }

  document.write("</FONT></CENTER>");

  top.PostFooterData(Doc, MenuId);
}

// *************************************************************************************
// Constants for FormatDate
// *************************************************************************************
// FormatTypes
var DATE                = 0;
var DATETIME            = 1;
var TIME                = 2;

// These must be in order Sunday..Saturday to match return codes from getDay.
DAYARRAY   = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");

// These must be in order Jabuary..December to match return codes from getMonth.
MONTHARRAY = new Array("January", "February", "March"    , "April"  , "May"     , "June",
                       "July"   , "August"  , "September", "October", "November", "December");

// *************************************************************************************
// FormatDate(InDate, FormatType)
//   Description : Takes a JavaScript DateTime value and returns a string
//   InDate      : DateTime value
//   FormatType  : DATE, DATETIME, TIME
//   Returns     : for DATE     => ***day, Month, Date, Year
//                 for DATETIME => ***day, Month, Date, Year hh:mm:ss [A|P]M (local time)
//                 for TIME     => hh:mm:ss [A|P]M (local time) 
// *************************************************************************************
function FormatDate(InDate, FormatType)
{
  var Day     = InDate.getDate();
  var End     = "th";
  var Year    = InDate.getYear();

  var RetStr  = DAYARRAY[InDate.getDay()] + ", " + MONTHARRAY[InDate.getMonth()] + " ";

  if (Day==1 || Day==21 || Day==31) End="st";
  if (Day==2 || Day==22)            End="nd";
  if (Day==3 || Day==23)            End="rd";

  RetStr += Day + End + ", ";

  if (IsNav) Year += 1900; //Netscape uses years since 1900.

  RetStr += Year;

  if (FormatType == DATE)
    return(RetStr);

  var Hours   = InDate.getHours();
  var Minutes = InDate.getMinutes();
  var Seconds = InDate.getSeconds()

  RetStr += " ";

  if (FormatType == TIME)
    RetStr = "";

  RetStr += ((Hours > 12) ? Hours - 12 : Hours);
  RetStr += ((Minutes < 10) ? ":0" : ":") + Minutes;
  RetStr += ((Seconds < 10) ? ":0" : ":") + Seconds;
  RetStr += (Hours >= 12) ? " P.M." : " A.M.";

  return(RetStr);
}

// *************************************************************************************
// *************************************************************************************
SORTNONE = -1;
SORTASC  = 0;
SORTDEC  = 1;

// *************************************************************************************
// *************************************************************************************
function ShouldSwap(First, Second, PriIx, PriOrder, SecIx, SecOrder)
// or, for arrays of non-arrays:
// function ShouldSwap(First, Second, PriOrder)
{
  // Hack for now for non-arrays
  if (arguments.length == 3) // Single (non-array) elements
    {
      var PriAscending = (PriIx == SORTASC);
      return(First > Second ? PriAscending : !PriAscending);
    }
  // End hack

  var PriAscending = (PriOrder == SORTASC);
  var SecAscending = (SecOrder == SORTASC);

  return(First[PriIx] == Second[PriIx] ? // Primaries equal
           (First[SecIx] == Second[SecIx] || SecOrder == SORTNONE ? false : // Secondaries also equal or don't care
              (First[SecIx] > Second[SecIx] ? SecAscending : !SecAscending)) : // Return Secondary check
        (First[PriIx] > Second[PriIx] ? PriAscending : !PriAscending)); // Primaries un-equal
}

// *************************************************************************************
// *************************************************************************************
function SortArray(InArray, PriIx, PriOrder, SecIx, SecOrder)
// or, for arrays of non-arrays:
// function function SortArray(InArray, PriOrder)
{
  var Ix, Temp, Last;
  var LastSwap = InArray.length - 1;

  // Hack for now for non-arrays
  if (arguments.length == 2)
    var Sorted = (PriIx == SORTNONE);
  else // End hack
    var Sorted = (PriOrder == SORTNONE);

  while (!Sorted)
    {
      Sorted = true;
      Last = --LastSwap;
      for (Ix = 0; Ix <= Last; Ix++)
        { 
          // Hack for now for non-arrays
          if (arguments.length == 2 ?
              ShouldSwap(InArray[Ix], InArray[Ix + 1], PriIx) :
              ShouldSwap(InArray[Ix], InArray[Ix + 1], PriIx, PriOrder, SecIx, SecOrder))
          // End Hack
            {
              LastSwap = Ix;
              Sorted = false;
              Temp = InArray[Ix];
              InArray[Ix] = InArray[Ix + 1];
              InArray[Ix + 1] = Temp;
            }
        }
    }
}
function SortArray(InArray, PriOrder)
{
  var Ix, Temp, Last;
  var LastSwap = InArray.length - 1;

  var Sorted = (PriOrder == SORTNONE);

  while (!Sorted)
    {
      Sorted = true;
      Last = --LastSwap;
      for (Ix = 0; Ix <= Last; Ix++)
        { 
          if (ShouldSwap(InArray[Ix], InArray[Ix + 1], PriOrder))
            {
              LastSwap = Ix;
              Sorted = false;
              Temp = InArray[Ix];
              InArray[Ix] = InArray[Ix + 1];
              InArray[Ix + 1] = Temp;
            }
        }
    }
}

// *************************************************************************************
// *************************************************************************************
var FONTFACE="Arial";

function WriteText(Doc, Size, Text)
{
  Doc.write("<FONT SIZE=" + Size + " FACE=" + FONTFACE + ">" + Text);
}

function WriteTD(Doc, ExtraInfo, Size, Text)
{
  Doc.write("<TD NOWRAP " + ExtraInfo + "><FONT SIZE=" + Size + " FACE=" + FONTFACE + ">" + Text + "</TD>");
}

function WriteTable(Doc, FontSize, 
                    Border, BGColor, CellPadding, CellSpacing, MaxRows,
                    InArray, Cols, HeaderRow)
{
  var TableStr = "<TABLE BORDER="      + Border;

  if (BGColor != "")
    TableStr += " BGCOLOR=" + BGColor;

  TableStr += " CELLSPACING=" + CellSpacing +
              " CELLPADDING=" + CellPadding + ">";
  Doc.write(TableStr);

  if (HeaderRow.length > 0)
    {
      Doc.write("<TR>");
      for (Col = 0; Col < Cols; Col++)
        { WriteTD(Doc, "", FontSize, HeaderRow[Col]); }
      Doc.write("</TR>");
    }

  for (Row = 0; Row < InArray.length; Row++)
    {
      Doc.write("<TR>");
      for (Col = 0; Col < Cols; Col++)
        { WriteTD(Doc, "", FontSize, InArray[Row][Col]); }
      Doc.write("</TR>");
    }

  Doc.write("</TABLE>");
}

// *************************************************************************************
// *************************************************************************************
function SameSizeTable(Doc, Header, FontSize, 
                       Border, BGColor, CellPadding, CellSpacing, MaxRows, MaxTables,
                       InArray, Cols, HeaderRow, PostSort,
                       PriSortIx, PriOrder, SecSortIx, SecOrder, 
                       Footer)
{
  var Ix, Row, Col;

  var LocalArray = new Array();

  SortArray(InArray, PriSortIx, PriOrder, SecSortIx, SecOrder);

  for (Row = 0; Row < InArray.length; Row++)
    { 
      LocalArray.length = Row + 1;
      LocalArray[Row] = new Array();

      if (Cols > 1)
        {
          for (Col = 0; Col < Cols; Col++)
            { LocalArray[Row][Col] = PostSort(InArray[Row][Col], Row, Col, HeaderRow, LocalArray); }
        }
      else
        { LocalArray[Row][0] = PostSort(InArray[Row], Row, Col, HeaderRow, LocalArray); }
    }

  if (Header != "")
    WriteText(Doc, FontSize, Header);

  var NumTables = Math.min(Math.ceil(LocalArray.length/MaxRows), MaxTables);
  var NumRows = Math.ceil(LocalArray.length / NumTables);
  var NewLength = NumRows*NumTables;

  for (Ix = 0; LocalArray.length < NewLength; Ix++)
    {
      LocalArray[LocalArray.length] = new Array();
      for (Ix = 0; Ix < Cols; Ix++)
        { LocalArray[LocalArray.length - 1][Ix] = "<FONT COLOR=" + BGColor + ">."; }
    }

  if (NumTables > 1)
    {
      var TableStr = "<TABLE BORDER="      + Border;

      if (BGColor != "")
        TableStr += " BGCOLOR=" + BGColor;

      TableStr += " CELLSPACING=" + CellSpacing +
                  " CELLPADDING=" + CellPadding + ">";
      Doc.write(TableStr);

      Doc.write("<TR>");

      for (Ix = 0; Ix < NumTables; Ix ++)
        {
          Doc.write("<TD>");

          WriteTable(Doc, FontSize, 
                     Border, BGColor, CellPadding, CellSpacing, NumRows,
                     LocalArray.slice(Ix*NumRows, (Ix + 1)*NumRows), Cols, HeaderRow);

          Doc.write("</TD>");
        }

      Doc.write("</TR></TABLE>");
    }

  else
    {
      WriteTable(Doc, FontSize, 
                 Border, BGColor, CellPadding, CellSpacing, NumRows,
                 LocalArray, Cols, HeaderRow);
    }

  if (Footer != "")
    WriteText(Doc, FontSize, Footer);
}

// ****************************** DEBUG below **********************************


var Popwin;

var MenuDebug = false;
var MenuDebugWindow;

if (MenuDebug)
{
MenuDebugWindow = window.open("", "DebugWindow", "width=300,height=600,resizable,scrollbars");
MenuDebugWindow.document.open("text/plain");
}

function MenuLocalWrite(Text)
{
  var Today = new Date();
  if (MenuDebug)
    {
      MenuDebugWindow.document.write(FormatDate(Today, TIME) + ": ");
      MenuDebugWindow.document.writeln(Text);
    }
}

