/*
    $Revision$
    $Id$

    ToonIMG.js

*/
var defaultScale=0.95;
var step=2.0;
var defaultIMG = "./Slnk2Img.asp";

var gIMGGenerator;
var gIMGKeyToSymbol;
var gPlanDWF;
var gPage;

var gCustomParameters;

var _gPaperColor;
var _gpaperWidth; // mm
var _gpaperHeight; // mm
var _gLabelPos;
var _gbPending; // Performance voor snel in/uitzoomen
var _gbNextQry;
var _gStyleSheet; // Voor printen

var qryWhat,qryFind;
var imgX, imgY; // Size

var dScale, currentX, currentY; // Pan & Zoom
var bmScale, bmCurrX, bmCurrY; // actual bitmap size
var basicTop, basicLeft; // without panning. Helps dragging while pending zoom

var PanMode=1; // 0=Pan, 1=Point/Identify, 2=ZoomIn, 3=ZoomOut
var rubberingBusy;
var rubberOrgX, rubberOrgY;
var draggingBusy;
var _ddReason; // DragAndDrop reason ONMOVE, ONROTATE, ONCOPY of DRAGANDDROP
var dragAndDroppingBusy = false;
var KeyDropBusy=false;
var gSLNKEvent;

var dragStartX, dragStartY;
var ignoreNextClick = false; // Voorkom onClick event na draggen
var ignoreNextMove = false; // Voorkom onMouseMove event na click

var _noAutoResize = false; // Geen resize als grootte veranderd.
var _sequence = 0; // anti/caching

panning=false;
gesturing=false;
function _onTouchStart(e)
{
  if(e.touches.length == 1) // Eerste vinger
  {
    var touch0 = e.touches[0]; // Get the information for finger #1
    firstMouseX = touch0.clientX;
    firstMouseY = touch0.clientY;
  }
  if(e.touches.length == 2) // Tweede vinger
  {
    panning = false;
    gesturing=true;
    var touch0 = e.touches[0]; // Get the information for finger #1
    var touch1 = e.touches[1]; // Get the information for finger #2
    firstMouseX = (touch0.clientX + touch1.clientX)/2;
    firstMouseY = (touch0.clientY + touch1.clientY)/2;
  }
}
function _onTouchMove(e)
{
  if(e.touches.length == 1) // Panmode
  {
    panning = true;
    e.preventDefault();
    var touch0 = e.touches[0]; // Get the information for finger #1
    lastMouseX = touch0.clientX;
    lastMouseY = touch0.clientY;
    var basicLeft = lastMouseX - firstMouseX;
    var basicTop = lastMouseY - firstMouseY;
    elemIMG.style.left = basicLeft + "px";
    elemIMG.style.top  = basicTop + "px";
  }
  if(e.touches.length == 2) // Tweede vinger
  {
    var touch0 = e.touches[0]; // Get the information for finger #1
    var touch1 = e.touches[1]; // Get the information for finger #2
    lastMouseX = (touch0.clientX + touch1.clientX)/2
    lastMouseY = (touch0.clientY + touch1.clientY)/2
  }
}

function _onTouchEnd(e)
{
  if(e.touches.length == 0 && panning) // niet gesture gedaan
  {
    currentX = lastMouseX + (currentX - firstMouseX);
    currentY = lastMouseY + (currentY - firstMouseY);
    _refresh(true);
    panning=false;
  }
}

function _onGestureStart(e)
{
  e.preventDefault();
}

function _onGestureChange(e)
{
    elemIMG.style.width  = imgX * e.scale + "px";
    elemIMG.style.height = imgY * e.scale + "px";
    var basicLeft = lastMouseX - firstMouseX * e.scale;
    var basicTop = lastMouseY - firstMouseY * e.scale;
    elemIMG.style.left = basicLeft + "px";
    elemIMG.style.top  = basicTop + "px";
}

function _onGestureEnd(e)
{
    currentX = lastMouseX + (currentX - firstMouseX)*e.scale;
    currentY = lastMouseY + (currentY - firstMouseY)*e.scale;
    dScale = dScale * e.scale;
    gesturing=false;

    _refresh(true);
}

/************************************************************\
* Onetime initialisations
\************************************************************/
function Init()
{
    elemIMG = document.getElementById("Eview");

    //elemIMG.src = "waiting.png";
    $("#Eview,#SystemMap")
              .on("load",             _onLoad)
              .on("mousewheel",       _onMouseWheel)
              .on("DOMMouseScroll",   _onMouseWheel) // FireFox
              .on("click",            _onClick)
              .on("contextmenu",      _oncontextmenu)
              .on("readystatechange", _readystatechange)
              .on("dblclick",         _onDblClick)
              .on("dragstart",        false)
              .on("mouseenter",       function () { if(parent.document.hasFocus()) this.parentElement.focus(); })
              .on("mousedown",        _onMouseDown)
              .on("mousemove",        _onMouseMove)
              .on("mouseup",          _onMouseUp);

    if (window.addEventListener) // FireFox
    {
        SysMap = document.getElementById("SystemMap");
        elemIMG.addEventListener('touchstart',    function(e) { return _onTouchStart(e)   });
        elemIMG.addEventListener('touchmove',     function(e) { return _onTouchMove(e)    });
        elemIMG.addEventListener('touchend',      function(e) { return _onTouchEnd(e)     });
        elemIMG.addEventListener('gesturestart',  function(e) { return _onGestureStart(e) });
        elemIMG.addEventListener('gesturechange', function(e) { return _onGestureChange(e)});
        elemIMG.addEventListener('gestureend',    function(e) { return _onGestureEnd(e)   });

        SysMap.addEventListener ('touchstart',    function(e) { return _onTouchStart(e)   });
        SysMap.addEventListener ('touchmove',     function(e) { return _onTouchMove(e)    });
        SysMap.addEventListener ('touchend',      function(e) { return _onTouchEnd(e)     });
        SysMap.addEventListener ('gesturestart',  function(e) { return _onGestureStart(e) });
        SysMap.addEventListener ('gesturechange', function(e) { return _onGestureChange(e)});
        SysMap.addEventListener ('gestureend',    function(e) { return _onGestureEnd(e)   });
    }
}

