//edit 文本框
import win.ui.ctrl.metaProperty;//导入控件属性元表支持
namespace win.ui.ctrl;  
 
//这里我们使用一个反向的装饰继承类来封装edit与richedit控件的公用属性
class editDecorateMeta{
	ctor(meta)begin
		this = meta
	end; 
	
	//公用属性
	//--------------------------------------
	
	modified = {
		_get = function(){ 
			return  ::SendMessage(owner[["hwnd"]],0xB8/*_EM_GETMODIFY*/);
		}
		_set = function( v ){
			::SendMessageInt(owner[["hwnd"]],0xB9/*_EM_SETMODIFY*/,0,v );
		} 	
	};  
	//公用方法
	//--------------------------------------
	getsel = function(){
      //获取起始和结束位置
      var re,min,max = ::SendMessageByInt(owner[["hwnd"]],0xB0/*_EM_GETSEL*/,0,0); 
      return  min,max  ;  
    }
    setsel = function(min=0,max=0){ 
     	//获取起始和结束位置
        ::SendMessageInt(owner[["hwnd"]],0xB1/*_EM_SETSEL*/,min ,max);
    }  
    selType = function(){
    	return ::SendMessage(owner.hwnd,0x442/*_EM_SELECTIONTYPE*/);
    } 
    lineCount = {
		_get = function(){ 
			return  ::SendMessage(owner[["hwnd"]],0xBA/*_EM_GETLINECOUNT*/);
		} 	
	}; 
	lineLength = function(ind=0){ 
		var chr = owner.lineToChar(ind);
		return ::SendMessageInt(owner[["hwnd"]],0xC1/*_EM_LINELENGTH*/,chr,0);
	};
    lineText = function(ind=0){   
    	var chr = owner.lineToChar(ind);
    	ind := owner.lineFromChar(chr)
		var len = ::SendMessageInt(owner[["hwnd"]],0xC1/*_EM_LINELENGTH*/,chr,0) * 2 + 2; 
	    var buffer = ..raw.malloc(len+4,{int len = len} );
		::SendMessage(  owner[["hwnd"]],0xC4/*_EM_GETLINE*/,topointer(ind-1),buffer);  
		return ..raw.str(buffer)
    }
    lineFromChar = function(pos){
       pos := owner.getsel(); 
       return  ::SendMessage(owner[["hwnd"]],0xC9/*_EM_LINEFROMCHAR*/,topointer(pos) )+1; 
    }
    lineToChar = function(line=0){
       line--;
       return  ::SendMessage(owner[["hwnd"]],0xBB/*_EM_LINEINDEX*/,topointer(line), ); 
    }
    lineScroll = function(line,h=0){ 
    	if(!line)line=owner.lineCount ;
       ::SendMessageInt(owner[["hwnd"]],0xB6/*_EM_LINESCROLL*/,h,line-1 );       
    }
    scrollCaret = function(){
       ::SendMessage( owner[["hwnd"]] , 0xB7/*_EM_SCROLLCARET*/);
    };
    
    canUndo = function(){
    	return !!::SendMessage(owner.hwnd,0xC6/*_EM_CANUNDO*/)
    };
    canRedo = function(){
    	return !!::SendMessage(owner.hwnd,0x455/*_EM_CANREDO*/)
    };
    canPaste = function(){
    	return !!::SendMessage(owner.hwnd,0x432/*_EM_CANPASTE*/)
    };
    canCopy = function(){
    	return !!owner.selType()
    };
    redo = function(){
    	::SendMessage(owner.hwnd,0x454/*_EM_REDO*/)
    }; 
    undo = function(){
    	::SendMessage(owner.hwnd,0xC7/*_EM_UNDO*/ )
    }
    clear = function(){
    	::SendMessage(owner.hwnd,0x303/*_WM_CLEAR*/ )
    };
    copy = function(){
    	::SendMessage(owner.hwnd,0x301/*_WM_COPY*/ )
    };
    cut = function(){
    	::SendMessage(owner.hwnd,0x300/*_WM_CUT*/ )
    };
    paste = function(){
    	::SendMessage(owner.hwnd,0x302/*_WM_PASTE*/ )
    };
    getLength = function(){
		return ::SendMessage(owner[["hwnd"]],0xE/*_WM_GETTEXTLENGTH*/ ); 
	}; 
    selectAll = function(){
		owner.setsel(0,-1);
	}; 
	deselect = function(){
		owner.setsel(-1,0);
	};
	appendText = function(s,...){
		var len = ::SendMessage(owner[["hwnd"]],0xE/*_WM_GETTEXTLENGTH*/ ); 
		owner.setsel(len,len);
		
		if(s){
			::SendMessage(owner[["hwnd"]],0xC2/*_EM_REPLACESEL*/,,tostring(s))
			len = len + #s;
			owner.setsel(len,len);
		}
		
		if(!...) return len;
		return owner.appendText(...);
	};
} 

