var OIM_dragging = false;
var OIM_lastX = -1;
var OIM_lastY = -1;
var OIM_startX = -1;
var OIM_startY = -1;
var OCE_savecolor = false;
var OCE_Tool_Pencil = 0;
var OCE_Tool_Line = 1;
var OCE_Tool_Rectangle = 2;
var OCE_Tool_Dropper = 3;
var OCE_Tool_HotSpot = 4;
var OCE_Tool_Eraser = 5;
var OCE_Tool_Ellipse = 6;
var OCE_Tool_FloodFill = 7;
var OIM_mode = OCE_Tool_Pencil;
var OCE_prevtool = OCE_Tool_Pencil;
var OCE_blending = 0;
var OCE_prevargbs = null;
var OCE_frames = new Array(new Array());
var OCE_hotspots = new Array(new Array(0, 0));
var OCE_curframe = 0;
var OCE_color = 0x80ff4040;
var OCE_recentcolors = new Array(0xff000000, 0xff2a2a2a, 0xff555555, 0xff808080, 0xffababab, 0xffd5d5d5, 0xffffffff);

function OCE_updateform()
{
    var pixels = '';
    for (y = 0; y < 32; ++y)
    {
        var line = '';
        for (x = 0; x < 32; ++x)
        {
            var pix = OCE_frames[0][y*32+x];
            if (pix == null) pix = 0;
            var hexpix = ((pix>>28)&15).toString(16)+((pix>>24)&15).toString(16)+((pix>>20)&15).toString(16)+((pix>>16)&15).toString(16)+((pix>>12)&15).toString(16)+((pix>>8)&15).toString(16)+((pix>>4)&15).toString(16)+(pix&15).toString(16);
            line += hexpix;
        }
        pixels += line;
    }
    document.editor.frame_0.value = pixels;
    document.editor.hotspot_0.value = OCE_hotspots[0][0]+','+OCE_hotspots[0][1];
}

function OCE_addtolibrary(location, cursordetail)
{
    OCE_updateform();
    var httpRequest = window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : null);
    httpRequest.onreadystatechange = function()
    {
        if (httpRequest.readyState == 4)
        {
            if (httpRequest.status == 200)
            {
                var newid = parseInt(httpRequest.responseText);
                if (httpRequest.responseText == newid && newid > 0)
                {
                    activecursorid = newid;
                    var btn = document.getElementById("lib_show_cur");
                    btn.removeAttribute("disabled");
                    btn.setAttribute("onclick", "window.location='"+cursordetail+activecursorid+"'");
                    document.getElementById("lib_post_cur").value = "Save";
                }
                else
                    alert("Error occured. ("+httpRequest.responseText+") Please try again later.");
                document.getElementById("lib_post_cur").removeAttribute("disabled");
                document.getElementById("statusmsg").innerHTML = "Changes were saved to the library. Click 'View' to inspect it.";

            }
            else
                alert("Error occured. Please try again later.");
        }
    };
    httpRequest.open('POST', location, true);
    var params =
        "name="+escape(document.editor.filename.value)+
        //"&desc="+escape(document.editor.cursor_desc.value)+
        "&license="+document.editor.cursor_license.value+
        "&role="+document.editor.cursor_role.value+
        "&handness="+document.editor.cursor_type.value+
        "&frame_0="+document.editor.frame_0.value+
        "&hotspot_0="+document.editor.hotspot_0.value+
        "&frames=0";
    if (activecursorid > 0)
        params += "&cursorid="+activecursorid;
    httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    httpRequest.setRequestHeader("Content-length", params.length);
    httpRequest.setRequestHeader("Connection", "close");
    httpRequest.send(params);
    document.getElementById("lib_post_cur").setAttribute("disabled", "disabled");
}

function OCE_sethotspot(x, y)
{
    OCE_hotspots[OCE_curframe] = new Array(x, y);
    var preview = document.getElementById("preview");
    preview.style.left = (40-x)+"px";
    preview.style.top = (45-y)+"px";
}

function OCE_template(name, baseurl, x, y)
{
    var httpRequest;
    if (window.XMLHttpRequest) { // Mozilla, Safari, ...
        httpRequest = new XMLHttpRequest();
        //httpRequest.overrideMimeType('text/xml');
    } else if (window.ActiveXObject) { // IE
        httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
    }
    httpRequest.onreadystatechange = function()
    {
        if (httpRequest.readyState == 4)
        {
            if (httpRequest.status == 200)
            {
                var data = httpRequest.responseText;
                var f = OCE_frames[OCE_curframe];
                for (pi = 0; pi < 1024; ++pi)
                {
                    var argb = parseInt(data.substr(pi<<3, 8), 16);
                    if (f[pi] != argb)
                        OCE_replacepixel(pi, argb);
                }
                OCE_sethotspot(x, y);
            }
        }
    };
    httpRequest.open('GET', baseurl+'template.php?name='+name, true);
    httpRequest.send(null);
}

