// aimsXML.js
/*
*  JavaScript template file for ArcIMS HTML Viewer
*       dependent on ArcIMSparam.js, aimsCommon.js, aimsMap.js,
*/

aimsXMLPresent=true;
// client version
var cVersion = "&ClientVersion=4.0.1";
/*
***************************************************************************************

Functions for sending XML requests and XML reponses

***************************************************************************************
*/

// global variables
    // change these in aimsCustom.js to send XML response to custom function.
    // use numbers >= 1000
var selectXMLMode = 6;
var identifyXMLMode = 7;
var queryXMLMode = 8;
var findXMLMode = 14;
var hyperlinkXMLMode = 15;

var abuttersXMLMode = 701;
var selectAddToList = 801;
var selectRemoveFromList = 802;

// encoding for XML header
var charEncoding = "UTF-8";
var localeEncoding = 'encoding="' + charEncoding + '" ';

// charset for dynamic HTML pages - static pages must be changed manually
var charSet = "ISO-8859-1"

var formColor = "#000000";

// common dynamic variables
var XMLMode = 1;
var okToSend = true;

var xHalf = xDistance/2;
var yHalf = yDistance/2;

// ending position to start parse scan of XML string
var xmlEndPos = 0;

//var theImageType = "PNG";

var drawOVExtentBox=false;
// force a request for Overview map image with each map request?
var forceNewOVMap = false;
// the base servlet connector URL
var connectorURL = "http://" + hostName + "/servlet/com.esri.esrimap.Esrimap?ServiceName=redirect";

    // index of current active MapService - default is zero - multiples in MultiService sample
var activeMapServiceIndex = 0;
    // array for determining if extent coordinates should have comma instead of point for decimals
var forceCommaInRequest = new Array();
forceCommaInRequest[activeMapServiceIndex] = false;
var forceCommaInOV = false;

var pastStart=false;
if (hasOVMap != true) pastStart = true;

// send in XML request and get XML response - uses helper applet
function sendToServer(URLString,XMLRequest,theType) {
//alert(theType);
    if (parent.PostFrame.document.forms[0]!=null) {
        if (okToSend) {
            XMLMode = theType;
            if (XMLMode==1) showRetrieveMap();
            //theForm = parent.AppletFrame.document.forms[0];
            if (debugOn>2) alert(msgList[8] + URLString + msgList[9] + XMLRequest);
            okToSend = false;
            var theForm = parent.PostFrame.document.forms[0];
            URLString = URLString + cVersion;
            var requestURL = URLString;
            if (theForm.RedirectURL!=null) {
                if (isNotSameHostInURL(URLString, hostName)) {
                    requestURL = connectorURL;
                    theForm.RedirectURL.value = URLString;
                } else {
                    theForm.RedirectURL.value = "";
                }
            }
            //alert(URLString);
            if (doURLencode) {
                theForm.action = requestURL + "&Form=True&Encode=True";
            } else {
                theForm.action = requestURL + "&Form=True&Encode=False";
            }
            var xmlHeader = '<?xml version="1.0" ' + localeEncoding + '?>';
            theForm.ArcXMLRequest.value = xmlHeader + XMLRequest;
            //if (theForm.FormCharset!=null) theForm.FormCharset.value = charEncoding;
            if (theForm.FormCharset!=null) theForm.FormCharset.value = charSet;
            //alert("ServiceName: " + theForm.action + "\nXMLRequest:\n " + theForm.xmlRequest.value);
            if (theForm.BgColor!=null) theForm.BgColor.value = formColor;
            theForm.submit();
        } else {
            alert(msgList[10]);
            hideRetrieveMap();
            hideRetrieveData();
        }
    } else {
        alert(msgList[11]);
            hideRetrieveMap();
            hideRetrieveData();
    }

}

// send custom XML request. . . set up custom response handler
function sendCustomToServer(XMLRequest, theFunction, theType) {
    var theForm = parent.PostFrame.document.forms[0];
    theForm.JavaScriptFunction.value = theFunction;
    sendToServer(imsQueryURL,XMLRequest,theType)
}

// send the created xml request to map server
function sendMapXML() {
    // ask for the Main map
    //window.onerror=clearError;
    beforeMapRefresh();
    //window.onerror=resetError;
    showRetrieveMap();
    var theText = writeXML();
    if (debugOn==2) alert(msgList[12] + theText);
    sendToServer(imsURL,theText,1);
}