/************************************************************\
*
\************************************************************/
function Reset(keepZoom)
{
    elemIMG = document.getElementById("Eview");

    SetIMGGenerator();
    gPlanDWF      = "";
    gPage         = 0;

    gCustomParameters = "";
    _gPaperColor  = -1;
    _gpaperWidth = 165; // A4 portrait
    _gpaperHeight = 260;
    _gStyleSheet = null;

    bmScale = -1;
    basicLeft = basicTop = 0;
    _gbPending=false;
    _gbNextQry="";

    _gLabelPos    = 1; // Default
    gSLNKEvent    = null;

    qryWhat="";
    imgX = $(window).width();
    imgY = $(window).height();
    _invalidateMap();

    if (!keepZoom || typeof keepZoom=='undefined')
    {
        dScale=defaultScale;
        currentX = (imgX/2) - (imgX/2)*dScale;
        currentY = (imgY/2) - (imgY/2)*dScale;
        _doPreview();
    }

    _resetRubber()
    draggingBusy=false;
    dragAndDroppingBusy = false;
    KeyDropBusy=false;

    PanMode=1; // Point
}

/************************************************************\
* Toon een eigen tekst als PNG
\************************************************************/
function SetText(message)
{
    qry2 = "./Slnk2Img.asp?sizeX="+imgX + "&sizeY="+imgY
               + "&txtAsPNG="+escape(message);
    elemIMG.hasMap = false;
    elemIMG.src = qry2;
}

/************************************************************\
*
\************************************************************/
function SetDWF(planDWF)
{
    gPlanDWF = planDWF;
}

/************************************************************\
*
\************************************************************/
function SetPage(page)
{
    gPage = page;
}

/************************************************************\
* Set custom asp to generate images
* Often used together with SetCustomParameters
\************************************************************/
function SetIMGGenerator(imgGen, fn_callback)
{
    if (typeof(imgGen) != "undefined")
    {
        gIMGGenerator = imgGen;
        gCallback = fn_callback;
    }
    else
        gIMGGenerator = defaultIMG; // "./Slnk2Img.asp"

    _updateWhat();
}

/************************************************************\
* Set custom asp to translate Symbolkey into symbolname
\************************************************************/
function SetKeyToSymbol(imgKeyToSymbol)
{
    if (typeof imgKeyToSymbol  != "undefined")
        gIMGKeyToSymbol = imgKeyToSymbol;
    else
        gIMGKeyToSymbol = null;
}

function cssclrhex(num)
{
    var s = "00000"+num.toString(16);
    return "#"+s.substring(s.length-6);
}

/************************************************************\
*
\************************************************************/
function SetPaperColor(paperColor)
{
    document.body.style.backgroundColor = cssclrhex(paperColor); // zie je bij uitzoomen

    _gPaperColor = paperColor;
}

/************************************************************\
*
\************************************************************/
function SetStyleSheet(styleSheet)
{
    _gStyleSheet = styleSheet;
}
/************************************************************\
*
\************************************************************/
function SetLabelPosition(labelPos)
{
    _gLabelPos = labelPos;
}
/************************************************************\
* Set paper print width and height in mm
* Note: we do not set landscape print mode automatically!
\************************************************************/
function SetPaperSize(paperWidth, paperHeight)
{
    _gpaperWidth = paperWidth;
    _gpaperHeight = paperHeight;
}
/************************************************************\
*
\************************************************************/
function SetCustomParameters(custParams)
{
    gCustomParameters = custParams;
    _updateWhat();
}

function GetCustomParameters()
{
    return gCustomParameters;
}

function _updateWhat()
{
    qryWhat = gIMGGenerator + "?labelPos=" + _gLabelPos
                       + (gPlanDWF?"&dwfFile="+escape(gPlanDWF):"")
                       + (gPage?"&page="+gPage:"")
                    + gCustomParameters;
}

// Er kan van alles veranderd zijn door de aanroeper.
/************************************************************\
*
\************************************************************/
function Refresh(bZoomExtents, force)
{
    if (force)
        _sequence ++;
    _resetRubber();
    _PickOff();
    elemIMG.title = ""; // alert wissen
    // Overrule eventuele pending
    _gbPending=false;
    _gbNextQry="";
    timerID=null;

    // Oke, nu verder met de echte (nieuwe) grootte
    imgX = $(window).width();
    imgY = $(window).height();

    // Basis query zonder zoom/pan informatie
    _updateWhat();

    qryFind = gIMGGenerator
                       + "?AsFND=1"
                       + (gPlanDWF?"&dwfFile="+escape(gPlanDWF):"")
                       + (gPage?"&page="+gPage:"")
                       + "&labelPos=" + _gLabelPos
                       + gCustomParameters;
    if (bZoomExtents)
        ZoomExtents()
    else // gewone refresh
        _refresh(false); // Zoom not changed
}

/************************************************************\
* Refresh na resize
* Indirect, anders een refresh voor elke pixel groter
* ZoomExtents omdat we toch niet goed zoom/pan kunnen vasthouden
\************************************************************/
var timerID;
function noAutoResize(nor)
{
    window._noAutoResize = nor;
}
function scheduleRefresh()
{
    if (window._noAutoResize)
        return;

    if (!elemIMG.parentElement)
        return;

    // Deze stonden al lang niet meer op '100%' en autosizen dus niet.
    elemIMG.style.width = elemIMG.parentElement.clientWidth + "px";
    if (elemIMG.parentElement.clientHeight)
        elemIMG.style.height = elemIMG.parentElement.clientHeight + "px";
    // else bij deactiveren van tabje wordt de hoogte in sommige browsers 0

    if (imgX == elemIMG.parentElement.clientWidth && imgY == elemIMG.parentElement.clientHeight)
        return;

    // Vergelijk eventueel/ook tegen de body afmetingen: die hebben geen last van _doPreview
    if (imgX == elemIMG.parentElement.clientWidth && imgY == elemIMG.parentElement.clientHeight)
        return;
    // Werkt in IE8 beter bij openen scneario zonder verdieping
    if (imgX == $(window).width() && imgY == $(window).height())
        return;

    if (timerID) // reset oude. Is goed voor de performance/response
        clearTimeout(timerID);

    imgX = $(window).width();
    imgY = $(window).height();

    timerID = setTimeout('Refresh();', 100);
}

/************************************************************\
*
\************************************************************/
function ZoomExtents(evt)
{
    if (!evt) evt=window.event;

    dScale=defaultScale;
    currentX = (imgX/2) - (imgX/2)*dScale;
    currentY = (imgY/2) - (imgY/2)*dScale;
    _doPreview();
    _refresh(true);
}

