/**
 * Global Variables
 *
 */
var blinkTimerId = 0;
var oneShot = false;
var blinkTimer = {
  "chat" : Array("Mini:Chat:Image", 0, true)
};
var locateTimerId = 0;
var saveView = false;
var rawTableCount = 0;
var messageTableCount = 0;
var positionsTableCount = 0;
var searchesTableCount = 0;
var ulsNames = new Array();
var darkControls = new Object();
var onShot = false;
var generateKey = false;
var chatIdle = 0;
var hideLabels = true;

/**
 * PutOnTop
 *
 * Put Gmarker on top.
 *
 */
function PutOnTop(marker, b) {
  return 6000;
} // PutOnTop

/**
 * goSearch
 *
 * Automatically search for a target.
 *
 */
function goSearch(searchMe) {
  var myForm = document.getElementById('oaprs_form_search');
  var mySearch = document.getElementById('oaprs_form_q');

  if (myForm == null || mySearch == null)
    return;

  mySearch.value = searchMe;

  myForm.submit();

  return;
} // goSearch

/**
 * orderSearch
 *
 * Automatically search for a target.
 *
 */
function orderSearch(orderMe) {
  var myForm = document.getElementById('oaprs_form_search');
  var mySearch = document.getElementById('oaprs_form_q');
  var re = /([ ]*order[:][a-z]+[ ]*(ASC|DESC))/g;
  var str;

  if (myForm == null || mySearch == null)
    return;

  mySearch.value = mySearch.value.replace(re, "");
  mySearch.value += " " + orderMe;

  myForm.submit();

  return;
} // orderSearch

/**
 * zoomSearch
 *
 * Change Zoom Level of Maps
 *
 */
function zoomSearch(zoomMe) {
  var myForm = document.getElementById('oaprs_form_search');
  var mySearch = document.getElementById('oaprs_form_q');
  var re = /([ ]*zoom:level[ ]*([0-9]+))/g;
  var str;

  if (myForm == null || mySearch == null)
    return;

  mySearch.value = mySearch.value.replace(re, "");
  mySearch.value += " " + zoomMe;

  myForm.submit();

  return;
} // zoomSearch

/**
 * sizeSearch
 *
 * Change Zoom Level of Maps
 *
 */
function sizeSearch(sizeMe) {
  var myForm = document.getElementById('oaprs_form_search');
  var mySearch = document.getElementById('oaprs_form_q');
  var re = /([ ]*map:size[ ]*([0-9]{1,3}[x][0-9]{1,3}))/g;
  var str;

  if (myForm == null || mySearch == null)
    return;

  mySearch.value = mySearch.value.replace(re, "");
  mySearch.value += " " + sizeMe;

  myForm.submit();

  return;
} // sizeSearch

/**
 * Hams Near You
 *
 * Toggle HNY functionality.
 *
 */
function toggleHNY() {
  var showULS = document.getElementById("openaprs_form_show_uls");
  var hnyOver = document.getElementById("hnyOver");

  if (showULS == null)
    return;

  if (showULS.options[0].selected == false) {
    showWindow('hnyOverlay');
    changeById('hnyOverlayMessage', 'Hams Nearest to Displayed City (US Only)');
    changeById('OpenAPRS:Href:HNY', '+ Hide HAMs Near You');

    if (hnyOver != null) {
      hnyOver.style.backgroundColor = 'darkred';
      hnyOver.style.color = 'white';
    } // if

    darkControl('controlHNY', true);
    showULS.options[0].selected = true;

  } // if
  else {
    hideWindow('hnyOverlay');

    if (hnyOver != null) {
      hnyOver.style.backgroundColor = 'white';
      hnyOver.style.color = 'black';
    } // if

    darkControl('controlHNY', false);
    showULS.options[1].selected = true;
    changeById('OpenAPRS:Href:HNY', 'Show HAMs Near You');

  } // else

  return;
} // HNY

/**
 * togglePHG
 *
 * Toggle PHG functionality.
 *
 */
function togglePHG() {
  var showPHG = document.getElementById("openaprs_form_show_phg");

  if (showPHG == null)
    return;

  if (showPHG.options[0].selected == false) {
    darkControl('controlPHG', true);
    showPHG.options[0].selected = true;
    changeById('OpenAPRS:Href:PHG', '+ Hide PHG Circles');
    gOpenAPRS.enablePHG();

  } // if
  else {
    darkControl('controlPHG', false);
    showPHG.options[1].selected = true;
    changeById('OpenAPRS:Href:PHG', 'Show PHG Circles');
    gOpenAPRS.disablePHG();

  } // else

  return;
} // togglePHG

/**
 * toggleIRLP
 *
 * Toggle IRLP functionality.
 *
 */
function toggleIRLP() {
  var showMe = document.getElementById("openaprs_form_show_irlp");

  if (showMe == null)
    return;

  if (showMe.options[0].selected == false) {
    darkControl('controlIRLP', true);
    showMe.options[0].selected = true;
    changeById('OpenAPRS:Href:IRLP', '+ Hide IRLP Stations');

  } // if
  else {
    darkControl('controlIRLP', false);
    showMe.options[1].selected = true;
    changeById('OpenAPRS:Href:IRLP', 'Show IRLP Stations');

  } // else

  return;
} // toggleIRLP

/**
 * toggleMOUSE
 *
 * Toggle MOUSE functionality.
 *
 */
function toggleMOUSE() {
  var enableMOUSE = document.getElementById("openaprs_form_enable_mouse");

  if (enableMOUSE == null)
    return;

  if (enableMOUSE.options[0].selected == false) {
    enableMOUSE.options[0].selected = true;
    darkControl('controlMOUSE', true);
    map.enableScrollWheelZoom();
  } // if
  else {
    enableMOUSE.options[1].selected = true;
    darkControl('controlMOUSE', false);
    // FIXMES
    //map.disableScrollWheelZoom();
  } // else

  return;
} // toggleMOUSE

/**
 * toggleTOOLS
 *
 * Toggle tools functionality.
 *
 */
function toggleTOOLS() {

var myId = document.getElementById('toolsOverlay');
  logById('logContainer', 'logTable', myId.style.display);


  if (isHidden('toolsOverlay')) {
    changeById('toolStatusOverlayMessage', 'Tools Mode');
    showWindow('toolsOverlay');
    showWindow('toolStatusOverlay');
    showControl('controlTOOLS', 'on');
    windowControl('toolsOverlay');
    Drag.init(document.getElementById("toolsHandle"), document.getElementById("toolsOverlay"), null, null, null, null, true);
  } // if
  else {
    showControl('controlCREATE', 'off');
    showControl('controlKILL', 'off');
    showControl('controlMEASURE', 'off');
    cObject.OFF();
    cObject.Clear();
    cRuler.OFF();
    cRuler.Clear();

    if (killObject)
      toggleKILL();

    hideWindow('toolsOverlay');
    hideWindow('toolStatusOverlay');
    showControl('controlTOOLS', 'off');

    unPause('openaprs_form_pause');
  } // else

  return;
} // toggleTOOLS

/**
 * checkScreenTips()
 *
 *
 */
function checkScreenTips() {
  st = document.getElementById("aprsTIPS:Form:On");

  if (st == null)
    return;

  if (st.checked == true)
    createCookie("myTips", "yes");
  else
    createCookie("myTips", "no");

  changeById('aprsTIPS:Error', 'OK!');
} // checkScreenTips

/**
 * toggleSTATIONS
 *
 * Toggle stations window.
 *
 */
function toggleSTATIONS() {
  if (isHidden('stationsOverlay')) {
    showWindow('stationsOverlay');
    showControl('controlSTATIONS', 'on');
    windowControl('stationsOverlay');
    Drag.init(document.getElementById("stationsHandle"), document.getElementById("stationsOverlay"), null, null, null, null, true);
    changeById('OpenAPRS:Href:Stations', '+ Hide Station List...');
  } // if
  else {
    showControl('controlSTATIONS', 'off');
    hideWindow('stationsOverlay');
    changeById('OpenAPRS:Href:Stations', 'Show Station List...');
  } // else

  return;
} // toggleSTATIONS

/**
 * toggleCHAT
 *
 * Toggle chat window.
 *
 */
function toggleCHAT() {
  clearChatTimer();

  if (isHidden('chatOverlay')) {
    showWindow('chatOverlay');
    showControl('controlCHAT', 'on');
    windowControl('chatOverlay');
    Drag.init(document.getElementById("chatHandle"), document.getElementById("chatOverlay"), null, null, null, null, false);
  } // if
  else {
    showControl('controlCHAT', 'off');
    hideWindow('chatOverlay');
  } // else

  return;
} // toggleCHAT

/**
 * clearChatTimer
 *
 * Clear blink timer on click.
 */
function clearChatTimer() {
  if (blinkTimer["chat"][1] > 0) {
    clearTimeout(blinkTimer["chat"][1]);
    blinkTimer["chat"][1] = 0;
    changeImageById('Mini:Chat:Image', '/images/mini/on/chat.png');
  } // if

  changeImageById('Mini:Chat:Image', '/images/mini/on/chat.png');

  return;
} // clearChatTimer();

/**
 * toggleTOP
 *
 * Toggle stations window.
 *
 */
function toggleTOP() {
  var windows = Array("locateOverlay",
                      "hnyOverlay",
                      "keyOverlay",
                      "menuOverlay",
                      "inputOverlay",
                      "weatherOverlay",
                      "loadOverlay",
                      "topOverlay",
                      "inputBox",
                      "topMESSAGE",
                      "mapSTATUSOverlay",
                      "mapSTATUSText",
                      "adOverlay",
                      "hnyOverlay"
                     );

  if (isHidden('topOverlay')) {
    showWindow('topOverlay');
    showWindow('inputBox');
    showWindow('topMESSAGE');
    showWindow('mapSTATUSOverlay');
    showWindow('mapSTATUSText');
    showWindow('adOverlay');
    hideWindow('unhideOverlay');
  } // if
  else {
    showWindow('unhideOverlay');
    for(w in windows)
      hideWindow(windows[w]);
  } // else

  return;
} // toggleTOP

/**
 * toggleOPTIONS
 *
 * Toggle tools functionality.
 *
 */
function toggleOPTIONS() {

  if (isHidden('optionsOverlay')) {
    showWindow('optionsOverlay');
    windowControl('optionsOverlay');
    showControl('controlOPTIONS', 'on');
    Drag.init(document.getElementById("optionsHandle"), document.getElementById("optionsOverlay"), null, null, null, null, false);
    changeById('OpenAPRS:Href:Options', '+ Options...');
  } // if
  else {
    showControl('controlOPTIONS', 'off');
    hideWindow('optionsOverlay');
    changeById('OpenAPRS:Href:Options', 'Options...');
    setDefaults();
  } // else

  return;
} // toggleOPTIONS

/**
 * toggleVIEW
 *
 * Toggle tools functionality.
 *
 */
function toggleVIEW(pause) {

  if (isHidden('viewOverlay')) {
    if (cRuler.isON())
      toggleRULER();

    if (cObject.isON())
      toggleOBJECT();

    showWindow('viewOverlay');
    windowControl('viewOverlay');
    showControl('controlVIEW', 'on');
    Drag.init(document.getElementById("viewHandle"), document.getElementById("viewOverlay"), null, null, null, null, true);
    doPause('openaprs_form_pause');
  } // if
  else {
    showControl('controlVIEW', 'off');
    hideWindow('viewOverlay');
    if (pause)
      unPause('openaprs_form_pause');
  } // else

  return;
} // toggleVIEW

/**
 * toggleLOGIN
 *
 * Toggle login functionality.
 *
 */
function toggleLOGIN(pause) {

  if (isHidden('loginOverlay')) {
    showWindow('loginOverlay');
    windowControl('loginOverlay');
    Drag.init(document.getElementById("loginHandle"), document.getElementById("loginOverlay"), null, null, null, null, false);
  } // if
  else {
    hideWindow('loginOverlay');
  } // else

  return;
} // toggleLOGIN

/**
 * toggleCONSOLE
 *
 * Toggle console functionality.
 *
 */
function toggleCONSOLE() {

  if (isHidden('consoleOverlay')) {
    showWindow('consoleOverlay');
    windowControl('consoleOverlay');
    Drag.init(document.getElementById("consoleHandle"), document.getElementById("consoleOverlay"), null, null, null, null, true);
    changeById('OpenAPRS:Href:Console', '+ Hide Console');
  } // if
  else {
    hideWindow('consoleOverlay');
    changeById('OpenAPRS:Href:Console', 'View Console');
  } // else

  return;
} // toggleCONSOLE

/**
 * clearTOOLS
 *
 * Clear tools objects.
 *
 */
function clearTOOLS() {

  cRuler.Clear();
  cObject.Clear();

  return;
} // clearTOOLS

/**
 * Blink Background
 *
 * Cause a background to blink at a given interval.
 *
 */
function blinkBackground(id, interval, bgColor1, fgColor1, bgColor2, fgColor2) {
  var blinkMe = document.getElementById(id);
  var re = new RegExp("^rgb");

  if (blinkMe == null)
    return;

  if (blinkMe.style.backgroundColor.match(re))
    var bgColor = rgbConvert(blinkMe.style.backgroundColor);
  else
    var bgColor = blinkMe.style.backgroundColor.toUpperCase();

  if (bgColor == bgColor1) {
    blinkMe.style.backgroundColor = bgColor2;
    blinkMe.style.color = fgColor2;
  } // if
  else {
    blinkMe.style.backgroundColor = bgColor1;
    blinkMe.style.color = fgColor1;
  } // else

  blinkTimerId = window.setTimeout('blinkBackground("'+id+'","'+interval+'","'+bgColor1+'","'+fgColor1+'","'+bgColor2+
                                  '","'+fgColor2+'")', interval);

  //changeById('debug', blinkTimerId + ':' + blinkMe.style.backgroundColor);
} // blinkBackground

/**
 * Blink IMG
 *
 * Cause a background to blink at a given interval.
 *
 */