class edit{

    //构造函数
    ctor(parent,tParam){
		if(tParam){
			if( tParam.readonly )
				tParam.style |= 0x800/*_ES_READONLY*/
				
			if( tParam.password )
				tParam.style |= 0x20/*_ES_PASSWORD*/
			else if( tParam.multiline ){
				tParam.style |= 0x4/*_ES_MULTILINE*/
				tParam.style |= 0x1000/*_ES_WANTRETURN*/;
			}
			
	    	if( tParam.num )
	    		tParam.style |=0x2000/*_ES_NUMBER*/
	    		
			if(! tParam.hidesel )
				tParam.style |= 0x100/*_ES_NOHIDESEL*/
				
			if( tParam.autoscroll ) {
				tParam.style |=  ( 0x80/*_ES_AUTOHSCROLL*/ |  0x40/*_ES_AUTOVSCROLL*/ );
			}
			else if ( !tParam.multiline ) {
				tParam.style |=  0x80/*_ES_AUTOHSCROLL*/;
			} 
	
        	select(tParam.align) {
			case  "center"   
	   		tParam.style |= 0x1/*_ES_CENTER*/; 
			case "right" 
	   		tParam.style |= 0x2/*_ES_RIGHT*/; 
			else 
			tParam.style |= 0x0/*_ES_LEFT*/;
			}
 	
			if(tParam.edge)   
				tParam.exstyle |= 0x200/*_WS_EX_CLIENTEDGE*/;   
		}
	
    }
    
	@_metaProperty;
}

edit._metaProperty = editDecorateMeta( metaProperty(
	limit = {
		_get = function(){ 
			return ::SendMessage(owner[["hwnd"]], 0x425/*_EM_GETLIMITTEXT*/, null , null);
		}
		_set = function( v ){
			assert( type(v) == type.number )
     		::SendMessage(owner[["hwnd"]], 0xC5/*_EM_LIMITTEXT*/, topointer(v) , null)
		} 	
	}  
	selText = {
		_get = function(){  
			var min,max = owner.getsel();  
			if( (min!==null) && ( max>min) ){
     	  		return ..string.sub(owner.text,min+1,max,true);  
			} 
		}
		_set = function( v ){ 
     		::SendMessage(owner[["hwnd"]],0xC2/*_EM_REPLACESEL*/,,tostring(v))
		} 	
	}; 
) );


