/**
 * @author aminisi
 * 
 * コードの拝借元
 * ◇描写関連◇
 * Fussy's HOMEPAGE様( http://www2.starcat.ne.jp/~fussy/ )
 * 
 * ◇タブ関連◇
 * たつをのホームページ様( http://nais.to/~yto/ )
 * 
 * ◇汎用関数関連◇
 * Decoration HTML Room様( http://www2.ocn.ne.jp/~yoochan/decoration/ )
 * 
 */

// =====================================

// ■■ 変数定義 ■■

// ◇参照保持◇

var Map;
var Capture;

var Ground;
var Objects;
var Mark = new Array( 16 );

var Palettes;

var GroundPalette;
var ObjectPalette;
var MarkPalette;

// ◇定数◇

var SECTION_X_COUNT = 5;
var SECTION_Y_COUNT = 5;

var COLUMN_COUNT = 16 * SECTION_X_COUNT;
var ROW_COUNT    = 16 * SECTION_Y_COUNT;

var CellSize      = 9;
var LineWidth     = 1;
var BoldLineWidth = 2;

var SectionSize = 16 * ( CellSize + LineWidth ) + BoldLineWidth - LineWidth;


// ◇動作関係◇

var ActionCommand;             //左クリック時のコマンド
var RightActionCommand;        //右クリック時のコマンド

var CurrentRightActionCommand; //右クリック時のコマンド待避用

var IsMouseDown = 0;

var LastX;
var LastY;

var MarkNm = 0;

var GroundData = new Array( 6800 );
var ObjectData = new Array( 6800 );
var MarkData   = new Array( 16 );

// =====================================

function init()
{
    if (
         ( Capture       = document.getElementById('capture'     ) )
      && ( Map           = document.getElementById('maps'        ) )
      && ( Ground        = document.getElementById('ground'      ) )
      && ( Objects       = document.getElementById('objects'     ) )
      && ( Palettes      = document.getElementById('palettes'    ) )
      && ( GroundPalette = document.getElementById('ground-tbody') )
      && ( ObjectPalette = document.getElementById('object-tbody') )
      && ( MarkPalette   = document.getElementById('mark-tbody'  ) )
    )
    {
        // ▽スクリプト初期化
        CurrentRightActionCommand = spuit;

        ActionCommand      = putGround;
        RightActionCommand = CurrentRightActionCommand;

        if ( document.attachEvent ) //☆
        {
            Capture.attachEvent( 'onmousemove', mouseMove );
            Capture.attachEvent( 'onmousedown', mouseDown );
            Capture.attachEvent( 'onmouseup'  , mouseUp   );

            Map.attachEvent( 'onmousemove', mouseMove );
            Map.attachEvent( 'onmousedown', mouseDown );
            Map.attachEvent( 'onmouseup'  , mouseUp   );

            GroundPalette.attachEvent( 'onmousedown', groundPaletteClick );
            ObjectPalette.attachEvent( 'onmousedown', objectPaletteClick );
            MarkPalette  .attachEvent( 'onmousedown', markPaletteClick );

            document.body.attachEvent( 'onmouseenter' , mouseUp   );
        }
        else if ( document.addEventListener )
        {
            Capture.addEventListener( 'mousemove', mouseMove, false );
            Capture.addEventListener( 'mousedown', mouseDown, false );
            Capture.addEventListener( 'mouseup'  , mouseUp,   false );

            Map.addEventListener( 'mousemove'   , mouseMove, false );
            Map.addEventListener( 'mousedown'   , mouseDown, false );
            Map.addEventListener( 'mouseup'     , mouseUp  , false );

            GroundPalette.addEventListener( 'mousedown', groundPaletteClick, false);
            ObjectPalette.addEventListener( 'mousedown', objectPaletteClick, false);
            MarkPalette  .addEventListener( 'mousedown', markPaletteClick, false);

            document.body.addEventListener( 'mouseenter' , mouseUp,   false );

        }

        // ▽divで配置されたデータを変数に読み込む
        var count = 0;

        for ( var node = Ground.firstChild;   node;   node = node.nextSibling )
        {
            GroundData[ count++ ] = node.style.backgroundColor;
        }


        for ( var node = Objects.firstChild;   node;   node = node.nextSibling )
        {
            ObjectData[ node.id.slice( 1 ) - 0 ] = node;
        }


        for ( var i = 0; i < 16; i++ )
        {
            Mark[ i ]     = document.getElementById( 'Mark' + i );
            MarkData[ i ] = new Array( 6800 );

            for ( var node = Mark[ i ].firstChild; node; node = node.nextSibling )
            {
                MarkData[ i ][ node.id.slice( node.id.indexOf("_") + 1) - 0 ] = node;
            }
        }

        // ▽表示初期化
        startGroundMode();
        SelectTab(1);
        setPalettesPosition();
        
        window.onresize = setPalettesPosition; //☆
    }
    else
    {
        alert('初期化に失敗しました');
    }

}
// =====================================

// ■■ イベント処理 ■■

function mouseDown( event )
{
    var x = getMousePositionX( event );
    var y = getMousePositionY( event );

    setIcon();

    if ( isRightClick( event ) )
    {
        IsMouseDown = 2;
    }
    else
    {
        IsMouseDown = 1;
    }

    var SectionSize = 16 * ( CellSize + LineWidth ) + BoldLineWidth - LineWidth

    LastX = Math.floor( x / SectionSize ) * 16 +  Math.floor(  ( x % SectionSize  ) / ( CellSize + LineWidth )  ) ;
    LastY = Math.floor( y / SectionSize ) * 16 +  Math.floor(  ( y % SectionSize  ) / ( CellSize + LineWidth )  );

    if ( LastX < 0 ) LastX = 0;
    if ( LastY < 0 ) LastY = 0;
    if ( LastX > COLUMN_COUNT -1 ) LastX = COLUMN_COUNT - 1;
    if ( LastY >    ROW_COUNT -1 ) LastY =    ROW_COUNT - 1;

    if ( IsMouseDown == 1 )
    {
        ActionCommand( LastX, LastY );
    }
    else
    {
        RightActionCommand( LastX, LastY );
    }
    
    return false;
}