function blinkIMG(id, interval, onImg, offImg) {
  var blinkMe = null;

  for(b in blinkTimer) {
    if (id == b) {
      blinkMe = document.getElementById(blinkTimer[b][0]);
      break;
    } // if
  } // for

  if (blinkMe == null)
    return;

  if (blinkTimer[b][2]) {
    blinkMe.src = offImg;
    blinkTimer[b][2] = false;
  } // if
  else {
    blinkMe.src = onImg;
    blinkTimer[b][2] = true;
  } // else

  blinkTimer[b][1] = window.setTimeout('blinkIMG("'+id+'","'+interval+'","'+onImg+'","'+offImg+'")', interval);

  //changeById('debug', blinkTimerId + ':' + blinkMe.style.backgroundColor);
} // blinkIMG

/**
 * navUpdate
 *
 * Update the navigation overlay.
 *
 */
function navUpdate(id, lat, lng) {
  var naviOverlay = document.getElementById(id);
  var geoCoords = document.getElementById("openaprs_form_geocoords");

  var latitude = lat.toFixed(6);
  var longitude = lng.toFixed(6);

  if (naviOverlay == null)
    return;

  if (geoCoords != null) {
    if (geoCoords.value == 'utm') {
      xy = new Object()
      zone = Math.floor ((lng + 180.0) / 6) + 1;
      zone = LatLonToUTMXY(DegToRad(lat), DegToRad(lng), zone, xy);
      latitude = zone + " " + parseInt(xy[0]) + "m E";
      longitude = parseInt(xy[1]) + "m N";
    } // if
    if (geoCoords.value == 'dms') {
      latitude = lat.toLat(0);
      longitude = lng.toLon(0);
    } // if
  } // if

  naviOverlay.innerHTML = latitude + ", " + longitude +
                          " " + LatLongToLocator(lat, lng);
  return;
} // navUpdate

/**
 * LatLongToLocator
 *
 * Create a cookie in users browser.
 *
 */
function LatLongToLocator(Lat, Long) {
  var locator = "";   
      
  Lat += 90;
  Long += 180;

  v = parseInt(Long / 20);

  Long -= v * 20;

  locator += String.fromCharCode('A'.charCodeAt(0) + v);

  v = parseInt(Lat / 10);

  Lat -= v * 10;
     
  locator += String.fromCharCode('A'.charCodeAt(0) + v);
  locator += (parseInt(Long / 2));

  locator += parseInt(Lat);
  Long -= parseInt(Long / 2) * 2;
  Lat -= parseInt(Lat);
                           
  locator += String.fromCharCode('A'.charCodeAt(0) + Long * 12);

  locator += String.fromCharCode('A'.charCodeAt(0) + Lat * 24);

  return locator;
} // LatLongToLocator

/**
 * showAddress
 *
 * Show address that was found.
 *
 */
function showAddress(address) {  
  if (geocoder) {  
    geocoder.getLatLng(  
      address,  
      function(point) {  
        if (!point) {  
          changeById("locate_status", "Unable to locate");
          changeById("locateOverlayMessage", "Unable to locate");
          logById('logContainer', 'logTable', "LOCATE: Unable to locate ["+address+"]");
        } // else
        else { 
          changeById("locate_status", "Located, centering map");
          hideWindow('locateOverlay');
          logById('logContainer', 'logTable', "LOCATE: Found location, centering map ["+address+"]");
          map.setCenter(point, 12);
        } // else  
      } // function
    );            
  } // if
} // showAddress

/**
 * popupTrack
 *
 * Pop up a tracking window.
 *
 */
function popupTrack(find) {
  optionsBox = document.getElementById("optionsBoxInner");
  trackWindowCallsign = document.getElementById("trackWindowCallsign");
  trackWindowLinkTrack = document.getElementById("trackWindowLinkTrack");
  trackWindowLinkInfo = document.getElementById("trackWindowLinkInfo");

  if (optionsBox == null)
    return;

  if (trackWindowCallsign != null)
    trackWindowCallsign.innerHTML = " - "+find.toUpperCase();

  if (trackWindowLinkTrack != null)
    trackWindowLinkTrack.href = "http://www.openaprs.net/engine/track/"+find.toUpperCase();

  if (trackWindowLinkInfo != null)
    trackWindowLinkInfo.href = "http://www.openaprs.net/engine/info/"+find.toUpperCase();

  openaprs_find = find;

  optionsBox.innerHTML = 
                 '<iframe name="openaprsMap" id="openaprsMap"'
                 + ' src="http://www.openaprs.net/embed/?width=100%&height=100%&zoom=6&find='
                 + find
                 + '"'
                 + ' marginwidth="0" marginheight="0"'
                 + ' vspace="0" hspace="0" allowtransparency="true"'
                 + ' frameborder="0" scrolling="no" width="450px" height="400px"></iframe>\n';

  showTrackWindow('trackWindowFg');
} // popupTrack

/**
 * showTrackWindow
 *
 * Select all text on click.
 *
 */
function showTrackWindow(id) {
  pPop = document.getElementById(id);

  if (pPop == null)
    return;

  pPop.style.display = "inline";

} // showTrackWindow

/**
 * hideTrackWindow
 *
 * Hide track window.
 *
 */
function hideTrackWindow(id) {
  pPop = document.getElementById(id);
  optionsBox = document.getElementById("optionsBoxInner");

  if (optionsBox == null)
    return;

  optionsBox.innerHTML = "";

  if (pPop == null)
    return;

  pPop.style.display = "none";

} // hideTrackWindow

/**
 * showMenu
 *
 * Select all text on click.
 *
 */
function showMenu(name) {
  var menus = {
    "menu": "menuOverlay",
    "chat": "chatOverlay",
    "server": "serverOverlay",
    "key": "keyOverlay"
  };

  if (name == "chat" && blinkTimerId > 0) {
    clearTimeout(blinkTimerId);
    blinkTimerId = 0;
  } // if

  for(var m in menus) {
    if (m == name) {
      var myOverlay = document.getElementById(m + "Over");
      if (myOverlay != null) {
        myOverlay.style.backgroundColor = '#F2EFE9';
        myOverlay.style.color = '#000000';
      } // if


      showWindow(menus[m]);

      if (name == "chat")
        maxScroll('chat_container');
    } // if
    else {
      var myOverlay = document.getElementById(m + "Over");
      if (myOverlay != null) {
        myOverlay.style.backgroundColor = '#FFFFFF';
        myOverlay.style.color = '#000000';
      } // if

      hideWindow(menus[m]);
    } // else
  } // for

  return void(0);
} // showMenu

/**
 * changeTopMESSAGE
 *
 * Select all text on click.
 *
 */
function changeTopMESSAGE(text) {
  var mySpace = document.getElementById('controlSPACE');
  var path = '/images/c2/';

  if (mySpace == null)
    return;

  // change logo area to a white space
  // so text is readable
  if (text.length > 0) {
    //mySpace.src = path + "off/white.png";
    changeById('topMESSAGE', text);
  } // if
  else {
    //mySpace.src = path + "off/space.png";
    changeById('topMESSAGE', '');
  } // else

  return;
}

/**
 * checkPHG
 *
 * Select all text on click.
 *
 */
function checkPHG() {
  var showPHG = document.getElementById('openaprs_form_show_phg');

  if (showPHG == null)
    return;

  if (showPHG.value == 'no')
    showControl('controlPHG', 'off');
  else
    showControl('controlPHG', 'on');

  return;
}

/**
 * checkMOUSE
 *
 * Select all text on click.
 *
 */
function checkMOUSE() {
  var showMOUSE = document.getElementById('openaprs_form_enable_mouse');

  if (showMOUSE == null)
    return;

  if (showMOUSE.value == 'no') {
    logById('logContainer', 'logTable', 'MOUSE WHEEL: OFF');
    showControl('controlMOUSE', 'off');
//FIXME
//    map.disableScrollWheelZoom();
  } // if
  else {
    logById('logContainer', 'logTable', 'MOUSE WHEEL: ON');
    showControl('controlMOUSE', 'on');
//FIXME
//    map.enableScrollWheelZoom();
  } // else

  return;
}

/**
 * checkHNY
 *
 * Select all text on click.
 *
 */
function checkHNY() {
  var showHNY = document.getElementById('openaprs_form_show_uls');

  if (showHNY == null)
    return;

  if (showHNY.value == 'no')
    showControl('controlHNY', 'off');
  else
    showControl('controlHNY', 'on');

  return;
}

/**
 * doHome
 *
 * Select all text on click.
 *
 */
function doHome(map) {
  var findMe = document.getElementById('openaprs_form_find');
  var myHome = readCookie('myLocation');
  var myZoom = readCookie('myZoom');
  var wasZoom = map.getZoom();

  if (findMe == null)
    return;

  if (myHome.length < 1)
    return;

  if (myZoom < 0 || myZoom > 23)
    myZoom = 11;

  findMe.value = myHome;
  map.setZoom(parseInt(myZoom));

  logById('logContainer', 'logTable', 'Location: ' + myHome);
  logById('logContainer', 'logTable', 'Zoom: ' + myZoom + ' (was: ' + wasZoom + ')');

  return;
} // doHome

/**
 * doHome
 *
 * Select all text on click.
 *
 */
function doZoom(myZoom) {
  if (myZoom < 0 || myZoom > 23)
    return;

  map.setZoom(parseInt(myZoom));

  return;
} // doZoom

/**
 * doZoomIn
 *
 * Select all text on click.
 *
 */
function doZoomIn() {
  if (map.getZoom() > 20)
    return;

  map.setZoom(map.getZoom() + 1);

  return;
} // doZoomIn

/**
 * doZoomOut
 *
 * Select all text on click.
 *
 */
function doZoomOut() {
  if (map.getZoom() < 1)
    return;

  map.setZoom(map.getZoom() - 1);

  return;
} // doZoomOut

/**
 * windowControl
 *
 * Select all text on click.
 *
 */
function windowControl(id) {
  var overlays = {
    "messagingOverlay": "messagingHandle",
    "friendsOverlay": "friendsHandle",
    "optionsOverlay": "optionsHandle",
    "toolsOverlay": "toolsHandle",
    "helpOverlay": "helpHandle",
    "tacticalOverlay": "tacticalHandle",
    "stationsOverlay": "stationsHandle",
    "chatOverlay": "chatHandle",
    "viewOverlay": "viewHandle",
    "loginOverlay": "loginHandle",
    "locationOverlay": "locationHandle",
    "consoleOverlay": "consoleHandle",
    "trackOverlay": "trackHandle",
    "logOverlay": "logHandle"
  } // overlays

  chatIdle = getUnixTime();

  for(var o in overlays) {
    if (id == o) {
      changeZindexById(o, 6000);
      changeBackgroundColorById(overlays[o], '#330099');
      changeColorById(overlays[o], 'white');
    } // if
    else {
      changeZindexById(o, 5000);
      changeBackgroundColorById(overlays[o], 'white');
      changeColorById(overlays[o], 'black');
    } // else
  } // for

  return;
} // zindexControl

/**
 * showControl
 *
 * Select all text on click.
 *
 */