/***intellisense()
!edit.cls = 设计时类名
!edit.className = 运行时类名
!edit.lineCount = 获取行数
!edit.setsel(1,__) = 设置选区,参数(起始位置,结束位置)
!edit.getsel() = 获取选区起始位置,结束位置 
!edit.selText = 获取或替换选区文本
!edit.modified = 文本内容是否已修改 
!edit.text = 编辑控件文本属性
!edit.hwnd = 控件句柄
!edit.id = 控件ID
!edit._parentForm = 控件所在的父窗口(指win.form对象)\n!winform.
!edit.getParent() = 返回父窗口\n!static.
!edit.setParent(__/*控件对象*/) = 改变父窗口 
!edit.hide = 控件是否隐藏
!edit.disabled = 控件时否可见
!edit.left = 左侧坐标
!edit.right = 右侧坐标
!edit.top = 顶部坐标
!edit.bottom = 底部坐标
!edit.width = 宽度
!edit.height = 高度
!edit.limit = 字符数限制
!edit.deselect() = 取消选定 
!edit.appendText(.(追加文本) = 追加文本并移动光标到文本尾部\n支持零个、或多个文本参数\n返回文本总长度
!edit.scrollCaret() = 滚动到光标处
!edit.lineScroll(.(滚动到指定行) = 滚动条移动到指定行\n如果不指定参数则滚动到最后一行 
!edit.lineToChar(__/*指定行号*/) = 获取指定行首字符偏移位置
!edit.lineToChar() = 获取当前选定行首字符偏移位置
!edit.lineFromChar(__/*指定位置*/) = 返回指定位置行数
!edit.lineFromChar() = 不指定参数则返回当前行
!edit.lineLength(__/*指定行号*/) = 返回指定行字符数
!edit.lineLength() = 不指定行号参数,则获取当前行字符数
!edit.lineText(__/*指定行号*/) = 获取指定行文本
!edit.lineText() = 不指定行号参数,则获取当前行文本
!edit.redraw() = 刷新
!edit.show(true__) = 显示控件
!edit.getRect() = 控件区块位置(::RECT结构体)
!edit.getRect(true) = 控件屏幕区块位置(::RECT结构体)  
!edit.setRect(rc) = 设置控件区块位置(::RECT结构体)  
!edit.setRect(rc,true) = 设置控件屏幕区块位置(::RECT结构体)
!edit.getClientRect() =  控件客户区块位置(::RECT结构体)\n!rect.
!edit.getFont() = 控件字体(::LOGFONT结构体)\n!logfont.
!edit.setFont(__/*指定字体*/) = 指定LOGFONT字体对象,或逻辑字体句柄 
!edit.setFont(混入字体属性) = @.setFont(point=10;name="宋体");
!edit.clientRect =  获取控件客户区块位置(::RECT结构体)
!edit.theme = 外观主题,例如\nwinform.button.theme = "Explorer"\nwinform.button.theme = false
!edit.modifyStyle(.(remove,add) = 如果指定第三个参数，则使用此参数调用::SetWidnowPos 
!edit.modifyStyleEx(.(remove,add) = 如果指定第三个参数，则使用此参数调用::SetWidnowPos
!edit.capture = 是否捕获全局鼠标消息
!edit.close() = 关闭控件窗
!edit.invalidate(__/*可选使用::RECT()对象指定客户区*/) = 使窗口绘图区无效
!edit.invalidate(__/*可选使用::RECT()对象指定客户区*/,0) = 使窗口绘图区无效\n不刷新背景
!edit.update() = 重绘invalidate函数指定的区块
!edit.wrap = 是否启用自动换行，仅richedit支持
!edit.onlink = @.onlink=function(msg,title){\n	\n}
!edit.setFocus() = 设置焦点
!edit.setFocus() = 设置焦点 
!edit.vScroll() = 滚动到底部
!edit.hScroll() = 滚动到右侧
!edit.vScroll(_SB__) = 滚动竖向滚动条
!edit.hScroll(_SB__) = 滚动横向滚动条
!edit.setPos(.(x坐标,y坐标,宽,高,插入位置,参数) = 调整窗口位置或排序,所有参数可选\n同时指定x,y坐标则移动位置\n同时指定宽高则改变大小\n指定插入位置(句柄或_HWND前缀常量)则调整Z序
!edit.getPos() = 返回相对坐标,宽,高\nx,y,cx,cy=win.getPos(hwnd)
!edit.selectAll() = 全选
!edit.redo() = 重做
!edit.undo() = 撤消
!edit.clear() = 清空
!edit.copy() = 复制
!edit.cut() = 剪切
!edit.paste() = 粘贴
!edit.canRedo() = 能否重做
!edit.canUndo() = 能否撤消
!edit.canPaste() = 能否粘贴
!edit.canCopy() = 能否复制  
?win.ui.ctrl.edit  =!edit.
win.ui.ctrl.edit() = 文本框控件\n!edit.
win.ui.ctrl.edit = 文本框控件支持库
end intellisense***/