//------------------

function mouseMove( event )
{
    if ( IsMouseDown == 0 ) return;

    x = getMousePositionX( event );
    y = getMousePositionY( event );


    x = Math.floor( x / SectionSize ) * 16 +  Math.floor(  ( x % SectionSize  ) / ( CellSize + LineWidth )  );
    y = Math.floor( y / SectionSize ) * 16 +  Math.floor(  ( y % SectionSize  ) / ( CellSize + LineWidth )  );

    if ( x < 0 ) x = 0;
    if ( y < 0 ) y = 0;
    if ( x > COLUMN_COUNT -1 ) x = COLUMN_COUNT - 1;
    if ( y >    ROW_COUNT -1 ) y =    ROW_COUNT - 1;

    var sx = ( x > LastX ) ? 1 : -1;
    var sy = ( y > LastY ) ? 1 : -1;
    var dx = ( x > LastX ) ? x - LastX : LastX - x;
    var dy = ( y > LastY ) ? y - LastY : LastY - y;

    var E;
    var x3=LastX;
    var y3=LastY;

    if ( dx >= dy )
    {
        E = -dx;
        for( var i=0; i<=dx; i++ )
        {
            if ( IsMouseDown == 1 )
            {
                ActionCommand( x3, y3 );
            }
            else
            {
                RightActionCommand( x3, y3 );
            }

            x3 += sx;
            E += 2 * dy;

            if ( E>=0 )
            {
                y3 += sy;
                E -= 2 * dx;
            }
        }
    }
    else
    {
        E =-dy;
        for( var i=0; i<=dy; i++)
        {
            if ( IsMouseDown == 1 )
            {
                ActionCommand( x3, y3 );
            }
            else
            {
                RightActionCommand( x3, y3 );
            }

            y3 += sy;
            E += 2 * dx;
            if ( E>=0 )
            {
                x3 += sx;
                E -= 2 * dy;
            }
        }
    }

    LastX = x;
    LastY = y;

    return false;
}

function mouseUp( event )
{
    IsMouseDown = 0;
    
    return false;
}

// -----------------

function groundPaletteClick ( event )
{
    var node  = getEventTargetNode( event );

    if ( node.nodeName.toLowerCase() != 'td' ) return;


    if ( isRightClick( event ) )
    {   // ▽パレットに保存
        if ( !document.tileForm.mode[ 0 ].checked )
        {
            alert('異なるパレットには保存できません');
            return;
        }
    
        if ( node.hasChildNodes() )
            node.removeChild( node.firstChild );

        node.appendChild(  document.createTextNode(" ")  );
        node.style.backgroundColor = document.tileForm["bgColor"].value;
    }
    else
    {   // ▽パレットを使用
        document.tileForm["bgColor"].value = node.style.backgroundColor;
        document.tileForm.mode[ 0 ].click();
    }
}

// -----------------

function objectPaletteClick ( event )
{
    var node  = getEventTargetNode( event );

    if ( node.nodeName.toLowerCase() != 'td' ) return;


    if ( isRightClick( event ) )
    {   // ▽パレットに保存
        if ( !document.tileForm.mode[ 1 ].checked )
        {
            alert('異なるパレットには保存できません');
            return;
        }
    
        if ( node.hasChildNodes() )
            node.removeChild( node.firstChild );

        node.appendChild(  document.createTextNode( document.tileForm["Char"].value )  );
        node.style.color           = document.tileForm["fontColor"].value;
        node.style.backgroundColor = document.tileForm["bgColor"  ].value;
    }
    else
    {   // ▽パレットを使用
        document.tileForm["Char"     ].value      = (node.firstChild != null ? node.firstChild.nodeValue: ' ');
        document.tileForm["fontColor"].value = node.style.color;
        document.tileForm["bgColor"  ].value   = node.style.backgroundColor;

        document.tileForm.mode[ 1 ].click();
    }
}

// -----------------

function markPaletteClick ( event )
{
    var node  = getEventTargetNode( event );

    if ( node.nodeName.toLowerCase() != 'td' ) return;

    if ( isRightClick( event ) )
    {
/*
        // ▽パレットに保存
        if ( !document.tileForm.mode[ 2 ].checked )
        {
            alert('異なるパレットには保存できません');
            return;
        }
    
        if ( node.hasChildNodes() )
            node.removeChild( node.firstChild );

        node.appendChild(  document.createTextNode( document.tileForm["Char"].value )  );
        node.style.color = document.tileForm["fontColor"].value;
        
        replaceMarks(
            node.cellIndex  +  MarkPalette.rows[ 0 ].cells.length * node.parentElement.rowIndex
          , document.tileForm["Char"     ].value
          , document.tileForm["fontColor"].value
        );
*/
        if (node.style.backgroundColor == 'white') {
            node.style.backgroundColor = 'lightsteelblue';
            Mark[node.cellIndex + MarkPalette.rows[0].cells.length * node.parentElement.rowIndex].style.display = 'none';
        }
        else
        {
            node.style.backgroundColor = 'white';
            Mark[node.cellIndex + MarkPalette.rows[0].cells.length * node.parentElement.rowIndex].style.display = 'block';
        }
    }
    else
    {   // ▽パレットを使用
        MarkNm = node.cellIndex  +  MarkPalette.rows[ 0 ].cells.length * node.parentElement.rowIndex;

        document.tileForm["Char"     ].value      = ( node.firstChild != null ? node.firstChild.nodeValue : ' '  );
        document.tileForm["fontColor"].value = node.style.color;

        document.tileForm.mode[ 2 ].disabled = false;
        document.tileForm.mode[ 2 ].click();
    }
}