function showControl(id, doACTION) {
  var myImg = document.getElementById(id);
  var path = '/images/c2/';
  chatIdle = getUnixTime();

  if (myImg == null)
    return;

  if (isChecked("openaprs_form_pause"))
    var pause = new Array("p/play.png", "Resume Live Feed");
  else
    var pause = new Array("p/pause.png", "Pause Live Feed");

  if (cMessage.isPAUSE())
    var msgpause = new Array("p/play.png", "Resume Message Feed");
  else
    var msgpause = new Array("p/pause.png", "Pause Message Feed");

  if (cFriends.isPAUSE())
    var frdpause = new Array("p/play.png", "Resume Friend List");
  else
    var frdpause = new Array("p/pause.png", "Pause Friend List");

  if (cTactical.isPAUSE())
    var tacpause = new Array("p/play.png", "Resume Tactical List");
  else
    var tacpause = new Array("p/pause.png", "Pause Tactical List");

  if (gOpenAPRS.track.isPaused())
    var trackpause = new Array("p/play.png", "Resume Tracking List");
  else
    var trackpause = new Array("p/pause.png", "Pause Tracking List");

  hideWindow('inputOverlay');

  var menus = {
    "controlCHAT": new Array("chat.png", "Chat"),
    "controlKEY":  new Array("key.png", "Map Key", "keyOverlay"),
    "controlHNY":  new Array("hny.png", "Toggle Hams Near You"),
    "controlPHG":  new Array("phg.png", "Toggle PHG Circles"),
    "controlMENU": new Array("menu.png", "Menu", "menuOverlay"),
    "controlOPTIONS": new Array("options.png", "Options"),
    "controlHELP": new Array("help.png", "Help"),
    "controlDONATE": new Array("donate.png", "Donate"),
    "controlBLOG": new Array("blog.png", "BLOG"),
    "controlPAUSE": pause,
    "controlSTATS": new Array("v/stats.png", "Database Stats", "serverOverlay"),
    "controlHOME": new Array("v/home.png", "Center Map on Home"),
    "controlSTATE": new Array("v/state.png", "Zoom to State View"),
    "controlSTREET": new Array("v/street.png", "Zoom to Street View"),
    "controlWORLD": new Array("v/world.png", "Zoom to World View"),
    "controlSTATIONS": new Array("v/stations.png", "Show Station List"),
    "controlCONTACT": new Array("v/contact.png", "Contact Us"),
    "controlMOUSE": new Array("v/mouse.png", "Toggle Scroll Wheel Zoom"),
    "controlTOOLS": new Array("v/tools.png", "Toggle Tools"),
    "controlCREATE": new Array("t/create.png", "Create Object"),
    "controlKILL": new Array("t/kill.png", "Kill Object"),
    "controlMEASURE": new Array("t/measure.png", "Measure Distance"),
    "controlCLEAR": new Array("t/clear.png", "Clear All"),
    "controlMESSAGING": new Array("t/messaging.png", "APRS Messaging"),
    "controlMSGPAUSE": msgpause,
    "controlFRIENDS": new Array("t/friends.png", "Friends List"),
    "controlFRIENDSPAUSE": frdpause,
    "controlTOOLSHELP": new Array("t/help.png", "Tools Help"),
    "controlTACTICAL": new Array("t/tactical.png", "Tactical Call List"),
    "controlTACTICALPAUSE": tacpause,
    "controlTRACK": new Array("t/friends.png", "APRS Tracking List"),
    "controlTRACKPAUSE": trackpause,
    "controlVIEW": new Array("t/save.png", "Save View"),
    "controlUNHIDE": new Array("unhide.png", "Unhide Top")
  };

  var tooltips = {
    "controlCHAT": '<div class="tooltip"><b>Web Chat</b><br /><br />Chat with others users currently on the website.</div>',
    "controlOPTIONS": '<div class="tooltip"><b>Options</b><br /><br />Customize your experience or login and verify your account.  Under options you can change several settings like the units of measure, display limits, your timezone and many other items to help get you the information you want.</div>',
    "controlPHG": '<div class="tooltip"><b>PHG Circles</b><br /><br />Toggles Power/HAAT/Gain circles, these circles show the estimated range of their stations.  Usuaully used for digipeaters or repeaters.</div>',
    "controlMOUSE": '<div class="tooltip"><b>Mouse Zoom Control</b><br /><br />When enabled, your mouse scroll wheel will zoom the map in or out when rotated forward or backward.</div>',
    "controlMESSAGING": '<div class="tooltip"><b>APRS Messaging</b><br /><br />Send an APRS Message right from OpenAPRS to a friend.</div>',
    "controlMEASURE": '<div class="tooltip"><b>Measure Distance</b><br /><br />Create a ruler by clicking on the map to measure a distance between to points.</div>',
    "controlFRIENDS": '<div class="tooltip"><b>APRS Friends List</b><br /><br />Add your friends callsign to this list to see when they are actively messaging over APRS.  This let\'s you know when your friend is online so you can QSO.</div>',
    "controlVIEW": '<div class="tooltip"><b>Save Current Map View</b><br /><br />Save the current map tracks for later viewing.  We only retain data for up to 10 days so if you have a track you want to store indefinately this is the way to do it.  Once saved you can use the web links provided to direct users from your website to your saved view.  This is great for balloon projects.</div>',
    "controlUNHIDE": '<div class="tooltip"><b>Restore Interface</b><br /><br />Restores main site interface.</div>',
    "controlHNY": '<div class="tooltip"><b>HAM\'s Near You</b><br /><br />Displays Amateur Radio Operators near the city closest to the center of the map.</div>',
    "controlHOME": '<div class="tooltip"><b>Zoom and Scroll Map to Default Home</b><br /><br />Zooms and scrolls the map the default home set by checking the "Save as default home" options in the zip code dropdown box.</div>',
    "controlWORLD": '<div class="tooltip"><b>Zoom to World Level</b><br /><br />Zooms map to the world level view.</div>',
    "controlSTATIONS": '<div class="tooltip"><b>Station List</b><br /><br />Shows the current list of stations displayed on the map in a window.</div>',
    "controlCONTACT": '<div class="tooltip"><b>Contact Us / Suggestion Box</b><br /><br />We want to hear from you, please use this form to contact us with suggestions, comments, concerns and bug reports.</div>',
    "controlTOOLS": '<div class="tooltip"><b>Tools</b><br /><br />Opens up the toolbar which will allow you to create and kill objects, send APRS messages, setup tactical callsigns and measure distances.  Most of the toolbar features require that you have an account with OpenAPRS.  To signup for an account click the Options icon at the top of the page then Signup.</div>',
    "controlSTATE": '<div class="tooltip"><b>Zoom to State Level</b><br /><br />Zoom map to state level view.</div>',
    "controlSTREET": '<div class="tooltip"><b>Zoom to Street Level</b><br /><br />Zoom map to street level view.</div>'
  };

  for(var m in menus) {
    if (m == id) {
      if (doACTION == 'over') {
        if (m == "controlKEY")
          loadKey();

        var mySub = "over/";
        if (tooltips[m] != undefined)
          Tip(tooltips[m], BALLOON, true, ABOVE, true, OFFSETX, 0);
      } // if
      else if (doACTION == 'on') {
        var mySub = "on/";
        darkControls[m] = true;
        myImg.src = path + mySub + menus[m][0];
      } // if
      else if (doACTION == 'off') {
        var mySub = "off/";
        darkControls[m] = false;
        myImg.src = path + mySub + menus[m][0];
        UnTip();
      } // if
      else {
        var mySub = "off/";
        UnTip();
      } // else

      if (!darkControls[m])
        myImg.src = path + mySub + menus[m][0];

      changeTopMESSAGE(menus[m][1]);
    } // if

    if (id != m && menus[m][2] != undefined)
      hideWindow(menus[m][2]);

    if (id == m && menus[m][2] != undefined)
      showWindow(menus[m][2]);
  } // for

  // change logo area to a white space
  // so text is readable
  if (doACTION != 'over')
    changeTopMESSAGE('');

  return void(0);
} // showControl

/**
 * darkControl
 *
 * Select all text on click.
 *
 */
function darkControl(id, isON) {
  var myImg = document.getElementById(id);
  var path = '/images/c2/';

  if (myImg == null)
    return;

  var menus = {
    "controlHNY":  "hny.png",
    "controlPHG":  "phg.png",
    "controlMOUSE": "v/mouse.png"
  };

  for(var m in menus) {
    if (m == id) {
      if (isON)
        var mySub = "on/";
      else
        var mySub = "off/";

      myImg.src = path + mySub + menus[m];
    } // if
  } // for

  darkControls[id] = isON;

  return void(0);
} // darkControl

/**
 * doPause
 *
 * Toggles pause on or off.
 *
 */
function doPause(id) {
  var pause = document.getElementById(id);

  if (pause == null)
    return;

  if (!isChecked(id)) {
    pause.checked = true;
    showControl('controlPAUSE', 'off');
  } // else

  return void(0);
} // doPause

/**
 * unPause
 *
 * Toggles pause on or off.
 *
 */
function unPause(id) {
  var pause = document.getElementById(id);

  if (pause == null)
    return;

  if (isChecked(id)) {
    pause.checked = false;
    showControl('controlPAUSE', 'off');
    //hideWindow('toolsOverlay');
  } // if

  clearTOOLS();
  if (cObject.isON()) {
    showControl('controlCREATE', 'off');
    cObject.OFF();
  } // if

  if (cRuler.isON()) {
    showControl('controlMEASURE', 'off');
    cRuler.OFF()
  } // if

  if (!isHidden('viewOverlay') && saveView == false)
    toggleVIEW(false);

  //hideWindow('toolsOverlay');
  //hideWindow('toolStatusOverlay');
  //showControl('controlTOOLS', 'off');


  return void(0);
} // unPause

/**
 * togglePAUSE
 *
 * Toggles pause on or off.
 *
 */
function togglePAUSE(id) {
  var pause = document.getElementById(id);

  if (pause == null)
    return;

  if (isChecked(id))
    unPause(id);
  else
    doPause(id);

  return void(0);
} // togglePAUSE

/**
 * showOptions
 *
 * Select all text on click.
 *
 */
function showOptions(id1, id2) {
  pBack = document.getElementById(id1);
  pPop = document.getElementById(id2);

  if (pBack == null || pPop == null)
    return;

  //pBack.style.display = "block";
  pPop.style.display = "inline";

  showControl('controlOPTIONS', 'on');

  maxScroll('logContainer');
} // showPopup

/**
 * hidePopup
 *
 * Select all text on click.
 *
 */
function hideOptions(id1, id2) {
  pBack = document.getElementById(id1);
  pPop = document.getElementById(id2);

  if (pBack == null || pPop == null)
    return;

  //pBack.style.display = "none";
  pPop.style.display = "none";

  showControl('controlOPTIONS', 'off');

  setDefaults();
} // hidePopup

/**
 * saveOAPRS
 *
 * Select all text on click.
 *
 */
function saveOAPRS(id) {
  setCookie("oaprs_form_units", "myUnits");
  setCookie("oaprs_form_geocoords", "myGeocoords");
  setCookie("oaprs_form_timezone", "myTimezone");
  setCookie("oaprs_form_satellites", "mySatellites");

  hideWindow(id);

} // hidePopup

/**
 * ClearMessages
 *
 * Select all text on click.
 *
 */
function ClearMessages() {
  ClearField('callsign');
  clearRows('message_table');  
  
  changeById("status", 'updating');
} // ClearMessages

/**
 * clearRealtime
 *
 * Select all text on click.
 *
 */
function clearRealtime(id1, id2, id3) {
  myTimestamp = document.getElementById("openaprs_form_timestamp");

  if (myTimestamp == null)
    return;

  myTimestamp = 0;

  ClearField(id1);
  clearRows(id2);  

  changeById(id3, 'updating');
} // ClearMessages

/**
 * trackStation(station)
 *
 * Track a specific station.
 *
 */
function trackStation(station) {
  pause = document.getElementById("openaprs_form_pause");
  find = document.getElementById("openaprs_form_find");

  if (pause != null) {
    pause.checked = false;
    showControl('controlPAUSE', 'out');
  } // if

  if (find == null)
    return void(0);

  find.value = station;

  return void(0);
} // trackStation

/**
 * trackSatellite(station)
 *
 * Track a specific station.
 *
 */
function trackSatellite(station) {

  document.form_search.find.value = station;

  refreshSatellite(map);

  return void(0);
} // trackSatellite

/**
 * trackMessages(station)
 *
 * Track a specific station.
 *
 */
function trackMessages(station) {
  var callsign = document.getElementById("openaprs_form_callsign");

  if (callsign == null)
    return;

  callsign.value = station;

  searchMessages();

  return void(0);
} // trackStation

/**
 * trackRaw(station)
 *
 * Track a specific station.
 *
 */
function trackRaw(station) {
  var callsign = document.getElementById("openaprs_form_callsign");

  if (callsign == null)
    return;

  callsign.value = station;

  searchRaw();

  return void(0);
} // trackRaw

/**
 * trackPositions(station)
 *
 * Track a specific station.
 *
 */
function trackPositions(station) {
  var callsign = document.getElementById("openaprs_form_callsign");

  if (callsign == null)
    return;

  callsign.value = station;

  searchPositions();

  return void(0);
} // trackPositions

function d2h(d) {return d.toString(16);}
function h2d(h) {return parseInt(h,16);}

/**
 * randomColor
 *
 * Returns a random color.
 *
 */
function randomColor() {
  var r = d2h((Math.round(Math.random() * 255)));
  var g = d2h((Math.round(Math.random() * 255)));
  var b = d2h((Math.round(Math.random() * 255)));

  // return '#' + r + g + b;
  return '#4800FF';
} // randomColor

/**
 * ageColor
 *
 * Returns a random color.
 *
 */
function ageColor(age_time) {
  var r = d2h((Math.round(Math.random() * 255)));
  var g = d2h((Math.round(Math.random() * 255)));
  var b = d2h((Math.round(Math.random() * 255)));

  var yellow = '#FFFF33';
  var red = '#FF0000';
  var green = '#00FF00';
  var orange = '#FFCC00';
  var black = '#000000';
  var blue = '#0000FF';

  random_color = new Array(red, green, blue);
  return random_color[Math.round(Math.random() * random_color.length)];

  // Over 4 hours
  if (age_time < (getUnixTime() - 14400))
    return red;
  // Over 8 hours
  else if (age_time < (getUnixTime() - 28800))
    return orange;
  // Over 12 hours
  else if (age_time < (getUnixTime() - 43200))
    return yellow;

  return black;
} // ageColor

/**
 * seqColor
 *
 * Color based on position in sequence.
 *
 */
function seqColor(seq, maxseq) {
  var colors = {
    'red': '#FF0000',
    'orange': '#FFCC00',
    'yellow': '#FFFF33',
    'blue': '#0000FF',
    'black': '#000000'
  };

  var colors = Array('#FF0000', '#FF0000', '#FFFF33', '#00FF00', '#0000FF', '#000000');
  //var colors = Array('#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3399', '#FF33CC', '#FF33FF', '#FF6633', '#FF6666', '#FF66CC', '#FF66FF', '#FF9900', '#FF9933', '#FF9966', '#FF9966', '#FF9999', '#FF99CC', '#FF99FF', '#FFCC00', '#FFCC33', '#FFCC66', '#FFCC99', '#FFCCCC', '#FFCCFF', '#FFFF00', '#FFFF33', '#FFFF66', '#FFFF99', '#FFFFCC');
  //var colors = Array('#FF0000', '#FF3300', '#FF6600', '#FF9900', '#FFFF00', '#FFFF33', '#FF00CC', '#0000FF', '#00FF00', '#00FF33', '#000000');

  var div = Math.ceil(maxseq / colors.length);
  if (div != 0)
    div = Math.floor(seq/div);
  else
    div = 0;

  //logById('logContainer', 'logTable', 'Color: ' + colors[div] + ', ' + maxseq + '/' + colors.length + ', ' + div);

  colors.reverse();

  return colors[div];
} // seqColor

/**
 * getSymbol
 *
 * Creates an icon of an APRS symbol.
 *
 */
function getSymbol(url) {
  var xShape = {
    image: url,
    shadow: false,
    iconSize: new google.maps.Size(37, 37),
    shadowSize: new google.maps.Size(22, 20),
    iconAnchor: new google.maps.Point(6, 20),
    infoWindowAnchor: new google.maps.Point(15, 13),
    contentAnchor: new google.maps.Point(0, 0),
    contentSize: new google.maps.Size(37, 37),
    zIndex: 3,
    points: []
  };

  // XIcon.shapes['none'] = xShape;

  //var icon = new XIcon('none');
  var icon = new google.maps.MarkerImage();

  icon.image = url;
  icon.shadow = "http://www.openaprs.net/images/icons/shadow.png";
  //icon.iconSize = new google.maps.Size(27.75, 27.75);
  icon.iconSize = new google.maps.Size(30, 30);
  icon.shadowSize = new google.maps.Size(22, 20);
  icon.iconAnchor = new google.maps.Point(18, 18);
  icon.infoWindowAnchor = new google.maps.Point(15, 13);
  icon.zIndex = 100;

  return icon;
} // getSymbol