function OCE_replacepixel(pi, argb)
{
    var f = OCE_frames[OCE_curframe];
    var c = document.getElementById('c'+pi);
    var p = document.getElementById('p'+pi);
    var prev = f[pi];
    var a255 = (argb>>24)&0xff;
    if (a255 == 0)
    {
        c.style.backgroundColor = '';
        p.style.backgroundColor = '';
        f[pi] = 0;
/*@cc_on
        c.style.filter = '';
        p.style.filter = '';
        return;
@*/
        c.style.opacity = '';
        p.style.opacity = '';
        return;
    }
    var rgb = "#"+((argb>>20)&15).toString(16)+((argb>>16)&15).toString(16)+((argb>>12)&15).toString(16)+((argb>>8)&15).toString(16)+((argb>>4)&15).toString(16)+(argb&15).toString(16);
    var a = a255/255;
    if (prev == 0 || (argb&0xffffff) != (prev&0xffffff))
    {
        c.style.backgroundColor = rgb;
        p.style.backgroundColor = rgb;
    }
    f[pi] = argb;
    if ((argb&0xff000000) != (prev&0xff000000) && (a255 != 0xff || prev != 0))
    {
/*@cc_on
        var val = a255 == 0 || a255 == 255 ? '' : 'alpha(opacity='+Math.round(100*a)+')';
        c.style.filter = val;
        p.style.filter = val;
        return;
@*/
        c.style.opacity = a;
        p.style.opacity = a;
    }
}

function OCE_drawpixel(x, y, argb)
{
    var pi = (y<<5)+x;
    var prev = OCE_frames[OCE_curframe][pi];
    if ((argb&0xff000000) != 0 && OCE_blending == 0 && (argb&0xff000000) != 0xff000000 && (prev&0xff000000) != 0)
    {
        var pa = (prev>>24)&0xff;
        var pr = (prev>>16)&0xff;
        var pg = (prev>>8)&0xff;
        var pb = prev&0xff;
        var na = (argb>>24)&0xff;
        var nr = (argb>>16)&0xff;
        var ng = (argb>>8)&0xff;
        var nb = argb&0xff;
		var fa = na*255 + (255-na)*pa;
		var fr = 0;
		var fg = 0;
		var fb = 0;
		if (fa != 0)
		{
			var bA1 = (255-na)*pa;
			var bA2 = na*255;
			fr = Math.floor((pr*bA1 + nr*bA2)/fa);
			fg = Math.floor((pg*bA1 + ng*bA2)/fa);
			fb = Math.floor((pb*bA1 + nb*bA2)/fa);
			fa = Math.floor(fa/255);
		}
		argb = (fa<<24)|(fr<<16)|(fg<<8)|fb;
    }
    if (prev != argb)
        OCE_replacepixel(pi, argb);
}

function OCE_drawline(x1, y1, x2, y2, argb, block)
{
	var dx = x2 > x1 ? (x2-x1) : (x1-x2);
	var dy = y2 > y1 ? (y2-y1) : (y1-y2);
	var sx = x2 > x1 ? 1 : -1;
	var sy = y2 > y1 ? 1 : -1;
	if (dx >= dy)
	{
	    if (dx == 0)
	    {
	        if (block == null)
	        {
		        OCE_drawpixel(x1, y1, argb);
		    }
		    else if (block[x1+y1*32] === undefined)
	        {
		        OCE_drawpixel(x1, y1, argb);
		        block[x1+y1*32] = true;
	        }
	    }
	    else
	    {
		    var step = dy/dx;
		    for (var i = 0; i <= dx; i++)
		    {
		        var x = x1+i*sx;
		        var y = y1+Math.round(i*step*sy);
	            if (block == null)
	            {
		            OCE_drawpixel(x, y, argb);
		        }
		        else if (block[x+y*32] === undefined)
	            {
		            OCE_drawpixel(x, y, argb);
		            block[x+y*32] = true;
	            }
	        }
		}
	}
	else
	{
		var step = dx/dy;
		for (var i = 0; i <= dy; i++)
		{
		    var x = x1+Math.round(i*step*sx);
		    var y = y1+i*sy;
	        if (block == null)
	        {
		        OCE_drawpixel(x, y, argb);
		    }
		    else if (block[x+y*32] === undefined)
	        {
		        OCE_drawpixel(x, y, argb);
		        block[x+y*32] = true;
	        }
		}
	}
}

function OCE_backupline(x1, y1, x2, y2)
{
	var dx = x2 > x1 ? (x2-x1) : (x1-x2);
	var dy = y2 > y1 ? (y2-y1) : (y1-y2);
	var sx = x2 > x1 ? 1 : -1;
	var sy = y2 > y1 ? 1 : -1;
	if (dx >= dy)
	{
	    if (dx == 0)
	    {
       	    OCE_prevargbs[y1*32+x1] = OCE_frames[OCE_curframe][y1*32+x1];
	    }
	    else
	    {
    		var step = dy/dx;
	    	for (var i = 0; i <= dx; i++)
		    {
		        var x = x1+i*sx;
    		    var y = y1+Math.round(i*step*sy);
	    	    OCE_prevargbs[y*32+x] = OCE_frames[OCE_curframe][y*32+x];
		    }
		}
	}
	else
	{
		var step = dx/dy;
		for (var i = 0; i <= dy; i++)
		{
		    var x = x1+Math.round(i*step*sx);
		    var y = y1+i*sy;
		    OCE_prevargbs[y*32+x] = OCE_frames[OCE_curframe][y*32+x];
		}
	}
}

function OCE_shouldfill(x, y, frame, block, match)
{
    if (x < 0 || y < 0 || x >= 32 || y >= 32)
        return false;
    var yy = y*32;
    if (block[yy+x] == true)
        return false;
    var argb = frame[yy+x];
    if (argb == null) argb = 0;
    return (argb^match) == 0;
}