// -----------------

function setIcon()
{
    var node = document.getElementById('stamp');


    if ( node.hasChildNodes() )
        node.removeChild( node.firstChild );


    if ( !document.tileForm["Char"].disabled )
    {
        node.appendChild(  document.createTextNode( document.tileForm["Char"].value )  );

        node.style.color = document.tileForm["fontColor"].value;
    }
    else
    {
        node.appendChild(  document.createTextNode(" ")  );
    }

    
    if ( !document.tileForm["bgColor"].disabled )
        node.style.backgroundColor = document.tileForm["bgColor"].value;
    else
        node.style.backgroundColor = "white";

    // ▽マーク書き換え時はパレットに反映
    
    if ( ActionCommand == putMark )
    {
        var cell = MarkPalette.rows[ Math.floor( MarkNm / 8 ) ].cells[ MarkNm % 8 ];
        
        if ( document.tileForm["Char"     ].value      != ( cell.innerText || cell.textContent || ' ' )
          || document.tileForm["fontColor"].value != cell.style.color 
        )
        {
            if ( cell.hasChildNodes() )
                cell.removeChild( cell.firstChild );

            cell.appendChild(  document.createTextNode( document.tileForm["Char"].value )  );
            cell.style.color = document.tileForm["fontColor"].value;
            
            replaceMarks( 
                MarkNm, 
                document.tileForm["Char"     ].value,
                document.tileForm["fontColor"].value
            );
                
        }

    }

}

// -----------------

//TODO:checkEnterKeyに変更
function setIcon2( e )
{
    if ( e.keyCode == 13 ) setIcon();

}

// =====================================

// ■■ モード切替 ■■

function startGroundMode()
{
    document.tileForm["Char"     ].disabled = true;
    document.tileForm["fontColor"].disabled = true;
    document.tileForm["bgColor"  ].disabled = false;

    document.tileForm.mode[ 2 ].disabled = true;

    ActionCommand      = putGround;
    RightActionCommand = CurrentRightActionCommand;

    setIcon();
}

// -----------------

function startObjectMode()
{
    document.tileForm["Char"     ].disabled = false;
    document.tileForm["fontColor"].disabled = false;
    document.tileForm["bgColor"  ].disabled = false;

    document.tileForm.mode[ 2 ].disabled = true;

    ActionCommand      = putObject;
    RightActionCommand = CurrentRightActionCommand;

    setIcon();
}

// -----------------

function startMarkMode()
{
    document.tileForm["Char"     ].disabled = false;
    document.tileForm["fontColor"].disabled = false;
    document.tileForm["bgColor"  ].disabled = true;

    ActionCommand      = putMark;
    RightActionCommand = CurrentRightActionCommand;

    setIcon();
}

// -----------------

function startRemoveObjectMode()
{
    document.tileForm["Char"].value = "削除";

    document.tileForm["Char"     ].disabled = true;
    document.tileForm["fontColor"].disabled = true;
    document.tileForm["bgColor"  ].disabled = true;

    document.tileForm.mode[ 2 ].disabled = true;

    ActionCommand      = removeObject;
    RightActionCommand = CurrentRightActionCommand;

    setIcon();
}

// -----------------

function startRemoveMarkMode()
{
    if ( ActionCommand != putMark )
    {
        alert('削除するマークを選択してからクリックしてください');
        return;
    }

    document.tileForm["Char"].value ="削除";

    document.tileForm["Char"     ].disabled = true;
    document.tileForm["fontColor"].disabled = true;
    document.tileForm["bgColor"  ].disabled = true;

    ActionCommand      = removeMark;
    RightActionCommand = CurrentRightActionCommand;


    setIcon();
}

// -----------------

function startPaletteMoveMode()
{
    document.tileForm["Char"].value ="移動";

    document.tileForm["Char"     ].disabled = true;
    document.tileForm["fontColor"].disabled = true;
    document.tileForm["bgColor"  ].disabled = true;

    document.tileForm.mode[ 2 ].disabled = true;

    ActionCommand      = movePalette;
    RightActionCommand = CurrentRightActionCommand;

    setIcon();
}

// -----------------

var IsPush;
var MoveTo;

function startMoveCellsMode( isPush, moveTo )
{
    IsPush = isPush;
    MoveTo = moveTo;

    document.tileForm["Char"].value = ( IsPush ? '引' : '押' ) + moveTo;

    document.tileForm["Char"     ].disabled = true;
    document.tileForm["fontColor"].disabled = true;
    document.tileForm["bgColor"  ].disabled = true;

    document.tileForm.mode[ 2 ].disabled = true;

    ActionCommand      = moveCells;
    RightActionCommand = moveCellsReverse;

    setIcon();
}


// =====================================

// ■■ ActionCommand ■■

function putGround ( x, y, color )
{
    if ( color == undefined ) color = document.tileForm["bgColor"].value;

    Ground.childNodes[ y * COLUMN_COUNT  + x ].style.backgroundColor = color;

    setGround( x, y, color );
}

// -----------------

function putObject( x, y, str, color, bgColor )
{
    if ( str     == undefined ) str     = document.tileForm["Char"     ].value;
    if ( color   == undefined ) color   = document.tileForm["fontColor"].value;
    if ( bgColor == undefined ) bgColor = document.tileForm["bgColor"  ].value;


    var oldObject = getObject( x, y );

    if ( oldObject != undefined )
    {
        Objects.removeChild( oldObject );
    }


    var div = document.createElement('DIV');

    div.appendChild(  document.createTextNode( str )  );

    div.id          = 'o' + ( y * COLUMN_COUNT + x );
    div.style.left  = x * ( CellSize + LineWidth) + Math.floor( x / 16 );
    div.style.top   = y * ( CellSize + LineWidth) + Math.floor( y / 16 );

    div.style.color           = color;
    div.style.backgroundColor = bgColor;

    Objects.appendChild( div );

    setObject( x, y, div );
}