/**
 * createLabel
 *
 * Simple function to create a marker in Google Maps.
 *
 */
function createLabel(marker, label) {
  google.maps.event.addListener(marker, "mouseover", function() {
    if (hideLabels)
      label.show();
  });

  google.maps.event.addListener(marker, "mouseout", function() {
    if (hideLabels)
      label.hide();
  });

  return;
} // createLabel

/**
 * createDigiPolyLine
 *
 * Simple function to create a marker in Google Maps.
 *
 */
function createDigiPolyLine(marker, digipolyline) {
  google.maps.event.addListener(marker, "mouseover", function() {
    digipolyline.show();
  });

  google.maps.event.addListener(marker, "mouseout", function() {
    digipolyline.hide();
  });

  return;
} // createDigiPolyLine

/**
 * createMarker
 *
 * Simple function to create a marker in Google Maps.
 *
 */
function createMarker(point, icon, callsign, name) {
  // var description = createTextOverlay(callsign);
  // var marker = new XMarker(point, icon, [description]);

  var opts = new google.maps.MarkerOptions();
  opts.title = callsign;

  var marker = new google.maps.Marker(point, icon, opts);

  // Show this marker's index in the info window when it is clicked
  var html = name;

  google.maps.event.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(html);
  });
    
  return marker;
} // createMarker

/**
 * createMarkerAJAX
 *
 * Simple function to create a marker in Google Maps.
 *
 */
function createMarkerAJAX(point, icon, callsign, symbol_table, name) {
  if (!(symbol_table == '/' || symbol_table == '\\'))
    var overlay = symbol_table;
  else
    var overlay = null;

  //var description = createTextOverlay(callsign);

  //var element = document.createElement('div');

  //var marker = new XMarker(point, icon, null, description, name);

  var opts = new Object();
  opts.title = callsign;
  opts.icon = icon;
  icon.iconSize = new google.maps.Size(22, 22);
  icon.iconAnchor = new google.maps.Point(11, 11);
  opts.zIndexProcess = PutOnTop;

  opts2 = {
           "icon": icon,
           "clickable": true,
           "draggable": false,
           "labelText": overlay,
           "labelOffset": new google.maps.Size(-4, -8)
         };

  if (overlay != null)
    var marker = new LabeledMarker(point, opts2);
  else
    var marker = new google.maps.Marker(point, opts);

  //var marker = new google.maps.Marker(point, opts);

  //if (overlay == null)
  //  var marker = new XMarker(point, icon);
  //else
  //  var marker = new XMarker(point, icon, [overlay]);

  // Show this marker's index in the info window when it is clicked
  var html = name;

  google.maps.event.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(html);
  });

  return marker;
} // createMarkerAJAX

/**
 * createStation
 *
 * Creates an APRS station marker.
 *
 */
function createStation(map, longitude, latitude, callsign, url, cdata) {
  var icon;
  var point;
  var marker;

  // Create our "tiny" marker icon
  icon = getSymbol(url);

  point = new google.maps.Point(longitude, latitude);
  marker = createMarker(point, icon, callsign, cdata);
  marker.setMap(map);

  return marker;
} // createStation

/**
 * createDirection
 *
 * Creates an APRS station marker.
 *
 */
function createDirection(map, longitude, latitude, image_name, cdata) {
  var icon;
  var point;
  var marker;

  // Create our "tiny" marker icon
  icon = new google.maps.MarkerImage();
  icon.image = "http://www.openaprs.net/images/compass/" + image_name;
  icon.shadow = "http://www.openaprs.net/images/icons/shadow.png";
  icon.iconSize = new google.maps.Size(8, 8);
  icon.shadowSize = new google.maps.Size(22, 20);
  //icon.iconAnchor = new google.maps.Point(10, 10);
  icon.iconAnchor = new google.maps.Point(4, 4);
  icon.infoWindowAnchor = new google.maps.Point(15, 13);
  icon.zIndex = 1;

  point = new google.maps.Point(longitude, latitude);
  marker = new google.maps.Marker(point, icon);

  // Show this marker's index in the info window when it is clicked
  var html = cdata;

  google.maps.event.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(html);
  });

  marker.setMap(map);

  return marker;
} // createDirection

/**
 * createPerson
 *
 * Creates an APRS station marker.
 *
 */
function createPerson(map, longitude, latitude, image_name, cdata) {
  var icon;
  var point;
  var marker;

  // Create our "tiny" marker icon
  icon = new google.maps.MarkerImage();
  icon.image = "http://www.openaprs.net/images/icons/gender/" + image_name;
  icon.shadow = "http://www.openaprs.net/images/icons/shadow.png";
  icon.iconSize = new google.maps.Size(37, 37);
  icon.shadowSize = new google.maps.Size(22, 20);
  //icon.iconAnchor = new google.maps.Point(10, 10);
  icon.iconAnchor = new google.maps.Point(18, 18);
  icon.infoWindowAnchor = new google.maps.Point(15, 13);
  icon.zIndex = 0;

  point = new google.maps.Point(longitude, latitude);
  marker = new google.maps.Marker(point, icon);

  // Show this marker's index in the info window when it is clicked
  var html = cdata;

  google.maps.event.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(html);
  });

  marker.setMap(map);

  return marker;
} // createPerson

/**
 * createStationAJAX
 *
 * Creates an APRS station marker.
 *
 */
function createStationAJAX(longitude, latitude, callsign, symbol_table, url, cdata) {
  var icon;
  var point;
  var marker;

  // Create our "tiny" marker icon
  icon = getSymbol(url);

  //point = new google.maps.Point(longitude, latitude);
  point = new google.maps.LatLng(latitude, longitude);
  marker = createMarkerAJAX(point, icon, callsign, symbol_table, cdata);
  // map.addOverlay(marker);

  return marker;
} // createStationAJAX

/**
 * createSatelliteAJAX
 *
 * Creates an APRS station marker.
 *
 */
function createSatelliteAJAX(longitude, latitude, name, url, cdata) {
  var icon;
  var point;
  var marker;

  // Create our "tiny" marker icon
  var point = new google.maps.LatLng(latitude, longitude);
  var icon = new google.maps.MarkerImage();
  
  icon.image = url;
  icon.shadow = "http://www.openaprs.net/images/icons/shadow.png";
  icon.iconSize = new google.maps.Size(32, 32);
  icon.shadowSize = new google.maps.Size(22, 20);
  icon.iconAnchor = new google.maps.Point(16, 16);
  icon.infoWindowAnchor = new google.maps.Point(15, 13);
  icon.zIndex = 0;

  opts2 = {
           "icon": icon,
           "clickable": true,
           "draggable": false
         };

  var marker = new LabeledMarker(point, opts2);

  google.maps.event.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(cdata);
  });

  return marker;
} // createSatelliteAJAX

/**
 * createLetterOverlay
 *
 * Creates a letter overlay for symbols.
 */
function createLetterOverlay(number) {
  var element = document.createElement("div");

  element.innerHTML = number;
  element.style.width = XMaps.toPixelString(30);
  element.style.textAlign = 'center';
  element.style.color = '#FFFFFF';

  return { topOffset: 11, leftOffset: 4, element: element };
} // createLetterOverlay

/**
 * createTextOverLay
 *
 * Creates a text overlay icon.
 *
 */
function createTextOverlay(labelText) {
  var element = document.createElement("div");

  element.innerHTML = labelText;
  element.style.width = "9em";
  element.style.textAlign = 'center';
  element.style.background = '#FFFFFF';
  element.style.border = "1px solid black";

  return element;
} // createTextOverLay


/**
 * updateMap
 *
 * Update the currently displayed map.
 *
 */
function updateAd(){
  // Load any new stations
  loadAd();

  // set the timer
  window.setTimeout('updateAd()', 120000);
} // updateAd

/**
 * updateServer
 *
 * Update the currently displayed server.
 *
 */
function updateServer(){
  // Load any new stations
  refreshServer();

  // set the timer
  window.setTimeout('updateServer()', 300000);
} // updateServer

/**
 * updateSatellite
 *
 * Update the currently displayed server.
 *
 */
function updateSatellite(){
  // Load any new stations
  refreshSatellite(map);

  // set the timer
  window.setTimeout('updateSatellite()', 30000);
} // updateSatellite

/**
 * updateChat
 *
 * Update the currently displayed server.
 *
 */
function updateChat(){
  // Load any new stations
  refreshChat();

  // set the timer
  if (hasSeed)
    window.setTimeout('updateChat()', 30000);
  else
    window.setTimeout('updateChat()', 10000);
} // updateChat

/**
 * updateMessages
 *
 * Update the currently displayed map.
 *
 */
function updateMessages(){
  // Load any new stations
  refreshMessages();

  // set the timer
  window.setTimeout('updateMessages()', 30000);
} // updateMessages

/**
 * updateRaw
 *
 * Update the currently displayed raw packets.
 *
 */
function updateRaw(){
  // Load any new stations
  refreshRaw();

  // set the timer
  window.setTimeout('updateRaw()', 30000);
} // updateRaw

/**
 * updateRaw
 *
 * Update the currently displayed raw packets.
 *
 */
function updatePositions(){
  // Load any new stations
  refreshPositions();

  // set the timer
  window.setTimeout('updatePositions()', 30000);
} // updatePositions

/**
 * updateSearches
 *
 * Update the currently displayed searches.
 *
 */
function updateSearches(){
  // Load any new stations
  refreshSearches();

  // set the timer
  window.setTimeout('updateSearches()', 30000);
} // updateSearches

/**
 * updateStations
 *
 * Update the currently displayed map.
 *
 */
function updateStations(){
  // Load any new stations
  refreshStations();

  // set the timer
  window.setTimeout('updateStations()', 30000);
} // updateStations

/**
 *
 * Set Default Location
 *
 * If the checkbox exists on the page
 * set a cookie with our default location.
 *
 */
function setDefaults() {
  var save_default = document.getElementById("openaprs_form_save_default");

  if (save_default != null && save_default.checked == true) {
    setLocation();
    setCookie("openaprs_form_limit", "myLimit");
    setCookie("openaprs_form_units", "myUnits");
    setCookie("openaprs_form_geocoords", "myGeocoords");
    setCookie("openaprs_form_timezone", "myTimezone");
    setCookie("openaprs_form_zoom", "myZoom");
    setCookie("openaprs_form_show_phg", "myPHG");
    setCookie("openaprs_form_show_irlp", "myIRLP");
    setCookie("openaprs_form_enable_mouse", "myMouse");
    setCookie("openaprs_form_tactical", "myTactical");

    unCheck('openaprs_form_save_default');
    logById('logContainer', 'logTable', 'Settings: Settings set as default');
  } // if
  else
    logById('logContainer', 'logTable', 'Settings: saved');

  return true;
} // setDefaults

/**
 *
 * Set Default Location
 *
 * If the checkbox exists on the page
 * set a cookie with our default location.
 *
 */
function setLocation() {
  if (isChecked('openaprs_form_set_default')) {
    var center = map.getCenter();
    var zoom = map.getZoom();

    createCookie("myLocation", center.lat().toFixed(6) + ','+center.lng().toFixed(6)+','+zoom, 365);
    createCookie("myZoom", map.getZoom(), 365);

    logById('logContainer', 'logTable', 'Cookie: Default location changed.');
    changeById('mapSTATUS', 'Location Saved');
    changeById('topMESSAGE', 'Location Saved');
    unCheck('openaprs_form_set_default');
    return true;
  } // if

  return false;
} // setLocation

/**
 *
 * Get Chat Callsign
 *
 * If the field exists, try and get the callsign
 * from the chat interface.
 *
 */
function getChatCallsign() {
  var callsign = document.getElementById("openaprs_form_chat_callsign");

  if (callsign == null)
    return null;

  return callsign.value;
} // getChatCallsign

/**
 *
 * Log By Id
 *
 * Try and change an element's innerHTML contents
 * safely by id.
 *
 */
function logById(id1, id2, msg) {
  myContainer = document.getElementById(id1);
  myTable = document.getElementById(id2);

  if (myContainer == null || myTable == null)
    return false;

  var logArray = [];
  var d = new Date();
  var logDate = "<b>"+d.formatDate("yyyy-MM-dd HH:mm:ss")+":</b> ";

  var aCell = new cellStruct;
  aCell.text = logDate+msg;
  aCell.className="logTable";
  logArray.push(aCell);

  addRow2(id2, logArray.reverse());

  maxScroll(id1);

  limitRows(id2, 100);

  return true;
} // logById

function log(m) {
  logById('logContainer', 'logTable', m);
} // log

/**
 * loadView
 *
 * Load a requested view.
 *
 */
function loadView(id) {
  var findMe = document.getElementById('openaprs_form_find');

  if (findMe == null || id.length != 32)
    return;

  findMe.value = 'load:'+id;

  unPause('openaprs_form_pause');
  return;
} // loadView

/**
 * deleteSavedTrack
 *
 * Redraws the current list of stations.
 *
 */
function deleteView(id) {
  var request = createXMLHttpRequest();

  if (loggedIn == false)
    return;

  var queryString = "/ajax/view/delete.php?hash="+seed+"&id="+id;

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/reply", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {  
      } // for

      refreshSavedTracks();

    } // if

  } // function()

  request.send(null);
} // deleteView

/**
 * saveTracksClicked
 *
 * Update the currently displayed map.
 *
 */