// process the response xml
function processXML(theReplyIn) {
    if (doURLencode) {
        theReplyIn = replacePlus(theReplyIn);
        var theReply = unescape(theReplyIn);
    } else {
        var theReply = theReplyIn;
    }
    okToSend = true;
    if (debugOn>2) alert(msgList[13] + theReply);
    var theError = getXMLErrorMessage(theReply);
    switch(XMLMode) {
        case 1:
            var theURL = "";
            theURL = getURL(theReply);
            if (theURL != "") {
                getXYs(theReply);
                document.theImage.src = theURL;

                afterMapRefresh();
                //window.onerror=resetError;
                if (toolMode==3) {
                    moveLayer("theMap",hspc,vspc);
                    clipLayer2("theMap",0,0,iWidth,iHeight);
                    window.setTimeout('showLayer("theMap");',1000);
                    if (hasLayer("theMapClicks")) {
                        moveLayer("theMapClicks",hspc,vspc);
                        clipLayer2("theMapClicks",0,0,iWidth,iHeight);

                    }
                }

            }
            else {

                if (debugOn>0) {
                    //JB Edit to Simplify the AXLPArser Error
                    //alert(msgList[14] + "\n" + theReply);
                    alert("C: " + msgList[14]);
                } else {
                    //alert(msgList[14] + theError);
                    alert("B: " + msgList[14] + theReply);
                }
            }
            if (toolMode==20) {
               updateMeasureBox();
            }

            if (legendVisible) {
                   legendVisible = false;
                   showLegend();
            }

            // Added to automatically show the layer list...
            if (layersVisible) {
               parent.MapFrame.clickFunction('layerlist');
            }
            if (hasOVMap) {
                if (ovIsVisible) {
                // ask for the overview
                    if ((!pastStart) || (forceNewOVMap)) {

                        theText = writeOVXML();
                        //pastStart=true;
                        sendToServer(imsOVURL,theText,2);
                    } else {
                        putExtentOnOVMap();
                        hideRetrieveMap();
                    }
                } else {
                    if ((!pastStart) || (forceNewOVMap)) {
					//if (false) {
                        theText = writeOVXML();
                        sendToServer(imsOVURL,theText,2);
                    } else {
                        hideRetrieveMap();
                    }

                }
            } else {
                hideRetrieveMap();
            }
            if (aimsBufferPresent) {
                if (getBufferedData) {
                    var buffString = writeGetBufferedData();
                    // parent.Debugger.document.write ("aimsXML.processXML(1): selectionMode = " + selectionMode + "<br>");
                    if (buffString!="") {
                        sendToServer(imsQueryURL,buffString,11);
                    } else {
                        alert(msgList[15]);
                    }
                    getBufferedData=false;
                }
            }
            break

        case 2:
            // just put up an overview map
            var theURL = "";
            theURL = getURL(theReply);
            if (!pastStart) {
                getOVXYs(theReply);
                pastStart=true;

            }
            //alert(theURL);
            if (theURL != "") {
                ovImageVar.src = theURL;
            }
            else {

                if (debugOn>0) {
                    alert(msgList[16] + "\n" + theReply);
                } else {
                    alert(msgList[16] + theError);
                }

            }
            if (ovIsVisible) putExtentOnOVMap();
            hideRetrieveMap();

            break

        case 3:
//  just get full extent - service info
            //alert("processXML()[3]\n" + theReply);
            getDBLinkLayerIndex(theReply);
            if (getLimitExtent) {
                getXYs(theReply);
                fullLeft = eLeft;
                fullRight = eRight;
                fullTop = eTop;
                fullBottom = eBottom;
                fullOVLeft = eLeft;
                fullOVRight = eRight;
                fullOVTop = eTop;
                fullOVBottom = eBottom;
                limitLeft = eLeft;
                limitRight = eRight;
                limitTop = eTop;
                limitBottom = eBottom;
                //if ((hasOVMap) && (imsURL!=imsOVURL)) forceCommaInOV = forceCommaInRequest[activeMapServiceIndex];
                //if ((hasOVMap) && (imsURL==imsOVURL)) forceCommaInOV = true;
            } else {
                fullLeft = limitLeft;
                fullRight = limitRight;
                fullTop = limitTop;
                fullBottom = limitBottom;
                fullOVLeft = limitLeft;
                fullOVRight = limitRight;
                fullOVTop = limitTop;
                fullOVBottom = limitBottom;
            }

            fullWidth = Math.abs(fullRight - fullLeft);
            fullHeight = Math.abs(fullTop - fullBottom);
            fullOVWidth = Math.abs(fullOVRight - fullOVLeft);
            fullOVHeight = Math.abs(fullOVTop - fullOVBottom);
            theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_SERVICE_INFO />\n';
            theString += '</REQUEST>\n</ARCXML>';
            // get list of geocoding layers
            if((aimsGeocodePresent) && ((useGeocode) || (useReverseGeocode))) {
                theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_SERVICE_INFO  renderer="false" />\n';
                theString += '</REQUEST>\n</ARCXML>';
                sendToServer(imsGeocodeURL,theString,25);
            } else {
                theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_SERVICE_INFO  renderer="false" extensions="true" />\n';
                theString += '</REQUEST>\n</ARCXML>';
                sendToServer(imsURL,theString,4);
                useGeocode=false;
                useReverseGeocode=false;

            }

            break

        case 4:
            // get service info - extent, layers
            //alert("processXML()[4]\n" + theReply);
            forceCommaInRequest[activeMapServiceIndex] = false;
			processStartExtent(theReply);

            break

        case 5:
            // get a list of ImageServices
            //alert("processXML()[5]\n" + theReply);
            processCatalog(theReply);

            break

        case 6:
            // get select response - used for both "Select by Line/Polygon" and "Select by Box".
            displayDBDataFromMap(theReply, XMLMode);   // Moded by CAT 3.15.03
            // displayAttributeData(theReply);

            break

        case 7:
            // get identify response
            //alert(theReply);
            displayAttributeData(theReply);

            break

        case 8:
            // get query response
            //alert("processXML()[8]\nQuery XML Response:\n" + theReply);
            displayAttributeData(theReply);

            break

        case 9:
            // get geocode response
            processGeocode(theReply);

            break
        case 10:
            // get identifyall response
            doIdentifyAll(theReply);

            break
        case 11:
            // get buffer response
            displayDBDataFromMap(theReply, XMLMode);
            //getBufferAttributeData(theReply)
            break
        /*
        case 12:
            // get proximity response
            processProx(theReply);

            break

        case 13:
            // get route response
            processRoute(theReply);

            break
        */
        case 14:
            // get find response
            //alert(theReply);
            displayAttributeData(theReply);

            break

        case 15:
            // get hyperlink response
            parseHyperLink(theReply);

            break

        case 16:
            // get hyperlinkAny response
            parseHyperLinkAny(theReply);

            break

        case 20:
            // process startup query
            parseStartQuery(theReply);

            break

        case 25:
            // get geocoding layers
            parseGeocodeLayers(theReply);
            // get layers for display
            var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_SERVICE_INFO  renderer="false" extensions="true" />\n';
            theString += '</REQUEST>\n</ARCXML>';
            sendToServer(imsURL,theString,4);

            break

        case 26:
            // get geocoding layers
            if (parseGeocodeParams(theReply,GCLayers[GCActiveLayer])) {
                var theAddressForm = appDir + "addmatch.htm";
                if ((useExternalWindow) || (!useTextFrame)) {
                    var Win1 = window.open(theAddressForm,"GeocodeWindow","width=575,height=150,scrollbars=yes,resizable=yes");
                } else {
                    parent.TextFrame.document.location= theAddressForm;
                }
            } else {
                if (debugOn>0) {
                    alert(msgList[17] + "\n" + theReply);
                    if (parent.TextFrame!=null) parent.TextFrame.document.location= appDir + "blank.htm";
                } else {
                    alert(msgList[17]);
                    if (parent.TextFrame!=null) parent.TextFrame.document.location= appDir + "blank.htm";
                }
            }

            break

        case 27:
            // get geocoding results
            parseGeocodeResults(theReply);

            break
        case 40:
            // get list of sample field values
            parseFieldSamples(theReply);
            writeQueryForm();

            break
        case 55:
            // get layer storedqueries
            //alert("55\n" + theReply);
            parseStoredQueries(theReply);

            break

        case 70:
            // get layer field for submission to external db
            // displayAttributeData(theReply);
                parseIDFieldData(theReply);

            break

        case 98:
            // just put up a map with legend
            var theURL = "";
            theURL = getURL(theReply);
            if (theURL != "") {
                document.theImage.src = theURL;
            }
            //else {
            //  alert(theReply + "\nUnable to display Map image");
            //}

            if (legendVisible) {
                showLegend();
                drawLegendOnly=false;
            }
            hideRetrieveMap();

            break

        case 99:
            // just put up a map
            var theURL = "";
            legendVisible=legendTemp;
            theURL = getURL(theReply);
            if (theURL != "") {
                document.theImage.src = theURL;
            }
            else {
                //JB Edit to Simplify AXLParser Error Message
                //alert(msgList[14] + theReply);
                alert("A: " + msgList[14]);
            }
            hideRetrieveMap();

            break

        case 101:
            // print - get Map image
            printMapURL = getURL(theReply);
            printLegURL = getLegendURL(theReply);
            if (hasOVMap) {
                getPrintOV();
            } else {
                //writePrintPage();
                getPrintLegend();
            }

            break

        case 102:
            // print - get OV image
            printOVURL = getURL(theReply);
            legendImage = printLegURL
            getPrintLegend();

            break

        case 103:
            // print - get Legend image

            hideRetrieveMap();
            writePrintPage();
            break

       case abuttersXMLMode:
           showAbutterAbutter = true;
           processAbuttersXML(theReply);
            break

       case selectAddToList:
          var featureCount = justGetFeatureCount(theReply);
          if (featureCount > 0) {
             addIDsToSelectedList (parseGISLinkFields(theReply, featureCount));
             // Process another request for map data with the added features
          }
         break

       case selectRemoveFromList:
            var featureCount = justGetFeatureCount(theReply);
            break

        case 900:
            // just make a map
            var theURL = "";
            theURL = getURL(theReply);
            if (theURL != "") {
                getXYs(theReply);
                document.theImage.src = theURL;
            }

            break


        case 902:
            // just put up an overview map
            var theURL = "";
            theURL = getURL(theReply);
            //alert(theURL);
            if (theURL != "") {
                document.ovImage2.src = theURL;
            }
            var tempLeft = fullLeft;
            var tempRight = fullRight;
            var tempTop = fullTop;
            var tempBottom = fullBottom;
            getOVXYs(theReply);
            fullLeft = tempLeft;
            fullRight = tempRight;
            fullTop = tempTop;
            fullBottom = tempBottom;

            break

        case 998:
            // receive serviceinfo for overview map to check decimal delimiter

            var tempLeft = limitLeft;
            var tempRight = limitRight;
            var tempTop = limitTop;
            var tempBottom = limitBottom;
            getOVXYs(theReply);
            limitLeft = tempLeft;
            limitRight = tempRight;
            limitTop = tempTop;
            limitBottom = tempBottom;
            var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_SERVICE_INFO renderer="false" extensions="false" fields="false" />\n';
            theString = theString + '</REQUEST>\n</ARCXML>';
            sendToServer(imsURL,theString,3);


            break
        case 999:
            // get a blank map to get modified limit extents according image proportions
            var tempLeft = eLeft;
            var tempRight = eRight;
            var tempTop = eTop;
            var tempBottom = eBottom;
            getXYs(theReply);
            imageLimitLeft=eLeft;
            imageLimitRight=eRight;
            imageLimitTop=eTop
            imageLimitBottom=eBottom;
            eLeft = tempLeft;
            eRight = tempRight;
            eTop = tempTop;
            eBottom = tempBottom;
            layersVisible = true;
            if ((aimsQueryPresent) && (highlightedOne!="") && (queryZoom)) {
                setStartQuery();
            } else {
                sendMapXML();
            }

            break

        default:
            // send any responses to custom requests off to the custom handler
                // XMLMode >= 1000 are reserved for custom requests/responses
            if (XMLMode >= 1000) {
                useCustomFunction(theReply);
            } else {
                alert(theReply + msgList[19]);
            }

        }
    //}


}