function OCE_fillpixel(x, y, frame, block, match, argb, stack)
{
    if (block[y*32+x] != true)
    {
        OCE_drawpixel(x, y, argb);
        block[y*32+x] = true;
    }
    
    if (OCE_shouldfill(x, y-1, frame, block, match)) stack.push([x, y-1]);
    if (OCE_shouldfill(x+1, y, frame, block, match)) stack.push([x+1, y]);
    if (OCE_shouldfill(x, y+1, frame, block, match)) stack.push([x, y+1]);
    if (OCE_shouldfill(x-1, y, frame, block, match)) stack.push([x-1, y]);
}

function OCE_floodfill(x, y, argb)
{
    var frame = OCE_frames[OCE_curframe];
    var match = frame[y*32+x];
    if (match == null) match = 0;
    var map = new Array();
    var stack = new Array();
    OCE_fillpixel(x, y, frame, map, match, argb, stack);
    
    while(stack.length>0)
    {
        var next = stack.pop();
        OCE_fillpixel(next[0], next[1], frame, map, match, argb, stack);
    }
}

function OCE_restorepixels(saved)
{
    for (var at in saved)
        OCE_replacepixel(at, saved[at]);
}

function OCE_clearcanvas()
{
    for (pi = 0; pi < 1024; ++pi)
        if (OCE_frames[OCE_curframe][pi] != 0)
            OCE_replacepixel(pi, 0);
}

function OCE_colorize()
{
    var color = parseInt(document.getElementById('picker_text').value, 16);
    color = rgbToHsv(((color>>16)&0xff)/255, ((color>>8)&0xff)/255, (color&0xff)/255, (color>>24)&0xff);
    var h = color.h;
    var s = color.s;
    for (pi = 0; pi < 1024; ++pi)
    {
        var pix = OCE_frames[OCE_curframe][pi];
        if (pix != null && pix&0xff000000)
        {
            var hsv = rgbToHsv(((pix>>16)&0xff)/255, ((pix>>8)&0xff)/255, (pix&0xff)/255, (pix>>24)&0xff);
            var rgb = hsvToRgb(h, s, hsv.v, hsv.a);
            var clr = (rgb.a<<24)|(Math.round(rgb.r*255)<<16)|(Math.round(rgb.g*255)<<8)|(Math.round(rgb.b*255));
            OCE_replacepixel(pi, clr);
        }
    }
    return false;
}

function OCE_blur(inp)
{
    var out = new Array();
    for (y = -4; y < 36; ++y)
        out[y] = new Array();
        
    for (y = -4; y < -2; ++y)
        for (x = -4; x < 36; ++x)
            out[x][y] = 0;
    for (y = -2; y < 34; ++y)
    {
        var line = inp[y];
        out[-4][y] = 0;
        out[-3][y] = 0;
        for (x = -2; x < 34; ++x)
        {
            out[x][y] = (line[x-2]+(line[x-1]<<1)+(line[x]<<1)+(line[x+1]<<1)+line[x+2])>>3;
        }
        out[34][y] = 0;
        out[35][y] = 0;
    }
    for (y = 34; y < 36; ++y)
        for (x = -4; x < 36; ++x)
            out[x][y] = 0;
    return out;
}

function OCE_dropshadow()
{
    var buf = new Array();
    for (i = -4; i < 0; ++i)
    {
        var line = new Array();
        for (x = -4; x < 36; ++x) line[x] = 0;
        buf[i] = line;
    }
    for (y = 0; y < 32; ++y)
    {
        var line = new Array();
        line[-4] = 0;
        line[-3] = 0;
        line[-2] = 0;
        line[-1] = 0;
        for (x = 0; x < 32; ++x)
            line[x] = (OCE_frames[OCE_curframe][y*32+x]>>24)&0xff;
        line[32] = 0;
        line[33] = 0;
        line[34] = 0;
        line[35] = 0;
        buf[y] = line;
    }
    for (i = 32; i < 36; ++i)
    {
        var line = new Array();
        for (x = -4; x < 36; ++x) line[x] = 0;
        buf[i] = line;
    }
    buf = OCE_blur(buf);
    buf = OCE_blur(buf);
    for (y = 0; y < 32; ++y)
    {
        var line = buf[y-1];
        for (x = 0; x < 32; ++x)
        {
            var pi = (y<<5)+x;
            var prev = OCE_frames[OCE_curframe][pi];
            if ((prev&0xff000000) != 0xff000000 && line[x-1] != 0)
            {
                if (prev&0xff000000)
                {
                    var argb = line[x-1]<<24;
                    var pa = (argb>>24)&0xff;
                    var pr = (argb>>16)&0xff;
                    var pg = (argb>>8)&0xff;
                    var pb = argb&0xff;
                    var na = (prev>>24)&0xff;
                    var nr = (prev>>16)&0xff;
                    var ng = (prev>>8)&0xff;
                    var nb = prev&0xff;
	                var fa = na*255 + (255-na)*pa;
	                var fr = 0;
	                var fg = 0;
	                var fb = 0;
	                if (fa != 0)
	                {
		                var bA1 = (255-na)*pa;
		                var bA2 = na*255;
		                fr = Math.floor((pr*bA1 + nr*bA2)/fa);
		                fg = Math.floor((pg*bA1 + ng*bA2)/fa);
		                fb = Math.floor((pb*bA1 + nb*bA2)/fa);
		                fa = Math.floor(fa/255);
	                }
                    OCE_replacepixel(pi, (fa<<24)|(fr<<16)|(fg<<8)|fb);
                }
                else
                    OCE_replacepixel(pi, line[x-1]<<24);
            }
        }
    }
    return false;
}