function saveTracksClicked() {
  var saveName = document.getElementById("aprsVIEW:Form:Name");
  var re = RegExp('^([a-zA-Z0-9 .,-]{1,64})$');

  if (saveName == null)
    return;

  if (saveName.value.length < 1) {
    changeById('aprsVIEW:Error', 'Please type in a name first.');
    logById('logContainer', 'logTable', 'SAVE TRACKS: Please type in a name to save tracks as.');
    return false;
  } // if

  if (loggedIn == false) {
    changeById('aprsVIEW:Error', 'You must be logged in to use this feature.');
    logById('logContainer', 'logTable', 'SAVE TRACKS: Cannot save tracks you are not logged in.');
    return false;
  } // if

  if (!saveName.value.match(re)) {
    changeById('aprsVIEW:Error', 'Invalid name.');
    logById('logContainer', 'logTable', 'SAVE TRACKS: Saved name given is invalid.');
    return false;
  } // if

  if (saveView == true) {
    changeById('aprsVIEW:Error', 'In progress alread.');
    logById('logContainer', 'logTable', 'SAVE TRACKS: Already attempting to save tracks.');
    return false;
  } // if

  changeById('viewSTATUS', 'Saving');
  logById('logContainer', 'logTable', 'SAVE TRACKS: Attempting to save tracks.');
  disableField('aprsVIEW:Form:Name');

  saveView = true;

  unPause('openaprs_form_pause');

  return;
} // saveTracksClicked

/**
 * generateKeyClicked
 *
 * Update the currently displayed map.
 *
 */
function generateKeyClicked() {
  var request = createXMLHttpRequest();

  if (loggedIn == false) {
    changeById('verifyStatus', '[not logged in]');
    logById('logContainer', 'logTable', 'VERIFY: Cannot generate key you are not logged in.');
    return;
  } // if

  if (generateKey == true) {
    changeById('verifyStatus', '[already in progress]');
    logById('logContainer', 'logTable', 'VERIFY: Already attempting to generate a key.');
    return false;
  } // if

  generateKey = true;
  changeById('verifyStatus', '[generating]');
  logById('logContainer', 'logTable', 'VERIFY: Attempting to generate key.');
  disableField('openaprs_button_generate_key');

  var queryString = "/ajax/verify/do.php?hash="+seed;

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/reply", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {  
        changeFieldById('openaprs_form_unique_key', retData[i]["key"]);
        changeById('verifyStatus', retData[i]["message"]);
        changeById('verifyPayPal', retData[i]["paypal"]);
      } // for

      enableField('openaprs_button_generate_key');
      generateKey = false;
    } // if
  } // function()

  request.send(null);
} // generateKeyClicked

/**
 * checkVerifyClicked
 *
 * Update the currently displayed map.
 *
 */
function checkVerifyClicked() {
  var request = createXMLHttpRequest();

  if (loggedIn == false) {
    changeById('checkVerifyStatus', 'You must login first.');
    logById('logContainer', 'logTable', 'CHECK VERIFY: Cannot check verification you are not logged in.');
    return;
  } // if

  changeById('checkVerifyStatus', 'Checking verification...');
  logById('logContainer', 'logTable', 'VERIFY: Attempting to check verification.');
  disableField('openaprs_button_check_verify');

  var queryString = "/ajax/verify/check.php?hash="+seed;

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/reply", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {  
        changeById('checkVerifyStatus', retData[i]["message"]);
      } // for

      enableField('openaprs_button_check_verify');
    } // if
  } // function()

  request.send(null);
} // checkVerifyClicked

/**
 * deauthClicked
 *
 * Update the currently displayed map.
 *
 */
function deauthClicked() {
  var request = createXMLHttpRequest();

  if (loggedIn == false) {
    changeById('verifyStatus', '[not logged in]');
    logById('logContainer', 'logTable', 'DEAUTHORIZE: Cannot deauthorize you are not logged in.');
    return;
  } // if

  if (generateKey == true) {
    changeById('verifyStatus', '[already in progress]');
    logById('logContainer', 'logTable', 'DEAUTHORIZE: Already attempting to deauthorize account.');
    return false;
  } // if

  generateKey = true;
  changeById('verifyStatus', '[deuathorizing]');
  logById('logContainer', 'logTable', 'DEAUTHORIZE: Attempting to deauthorize account.');
  disableField('openaprs_button_deauth');

  var queryString = "/ajax/verify/deauth.php?hash="+seed;

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/reply", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {  
        changeFieldById('openaprs_form_unique_key', retData[i]["key"]);
        changeById('verifyStatus', retData[i]["message"]);
      } // for

      enableField('openaprs_button_deauth');
      generateKey = false;
    } // if
  } // function()

  request.send(null);
} // deauthClicked

/**
 * chatClicked
 *
 * Update the currently displayed map.
 *
 */
function chatClicked(){
  var request = createXMLHttpRequest();

  nick = escape(document.form_chat.chat_nick.value);
  message = escape(document.form_chat.chat_message.value);
  timestamp = document.form_chat.chat_timestamp.value;
  sequence = document.form_chat.chat_sequence.value;

  if (isValidCallsign(nick))
    createCookie("myCallsign", nick.toUpperCase(), 365);
  else {
    setChatStatus("Error", "Invalid callsign");
    changeById("chatSTATUS", "Invalid callsign");
    return;
  } // else

  if (message.toUpperCase() == "MESSAGE") {
    setChatStatus("Error", "Please type in a valid message first");
    changeById("chatSTATUS", "Missing message");
    return;
  } // if

  var queryString = "/ajax/chat.oapi?c=chat&chat_sequence=" + sequence + "&now=" + getUnixTime() + "&timestamp=" + timestamp + "&nick=" + nick + "&message=" + message;

  document.form_chat.chat_message.value = "";

  var start_date = new Date();

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      storeChatFromServer(request, start_date);
    } // if
  } // function()

  request.send(null);
} // chatClicked

function traverse(tree) {
        if(tree.hasChildNodes()) {
                document.write('<ul><li>');
                document.write('<b>'+tree.tagName+' : </b>');
                var nodes=tree.childNodes.length;
                for(var i=0; i<tree.childNodes.length; i++)
                        traverse(tree.childNodes(i));
                document.write('</li></ul>');
        }
        else
                document.write(tree.text);
}

/**
 * createURI
 *
 * Redraws the current list of stations.
 *
 */
function createURI(doc, first, ids, dfts) {
  var uri = "";

  if (first == true)
    var sep = '?';
  else
    var sep = '&';

  for(var obj in ids) {
    var checkMe = doc.getElementById(ids[obj]);

    if (uri.length > 0)
      sep = '&';

    if (checkMe == null ||
        checkMe.value.length < 1) {

      if (dfts != undefined 
          && dfts[obj] != undefined
          && dfts[obj].length > 0)
        uri += sep+obj+'='+encodeURIComponent(dfts[obj]);

      continue;
    } // if

    uri += sep+obj+'='+encodeURIComponent(checkMe.value);
  } // for

  return uri;
} // createURI

/**
 * linkGen
 *
 * Generate a link to OpenAPRS
 *
 */
function linkGen() {
  var url = "http://www.openaprs.net/";
  var linkField = document.getElementById("openaprs_form_linkgen");
  var findMe = document.getElementById("openaprs_form_find");

  if (linkField == null)
    return;

  if (findMe == null || findMe.value.length < 1) {
    linkField.value = "ERROR: Please fill the find field";
    return;
  } // if

  /**
   * Default Variables
   *
   * Span through the possible field values
   * and set our variable list accordingly.
   *
   */
  var ids = {
    "find": "openaprs_form_find",
    "tocall": "openaprs_form_tocall",
    "limit": "openaprs_form_limit",
    "limit_tracks": "openaprs_form_limit_tracks",
    "limit_uls": "openaprs_form_limit_uls",
    "age": "openaprs_form_age",
    "units": "openaprs_form_units",
    "geocoords": "openaprs_form_geocoords",
    "save": "openaprs_form_save_name",
    "load": "openaprs_form_load_name",
    "show_tracks": "openaprs_form_show_tracks",
    "show_irlp": "openaprs_form_show_irlp",
    "show_uls": "openaprs_form_show_uls",
    "timezone": "openaprs_form_timezone"
  };

  var dfts = {
    "find": "",
    "tocall": "",
    "limit": "15",
    "limit_tracks": "15",
    "limit_uls": "100",
    "age": "4 HOUR",
    "units": "imperial",
    "geocoords": "decimal",
    "save": "",
    "load": "",
    "show_tracks": "yes",
    "show_irlp": "yes",
    "show_uls": "no",
    "timezone": "America/Los_angeles"
  };

  var var_list = createURI(document, true, ids, dfts);

  url += var_list;

  linkField.value = url;

  return;
} // linkGen

/**
 * showHam
 *
 * Show ham that was found.
 *
 */
function showHam(callsign, address, image_name, cdata) {
  //logById('logContainer', 'logTable', 'Finding: ' + address);

  if (geocoder) {  
    geocoder.getLatLng(
      address,  
      function(point) {  
        if (point) {
          //logById('logContainer', 'logTable', 'Found: ' + address + ' '+point.x+','+point.y);
          var marker = createPerson(map, point.x, point.y, image_name, cdata);
        } // if
        else
          logById('logContainer', 'logTable', 'ULS: Unable to locate '+callsign+' ['+address+']');
      } // function
    );            
  } // if
} // showHam

/**
 * parseHams
 *
 * Parse the list of HAM items.
 *
 */
function parseHams(xmlDoc, object_list) {
  var address;

  if (xmlDoc == null)
    return 0;

  // initial variables
  retData = new Array();

  xmlArray("/openaprs/hams/ham", xmlDoc, retData);

  logById('logContainer', 'logTable', 'Found '+retData.length+' ham(s) in area');

  for (i=0; i < retData.length; i++) {  
    // don't try and re-add ULS entries, it would be
    // messy and slow.
    for(j=0; j < ulsNames.length; j++)
      if (ulsNames[j].toUpperCase() == retData[i]["callsign"].toUpperCase())
        break;

    if (j != ulsNames.length)
      continue;

    address = retData[i]["address"]+", "+
              retData[i]["city"]+", "+
              retData[i]["state"];

    //window.setTimeout('showHam(retData[i]["callsign"], address, retData[i]["image"], retData[i]["cdata"])',
    //                  i*1000);

    window.setTimeout('showHam("'+retData[i]["callsign"]+'", "'+address+'", "'+retData[i]["image"]+'", "'+addslashes(retData[i]["cdata"])+'")',
                      i*200);

    ulsNames.push(retData[i]["callsign"]);
  } // for

  return retData.length;
} // parseHams

/**
 * parseDraw
 *
 * Parse the list of HAM items.
 *
 */
function parseDraw(map, xmlDoc, object_list) {
  var address;
  var new_object_list = new Array();

  if (xmlDoc == null)
    return 0;

  // initial variables
  retData = new Array();

  xmlArray("/openaprs/draw/polygon", xmlDoc, retData);

  for (i=0; i < retData.length; i++) {
    if (typeof(retData[i]["line"]) != 'undefined') {
      var mySplitPlot = retData[i]["line"].split("|");

      if (mySplitPlot.length < 4) {
        logById('logContainer', 'logTable', 'DRAW: Invalid parameter count for polyline.');
        continue;
      } // if

      var points = Array();
      var color = mySplitPlot[0];
      var weight = mySplitPlot[1];
      var opacity = mySplitPlot[2];
      var coords = mySplitPlot[3].split(',');

      if ((coords.length % 2) != 0) {
        logById('logContainer', 'logTable', 'DRAW: Coordinate list not a modulous of 2 in polyline.');
        continue;
      } // if

      points.push(new google.maps.LatLng(coords[0], coords[1]));
      points.push(new google.maps.LatLng(coords[2], coords[3]));
      var polyline = new google.maps.Polyline({
        clickable: false,
        path: points,
        strokeColor: color,
        strokeWeight: weight,
        strokeOpacity: opacity
      });
      new_object_list.push(polyline);
    } //if

    // Draw polygon
    if (retData[i]["plot"] != undefined) {
      var points = Array();
      var mySplitCircle = retData[i]["plot"].split("|");

      if (mySplitCircle.length < 6) {
        logById('logContainer', 'logTable', 'DRAW: Invalid parameter count for polygon.');
        continue;
      } // if

      var strokeColor = mySplitCircle[0];
      var strokeWeight = mySplitCircle[1];
      var strokeOpacity = mySplitCircle[2];
      var fillColor = mySplitCircle[3];
      var fillOpacity = mySplitCircle[4];
      var coords = mySplitCircle[5].split(',');

      if ((coords.length % 2) != 0) {
        logById('logContainer', 'logTable', 'DRAW: Coordinate list not a modulous of 2 in polygon.');
        continue;
      } // if

      for(var k=0; k < coords.length; k+=2) {
        points.push(new google.maps.LatLng(coords[k], coords[k+1]));
//        logById('logContainer', 'logTable', 'DRAW: ' + coords[k] + ' ' + coords[k+1]);
      } // for

      if (retData[i]["label"] != undefined && retData[i]["center"] != undefined) {
        var center = retData[i]["center"].split(',');

        if ((center.length % 2) != 0)
          logById('logContainer', 'logTable', 'DRAW: Coordinate list not a modulous of 2 in polygon label.');
        else {
/* FIXME
          var label = new ELabel(new google.maps.LatLng(center[0], center[1]), retData[i]["label"], "polygonLabel", new google.maps.Size(-6, 4), 90);
          new_object_list.push(label);
*/
        } // else
     
      } // if

      if (points.length > 0) {
        var polygon = new google.maps.Polygon(points, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity);
        google.maps.event.addListener(polygon, "click", function(latlng) {
          map.setCenter(latlng, 11);
        });

        new_object_list.push(polygon);
      } // if

    } // if
  } // for

  for(var k = 0; k < new_object_list.length; k++)
    new_object_list[k].setMap(map);

  return retData.length;
} // parseDraw

/**
 * parseWeather
 *
 * Parse current weather conditions.
 *
 */
function parseWeather(xmlDoc) {
  var address;

  if (xmlDoc == null)
    return 0;

  // initial variables
  retData = new Array();

  xmlArray("/openaprs/weather", xmlDoc, retData);

  for (i=0; i < retData.length; i++) {  
    hideWindow('locateOverlay');

    if (!isHidden('topOverlay'))
      showWindow('weatherOverlay');

    changeById('weatherOverlay', retData[i]['cdata']);
  } // for

  if (retData.length < 1)
    hideWindow('weatherOverlay');

  return retData.length;
} // parseWeather