// -----------------

function removeObject( x, y )
{
    var oldObject = getObject( x, y );

    if ( oldObject != undefined )
    {
        Objects.removeChild( oldObject );
    }

    setObject( x, y, undefined );
}

// -----------------

function putMark( x, y, mn, str, color )
{
    if ( mn    == undefined ) mn    = MarkNm;
    if ( str   == undefined ) str   = document.tileForm["Char"     ].value;
    if ( color == undefined ) color = document.tileForm["fontColor"].value;

    var oldMark = getMark( x, y, mn );

    if ( oldMark != undefined )
    {
        Mark[ mn ].removeChild( oldMark );
    }

    var div = document.createElement('DIV');


    div.appendChild(  document.createTextNode( str )  );


    div.id          = 'm' + mn + "_" + ( y * COLUMN_COUNT + x ) ;

    div.style.left  = x * ( CellSize + LineWidth) + Math.floor( x / 16 );
    div.style.top   = y * ( CellSize + LineWidth) + Math.floor( y / 16 );

    div.style.color           = color;
    div.style.backgroundColor = "transparent";


    Mark[ mn ].appendChild( div );

    setMark( x, y, mn, div );
}

// -----------------

function removeMark( x, y, mn )
{
    if ( mn == undefined ) mn = MarkNm;

    var oldMark = getMark( x, y, mn );

    if ( oldMark != undefined )
    {
        Mark[ mn ].removeChild( oldMark );
    }

    setMark( x, y, mn, undefined );
}

// -----------------


function movePalette( x, y )
{
    moveDivTo(
        Palettes
      , x * ( CellSize + LineWidth) + Math.floor( x / 16 )
      , y * ( CellSize + LineWidth) + Math.floor( y / 16 )  
    );

    IsMouseDown = 0;
}

// -----------------

var SpuitX;
var SpuitY;

function spuit( x, y )
{
    SpuitX = x;
    SpuitY = y;

    document.tileForm["Char"     ].disabled = true;
    document.tileForm["fontColor"].disabled = true;
    document.tileForm["bgColor"  ].disabled = true;

    ActionCommand = pasteCell;

    for ( var i = 0;  i < 16;  i++  )
    {
        var mark = getMark( x, y, i );

        if ( mark != undefined )
        {
            document.tileForm["Char"     ].value = mark.innerText || mark.textContent || ' ';
            document.tileForm["fontColor"].value = mark.style.color;
            document.tileForm["fontColor"].value = getGround( x, y )
            
            setIcon();
            return;
        }
    }
    
    var obj = getObject( x, y );
    
    if ( obj != undefined )
    {
        document.tileForm["Char"     ].value = obj.innerText || obj.textContent || ' ';
        document.tileForm["fontColor"].value = obj.style.color;
        document.tileForm["bgColor"  ].value = obj.style.backgroundColor;
        
        setIcon();
        return;
    }
    
    document.tileForm["bgColor"].value = getGround( x, y );
    setIcon();

    IsMouseDown = 0;
}

function pasteCell( x, y )
{
    // ▽削除による初期化処理
    resetCell( x, y );

    // ▽コピー処理
    for ( var i = 0;  i < 16;  i++  )
    {
        var mark = getMark( SpuitX, SpuitY, i );
        
        if ( mark != undefined )
        {
            putMark( x, y, i
              , (  mark.innerText || mark.textContent || ' '  )
              , mark.style.color
            );
        }
    }
    
    var copyObj = getObject( SpuitX, SpuitY );
    
    if ( copyObj != undefined )
    {
        putObject( 
            x, y
          , (  copyObj.innerText || copyObj.textContent || ' '  )
          , copyObj.style.color
          , copyObj.style.backgroundColor
        );
    }

    putGround( x, y, getGround( SpuitX, SpuitY ) );


}

// ○現在未使用
function spuit2( x, y )
{

    for ( var i = 0;  i < 16;  i++  )
    {
        var mark = getMark( x, y, i );
    
        if ( mark != undefined )
        {
            document.tileForm["Char"     ].disabled = false;
            document.tileForm["fontColor"].disabled = false;
            document.tileForm["bgColor"  ].disabled = true;

            document.tileForm["Char"     ].value = mark.innerText || mark.textContent || ' ';
            document.tileForm["fontColor"].value = mark.style.color;
            document.tileForm["bgColor"  ].value = getGround( x, y );

            MarkNm = i;
            
            startMarkMode();
            
            return;
        }
    }

    var obj = getObject( x, y );

    if ( obj != undefined )
    {
        document.tileForm["Char"     ].disabled = false;
        document.tileForm["fontColor"].disabled = false;
        document.tileForm["bgColor"  ].disabled = false;

        document.tileForm["Char"     ].value = obj.innerText || obj.textContent || ' ';
        document.tileForm["fontColor"].value = obj.style.color;
        document.tileForm["bgColor"  ].value = obj.style.backgroundColor;
        
        startObjectMode();
    }
    else
    {
        document.tileForm["Char"     ].disabled = true;
        document.tileForm["fontColor"].disabled = true;
        document.tileForm["bgColor"  ].disabled = false;

        document.tileForm["bgColor"].value = getGround( x, y );

        startGroundMode();
    }
}


function resetCell( x, y )
{
    for ( var i = 0;  i < 16;  i++  )
    {
        var mark = getMark( x, y, i );
        
        if ( mark != undefined )
        {
            removeMark( x, y , i );
        } 
    }
    
    var obj = getObject( x, y )
    
    if ( obj != undefined )
    {
        removeObject( x, y );
    }
    
    putGround( x, y, 'white' )
}