function zoom2DWG(centerX, centerY, newScale)
{
    if (!gSLNKEvent)
        return; // we waren zelf nog niet klaar.
    var currScale=imgY / (gSLNKEvent.viewmaxY - gSLNKEvent.viewminY);
    var currScale=imgX / (gSLNKEvent.viewmaxX - gSLNKEvent.viewminX);

    // zie ook CWhip2DCState::SetExtents
    var mulY =  imgY / (gSLNKEvent.DWGmaxY - gSLNKEvent.DWGminY)
    var mulX =  imgX / (gSLNKEvent.DWGmaxX - gSLNKEvent.DWGminX);

    if (mulY > mulX)
    {
        var autoMinX = gSLNKEvent.DWGminX; // als ik niets verschuif of schaal
        var autoMaxY = (gSLNKEvent.DWGminY+gSLNKEvent.DWGmaxY + imgY/mulX)/2;
    }
    else
    {
        var autoMinX = (gSLNKEvent.DWGminX+gSLNKEvent.DWGmaxX - imgX/mulY)/2;
        var autoMaxY = gSLNKEvent.DWGmaxY;
    }
    currentX = (autoMinX - centerX) * newScale + imgX/2;
    currentY = (centerY - autoMaxY) * newScale + imgY/2;
    dScale = dScale / currScale * newScale;

    _doPreview();
    _refresh(true);
}

/************************************************************\
*
\************************************************************/
function toDwgXY(imgX, imgY)
{
    result = null;

    if (gSLNKEvent && gSLNKEvent.success)
    {
        var result = new Object();
        result.scaleX = gSLNKEvent.scaleX; // DWG Size of one screen pixel X
        result.scaleY = gSLNKEvent.scaleY; // DWG Size of one screen pixel Y
        result.dwgX = gSLNKEvent.viewminX+imgX*result.scaleX;
        result.dwgY = gSLNKEvent.viewmaxY-imgY*result.scaleY;
    }
    return result;
}

/************************************************************\
*
\************************************************************/
function SetPanMode(pnm)
{
    _resetRubber();
    PanMode=pnm;
    if (PanMode==1)
    {
        elemIMG.useMap="#SystemMap";
    }
    elemIMG.style.cursor=(PanMode==1?'pointer':'move');
}

/************************************************************\
    - INT scale: -1 is altijd FIT,
                  0 is BYCURRENTZOOM (default)
                  >1, bijvoorbeeld 100 is vast 1:100
    - BOOL CurrentDWF  ==>Parameters voor huidige tekening worden toegevoegd
           (anders moet aanroeper zelf customParameters toevoegen en zelf oplossen
            via eigen IMGGenerator)
    - BOOL UNSUPPORTED: allowFineTuning van schaal en pan factor.
           Dan moeten paperWidth en paperHeight al meegegeven zijn!

\************************************************************/
function GetPrintURL(CurrentDWF, allowFineTuning)
{
    var printURL;
    if (CurrentDWF)
        printURL = qryWhat+"&ForPrint=1";
    else
        printURL = gIMGGenerator+"?ForPrint=1";;

    printURL += "&DWGminX="  + Math.round(gSLNKEvent.DWGminX)
             +  "&DWGminY="  + Math.round(gSLNKEvent.DWGminY)
             +  "&DWGmaxX="  + Math.round(gSLNKEvent.DWGmaxX)
             +  "&DWGmaxY="  + Math.round(gSLNKEvent.DWGmaxY)
             +  "&centerX="  + Math.round((gSLNKEvent.viewminX + gSLNKEvent.viewmaxX)/2)
             +  "&centerY="  + Math.round((gSLNKEvent.viewminY + gSLNKEvent.viewmaxY)/2);

    return printURL;
}

/************************************************************\
*
*
\************************************************************/
function _invalidateMap()
{
   document.getElementById("SystemMap").innerHTML = ""; // Tijdelijk ongeldig
    _PickOff()
}

/************************************************************\
* globalen: bmScale, bmCurrX, bmCurrY zoals de bitmap nu (nog) is
* globalen: dScale, currentX, currentY zoals we uiteindelijk nastreven
\************************************************************/
function _doPreview()
{
    if (bmScale == -1)
        return;

    _invalidateMap();

    elemIMG.style.width  = String(dScale/bmScale*100)+"%";
    elemIMG.style.height = String(dScale/bmScale*100)+"%";

    basicLeft = currentX - bmCurrX*dScale/bmScale;
    basicTop = currentY - bmCurrY*dScale/bmScale;
    elemIMG.style.left = basicLeft + "px";
    elemIMG.style.top  = basicTop + "px";
}

//
//
/************************************************************\
* Werkt alleen bij IE
* A) Voorkom flikkering.
* B) Performance verbetering: alleen eerste en laatste zoomfactor
*    wordt uiteindelijk uitgerekend
\************************************************************/
function _readystatechange(event)
{
    if (elemIMG.readyState=="loading")
    {
        if (_gbPending && _gbNextQry != "")
        {
            bmScale = pendScale;
            bmCurrX = pendX;
            bmCurrY = pendY;

            // Tegencorrectie preview settings voor het vorige plaatje
            _doPreview();

            // Verder gaan met de pending query doen we in de onLoad.
            // Dan weten we zeker dat het plaatje getoond wordt en
            // we willen ook niet echt afhankelijk zijn van _readystatechange
            return true;
        }

        bmScale = dScale;
        bmCurrX = currentX;
        bmCurrY = currentY;

        _gbPending = false;

        _doPreview();
        return;
    }
}

/************************************************************\
*
\************************************************************/
function _refresh(zoomChanged)
{
    elemIMG.style.cursor='progress';
    _showBusy();

    // Just in case
    var dd=document.getElementById("DragAndDrop")
    dd.style.display = 'none';
    dragAndDroppingBusy = false;
    _hideMenu();

    if (!imgX || !imgY || !currentX ||!currentY || !dScale)
        return; // dat wordt toch helemaal niets. Bijvoorbeeld Graphics in inactieve tab

    qryShow = "&sizeX="+imgX + "&sizeY="+imgY
            + "&offsetX="+Math.round(currentX)
            + "&offsetY="+Math.round(currentY)
            + "&scale="+Math.round(1000*dScale)
            + "&paperColor=" + _gPaperColor;
    if (gSLNKEvent && gSLNKEvent.success)
    {
        var hintX = (gSLNKEvent.DWGmaxX-gSLNKEvent.DWGminX) / dScale / imgX;
        var hintY = (gSLNKEvent.DWGmaxY-gSLNKEvent.DWGminY) / dScale / imgY;
        qryShow += "&hintScale=" + Math.max(hintX, hintY);
    }

    var qryAll = qryWhat + qryShow;

    _FireEvent("onIMGRefresh", "\""+qryAll+"\"");

    if (_gbPending && elemIMG.getAttribute("readyState")!="complete")
    {
        _gbNextQry=qryAll; // No use setting elemIMG.src while pending.
    }
    else
    {
        // sequence is opgehoogd bij geforceerde refresh
        elemIMG.src = qryAll +"&_dt_=" + _sequence;
        elemIMG.hasMap = true;

        _gbPending = true;
        // Remember settings for when arriving in readystatechange
        pendScale = dScale
        pendX = currentX;
        pendY = currentY;
    }
}