/**
 * refreshSatellite
 *
 * Redraws the current list of stations.
 *
 */
function refreshSatellite(map) {
  var request = createXMLHttpRequest();
  var pause = document.getElementById("openaprs_form_pause");

  if (pause != null && pause.checked == true) {
    changeById('locate_status', 'Paused');
    changeById('mapSTATUS', 'Paused');
    changeById('topMESSAGE', 'Paused');
    return;
  } // if

  /**
   * Default Variables
   *
   * Span through the possible field values
   * and set our variable list accordingly.
   *
   */
  var ids = {
    "find": "openaprs_form_find",
    "units": "openaprs_form_units",
    "geocoords": "openaprs_form_geocoords",
    "timezone": "openaprs_form_timezone"
  };

  var dfts = {
    "find": "",
    "units": "imperial",
    "geocoords": "decimal",
    "timezone": "America/Los_angeles"
  };

  var var_list = createURI(document, false, ids, dfts);

  changeById('mapSTATUS', 'Updating');
  changeById('topMESSAGE', 'Updating');
  changeById("locate_status", "<i>updating</i>");

  var queryString = "/ajax/satellites.php?hash="
                    + var_list;

  var start_date = new Date();

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {
    var len;

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var c = processSatellites(xmlDoc);

      var end_date = new Date();
      var diff = parseFloat((end_date.getTime()/1000) - (start_date.getTime()/1000));

      changeById("mapRESULTS", "Results " + c + " satellites (" + diff.toRound(3) + " seconds)");

    } // if

  } // function()

  request.send(null);
} // refreshSatellite

function processSatellites(xmlDoc) {
  var new_object_list = [];
  var station_list = "<table class=\"station_table\">";
  gmarkers = Array();

  if (xmlDoc == null)
    return;

  // Process Locations
  var retData = new Array();
  xmlArray("/openaprs/locations/location", xmlDoc, retData);
  for (i=0; i < retData.length; i++) {  
    var longitude = parseFloat(retData[i]["longitude"], 6);
    var latitude = parseFloat(retData[i]["latitude"], 6);

    // Draw the marker on the map only if it isn't in the station list
    var marker = createStationAJAX(longitude, latitude, retData[i]["name"], "/", retData[i]["icon"], retData[i]["info"]);

/* FIXME
    var label = new ELabel(new google.maps.LatLng(latitude, longitude), retData[i]["name"], "labels", new google.maps.Size(-18, +60), 90);
    createLabel(marker, label);
    label.hide();
    new_object_list.push(label);
*/
    new_object_list.push(marker);
  } // for

  var retData = new Array();
  xmlArray("/openaprs/satellites/satellite", xmlDoc, retData);
  for (i=0; i < retData.length; i++) {  
    var longitude = parseFloat(retData[i]["longitude"], 6);
    var latitude = parseFloat(retData[i]["latitude"], 6);
    var isPlanet = false;
    if (retData[i]["number"] == "-1" || retData[i]["number"] == "-2")
      isPlanet = true;

    if (retData.length == 1) {
      //var point = new google.maps.Point(longitude, latitude);
      //map.recenterOrPanToLatLng(point);
      //map.setCenter(new google.maps.LatLng(latitude, longitude));
    } // if

    if (retData[i]["home"] != undefined && retData.length == 3 && !isPlanet) {
      var homeLine = retData[i]["home"].split(",");
      var points = Array();
      points.push(new google.maps.LatLng(latitude, longitude));
      points.push(new google.maps.LatLng(homeLine[0], homeLine[1]));

      var bearing = Math.round(LatLon.bearing(parseFloat(homeLine[0]), parseFloat(homeLine[1]), latitude, longitude)*10)/10;

      var out = "Az: " + bearing + "&deg;"

      if (retData[i]["elevation"].length != 0) {
        var elevation = Math.round( parseFloat(retData[i]["elevation"])*10)/10;
        out += " El: " + elevation.toString() + "&deg;";
      } // if

      out += "<br />Alt: " + retData[i]["altitude"];

/* FIXME
      var label = new ELabel(new google.maps.LatLng(homeLine[0], homeLine[1]), out,"satLabel",new google.maps.Size(-20,90), 60);
      new_object_list.push(label);
*/

      var polyline = google.maps.Polyline({
        clickable: false,
        path: points,
        strokeColor: 'white',
        strokeWeight: 2,
        strokeOpacity: 0.8
      });
      new_object_list.push(polyline);
    } // if

    // Create ground circle
    // draw PHG circle if there is data for it.
    if (retData[i]["ground_circle"] != undefined) {
      var points = Array();
      var mySplitCircle = retData[i]["ground_circle"].split("|");

      for(var k=0; k < mySplitCircle.length; k++) {
        var circle_latlong = mySplitCircle[k].split(",");
        points.push(new google.maps.LatLng(circle_latlong[0], circle_latlong[1]));
      } // for

      if (points.length > 0)
        new_object_list.push(new google.maps.Polygon(points, 'green', 2, 0.8, 'green', 0.3));
    } // if

    // create track path
    var retCoordData = new Array();
    var points = Array();
    var colors = Array();

    xmlArray("/openaprs/satellites/satellite[name='"+retData[i]["name"]+"']/coordinates/coordinate", xmlDoc, retCoordData);

    for (j=0; j < retCoordData.length; j++) {  
      var coord_longitude = parseFloat(retCoordData[j]["longitude"], 6);
      var coord_latitude = parseFloat(retCoordData[j]["latitude"], 6);

      points.push(new google.maps.LatLng(coord_latitude, coord_longitude));
      colors.push(ageColor(retCoordData[j]["timestamp"]));
    } // for

    if (points.length > 0) {
      for(var y=0; y < points.length; y++) {
        if (y > 0) {
          var cpoints = Array();
          cpoints.push(lpoints);
          cpoints.push(points[y]);
          var polyline = new google.maps.Polyline({
            clickable: false,
            path: cpoints,
            strokeColor: seqColor(y, points.length),
            strokeWeight: 2,
            strokeOpacity: .5
          });
          new_object_list.push(polyline);
        } // if

        var lpoints = points[y];
      } // for
    } // if

    station_list += "<tr><td class=\"station_table\"><img src=\"" + retData[i]["imagePath"] + "\" width=\"18\" height=\"18\" /></td><td><a class=\"markerList\" onmouseover=\"javascript:google.maps.event.trigger(gmarkers['marker" + i + "'], 'mouseover')\" onmouseout=\"javascript:google.maps.event.trigger(gmarkers['marker" + i + "'], 'mouseout')\" href=\"javascript:trackSatellite('" + retData[i]["name"] + "')\">" + retData[i]["display"] + "</a> [<a class=\"markerList\" href=\"javascript:google.maps.event.trigger(gmarkers['marker" + i + "'], 'click')\">info</a>]</td><td>" + retData[i]["packetTime"] + "</td></tr>";
    // Draw the marker on the map only if it isn't in the station list
    var marker = createSatelliteAJAX(longitude, latitude, retData[i]["name"], retData[i]["imagePath"], retData[i]["cdata"]);
/* FIXME
    var label = new ELabel(new google.maps.LatLng(latitude, longitude), retData[i]["name"], "labels", new google.maps.Size(-18, +60), 90);
    if (hideLabels)
      label.hide();
    createLabel(marker, label);
    new_object_list.push(label);
*/

    gmarkers['marker'+i] = marker;

    new_object_list.push(marker);

  } // for

  station_list += "</table>";
  changeById("stationsContainer", station_list);
  changeById("locate_status", "<i>" + retData.length + " stations displayed</i>");
  changeById("mapSTATUS", "Idle");
  changeById('topMESSAGE', 'Idle');

  if (retData.length == 1)
    changeById("googleEarthLink", '[<a href="http://www.openaprs.net/ajax/google_earth/satellites/query.php?find='+retData[0]["name"]+'">Google Earth: ' + retData[0]["name"].toUpperCase() + '</a>]');
  else
    changeById("googleEarthLink", '[<a href="http://www.openaprs.net/ajax/google_earth/satellites/query.php">Google Earth: Satellites</a>]');

  if (retData.length < 1)
    changeById("stationsContainer", "<i>none</i>");

  // clear the map markers and draw the new ones
  map.clearOverlays();

  for(var k = 0; k < new_object_list.length; k++)
    new_object_list[k].setMap(map);

  object_list = new_object_list;

  return retData.length;
} // processSatellite

/**
 * refreshNews
 *
 * Redraws the current list of stations.
 *
 */
function refreshNews() {
  var request = createXMLHttpRequest();

  var queryString = "/ajax/news.php";

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      var markers = xmlDoc.documentElement.getElementsByTagName("marker");
      var news_list = "<table>";

      for (var i = 0; i < markers.length; i++) {

        var id = markers[i].getAttribute("id");
        var title = markers[i].getAttribute("title");
        var read = markers[i].getAttribute("read");
        var comments = markers[i].getAttribute("comments");

        news_list += "<tr><td><h2 id=\"news\"><a class=\"news\" href=\"/comments.html?id=" + id + "\">" + title + "</a></h2><br />";
        // news_list += "<a href=\"/comments.html?id=" + id + "\"><i>" + read + "</i></a> | <a href=\"/comments.html?id=" + id + "\"><i>" + comments + "</i></a>";
        news_list += "<a href=\"/comments.html?id=" + id + "\"><i>" + comments + "</i></a>";

      } // for

      news_list += "</table>";
      changeById("news_xml", news_list);
    } // if

  } // function()

  request.send(null);
} // refreshNews

/**
 * refreshServer
 *
 * Redraws the current list of stations.
 *
 */
function refreshServer() {
  var request = createXMLHttpRequest();
  var now = new Date();

  if (loading['server'] > 0) {
    now.setTime(loading['server']);
    logById('logContainer', 'logTable', 'STATS: Waiting on request from '+now.formatDate('yyyy-MM-dd hh:mm:ss'));
    return;
  } // if

  loading['server'] = now.getTime();

  var queryString = "/ajax/server.php";

  // ### PROFILING: START
  var start_date = new Date();

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      // var markers = xmlDoc.documentElement.getElementsByTagName("marker");
      var server_status = "<table>";

      loading['server'] = 0;

      clearRows('server_table');

      var retData = new Array();
      xmlArray("/openaprs/server/stat", xmlDoc, retData);

      for (var i = 0; i < retData.length; i++) {

        var name = retData[i]["name"];
        var formatted = retData[i]["formatted"];

        var chatArray = [];

        var aCell = new cellStruct;
        aCell.text = name;
        aCell.css_class = "header";
        chatArray.push(aCell);

        var aCell = new cellStruct;
        aCell.text = formatted;
        chatArray.push(aCell);

        addRow2('server_table', chatArray.reverse());

        //server_status += "<tr>";
        //server_status += "<td align=\"right\"><b>" + name + "</b></td><td>" + formatted + "</td>";
        //server_status += "</tr>";
      } // for

      // ### PROFILING: END
      var end_date = new Date();
      var diff = parseFloat((end_date.getTime()/1000) - (start_date.getTime()/1000));

      logById('logContainer', 'logTable', 'STATS: UPDATED (xml:'+diff.toRound(3)+' seconds)');
    } // if

  } // function()

  request.send(null);
} // refreshServer

/**
 * isValidCallsign
 *
 * Check to see if callsign looks valid.
 *
 */
function isValidCallsign(callsign) {
  var re = new RegExp("^([a-zA-Z0-9]{2,6})([-]{1}[0-9]+)?[*]*$");

  return callsign.match(re);
} // isValidCallsign

/**
 * setChatStatus
 *
 * Set the chat status box message.
 *
 */
function setChatStatus(status_type, status_message) {

  changeById("chat_status", "<b>" + status_type + ":</b>&nbsp;" + status_message);

  return;
} // setChatStatus

function dump(arr,level) {
	var dumped_text = "";
	if(!level) level = 0;
	
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";
	
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			var value = arr[item];
			
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}


/**
 * refreshChat
 *
 * Redraws the current list of stations.
 *
 */
function refreshChat() {
  var request = createXMLHttpRequest();
  var now = new Date();
  var then = new Date();

  if (!hasSeed) {
    // don't load chat if we don't have a session established
    // with the server
    logById('logContainer', 'logTable', 'CHAT: Waiting for session to be established with server.');
    return false;
  } // if
 
  // if we already are loading, don't try again.
  if (loading['chat'] > 0) {
    var diff = parseInt((now.getTime() - loading['chat'])/1000);
    then.setTime(loading['chat']);

    if (diff > 120) {
      logById('logContainer', 'logTable', 'CHAT: Expiring stale request from '+then.formatDate('yyyy-MM-dd hh:mm:ss'));
      loading['chat'] = 0;
    } // if
    else {
      setChatStatus('Status', 'please Wait');
      changeById('chatSTATUS', 'Please Wait');
      logById('logContainer', 'logTable', 'CHAT: Waiting on request from '+then.formatDate('yyyy-MM-dd hh:mm:ss')+' '+diff+ ' seconds');
      return;
    } // else
  } // if

  changeById('chatSTATUS', "Updating");
  var nick = escape(document.form_chat.chat_nick.value);

  // set timezone information
  var timezone = readCookie('myTimezone');

  if (timezone.length < 0)
    timezone = "America/Los_Angeles";

  if (isValidCallsign(nick))
    var queryString = "/ajax/chat.oapi?c=chat&chat_sequence=" + document.form_chat.chat_sequence.value + "&nick=" + nick + "&now=" + getUnixTime() + "&timestamp=" + document.form_chat.chat_timestamp.value + "&timezone=" + timezone+"&session="+seed+"&idle="+(getUnixTime()-chatIdle);
  else
    var queryString = "/ajax/chat.oapi?c=chat&chat_sequence=" + document.form_chat.chat_sequence.value + "&now=" + getUnixTime() + "&timestamp=" + document.form_chat.chat_timestamp.value + "&timezone=" + timezone+"&session="+seed+"&idle="+(getUnixTime()-chatIdle);

  document.form_chat.chat_timestamp.value = getUnixTime();

  // ### PROFILING: START
  var start_date = new Date();

  loading['chat'] = now.getTime();

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {
    //var chat_debug = document.getElementById("chat_debug")

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      // var markers = xmlDoc.documentElement.getElementsByTagName("chat");
      var len;

      loading['chat'] = 0;

      if (isValidCallsign(document.form_chat.chat_nick.value)) {
        setChatStatus("Status", "Idle");
        changeById('chatSTATUS', "Idle");
      } // if
      else
        changeById('chatSTATUS', "Please type in callsign");

      storeChatFromServer(request, start_date);

    } // if

  } // function()

  request.send(null);
} // refreshChat