// =====================================

// ■■ 保存 ■■

function concatGroundData()
{
    var hash = {};
    var colorIndex = 0;

    var concatData = "";


    for ( var i = 0; i < COLUMN_COUNT * ROW_COUNT; i++ )
    {
        var color = (  GroundData[ i ] || "white"  );
        color     = color.replace( "," ,  "&#2c;" );

        if (  !( color in hash )  )
            hash[ color ] = colorIndex++;

        concatData = concatData + hash[ color ] + ",";
    }

    var groundColors = "";

    for ( var key in hash )
    {
        groundColors += ( key == '' ? "white" : key )  + ",";
    }

    return "groundColors=" + encodeURIComponent(  groundColors.slice( 0, -1 )  )
        + "&groundData="   + encodeURIComponent(  concatData  .slice( 0, -1 )  );
}

// -----------------

function concatObjectData()
{
    var hash = {}
    var objectIndex = 0;
    var objectHash  = {};

    var concatData = "";


    for ( var i = 0; i < ObjectData.length ; i++ )
    {
        if ( ! ObjectData[ i ] ) continue;

        var character = (  ObjectData[ i ].innerText || ObjectData[ i ].textContent || ' '  );
        var color     = ObjectData[ i ].style.color;
        var bgColor   = ObjectData[ i ].style.backgroundColor;

        var key = character.replace( "," ,  "&#2c;" ) + ","
                + color    .replace( "," ,  "&#2c;" ) + ","
                + bgColor  .replace( "," ,  "&#2c;" );

        if (  !( key in hash )  )
        {
            hash[ key ]       = objectIndex++;
            objectHash[ key ] = "";
        }

        objectHash[ key ] += + i + ",";
    }


    var returnValue = "";

    for ( var key in hash )
    {
        returnValue += "o" + hash[ key ] + "=" + encodeURIComponent(  key + "," + objectHash[ key ].slice( 0, -1 )  ) + "&";
    }


    if ( returnValue != "" )
    {
        return returnValue.slice( 0, -1 );
    }
    else
    {
        return "o1=";
    }
}

// -----------------

function concatMarkData()
{
    var concatData = "";

    for ( var r = 0; r < MarkPalette.rows.length; r++ )
    {
        for ( var c = 0; c < MarkPalette.rows[ r ].cells.length; c++ )
        {
            var cell = MarkPalette.rows[ r ].cells[ c ];
            
            var character = (  cell.innerText || cell.textContent || ' '  ).replace( "," ,  "&#2c;" );
            var color     = cell.style.color.replace( "," ,  "&#2c;" );

            var concatString = "";


            for ( var i = 0 ; i < MarkData[ r * 8 + c ].length; i++ )
            {
                if ( MarkData[ r * 8 + c ][ i ] != undefined )
                    concatString += i + ",";
            }

            concatData += "m" + ( r * 8 + c ) + "="
                       + encodeURIComponent(  character + "," + color + "," + concatString.slice( 0, -1 )  ) + "&";
        }
    }

    return concatData.slice( 0, -1 );
}

// -----------------

function concatGroundPaletteData()
{
    var returnValue = "";

    for ( var i=0; i < GroundPalette.rows.length; i++ )
    {
        for ( var j=0; j < GroundPalette.rows[ i ].cells.length; j++ )
        {
            returnValue += GroundPalette.rows[ i ].cells[ j ].style.backgroundColor.replace( "," ,  "&#2c;" ) + ',';
        }
    }

    return "groundPalette=" + encodeURIComponent(  returnValue.slice( 0, -1 )  );
}

// -----------------

function concatObjectPaletteData()
{
    var chars    = "";
    var colors   = "";
    var bgColors = "";


    for ( var i=0; i < ObjectPalette.rows.length; i++ )
    {
        for ( var j=0; j < ObjectPalette.rows[ i ].cells.length; j++ )
        {
            var cell = ObjectPalette.rows[ i ].cells[ j ];
            
            chars    += (  cell.innerText || cell.textContent || ' '  ).replace( "," ,  "&#2c;" ) + ",";
            colors   += cell.style.color          .replace( "," ,  "&#2c;" ) + ',';
            bgColors += cell.style.backgroundColor.replace( "," ,  "&#2c;" ) + ',';
        }
    }

    return "OPchar="   + encodeURIComponent(  chars   .slice( 0, -1 )  )
         + "&OPcolor=" + encodeURIComponent(  colors  .slice( 0, -1 )  )
         + "&OPbgc="   + encodeURIComponent(  bgColors.slice( 0, -1 )  );
}

// =====================================
// ■ 汎用関数 ■


function getMousePositionX( event )
{ 
    if ( !event ) var event = window.event;

    if ( window.opera )
    {                        // Opera
        return ( document.documentElement ? window.pageXOffset : 0 ) + event.clientX;
    } 
    else if ( event.pageX )
    {                        // Mozilla, NN4, Safari
        return event.pageX; 
    }
    else if ( event.clientX )
    {                        // IE, others
        var sl = 0;
        
        if ( document.documentElement && document.documentElement.scrollLeft )
        {
            sl = document.documentElement.scrollLeft;
        }
        else if ( document.body && document.body.scrollLeft )
        {
            sl = document.body.scrollLeft;
        }
        else if ( window.scrollX || window.pageXOffset ) 
        {
            sl = ( window.scrollX || window.pageXOffset );
        }
        return sl + event.clientX;         
    }
    return 0;
} 

// -----------------