function isDwfViewerInstalled ()
{
    try
    {
        return new ActiveXObject("AdView.AdViewer");
    }
    catch ( e )
    {
		//Failed to create object, viewer not installed
		return false;
    }
}

// Print met de Autodesk DWF Viewer.
// Let wel: aanroeper heeft al gecontroleerd dat die er is.
function onPrintEv(evt)
{
    if (!evt) evt=window.event;

    var newWindow = window.open("PrintEmbedded.asp?qryWhat="+escape(qryWhat));
    newWindow.focus();
    return;
}

/************************************************************\
*
\************************************************************/
function onPrint(evt)
{
    if (!evt) evt=window.event;
    if (evt.ctrlKey && isDwfViewerInstalled)
    {
        newWindow = window.open("PrintEmbedded.asp?qryWhat="+escape(qryWhat));
        newWindow.focus();
        return;
    }
    if (_FireEvent("onPrint"))
    {
        PrintDialog();
    }
}

/************************************************************\
* Forceer de SLNK Print routine
\************************************************************/
function PrintDialog_callback(printParams)
{
    var qryPrint = "../Slnkdwf/Print.asp?paperSizeX="+printParams.paperWidth
                          + "&paperSizeY="+printParams.paperHeight // inches
                          + "&mustrotate="+(printParams.mustrotate?1:0)
                          + printParams.qryShow
                          + "&sheetsR=" + printParams.sheetsR
                          + "&sheetsX=" + printParams.sheetsX
                          + "&sheetsY=" + printParams.sheetsY
                          + "&img="+escape(qryWhat + gSLNKEvent.qryDWGSize + "&ForPrint=1") ;

    newWindow = window.open(qryPrint);
    newWindow.focus();
}

function PrintDialog(evt)
{
    if (!gSLNKEvent)
        return; // Te vroeg op print gedrukt. We weten nog niet genoeg

    gSLNKEvent.qryDWGSize = "&DWGminX="  + Math.round(gSLNKEvent.DWGminX)
                          + "&DWGmaxX="  + Math.round(gSLNKEvent.DWGmaxX)
                          + "&DWGminY="  + Math.round(gSLNKEvent.DWGminY)
                          + "&DWGmaxY="  + Math.round(gSLNKEvent.DWGmaxY);
    var optParam = "qryWhat="+escape(qryWhat);
    if (_gStyleSheet) optParam += "&stylesheet="+_gStyleSheet;
    var url = "../slnkdwf/printOptions.asp?"+optParam;

    delete gSLNKEvent.event; // IE8 probeert in $.widget.extend uiteindelijk event.hasOwnProperty
                             // te bepalen wat niet kan. Omdat we event toch verder niet nodig hebben
                             // verwijderen we die maar uit gSLNKEvent
    FcltMgr.openModalDetail(url, L("lcl_print"),
                             { SLNKEvent: gSLNKEvent,
                               callback: PrintDialog_callback
                             }
                           );

}

/************************************************************\
*
\************************************************************/
function onFullScreen()
{
}

/************************************************************\
* reason will be ONMOVE of DRAGANDDROP
* evt is optioneel
\************************************************************/
function EnableDragAndDrop(html, dragReason, evt)
{
    if (dragReason)
        _ddReason = dragReason;
    else
        _ddReason = "DRAGANDDROP";

    var dd = document.getElementById("DragAndDrop")
    dd.innerHTML = html;
    dragAndDroppingBusy = true;
    KeyDropBusy=false;

    // komt bij de eerste echte mousemove wel dd.style.display = 'block';
    // Dan weten we pas de muis positie. Als we evt hebben gebruiken we hem natuurlijk wel (symbolen draggen)
    if (evt) Dropper_onMouseMove(evt);
}

/************************************************************\
* Public doDrop
*        Aanroeper moet 'MMap'_onDrop gedefinieerd hebben
*        evt.clientX werkt niet omdat _DoFinder de relatieve Mmap coordinaten verwacht
*        Hier komen we langs als we symbolen vanuit het menu droppen
*        Hier komen we niet langs als we legendawaardes droppen
*        Waarom snap ik (JGL) niet.
\************************************************************/
function doDrop(evt, posX, posY)
{
    _DoFinder(evt, "DRAGANDDROP", posX, posY);
}

/************************************************************\
* Callback event als FND query is gedaan
\************************************************************/
function finder_onLoad(SLNKEvent)
{
    //_hideBusy();
    gSLNKEvent = SLNKEvent;

    if (SLNKEvent.Param == "DRAGANDDROP")
        _FireEvent("onDrop", SLNKEvent)
    else if (_FireEvent("onClick", SLNKEvent))
    {
        var msg = "Geklikt op X=" + SLNKEvent.dwgX + " Y=" + SLNKEvent.dwgY;
        if (SLNKEvent.ContourLabel != "")
            msg += "\nContour " + SLNKEvent.ContourLabel + " (Laag " + SLNKEvent.ContourLayer + ")";
        if (SLNKEvent.TextLabel != "")
            msg += "\nText " + SLNKEvent.TextLabel + " (Laag " + SLNKEvent.TextLayer + ")";
        // FcltMgr.alert(msg)
    }
}

/************************************************************\
* Callback event als MAP query is gedaan
\************************************************************/
function mapper_onLoad(SLNKEvent)
{
    gSLNKEvent = SLNKEvent;

    document.getElementById("SystemMap").innerHTML = SLNKEvent.Map;
    document.getElementById("Eview").useMap="#SystemMap";
    //Plaatje schuift niet zichtbaar tijdens draggen?
    //$('img[usemap]').maphilight({ fillColor: '8080ff', fillOpacity: 0.05,
    //            stroke: false, shadow: true, shadowRadius: 12 * SLNKEvent.dScale });
    document.body.style.backgroundColor = cssclrhex(_gPaperColor>=0?_gPaperColor:SLNKEvent.paperColor); // deze komt uit de tekening. Zie je bij uitzoomen

    _FireEvent("onMapperLoad", SLNKEvent);

    _hideBusy()
}

/************************************************************\
* Leaving entire body
\************************************************************/
function _onMouseLeave(evt)
{
    if (dragAndDroppingBusy)
    {
        var dd=document.getElementById("DragAndDrop")
        dd.style.display = 'none';
    }
}

var _symbolHot = false;