function OIM_mousedown(x, y)
{
    OCE_color = parseInt(document.getElementById('picker_text').value, 16);
    switch (OIM_mode)
    {
    case OCE_Tool_Pencil:
        OCE_prevargbs = new Array();
        OCE_drawline(x, y, x, y, OCE_color, OCE_prevargbs);
        OIM_lastX = x;
        OIM_lastY = y;
        OIM_dragging = true;
        OCE_savecolor = true;
        break;
    case OCE_Tool_Eraser:
        OCE_prevargbs = new Array();
        OCE_drawline(x, y, x, y, 0, OCE_prevargbs);
        OIM_lastX = x;
        OIM_lastY = y;
        OIM_dragging = true;
        OCE_savecolor = true;
        break;
    case OCE_Tool_Line:
        OCE_prevargbs = new Array();
        OIM_lastX = OIM_startX = x;
        OIM_lastY = OIM_startY = y;
	    OCE_prevargbs[y*32+x] = OCE_frames[OCE_curframe][y*32+x];
        OCE_drawpixel(x, y, OCE_color);
        OIM_dragging = true;
        OCE_savecolor = true;
        break;
    case OCE_Tool_Rectangle:
    case OCE_Tool_Ellipse:
        OCE_prevargbs = new Array();
        OIM_lastX = OIM_startX = x;
        OIM_lastY = OIM_startY = y;
	    OCE_prevargbs[y*32+x] = OCE_frames[OCE_curframe][y*32+x];
        OCE_drawpixel(x, y, OCE_color);
        OIM_dragging = true;
        OCE_savecolor = true;
        break;
    case OCE_Tool_Dropper:
        if (OCE_savecolor)
        {
            var picker = document.getElementById('picker_text');
            OCE_recentcolors.unshift(parseInt(picker.value, 16));
            OCE_recentcolors.pop();
            OCE_updaterecentcolors();
            OCE_savecolor = false;
        }
        var clr = OCE_frames[OCE_curframe][y*32+x];
        if (clr == null) clr = 0;
        document.getElementById('picker_text').value = argbToHex2(clr);
        if (document.createEventObject)
        {
            document.getElementById('picker_text').fireEvent('onchange', document.createEventObject())  
        }
        else
        {
            var evObj = document.createEvent('HTMLEvents');
            evObj.initEvent('change', false, false)
            document.getElementById('picker_text').dispatchEvent(evObj);
        }
        OCE_settool(OCE_prevtool);
        break;
    case OCE_Tool_HotSpot:
        OCE_sethotspot(x, y);
        OIM_dragging = true;
        break;
    case OCE_Tool_FloodFill:
        OCE_floodfill(x, y, OCE_color);
        OIM_dragging = true;
        OCE_savecolor = true;
        break;
    }
    return false;
}
function OIM_mousemove(x, y, e)
{
    /*@cc_on if (e && e.srcElement)
    {
        if ("xpos" in e.srcElement && "ypos" in e.srcElement)
        {
            x = e.srcElement.xpos;
            y = e.srcElement.ypos;
        }
        else
            return false;
    }
    else
        return false;
    @*/
    switch (OIM_mode)
    {
    case OCE_Tool_Pencil:
        if (OIM_dragging && (x != OIM_lastX || y != OIM_lastY))
        {
            OCE_drawline(x, y, OIM_lastX, OIM_lastY, OCE_color, OCE_prevargbs);
            OIM_lastX = x;
            OIM_lastY = y;
        }
        break;
    case OCE_Tool_Eraser:
        if (OIM_dragging && (x != OIM_lastX || y != OIM_lastY))
        {
            OCE_drawline(x, y, OIM_lastX, OIM_lastY, 0, OCE_prevargbs);
            OIM_lastX = x;
            OIM_lastY = y;
        }
        break;
    case OCE_Tool_Line:
        if (OIM_dragging && (x != OIM_lastX || y != OIM_lastY))
        {
            OCE_restorepixels(OCE_prevargbs);
            OCE_prevargbs = new Array();
            if (OIM_startX == x && OIM_startY == y)
            {
	            OCE_prevargbs[y*32+x] = OCE_frames[OCE_curframe][y*32+x];
                OCE_drawpixel(x, y, OCE_color);
            }
            else
            {
                OCE_backupline(OIM_startX, OIM_startY, x, y);
                OCE_drawline(OIM_startX, OIM_startY, x, y, OCE_color);
            }
            OIM_lastX = x;
            OIM_lastY = y;
        }
        break;
    case OCE_Tool_Rectangle:
        if (OIM_dragging && (x != OIM_lastX || y != OIM_lastY))
        {
            OCE_restorepixels(OCE_prevargbs);
            OCE_prevargbs = new Array();
            var x1 = OIM_startX < x ? OIM_startX : x;
            var y1 = OIM_startY < y ? OIM_startY : y;
            var x2 = OIM_startX > x ? OIM_startX : x;
            var y2 = OIM_startY > y ? OIM_startY : y;
            OCE_backupline(x1, y1, x2, y1);
            OCE_drawline(x1, y1, x2, y1, OCE_color);
            if ((y2-y1) > 1)
            {
                OCE_backupline(x1, y1+1, x1, y2-1);
                OCE_drawline(x1, y1+1, x1, y2-1, OCE_color);
                if (x2 != x1)
                {
                    OCE_backupline(x2, y1+1, x2, y2-1);
                    OCE_drawline(x2, y1+1, x2, y2-1, OCE_color);
                }
            }
            if (y2 != y1)
            {
                OCE_backupline(x1, y2, x2, y2);
                OCE_drawline(x1, y2, x2, y2, OCE_color);
            }
            OIM_lastX = x;
            OIM_lastY = y;
        }
        break;
    case OCE_Tool_Ellipse:
        if (OIM_dragging && (x != OIM_lastX || y != OIM_lastY))
        {
            OCE_restorepixels(OCE_prevargbs);
            OCE_prevargbs = new Array();
            var x1 = OIM_startX < x ? OIM_startX : x;
            var y1 = OIM_startY < y ? OIM_startY : y;
            var x2 = OIM_startX > x ? OIM_startX : x;
            var y2 = OIM_startY > y ? OIM_startY : y;
            if (x1 == x2 || y1 == y2)
            {
                OCE_backupline(x1, y1, x2, y2);
                OCE_drawline(x1, y1, x2, y2, OCE_color);
            }
            else
            {
                var xm = (x2+x1)>>1;
                var ym = (y2+y1)>>1;
                if ((x2-x1) >= (y2-y1))
                {
				    var ratio = (y2-y1)/(x2-x1);
				    var radius = 0.5*(x2-x1); // subtract half pixel
				    var lastX = (x2-x1)>>1;
				    var centerY = 0.5*(y2-y1);
				    var lastDrawn = (y2-y1)>>1;
				    for (var x = 0; x <= lastX; ++x)
				    {
					    var y = Math.round(centerY-ratio*Math.sqrt(radius*radius - (radius-x-0.5)*(radius-x-0.5)));
					    if (lastDrawn < y)
						    lastDrawn = y;
					    while (lastDrawn >= y)
					    {
						    var xx = x1+x;
						    var yy = y1+lastDrawn;
    	    	            OCE_prevargbs[yy*32+xx] = OCE_frames[OCE_curframe][yy*32+xx];
                            OCE_drawpixel(xx, yy, OCE_color);
                            if (xx != x2-x)
                            {
                                xx = x2-x;
        	    	            OCE_prevargbs[yy*32+xx] = OCE_frames[OCE_curframe][yy*32+xx];
                                OCE_drawpixel(xx, yy, OCE_color);
                            }
                            if (yy != y2-lastDrawn)
                            {
                                xx = x1+x;
                                yy = y2-lastDrawn;
    	    	                OCE_prevargbs[yy*32+xx] = OCE_frames[OCE_curframe][yy*32+xx];
                                OCE_drawpixel(xx, yy, OCE_color);
                                if (xx != x2-x)
                                {
                                    xx = x2-x;
        	    	                OCE_prevargbs[yy*32+xx] = OCE_frames[OCE_curframe][yy*32+xx];
                                    OCE_drawpixel(xx, yy, OCE_color);
                                }
                            }
						    --lastDrawn;
					    }
				    }
                }
                else
                {
				    var ratio = (x2-x1)/(y2-y1);
				    var radius = 0.5*(y2-y1); // subtract half pixel
				    var lastY = (y2-y1)>>1;
				    var centerX = 0.5*(x2-x1);
				    var lastDrawn = (x2-x1)>>1;
				    for (var y = 0; y <= lastY; ++y)
				    {
					    var x = Math.round(centerX-ratio*Math.sqrt(radius*radius - (radius-y-0.5)*(radius-y-0.5)));
					    if (lastDrawn < x)
						    lastDrawn = x;
					    while (lastDrawn >= x)
					    {
						    var yy = y1+y;
						    var xx = x1+lastDrawn;
    	    	            OCE_prevargbs[yy*32+xx] = OCE_frames[OCE_curframe][yy*32+xx];
                            OCE_drawpixel(xx, yy, OCE_color);
                            if (yy != y2-y)
                            {
                                yy = y2-y;
        	    	            OCE_prevargbs[yy*32+xx] = OCE_frames[OCE_curframe][yy*32+xx];
                                OCE_drawpixel(xx, yy, OCE_color);
                            }
                            if (xx != x2-lastDrawn)
                            {
                                yy = y1+y;
                                xx = x2-lastDrawn;
    	    	                OCE_prevargbs[yy*32+xx] = OCE_frames[OCE_curframe][yy*32+xx];
                                OCE_drawpixel(xx, yy, OCE_color);
                                if (yy != y2-y)
                                {
                                    yy = y2-y;
        	    	                OCE_prevargbs[yy*32+xx] = OCE_frames[OCE_curframe][yy*32+xx];
                                    OCE_drawpixel(xx, yy, OCE_color);
                                }
                            }
						    --lastDrawn;
					    }
				    }
                }
            }
            OIM_lastX = x;
            OIM_lastY = y;
        }
        break;
    case OCE_Tool_HotSpot:
        if (OIM_dragging && (x != OIM_lastX || y != OIM_lastY))
        {
            OCE_sethotspot(x, y);
            OIM_lastX = x;
            OIM_lastY = y;
        }
        break;
    }

    return false;
}
function OIM_mouseup(e)
{
    OIM_dragging = false;
    return false;
}