// write out a blank map. . . to get image extents from limit extents
function writeBlankMapXML() {
    var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_IMAGE>\n<PROPERTIES>\n<ENVELOPE minx="' + forceComma(limitLeft) + '" miny="' + forceComma(limitBottom) + '" maxx="' + forceComma(limitRight) + '" maxy="' + forceComma(limitTop) + '" />\n';
    theString += '<IMAGESIZE height="' + iHeight + '" width="' + iWidth + '" />\n';
    var visString = "";
    // tell the server which layers are to be visible
    if (aimsLayersPresent) {
        theString += '<LAYERLIST >\n';
        for (var i=0;i<layerCount;i++) {
            theString += '<LAYERDEF name="' + LayerName[i] + '" visible="false" />\n';
        }
        theString += '</LAYERLIST>\n';
    }
    theString += '</PROPERTIES>\n';
    theString += '</GET_IMAGE>\n</REQUEST>\n</ARCXML>';
    //sendToServer(imsURL,theString,999);            //cdm
	
	if (!pastStart) { //concord
	layersVisible=true;		//concord		
	pastStart=true;        //concord	 
	}
	sendMapXML();     // concord
}

// prepare the request in xml format for Main Map
function writeXML() {
    if (buffpresent) {
        buffpresent=false;
        calcSelectEnvelope();
        saveLastExtent();

        //var minx_ = selMaxEnvelope[0] - (parseInt(bufferDistance)+200);
        //var miny_ = selMaxEnvelope[1] - (parseInt(bufferDistance)+200);
        //var maxx_ = selMaxEnvelope[2] - (0-(parseInt(bufferDistance)+200));
        //var maxy_ = selMaxEnvelope[3] - (0-(parseInt(bufferDistance)+200));

        var minx_ = forceComma(eLeft) - bufferDistance;
        var miny_ = forceComma(eBottom) - bufferDistance;
        var maxx_ = forceComma(eRight) - (0-bufferDistance);
        var maxy_ = forceComma(eTop) - (0-bufferDistance);

        //alert(minx_ + "=" + forceComma(eLeft) +"-"+ (parseInt(bufferDistance)+200));
        var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_IMAGE>\n<PROPERTIES>\n<ENVELOPE minx="' + minx_ + '" miny="' + miny_ + '" maxx="' + maxx_ + '" maxy="' + maxy_ + '" />\n';
        //var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_IMAGE>\n<PROPERTIES>\n<ENVELOPE minx="' + forceComma(eLeft) + '" miny="' + forceComma(eBottom) + '" maxx="' + forceComma(eRight) + '" maxy="' + forceComma(eTop) + '" />\n';

    } else {
        var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_IMAGE>\n<PROPERTIES>\n<ENVELOPE minx="' + forceComma(eLeft) + '" miny="' + forceComma(eBottom) + '" maxx="' + forceComma(eRight) + '" maxy="' + forceComma(eTop) + '" />\n';
    }
    theString += '<IMAGESIZE height="' + iHeight + '" width="' + iWidth + '" />\n';
        var visString = "";
    if (aimsLayersPresent) {

        // tell the server which layers are to be visible
        if (toggleVisible) {
            theString += '<LAYERLIST >\n';
            for (var i=0;i<layerCount;i++) {
                if (LayerVisible[i]==1) {
                    theString += '<LAYERDEF id="' + LayerID[i] + '" visible="true" ';
                    if (aimsClassRenderPresent) {
                        theString += addSpecialRenderToMap(i);
                    } else {
                        theString += '/>\n';
                    }

                }
                else {
                    theString += '<LAYERDEF id="' + LayerID[i] + '" visible="false" />\n';
                }

            }
            theString += '</LAYERLIST>\n';
        }
    }

    // map background color
    if (mapTransparent) {
        theString += '<BACKGROUND color="255,255,254" transcolor="255,255,254" />\n';
    } else {
        if (mapBackColor!="") {
            theString += '<BACKGROUND color="' + mapBackColor + '" />\n\n';
        }
    }

    if (aimsLegendPresent) {
        // create a legend image
        if (legendVisible) theString += addLegendToMap();
    }

    theString += '</PROPERTIES>\n';

    // buffer
    if (aimsBufferPresent) {
        if (showBuffer) theString += addBufferToMap();
    }

   var rExp1 = /</g;
   var rExp2 = />/g;
   //parent.Debugger.document.write ("<br>" + theString.replace(rExp1, "[").replace(rExp2, "]"));

    // select
    if (aimsSelectPresent) {
        theString += addSelectToMap();
    }

    // any custom stuff to fit here
    if (aimsCustomPresent) theString += addCustomToMap1();

    if (aimsClickPresent){
        // clickpoints
        if (clickCount>0) {
            // draw click points and lines between them on map
            var clickColor = selectColor;
            if (clickType==1) clickColor = clickMarkerColor;
            theString += '<LAYER type="acetate" name="allTheClicks">\n';
            if (clickCount>1) {
                theString += '<OBJECT units="database">\n<LINE coords="' + forceComma(clickPointX[0]) + coordsDelimiter + forceComma(clickPointY[0]);
                for (var i=1;i<clickCount;i++) {
                    theString += pairsDelimiter  + forceComma(clickPointX[i]) + coordsDelimiter + forceComma(clickPointY[i]);
                }
                theString += '" >\n';
                theString += '<SIMPLELINESYMBOL type="solid" color="' + clickMarkerColor;
                theString += '" width="3" />\n</LINE>\n</OBJECT>\n';
                theString += '<OBJECT units="database">\n<LINE coords="' + forceComma(clickPointX[0]) + coordsDelimiter + forceComma(clickPointY[0]);
                for (var i=1;i<clickCount;i++) {
                    theString += pairsDelimiter  + forceComma(clickPointX[i]) + coordsDelimiter + forceComma(clickPointY[i]);
                }
                theString += '" >\n';
                theString += '<SIMPLELINESYMBOL type="solid" color="255,255,255" width="1" />\n</LINE>\n</OBJECT>\n';
            }
            for (var i=0;i<clickCount;i++) {
                theString += '<OBJECT units="database">\n<POINT coords="' + forceComma(clickPointX[i]) + coordsDelimiter + forceComma(clickPointY[i]) + '">\n';
                theString += '<SIMPLEMARKERSYMBOL  type="' + clickMarkerType + '"';
                theString += ' color="' + clickMarkerColor + '" width="' + clickMarkerSize + '" />\n</POINT>\n</OBJECT>\n';
            }
            theString += '</LAYER>\n';
        }
    }

    // geocoding or point with label
    if (showGeocode) {
        // draw the point . . . also used to display any point with a label on map
        theString += '<LAYER type="acetate" name="GeoCode1">\n';
        theString += '<OBJECT units="database">\n<POINT coords="' + forceComma(geocodeX) + coordsDelimiter + forceComma(geocodeY) + '">\n';
        theString += '<SIMPLEMARKERSYMBOL  type="circle"  color="' + geocodePointColor + '" width="' + geocodePointSize +'" overlap="false" />\n</POINT></OBJECT>\n';
        if (geocodeLabel!="") {
            theString += '<OBJECT units="database">\n<TEXT coords="' + forceComma(geocodeX) + coordsDelimiter + forceComma(geocodeY) + '" label="' + geocodeLabel + '">\n';
            theString += '<TEXTMARKERSYMBOL fontcolor="' + geocodePointColor + '" fontsize="12" shadow="64,64,64" glowing="255,255,0" halignment="right" valignment="top" overlap="false" /></TEXT></OBJECT>\n';
        }
        theString += '</LAYER>\n';

    }

    // any custom stuff to fit here
    if (aimsCustomPresent) theString += addCustomToMap2();

    if (drawCopyright) {
        // draw text on the map
        theString += '<LAYER type="acetate" name="theCopyright">\n';
        theString += '<OBJECT units="pixel">\n<TEXT coords="' + CopyrightCoords + '" label="' + CopyrightText + '">\n';
        theString += '<TEXTMARKERSYMBOL fontstyle="' + CopyrightStyle + '" fontsize="' + CopyrightSize + '" ';
        theString += 'font="' + CopyrightFont + '" fontcolor="' + CopyrightColor + '" antialiasing="True" ';
        //if (CopyrightBackground.toUpperCase()=="TRUE") theString += 'background="' + CopyrightBackground + '" backcolor="' + CopyrightBGColor + '" ';
        if (CopyrightBackground.toUpperCase()=="TRUE") theString += 'blockout="' + CopyrightBGColor + '" ';
        theString += 'shadow="32,32,32" overlap="false" ';
        if (CopyrightGlow.toUpperCase()=="TRUE") theString += ' glowing="' + CopyrightGlowColor + '" ';
        theString += '/>\n</TEXT>\n</OBJECT>\n';
        theString += '</LAYER>\n';
    }
    if (drawNorthArrow) {
        // draw a north arrow
        theString += '<LAYER type="acetate" name="theNorthArrow">\n';
        theString += '<OBJECT units="pixel">\n<NORTHARROW type="' + NorthArrowType + '" size="' + NorthArrowSize + '" coords="' + NorthArrowCoords + '" shadow="32,32,32" ';
        theString += 'angle="' + NorthArrowAngle + '" antialiasing="True" overlap="False" />\n</OBJECT>\n';
        theString += '</LAYER>\n';
    }
    if (drawScaleBar) {
        // draw a scale bar
        theString += '<LAYER type="acetate" name="theScaleBar">\n';
        xDistance = eRight - eLeft;
        theString += '<OBJECT units="pixel">\n';
        theString += '<SCALEBAR coords="' + parseInt(iWidth * (6/10)) + coordsDelimiter + '2" ';
        if (MapUnits=="DEGREES") theString += 'mode="geodesic" ';

        theString += 'outline="' + ScaleBarBackColor + '" ';
        theString += 'font="' + ScaleBarFont + '" fontcolor="' + ScaleBarFontColor + '" style="' + ScaleBarStyle + '" barcolor="' + ScaleBarColor + '" ';
        if (MapUnits!="DEGREES") {
            theString += 'mapunits="' + MapUnits.toLowerCase() + '" ';
        }
        theString += 'scaleunits="' + ScaleBarUnits.toLowerCase() + '" antialiasing="True" ';
        var sDistance = getScaleBarDistance();
        if (MapUnits=="DEGREES") {
            if (xDistance<1/10){
                theString += 'precision="' + ScaleBarPrecision + '" ';
            }
        } else if (sDistance<5) {
            theString += 'precision="' + ScaleBarPrecision + '" ';
        }
        theString += 'screenlength="' + parseInt(iWidth * (2/10)) + '" ';
        theString += 'fontsize="' + ScaleBarSize + '" barwidth="' + ScaleBarWidth + '" overlap="False"  ';
        theString += '/>\n</OBJECT>\n';
        theString += '</LAYER>\n';

    }

    // any custom stuff to fit here
    if (aimsCustomPresent) theString += addCustomToMap3();

    if (drawModeOnMap) {
        // draw the current mode on the map
        theString += '<LAYER type="acetate" name="theMode">\n';
        theString += '<OBJECT units="pixel">\n<TEXT coords="5' + coordsDelimiter + (iHeight-10) + '" label="' + modeBlurb + '">\n';
        theString += '<TEXTMARKERSYMBOL fontstyle="BOLD" fontsize="12" font="ARIAL" fontcolor="' + modeMapColor + '" ';
        theString += 'threed="TRUE" glowing="' + modeMapGlow + '" overlap="false" />\n</TEXT>\n</OBJECT>';

    }

    // any custom stuff to be drawn on top of everything
    if (aimsCustomPresent) theString += addCustomToMap4();

    theString += '</GET_IMAGE>\n</REQUEST>\n</ARCXML>';
    // alert(theString);
    return theString;
}