function _Centroid(arX, arY)
{
    var ptx = 0;
	var pty = 0;
	var totArea = 0;
	var i;
	for (i = 0; i < arX.length; i++) {
		var j = (i + 1) % arX.length;
		var dArea =  arX[i]*arY[j] - arX[j]*arY[i];
		totArea += dArea;
		ptx += (arX[i]+arX[j]) * dArea;
		pty += (arY[i]+arY[j]) * dArea;
	}
	return { X: ptx / totArea / 3, Y: pty / totArea / 3, AREA: totArea / 2 };
}

function _eventtarget (evt)
{
    evt = evt || window.event;
    var targ = evt.target || evt.srcElement;
    if (targ.nodeType === 3) { // fix Opera text node issue
        targ = targ.parentNode;
    }
    return targ;
}
// Muis bewogen over een AREA binnen onze MAP
function _areain(evt)
{
    if (!evt) evt=window.event;
    //if (!evt.ctrlKey) return; // Zonder control doen we niet aan highlight

    if (!gIMGKeyToSymbol) return;

    var elemArea = _eventtarget (evt);

    if (elemArea.tagName != "AREA") return;

    if (!elemArea.getAttribute("SLNKSymbolKey")) // Alleen symbolen highlighten
        return;

    _symbolKey = elemArea.getAttribute("SLNKSymbolKey"); // De DLL genereert deze waarde voor alles op laag "SLNK Symbols"
    var arX = [];
    var arY = [];
    var i;
    var coords = elemArea.coords.split(",");
    var minX=parseInt(coords[0]);
    var minY=parseInt(coords[1]);
    var maxX=minX;
    var maxY=minY;
    for (i=0; i < coords.length /2; i++)
    {
        arX[i] = parseInt(coords[2*i]);
        arY[i] = parseInt(coords[2*i+1]);
        minX=Math.min(minX,arX[i]);
        minY=Math.min(minY,arY[i]);
        maxX=Math.max(maxX,arX[i]);
        maxY=Math.max(maxY,arY[i]);
    }
    arX[i] = arX[0];
    arY[i] = arY[0];

    var ct = _Centroid(arX, arY)
    //ct.X = ((minX+maxX)/2);
    //ct.Y = ((minY+maxY)/2);

    if (Math.abs(ct.AREA) < 64) // Te klein
        return;

    var pick = document.getElementById("Pickpoint");
    pick.style.top=(ct.Y-6)+"px";
    pick.style.left=(ct.X-6)+"px";
    _PickCold();

    SLNKSymbolPos = { top: minY, left: minX, bottom: maxY, right: maxX };
}

function _areaout(evt)
{   if (!evt) evt=window.event;
    if (evt.toElement && evt.toElement.id == "Pickpoint")
        _PickHot(evt); // Zou vanzelf wel gekomen zijn maar dit flikkert minder
    else
        _PickOff();
}

function _PickOff(evt)
{
    $("#Pickpoint").hide();
    _symbolHot = false;
}

function _PickHot(evt)
{
    $("#Pickpoint").show().css("backgroundColor", "#FF0000");
    _symbolHot = true;
}

function _PickCold(evt)
{
    $("#Pickpoint").show().css("backgroundColor", "#0000FF");
    _symbolHot = false;
}

function _SnapOn(X, Y)
{
    var snp = document.getElementById("Snapper");
    snp.style.top = (Y-6)+"px";
    snp.style.left = (X-6)+"px";
    snp.style.display='block';
}

/************************************************************\
* Als in drag-and-drop mode dan kun je met pijltjestoetsen
* en enter verplaatsen per pixel
\************************************************************/
function _onKeyDown(evt)
{
    if (!dragAndDroppingBusy && !KeyDropBusy) // Safety check
        return;

    if (!evt) evt=window.event;
    var dd=document.getElementById("DragAndDrop")

    var dx=0;
    var dy=0;

    switch(evt.keyCode)
    {
        case 38:dy=-1;;break;
        case 40:dy=1;break;
        case 37:dx=-1;break;
        case 39:dx=1;break;
        case 13:{
                    KeyDropBusy=false;
                    _DoFinder(evt, _ddReason, parseInt(dd.style.left), parseInt(dd.style.top));
                    dd.style.display = 'none';

                    return false; // geen dingding
                }
        default: return;
    }

    dragAndDroppingBusy=false; // stop mouse-dragging
    KeyDropBusy=true; // en ga verder met key-dragging

    dd.style.display = 'block';

    dd.style.top = parseInt(dd.style.top)+dy + "px";
    dd.style.left = parseInt(dd.style.left)+dx + "px";

    return false;
}
/************************************************************\
* IE en FireFox/Safari hebben verschillende waarden voor de
* muisknoppen. Converteer deze tot dezelfde waarde.
* Werkt niet voor MouseCLick, maar wel voor MouseDown, MouseUp.
\************************************************************/
function _mouseButtonPressed(evt)
{
    if (evt.which == null)
    {
       /* IE case */
       if (!evt.button)
          return "NONE";
       button= (evt.button < 2) ? "LEFT" :
                 ((evt.button == 4) ? "MIDDLE" : "RIGHT");
    }
    else
    {
       /* All others */
       if (!evt.which)
          return "NONE";
       button= (evt.which < 2) ? "LEFT" :
                 ((evt.which == 2) ? "MIDDLE" : "RIGHT");
    }
    return button;
}

/************************************************************\
*
\************************************************************/
function _onMouseDown(evt)
{
    ignoreNextMove = true;
    if (!evt) evt=window.event;
    _hideMenu();
    stopPropagation(evt); // cancel element drag..

    dragStartX = evt.clientX;
    dragStartY = evt.clientY;
//    if (evt.button!=1)
    if (_mouseButtonPressed(evt)!='LEFT')
        return false; // ga verder met context menu

    if (_symbolHot && gIMGKeyToSymbol) // Boven het rode vierkantje
    {
        _StartSymbolDragging(evt)
        return;
    }
    switch (PanMode)
    {
        case 0: // Panning
        case 1: // Point/Identify
        {
            draggingBusy=true;
            // if (elemIMG.setCapture) elemIMG.setCapture(); FF geen onclick meer
            break;
        }
        case 2: // Zoom window
        {
            if (rubberingBusy)
                _stopRubber(evt);
            else
                _startRubber(evt);
        }
        case 3: // Zoom out
        {
            break; // wacht op klik
        }
    }
    return false;
}

// Helper voor _StartSymbolDragging
// Bij dobbelstenen op halve grootte kan het gebeuren dat ons drag
// symbool groter is dan verwacht. Daar corrigeren we hier voor.
function _Reposition(elmSymb)
{
    if (_pendingSymbol)
    {
        var xx=_pendingSymbol;
        _pendingSymbol = null;
        elmSymb.src = xx;
    }

    elmSymb.style.top = ((SLNKSymbolPos.top-dragStartY) * elmSymb.height / (SLNKSymbolPos.bottom - SLNKSymbolPos.top))+"px";
    elmSymb.style.left = ((SLNKSymbolPos.left-dragStartX) * elmSymb.width / (SLNKSymbolPos.right - SLNKSymbolPos.left))+"px";
}