function storeChatFromServer(xmlDoc, start_date) {
  if (xmlDoc == null) return;

  var parseMe = xmlDoc.responseText.split('\n');

  var users = 0;
  var hidden = 0;
  var nick_list = "";
  var chat_list = "";

  // Main large loop
  for(i=0; i < parseMe.length; i++) {
    // Skip broken lines or comments
    if (parseMe[i].length < 1 ||
        parseMe[i].substr(0, 1) == "#")
      continue;

    var v = new Vars();

    v.Parse(parseMe[i]);

    // BEGIN: Handle messages
    if (v.getField("TY") == "CH") {
      var chatArray = [];

      var aCell = new cellStruct;
      aCell.text = "<b>" + v.getField("NK") + "</b>:";
      chatArray.push(aCell);

      var aCell = new cellStruct;
      aCell.text =  v.getField("MS");
      chatArray.push(aCell);

      addRow2('chat_table', chatArray.reverse());

      var chatArray = [];

      var aCell = new cellStruct;
      aCell.text = "<i>(sent: " + v.getField("DT") + ")</i>";
      aCell.colspan = 2;
      chatArray.push(aCell);

      addRow2('chat_table', chatArray.reverse());
    } // if
    maxScroll('chat_container');
    maxScroll('chatMainText');
    limitRows('chat_table', 107);
    // END: Handle messages


    /**
     * Update the status window.
     *
     */
    if (v.getField("TY") == "ST") {
      // Change chat menu bottom background color.
      if (v.getField("SQ") > document.form_chat.chat_sequence.value && blinkTimerId == 0) {
        changeTopMESSAGE('<span style="color: red">Unread Chat Messages</span>');
        //blinkIMG("chat", 800, "/images/mini/on/chat.png", "/images/mini/blink/blank.png");
        changeImageById('Mini:Chat:Image', '/images/mini/newchat.png');
      } // if

      //if (retData[i]["sequence"] > document.form_chat.chat_sequence.value && blinkTimerId == 0)
      //  blinkBackground('chatOver', 500, '#C00000', '#FFFFFF', '#FFFFFF', '#000000');

      users = v.getField("NU");
      hidden = v.getField("HC");

      document.form_chat.chat_sequence.value = v.getField("SQ");
      changeById("chat_stats", users+" USERS "+hidden+" HIDDEN");
      changeById("mapCHAT", "Online: " +users+" users "+hidden+" hidden");
    } // if

    /**
     * Update Who's Online.
     *
     */
    if (v.getField("TY") == "OL") {
        chat_list += v.getField("URL") + "<br />";

        if (nick_list.length == 0)
          nick_list += v.getField("URL");
        else
          nick_list += ", " + v.getField("URL");
      } // if

  } // for

  if (nick_list.length == 0)
    nick_list += "<i>none</i>";

  changeById("chatNicklist", "<b>" + chat_list + "</b>");

  changeById("chat_online", nick_list);

  // ### PROFILING: END
  var end_date = new Date();
  var diff = parseFloat((end_date.getTime()/1000) - (start_date.getTime()/1000));

  changeById("chatSTATS", "Results " + users +" users "+ hidden+" hidden (" + diff.toRound(3) +" secs)");
  logById('logContainer', 'logTable', 'CHAT: UPDATED (T:'+diff.toRound(3)+' seconds)');
} // storeChatFromServer

/**
 * refreshChat
 *
 * Redraws the current list of stations.
 *
 */
function OLDrefreshChat() {
  var request = createXMLHttpRequest();
  var now = new Date();
  var then = new Date();

  if (!hasSeed) {
    // don't load chat if we don't have a session established
    // with the server
    logById('logContainer', 'logTable', 'CHAT: Waiting for session to be established with server.');
    return false;
  } // if
 
  // if we already are loading, don't try again.
  if (loading['chat'] > 0) {
    var diff = parseInt((now.getTime() - loading['chat'])/1000);
    then.setTime(loading['chat']);

    if (diff > 120) {
      logById('logContainer', 'logTable', 'CHAT: Expiring stale request from '+then.formatDate('yyyy-MM-dd hh:mm:ss'));
      loading['chat'] = 0;
    } // if
    else {
      setChatStatus('Status', 'please Wait');
      changeById('chatSTATUS', 'Please Wait');
      logById('logContainer', 'logTable', 'CHAT: Waiting on request from '+then.formatDate('yyyy-MM-dd hh:mm:ss')+' '+diff+ ' seconds');
      return;
    } // else
  } // if

  changeById('chatSTATUS', "Updating");
  var nick = escape(document.form_chat.chat_nick.value);

  // set timezone information
  var timezone = readCookie('myTimezone');

  if (timezone.length < 0)
    timezone = "America/Los_Angeles";

  if (isValidCallsign(nick))
    var queryString = "/ajax/chat.oapi?c=chat&chat_sequence=" + document.form_chat.chat_sequence.value + "&nick=" + nick + "&now=" + getUnixTime() + "&timestamp=" + document.form_chat.chat_timestamp.value + "&timezone=" + timezone+"&session="+seed+"&idle="+(getUnixTime()-chatIdle);
  else
    var queryString = "/ajax/chat.oapi?c=chat&chat_sequence=" + document.form_chat.chat_sequence.value + "&now=" + getUnixTime() + "&timestamp=" + document.form_chat.chat_timestamp.value + "&timezone=" + timezone+"&session="+seed+"&idle="+(getUnixTime()-chatIdle);

  document.form_chat.chat_timestamp.value = getUnixTime();

  // ### PROFILING: START
  var start_date = new Date();

  loading['chat'] = now.getTime();

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {
    //var chat_debug = document.getElementById("chat_debug")

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      // var markers = xmlDoc.documentElement.getElementsByTagName("chat");
      var len;

      loading['chat'] = 0;

      if (isValidCallsign(document.form_chat.chat_nick.value)) {
        setChatStatus("Status", "Idle");
        changeById('chatSTATUS', "Idle");
      } // if
      else
        changeById('chatSTATUS', "Please type in callsign");

      //var arr = xml2array(xmlDoc);
      //chat_debug.innterHTML += arr.length;
      //return;
      var retData = new Array();
      xmlArray("/openaprs/chat/messages", xmlDoc, retData);
      // chat_debug.innerHTML += "L:" + retData.length+"<br />";

      for (i=0; i < retData.length; i++) {  
        var chatArray = [];

        var aCell = new cellStruct;
        aCell.text = "<b>" + retData[i]["nick"] + "</b>:";
        chatArray.push(aCell);

        var aCell = new cellStruct;
        aCell.text = retData[i]["message"];
        chatArray.push(aCell);

        addRow2('chat_table', chatArray.reverse());

        var chatArray = [];

        var aCell = new cellStruct;
        aCell.text = "<i>(sent: " + retData[i]["date"] + ")</i>";
        aCell.colspan = 2;
        chatArray.push(aCell);

        addRow2('chat_table', chatArray.reverse());
      } // for

      maxScroll('chat_container');
      maxScroll('chatMainText');
      limitRows('chat_table', 107);

      /**
       * Update the status window.
       *
       */
      var retData = new Array();
      var users = 0;
      var hidden = 0;
      xmlArray("/openaprs/chat/status", xmlDoc, retData);

      for (i=0; i < retData.length; i++) {  
        // Change chat menu bottom background color.
        if (retData[i]["sequence"] > document.form_chat.chat_sequence.value && blinkTimerId == 0) {
          changeTopMESSAGE('<span style="color: red">Unread Chat Messages</span>');
          //blinkIMG("chat", 800, "/images/mini/on/chat.png", "/images/mini/blink/blank.png");
          changeImageById('Mini:Chat:Image', '/images/mini/newchat.png');
        } // if

        //if (retData[i]["sequence"] > document.form_chat.chat_sequence.value && blinkTimerId == 0)
        //  blinkBackground('chatOver', 500, '#C00000', '#FFFFFF', '#FFFFFF', '#000000');

        users = retData[i]["users"];
        hidden = retData[i]["hidden"]

        document.form_chat.chat_sequence.value = retData[i]["sequence"];
        changeById("chat_stats", retData[i]["users"]+" USERS "+retData[i]["hidden"]+" HIDDEN");
        changeById("mapCHAT", "Online: " +retData[i]["users"]+" users "+retData[i]["hidden"]+" hidden");
      } // for

      /**
       * Update Who's Online.
       *
       */
      var nick_list = "";
      var chat_list = "";

      var retData = new Array();
      xmlArray("/openaprs/chat/online/user", xmlDoc, retData);

      for (i=0; i < retData.length; i++) {  
        chat_list += retData[i]["url"] + "<br />";

        if (nick_list.length == 0)
          nick_list += retData[i]["url"];
        else
          nick_list += ", " + retData[i]["url"];
      } // for

      if (nick_list.length == 0)
        nick_list += "<i>none</i>";

      changeById("chatNicklist", "<b>" + chat_list + "</b>");

      changeById("chat_online", nick_list);

      // ### PROFILING: END
      var end_date = new Date();
      var diff = parseFloat((end_date.getTime()/1000) - (start_date.getTime()/1000));

      logById('logContainer', 'logTable', 'CHAT: UPDATED (xml:'+diff.toRound(3)+' seconds)');
      changeById("chatSTATS", "Results " + users +" users "+ hidden+" hidden (" + diff.toRound(3) +" secs)");

    } // if

  } // function()

  request.send(null);
} // OLDrefreshChat

/**
 * showViewLinks
 *
 */
function showViewLinks(id) {
  changeFieldById('aprsVIEW:Form:Link', 
                  'http://www.openaprs.net/engine/load/' + id);

  changeFieldById('aprsVIEW:Form:geLink', 
                  'http://www.openaprs.net/engine/google_earth/load/' + id);
} // showViewLinks

/**
 * refreshSavedTracks
 *
 * Redraws the current list of stations.
 *
 */
function refreshSavedTracks() {
  var request = createXMLHttpRequest();
  var now = new Date();

  if (loggedIn == false)
    return;

  var queryString = "/ajax/view/views.php?hash="+seed;

  // ### PROFILING: START
  var start_date = new Date();

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      var bColor;
      var numViews = 0;

      clearRows('viewTable');

      var retData = new Array();
      xmlArray("/openaprs/views/view", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {  
        if ((i % 2) == 0)
          bColor = 'bgLight';
        else
          bColor = 'bgDark';

        var cellArray = [];
  
        var aCell = new cellStruct;
        aCell.text = '<a href="javascript:void(0)" onClick="gOpenAPRS.loadView(\''+retData[i]["hash"]+'\')">'+retData[i]["name"]+'</a>';
        aCell.css_class = bColor;
        cellArray.push(aCell);

        var aCell = new cellStruct;
        aCell.text = retData[i]["since"] + " ago";
        aCell.css_class = bColor;
        cellArray.push(aCell);

        var aCell = new cellStruct;
        aCell.text = '<a href="javascript:showViewLinks(\''+retData[i]["hash"]+'\')"><img src="/images/views/links.png" width="12" height="12" border="0" /></a>'
                     + '&nbsp;<a href="javascript:deleteView(\''+retData[i]["hash"]+'\')"><img src="/images/friends/remove.png" width="12" height="12" border="0" /></a>';
        aCell.css_class = bColor;
        cellArray.push(aCell);

        addRow2('viewTable', cellArray.reverse());

        numViews++;

      } // for

      // ### PROFILING: END
      var end_date = new Date();
      var diff = parseFloat((end_date.getTime()/1000) - (start_date.getTime()/1000));
      logById('logContainer', 'logTable', 'aprsVIEW: UPDATED (xml:'+diff.toRound(3)+' seconds)');
      changeById("viewSTATS", numViews +" views (" + diff.toRound(3) +" secs)");
      changeById('viewSTATUS', 'Idle');

      if (retData.length > 0)
        logById('logContainer', 'logTable', 'SAVED TRACKS: You have '+retData.length+' saved track(s)');
      else
        logById('logContainer', 'logTable', 'SAVED TRACKS: You have no saved tracks.');

    } // if

  } // function()

  request.send(null);
} // refreshSavedTracks

/**
 * searchRaw
 *
 * Search for a callsign in the raw table.
 *
 */
function searchRaw() {
  timestamp = document.getElementById("openaprs_form_timestamp");

  if (timestamp == null)
    return;

  unCheck("openaprs_form_pause");

  clearRows('rawTable');
  timestamp.value = 0;

  refreshRaw();
} // searchRaw

/**
 * refreshRaw
 *
 * Redraws the current list of stations.
 *
 */
