unit UTslSynMemo; interface {** @explan(说明) tsl语法编辑器库 **} uses utslvclauxiliary,UTslMemo; type thighlitcolor = class(tcomponent) function Create(AOwner); begin inherited; intitcolors(); end function gutterbkcolor(); begin return FColors["行号背景"]; end function selbkcolor(); begin return FColors["选中背景"]; end function curbkcolor(); begin return FColors["当前行背景"]; end function bkcolor(); //背景 begin return FColors["back"]; end function fontcolor();//字体颜色 begin return FColors["字体"]; end function keycolor();//关键字 begin return FColors["关键字"]; end function symcolor();//符号 begin return FColors["符号"]; end function commentcolor();//注释 begin return FColors["注释"]; end function strcolor(); //字符串 begin return FColors["字符串"]; end function numcolor();//数字 begin return FColors["数字"]; end function sysfunccolor();//系统函数 begin return FColors["系统函数"]; end property colors write setcolors; private function intitcolors(cls); begin if not FColors then begin FColors := array(); for i,v in array("字体": ("font":0,"back":16448250),"关键字": ("font":255,"back":16448250),"符号": ("font":255,"back":16448250),"行号背景": ("font":0,"back":15000804),"注释": ("font":2263842,"back":16448250),"字符串": ("font":9109643,"back":16448250),"数字": ("font":6710886,"back":16448250),"系统函数": ("font":13434880,"back":16448250),"选中背景": ("font":0,"back":rgb(192,192,192)),"当前行背景": ("font":0,"back":rgb(232,232,255))) do begin if i="字体" then begin FColors["back"] := new tcolor(v["back"]); end if i in array("选中背景","当前行背景","行号背景") then begin FColors[i] := new tcolor(v["back"]); end else FColors[i] := new tcolor(v["font"]); end end end function transblk(c); begin return (c=0)?1:c; end function setcolors(cls); begin cgd := false; for i,v in FColors do begin if i="back" then begin v.changed := false; bc := cls["字体"]["back"]; v.color := transblk(bc); if v.changed then begin cgd .|= 2; end end else begin v.changed := false; if i in array("选中背景","当前行背景","行号背景") then begin v.color := transblk(cls[i]["back"]); end else v.color := transblk(cls[i]["font"]); if v.changed then begin if i="字体" then begin cgd .|= 4; end else if i="选中背景" then begin cgd .|= 8; end else if i= "当前行背景" then begin cgd .|= 16; end else if i="行号背景" then begin cgd .|= 32; end else cgd .|= 1; end end end if cgd then begin p := Owner; if p then p.Notification(self,array("value":cgd,"editer":1)); end end FColors; end type tcsssyncompletion = class(TSynCompletion) function Create(AOwner); begin inherited; IgnoreCase := false; end function PrepareCompletion(m);override; begin //解析 if not Memo then return ; sd := static getcsswordsa(); d := gettextwords(Memo.Text); if d then sd union=d; SetCompData(sd); end function getcsswordsa(); begin getcsskeywords(r); return r; end function gettextwords(s); begin parseregexpr("[A-Zaz0-9_\\-]+",s,"mi",mched,mchpos,mathlen); r := array(); for ri,v in mched do begin v0 := v[0]; lv := lowercase(v0); if r[lv] then continue; r[lv] := v0; end d := array(); i := 0; for lv,v in r do begin d[i,"caption"] := v; d[i,"value"] := v; d[i,"lvalue"] := lv; cl := length(v); d[i,"clen"] := cl; d[i,"vlen"] := cl; i++; end return d; end end type tjssyncompletion = class(TSynCompletion) function Create(AOwner); begin inherited; IgnoreCase := false; end function PrepareCompletion(m);override; begin //解析 if not Memo then return ; sd := static getjswords(); d := gettextwords(Memo.Text); if d then sd union=d; SetCompData(sd); end function getjswords(); begin getjskeywordstip(r); getcsskeywords(r); return r; end function gettextwords(s); begin parseregexpr("[A-Zaz0-9_\\-]+",s,"mi",mched,mchpos,mathlen); r := array(); for ri,v in mched do begin v0 := v[0]; lv := lowercase(v0); if r[lv] then continue; r[lv] := v0; end d := array(); i := 0; for lv,v in r do begin d[i,"caption"] := v; d[i,"value"] := v; d[i,"lvalue"] := lv; cl := length(v); d[i,"clen"] := cl; d[i,"vlen"] := cl; i++; end return d; end end type TTSLCompletion= class(TSynCompletion) {** @explan(说明) tsl提示自动完成类 **} static FCodeBlocks; function Create(AOwner); begin inherited; GetTslParser(); end function getallfunctions(); begin return FTslParser.DispatchMethod(0,array("method":"allfunctions")); end function GetFileFullPath(f);//获得全名 begin return FTslParser.DispatchMethod(0,array("method":"getfullpath","value":f)); end class function SetFindDirs(dirs); //设置搜索目录 begin return GetTslParser().DispatchMethod(0,array("method":"finddirs","value":dirs)); end class function SetCacheDir(dir); //设置缓存目录 begin return GetTslParser().DispatchMethod(0,array("method":"cachedir","value":dir)); end class function getdirtsfs(); begin return GetTslParser().DispatchMethod(0,array("method":"getprojecttsfs")); end class function GetCodeBlocks(); begin r := array(); {try FCodeBlocks := GetTslCompletionCodeBlocks(); except FCodeBlocks := array(); end} if ifarray(FCodeBlocks) then begin idx := 0; for i ,vv in FCodeBlocks do begin if not ifarray(vv) then continue; cp := vv["caption"]; if not(cp and ifstring(cp)) then continue; v := vv["value"]; if not(v and ifstring(v)) then continue; ve := vv["valueext"]; if not(ve and ifstring(ve)) then continue; r[idx]["caption"] := cp; r[idx]["value"] := v; r[idx]["lvalue"] := lowercase(v); r[idx]["vlen"] := length(v); r[idx]["clen"] := length(cp); r[idx]["order"] := 0; r[idx]["valueext"] := ve; if vv["prefix"] then r[idx]["prefix"]:=true; idx++; end end return r; end function getjumpinfo(); begin return FTslParser.DispatchMethod(0,array("method":"allfunctions")); end function PrepareCompletion(m);override; begin //解析 if not Memo then return ; //mtic; { setprofiler(7); t := now();} sd := static GetTslKeyWords(); d := FTslParser.DispatchMethod(0,array("method":"parserstring","value":Memo.Text,"minus":m)); if ifarray(d) and d then sd union=d; sd union=GetCodeBlocks(); //sd[length(sd)] := array("caption":"try except end","value":"try","lvalue":"try","vlen":3,"clen":14,"order":0,"valueext":"\r\nexcept\r\nend;"); SetCompData(sd); //echo "\r\ntime:",mtoc; {if (now()-t)>(1/24/60/60/3) then begin except end; d := getprofilerinfo(true); exportfile(ftstream(),"",format("d:\\tst\\profile\\%ssynprofile.stm",tostn(random())),d); end} //FTslParser end function GetTslKeyWords(); //关键字 begin gjz := TSL_ReservedKeys2(); r := array(); idx := 0; for i,v in gjz do begin c := v+" "; r[idx]["caption"] := c; r[idx]["value"] := v; r[idx]["lvalue"] := lowercase(v); r[idx]["vlen"] := length(v); r[idx]["clen"] := length(c); r[idx]["order"] := 0; idx++; end gjz := unit(utssvr_api_c).get_sys_functions();//tslL_getfunctions_2_(); for i,v in gjz do begin c := v+" "; r[idx]["caption"] := c; r[idx]["value"] := v; r[idx]["lvalue"] := lowercase(v); r[idx]["vlen"] := length(v); r[idx]["clen"] := length(c); r[idx]["order"] := 2; idx++; end getjskeywordstip(r); getcsskeywords(r); return r; end private class function GetTslParser(); begin if not FTslParser then FTslParser := new TTsfFileParser(); return FTslParser; end static FTslParser; end type TTslSynHighLighter = class(TSynHighLighter) {** @explan(说明) tsl语法高亮类 **} private fpairbegin; public fforcehtml; function forcehtml(h); begin if h then begin fforcehtml := true; FSynBranch := "tslx"; end else begin fforcehtml := false; FSynBranch := 0; end end function Create(AOwner); begin inherited; fforcehtml := 0; fpairbegin := array("select":1,"sselect":1,"update":1,"mselect":1,"vselect":1,"try":1,"begin":1,"type":1,"case":1); FSynBranch := 0;// 0, "tsl" "tslx" Clean(); FChangeDeal := true; if not ifarray(FKeyWords) then begin FKeyWords := array(); for i,v in TSL_ReservedKeys2() do begin FKeyWords[v] := v; end FBinFunc := array(); for i,v in unit(utssvr_api_c).get_sys_functions() do begin FBinFunc[v]:=v; end FJsKeyWords := array(); for i,v in getjskeywords() do begin FJsKeyWords[v]:=v; end FJsSysClass := array(); for i,v in array("Array","Date","eval","function","hasOwnProperty","Infinity","isFinite","isNaN","isPrototypeOf","length","Math","NaN","name","Number","Object","prototype","String","toString","undefined","valueOf") do begin FJsSysClass[v]:=true; end FJsWindows := array(); for i,v in getjsfunwords() do begin FJsWindows[v]:=true; end FJsHtmlEvent := array(); for i,v in getdomeventwords() do begin FJsHtmlEvent[v]:=true; end FCssPropertys := array(); for i,v in getcsswords() do begin FCssPropertys[v]:=true; end end FLastDispathTime := 0; end function Clean();override; begin // { ' " %% 0 FTokens := array(); FSates := array(0); //状态 if fforcehtml then begin FSynSates := array("tslx"); end else FSynSates := array(0); FBBStates := array(new TBBState(")")); FBEStates := array(new TBBState("end")); FMBStates := array(new TBBState("]")); FJsxkhs := array(new TBBState(")")); FJshkhs := array(new TBBState("}")); FJsDkhs := array(new TBBState("]")); FSatesCount := 1; //改变的行 end function Recycling();override; begin Clean(); inherited; end function SetInValidateIndex(idx);override; //设置无效的数据 begin idx := max(1,idx); if not(FChangeDeal) and idx>FSatesCount then return ; fdolastline := idx-2; if length(FSates)>=idx then FSatesCount := idx; else FSatesCount := length(FSates)-1; if FSatesCount = 1 then Clean(); FChangeDeal := false; end function SetJsToken(tokens,ttk,idx,tp); begin bttk := ttk; if not ttk then return nil; d := inherited SetTToken(tokens,ttk,idx,tp); case tp of '//','/*': begin if hightercolor then d.FFcolor := hightercolor.commentcolor() ; else d.FFColor := 0x8D9600; end '"',"'": begin if hightercolor then d.FFcolor := hightercolor.strcolor() ; else d.FFcolor := 0x968080; end "{": begin if bttk="{" then begin FJshkh.GetLeft(); d.FMate := FJshkh.GetSate(); end else begin FJshkh.GetRight(); d.FMate := FJshkh.GetSate(); end end "(": begin if bttk="(" then begin FJsxkh.GetLeft(); d.FMate := FJsxkh.GetSate(); end else begin FJsxkh.GetRight(); d.FMate := FJsxkh.GetSate(); end end "[": begin if bttk="[" then begin FJsDkh.GetLeft(); d.FMate := FJsDkh.GetSate(); end else begin FJsDkh.GetRight(); d.FMate := FJsDkh.GetSate(); end end else begin if FJsWindows[bttk] then // begin if hightercolor then d.FFcolor := hightercolor.sysfunccolor() ; else d.FFColor := 0xFF0000; end else if FJsKeyWords[bttk] then // FE0064 begin if hightercolor then d.FFcolor := hightercolor.keycolor() ; else d.FFColor := 0xFF0000; end else if FJsSysClass[bttk] then // begin if hightercolor then d.FFcolor := hightercolor.keycolor() ; else d.FFcolor := 0xcd0000; end else if FJsHtmlEvent[bttk] then // begin if hightercolor then d.FFcolor := hightercolor.sysfunccolor() ; else d.FFColor := 0xFF0000; end else if FCssPropertys[bttk] then begin if hightercolor then d.FFcolor := hightercolor.keycolor() ; else d.FFColor := 0x0000FF; end end end return d; end function SetTToken(tokens,ttk,idx,tp);override; begin if not ttk then return ; ottk := ttk; d := inherited; tkl := d.FLen; lwttk := lowercase(ottk); donext := true; //if tp in array("'",'"') then if tp='"' or tp="'" or (tp=array("%%")) then begin if hightercolor then d.FFcolor := hightercolor.strcolor() ; else d.FFcolor := 0x8B008B; donext := false; end else if tp="//" or tp="{" or tp="(*" then //if tp in array("//","{","(*") then begin if hightercolor then d.FFcolor := hightercolor.commentcolor() ; else d.FFcolor := 0x228B22; donext := false; end else if FKeyWords[lwttk] then begin if hightercolor then d.FFcolor := hightercolor.keycolor() ; else d.FFcolor := 0x0000FF; end else if FBinFunc[lwttk] then begin if hightercolor then d.FFcolor := hightercolor.sysfunccolor() ; else d.FFcolor := 0xcd0000; //d.FFfacename := "MS Mincho"; //d["vtype"] := "function"; donext := false; end if donext then begin if (tkl=1) and pos(ottk,";.`~!@#$%^&*-+,><.,=:;"; if cst=0 then begin while idx<=e do begin vi := s[idx]; viod := ord(vi); //if vi="<" and ( e-b)>2 and s[idx+1:idx+3]="!--" then if vi="<" and ( e-idx)>2 and s[idx+1:idx+3]="!--" then begin //FindRightChars SetJsToken(tokens,"",s,b,e); if r=0 then begin SetJsToken(tokens,s[b:],e,"/*"); return cst; end else if r<=e then begin SetJsToken(tokens,s[b:r],r,"/*"); if r0x40 and viod<0x5B) or (viod>0x60 and viod<0x7B) or (viod>0x2F and viod<0x3A) then begin ttk+=vi; end else if FSynBranch="tsl" and vi="?" then begin if ttk then SetTToken(tokens,ttk,idx-1); if idx",idx+1); FSynBranch := "tslx"; return ParserTslxTokenLines(s,idx+2,e,cst,tokens); end else begin SetTToken(tokens,"?",idx); end end else if (vi=" ") or (vi="\t") then //空格 begin SetTToken(tokens,ttk,idx-1); end else if vi ="'" then begin if ttk then SetTToken(tokens,ttk,idx-1); SetTToken(tokens,"'",idx,"'"); if idx=e then return "'"; r := FindRightChar("'",s,idx+1,e,"\\"); if r = 0 then begin SetTToken(tokens,s[idx+1:],e,"'"); return "'"; end else begin if r>idx+1 then begin SetTToken(tokens,s[idx+1:r-1],r-1,"'"); end SetTToken(tokens,s[r:r],r,"'"); idx := r+1; continue; end //return ParserTokenLines(s,idx+1,e,"'",tokens); end else if vi = '"' then begin if ttk then SetTToken(tokens,ttk,idx-1); SetTToken(tokens,'"',idx,'"'); if idx=e then return '"'; r := FindRightChar('"',s,idx+1,e,"\\"); if r = 0 then begin SetTToken(tokens,s[idx+1:],e,'"'); return '"'; end else begin if r>idx+1 then begin SetTToken(tokens,s[idx+1:r-1],r-1,'"'); end SetTToken(tokens,s[r:r],r,'"'); idx := r+1; continue; end //return ParserTokenLines(s,idx+1,e,'"',tokens); end else if vi="{" then begin if ttk then SetTToken(tokens,ttk,idx-1); SetTToken(tokens,'{',idx,'{'); return ParserTokenLines(s,idx+1,e,'{',tokens); end else if vi="/" then begin if ttk then SetTToken(tokens,ttk,idx-1); if idx=e then begin SetTToken(tokens,vi,idx); end else begin if s[idx+1]="/" then begin SetTToken(tokens,s[idx:],e,"//"); return 0; end else begin SetTToken(tokens,vi,idx); end end end else if vi="#" then begin if ttk then SetTToken(tokens,ttk,idx-1); if idx=e then begin SetTToken(tokens,vi,idx); end else begin if s[idx+1]="!" then begin SetTToken(tokens,s[idx:],e,"//"); return 0; end else begin SetTToken(tokens,vi,idx); end end end else if vi="(" then begin if ttk then SetTToken(tokens,ttk,idx-1); if idx=e then begin FCBBState.GetLeft(); SetTToken(tokens,"(",idx,array("(")); end else begin if s[idx+1]="*" then begin SetTToken(tokens,"(*",idx+1,"(*"); return ParserTokenLines(s,idx+2,e,"(*",tokens); end else begin FCBBState.GetLeft(); SetTToken(tokens,"(",idx,array("(")); end end end else if vi="%" then begin if ttk then SetTToken(tokens,ttk,idx-1); idx++; if idx<=e then begin tvi:=s[idx]; typeidx := idx-1; if tvi="%" then // begin ccs := "%%"; while idx<=e do begin idx++; if idx>e then begin SetTToken(tokens,const ccs,e,array("%%")); return ccs; end tvi := s[idx]; if tvi=" " or tvi="\t" then begin SetTToken(tokens,const ccs,idx-1,array("%%")); return ParserTokenLines(s,idx+1,e,ccs,tokens); end else ccs+=tvi; end end else begin SetTToken(tokens,"%",idx-1); idx--; end end else begin SetTToken(tokens,"%",idx-1); end end else if vi="<" then begin if ttk then SetTToken(tokens,ttk,idx-1); if (idx+6<=e) and s[idx+1]="?" and lowercase(s[idx+2:idx+6])="tslx>" then begin d := SetTToken(tokens,s[idx:idx+6],idx+6); d.FFColor := 0xFF00FF; FSynBranch := "tslx"; if idx+6=e then begin return 0; end return ParserTSlxTokenLines(s,idx+7,e,0,tokens);; end else begin SetTToken(tokens,"<",idx); end end else if pos(vi,"`~@#$^&*)+-;,.?:[]|\\=><%/") then begin if ttk then SetTToken(tokens,ttk,idx-1); if vi=")" then begin FCBBState.GetRight(); SetTToken(tokens,")",idx,array("(")); end else if vi="[" then begin FCMBState.GetLeft(); SetTToken(tokens,"[",idx,array("[")); end else if vi="]" then begin FCMBState.GetRight(); SetTToken(tokens,"]",idx,array("[")); end else begin SetTToken(tokens,vi,idx); end end else begin ttk+=vi; end idx++; end if ttk then SetTToken(tokens,ttk,idx-1); end else if cst="'" or cst='"' then begin if b>e then return cst; r := FindRightChar(cst,s,b,e,"\\"); if r=0 then //没找到 begin Setttoken(tokens,s[b:],e,cst); return cst; end else //找到 if r<=e then begin if be then return cst; r := FindRightChar("}",s,b,e); if r=0 then //没找到 begin Setttoken(tokens,s[b:e],e,cst); return cst; end else //找到 if r<=e then begin Setttoken(tokens,s[b:r],r,cst); if re then return cst; r := FindRightChars(cst,s,b,e); if r=0 then begin Setttoken(tokens,s[b:e],e,array("%%")); return cst; end else if r<=e then begin Setttoken(tokens,s[b:r],r,array("%%")); if re then return cst; r := FindRightChars("*)",s,b,e); if r=0 then begin Setttoken(tokens,s[b:],e,cst); return cst; end else if r<=e then begin Setttoken(tokens,s[b:r],r,cst); if r=LastLine then return ; fdolastline := LastLine; for i:= FSatesCount-1 to LastLine do begin if i<0 then continue; s := ls.GetStringByIndex(i); cst := FSates[i]; FSynBranch := FSynSates[i]; tks := array(); if FSynBranch ="tslx" then //减少对象构造 begin FCBBState := FBBStates[i];//.Clone; FCBEState := FBEStates[i];//.Clone; FCMBState := FMBStates[i];//.Clone; FJsHkh := FJsHkhs[i].Clone; FJsDkh := FJsDkhS[i].Clone; FJsXkh := FJsXkhS[i].Clone; end else begin FCBBState := FBBStates[i].Clone; FCBEState := FBEStates[i].Clone; FCMBState := FMBStates[i].Clone; FJsHkh := FJsHkhs[i];//.Clone; FJsDkh := FJsDkhS[i];//.Clone; FJsXkh := FJsXkhS[i];//.Clone; end FSates[i+1] := ParserTokenLines(s,1,length(s),cst,tks); FJsHkhs[i+1] :=FJsHkh;//.Clone; FJsDkhS[i+1] := FJsDkh;//.Clone; FJsXkhS[i+1] := FJsXkh; FSynSates[i+1] := FSynBranch; FBBStates[i+1] :=FCBBState;//.Clone; FBEStates[i+1] := FCBEState;//.Clone; FMBStates[i+1] := FCMBState; FSatesCount := i+1; FTokens[i] := tks; //TryDispatch(); end {if (now()-t)>(1/24/60/60) then begin echo "\r\ntime:",mtoc; d := getprofilerinfo(true); exportfile(ftstream(),"",format("d:\\tst\\profile\\%ssynprofile.stm",tostn(random())),d); end} //if tks then echo "\r\ntokencount:",tks[0].FTokenCount,"\r\n"; end function TryDispatch(); begin t := now(); if (t-FLastDispathTime)>1.5e-5 then begin FLastDispathTime := t; GetAndDispatchMessageA(); end end function GetLineTokens(idx);override; begin if idxe then return 0; continue; end if s[i]=c then //找到了 begin return i; end i++; end return 0; //没找到 for i := b to e do begin if s[i]=c then //找到了 begin return i; end end end function FindRightChars(cs,s,b,e); begin lcs := length(cs)-1; for i:= b to e-lcs do begin if s[i:i+lcs]=cs then return i+lcs; end return 0; end function StrIsANumber(s); begin if not s then return 0; c1 := ord(s[1]); return c1<58 and c1>47; return (1=ParseRegExpr("^0x[0-9 a-f A-F]+$",s,"i",result,MPos,Mlen)) or (1=ParseRegExpr("^\\d+$",s,"i",result,MPos,Mlen)); //ParseRegExpr("0x\\d+|\\d+",s,"i",result,MPos,Mlen); end FTokens; FSynSates; FSates; FSatesCount; FJsxkhs; FJsxkh; FJshkhs; FJsHkh; FJsDkhs; FJsDkh; FBBStates; FCBBState; FBEStates; FCBEState; FCMBState; FMBStates; FLastDispathTime; static FKeyWords; static FBinFunc; static FJSWindows; static FJsKeyWords; static FJsSysClass; static FJsHtmlEvent; static FCssPropertys; private fdolastline; FChangeDeal; //语言分支 FSynBranch; end type ThtmlSynHighLighter = class(TTslSynHighLighter) function Create(AOwner); begin inherited; forcehtml(1); Clean(); end end type TBatSynHigLighter = class(TSynHighLighter) function Create(AOwner); begin inherited; end function CharInSyn(v);override; begin if not(FSyns) then FSyns := "'`!@#$^&*()-+=[]{}|\\?/';,.><"+'"'; return pos(v,FSyns); end function SetInValidateIndex(idx); virtual; begin inherited; end function GetLineTokens(idx);override; begin r := inherited; rem := false; for i,v in r do begin if rem then begin v.FFColor := 0x80CD43; end else begin vv := v.FValue; lvv := lowercase(vv); case lvv of "rem": begin if hightercolor then v.FFcolor := hightercolor.commentcolor(); else v.FFColor := 0x80CD43; rem := true; end "if","else","echo","for","in","dir","cmd","pause","not": begin if hightercolor then v.FFcolor := hightercolor.keycolor(); else v.FFColor := 0xFF0000; end "@","~","#","%","&","*","=": begin if hightercolor then v.FFcolor := hightercolor.symcolor(); else v.FFColor := 0x0000FF; end else begin if i=0 then begin if pos("::",lvv) then begin if hightercolor then v.FFcolor := hightercolor.commentcolor(); else v.FFColor := 0x80CD43; rem := true; end else begin if hightercolor then v.FFcolor := hightercolor.fontcolor(); else v.FFColor := 0xFF9900;// #0099FF end end else begin if pos("%",lvv) then begin if hightercolor then v.FFcolor := hightercolor.sysfunccolor(); else v.FFColor := 0xFF0000; end end end end end end return r; end private FSyns; end type TINISynHigLighter = class(TSynHighLighter) function Create(AOwner); begin inherited; end function GetLineTokens(idx);override; begin r := inherited; if r and ifarray(r) then begin if r[0].FValue="[" then begin if hightercolor then c := hightercolor.sysfunccolor(); else c := 0xE22B8A; for i,v in r do begin v.FFColor := c; end end else if r[0].FValue in array(";","!","#") then begin if hightercolor then c := hightercolor.commentcolor(); else c := 0x80CD43; for i,v in r do begin v.FFColor := c; //#43CD80 end end else if r[0].FValue = "@" then begin if hightercolor then c := hightercolor.keycolor(); else c := 0x0000FF; r[0].FFColor := c; end else begin if hightercolor then begin c1 := hightercolor.strcolor(); c2 := hightercolor.keycolor(); end else begin c1 := 0x0000F0; c2 := 0xf0f0f0; end for i,v in r do begin if v.FValue="=" then begin v.FFColor := c1; break; end else begin v.FFColor := c2; end end end end return r; end end type TJsonSynHighLighter = class(tcustomsynhighlighter) function create(AOwner); begin inherited; ExecuteCommand("strings",array(('"',"\\"),("'","\\"))); ExecuteCommand("keywords",array("null","true","false")); ExecuteCommand("rowannotes",array()); ExecuteCommand("blockannotes",array()); ExecuteCommand("syms",array("{","}","[","]","<",">",":",",","=")); ExecuteCommand("pairs",array(("{","}"),("[","]"))); end end type TxmlSynHighLighter = class(tcustomsynhighlighter) function create(AOwner); begin inherited; ExecuteCommand("strings",array(('"'),("'"))); ExecuteCommand("keywords",array()); ExecuteCommand("rowannotes",array()); ExecuteCommand("blockannotes",array((""))); ExecuteCommand("syms",array("<",">","=","?",""),(""),("[","]"))); end function SetTToken(tokens,ttk,idx,ext);override; begin d := inherited; if not d then return ; st := ExecuteCommand("getcurrentpairstate",">"); if st then st1 := st.state; if st1=1 {and st.state=1} then begin st.subitemadd(); if st.subitemcount()>1 then begin end else begin end case d.FFColor of stringcolor,symcolor: begin end else begin if st.subitemcount()>1 then begin d.FFColor := keywordcolor;// 0x0000ff; end else d.FFColor := sysfuncolor; end end; end return d; //echo "\r\n>>>",st1,"====",st2; end end type TJsSynHighLighter = class(tcustomsynhighlighter) function create(AOwner); begin inherited; keywordcolor := 0xff0000; stringcolor := 0x968080; annotationcolor := 0x8D9600; ExecuteCommand("strings",array(('"',"\\"),("'","\\"))); ExecuteCommand("keywords",jskeywords1()); ExecuteCommand("rowannotes",array("//")); ExecuteCommand("blockannotes",array(("/*","*/"))); ExecuteCommand("syms",array("{","}","[","]","<",">","(",")",":",",","=","?","+","-","*","/",".",";")); ExecuteCommand("pairs",array(("{","}"),("[","]"),("(",")"))); ExecuteCommand("sysfun",jskeywords2()); end function jskeywords1(); begin return getjskeywords() union2 getdomeventwords(); end function jskeywords2(); begin return getjsclasswords() union2 getjsfunwords(); end end type TcssSynHighLighter = class(tcustomsynhighlighter) function create(AOwner); begin inherited; keywordcolor := 0xff0000; stringcolor := 0x968080; annotationcolor := 0x8D9600; ExecuteCommand("strings",array(('"',"\\"))); ExecuteCommand("keywords",getcsswords()); ExecuteCommand("rowannotes",array()); ExecuteCommand("blockannotes",array(("/*","*/"))); ExecuteCommand("syms",array("{","}","[","]","<",">","(",")",";",":",",","=","?","+","*","/",".","#")); ExecuteCommand("pairs",array(("{","}"),("[","]"),("(",")"))); ExecuteCommand("sysfun",array()); end end type ttfmhighlighter = class(tcustomsynhighlighter) function create(AOwner); begin inherited; ExecuteCommand("strings",array(('"',"\\"))); ExecuteCommand("keywords",array("object","end","inherited")); ExecuteCommand("rowannotes",array()); ExecuteCommand("blockannotes",array(("{","}"))); ExecuteCommand("syms",array("{","}","[","]","<",">",":",",","=")); ExecuteCommand("pairs",array(("{","}"),("[","]"),("<",">"),("object","end"),("inherited","end"))); end end implementation function getcsswords(); begin return array("align-content","align-items","align-self","all","animation","animation-delay", "animation-direction","animation-duration","animation-fill-mode","animation-iteration-count", "animation-name","animation-play-state","animation-timing-function","appearance","backface-visibility", "background","background-attachment","background-blend-mode","background-clip","background-color", "background-image","background-origin","background-position","background-repeat","background-size", "border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius", "border-bottom-style","border-bottom-width","border-collapse","border-color","border-image", "border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width", "border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right", "border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top", "border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width", "border-width","bottom","box-align","box-direction","box-flex","box-flex-group","box-lines","box-ordinal-group", "box-orient","box-pack","box-shadow","box-sizing","caption-side","clear","clip","color","column-count","column-fill", "column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width", "columns","content","counter-increment","counter-reset","cursor","direction","display","empty-cells","filter","flex", "flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","font","font-face","font-family", "font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","grid-columns","grid-rows", "hanging-punctuation","height","icon","justify-content","keyframes","left","letter-spacing","line-height","list-style", "list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top", "max-height","max-width","media","min-height","min-width","mix-blend-mode","object-fit","object-position","nav-down","nav-index", "nav-left","nav-right","nav-up","opacity","order","outline","outline-color","outline-offset","outline-style","outline-width", "overflow","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page-break-after", "page-break-before","page-break-inside","perspective","perspective-origin","position","punctuation-trim","quotes","resize","right", "rotation","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last", "text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-justify", "text-outline","text-overflow","text-shadow","text-transform","text-wrap","top","transform","transform-origin","transform-style", "transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align", "visibility","white-space","width","word-break","word-spacing","word-wrap","z-index","writing-mode"); end function getcsskeywords(r); begin if not ifarray(r) then r := array(); idx := length(r); for i,v in getcsswords()do begin c := v+" "; r[idx]["caption"] := c; r[idx]["value"] := v; r[idx]["lvalue"] := lowercase(v); r[idx]["vlen"] := length(v); r[idx]["clen"] := length(c); r[idx]["order"] := 5; idx++; end end function getjskeywords(); begin return array("abstract","arguments","boolean","break","byte","case","catch","char","class","const","continue", "debugger","default","delete","do","double","else","enum","eval","export","extends","false","final","finally", "float","for","function","goto","if","implements","import","in","instanceof","int","interface","let","long", "native","new","null","package","private","protected","public","return","short","static","super","switch", "synchronized","this","throw","throws","transient","true","try","typeof","var","void","volatile","while","with","yield"); end function getjsclasswords(); begin return array("Date","hasOwnProperty","Infinity","isFinite","isNaN","isPrototypeOf","Math", "NaN","name","Number","Object","prototype","String","toString","undefined","valueOf"); end function getjsfunwords(); begin return array("$","alert","anchor","anchors","area","assign","blur","button","checkbox", "clearInterval","clearTimeout","clientInformation","close","closed","confirm", "constructor","crypto","decodeURI","decodeURIComponent","defaultStatus","document", "element","elements","embed","embeds","encodeURI","encodeURIComponent","escape","event", "fileUpload","focus","form","forms","frame","innerHeight","innerWidth","layer","layers", "link","location","mimeTypes","navigate","navigator","frames","frameRate","hidden","history", "image","images","offscreenBuffering","open","opener","option","outerHeight","outerWidth","packages", "pageXOffset","pageYOffset","parent","parseFloat","parseInt","password","pkcs11","plugin","prompt", "propertyIsEnum","radio","reset","screenX","screenY","scroll","secure","setInterval", "setTimeout","status","submit","taint","text","textarea","top","unescape","untaint","window"); end function getdomeventwords(); begin return array("onblur","onclick","onerror","onfocus","onkeydown","onkeypress","onkeyup","onmouseover","onload","onmouseup","onmousedown","onsubmit"); end function getjskeywordstip(r); begin if not ifarray(r) then r := array(); idx := length(r); for i,v in getjskeywords() do begin c := v+" "; r[idx]["caption"] := c; r[idx]["value"] := v; r[idx]["lvalue"] := lowercase(v); r[idx]["vlen"] := length(v); r[idx]["clen"] := length(c); r[idx]["order"] := 4; idx++; end //"Array","function","length","eval", for i,v in getjsclasswords() do begin c := v+" "; r[idx]["caption"] := c; r[idx]["value"] := v; r[idx]["lvalue"] := lowercase(v); r[idx]["vlen"] := length(v); r[idx]["clen"] := length(c); r[idx]["order"] := 4; idx++; end //"all","select","self", for i,v in getjsfunwords()do begin c := v+" "; r[idx]["caption"] := c; r[idx]["value"] := v; r[idx]["lvalue"] := lowercase(v); r[idx]["vlen"] := length(v); r[idx]["clen"] := length(c); r[idx]["order"] := 4; idx++; end for i,v in getdomeventwords() do begin c := v+" "; r[idx]["caption"] := c; r[idx]["value"] := v; r[idx]["lvalue"] := lowercase(v); r[idx]["vlen"] := length(v); r[idx]["clen"] := length(c); r[idx]["order"] := 4; idx++; end end type tcolor = class() function create(c); begin fcolor := c; end changed; property color read fcolor write setcolor; private function setcolor(cl); begin if (cl>=0 or cl<0) and cl<>fcolor then begin fcolor := cl; changed := true; end end fcolor; end type TBBState =class(tpairstate) //括号状态 function Create(t); begin inherited; end end type TTsfFileParser = class() //文件解析 private fiofs; public function Create(); begin FNsCaches := array(); fmsgcaches := array(); fiofs := ioFileseparator(); FCacheDir :=TS_GetUserProfileHome()+"TslSynMemo"+fiofs+"cmpCaches";// d["value"]; //FCacheAbsFileName := FCacheDir+"\\cacheabstruct.stm"; FFindDirs := array(); end function DispatchMethod(o,d);//分发消息 begin if not ifarray(d) then return ; case d["method"] of "cachedir": //缓存目录 begin scache := d["value"] ; r := FCacheDir; if not(scache and ifstring(scache)) then return r; FCacheDir := scache; Clearcache(); return r; end "getbyname": //获得 begin return LoadByName(d["value"]); end "finddirs": //查找目录 begin return DirSet(d["value"]); end "namespace": begin end "getfinddirs": begin return FFindDirs; end "filechanged": //文件改变 begin filechanged(d["value"]); end "getfullpath": begin if not ifarray(FFilePaths) then return ""; r := FFilePaths[lowercase(d["value"])+".tsf"]; return r; end "getprojecttsfs": begin return getprojecttsfs(); end "allfunctions": begin return getallfunctions(); end "parserstring": begin r := parserstring(o,d); return r; end end end private function addnsfile(us); begin if not ifarray(us) then return array(); r := us; rl := length(r); for i,v in us do begin for j,vj in FNsCaches[lowercase(v)] do begin if vj then begin r[rl++] := v+j; end end end return r; end function getinheriteds(r,m,dounits,us,uso,cs,cso); begin if not ifarray(us) then us := array(); if not ifarray(uso) then uso := array(); if not ifarray(cs) then cs := array(); if not ifarray(cso) then cso := array(); for i,v in addnsfile(r["units"]) do begin //vfn := checknamespacename(v); vfn := v; if m=(lowercase(vfn)+".tsf") then continue; vi := LoadByName(vfn); if vi then begin if dounits[vi["msg"]] then begin continue; end dounits[vi["msg"]] := 1 ; us[length(us)] := vfn; uso[length(uso)] := vi; getinheriteds(vi,m,dounits,us,uso,cs,cso); end end for i,v in addnsfile(r["class"]) do begin vfn := v; //vfn := checknamespacename(v); if m=(lowercase(vfn)+".tsf") then continue; vi := LoadByName(vfn); if vi then begin if dounits[vi["msg"] ] then continue; dounits[vi["msg"]] := 1; cs[length(cs)] := vfn; cso[length(cso)] := vi; getinheriteds(vi,m,dounits,us,uso,cs,cso); end end end function parserstring(o,d); begin rti := 0; rt := array(); m := d["minus"]; if ifstring(m) then m := lowercase(m); filechanged(m); FormatFile(rti,FCacheS,rt,3,m); if m and ifarray(FCacheS) then begin r := FCacheS[m]; end if r then begin //echo "\r\nlodad"; vmsg := r["msg"]; end else begin s := d["value"]; if not(s and ifstring(s)) then return rt ; if errtslcode(s) then return rt; r := unit(utssvr_api_c).get_tsl_tokenizeex(s,1);//tsl_tokenizeex_2_(s,1); if not( r and ifarray(r)) then return rt; cls := array(); ScriptDelBlocks(r["blcks"],str2array(s,"\n"),cls); r["blcks"] := cls; vmsg := getmsgd_Crc32(s);//GetMsgdigest(s,0); end ext := array(); FormatFunction(rti,r["functions"],rt,"",r["lines"],ext,1); FormatBlocks(rti,r["blcks"],rt,"",nil,ext,1); FormatWords(rti,r["words"],rt,"",ext,1); dounits := array(vmsg:1); getinheriteds(r,m,dounits,us,uso,cs,cso); for i,v in us do //单元 begin vfn := v; vi := uso[i]; ext := array(); FormatFunction(rti,vi["functions"],rt,vfn,vi["lines"],ext,4); FormatBlocks(rti,vi["blcks"],rt,vfn,nil,ext,4); FormatWords(rti,vi["words"],rt,vfn,ext,4); end for i,v in cs do //类 begin vfn := v; vi := cso[i]; ext:= array(); FormatFunction(rti,vi["functions"],rt,vfn,vi["lines"],ext,4); FormatWords(rti,vi["words"],rt,vfn,ext,4); end //FormatFile(rti,FCacheS,rt,3,m); return rt; //return o.postmessage(r); end function getallfunctions(); begin filechanged(); if not ifarray(FCacheS) then return array(); rti :=0; rt := array(); ext := array(); for i,v in FCacheS do begin vfn := v["name"]; FormatFunction(rti,v["functions"],rt,vfn,v["lines"],ext); FormatBlocks(rti,v["blcks"],rt,vfn,nil,ext); end return rt; end function checknamespacename(v); begin for ii in FCacheS do begin if pos(v+"@",ii)=1 then begin return ii[1:length(ii)-4]; end end return v; end function FormatFile(idx,r,d,od,m); //文件 begin for v,vv in r do begin if v=m then continue; //echo FFilePaths; if FFilePaths and not(FFilePaths[v]) then continue; //已经排除 wd := vv["functions"][0]; nns := vv["nspace"]; if wd and ifarray(wd) and (wd0:=wd[0]) and wd0 and (v=lowercase(wd0)+nns+".tsf") then // begin t := Formatfparams(wd)+" "+inttostr(vv["lines"][0]); d[idx]["value"]:= wd0; d[idx]["lvalue"] := lowercase(wd0); d[idx]["vlen"] := length(wd0); d[idx]["clen"] := length(t); d[idx]["jump"] := true; d[idx]["caption"] :=t; d[idx]["file"] := wd0+nns; if od>=0 then d[idx]["order"] := od; d[idx]["line"] := vv["lines"][0]; idx++; continue; end else begin if length(v)>4 then begin wd0 := vv["words"][0]; if wd0 and ( (lowercase(wd0)+nns+".tsf")=v) then begin end else wd0 := v[1:length(v)-4]; d[idx]["value"]:= wd0; d[idx]["lvalue"] := lowercase(wd0); d[idx]["vlen"] := length(wd0); t := wd0+" " ; d[idx]["jump"] := true; d[idx]["caption"] := t; d[idx]["clen"] := length(t); d[idx]["file"] := wd0+nns; d[idx]["line"] := 1; idx++; end end continue; wd0 := vv["words"][0]; if wd0 and ifstring(wd0) and ( v=lowercase(wd0)+vv["nspace"]+".tsf") then // begin d[idx]["value"]:= wd0; d[idx]["lvalue"] := lowercase(wd0); d[idx]["vlen"] := length(wd0); t := wd0+" " ; d[idx]["jump"] := true; d[idx]["caption"] := t; d[idx]["clen"] := length(t); d[idx]["file"] := wd0+vv["nspace"]; d[idx]["line"] := 1; idx++; end end end function FormatWords(idx,r,d,f,ext,od); //单词 begin if not ifarray(ext) then ext := array(); for i,v in r do begin llv := lowercase(v); if ext[llv] then begin continue; end d[idx]["value"]:= v; d[idx]["lvalue"] := llv; d[idx]["vlen"] := length(v); c := v+" "; if f then begin c+= f; end d[idx]["caption"] := c; d[idx]["clen"] := length(c); if od>=0 then d[idx]["order"] := od; idx++; end end function ScriptDelBlocks(blcks,strs,r); begin if not blcks then return ; for i,v in blcks do begin if v["mtype"]=3 then begin idx := v["mbeg"]-1; s := strs[idx]; if ifstring(s) and s then begin if ParseRegExpr("type\\s+(\\w+)\\s*=\\s*Class",s,"i",result,MPos,Mlen)=1 then begin r[length(r)] := array(result[0,1],idx+1); end end end ScriptDelBlocks(v["msub"],strs,r); end end function FormatBlocks(idx,r,d,f,rr,ext,od); begin if not ifarray(ext) then ext := array(); for i,v in r do begin //if not(lines[i]>0) then continue; v0 := v[0]; li := v[1]; d[idx]["jump"] := 1; t := v0+" "; d[idx]["value"]:= v0; lvl := lowercase(v0); d[idx]["lvalue"]:= lvl; ext[lvl] := true; d[idx]["vlen"] := length(v0); if f then t+=" "+f; if li>=0 then t+="("+inttostr(li)+")"; d[idx]["clen"] := length(t); d[idx]["caption"] := t; d[idx]["file"] := f; d[idx]["line"] := li; if od>=0 then d[idx]["order"] := od; idx++; end end function FormatFunction(idx,r,d,f,lines,ext,od) //函数 begin if not ifarray(ext) then ext := array(); for i,v in r do begin //if not(lines[i]>0) then continue; v0 := v[0]; li := lines[i]; d[idx]["jump"] := 1; if li .& 0x40000000 then //pro begin t := v0 +" "; li := li .& 0x3FFFFFFF; //d[idx]["type"] := "pro"; end else begin if li>0 then t := Formatfparams(v)+ " "; else t := Formatfparams(v)+ " "; if li .& 0x80000000 then begin li := li .& 0x3FFFFFFF; end end d[idx]["value"]:= v0; lvl := lowercase(v0); d[idx]["lvalue"]:= lvl; ext[lvl] := true; d[idx]["vlen"] := length(v0); if f then t+=" "+f; if li>=0 then t+="("+inttostr(li)+")"; d[idx]["clen"] := length(t); d[idx]["caption"] := t; d[idx]["file"] := f; d[idx]["line"] := li; if od>=0 then d[idx]["order"] := od; idx++; end end function Formatfparams(d); //函数参数 begin r := ""; r+=d[0]; lend := length(d)-1; r+="("; for i:= 1 to lend do begin r+=d[i]; if id["fullpath"]) then begin return 0; end nns := d["nspace"]; if nns then begin nn := d["name"]; FNsCaches[nn][nns] := 1; end if g then return d; return 1; end end end function setnamespace(ns); begin if FNamespace<>ns then begin FNamespace := ns; ClearCache(FFindDirs?true:false); end end function DirSet(d_); //设置 begin if not ifarray(d_) then return FFindDirs; d := format_dirs(d_); if d=FFindDirs then return d; r := FFindDirs; FFinddirsseted := true; if ifarray(d) and d then begin cl := FFindDirs?true:false; FFindDirs := d; ClearCache(cl); end return r; end function format_dirs(d); begin r := array(); idx := 0; for i,v in d do begin if ifstring(v) and v then begin vlen := length(v); if v[vlen]=fiofs then r[idx] := v[1:(vlen-1)]; else r[idx] := v; idx++; end end return r; end function ClearCache(cl); //清空缓存 begin if cl then begin DeleteAllFiles(FCacheDir); end FFileNames := array(); FFilePaths := array(); FCacheS := array(); FNsCaches := array(); end function filechanged(d); begin ParserFindDir(d); end private FFinddirsseted; FFileWorker; FFilePaths; FCacheS; //缓存 FNsCaches; FCacheblk; FFileNames; //文件名 FCacheDir; //缓存目录非 \结尾 FCacheList;//目录列表 以 //FCacheAbsFileName;//缓存概要 FFindDirs; //查找目录 FNamespace; //别名 fmsgcaches; function errtslcode(s); //判断 function procedure结尾搞不定 begin return 0; return 0; end end initialization end.