function _RotatePoint(pt, rot, center)
{
    pt.x -= center.x;
    pt.y -= center.y;
    newx = pt.x * Math.cos(rot) - pt.y * Math.sin(rot);
    newy = pt.y * Math.cos(rot) + pt.x * Math.sin(rot);
    return { x : newx + center.x, y : newy + center.y };
}

function _RotateBoundingBox(box, rot)
{
    var cen = { x: (box.left + box.right)/2, y: (box.top + box.bottom)/2 }
    var p1 = _RotatePoint({ x : box.left, y :  box.bottom}, rot, cen);
    var p2 = _RotatePoint({ x : box.right, y : box.bottom}, rot, cen);
    var p3 = _RotatePoint({ x : box.right, y : box.top}, rot, cen);
    var p4 = _RotatePoint({ x : box.left, y : box.top}, rot, cen);

	return { left   : min(min(min(p1.m_x, p2.m_x), p3.m_x),p4.m_x),
	         bottom : min(min(min(p1.m_y, p2.m_y), p3.m_y),p4.m_y),
	         right  : max(max(max(p1.m_x, p2.m_x), p3.m_x),p4.m_x),
  	         top    : max(max(max(p1.m_y, p2.m_y), p3.m_y),p4.m_y) };
}

/************************************************************\
* Globale _symbolKey bevat ondertussen al wel 'onze' symbolkey
\************************************************************/
function _StartSymbolDragging(evt)
{
    if (!evt) evt=window.event;
    _invalidateMap();
    symbolDraggingBusy = true;
    _PickOff();

    var qryShow = "&sdwgScale=" + gSLNKEvent.scaleY
    var src = gIMGKeyToSymbol + "?pSymbolKey=" + _symbolKey + qryShow
    src += "&paperColor="+(_gPaperColor>=0?_gPaperColor:gSLNKEvent.paperColor);
    src += gCustomParameters;
    _pendingSymbol = null;
    _SymbolSrc = src;

    var newTop=SLNKSymbolPos.top-dragStartY;
    var newLeft=SLNKSymbolPos.left-dragStartX;

    var dv = "<img onload='_Reposition(this)'"
           + "     style=\"border:0;position:absolute;"
           +   "top:"+newTop+"px"
           +"; left:"+newLeft+"px"+";\" "
           + "       galleryimage=false"
           + "       src=\"" + src + "\">"
           +"</img>"
    EnableDragAndDrop(dv, "ONMOVE", evt); // Simpel maar doeltreffend
}

/************************************************************\
*
\************************************************************/
function _onMouseMove(evt)
{
    if(ignoreNextMove) {
        ignoreNextMove = false;
        return;
    }
    if (!evt) evt=window.event;
    _FireEvent("onMouseMove", evt);
    //_PickOff(); // Kan nooit de bedoeling zijn dat die hot blijft?

    lastMouseX = evt.clientX;
    lastMouseY = evt.clientY;

//    if (evt.button!=1)
    // TODO: anders voor FireFox, die doet evt.button alleen voor echte mouse-clicks
    // IE9 doet dat ook niet meer. JQuery's event.which blijft op 1 staan als de mouse-up
    //     buiten ons scherm is gebeurd
    if (_mouseButtonPressed(evt)!='LEFT')
    {
       var dd=document.getElementById("DragAndDrop")
        dd.style.display = 'none';
        dragAndDroppingBusy = false;
    }
    if (dragAndDroppingBusy)
    {   Dropper_onMouseMove(evt);
    }
    else if (rubberingBusy)
    {
        _moveRubber(evt);
    }
    else if (draggingBusy)
    {
        _invalidateMap();
        elemIMG.style.left = (basicLeft + evt.clientX - dragStartX)+"px";
        elemIMG.style.top = (basicTop + evt.clientY - dragStartY)+"px";
    }
}

/************************************************************\
*
\************************************************************/
function _onMouseUp(evt)
{
    ignoreNextMove = true; // Chrome onMouseUp includes an onMouseMove aparently
    if (!evt) evt=window.event;
    stopPropagation(evt);

    if (elemIMG.releaseCapture) elemIMG.releaseCapture();
    if (dragAndDroppingBusy) // Dekt ook moving
        Dropper_onMouseUp(evt);
    else if (rubberingBusy)
        _stopRubber(evt);
    else
    {
        if (!evt) evt=window.event;
        draggingBusy=false;
        var dx=(evt.clientX - dragStartX);
        var dy=(evt.clientY - dragStartY);
        if (!rubberingBusy && dx != 0 && dy != 0)
        {
            currentX += dx;
            currentY += dy;
            ignoreNextClick = true;
            dragStartX = evt.clientX;
            dragStartY = evt.clientY;
            _doPreview();
            _refresh(true);
        }
        else
        {
            ignoreNextClick = false;
        }
    }
}

/************************************************************\
* Drag and drop actief
* merk op dat symbolen verplaatsen is geimplementeerd als
* een identiek symbool droppen op de nieuwe plaats
\************************************************************/
function Dropper_onMouseMove(evt)
{
    if (dragAndDroppingBusy) // Safety check
    {
        _hideMenu(); // just in case

        var dd=document.getElementById("DragAndDrop")
        if (!evt) evt=window.event;
        dd.style.display = 'block';

        if (_ddReason=="ONMOVE" && evt.ctrlKey) // Initiate Rotate mode
        {
            _ddReason="ONROTATE";
            dd.firstChild.style.top = SLNKSymbolPos.top-dragStartY+"px";
            dd.firstChild.style.left = SLNKSymbolPos.left-dragStartX+"px";
            dd.style.top = (dragStartY - dd.clientHeight/2)+"px";
            dd.style.left = (dragStartX - dd.clientWidth/2)+"px";
        }
        if (_ddReason=="ONMOVE" && evt.shiftKey) // Initiate Copy mode
        {
            _ddReason="ONCOPY";
            //dd.appendChild(document.createTextNode("copy"));
            //dd.appendChild(document.createElement("<img src=xx style=position:absolute>"));
            var span = document.createElement("span")
            span.style.position="absolute";
            span.style.top="-10px";
            span.style.left="0px";
            span.style.height="10px";
            span.style.width="10px";
            span.style.textAlign="center";
            span.style.backgroundColor="red";
            span.innerHTML = "+"
            dd.appendChild(span);
        }

        if (_ddReason=="ONROTATE") // Rotate mode
        {
            var angle = Math.atan((dragStartY - evt.clientY) / (evt.clientX - dragStartX));
            if (isNaN(angle))
                var rot=0;
            else
                var rot = Math.round(0.5+(360+angle/3.1415926*180)%360);
            if (dragStartX > evt.clientX)
                rot = (rot+180)%360;

            if (dd.firstChild.readyState!="complete")
                _pendingSymbol = _SymbolSrc + "&rotation="+rot;
            else
                dd.firstChild.src = _SymbolSrc + "&rotation="+rot;

            return;
        }

        var ch=dd.clientHeight;
        var cw=dd.clientWidth;
        if (ch==0 && cw==0 && dd.firstChild) // Firefox past de width van de div niet aan?
        {
            var ch=dd.firstChild.clientHeight;
            var cw=dd.firstChild.clientWidth;
        }

        dd.style.top = (evt.clientY - dd.clientHeight/2)+"px";
        dd.style.left = (evt.clientX - dd.clientWidth/2)+"px";
    }
}