// prepare the request in xml format for overview map
function writeOVXML() {
    var extentRatio = xDistance/fullWidth;
    var midX = eLeft + xHalf;
    var midY = eBottom + yHalf;
    var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_IMAGE><PROPERTIES>\n';
    theString += '<ENVELOPE minx="' + forceOVComma(fullOVLeft) + '" miny="' + forceOVComma(fullOVBottom) + '" maxx="' + forceOVComma(fullOVRight) + '" maxy="' + forceOVComma(fullOVTop) + '" />\n';
    theString += '<IMAGESIZE height="' + i2Height + '" width="' + i2Width + '" />\n';
    if ((toggleOVVisible) && (imsURL==imsOVURL)) {
        theString += '<LAYERLIST >\n';
        for (var i=0;i<layerCount;i++) {
            if (LayerVisible[i]==1) {
                visString = "true";
            }
            else {
                visString = "false";
            }
            theString += '<LAYERDEF name="' + LayerName[i] + '" visible="' + visString + '" />\n';

        }
        theString += '</LAYERLIST>\n';
    }
    if (mapBackColor!="") {
        theString += '<BACKGROUND color="' + mapBackColor + '" />\n';
    }

    theString += '</PROPERTIES>\n';
    if (drawOVExtentBox) {
        theString += '<LAYER type="acetate" name="ACETATE">\n';
        if (extentRatio<(1/100)) {
            theString += '<OBJECT units="database">\n<POINT coord="' + forceOVComma(midX) + coordsDelimiter + forceOVComma(midY) + '">\n';
            theString += '<SIMPLEMARKERSYMBOL  type="Square" color="' + ovBoxColor + '" width="4" />\n</POINT></OBJECT>\n';
        } else {
            theString += '<OBJECT units="database">\n<LINE coords="' + forceOVComma(eLeft) + coordsDelimiter + forceOVComma(eBottom) + pairsDelimiter + forceOVComma(eLeft) + coordsDelimiter + forceOVComma(eTop) + pairsDelimiter;
            theString += forceOVComma(eRight) + coordsDelimiter + forceOVComma(eTop) + pairsDelimiter + forceOVComma(eRight) + coordsDelimiter + forceOVComma(eBottom) + pairsDelimiter + forceOVComma(eLeft) + coordsDelimiter + forceOVComma(eBottom) + '">\n';
            theString += '<SIMPLELINESYMBOL type="solid" color="' + ovBoxColor + '" width="3" />\n</LINE></OBJECT>\n';
        }
        theString += '</LAYER>\n';
    }
    theString += '</GET_IMAGE>\n</REQUEST>\n</ARCXML>';
    //alert(theString);
    return theString;
}