function getMousePositionY( event )
{ 
    if ( !event ) var event = window.event;
    
    if ( window.opera )
    {                        // Opera
        return ( document.documentElement ? window.pageYOffset : 0 ) + event.clientY;
    }
    else if (event.pageY)
    {                        // Mozilla, NN4, Safari
        return event.pageY; 
    }
    else if ( event.clientY )
    {                        // IE, others
        var st=0;
        
        if ( document.documentElement && document.documentElement.scrollTop )
        {
            st = document.documentElement.scrollTop;
        }
        else if ( document.body && document.body.scrollTop )
        {
            st = document.body.scrollTop;
        }
        else if ( window.scrollY || window.pageYOffset )
        {
            st = ( window.scrollY || window.pageYOffset );
        }
        return st + event.clientY;
    }
    return 0;
}

function isRightClick( event )
{
    if (
        (  event.button & 2  &&  ( document.all || document.getElementById )  )
     || document.layers && event.which == 3
    )
    {
        return true;
    }

}

function getEventTargetNode( event )
{
    return (document.all ? event.srcElement : event.target );
}

// -----------------

function getWindowWidth()
{
    // ▽Mozilla, Opera, NN4
    if ( window.innerWidth )
        return window.innerWidth; 

    // ▽IE
    if ( document.documentElement
      && document.documentElement.clientWidth )
    {
        return document.documentElement.clientWidth;
    }
    else if (document.body 
          && document.body.clientWidth )
    {
        return document.body.clientWidth;
    }
    return 0;
}

// -----------------

function getDivWidth( div )
{ 
  return document.layers?   div.clip.width
                        : ( div.offsetWidth || div.style.pixelWidth || 0 );
}



// -----------------

function moveDivTo( div, left, top )
{
    if ( document.layers ) // NN4
    {
        div.moveTo( left, top );
        return; 
    } // ▽IE5+, Mozilla, Opera 7
    if ( typeof div.style.left != "undefined"
     && typeof div.style.left == "string" )
    { 
        div.style.left = left + 'px';
        div.style.top  = top  + 'px';
    } // ▽IE4, Opera 6
    else if ( typeof div.style.pixelLeft != "undefined" )
    { 
        div.style.pixelLeft = left;
        div.style.pixelTop  = top;
    }
}

// ---------------------------

function setGround( x, y, color )
{
    GroundData[ y * COLUMN_COUNT + x ] = color;
}

// -----------------

function getGround( x, y )
{
    return GroundData[ y * COLUMN_COUNT + x ];
}

// ---------------------------

function setObject( x, y, div )
{
    ObjectData[ y * COLUMN_COUNT + x ] = div;
}

// -----------------

function getObject( x, y )
{
    return ObjectData[ y * COLUMN_COUNT + x ];
}

// ---------------------------

function setMark( x, y, nm, div )
{
    MarkData[ nm ][ y * COLUMN_COUNT + x ] = div;
}

// -----------------

function getMark( x, y, nm )
{
    return MarkData[ nm ][ y * COLUMN_COUNT + x ];
}

// -----------------

function setPalettesPosition()
{
    if(  getWindowWidth() < getDivWidth( Ground ) + getDivWidth( Palettes ) + 5 )
    {
        moveDivTo( Palettes, getWindowWidth() - getDivWidth( Palettes ) , 5 );
    }
    else
    {
        moveDivTo( Palettes, getDivWidth( Ground ) + 5, 5 );
    }
}

// -----------------

function replaceMarks( mn, str, color )
{
    for ( var i = 0 ; i < MarkData[ mn ].length; i++ )
    {
        if ( MarkData[ mn ][ i ] != undefined )
        {
            var node = MarkData[ mn ][ i ];

            if ( node.hasChildNodes() )
                node.removeChild( node.firstChild );

            node.appendChild(  document.createTextNode( str )  );
            node.style.color = color;
        }
    }
    
}

// -----------------

function output( s )
{
    document.getElementById('output').value += s + "\n";
}

// =====================================
// ■■ タブ処理 ■■


var nowTab=1;
var id_max=4;

function SelectTab( selected )
{
    if ( !document.getElementById) return;

    for ( var i = 0;  i <= id_max;  i++ )
    {
        if ( !document.getElementById( 'box' + i ) ) continue;

        if ( i == selected )
        {
            document.getElementById( 'box' + i  ).style.visibility = "visible";
            document.getElementById( 'box' + i  ).style.position   = "";
            document.getElementById( 'head' + i ).className        = "open";
        }
        else
        {
            document.getElementById( 'box'  + i ).style.visibility = "hidden";
            document.getElementById( 'box'  + i ).style.position   = "absolute";
            document.getElementById( 'head' + i ).className        = "close";
        }
    }
    nowTab = selected;
}

// =====================================
// ■■ AJAX ■■

var xmlhttp = null;

function Save()
{
    setTimeout( "Send()", 1 );

}

function Send()
{

    if ( initializeXMLHttp() )
    {
        xmlhttp.onreadystatechange = Receive;
        xmlhttp.open('POST', './MuraMapper.cgi',true);
        xmlhttp.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");
        //xmlhttp.setRequestHeader("If-Modified-Since", last_modified);

        var sendData =
            concatGroundData() + "&" +
            concatObjectData() + "&" +
            concatMarkData()   + "&" +
            concatGroundPaletteData() + "&" +
            concatObjectPaletteData() + "&" +
            "ID="       + encodeURIComponent( document.save.ID.value ) +
            "&PASS="    + encodeURIComponent( document.save.PASS.value ) +
            "&private=" + encodeURIComponent( ( document.save.private.checked ? '1' : '' ) ) +
            "&Save=1&Ajax=1";

        output(       sendData );
        xmlhttp.send( sendData );

    }
    else
    {
        alert("XMLHttpRequest失敗");
    }
}

function Receive()
{
    if ( xmlhttp.readyState == 4  &&  xmlhttp.status == 200 )
    {
        if ( xmlhttp.responseText == 'OK' )
        {
            alert('更新完了');
        }
        else
        {
            alert( xmlhttp.responseText );
        }


        document.body.style.cursor = 'default';
    }
}