function OCE_settool(tool)
{
    if (OIM_mode != tool)
    {
        if (OIM_mode != OCE_Tool_HotSpot && OIM_mode != OCE_Tool_Dropper && OIM_mode != OCE_Tool_Eraser)
            OCE_prevtool = OIM_mode;
        document.getElementById('tool-'+OIM_mode).className = '';
        OIM_mode = tool;
        document.getElementById('tool-'+OIM_mode).className = 'tool-sel';
    }
    //document.getElementById('tool-'+tool).blur();
    return false;
}

function OCE_setblending(mode)
{
    if (OCE_blending != mode)
    {
        document.getElementById('blending-'+OCE_blending).className = '';
        OCE_blending = mode;
        document.getElementById('blending-'+OCE_blending).className = 'tool-sel';
    }
    //document.getElementById('blending-'+mode).blur();
    return false;
}

function OCE_menuover(index)
{
    document.getElementById('menu-l-'+index).className = 'toolbar_button_hot';
    document.getElementById('menu-r-'+index).className = 'toolbar_btn_r_hot';
    document.getElementById('menu-c-'+index).className = 'toolbar_btn_c_hot';
}

function OCE_menuout(index)
{
    document.getElementById('menu-l-'+index).className = 'toolbar_button';
    document.getElementById('menu-r-'+index).className = 'toolbar_btn_r';
    document.getElementById('menu-c-'+index).className = 'toolbar_btn_c';
}


