flash on 2012-2-25

by tepe
addChild(eb);
addChild(eb2);
var x1:uint = parseInt("0xffffffff");
oz.scaling(-1);
oz.scaling(1);

t2.text ="";
removeChild(eb3);

スコープ

if(tk.list[i].type=='}'){

t2.text = tk.func3(tk.list[i].pair);
t2.text = tk.getBlockText(tk.list[i].pair);
return;
var eb3:editorBase = new editorBase(i.toString(),tk.getBlockText(tk.list[i].pair));
addChild(eb3);
eb3.x=i*10;
}

if(tk.list[i].type=="space")continue;
t2.appendText(tk.list[i].tag+" "+tk.list[i].text+"\n");
------------------------------------------------------------------------------
package ozworks {
♥0 | Line 1153 | Modified 2012-03-10 09:48:38 | MIT License
play

ActionScript3 source code

/**
 * Copyright tepe ( http://wonderfl.net/user/tepe )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/4eux
 */

package {
    import flash.display.Sprite;
    import flash.events.*;
    public class FlashTest extends Sprite {//
        private var t1:TextEditor;
        private var oz:ozmap = new ozmap();
        public function FlashTest() {
            // write as3 code here..
            addChild(oz);
            oz.addEventListener(KeyboardEvent.KEY_DOWN,onKey);
            t1 = new TextEditor();
            t1.border = true;
            t1.z=0;
            oz.addObject(t1);
            
            var t2:TextEditor = new TextEditor();
            t2.border = true;
            t2.y = 120;
            t2.z = 0;
            oz.addObject(t2);
            oz.addObject(ss);
            var t3:TextEditor = new TextEditor();
            t3.border = true;
            t3.y = 240;
            t3.z = 0;
            oz.addObject(t3);
            
            t1.setNextTF(t2);
            t2.setPrevTF(t1);
            t2.setNextTF(t3);
            t3.setPrevTF(t2);
            var eb:editorBase = new editorBase();
            //addChild(eb);
            eb.x = 200;
            var eb2:editorBase = new editorBase();
            //addChild(eb2);
            t1.addEventListener(Event.CHANGE,onChange);
            //var x1:uint = parseInt("0xffffffff");

        }
        
        private function onKey(e:KeyboardEvent):void{
            if(e.keyCode== 13){
                oz.browseOff();
            }
            if(e.keyCode == 27){
                oz.browseOn();
            }
            
            if(e.keyCode == 40){
                //oz.scaling(-1);
            }
            else if(e.keyCode == 38){
                //oz.scaling(1);
            }




        }

        private var ss:Sprite = new Sprite();
        private function onChange(e:Event=null):void{//
            
            while(ss.numChildren > 0)ss.removeChildAt(0);  
            
            var cnt:int=0;
            var tk:token = new token();
            tk.getToken(t1.text);
            
            //t2.text ="";
            tk.func2();
            tk.setKeywordAS3();
            //removeChild(eb3);
            for(var i:int=0;i<tk.listLength;i++){
                
                if(tk.list[i].type=="keyword"){//
                    var str:String=tk.list[i].text;
                    var str2:String ="";
                    if(tk.list[i+2].type=="string")str += " "+tk.list[i+2].text;
                    if(tk.list[i].text == "function"){
                        while(tk.list[i].type!='{' && tk.list[i].type!=';' && i<tk.listLength){
                            i++;
                        }
                        if(tk.list[i].type=='{'){
                            str2 = tk.getBlockText(i);
                        }


                    }

                    var eb3:editorBase = new editorBase(str,str2);
                    eb3.z =0;
                    eb3.y =20*cnt;
                    ss.addChild(eb3);
                    eb3.addEventListener(MouseEvent.MOUSE_DOWN,oz.browseOff);
                    eb3.addEventListener(MouseEvent.MOUSE_UP,oz.browseOn);
                    cnt++;
                }
                //スコープ
                /*if(tk.list[i].type=='}'){
                    
                    //t2.text = tk.func3(tk.list[i].pair);
                    //t2.text = tk.getBlockText(tk.list[i].pair);
                    //return;
                    var eb3:editorBase = new editorBase(i.toString(),tk.getBlockText(tk.list[i].pair));
                    addChild(eb3);
                    //eb3.x=i*10;
                }*/
                //if(tk.list[i].type=="space")continue;
                //t2.appendText(tk.list[i].tag+" "+tk.list[i].text+"\n");
         
            }
            
        }
    }
}

//------------------------------------------------------------------------------

//package ozworks {
    

    import flash.geom.*;
    import flash.display.*;
    import flash.text.*;
    import flash.events.*;
    import flash.ui.*;

    //public 
    class ozmap extends Sprite{
        
        private var scale:Number = 1;
        
        public var wheel:int;//ホイール回転量
        private var zoom:Number = 1.0;//拡大率
        
        private var mapBase:Sprite;
        private var map:Sprite;//フィールド
        
        private var scrFocusX:Number=0; 
        private var scrFocusY:Number = 0;
        
        //マップエリア
        private var mapWidth:int;
        private var mapHeight:int;

        private var mapscale:int=0;
        
        private var dragPanel:Sprite = new Sprite();//オブジェクトの前
        private var dragField:Sprite = new Sprite();//オブジェクトより後ろ
                
        //ozmap状態フラグ
        private const testMode:Boolean = false;//テスト表示
        private var mapBrowseMode:Boolean;//マップ移動操作
        private var mapDragMode:Boolean;//マップドラッグ中はtrue
        private var mapRotationMode:Boolean;//マップ回転操作
        
        private var endZoomIn:int = -7;
        private var endZoomOut:int = 15;
        
        private var sizeX:Number;
        private var sizeY:Number;
       
        
        public function get mapX():Number {
            return map.mouseX;
        }
        public function get mapY():Number {
            return map.mouseY;
        }
        
        
        //コンストラクタ 
        public function ozmap():void {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
            
            mapWidth = 1200;
            mapHeight = 1000;
            mapBase = new Sprite();//ズーム中心
            
            if(testMode == true){ 
                with( mapBase.graphics ){
                    lineStyle(1,0x00ff00,0.3);
                    moveTo(-100,0);
                    lineTo(100,0);
                    moveTo(0,-100);
                    lineTo(0,100);
                }
            }
            
            addChild(mapBase);
            
            with(dragField.graphics){
                beginFill(0x0000ff,0.2);
                drawCircle(0,0,20);
                endFill();
            }
            


            //マップ上への配置
            map = new Sprite();
            map.addChild(dragField);
            if(testMode == true){
                var t3:TextField = new TextField();
                with(t3){
                    textColor = 0x0000ff;
                    selectable = false;
                    y = -20;
                    text = "map 0,0";
                }
                map.addChild(t3);
                with( map.graphics ){
                    lineStyle(1,0x0000ff,0.3);
                    moveTo(-100,0);
                    lineTo(100,0);
                    moveTo(0,-100);
                    lineTo(0,100);
                }
                var t5:TextField = new TextField();
                t5.textColor = 0xff0000;
                addChild(t5);
                addEventListener(Event.ENTER_FRAME, function():void {
                    var x:Number = mapX;
                    var y:Number = mapY;
                    
                    graphics.clear();
                    graphics.lineStyle(1, 0xff0000, 0.3);
                    graphics.drawCircle(mouseX, mouseY, 5*(map.scaleX*zoom));
                    graphics.moveTo(mouseX, mouseY);
                    graphics.lineTo(mouseX + 100, mouseY - 50);
                    graphics.lineTo(mouseX + 150, mouseY - 50);
                    t5.x = mouseX + 100; t5.y = mouseY - 50;
                    t5.text = "x:" + x.toString() + "\ny:" + y.toString();
                    t5.appendText("\nscale:" + map.scaleX*zoom);
                });
                
            } 
            
            browseOn();
 
            mapBase.addChildAt(map,0); 
            map.addChild(dragPanel);
            dragPanel.doubleClickEnabled = true;

            update();
    
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // スケールモードを「100 % 表示」に設定
            stage.scaleMode = StageScaleMode.NO_SCALE;
            mapWidth = stage.stageWidth;
            mapHeight = stage.stageHeight;
            // リサイズされたときに呼び出されるイベント
            stage.addEventListener(Event.RESIZE, function(e:Event):void{
                mapWidth = stage.stageWidth;
                mapHeight = stage.stageHeight;
            });
        }
        
        
        //オブジェクト追加
        public function addObject(s:DisplayObject=null):void {
            if (s == null) return;
            if (mapBrowseMode == true) {
                browseOff();
                map.addChild(s);
                browseOn();
            }
            else {
                map.addChild(s);
            }
            
        }
        public function removeObject(s:DisplayObject = null):void {
            if (s == null) return;
            if (mapBrowseMode == true) {
                browseOff();
                map.removeChild(s);
                browseOn();
            }
            else {
                map.removeChild(s);
            }
        }
        
        public function get scaleSize():int{
            return mapscale;
        }
        
        //マップ移動操作状態
        public function get IsBrowseMode():Boolean{
            return mapBrowseMode;
        }
        //マップドラッグスクロール状態
        public function get IsDragMode():Boolean{
            return mapDragMode;
        }        
        //マップ回転操作状態
        public function get IsRotationMode():Boolean{
            return mapRotationMode;
        }

        //
        public function returnHome():void{
            map.x = 0;
            map.y = 0;
            map.scaleX = map.scaleY = 1.0;
            mapscale = 0;
            update();
            
        }

        
        //画面移動操作の受付 ON・OFF切り替え
        public function browseOn():void {
            //Mouse.hide();//マウスカーソル非表示
            mapBrowseMode = true;
            map.addEventListener(MouseEvent.MOUSE_DOWN,down);
            map.addEventListener(MouseEvent.MOUSE_UP,up);
            dragPanel.addEventListener(MouseEvent.DOUBLE_CLICK,onDouble);
            this.addEventListener(MouseEvent.MOUSE_WHEEL,on_wheel,true);//ホイール操作 
            map.addChild(dragPanel);
        }
        public function browseOff():void {
            //Mouse.show();//マウスカーソル表示
            wheel = 0;
            mapBrowseMode = false;
            map.removeEventListener(MouseEvent.MOUSE_DOWN,down);
            map.removeEventListener(MouseEvent.MOUSE_UP,up);
            dragPanel.removeEventListener(MouseEvent.DOUBLE_CLICK,onDouble);
            this.removeEventListener(MouseEvent.MOUSE_WHEEL,on_wheel,true);//ホイール操作 
            map.removeChild(dragPanel);
        }
        
        //ダブルクリックでマップブラウズモード解除 ⇒ オブジェクト操作モードに移行
        private function onDouble(e:MouseEvent):void{
            browseOff();
            //ホイール操作でブラウズモードに移行
            stage.addEventListener(MouseEvent.MOUSE_WHEEL,function():void{
                browseOn();
            });
        }


  
        //マップドラッグ開始
        private function down(e:MouseEvent):void{
            wheel = 0;//ズーム操作ストップ
           e.currentTarget.startDrag();
           addEventListener(MouseEvent.MOUSE_MOVE,onMove);
           stage.removeEventListener(Event.ENTER_FRAME,onFrame);
           e.stopPropagation();//イベントの伝播を止める
           
        }
        
        private function up(e:MouseEvent):void {
            
            e.currentTarget.stopDrag();
            removeEventListener(MouseEvent.MOUSE_MOVE,onMove);
            e.stopPropagation();//イベントの伝播を止める

        }
        
        //マップドラッグ中
        private function onMove(e:MouseEvent):void{
            update();
        }

        //ホイール操作
        private function on_wheel(e:MouseEvent):void{  
            if(wheel == 0)update();
            wheel += e.delta;
            
            if(wheel != 0)addEventListener(Event.ENTER_FRAME,onFrame);
        }
        
        public function scaling(val:int=0):void{
            if(wheel == 0)update();
            wheel += val;
            if(wheel != 0)addEventListener(Event.ENTER_FRAME,onFrame);
        }

        
        //ホイール操作 ズーム
        private function onFrame(e:Event):void {
            if(wheel==0){
                removeEventListener(Event.ENTER_FRAME,onFrame);
            }
            on_zoom(1+(0.005*wheel));
        }
        
        
        //マップ表示位置を更新
        private function update(z:Number=1, x:Number=0, y:Number=0, a:Number=0):void{
            var mX:int,mY:int;
            
            if(1<=z){//ズームイン
                mX = mouseX;
                mY = mouseY;//カーソル位置 
            }
            else{//ズームアウト
                mX = this.root.loaderInfo.width/2;
                mY = this.root.loaderInfo.height / 2;//カーソル位置
            }
            
            //ズーム中心
            mapBase.x = mX;
            mapBase.y = mY; 
            //マップ位置
            map.x -= (mX-scrFocusX)/zoom;
            map.y -= (mY-scrFocusY)/zoom;
            //フォーカス位置
            scrFocusX = mX;
            scrFocusY = mY;
            
            dragField.x = map.mouseX;
            dragField.y = map.mouseY;
            
            //フィールドドラッグ用
            with(dragPanel.graphics){
                clear();
                beginFill(0xff0000, 0.2);
                drawCircle( -map.x/map.scaleX, -map.y/map.scaleY, 1200/(zoom*map.scaleX) );
                
                endFill();
            }
            //グリッドライン描画
            if(false){
                var i:int;
                var c:uint = 0x00aa00;
                const j:int = 32;
                with (dragPanel.graphics) {
                    
                    //横線
                    for(i= -20-(map.y/j);i<20-(map.y/j);i++){
                        if(Math.abs(i)%2 == 1)lineStyle(0,c,(zoom*0.5)-0.5);
                        else lineStyle(0,c,0.5);
                        moveTo((-600-map.x-mouseX)/map.scaleX , i*j/map.scaleX);
                        lineTo((1600-map.x-mouseX)/map.scaleX , i*j/map.scaleX);
                    }
                    //縦線
                    for(i=-20-(map.x/j);i<20-(map.x/j);i++){
                        if(Math.abs(i)%2 == 1)lineStyle(0,c,(zoom*0.5)-0.5);
                        else lineStyle(0,c,0.5);
                        moveTo(i*j/map.scaleX, (-600-map.y)/map.scaleX);
                        lineTo(i*j/map.scaleX, (1600-map.y)/map.scaleX);
                    }
                }
            }
      
        }

        //ズーム処理
        private function on_zoom(z:Number=0):void{
            if (z == 0) return;
            if(z>1 && endZoomIn > mapscale){
                wheel = 0;
            }
            else if(z<1 && endZoomOut < mapscale){
                wheel = 0;
            }
            else zoom *= z; 
   
                
            if(2 < zoom){
                with(map){
                    x+=x; y+=y;
                    scaleX = scaleY *= 2;
                }
                zoom /= 2;      
                mapscale--;
                
            }
            else if(zoom < 1.0){
                with(map){
                    x-=x/2; y-=y/2;
                    scaleX = scaleY /= 2;
                }        
                zoom *= 2;    
                mapscale++;
                    
            }
            
            with(mapBase){
                scaleX = scaleY = zoom;
            }
            update(z);//基準点更新      
          
        }
  
    }
//}
//------------------------------------------------------


import flash.display.*;
import flash.events.*;
import flash.text.*;
class editorBase extends Sprite{
    private var color1:uint = 0xdddddd;
    private var color2:uint = 0x00ff00;
    private var s1:Sprite = new Sprite();
    private var tytle:TextEditor = new TextEditor();
    private var source:TextEditor = new TextEditor();
    private var btn:Sprite = new Sprite();
    private var mode:String = new String();
    public function editorBase(name:String="tytle",t:String=""){
        //mode = "open";
        tytle.setNextTF(source);
        source.setPrevTF(tytle);
        source.type = "input";
        source.y = 20;
        source.text = t;
        source.width = 400;
        source.height = source.textHeight+20;
        tytle.text = name;
        tytle.doubleClickEnabled = true;
        //tytle.type = "input";
        tytle.selectable = false;
        tytle.height = 20;
        tytle.width = tytle.textWidth+20;
        s1.addChild(tytle);
        addChild(s1);
        func1();
        addEventListener(MouseEvent.MOUSE_DOWN,onDown);
        addEventListener(MouseEvent.DOUBLE_CLICK,onDouble);
     
    }
    private function onDouble(e:MouseEvent):void{
        this.tytle.type = "input";
        this.tytle.selectable = true;
        stage.focus = this.tytle;
        if(mode != "open")func2();
        else func1();
        
        
    }

    private function onDown(e:MouseEvent):void{
        e.currentTarget.startDrag();
        var _parent:DisplayObjectContainer = this.parent;
        this.parent.removeChild(this);
        _parent.addChild(this);
        //this.parent.addChild(this);
        addEventListener(MouseEvent.MOUSE_UP,onUp);
    }
    private function onUp(e:MouseEvent):void{
        e.currentTarget.stopDrag();
        removeEventListener(MouseEvent.MOUSE_UP,onUp);
    }
    
    private function onFocus():void{
        if(mode == "open"){
            s1.graphics.clear();
            s1.graphics.beginFill(color2,0.8);
            s1.graphics.drawRect(0,0,tytle.width,tytle.height);
            s1.graphics.drawRect(0,20,source.width,source.height);
            s1.graphics.endFill();
        }
        else{
            s1.graphics.clear();
            s1.graphics.beginFill(color2,0.8);
            s1.graphics.drawRoundRect(0,0,tytle.width,tytle.height,15,15);
            s1.graphics.endFill();
        }


    }
    public var next:editorBase;
    public var prev:editorBase;
    private function move(e:KeyboardEvent):void{
        if(e.keyCode == 40){
            if(next!=null)stage.focus = next;
        }
        else if(e.keyCode == 38){
            if(prev!=null)stage.focus = prev;
        }


    }



    //省略モードで表示
    public function func1():void{
        
        if(mode == "open")removeChild(source);
        tytle.setSelection(0,0);  
        tytle.selectable = false;
        tytle.type = "dynamic";  
        s1.graphics.clear();
        s1.graphics.beginFill(color1,0.8);
        s1.graphics.drawRoundRect(0,0,tytle.width,tytle.height,15,15);
        s1.graphics.endFill();
        mode = "close";
        
    }
    public function func2():void{
        if(mode != "open")addChild(source);
        tytle.type = "input";
        tytle.selectable = true;
        s1.graphics.clear();
        s1.graphics.beginFill(color1,0.8);
        s1.graphics.drawRect(0,0,tytle.width,tytle.height);
        s1.graphics.drawRect(0,20,source.width,source.height);
        s1.graphics.endFill();
        mode = "open";
    }



}


////////////////////////////////////////////////////////////////////////
//  TextEditor class
////////////////////////////////////////////////////////////////////////

/*
    --TextFieldへの追加機能--
        ・改行入力
        ・タブ入力
        ・オートインデント
        ・アンドゥ/リドゥ
*/

    import flash.text.TextField;
    import flash.events.*;
    class TextEditor extends TextField {
        private var prevText:String = "";//text変更前の状態
        private var indentStr:String;
        private var sc:StringComparator = new StringComparator();
        private var historyManager:HistoryManager = new HistoryManager();
        private var comparator:StringComparator = new StringComparator();
        
        public function TextEditor():void {
            this.type = "input";//入力可能
            //this.multiline = true;//マルチライン
            this.addEventListener(KeyboardEvent.KEY_DOWN, onKey); 
            this.addEventListener(FocusEvent.KEY_FOCUS_CHANGE,focusChangeListener);//タブキーによるフォーカス変更をキャンセル
            this.addEventListener(Event.CHANGE,onChange);//textの変更

        }
        
        private var sw:Boolean;
        private function onChange(e:Event):void{  
    
            if(sw==false)addHistory();
            if(sw2==true){
                this.multiline = false;
                sw2=false;
            }

            prevText = this.text;
            sw=false;      
        }
      
        private function focusChangeListener(e:FocusEvent):void{
            e.preventDefault();
        }
        
        //入力履歴更新
        private function addHistory():void{
            comparator.compare(prevText, this.text);   
            var entry:HistoryEntry = new HistoryEntry(comparator.commonPrefixLength);      
                entry.removeText = prevText.substring(comparator.commonPrefixLength, prevText.length - comparator.commonSuffixLength);
                entry.addText = this.text.substring(comparator.commonPrefixLength, this.text.length - comparator.commonSuffixLength);
                historyManager.appendEntry(entry); 
                prevText = this.text;
        }

        
        //キー入力
        private var sw2:Boolean;
        private function onKey(e:KeyboardEvent):void {        
        
        
            //カーソル操作
            if(e.keyCode <=40 && e.keyCode>=37){
                moveCaret(e.keyCode);
            }

            
            // Ctrl+Z : UNDO
            if (e.keyCode == 90 && e.ctrlKey) {
                sw=true;
                undo();
                return;
            }
        
            // Ctrl+Y : REDO
            if (e.keyCode == 89 && e.ctrlKey) {
                sw=true;
                redo();
                return;
            }
            //ペースト
            if(e.keyCode == 86 && e.ctrlKey){
                this.multiline = true;//改行を含むコピーに対応
                sw2=true;
            }

            
            //キャレット位置に改行文字を挿入
            if(e.keyCode == 13 || e.keyCode == 108){
                lineFeed();
                return;
            }
            //tab
            if (e.keyCode == 9) {
                tab();
                return;
            }
        }
        
        
        private function moveCaret(keyCode:int):void{
            if(keyCode == 40 && this.caretIndex == this.length){// ↓
                if(nextTF==null)return;
                stage.focus = nextTF;
                //キャレット位置セット
                nextTF.setSelection(0,0);
            }
            if(keyCode == 39 && this.caretIndex == this.length){// →
                if(nextTF==null)return;
                stage.focus = nextTF;
                nextTF.setSelection(0,0);
            }
            if(keyCode == 38 && this.caretIndex == 0){// ↑
                if(prevTF==null)return;
                stage.focus = prevTF;
                prevTF.setSelection(prevTF.length,prevTF.length);      
            }
            if(keyCode == 37 && this.caretIndex == 0){// ←
                if(prevTF==null)return;
                stage.focus = prevTF;
                prevTF.setSelection(prevTF.length,prevTF.length);
            }
        }
        
        //テキストフィールド間のキャレット移動
        public function setNextTF(TF:TextField):void{
            nextTF=TF;
        }
        public function setPrevTF(TF:TextField):void{
            prevTF=TF;
        }
        private var prevTF:TextField = null;
        private var nextTF:TextField = null;
             


        
        //改行
        
        public function lineFeed():void{
            //sw2=true;
            var str1:String;
            var str2:String;
            var scrV:int = this.scrollV;
            str1 = this.text.substring(0, this.caretIndex);
            str2 = this.text.substring(this.caretIndex, this.length);
            this.text = str1;
            this.appendText("\n");//キャレット位置で改行
                
            //インデント構造(タブ&スペースの構成)を調べる
            var indent:int=0;
            var prevReturn:int = this.text.lastIndexOf('\r', this.caretIndex-1);//前回の改行位置
            //一つ前の改行直後に続くタブコードの数=インデント深度
            for (var j:int = prevReturn+1; j < this.caretIndex; j++) {
                if (this.text.charAt(j) == '\t' || this.text.charAt(j) == ' ' ) indent++;
                else break;
            }
            //上の行のインデントに従う
            var iStr:String = this.text.slice(prevReturn + 1, prevReturn + 1 + indent);
            indentStr = iStr;
            this.appendText(iStr);//インデント
            this.text += str2;//結合 
             
            //キャレット位置をインクリメント
            this.scrollV = scrV;
            this.setSelection(this.caretIndex +indent + 1, this.caretIndex +indent + 1);
            
            this.dispatchEvent(new Event(Event.CHANGE));
            
        }

        //タブ
        public function tab():void{
            var str1:String;
            var str2:String;
            str1 = this.text.substring(0, this.caretIndex);
            str2 = this.text.substring(this.caretIndex, this.length);
            this.text = str1 + '\t' + str2;
            //キャレット位置をインクリメント
            this.setSelection(this.caretIndex + 1, this.caretIndex + 1);        
            this.dispatchEvent(new Event(Event.CHANGE));
        }

        //アンドゥ
        public function undo():void {
            if (historyManager.canBack) {
                var entry:HistoryEntry = historyManager.back();
                //テキストセット
                this.replaceText(entry.index, entry.index + entry.addText.length, entry.removeText);
                //キャレット位置セット
                this.setSelection(entry.index + entry.removeText.length, entry.index + entry.removeText.length);               
            }
            this.dispatchEvent(new Event(Event.CHANGE));           
        }
    
        //リドゥ
        public function redo():void {
            if (historyManager.canForward) {
                var entry:HistoryEntry = historyManager.forward();
                //テキストセット
                this.replaceText(entry.index, entry.index + entry.removeText.length, entry.addText);
                //キャレット位置セット
                this.setSelection(entry.index + entry.addText.length, entry.index + entry.addText.length);            
            }
            this.dispatchEvent(new Event(Event.CHANGE));         
        }
        
    }


import __AS3__.vec.Vector;

class HistoryManager {
    public var currentIndex:int = 0;
    public var length:int=0;
    private var entries:Vector.<HistoryEntry>;
    
    public function HistoryManager() {
        entries = new Vector.<HistoryEntry>();
    }
    //履歴追記
    public function appendEntry(entry:HistoryEntry):void {
        entries.length = currentIndex;
        length = entries.length;
        entries.push(entry);
        currentIndex++;// = entries.length;
    }
    //履歴削除
    public function clear():void {
        currentIndex = 0;
        entries.length = 0;
    }
    //リドゥ可能
    public function get canForward():Boolean {
        return currentIndex < entries.length;
    }
    //アンドゥ可能
    public function get canBack():Boolean {
        return currentIndex > 0;
    }
    //リドゥ
    public function forward():HistoryEntry {
        return entries[currentIndex++];
    }
    //アンドゥ
    public function back():HistoryEntry {
        return entries[--currentIndex];
    }

}


class HistoryEntry {
    public var index:int;
    public var removeText:String;
    public var addText:String;
    
    public function HistoryEntry(index:int=0, remove:String="", add:String="") {
        this.index   = index;//文字列先頭位置
        this.removeText = remove;//消した文字列
        this.addText = add;//追加した文字列
    }
}
    

 // 文字列の左右一致を数える
class StringComparator {
    // 左側の共通文字列長
    public var commonPrefixLength:int;    
    // 右側の共通文字列長
    public var commonSuffixLength:int;
    /**
     * 2つの文字列を比較し、commonPrefixLengthとcommonSuffixLengthをセットする
     * 
     * @param str1 比較する文字列の一方
     * @param str2 比較する文字列の他方
     */
    public function compare(str1:String, str2:String):void {
        var minLength:int = Math.min(str1.length, str2.length);
        var step:int, l:int, r:int;
        
        step = Math.pow(2, Math.floor(Math.log(minLength) / Math.log(2)));
        for (l=0; l<minLength; ) {
            if (str1.substr(0, l + step) != str2.substr(0, l + step)) {
                if (step == 1) { break; }
                step >>= 1;
            } else {
                l += step;
            }
        }
        l = Math.min(l, minLength);
        
        minLength -= l;
        
        step = Math.pow(2, Math.floor(Math.log(minLength) / Math.log(2)));
        for (r=0; r<minLength; ) {
            if (str1.substr(-r - step) != str2.substr(-r - step)) {
                if (step == 1) { break; }
                step >>= 1;
            } else {
                r += step;
            }
        }
        r = Math.min(r, minLength);
        
        commonPrefixLength = l;
        commonSuffixLength = r;
    }    
}  


//////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////
import flash.display.*;
import flash.events.*;


//テキストからトークンを抽出する
class token{
    public var list:Object;//トークン列
    private var source:String;
    public var listLength:int = 0;
   
    public function token(){
        list = new Object();
    }
  
    //指定インデクスからmax個までトークン抽出
    //抽出したトークンはlistに追加
    //抽出したところまでのインデクスを返す
    public function getToken(str:String,index:int=0,max:int=1000):int{
        if(str!=source){
            source=str;
            list=null;
            list=new Object;
            listLength = 0;
            index01=0;
        }
        var currentIndex:int = index;
        var cnt:int = 0;
        while(currentIndex<source.length){
            
            currentIndex = func01();
            cnt++;
            if(max<cnt)break;
        }
        return currentIndex;
    }

/*
    public function func4():void{
        // ;
            else if(list[i].type==';'){
                //list[i].step = stepCnt[stepCnt.length-1];
                //list[i].group = stac[stac.length-1];
                //stepCnt[stepCnt.length-1]++;//ステップをカウントアップ
                continue;
            }
// space            
            else if(list[i].type=="space"){
                //list[i].step = stepCnt[stepCnt.length-1];
                //list[i].group = stac[stac.length-1];
                if(list[i].text.search(/[\n\r]/gm)!=-1){
                    list[i].tag += "onReturn\n";//改行が含まれる
                    //lineCnt[stepCnt.length-1]++;
                }
                if(list[i].text.search(/ /gm)!=-1)list[i].tag += "onFullwidthSpace\n";//全角スペースが含まれる
                continue;
            }

// その他
            else{
                //list[i].step = stepCnt[stepCnt.length-1];
                //list[i].group = stac[stac.length-1];
                continue;

            }
    }

*/

    
    public function setKeywordAS3():void{//
        var keyword1:Array = new Array("function","var","class","const");
        var keyword2:Array = new Array("for","while","if","else","do","switch","each");
        var keyword3:Array = new Array("null","void","int","uint",
                                        "Boolean","Number","String","Object","Array",
                                        "Date","RegExp","Error","Function","XML","XMLList");
        var keyword4:Array = new Array("private","public","static","");
        getStringToken();
        var i:int;
        for(i=0;i<keyword1.length;i++){
            setType(keyword1[i],"keyword");
        }
        for(i=0;i<keyword2.length;i++){
            setType(keyword1[i],"control");
        }
        for(i=0;i<keyword3.length;i++){
            setType(keyword1[i],"DataType");
        }
        for(i=0;i<keyword4.length;i++){
            setType(keyword1[i],"access");
        }

    }


    //token.type="string"からタイプを書き換える
    private var strToken:Array;
    private function setType(str:String,type:String):void{
        for(var i:int=0;i<strToken.length;i++){
            if(list[strToken[i]].text==str){
                list[strToken[i]].type=type;
            }

        }
        regetStringToken();

    }
    private function regetStringToken(str:String="string"):void{
        var ary:Array=strToken;
        var ary2:Array = new Array();
        for(var i:int=0;i<ary.length;i++){
            if(list[ary[i]].type==str){
                ary2.push(ary[i]);
            }

        }
        strToken = null;
        strToken = ary2;

    }

    //type == string のトークンid列を取得
    private function getStringToken(str:String="string"):void{//
        strToken = new Array();
        for(var i:int=0;i<listLength;i++){
            if(list[i].type==str){
                strToken.push(i);
            }

        }

    }



    //func2から得たArrayで指定
    public function getBlockTokenList(entry:int=-1):Array{
        var i:int;
        var lastToken:int;
        var tokenIdList:Array = new Array();
        if(entry == -1){//トークン全体全体
            lastToken = listLength;
            for(i=0;i<lastToken;i++){
                tokenIdList.push(i);
            }
            return tokenIdList;
        }
        else{
            lastToken = list[entry].pair;
            for(i=entry+1;i<lastToken;i++){
                tokenIdList.push(i);
            }
            return tokenIdList;
        }
    }
    //指定したスコープ内のテキスト取得
    public function getBlockText(entry:int=-1):String{
        var i:int;
        var lastToken:int;
        var str:String = new String();
        if(entry == -1){//トークン全体全体
            lastToken = listLength;
            for(i=0;i<lastToken;i++){
                str += list[i].text;
            }
            return str;
        }
        else{
            lastToken = list[entry].pair;
            for(i=entry+1;i<lastToken;i++){
                str += list[i].text;
            }
            return str;
        }
    }




    //スコープ別にテキストを取り出す
    public function func3(tokenID:int):String{
        var n:int=tokenID;
        var str:String = new String();
        
        if(list[n].type!='{'){
            n=list[n].group;
        }
        for(var i:int = n;i<list[n].pair+1;i++){
            str+=list[i].text;
            if(list[i].type=='{')i=list[i].pair-1;//スコープ内を省略
        }

        return str;
    }

    //トークンにブロックを割り当てる { } ( ) [ ]
    public function func2():Array{
        const err1:String = "scopeErrer1\n";//スコープの終了がない
        const err2:String = "scopeErrer2\n";//ペアの種類が異なる
        const err3:String = "scopeErrer3\n";//スコープの開始がない
        var stac:Array = new Array();
        var scopeEntry:Array = new Array();//スコープの開始位置のトークンID列
        scopeEntry.push(-1);
        for(var i:int=0;i<listLength;i++){
// {
            if(list[i].type=='{'){
                stac.push(i);
                continue;
            }
            else if(list[i].type=='}'){
                if(stac.length==0){
                    list[i].tag += err3;//エラー
                    continue;
                }
                if(list[stac[stac.length-1]].type != '{'){
                    list[i].tag += err2;//エラー
                    continue;
                }
                //ペア登録
                list[i].pair = stac.pop();
                list[list[i].pair].pair = i;
                scopeEntry.push(list[i].pair);
                continue;
            }
// ( )
            else if(list[i].type=='('){
                stac.push(i);
                continue;
            }
            else if(list[i].type==')'){
                if(stac.length==0){
                    list[i].tag += err3;//エラー
                    continue;
                }
                if(list[stac[stac.length-1]].type != '('){
                    list[i].tag += err2;//エラー
                    continue;
                }
                //ペア登録
                list[i].pair = stac.pop();
                list[list[i].pair].pair = i;
                scopeEntry.push(list[i].pair);
                continue;
            }
// [ ]
            else if(list[i].type=='['){
                stac.push(i);

                continue;
            }
            else if(list[i].type==']'){
                if(stac.length==0){//スコープ開始位置が存在しない
                    list[i].tag += err3;//エラー
                    continue;
                }
                if(list[stac[stac.length-1]].type != '['){//種類が異なる
                    list[i].tag += err2;//エラー
                    continue;
                }
                //ペア登録
                list[i].pair = stac.pop();
                list[list[i].pair].pair = i;
                scopeEntry.push(list[i].pair);
                continue;
            }      
        }//for

        if(stac.length!=0){//スコープが閉じられる前に最期まで到達した時
            for(var j:int=0;j<stac.length;j++){
                list[stac[j]].tag += err1;
            }
        }
        return scopeEntry;
        
    }

//-------------------------------------------------------------
    //開始インデクスを受け取りトークンのタイプを返す
    private var index01:int=0;
    private function func01():int{
        var index:int = index01;
        var token:Object = new Object();
        var reg:RegExp = new RegExp();                
        var result:Object;
        var index2:int = index;
        list[listLength] = token;
        listLength++;
        token.index = index;
        token.tag = "";
        //トークンタイプ:空白か?
        if(    source.charAt(index)== " " ||
               source.charAt(index)=="\t" ||
               source.charAt(index)=="\n" ||
               source.charAt(index)=="\r" ||
               source.charAt(index)==" "){
                   token.type = "space";
                   reg = /[^\s ]/mg;
                   reg.lastIndex = index;
                   result = reg.exec(source);
                   //トークン作成
                   if(result == null)token.lastIndex = source.length;
                   else token.lastIndex = result.index;
                   token.text = source.substring(index,token.lastIndex);
                   index01 = token.lastIndex;//次の開始位置
                   return token.lastIndex;
                    
               }

        
        //トークンタイプ:文字列定数1
        if(    source.charAt(index)== "'"){
            token.type = "text1";
            
            do{//エスケープ処理
                reg = /['\n\r]/mg;
                reg.lastIndex = index2+1;
                result = reg.exec(source);
                if(result==null)break;
                else index2 = result.index+1;
            }while(source.charAt(index2-2)=="\\");
            
            
            //トークン作成
            if(result == null)token.lastIndex = token.index+1;
            else token.lastIndex = result.index+1;   
            token.text= source.substring(token.index,token.lastIndex);
            
            //エラー検出
            if(source.charAt(result.index)!="'"){
                token.type += "_start";
                token.text = "'";
                token.lastIndex = index+1
                
            }
            index01 = token.lastIndex;//次の開始位置
            return token.lastIndex;    
        }
 
        //トークンタイプ:文字列定数2
        if(    source.charAt(index)== '"'){
            token.type = "text2";
            
            do{//エスケープ処理
                reg = /["\n\r]/mg;
                reg.lastIndex = index2+1;
                result = reg.exec(source);
                if(result==null)break;
                else index2 = result.index+1;
            }while(source.charAt(index2-2)=="\\");
            
            //トークン作成
            if(result == null)token.lastIndex = index+1
            else token.lastIndex = result.index+1;   
            token.text= source.substring(index,token.lastIndex);
            
            //エラー検出
            if(source.charAt(result.index)!='"'){
                token.type += "_start";
                token.text = '"';
                token.lastIndex = index+1;
            }
            index01 = token.lastIndex;//次の開始位置
            return token.lastIndex;
        }
        
        if(source.charAt(index)== "/"){
               //一行コメント
               if(source.charAt(index+1)== "/"){
                   reg = /[\n\r]/mg;
                   reg.lastIndex = index+1;
                   result = reg.exec(source);
                   if(result == null)token.lastIndex = source.length;
                   else token.lastIndex = result.index;
                   token.type = "comment1";
                   token.text = source.substring(index,token.lastIndex);
                   index01 = token.lastIndex;//次の開始位置
                   return token.lastIndex;

               }
               //複数行コメント
               if(source.charAt(index+1)== "*"){
                   reg = /\*\//mg;
                   reg.lastIndex = index+2;
                   result = reg.exec(source);
                   
                   //トークン作成
                   token.type = "comment2";
                   if(result == null)token.lastIndex = index+2
                   else token.lastIndex = result.index+2;
                   
                   //エラー検出
                   if(result == null){
                       token.type += "_start";
                       token.text = '/*';
                       token.lastIndex = index+2;
                   }
                   else token.text = source.substring(index,token.lastIndex);
                   index01 = token.lastIndex;//次の開始位置
                   return token.lastIndex;
               }
        }
        //複数行コメント終わり
        if(source.charAt(index)== "*"){
            if(source.charAt(index+1)=="/"){
                token.type = "comment2_end";
                token.text = "*/";
                token.lastIndex = index+2;
                index01 = token.lastIndex;//次の開始位置
                return token.lastIndex;
            }

        }
        
        
        //半角記号
        index2 = mark();
        if(index2!=0){
            index01 = token.lastIndex;//次の開始位置
            return index2;
        }

        //name
        reg = /[a-zA-Z0-9_]/mg;
        reg.lastIndex = index;
        result = reg.exec(source);
        if(result != null){
            if(index == result.index){
                reg = /[^a-zA-Z0-9_]/mg;
                reg.lastIndex = index+1;
                result = reg.exec(source);
                if(result==null)token.lastIndex = source.length;
                else if(result.index == 0)token.lastIndex = source.length;
                else token.lastIndex = result.index;
            
                token.type = "string";//半角英数字
                token.text = source.substring(token.index,token.lastIndex);
                index01 = token.lastIndex;//次の開始位置
                return token.lastIndex;
            
            }
        }
        
        token.type = "other";//その他文字列 マルチバイト文字等はここに入る
        reg = /[\x01-\x7f]/mg;
        reg.lastIndex = index+1;
        result = reg.exec(source);
        if(result==null)token.lastIndex = token.index+1;
        else if(token.index>result.index)token.lastIndex = token.index+1;
        else token.lastIndex = result.index;

        token.text = source.substring(token.index,token.lastIndex);
        index01 = token.lastIndex;//次の開始位置
        return token.lastIndex;
    }
//トークン抽出 記号類の処理
//-------------------------------------------------------------------
    private function mark():int{
        
        var token:Object= list[listLength-1];
        var index:int = token.index;
        
        //ブロック
        // { }        
        if(source.charAt(index)=='{'){
            token.type = "{";
            token.text = '{';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='}'){
            token.type = "}";
            token.text = '}';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        // ( )
        else if(source.charAt(index)=='('){
            token.type = "(";
            token.text = '(';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)==')'){
            token.type = ")";
            token.text = ')';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        // [ ]
        else if(source.charAt(index)=='['){
            token.type = "[";
            token.text = '[';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)==']'){
            token.type = "]";
            token.text = ']';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        
        //記号
        if(source.charAt(index)==';'){
            token.type = ";";
            token.text = ';';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)==','){
            token.type = ",";
            token.text = ',';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='.'){
            token.type = ".";
            token.text = '.';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='!'){
            token.type = "!";
            token.text = '!';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='#'){
            token.type = "#";
            token.text = '#';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='$'){
            token.type = "$";
            token.text = '$';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='%'){
            token.type = "%";
            token.text = '%';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='&'){
            token.type = "&";
            token.text = '&';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='-'){
            token.type = "-";
            token.text = '-';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='='){
            token.type = "=";
            token.text = '=';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='^'){
            token.type = "^";
            token.text = '^';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='~'){
            token.type = "~";
            token.text = '~';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='\\'){
            token.type = "\\";
            token.text = '\\';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='|'){
            token.type = "|";
            token.text = '|';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='+'){
            token.type = "+";
            token.text = '+';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='*'){
            token.type = "*";
            token.text = '*';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)==':'){
            token.type = ":";
            token.text = ':';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='<'){
            token.type = "<";
            token.text = '<';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='>'){
            token.type = ">";
            token.text = '>';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='?'){
            token.type = "?";
            token.text = '?';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        else if(source.charAt(index)=='@'){
            token.type = "@";
            token.text = '@';
            token.lastIndex = index+1;
            return token.lastIndex;
        }
        return 0;
    }





}