function initializeXMLHttp()
{
    if (xmlhttp != null)
    {
        xmlhttp.abort();
        return true;
    }
    else
    {
        try
        {
            if (typeof XMLHttpRequest != 'undefined')
            {
                xmlhttp = new XMLHttpRequest();
                return true;
            }
            else
            {
                xmlhttp = new ActiveXObject ("Microsoft.XMLHTTP");
                return true;
            }
        }
        catch( e )
        {
            return false;
        }
    }

    IsMouseDown = 0;
}




function moveCells( x, y )
{
    if ( !IsPush )
    {
        if      ( MoveTo == '↓' ){ moveIconY( x, 0               , y ); }
        else if ( MoveTo == '↑' ){ moveIconY( x, ROW_COUNT    - 1, y ); }
        else if ( MoveTo == '←' ){ moveIconX( y, COLUMN_COUNT - 1, x ); }
        else if ( MoveTo == '→' ){ moveIconX( y, 0               , x ); }
    }
    else
    {
        if      ( MoveTo == '↑' ){ moveIconY( x, y, 0                ); }
        else if ( MoveTo == '↓' ){ moveIconY( x, y, ROW_COUNT    - 1 ); }
        else if ( MoveTo == '→' ){ moveIconX( y, x, COLUMN_COUNT -1  ); }
        else if ( MoveTo == '←' ){ moveIconX( y, x, 0                ); }
    }
    IsMouseDown = 0;
}

function moveCellsReverse( x, y )
{
    if ( IsPush )
    {
        if      ( MoveTo == '↑' ){ moveIconY( x, 0               , y ); }
        else if ( MoveTo == '↓' ){ moveIconY( x, ROW_COUNT    - 1, y ); }
        else if ( MoveTo == '→' ){ moveIconX( y, COLUMN_COUNT - 1, x ); }
        else if ( MoveTo == '←' ){ moveIconX( y, 0               , x ); }
    }
    else
    {
        if      ( MoveTo == '↓' ){ moveIconY( x, y, 0                ); }
        else if ( MoveTo == '↑' ){ moveIconY( x, y, ROW_COUNT    - 1 ); }
        else if ( MoveTo == '←' ){ moveIconX( y, x, COLUMN_COUNT -1  ); }
        else if ( MoveTo == '→' ){ moveIconX( y, x, 0                ); }
    }

    IsMouseDown = 0;
}



function moveIconX( y, fromX, toX )
{
    if ( getObject( toX, y ) != undefined) removeObject( toX, y );

    for ( var mn = 0;  mn < 16;  mn++ )
    {
        if ( getMark( toX, y, mn ) != undefined) removeMark( toX, y, mn );
    }

    // ○上書きタイミングの関係で引く形で処理する
    var vec = ( toX < fromX ? 1 : -1 );

    for ( var i = toX;  i != fromX;  i += vec  )
    {
        var arg = y * COLUMN_COUNT  + i;
        
        // ▽地面色移動処理
        Ground.childNodes[ arg ].style.backgroundColor = Ground.childNodes[ arg + vec ].style.backgroundColor;
        GroundData[ arg ] = GroundData[ arg + vec ];
        
        // ▽オブジェクト移動処理
        
        var obj = getObject( i + vec , y );
        
        if ( obj != undefined )
        {
            moveDivTo( 
                obj, 
                i * ( CellSize + LineWidth) + Math.floor( i / 16 ),
                y * ( CellSize + LineWidth) + Math.floor( y / 16 )
            );
            
            setObject( i + vec, y, undefined );
            setObject( i      , y, obj       );
        }

        // ▽マーキング移動処理

        for ( var mn = 0;  mn < 16;  mn++)
        {
            var mark = getMark( i + vec, y, mn );
            
            if ( mark != undefined ) 
            {
                moveDivTo( 
                    mark, 
                    i * ( CellSize + LineWidth) + Math.floor( i / 16 ),
                    y * ( CellSize + LineWidth) + Math.floor( y / 16 )
                );
                
                setMark( i + vec, y, mn, undefined );
                setMark( i      , y, mn, mark      );
            }
        }
    }

    Ground.childNodes[ y * COLUMN_COUNT  + fromX ].style.backgroundColor = 'white';
    GroundData[        y * COLUMN_COUNT  + fromX ]                       = 'white';
}

function moveIconY( x, fromY, toY )
{
    if ( getObject( x, toY ) != undefined) removeObject( x, toY );

    for ( var mn = 0;  mn < 16;  mn++ )
    {
        if ( getMark( x, toY, mn ) != undefined) removeMark( x, toY, mn );
    }

    // ○上書きタイミングの関係で引く形で処理する
    var vec = ( toY < fromY ? 1 : -1 );

    for ( var i = toY;  i != fromY;  i += vec  )
    {
        var arg = i * COLUMN_COUNT  + x;
        
        // ▽地面色移動処理

        Ground.childNodes[ arg ].style.backgroundColor = Ground.childNodes[ arg + ( vec * COLUMN_COUNT ) ].style.backgroundColor;
        GroundData[ arg ]                              = GroundData[        arg + ( vec * COLUMN_COUNT ) ];
        
        // ▽オブジェクト移動処理
        
        var obj = getObject( x , i + vec );
        
        if ( obj != undefined )
        {
            moveDivTo( 
                obj, 
                x * ( CellSize + LineWidth) + Math.floor( x / 16 ),
                i * ( CellSize + LineWidth) + Math.floor( i / 16 )
            );
            
            setObject( x, i + vec, undefined );
            setObject( x, i      , obj       );
        }

        // ▽マーキング移動処理

        for ( var mn = 0;  mn < 16;  mn++ )
        {
            var mark = getMark( x, i + vec, mn );
            
            if ( mark != undefined ) 
            {
                moveDivTo( 
                    mark, 
                    x * ( CellSize + LineWidth) + Math.floor( x / 16 ),
                    i * ( CellSize + LineWidth) + Math.floor( i / 16 )
                );
                
                setMark( x, i + vec, mn, undefined );
                setMark( x, i      , mn, mark      );
            }
        }
    }

    Ground.childNodes[ fromY * COLUMN_COUNT  + x ].style.backgroundColor = 'white';
    GroundData[        fromY * COLUMN_COUNT  + x ]                       = 'white';
}