function OCE_download()
{
    OCE_updateform();
    document.editor.submit();
}

function OCE_updaterecentcolors()
{
    for (i = 0; i < 7; ++i)
    {
        var clr = OCE_recentcolors[i];
        var item = document.getElementById('picker_recent'+i);
        item.style.backgroundColor = rgbToHex2(clr);
        /*@cc_on
        var a255 = ((clr>>24)&0xff);
        item.style.filter = a255 == 0 || a255 == 255 ? '' : 'alpha(opacity='+Math.round(100*a255/255)+')';
        return; @*/
        item.style.opacity = ((clr>>24)&0xff)/255;
    }
}

function OCE_recentcolor(index)
{
    var picker = document.getElementById('picker_text');
    OCE_recentcolors.unshift(parseInt(picker.value, 16));
    picker.value = argbToHex2(OCE_recentcolors[index+1]);
    OCE_recentcolors.splice(index+1, 1);
    OCE_updaterecentcolors();
    if (document.createEventObject)
    {
        picker.fireEvent('onchange', document.createEventObject())  
    }
    else
    {
        var evObj = document.createEvent('HTMLEvents');
        evObj.initEvent('change', false, false)
        picker.dispatchEvent(evObj);
    }
}

function OCE_savetolib()
{
    var uploadbar = document.getElementById('uploadbar');
    if (uploadbar.style.visibility == 'hidden')
    {
        uploadbar.style.visibility = 'visible';
        document.getElementById("lib_post_cur").removeAttribute("disabled");
        document.getElementById("lib_show_cur").setAttribute("disabled", "disabled");
    }
    else
    {
        uploadbar.style.visibility = 'hidden';
    }
}

var OCE_basichelpsection = '';

function OCE_showhelp(section)
{
    var helpbubble = document.getElementById('help');
    if (section != undefined || helpbubble.style.visibility == 'hidden')
    {
        if (section == undefined)
            section = 'index';
        if (section != OCE_basichelpsection)
        {
            OCE_basichelpsection = section;
            document.getElementById('help_content').innerHTML = document.getElementById('help_'+OCE_basichelpsection).innerHTML;
        }
        helpbubble.style.visibility = 'visible';
    }
    else
        helpbubble.style.visibility = 'hidden';
}

function OCE_namechanged(name)
{
    document.getElementById('caption').innerHTML = name+'.cur - Online Cursor Editor';
}

// Here are some boring utility functions. The real code comes later.

function hexToArgb(hex_string, default_)
{
    if (default_ == undefined)
    {
        default_ = null;
    }

    if (hex_string.substr(0, 1) == '#')
    {
        hex_string = hex_string.substr(1);
    }
    
    var a;
    var r;
    var g;
    var b;
    if (hex_string.length == 3)
    {
        a = "FF";
        r = hex_string.substr(0, 1);
        r += r;
        g = hex_string.substr(1, 1);
        g += g;
        b = hex_string.substr(2, 1);
        b += b;
    }
    if (hex_string.length == 4)
    {
        a = hex_string.substr(0, 1);
        a += a;
        r = hex_string.substr(0, 1);
        r += r;
        g = hex_string.substr(1, 1);
        g += g;
        b = hex_string.substr(2, 1);
        b += b;
    }
    else if (hex_string.length == 6)
    {
        a = "FF";
        r = hex_string.substr(0, 2);
        g = hex_string.substr(2, 2);
        b = hex_string.substr(4, 2);
    }
    else if (hex_string.length == 8)
    {
        a = hex_string.substr(0, 2);
        r = hex_string.substr(2, 2);
        g = hex_string.substr(4, 2);
        b = hex_string.substr(6, 2);
    }
    else
    {
        return default_;
    }
    
    a = parseInt(a, 16);
    r = parseInt(r, 16);
    g = parseInt(g, 16);
    b = parseInt(b, 16);
    if (isNaN(a) || isNaN(r) || isNaN(g) || isNaN(b))
    {
        return default_;
    }
    else
    {
        return {r: r / 255, g: g / 255, b: b / 255, a: a / 255};
    }
}