function Dropper_onMouseUp(evt)
{
    if (!dragAndDroppingBusy)
        return true;

    if (!evt) evt=window.event;
    stopPropagation(evt);

    var dx = Math.abs(evt.clientX - dragStartX);
    var dy = Math.abs(evt.clientY - dragStartY);
    if (_ddReason=="ONMOVE" && (dx+dy<3))
    {   // Heel weinig moven zien we als single-click
        // Dan gaan we verder als button-less ONMOVE
        // Omdat/zolang de muis boven getElementById("DragAndDrop") hangt gaan we
        // wel via Dropper_onMouseUp
        return;
    }

    var dd=document.getElementById("DragAndDrop")

    dd.innerHTML = "&nbsp;"; // Dit simpele regeltje lijkt een crash in IE8 bij slepen van symbolen te voorkomen

    dd.style.display = 'none';
    dragAndDroppingBusy = false;
    _DoFinder(evt, _ddReason);
    dd.style.display = 'none';
}

function _showBusy()
{
    var b = $("#busymarker");
    b.css('left', (imgX - b.outerWidth() - 5) + "px");
    b.css('top', "32px");
    b.show();
}

function _hideBusy()
{
    $("#busymarker").hide();
}
/************************************************************\
*
\************************************************************/
function _resetRubber()
{
    rubberingBusy=false;
    $("#rubberBand").hide();
    $("#dwgDist").hide();
}

/************************************************************\
*
\************************************************************/
function _startRubber(evt)
{
    if (rubberingBusy)
    {
        _stopRubber(evt);
    }
    else
    {
        rubberOrgX = evt.clientX;
        rubberOrgY  = evt.clientY;
        _moveRubber(evt)
        $("#rubberBand").show();
        rubberingBusy=true;
    }
}

/************************************************************\
*
\************************************************************/
function _moveRubber (evt)
{
    if (!evt) evt=window.event;
    var r = document.getElementById("rubberBand");

    var w = evt.clientX - rubberOrgX;
    if (w > 0)
        r.style.width = w + "px";
    else
    {
        r.style.left = (evt.clientX)+"px";
        r.style.width = (-w)+"px";
    }

    var h = evt.clientY - rubberOrgY;
    if (h > 0)
        r.style.height = h +"px";
    else
    {
        r.style.top = evt.clientY+"px";
        r.style.height = (-h)+"px";
    }
}

/************************************************************\
*
\************************************************************/
function _stopRubber(evt)
{
    if (!evt) evt=window.event;
    stopPropagation(evt);
    if (!rubberingBusy)
        return;

    var mx = (evt.clientX + rubberOrgX)/2;
    var my = (evt.clientY + rubberOrgY)/2;
    var dx = Math.abs(evt.clientX - rubberOrgX);
    var dy = Math.abs(evt.clientY - rubberOrgY);
    if (dx>2 && dy>2)
    {
        _resetRubber()

        mystepX = imgX/dx;
        mystepY = imgY/dy;
        mystep  = mystepX>mystepY?mystepY:mystepX;

        currentX = imgX/2 + (currentX - mx)*mystep;
        currentY = imgY/2 + (currentY - my)*mystep;
        dScale*=mystep;

        _doPreview();
        _refresh(true);
    }
    // else gewoon doorgaan
}


/************************************************************\
*
\************************************************************/
function _onClick(evt)
{
    if (!evt) evt=window.event;
    stopPropagation(evt);
    switch (PanMode)
    {
        case 0: // Panning
//        {
//            currentX += (imgX/2 - event.clientX);
//            currentY += (imgY/2 - event.clientY);
//            _refresh(true);
//            break;
//        }
        case 1: // Point/Identify
        {
            if (!ignoreNextClick) //  && dragStartX == evt.clientX && dragStartY == evt.clientY
            {
                if (dragAndDroppingBusy)
                {
                    ignoreNextClick = true;
                    Dropper_onMouseUp(evt);
                }
                else
                    _DoFinder(evt, "onclick");
            }
            ignoreNextClick=false;
            break;
        }
        case 2: // Zoom window ontvangt (na mouse up) een ongewilde onClick
        {
            //_startRubber(evt);
            // Terugspringen naar gewone pan
            SetPanMode(1);
            break;
        }
        case 3: // Zoom out
        {
            _doZoom(evt, step);
            break;
        }
    }
}

/************************************************************\
*
\************************************************************/
function _onDblClick(evt)
{
    if (!evt) evt=window.event;

    if (_FireEvent("onDblClick"))
        _DoFinder(evt, "ondblclick");
}

function showContextMenu(evt, divMenu)
{
    $(divMenu).show()
              .resize(_positionMenu(evt));
    if (!($(divMenu).attr("slnkhandlers")==1))
    {
        $(divMenu).on("click", ".menuItem", _clickMenu)
                  .on("mouseover", ".menuItem", _switchMenu)
                  .on("mouseout" , ".menuItem", _switchMenu);
        $(divMenu).attr("slnkhandlers", 1);
    }
    _positionMenu(evt, divMenu);
}
/************************************************************\
*
\************************************************************/
function _positionMenu(evt, divMenu)
{
    if (!evt) evt=window.event;
    var ctm = $(divMenu);
    // Herpositioneren als buiten beeld
    if (evt.clientY > imgY / 2)
        ctm.css("top", Math.max(evt.clientY-ctm.height(), 0) + "px"); // omhoog
    else
        ctm.css("top", Math.min(evt.clientY, imgY-ctm.height()) + "px"); // 'omlaag'

    if (evt.clientX + ctm.width()>imgX)
        ctm.css("left", evt.clientX - ctm.width() + "px");
    else
        ctm.css("left", evt.clientX + "px");
}