function refreshRaw() {
  var request = createXMLHttpRequest();
  var timestamp = document.getElementById("openaprs_form_timestamp");
  var callsign = document.getElementById("openaprs_form_callsign");
  var loading = document.getElementById("openaprs_form_loading");
  var limit = 30;

  if (timestamp == null || callsign == null || loading == null)
    return;

  if (parseInt(loading.value) == 1)
    return;

  if (isChecked("openaprs_form_pause")) {
    changeById('rawStatus', 'Paused');
    return;
  } // if

  loading.value = 1;

  // set timezone information
  var timezone = escape(readCookie('myTimezone'));

  if (timezone.length < 0)
    timezone = "America/Los_Angeles";

  if (limit > 1000)
    limit = 100;

  if (callsign.value.length < 1)
    var queryString = "/ajax/raw.php?timestamp=" + timestamp.value + "&limit=" + limit + "&timezone=" + timezone;
  else
    var queryString = "/ajax/raw.php?timestamp=" + timestamp.value + "&callsign=" + callsign.value + "&limit=" + limit + "&timezone=" + timezone;

  changeById('rawStatus', 'updating');

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      var tableRef = document.getElementById("rawTable");
      var markers = xmlDoc.documentElement.getElementsByTagName("status");
      var timestamp = document.getElementById("openaprs_form_timestamp");

      for (var i = 0; i < markers.length; i++) {
        var num_returned = markers[i].getAttribute("count");
        timestamp.value = markers[i].getAttribute("timestamp");
        var since = markers[i].getAttribute("since");
        var display_mode = markers[i].getAttribute("mode");
        var search = parseInt(markers[i].getAttribute("search"));

        changeById("rawStatus", tableRef.rows.length + " displayed " + num_returned + " added " + since + " ago running in " + display_mode + " mode");
      } // for

      var markers = xmlDoc.documentElement.getElementsByTagName("marker");

      for (var i = 0; i < markers.length; i++) {

        var source = markers[i].getAttribute("source");
        var path = markers[i].getAttribute("path");
        var information = markers[i].getAttribute("information");
        var packet_date = markers[i].getAttribute("packet_date");
        var error_message = markers[i].getAttribute("error");

        var chatArray = [];
  
        var aCell = new cellStruct;
        if (error_message.length > 0)
          aCell.text = "<div id=\"rawTD"+rawTableCount+"\" class=\"liveDivERROR\">&nbsp;<b>["+error_message+"]</b>&nbsp;<a href=\"javascript:trackRaw('" + source + "')\">" + source + "</a>&gt;" + path + ":" + information + "<br /><i>(sent: "+packet_date+"</i></div>";
        else
          aCell.text = "<div id=\"rawTD"+rawTableCount+"\" class=\"liveDiv\">&nbsp;<a class=\"message_list\" href=\"javascript:trackRaw('" + source + "')\">" + source + "</a>&gt;" + path + ":" + information+"<br /><i>(sent: "+packet_date+")</i></div>";
        // aCell.id = 'rawTD'+rawTableCount;
        chatArray.push(aCell);

        pushRow('rawTable', chatArray.reverse());

        opacity('rawTD'+rawTableCount, 5, 100, 1, 1000, i);
        rawTableCount++;
      } // for

      limitRowsEnd('rawTable', 300);
      loading.value = 0;
    } // if

  } // function()

  request.send(null);
} // refreshRaw

/**
 * searchPositions
 *
 * Search for a callsign in the raw table.
 *
 */
function searchPositions() {
  timestamp = document.getElementById("openaprs_form_timestamp");

  if (timestamp == null)
    return;

  unCheck("openaprs_form_pause");
  clearRows('positionsTable');
  timestamp.value = 0;

  refreshPositions();
} // searchPositions

/**
 * refreshPositions
 *
 * Redraws the current list of stations.
 *
 */
function refreshPositions() {
  var request = createXMLHttpRequest();
  var timestamp = document.getElementById("openaprs_form_timestamp");
  var callsign = document.getElementById("openaprs_form_callsign");
  var loading = document.getElementById("openaprs_form_loading");
  var limit = 30;

  if (timestamp == null || callsign == null || loading == null)
    return;

  if (parseInt(loading.value) == 1)
    return;

  if (isChecked("openaprs_form_pause")) {
    changeById('positionsStatus', 'Paused');
    return;
  } // if

  loading.value = 1;

  // set timezone information
  var timezone = escape(readCookie('myTimezone'));

  if (timezone.length < 0)
    timezone = "America/Los_Angeles";

  if (callsign.value.length < 1)
    var queryString = "/ajax/positions.php?timestamp=" + timestamp.value + "&limit=" + limit + "&timezone=" + timezone;
  else
    var queryString = "/ajax/positions.php?timestamp=" + timestamp.value + "&callsign=" + callsign.value + "&limit=" + limit + "&timezone=" + timezone;

  changeById('positionsStatus', 'updating');

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      var tableRef = document.getElementById("positionsTable");
      var markers = xmlDoc.documentElement.getElementsByTagName("status");
      var timestamp = document.getElementById("openaprs_form_timestamp");

      for (var i = 0; i < markers.length; i++) {
        var num_returned = markers[i].getAttribute("count");
        timestamp.value = markers[i].getAttribute("timestamp");
        var since = markers[i].getAttribute("since");
        var display_mode = markers[i].getAttribute("mode");
        var search = parseInt(markers[i].getAttribute("search"));

        changeById("positionsStatus", tableRef.rows.length + " displayed " + num_returned + " added " + since + " ago running in " + display_mode + " mode");
      } // for

      var markers = xmlDoc.documentElement.getElementsByTagName("marker");
      for (var i = 0; i < markers.length; i++) {

        var source = markers[i].getAttribute("source");
        var latitude = markers[i].getAttribute("latitude");
        var longitude = markers[i].getAttribute("longitude");
        var city = markers[i].getAttribute("city");
        var state = markers[i].getAttribute("state");
        var county = markers[i].getAttribute("county");
        var distance = markers[i].getAttribute("distance");
        var cdata = markers[i].getAttribute("cdata");
        var packet_date = markers[i].getAttribute("packet_date");

        var geocoords = readCookie("myGeocoords");

        if (geocoords == "utm") {
          xy = new Object()
          zone = Math.floor ((longitude + 180.0) / 6) + 1;
          zone = LatLonToUTMXY(DegToRad(latitude), DegToRad(longitude), zone, xy);
          latitude = zone + " " + parseInt(xy[0]) + "m E";
          longitude = parseInt(xy[1]) + "m N";
        } // if
        if (geocoords == "dms") {
          latitude = parseFloat(latitude).toLat();
          longitude = parseFloat(longitude).toLon();
        } // if

        var chatArray = [];
  
        var aCell = new cellStruct;
        aCell.text = "<div id=\"positionsTD"+positionsTableCount+"\">&nbsp;" + packet_date + ": <a class=\"message_list\" href=\"javascript:trackPositions('" + source + "')\">" + source + "</a>&gt;" + latitude + ", " +longitude+": " +cdata+"</div>";
        chatArray.push(aCell);

        pushRow('positionsTable', chatArray.reverse());

        opacity('positionsTD'+positionsTableCount, 5, 100, 1, 1000, i);
        positionsTableCount++;
      } // for

      limitRowsEnd('positionsTable', 300);
      loading.value = 0;
    } // if

  } // function()

  request.send(null);
} // refreshPositions

/**
 * searchMessages
 *
 * Search for a callsign in the raw table.
 *
 */
function searchMessages() {
  timestamp = document.getElementById("openaprs_form_timestamp");

  if (timestamp == null)
    return;

  unCheck("openaprs_form_pause");
  clearRows('messageTable');
  timestamp.value = 0;

  refreshMessages();
} // searchMessages

/**
 * refreshMessages
 *
 * Redraws the current list of stations.
 *
 */
function refreshMessages() {
  var request = createXMLHttpRequest();
  var timestamp = document.getElementById("openaprs_form_timestamp");
  var callsign = document.getElementById("openaprs_form_callsign");
  var match_field = document.getElementById("openaprs_form_match");
  var loading = document.getElementById("openaprs_form_loading");
  var limit = 30;

  if (timestamp == null || callsign == null || loading == null || match_field == null)
    return;

  if (parseInt(loading.value) == 1)
    return;

  if (isChecked("openaprs_form_pause")) {
    changeById('messageStatus', 'Paused');
    return;
  } // if

  loading.value = 1;

  // set timezone information
  var timezone = escape(readCookie('myTimezone'));

  if (timezone.length < 0)
    timezone = "America/Los_Angeles";

  if (limit > 1000)
    limit = 100;

  if (callsign.length < 1 || callsign.value == 'Callsign')
    var queryString = "/ajax/messages.php?timestamp=" + timestamp.value + "&limit=" + limit + "&timezone=" + timezone;
  else
    var queryString = "/ajax/messages.php?timestamp=" + timestamp.value + "&callsign=" + callsign.value + "&match=" + match_field.value + "&limit=" + limit + "&timezone=" + timezone;

  changeById('messageStatus', 'updating');

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      var tableRef = document.getElementById("messageTable");
      var markers = xmlDoc.documentElement.getElementsByTagName("status");
      var timestamp = document.getElementById("openaprs_form_timestamp");

      for (var i = 0; i < markers.length; i++) {
        var num_returned = markers[i].getAttribute("count");
        timestamp.value = markers[i].getAttribute("timestamp");

        var since = markers[i].getAttribute("since");
        var display_mode = markers[i].getAttribute("mode");
        var search = parseInt(markers[i].getAttribute("search"));

        changeById("messageStatus", tableRef.rows.length + " displayed " + num_returned + " added " + since + " ago running in " + display_mode + " mode");
      } // for

      var markers = xmlDoc.documentElement.getElementsByTagName("marker");

      for (var i = 0; i < markers.length; i++) {
        var source = markers[i].getAttribute("source");
        var addressee = markers[i].getAttribute("addressee");
        var message = markers[i].getAttribute("message");
        var packet_date = markers[i].getAttribute("packet_date");
        var track_url = markers[i].getAttribute("track_source");
        var track_addressee = markers[i].getAttribute("track_addressee");

        if (callsign.value == addressee)
          var className = "liveDivLight";
        else
          var className = "liveDiv";

        var chatArray = [];
  
        var aCell = new cellStruct;
        aCell.text = "<div id=\"messageTD"+messageTableCount+"\" class=\""+className+"\">&nbsp;<a class=\"message_list\" href=\"javascript:trackMessages('" + source + "')\">" + source + "</a><b>&gt;</b><a class=\"message_list\" href=\"javascript:trackMessages('" + addressee + "')\">" + addressee + "</a><b>:</b> " + message+ "<br /><i>(sent: "+packet_date+"</i>)</div>";
        // aCell.id = 'rawTD'+messageTableCount;
        chatArray.push(aCell);

        pushRow('messageTable', chatArray.reverse());

        opacity('messageTD'+messageTableCount, 5, 100, 1, 1000, i);
        messageTableCount++;
      } // for

      limitRowsEnd('messageTable', 300);
      loading.value = 0;
    } // if

  } // function()

  request.send(null);
} // refreshMessages

/**
 * refreshSearches
 *
 * Redraws the current list of searches.
 *
 */
function refreshSearches() {
  var request = createXMLHttpRequest();
  var limit = 30;

  if (parseInt(document.form_packet.loading.value) == 1)
    return;

  document.form_packet.loading.value = 1;

  var timestamp = document.form_packet.timestamp.value;

  // set timezone information
  var timezone = escape(readCookie('myTimezone'));

  if (timezone.length < 0)
    timezone = "America/Los_Angeles";

  var queryString = "/ajax/searches.php?timestamp=" + timestamp + "&limit=" + limit + "&timezone=" + timezone;

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      var tableRef = document.getElementById("searchesTable");
      var markers = xmlDoc.documentElement.getElementsByTagName("status");

      for (var i = 0; i < markers.length; i++) {
        var num_returned = markers[i].getAttribute("count");
        document.form_packet.timestamp.value = markers[i].getAttribute("timestamp");
        var since = markers[i].getAttribute("since");

        changeById("searchesStatus", tableRef.rows.length + " previously displayed " + num_returned + " added since ~" + since + " ago");
      } // for

      var markers = xmlDoc.documentElement.getElementsByTagName("marker");

      for (var i = 0; i < markers.length; i++) {

        var name = markers[i].getAttribute("name");
        var search_date = markers[i].getAttribute("search_date");
        var callsign = markers[i].getAttribute("source");
        var count = markers[i].getAttribute("count");
        var browser = markers[i].getAttribute("browser");
        var search_type = markers[i].getAttribute("type").toLowerCase();
        var track_url = markers[i].getAttribute("track_url");

        var chatArray = [];
  
        var aCell = new cellStruct;
        aCell.text = "<div id=\"searchesTD"+searchesTableCount+"\">&nbsp;" + search_date + ": <a class=\"message_list\" href=\"http://www.openaprs.net/engine/track/" + callsign + "\">" + callsign + "</a> <span style=\"color:red\">("+browser+")</span> searched for <a class=\"message_list\" href=\"" + track_url + "\">" + name + "</a> [<a href=\"http://www.openaprs.net/info/" + name + "\">info</a>] [<a href=\"javascript:popupTrack('" + name + "')\">track</a>] by <span style=\"color:green\">" + search_type.toUpperCase() + "</span> interface [popularity+" + count + "]</div>";
        chatArray.push(aCell);

        pushRow('searchesTable', chatArray.reverse());

        opacity('searchesTD'+searchesTableCount, 5, 100, 1, 1000, i);
        searchesTableCount++;
      } // for

      limitRowsEnd('searchesTable', 300);
      document.form_packet.loading.value = 0;
    } // if

  } // function()

  request.send(null);
} // refreshSearches

/**
 * refreshStations
 *
 * Redraws the current list of stations.
 *
 */
function refreshStations() {
  var request = createXMLHttpRequest();

  var queryString = "/ajax/stations.php";

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      var markers = xmlDoc.documentElement.getElementsByTagName("marker");
      var station_list = "";

      for (var i = 0; i < markers.length; i++) {

        var callsign = markers[i].getAttribute("source");
        var packet_date = markers[i].getAttribute("packet_date");

        station_list += "<a class=\"maplist\" href=\"/track.html?source=" + callsign + "\">" + callsign + "</a><br />";
        station_list += packet_date + "<br />";

      } // for

      changeById("xml_stations", station_list);
      changeById("station_footer", "Query returned " + i + " results.");
    } // if

  } // function()

  request.send(null);
} // refreshStations