function rgbToHex2(rgb, includeHash)
{
    r = ((rgb>>16)&0xff).toString(16); if (r.length == 1) r = '0' + r;
    g = ((rgb>>8)&0xff).toString(16); if (g.length == 1) g = '0' + g;
    b = (rgb&0xff).toString(16); if (b.length == 1) b = '0' + b;
    return ((includeHash == undefined || includeHash ? '#' : '') + r + g + b).toUpperCase();
}

function rgbToHex(r, g, b, includeHash)
{
    r = Math.round(r*255).toString(16); if (r.length == 1) r = '0' + r;
    g = Math.round(g*255).toString(16); if (g.length == 1) g = '0' + g;
    b = Math.round(b*255).toString(16); if (b.length == 1) b = '0' + b;
    return ((includeHash == undefined || includeHash ? '#' : '') + r + g + b).toUpperCase();
}

function argbToHex2(argb)
{
    a = ((argb>>24)&0xff).toString(16); if (a.length == 1) a = '0' + a;
    r = ((argb>>16)&0xff).toString(16); if (r.length == 1) r = '0' + r;
    g = ((argb>>8)&0xff).toString(16); if (g.length == 1) g = '0' + g;
    b = (argb&0xff).toString(16); if (b.length == 1) b = '0' + b;
    return (a + r + g + b).toUpperCase();
}

function argbToHex(a, r, g, b)
{
    a = Math.round(a*255).toString(16); if (a.length == 1) a = '0' + a;
    r = Math.round(r*255).toString(16); if (r.length == 1) r = '0' + r;
    g = Math.round(g*255).toString(16); if (g.length == 1) g = '0' + g;
    b = Math.round(b*255).toString(16); if (b.length == 1) b = '0' + b;
    return (a + r + g + b).toUpperCase();
}

function trackDrag(node, handler)
{
    function fixCoords(x, y)
    {
        var nodePageCoords = pageCoords(node);
        x = (x - nodePageCoords.x) + document.documentElement.scrollLeft + document.body.scrollLeft; // chome hack
        y = (y - nodePageCoords.y) + document.documentElement.scrollTop + document.body.scrollTop; // chome hack
        if (x < 0) x = 0;
        if (y < 0) y = 0;
        if (x > node.offsetWidth - 1) x = node.offsetWidth - 1;
        if (y > node.offsetHeight - 1) y = node.offsetHeight - 1;
        return {x: x, y: y};
    }
    function mouseDown(ev)
    {
        var coords = fixCoords(ev.clientX, ev.clientY);
        var lastX = coords.x;
        var lastY = coords.y;
        handler(coords.x, coords.y);

        function moveHandler(ev)
        {
            var coords = fixCoords(ev.clientX, ev.clientY);
            if (coords.x != lastX || coords.y != lastY)
            {
                lastX = coords.x;
                lastY = coords.y;
                handler(coords.x, coords.y);
            }
        }
        function upHandler(ev)
        {
            myRemoveEventListener(document, 'mouseup', upHandler);
            myRemoveEventListener(document, 'mousemove', moveHandler);
            myAddEventListener(node, 'mousedown', mouseDown);
        }
        myAddEventListener(document, 'mouseup', upHandler);
        myAddEventListener(document, 'mousemove', moveHandler);
        myRemoveEventListener(node, 'mousedown', mouseDown);
        if (ev.preventDefault) ev.preventDefault();
    }
    myAddEventListener(node, 'mousedown', mouseDown);
    node.onmousedown = function(e) { return false; };
    node.onselectstart = function(e) { return false; };
    node.ondragstart = function(e) { return false; };
}

var eventListeners = [];

function findEventListener(node, event, handler)
{
    var i;
    for (i in eventListeners)
    {
        if (eventListeners[i].node == node && eventListeners[i].event == event
         && eventListeners[i].handler == handler)
        {
            return i;
        }
    }
    return null;
}
function myAddEventListener(node, event, handler)
{
    if (findEventListener(node, event, handler) != null)
    {
        return;
    }

    if (!node.addEventListener)
    {
        node.attachEvent('on' + event, handler);
    }
    else
    {
        node.addEventListener(event, handler, false);
    }

    eventListeners.push({node: node, event: event, handler: handler});
}

function removeEventListenerIndex(index)
{
    var eventListener = eventListeners[index];
    delete eventListeners[index];
    
    if (!eventListener.node.removeEventListener)
    {
        eventListener.node.detachEvent('on' + eventListener.event,
                                       eventListener.handler);
    }
    else
    {
        eventListener.node.removeEventListener(eventListener.event,
                                               eventListener.handler, false);
    }
}

function myRemoveEventListener(node, event, handler)
{
    removeEventListenerIndex(findEventListener(node, event, handler));
}

function cleanupEventListeners()
{
    var i;
    for (i = eventListeners.length; i > 0; i--)
    {
        if (eventListeners[i] != undefined)
        {
            removeEventListenerIndex(i);
        }
    }
}
myAddEventListener(window, 'unload', cleanupEventListeners);

