/**
* 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;
}
}