// get the map extents from xml reply
function getXYs(theString) {
    var tempStr = "";
    var smallStr = "";
    var startpos = 0;
    var endpos = 0;
    var theReply = theString
    var theXYs =  getEnvelopeXYs(theString, 0)
    eLeft = theXYs[0];
    eBottom = theXYs[1];
    eRight = theXYs[2];
    eTop = theXYs[3];
    xDistance = Math.abs(eRight-eLeft);
    yDistance = Math.abs(eTop-eBottom);
    xHalf = xDistance / 2;
    yHalf = yDistance / 2;
    panX = xDistance * panFactor;
    panY = yDistance * panFactor;
    var sFactor = xDistance / iWidth
    if (aimsLayersPresent) {
        if (sFactor!=mapScaleFactor) {
            mapScaleFactor = sFactor;
            try {
               if ((hasTOC) && (!legendVisible)) parent.TOCFrame.document.location = appDir + "toc.asp?tt=layers";
            } catch (eMiss) {
               // CAT - we are not catching anything.. alert ('Error is here');
            }
            if (aimsLayersPresent) {
                if (LayerListOpen) writeLayerListForm();
            }

        }
    }
}

/*
   Function to dynamically determine the dbLinkLayerID and dbLinkLayerIndex
   which were statically identified in aimsDB.js - this counts on knowing
   the value of the dbLinkLayer - which should be set in the aimsDB.js
   The dbLinkLayer is the NAME attribute of the layer that has the link to
   the database.  for now this is a parcel layer, but it could be any layer that
   we want to link to.
   */