// ペイント処理

var buffer = new Array;

function StartPaintMode()
{
    PaintFlag = true;
    document.getElementById('paintButton').value = '塗りつぶし選択';
    document.getElementById('paintButton').disabled = true;
}

function paint( x , y)
{
    document.getElementById('paintButton').value = '塗りつぶし中';

    if( !document.getElementById('alertOff').checked )
        alert("塗りつぶしを開始します\n範囲が広い場合３０秒以上\n処理にかかることもあります");

    var tile =
        [
            (map.rows[y].cells[x].firstChild != null ? map.rows[y].cells[x].firstChild.nodeValue : '　'),
             map.rows[y].cells[x].style.color,
             map.rows[y].cells[x].style.backgroundColor
        ];

    var icon=
        [
            document.stamp.Char.value,
            document.stamp.fontColor.value,
            document.stamp.bgColor.value
        ]

    buffer.unshift([x,x,y,y]);

    do
    {
        var a = buffer.shift();

        var leftX   = a[0];
        var rightX  = a[1];
        var topY    = a[2];
        var bottomY = a[2];
        var parentY = a[3];

        var lLeftX  = leftX  -1;
        var lRightX = rightX +1;

        if( compare( icon, leftX, topY ) )continue;

        while( rightX < 63)
        {
            if ( !compare( tile, rightX +1, topY ) )break;
            rightX++;
        }

        while( leftX > 0 )
        {
            if ( !compare( tile, leftX -1, topY ) )break;
            leftX--;
        }

        for( var i=leftX; i<= rightX; i++)
        {
            putIcon( i, topY);
        }

        if( --topY >= 0 )
        {
            if( topY == parentY )
            {
                scanLine( leftX, lLeftX, topY, topY +1, tile);
                scanLine( lRightX, rightX, topY, topY +1, tile);
            }
            else
            {
                scanLine( leftX, rightX, topY, topY +1, tile);
            }
        }

        if ( ++bottomY <= 63 )
        {
            if( bottomY == parentY )
            {
                scanLine( leftX, lLeftX, bottomY, bottomY -1, tile);
                scanLine( lRightX, rightX, bottomY, bottomY -1, tile);
            }
            else
            {
                scanLine( leftX, rightX, bottomY, bottomY -1, tile);
            }
        }
    } while ( buffer.length > 0 );

    if( document.getElementById('repaint').checked )
    {
        document.getElementById('paintButton').value = '塗りつぶし選択';
    }
    else
    {
        PaintFlag = false;
        document.getElementById('paintButton').value = '塗りつぶし開始';
        document.getElementById('paintButton').disabled = false;
    }

}

function compare( tile,x, y)
{
    if ( tile[0] == (map.rows[y].cells[x].firstChild != null ? map.rows[y].cells[x].firstChild.nodeValue : '　') &&
         tile[1] ==  map.rows[y].cells[x].style.color &&
         tile[2] ==  map.rows[y].cells[x].style.backgroundColor )
    {
        return true;
    }
    else
    {
        return false;
    }
}


function scanLine( leftX, rightX, y, parentY, tile )
{

    while( leftX <= rightX )
    {
        while( leftX < rightX )
        {
            if( compare( tile, leftX, y) ) break;
            leftX++;
        }
        if( !compare( tile, leftX, y) ) break;

        var temp = leftX;

        while( leftX <= rightX )
        {
            if( !compare( tile, leftX, y ) ) break;
            leftX++;
        }

        buffer.unshift([temp, leftX-1, y, parentY]);

    }
}



function countIcon()
{
    var totalPoint = 0;

    var tree   = document.countForm["tree"  ].value.split(" ")
    var flower = document.countForm["flower"].value.split(" ");
        
    for ( var a = 0;  a < SECTION_X_COUNT;  a++ )
    {
        for ( var b = 0;  b < SECTION_Y_COUNT;  b++ )
        {
            var treeCount   = 0;
            var flowerCount = 0;
            
            for ( var x = a * 16;  x < a * 16 + 16;  x++ )
            {
                for ( var y = b * 16;  y < b * 16 + 16; y++ )
                {
                    var obj = getObject( x, y );
                    var txt = "";
                    if ( obj != undefined ) txt = obj.innerText || obj.textContent || ' ';
                                        
                    for ( var i = 0;  i < tree.length;  i++ )
                    {
                        if ( txt == tree[ i ] )
                        {
                            output("???\n\n")
                            treeCount++;
                            break;
                        }
                    }
                    
                    
                    for ( var i = 0;  i < flower.length;  i++ )
                    {
                        if ( txt == flower[ i ] )
                        {
                            flowerCount++;
                            break;
                        }
                    }
   
                }
            }
            
            document.countForm[ "T" + b + a ].value = treeCount;
            document.countForm[ "F" + b + a ].value = flowerCount;
                        
            var point = ( treeCount < 10 ? treeCount -10 : 0 ) + ( treeCount > 15 ? 15 - treeCount : 0 ) + flowerCount;
            if ( point > 3 ) point = 3;
            document.countForm[ "P" + b + a ].value = point;
            
            totalPoint += point;

        }
    }

    document.countForm["point"].value = totalPoint + ( totalPoint > 23 ? '(サイコー)' : '' );
}