function _displayMenu(evt)
{
    if (!evt) evt=window.event;
    var ctm = document.getElementById("contextMenu");
    _positionMenu(evt)
    ctm.style.display="block";
    if (ctm.setCapture) ctm.setCapture();
}

function _clickMenu(evt)
{
    if (!evt) evt=window.event;
    _hideMenu(evt);
    var el=_eventtarget (evt);

    if (el.getAttribute("monClick"))
        eval(el.getAttribute("monClick"));
//    else // TODO: Only if within bounds of our IMG
//        _displayMenu(evt); // On the new location
}

function _hideMenu(evt)
{
    $(".slnkmenu").hide();
    if (parent.$) parent.$(".slnkmenu").hide(); // Een symbool menu
}

function _switchMenu(evt)
{
    if (!evt) evt=window.event;
    var el=_eventtarget (evt)
    $(el).toggleClass("highlightItem");
}

function _onPickcontextmenu (evt)
{
    if (!evt) evt=window.event;

    if (evt.ctrlKey && evt.altKey && evt.shiftKey)
        return true; // Show normal context menu
    else
    {
        if (_FireEvent("onPickcontextmenu", { symbolKey: _symbolKey, event:evt } ))
        {
         //   _displayMenu(evt, "PickcontextMenu");
        }
        return false;
    }
}

function _oncontextmenu (evt)
{
    if (!evt) evt=window.event;

//    _DoFinder(evt, "oncontextmenu");
    if (evt.ctrlKey && evt.altKey && evt.shiftKey)
        return true; // Show normal context menu
    else
    {
        stopPropagation(evt);
        showContextMenu(evt, document.getElementById("defaultContextMenu"));
        return false;
    }
}

/************************************************************\
*
\************************************************************/
function _doZoom(evt, pStep)
{
    // evt.clientX/evt.clientY werkt niet goed in FireFox 1.5.0.1
    currentX = lastMouseX + (currentX - lastMouseX)/pStep;
    currentY = lastMouseY + (currentY - lastMouseY)/pStep;
    dScale/=pStep;
    // Preview the scale immediately
    if (gSLNKEvent && gSLNKEvent.success)
    {
        gSLNKEvent.scaleX *=pStep;
        gSLNKEvent.scaleY *=pStep;
    }

    _doPreview();

    _refresh(true);
}

/************************************************************\
* When holding Shift-key only 1/10 of zoom
\************************************************************/
function _onMouseWheel(evt)
{
    if (!evt) evt=window.event;
    stopPropagation(evt);

    var delta = evt.originalEvent.wheelDelta;
    var detail = evt.originalEvent.detail; // FireFox
    var stp = step;
    if (evt.shiftKey)
        stp = 1+(stp-1)/10;
    if (evt.ctrlKey)
        stp = 1+(stp-1)/100;

    if (delta <=- 120 || detail > 0) // Verkleinen
    {
        _doZoom(evt, stp)
    }
    else if (delta >= 120 || detail < 0) // Vergroten
    {
        _doZoom(evt, 1.0/stp);
    }
    return false;
}

/************************************************************\
* Het plaatje is klaar met laden
\************************************************************/
function _onLoad(evt)
{
    if (!evt) evt=window.event;

    if (_gbPending && _gbNextQry != "")
    {
        // En ga verder met de pending query
        elemIMG.src = _gbNextQry;
        _gbPending = false;
        _gbNextQry = "";
        return;
    }
    _gbPending = false;
    elemIMG.style.top = "0px";
    elemIMG.style.left = "0px";
    elemIMG.style.width=imgX + "px";
    elemIMG.style.height=imgY + "px";

    elemIMG.style.cursor=(PanMode==1?'pointer':draggingBusy?'move':'auto');

    // Het plaatje is klaar. Langer kunnen we de mapper niet meer uitstellen
    if (elemIMG.hasMap)
    {
        // Alleen als nodig
        // -->Toch maar wat vaker omdat mogelijk tooltips wel veranderd zijn (ander thema)
        sendQuery(elemIMG.src + "&AsMap=1", mapper_onLoad, evt);

    }
    else
        _hideBusy();

    _FireEvent("onIMGLoad");

}
/************************************************************\
* Aanroeper mag cX en cY meegeven. Anders nemen we evt. waarden
\************************************************************/
function _DoFinder(evt, param, cX, cY)
{
    var qryAll;
    qryAll = qryFind  + "&sizeX="+imgX + "&sizeY=" + imgY + "&offsetX="
                      + Math.round(currentX) + "&offsetY=" + Math.round(currentY)
                      + "&scale=" + Math.round(1000*dScale);
    qryAll += "&findX="+(cX?cX:evt.clientX)+"&findY="+(cY?cY:evt.clientY);
    if (param == "ONMOVE" || param == "ONCOPY" || param == "ONROTATE") // Symbool verplaatsen
    {
        qryAll += "&fromX="+dragStartX+"&fromY="+dragStartY + "&SymbolKey=" + _symbolKey;
    }
    qryAll += "&prm=" + param;
    qryAll += "&evttype=" + evt.type;
    sendQuery(qryAll + "&AsFND=1", finder_onLoad, evt);
}

function _CopyToClip(divId)
{
   var div = document.getElementById(divId);
   div.contentEditable = 'true';
   var controlRange;
   if (document.body.createControlRange) {
     controlRange = document.body.createControlRange();
     controlRange.addElement(div);
     controlRange.execCommand('Copy');
   }
   div.contentEditable = 'false';
}

function sendQuery(url, callback, evt)
{
    if (!evt) evt = window.event;
    // Simpel myEvent=evt werkt niet: binnen de onreadystatechange bestaat evt niet meer in de scope
    myEvent = new Object();
    for (itm in evt)
    {
//    FcltMgr.alert(evt[itm]);
        myEvent[itm] = evt[itm];
    }
    $.getJSON(url,  { }, function (data) { data.event = myEvent; callback(data); });
}

function _FireEvent(evt_name, param)
{
    var pHandler = "parent."+this.name+ "_" + evt_name;

    if (eval(pHandler))
        return eval(pHandler).call(null, param);
    else
        return true; // Do default action
}

// We hebben nog geen FcltMgr.stopPropagation
function stopPropagation(eventHandler)
{
    eventHandler = eventHandler || window.event || {};
    if (eventHandler.stopPropagation)
        eventHandler.stopPropagation();
    if (eventHandler.preventDefault)
        eventHandler.preventDefault();
    eventHandler.cancelBubble = true;
}