function getDBLinkLayerIndex(theString) {
        var layerInfoNode = "<LAYERINFO";
        var layerInfoPos = theString.indexOf(layerInfoNode);
        var idPos = 0;
        var namePos = 0;
        var idQuotePos = 0;
        var nameQuotePos = 0;
        var nameValue = "";
        var idValue = "";
        var layerIndex = 0;
        var totalLayerCount = 0;
        while (layerInfoPos > 0) {
            totalLayerCount ++;
            idPos = theString.indexOf("id=", layerInfoPos);
            namePos = theString.indexOf("name=", layerInfoPos);
            idQuotePos = theString.indexOf("\"", idPos+4);
            idValue = theString.substring(idPos + 4, idQuotePos);
            nameQuotePos = theString.indexOf("\"", namePos+6);
            nameValue = theString.substring(namePos+6, nameQuotePos);
            if (nameValue == dbLinkLayer) {
                layerIndex = totalLayerCount;
                dbLinkLayerID = idValue;
            }
            layerInfoPos = theString.indexOf(layerInfoNode, layerInfoPos + 1);
        }
        dbLinkLayerIndex = (parseInt(totalLayerCount) - parseInt(layerIndex));
        ActiveLayerIndex = dbLinkLayerIndex;
}

// get the map extents from xml reply
function getOVXYs(theString) {
    var tempStr = "";
    var smallStr = "";
    var startpos = 0;
    var endpos = 0;
    var tempComma = forceCommaInRequest[activeMapServiceIndex];
    var theXYs =  getEnvelopeXYs(theString, 0)
    forceCommaInOV = forceCommaInRequest[activeMapServiceIndex];
    forceCommaInRequest[activeMapServiceIndex] = tempComma;
    fullOVLeft = theXYs[0];
    fullOVBottom = theXYs[1];
    fullOVRight = theXYs[2];
    fullOVTop = theXYs[3];
    fullOVWidth = Math.abs(fullOVRight - fullOVLeft);
    fullOVHeight = Math.abs(fullOVTop - fullOVBottom);
    //alert("Left:" + fullLeft + "\nTop:" + fullTop + "\nRight:" + fullRight + "\nBottom:" + fullBottom);
}