// This copyright statement applies to the following two functions,
// which are taken from MochiKit.
//
// Copyright 2005 Bob Ippolito <bob@redivi.com>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject
// to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

function hsvToRgb(hue, saturation, value, alpha)
{
    var red;
    var green;
    var blue;
    if (value == 0.0)
    {
        red = 0;
        green = 0;
        blue = 0;
    }
    else
    {
        var i = Math.floor(hue * 6);
        var f = (hue * 6) - i;
        var p = value * (1 - saturation);
        var q = value * (1 - (saturation * f));
        var t = value * (1 - (saturation * (1 - f)));
        switch (i)
        {
            case 1: red = q; green = value; blue = p; break;
            case 2: red = p; green = value; blue = t; break;
            case 3: red = p; green = q; blue = value; break;
            case 4: red = t; green = p; blue = value; break;
            case 5: red = value; green = p; blue = q; break;
            case 6: // fall through
            case 0: red = value; green = t; blue = p; break;
        }
    }
    return {r: red, g: green, b: blue, a: alpha};
}

function rgbToHsv(red, green, blue, alpha)
{
    var max = Math.max(Math.max(red, green), blue);
    var min = Math.min(Math.min(red, green), blue);
    var hue;
    var saturation;
    var value = max;
    if (min == max)
    {
        hue = 0;
        saturation = 0;
    }
    else
    {
        var delta = (max - min);
        saturation = delta / max;
        if (red == max)
        {
            hue = (green - blue) / delta;
        }
        else if (green == max)
        {
            hue = 2 + ((blue - red) / delta);
        }
        else
        {
            hue = 4 + ((red - green) / delta);
        }
        hue /= 6;
        if (hue < 0)
        {
            hue += 1;
        }
        if (hue > 1)
        {
            hue -= 1;
        }
    }
    return {
        h: hue,
        s: saturation,
        v: value,
        a: alpha
    };
}

function pageCoords(node)
{
    var x = node.offsetLeft;
    var y = node.offsetTop;
    var parent = node.offsetParent;
    while (parent != null)
    {
        x += parent.offsetLeft;
        y += parent.offsetTop;
        parent = parent.offsetParent;
    }
    return {x: x, y: y};
}

function initColorPicker(inputBox, satLumDiv, hueDiv, alphaDiv, previewDiv)
{
    var rgb, hsv
    
    function colorChanged()
    {
        if (OCE_savecolor)
        {
            var picker = document.getElementById('picker_text');
            OCE_recentcolors.unshift(parseInt(picker.value, 16));
            OCE_recentcolors.pop();
            OCE_updaterecentcolors();
            OCE_savecolor = false;
        }
        var hex = rgbToHex(rgb.r, rgb.g, rgb.b);
        var hex2 = argbToHex(rgb.a, rgb.r, rgb.g, rgb.b);
        var hueRgb = hsvToRgb(hsv.h, 1, 1, 0);
        var hueHex = rgbToHex(hueRgb.r, hueRgb.g, hueRgb.b);
        previewDiv.style.background = hex;
        /*@cc_on
        var a255 = Math.round(rgb.a*255);
        previewDiv.style.filter = a255 == 0 || a255 == 255 ? '' : 'alpha(opacity='+Math.round(100*a255/255)+')';
        if (false) @*/
        previewDiv.style.opacity = rgb.a;
        inputBox.value = hex2;
        satLumDiv.style.background = hueHex;
        alphaDiv.style.background = hex;
        crossHairs.style.left = ((hsv.v*199)-2).toString() + 'px';
        crossHairs.style.top = (((1-hsv.s)*199)+34).toString() + 'px';
        huePos.style.left = ((hsv.h*199)-1).toString() + 'px';
        alphaPos.style.left = ((rgb.a*199)-1).toString() + 'px';
    }
    function rgbChanged()
    {
        hsv = rgbToHsv(rgb.r, rgb.g, rgb.b, rgb.a);
        colorChanged();
    }
    function hsvChanged()
    {
        rgb = hsvToRgb(hsv.h, hsv.s, hsv.v, rgb.a);
        colorChanged();
    }
    
    var crossHairs = document.getElementById('thumb_satlum');
    function satLumDragged(x, y)
    {
        hsv.s = 1-(y/199);
        hsv.v = (x/199);
        hsvChanged();
    }
    trackDrag(satLumDiv, satLumDragged)

    var huePos = document.getElementById('thumb_hues');
    function hueDragged(x, y)
    {
        hsv.h = x/199;
        hsvChanged();
    }
    trackDrag(hueDiv, hueDragged);
    
    var alphaPos = document.getElementById('thumb_alpha');
    function alphaDragged(x, y)
    {
        rgb.a = x/199;
        colorChanged();
    }
    trackDrag(alphaDiv, alphaDragged);

    function inputBoxChanged()
    {
        rgb = hexToArgb(inputBox.value, {r: 0, g: 0, b: 0, a: 0});
        rgbChanged();
    }
    myAddEventListener(inputBox, 'change', inputBoxChanged);
    
    inputBoxChanged();
}

function makeColorSelectors(ev)
{
    initColorPicker(
        document.getElementById('picker_text'),
        document.getElementById('picker_satlum'),
        document.getElementById('picker_hues'),
        document.getElementById('picker_alpha'),
        document.getElementById('picker_active'));
}

myAddEventListener(window, 'load', makeColorSelectors);