// get URL
function getURL(theReply) {
    var theURL = "";
    var startpos = 0;
    var endpos = 0;

    var pos = theReply.indexOf("OUTPUT");
    if (pos != -1) {
        theURL = getInsideString(theReply,'url="',dQuote,pos,0,false);
    }
    legendImage = getLegendURL(theReply);
    return theURL;

}


// getLegendURL
function getLegendURL(theReply) {
    var theURL = "";
    var startpos = 0;
    var endpos = 0;
    var pos = theReply.indexOf("LEGEND");
    //alert(pos);
    if (pos != -1) {
        theURL = getInsideString(theReply,'url="',dQuote,pos,0,false);
    }
    //alert("Legend:" + theURL);
    return theURL;

}

// just make a map with URL and  extent
function justGetMap(theURL, extentLeft, extentTop, extentRight, extentBottom, getOVMap) {
    var mode = 900;
    if (getOVMap) mode = 1;
    if (extentLeft!="") eLeft = extentLeft;
    if (extentTop!="") eTop = extentTop
    if (extentRight!="") eRight = extentRight;
    if (extentBottom!="") eBottom = extentBottom;
    var theText = writeXML();
    if (debugOn==2) alert(msgList[12] + theText);
    sendToServer(theURL,theText,mode);

}

// get min and max x,y's from xml stream . . . return an array with values
function getEnvelopeXYs(theString, startpos) {
    var theEnvelope = new Array();

    //forceCommaInRequest[activeMapServiceIndex] = false;
    theString = theString.toUpperCase();
    var tempString = "";
    var pos = theString.indexOf("ENVELOPE",startpos);
    if (pos!=-1) {
        pos = pos + 8;
        startpos = theString.indexOf("MINX=",pos);
        startpos += 6;
        var endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        theEnvelope[0] = parseFloat(setDecimalString(tempString));
        startpos = theString.indexOf("MINY=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        theEnvelope[1] = parseFloat(setDecimalString(tempString));
        startpos = theString.indexOf("MAXX=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        theEnvelope[2] = parseFloat(setDecimalString(tempString));
        startpos = theString.indexOf("MAXY=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        theEnvelope[3] = parseFloat(setDecimalString(tempString));
        xmlEndPos = endpos;
    }
    return theEnvelope;

}

// 2003-02-27: bunsongsikult@cdm.com
// get the extreme min and max x,y's of all selected features (based on maxfeaturecount)
// from xml stream . . . return an array with values
function getFullEnvelopeXYs(theString, startpos) {

    var theEnvelope = new Array();
    //forceCommaInRequest[activeMapServiceIndex] = false;

    theString = theString.toUpperCase();
    var tempString = "";

    //  get the initial envelope of the first feature
    var pos = theString.indexOf("ENVELOPE",startpos);
    if (pos!=-1) {
        pos = pos + 8;
        startpos = theString.indexOf("MINX=",pos);
        startpos += 6;
        var endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        tmpMinX = parseFloat(setDecimalString(tempString));
        startpos = theString.indexOf("MINY=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        tmpMinY = parseFloat(setDecimalString(tempString));
        startpos = theString.indexOf("MAXX=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        tmpMaxX = parseFloat(setDecimalString(tempString));
        startpos = theString.indexOf("MAXY=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        tmpMaxY = parseFloat(setDecimalString(tempString));
        xmlEndPos = endpos;
    }

    var pos = theString.indexOf("ENVELOPE",startpos);
    var maxpos = theString.length;
    if (pos!=-1) {
      while ((pos < maxpos) && (pos > 0)) {
        pos = pos + 8;
        startpos = theString.indexOf("MINX=",pos);
        startpos += 6;
        var endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        theEnvelope[0] = parseFloat(setDecimalString(tempString));
        if (theEnvelope[0] >= tmpMinX) {
          theEnvelope[0] = tmpMinX;   }
        else {
          tmpMinX = theEnvelope[0];   }
        startpos = theString.indexOf("MINY=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        theEnvelope[1] = parseFloat(setDecimalString(tempString));
        if (theEnvelope[1] >= tmpMinY) {
          theEnvelope[1] = tmpMinY;    }
        else {
          tmpMinY = theEnvelope[1];    }
        startpos = theString.indexOf("MAXX=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        theEnvelope[2] = parseFloat(setDecimalString(tempString));
        if (theEnvelope[2] <= tmpMaxX) {
          theEnvelope[2] = tmpMaxX;    }
        else {
          tmpMaxX = theEnvelope[2];    }
        startpos = theString.indexOf("MAXY=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        tempString = theString.substring(startpos,endpos);
        theEnvelope[3] = parseFloat(setDecimalString(tempString));
        if (theEnvelope[3] <= tmpMaxY) {
          theEnvelope[3] = tmpMaxY;    }
        else {
          tmpMaxY = theEnvelope[3];    }
        xmlEndPos = endpos;
        pos = theString.indexOf("ENVELOPE",endpos);
      }
    }
    return theEnvelope;

}

// set number string to have decimal character to match browser language type - point or comma
function setDecimalString(numberString) {
    if (numberString.indexOf(",")!=-1) forceCommaInRequest[activeMapServiceIndex] = true;
    if (decimalChar==".") {
        numberString = numberString.replace(/,/g, ".");
    } else {
        numberString = numberString.replace(/./g, ",");
    }
    return numberString;
}

function forceComma(theNumber) {
    var comma = ",";
    var dot = ".";
    var charOut = comma;
    var charIn = dot;
    var numberString = new String(theNumber);
    if (forceCommaInRequest[activeMapServiceIndex]) {
        charOut = dot;
        charIn = comma;
    }
    var pos = numberString.indexOf(charOut);
    if (pos!=-1) {
        var begin = numberString.substring(0,pos);
        var ending = numberString.substring(pos+1, numberString.length);
        numberString = begin + charIn + ending;
    }
    return numberString;
}
function forceOVComma(theNumber) {
    var comma = ",";
    var dot = ".";
    var charOut = comma;
    var charIn = dot;
    var numberString = new String(theNumber);
    if (forceCommaInOV) {
        charOut = dot;
        charIn = comma;
    }
    var pos = numberString.indexOf(charOut);
    if (pos!=-1) {
        var begin = numberString.substring(0,pos);
        var ending = numberString.substring(pos+1, numberString.length);
        numberString = begin + charIn + ending;
    }
    return numberString;
}

// check if there is an error message in the response
function getXMLErrorMessage(theString) {
    var pos1 = 0;
    var pos2 = 0;
    var pos3 = 0;
    var theError = "";
    pos3 = theString.indexOf("<ERROR");
    if (pos3!=-1) {
        pos1 = theString.indexOf(">",pos3);
        pos1 += 1;
        pos2 = theString.indexOf("</ERROR");
        theError = theString.substring(pos1,pos2)
    }
    return theError;

}

// check if theURL has different host from theHost
function isNotSameHostInURL(theURL, theHost) {
    var startpos = theURL.indexOf("//");
    if (startpos==-1) {
        startpos = 0;
    } else {
        startpos = startpos + 2;
    }
    var endpos = theURL.indexOf("/",startpos);
    if (endpos==-1) endpos = theURL.length;
    var thisHost = theURL.substring(startpos,endpos);
    if (thisHost==theHost) {
        return false;
    } else {
        return true;
    }
}



