diff options
Diffstat (limited to 'lib/wx/api_gen/wx_gen_cpp.erl')
-rw-r--r-- | lib/wx/api_gen/wx_gen_cpp.erl | 1220 |
1 files changed, 1220 insertions, 0 deletions
diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl new file mode 100644 index 0000000000..fd0bea04ae --- /dev/null +++ b/lib/wx/api_gen/wx_gen_cpp.erl @@ -0,0 +1,1220 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%%------------------------------------------------------------------- +%%% File : wx_gen_cpp.erl +%%% Author : Dan Gudmundsson <[email protected]> +%%% Description : +%%% +%%% Created : 19 Feb 2007 by Dan Gudmundsson <[email protected]> +%%%------------------------------------------------------------------- +-module(wx_gen_cpp). + +-include("wx_gen.hrl"). + +-compile(export_all). + +-import(lists, [foldl/3,foldr/3,reverse/1, keysearch/3, map/2, filter/2]). +-import(gen_util, [lowercase/1, lowercase_all/1, uppercase/1, uppercase_all/1, + open_write/1, close/0, c_copyright/0, w/2, w/1, + args/3, strip_name/2]). +-import(wx_gen, [next_id/1]). + +gen(Defs) -> + open_write("../c_src/gen/wxe_derived_dest.h"), + c_copyright(), + w("~n/***** This file is generated do not edit ****/ ~n~n", []), + gen_derived_dest(Defs), + close(), + + open_write("../c_src/gen/wxe_funcs.cpp"), + c_copyright(), + Res = gen_funcs(Defs), + close(), + + open_write("../c_src/gen/wxe_macros.h"), + c_copyright(), + gen_macros(), + close(), + + open_write("../c_src/gen/wxe_init.cpp"), + c_copyright(), + build_enums(), + close(), + + build_events(), + Res. + +gen_derived_dest(Defs) -> + [gen_derived_dest_2(Class) || Class <- Defs], + + UglySkipList = ["wxCaret", "wxCalendarDateAttr", + "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject" + ], + + ?WTC("gen_derived_dest"), + w("void WxeApp::delete_object(void *ptr, wxeRefData *refd) {~n", []), + w(" switch(refd->type) {~n", []), + Case = fun(#class{name=Class, id=Id, abstract=IsAbs, parent=P}) when P /= "static" -> + UglyWorkaround = lists:member(Class, UglySkipList), + case hd(reverse(wx_gen_erl:parents(Class))) of + root when IsAbs == false, UglyWorkaround == false -> + w(" case ~p: delete (~s *) ptr; break;~n", [Id, Class]); + root when IsAbs == false, UglyWorkaround == true -> + w(" case ~p: /* delete (~s *) ptr;" + "These objects must be deleted by owner object */ " + "break;~n", [Id, Class]); + _ -> ok + end; + (_) -> ok + end, + [Case(Class) || Class <- Defs], + w(" default: delete (wxObject *) ptr;~n", []), + w("}}~n~n", []). + +gen_derived_dest_2(C=#class{name=Class}) -> + case is_derived(C) of + true -> + ?WTC("gen_derived_dest_2"), + w("class E~s : public ~s { ~n",[Class,Class]), + case Class of + "wxGLCanvas" -> %% Special for cleaning up gl context + w(" public: ~~E~s() {deleteActiveGL(this);" + "((WxeApp *)wxTheApp)->clearPtr(this);}; ~n", [Class]); + _ -> + w(" public: ~~E~s() {((WxeApp *)wxTheApp)->clearPtr(this);}; ~n", [Class]) + end, + gen_constructors(C), + w("}; ~n~n", []); + false -> + ignore + end. + +gen_constructors(#class{name=Class, methods=Ms0}) -> + Ms = lists:append(Ms0), + Cs = lists:filter(fun(#method{method_type=MT}) -> MT =:= constructor end, Ms), + [gen_constructor(Class, Const) || Const <- Cs]. + +gen_constructor(_Class, #method{where=merged_c}) -> ok; +gen_constructor(_Class, #method{where=erl_no_opt}) -> ok; +gen_constructor(Class, _M=#method{params=Ps}) -> + Gen1 = fun(#param{name=N, type=T}) -> gen_type(T,1) ++ N end, + Gen2 = fun(#param{name=N, type=T}) -> gen_type(T,2) ++ N end, + CallA = fun(#param{name=N}) -> N end, + HaveMergedType = fun(#param{type={merged,_,_,_,_,_,_}}) -> true; (_) -> false end, + ?WTC("gen_constructor"), + case lists:any(HaveMergedType, Ps) of + false -> + w(" E~s(~s) : ~s(~s) {};~n", + [Class,args(Gen1,",",Ps),Class,args(CallA,",",Ps)]); + true -> + w(" E~s(~s) : ~s(~s) {};~n", + [Class,args(Gen1,",",Ps),Class,args(CallA,",",Ps)]), + w(" E~s(~s) : ~s(~s) {};~n", + [Class,args(Gen2,",",Ps),Class,args(CallA,",",Ps)]) + end. + +gen_type(#type{name=Type, ref={pointer,1}, mod=Mod},_) -> + mods(Mod) ++ to_string(Type) ++ " * "; +gen_type(#type{name=Type, ref={pointer,2}, mod=Mod},_) -> + mods(Mod) ++ to_string(Type) ++ " ** "; +gen_type(#type{name=Type, ref=reference, mod=Mod},_) -> + mods(Mod) ++ to_string(Type) ++ "& "; +gen_type(#type{name=Type, ref=undefined, base=binary, mod=Mod},_) -> + mods(Mod) ++ to_string(Type) ++ " * "; +gen_type(#type{name=Type, ref=undefined, single=array, mod=Mod},_) -> + mods(Mod) ++ to_string(Type) ++ " * "; +gen_type(#type{name=Type, ref=undefined, mod=Mod},_) -> + mods(Mod) ++ to_string(Type) ++ " "; +gen_type({merged, _, T1, _,_, _T2,_}, 1) -> + gen_type(T1,error); +gen_type({merged, _, _T1,_, _, T2,_}, 2) -> + gen_type(T2,error). + +gen_funcs(Defs) -> + w("~n/***** This file is generated do not edit ****/ ~n~n"), + w("#include <wx/wx.h>~n"), + w("#include \"../wxe_impl.h\"~n"), + w("#include \"../wxe_events.h\"~n"), + w("#include \"../wxe_return.h\"~n"), + w("#include \"wxe_macros.h\"~n"), + w("#include \"wxe_derived_dest.h\"~n~n"), + + w("void WxeApp::wxe_dispatch(wxeCommand& Ecmd)~n{~n"), + w(" char * bp = Ecmd.buffer; ~n"), + w(" wxeMemEnv *memenv = getMemEnv(Ecmd.port);~n"), +%% w(" wxMBConvUTF32 UTFconverter;~n"), + w(" wxeReturn rt = wxeReturn(WXE_DRV_PORT, Ecmd.caller, true);~n"), + w(" try { ~n"), + w(" switch (Ecmd.op) ~n{~n"), +%% w(" case WXE_CREATE_PORT: ~n", []), +%% w(" { newMemEnv(Ecmd.port); } break; ~n", []), +%% w(" case WXE_REMOVE_PORT: ~n", []), +%% w(" { destroyMemEnv(Ecmd.port); } break; ~n", []), + w(" case DESTROY_OBJECT: { ~n"), + w(" wxObject *This = (wxObject *) getPtr(bp,memenv); "), + w(" if(This) {"), + w(" ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n"), + w(" delete This; }~n } break; ~n"), + w(" case WXE_REGISTER_OBJECT: {~n" + " registerPid(bp, Ecmd.caller, memenv);~n" + " rt.addAtom(\"ok\");~n" + " break;~n" + " }~n"), + + Res = [gen_class(Class) || Class <- Defs], + + w(" default: {~n"), + w(" wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false);"), + w(" error.addAtom(\"_wxe_error_\");~n"), + w(" error.addInt((int) Ecmd.op);~n"), + w(" error.addAtom(\"not_supported\");~n"), + w(" error.addTupleCount(3);~n"), + w(" error.send();~n"), + w(" return ;~n"), + w(" }~n"), + w("} // switch~n"), + w(" rt.send();~n"), + w("} catch (wxe_badarg badarg) { // try ~n"), + w(" wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false);"), + w(" error.addAtom(\"_wxe_error_\");~n"), + w(" error.addInt((int) Ecmd.op);~n"), + w(" error.addAtom(\"badarg\");~n"), + w(" error.addInt((int) badarg.ref);~n"), + w(" error.addTupleCount(2);~n"), + w(" error.addTupleCount(3);~n"), + w(" error.send();~n"), + w("}} /* The End */ ~n"), + Res. + +gen_class(C=#class{name=Name,methods=Ms,options=Opts}) -> + put(current_class, Name), + NewMs = + case lists:member(taylormade, Opts) of + true -> + {ok, Bin} = file:read_file(filename:join([wx_extra,Name++".c_src"])), + ?WTC("gen_class"), + w("~s~n", [binary_to_list(Bin)]), + Ms; + false -> + case lists:keysearch(ifdef,1,Opts) of + {value, {ifdef, What}} -> + w("#if ~p~n",[What]), + Methods = lists:flatten(Ms), + MsR = [gen_method(Name,M) || + M <- lists:keysort(#method.id, Methods)], + w("#endif // ~p~n",[What]), + MsR; + false -> + Methods = lists:flatten(Ms), + [gen_method(Name,M) || + M <- lists:keysort(#method.id, Methods)] + end + end, + erase(current_class), + C#class{methods=NewMs}. + +gen_method(_CName, M=#method{where=erl_no_opt}) -> M; +gen_method(CName, M=#method{where=taylormade, name=Name, id=Id}) -> + {ok, Bin} = file:read_file(filename:join([wx_extra, CName ++".c_src"])), + Str0 = binary_to_list(Bin), + %% io:format("C++ Class ~p ~p ~n", [CName, Name]), + + {match, [Str1]} = re:run(Str0, "<<"++Name++"(.*)"++Name++">>", + [dotall, {capture, all_but_first, list}]), + ?WTC("gen_method"), + w(Str1, [wx_gen_erl:get_unique_name(Id)]), + M; +gen_method(CName, M=#method{name=N,params=[Ps],method_type=destructor,id=MethodId}) -> + case hd(reverse(wx_gen_erl:parents(CName))) of + root -> + ?WTC("gen_method"), + w("case ~s: { // ~s::~s ~n", [wx_gen_erl:get_unique_name(MethodId),CName,N]), + decode_arguments([Ps]), + w(" if(This) {", []), + w(" ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n", []), + w(" delete This;}~n", []), + free_args(), + w(" break; ~n}~n", []); + object -> %% Use default + ignore + end, + M; +gen_method(CName, M=#method{name=N,params=Ps0,type=T,method_type=MT,id=MethodId}) -> + put(current_func, N), + put(bin_count,-1), + ?WTC("gen_method"), + w("case ~s: { // ~s::~s ~n", [wx_gen_erl:get_unique_name(MethodId),CName,N]), + Ps1 = declare_variables(void, Ps0), + {Ps2,Align} = decode_arguments(Ps1), + Opts = [Opt || Opt = #param{def=Def,in=In,where=Where} <- Ps2, + Def =/= none, In =/= false, Where =/= c], + decode_options(Opts, Align), + case M#method.pre_hook of + undefined -> skip; + Pre -> w(" ~s;~n", [Pre]) + end, + Ps3 = call_wx(N,{MT,CName},T,Ps2), + case M#method.post_hook of + undefined -> skip; + Post -> w(" ~s;~n", [Post]) + end, + free_args(), + build_return_vals(T,Ps3), + w(" break; ~n}~n", []), + erase(current_func), + M. + +declare_variables(void,Ps) -> + [declare_var(P) || P <- Ps]; +declare_variables(T, Ps) -> + declare_type("result", out, ignore, T), + [declare_var(P) || P <- Ps]. + +declare_var(P = #param{where=erl}) -> P; +declare_var(P = #param{where=this}) -> P; +declare_var(P = #param{name=Name,def=Def,type=Type,in=true}) when Def =/= none -> + declare_type(Name, true, Def, Type), + P; +declare_var(P = #param{in=In}) when In =/= false -> P; +declare_var(P = #param{name=Name,in=In,def=Def,type=Type}) -> + declare_type(Name, In, Def, Type), + P. + +declare_type(N,false,_,#type{name="wxArrayInt"}) -> + w(" wxArrayInt ~s;~n", [N]); +declare_type(N,false,_,#type{name="wxArrayString"}) -> + w(" wxArrayString ~s;~n", [N]); +declare_type(N,false,_,#type{base=Base,single=true,name=Type,by_val=false,mod=Mod}) + when Base =:= int; Base =:= long; Base =:= float; Base =:= double -> + w(" ~s~s ~s;~n", [mods(Mod),Type,N]); +declare_type(N,false,_,#type{base={enum,_},single=true,name=Type,by_val=false,mod=Mod}) -> + w(" ~s~s ~s;~n", [mods(Mod),Type,N]); +declare_type(N,false,_,#type{name="wxArrayTreeItemIds",ref=reference}) -> + w(" wxArrayTreeItemIds ~s;~n", [N]); +declare_type(N,false,_,#type{name="wxDateTime"}) -> + w(" wxDateTime ~s;~n", [N]); +declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=true}) + when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool -> + w(" ~s ~s=~s;~n", [Type,N,Def]); +declare_type(N,true,Def,#type{base={comp,_,_},single=true,name=Type,mod=Mod,ref={pointer,1}}) -> + w(" ~s~s *~s=~s; ~s ~s;~n", [mods(Mod),Type,N,Def,Type,N++"Tmp"]); +declare_type(N,true,Def,#type{base={comp,_,_},single=true,name=Type,ref=reference}) -> + w(" ~s ~s= ~s;~n", [Type,N,Def]); +declare_type(N,true,Def,#type{base={enum,Type},single=true}) -> + w(" ~s ~s=~s;~n", [enum_type(Type),N,Def]); +declare_type(N,true,Def,#type{base={class,_},single=true,name=Type,ref={pointer,1},mod=Mod}) -> + w(" ~s~s * ~s=~s;~n", [mods(Mod),Type,N,Def]); +declare_type(N,true,Def,#type{base={class,_},single=true,name=Type,ref=reference,mod=Mod}) -> + w(" ~s~s * ~s= &~s;~n", [mods(Mod),Type,N,Def]); +declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=false,ref={pointer,1}}) + when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool -> + w(" ~s *~s=~s;~n", [Type,N,Def]); +declare_type(N,true,Def,#type{single=true,name="wxArtClient"}) -> + w(" wxArtClient ~s= ~s;~n", [N,Def]); +declare_type(N,true,Def,#type{single=true,base=string}) -> + w(" wxString ~s= ~s;~n", [N,Def]); +%% declare_type(N,true,_Def,#type{name="wxString"}) -> +%% w(" wxString ~s= wxEmptyString;~n", [N]); +declare_type(N,true,Def,#type{base=binary, name=char}) -> + w(" char ~sD[] = {~s}, * ~s = ~sD;~n", [N,Def,N,N]); +declare_type(_N,true,_Def,void) -> + skip; +declare_type(N,true,Def,#type{name=Type, ref={pointer,2}}) -> + %% xxxx + w(" ~s ** ~s = ~s;~n", [Type,N,Def]); +declare_type(N,true,Def,#type{name=Type, single=array, ref={pointer,1}}) -> + w(" int * ~sLen = 0;~n", [N]), + w(" ~s * ~s = ~s;~n", [Type,N,Def]); +declare_type(N,true,"",#type{name="wxArrayString", single=array, ref=reference}) -> + w(" wxArrayString ~s;~n", [N]); +declare_type(N,true,Def,#type{name=Type, base={term,_}}) -> + w(" ~s * ~s= ~s;~n", [Type,N,Def]); +declare_type(N,In,Def,T) -> + ?error({unhandled_type, {N,In,Def,T}}). + +decode_options([], _Align) -> ok; +decode_options(Opts, Align) -> + align(Align, 64), + w(" while( * (int*) bp) { switch (* (int*) bp) { ~n", []), + foldl(fun decode_opt/2, 1, Opts), + w(" }}; ~n", []). + +decode_opt(#param{name=Name,type=Type}, N) -> + w(" case ~p: {bp += 4;~n", [N]), + Align = decode_arg(Name,Type,opt,1), + align(Align, 64), + w(" } break;~n", []), + N+1. + +decode_arguments(Ps0) -> + lists:mapfoldl(fun decode_arg/2,0,Ps0). + +store_free(N) -> + case get(free_args) of + undefined -> put(free_args, [N]); + List -> put(free_args, [N|List]) + end. + +free_args() -> + case get(free_args) of + undefined -> ignore; + List -> + erase(free_args), + [w(" driver_free(~s);~n", [Arg]) || Arg <- List] + end. + +decode_arg(P = #param{where=erl},A) -> {P,A}; +decode_arg(P = #param{where=c},A) -> {P,A}; +decode_arg(P = #param{in=false},A) -> {P,A}; +decode_arg(P = #param{def=Def},A) when Def =/= none -> {P,A}; +decode_arg(P = #param{name=Name,type=Type},A0) -> + A = decode_arg(Name, Type, arg, A0), + {P, A}. + +wa(Decl,DA,Get,GetA,arg) -> + w(Decl,DA), + w(Get,GetA); +wa(_Decl,_DA,Get,GetA,opt) -> + w(Get,GetA). + +decode_arg(N,#type{name=Class,base={class,_},single=true},Arg,A0) -> + A = align(A0,32), + wa(" ~s *",[Class],"~s = (~s *) getPtr(bp,memenv); bp += 4;~n",[N,Class],Arg), + A; +decode_arg(N,{merged,_,#type{name=Class,base={class,_},single=true},_,_,_,_},arg,A0) -> + A = align(A0,32), + w(" ~s * ~s = (~s *) getPtr(bp,memenv); bp += 4;~n", [Class,N,Class]), + A; +decode_arg(N,#type{base=long,single=true,name=Type},arg,A0) -> + A = align(A0,64), + w(" long * ~s = (~s *) bp; bp += 8;~n", [N,Type]), + A; +decode_arg(N,#type{base=int,single=true,mod=Mod0,name=Type,ref=Ref},Arg,A0) -> + Mod = mods(Mod0), + case Arg of + arg -> w(" ~s~s * ~s = (~s~s *) bp; bp += 4;~n", [Mod,int,N,Mod,int]); + opt when Ref =:= {pointer,1} -> + w(" ~s = (~s *) bp; bp += 4;~n", [N,int]); + opt -> + w(" ~s = (~s)*(~s~s *) bp; bp += 4;~n", [N,Type,Mod,int]) + end, + align(A0,32); +decode_arg(N,#type{base=float,single=true,name=Type},arg,A0) -> + w(" ~s * ~s = (~s *) bp; bp += 4;~n", [Type,N,Type]), + align(A0,32); +decode_arg(N,#type{base=double,single=true,name=Type},Arg,A0) -> + A = align(A0,64), + case Arg of + arg -> w(" ~s * ~s = (~s *) bp; bp += 8;~n", [Type,N,Type]); + opt -> w(" ~s = * (~s *) bp; bp += 8;~n", [N,Type]) + end, + A; +decode_arg(N,#type{base=bool,single=true,name=Type},Arg,A0) -> + case Arg of + arg -> w(" bool * ~s = (~s *) bp; bp += 4;~n", [N,Type]); + opt -> w(" ~s = *(~s *) bp; bp += 4;~n", [N,Type]) + end, + align(A0,32); +decode_arg(N,#type{base={enum,Type},single=true},Arg,A0) -> + wa(" ~s ", [enum_type(Type)], "~s = *(~s *) bp; bp += 4;;~n",[N, enum_type(Type)], Arg), + align(A0,32); +decode_arg(N,#type{base={comp,"wxDateTime",List},single=true,name=Type,ref=Ref},Arg,A0) -> + Decl = fun({int,Spec}) -> + w(" int * ~s~s = (int *) bp; bp += 4;~n", [N,Spec]) + end, + align(A0,32), + lists:foreach(Decl,List), + Name = fun({_,"Mo"}) -> "(wxDateTime::Month) *"++N++"Mo"; + ({_,"Y"}) -> "*"++N++"Y"; + ({_,Spec}) -> "(wxDateTime::wxDateTime_t) *"++N++Spec + end, + case Arg of + arg -> w(" ~s ~s = ~s(~s);~n", [Type,N,Type,args(Name, ",", List)]); + opt when Ref =:= {pointer,1} -> + w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n", + [N,Type,args(Name, ",", List), N,N]); + opt -> + w(" ~s = ~s(~s);~n", [N,Type,args(Name, ",", List)]) + end, + (A0+length(List)) rem 2; +decode_arg(N,#type{base={comp,_,List},single=true,name=Type,ref=Ref},Arg,A0) -> + Decl = fun({int,Spec}) -> + w(" int * ~s~s = (int *) bp; bp += 4;~n", [N,Spec]); + ({double, Spec}) -> + w(" wxDouble * ~s~s = (wxDouble *) bp; bp += 8;~n", [N,Spec]) + end, + case hd(List) of + {int, _} -> align(A0,32); + {double, _} -> align(A0,64) + end, + lists:foreach(Decl,List), + Name = fun({_,Spec}) -> "*"++N++Spec end, + case Arg of + arg -> w(" ~s ~s = ~s(~s);~n", [Type,N,Type,args(Name, ",", List)]); + opt when Ref =:= {pointer,1} -> + w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n", + [N,Type,args(Name, ",", List), N,N]); + opt -> + w(" ~s = ~s(~s);~n", [N,Type,args(Name, ",", List)]) + end, + case hd(List) of + {int, _} -> (A0+length(List)) rem 2; + {double, _} -> 0 + end; + +decode_arg(N,#type{name=Class,base={ref,"wxTreeItemId"},single=true},Arg,A0) -> + A = align(A0,32), + wa(" ~s ",[Class],"~s = wxTreeItemId(getPtr(bp,memenv)); bp += 4;~n",[N],Arg), + A; +decode_arg(N,#type{name="wxChar", single=S},Arg,A0) + when S =/= true -> + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + wa(" wxString", []," ~s = wxString(bp, wxConvUTF8);~n", [N],Arg), + w(" bp += *~sLen+((8-((~p+ *~sLen) & 7)) & 7);~n", [N,4*((A0+1) rem 2),N]), + 0; +decode_arg(N,#type{base=string, name="wxFileName"},Arg,A0) -> + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + wa(" wxString", []," ~sStr = wxString(bp, wxConvUTF8);~n", [N],Arg), + w(" bp += *~sLen+((8-((~p+ *~sLen) & 7)) & 7);~n", [N,4*((A0+1) rem 2),N]), + w(" wxFileName ~s = wxFileName(~sStr);~n",[N,N]), + 0; +decode_arg(N,#type{base=string},Arg,A0) -> + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + wa(" wxString", []," ~s = wxString(bp, wxConvUTF8);~n", [N],Arg), + w(" bp += *~sLen+((8-((~p+ *~sLen) & 7)) & 7);~n", [N,4*((A0+1) rem 2),N]), + 0; +decode_arg(N,#type{name="wxArrayString"},Place,A0) -> + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + case Place of + arg -> w(" wxArrayString ~s;~n", [N]); + opt -> ignore %% Allready declared + end, + w(" int ~sASz = 0, * ~sTemp;~n", [N,N]), + w(" for(int i=0; i < *~sLen; i++) {~n", [N]), + w(" ~sTemp = (int *) bp; bp += 4;~n", [N]), + w(" ~s.Add(wxString(bp, wxConvUTF8));~n", [N]), + w(" bp += *~sTemp;~n", [N]), + w(" ~sASz += *~sTemp+4;~n }~n", [N,N]), + w(" bp += (8-((~p+ ~sASz) & 7 )) & 7;~n", [4*((A0+1) rem 2),N]), + 0; + +decode_arg(N,#type{name="wxArrayInt"},arg,A0) -> + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + w(" wxArrayInt ~s;~n", [N]), + w(" for(int i=0; i < *~sLen; i++) {", [N]), + w(" ~s.Add(*(int *) bp); bp += 4;}~n", [N]), + w(" bp += ((*~sLen + ~p) % 2 )*4;~n",[N, (A0+1)]), + 0; +decode_arg(N,#type{name="wxArrayDouble"},arg,A0) -> + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + align(A0+1,64), + w(" wxArrayDouble ~s;~n", [N]), + w(" for(int i=0; i < *~sLen; i++) {", [N]), + w(" ~s.Add(*(int *) bp); bp += 4;}~n", [N]), + 0; +decode_arg(_N,#type{base=eventType},_Arg,A0) -> +%% w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), +%% case Arg of +%% arg -> +%% w(" int ~s = wxeEventTypeFromAtom(bp);bp += *~sLen;~n",[N,N]), +%% w(" char *class_name = bp;~n", []), +%% w(" wxeCallbackData * Evt_cb = new wxeCallbackData(Ecmd.caller,This,class_name);~n", +%% []) +%% end, + A0; +decode_arg(N,#type{name=Type,base=binary,mod=Mod0},Arg,A0) -> + Mod = mods([M || M <- Mod0]), + case Arg of + arg -> + w(" ~s~s * ~s = (~s~s*) Ecmd.bin[~p]->base; ~n", + [Mod,Type,N,Mod,Type, next_id(bin_count)]); + opt -> + w(" ~s = (~s~s*) Ecmd.bin[~p]->base; ~n", + [N,Mod,Type,next_id(bin_count)]) + end, + A0; +decode_arg(N,#type{base={term,"wxTreeItemData"},mod=Mod0},Arg,A0) -> + Mod = mods([M || M <- Mod0]), + Type = "wxETreeItemData", + BinCnt = next_id(bin_count), + case Arg of + arg -> + w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base); ~n", + [Mod,Type,N,Type,BinCnt,BinCnt]); + opt -> + w(" ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base); ~n", + [N,Type,BinCnt,BinCnt]) + end, + A0; +decode_arg(N,#type{name=Type,base={term,_},mod=Mod0},Arg,A0) -> + Mod = mods([M || M <- Mod0]), + BinCnt = next_id(bin_count), + case Arg of + arg -> + w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]); ~n", + [Mod,Type,N,Type,BinCnt]); + opt -> + w(" ~s = new ~s(Ecmd.bin[~p]); ~n", + [N,Type,BinCnt]) + end, + A0; +decode_arg(N,#type{single=array,base=int},Arg,A0) -> + case Arg of + arg -> + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + w(" int * ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n", + [N,N,(A0+1) rem 2,N]); + opt -> + w(" ~sLen = (int *) bp; bp += 4;~n", [N]), + w(" ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n", + [N,N,(A0+1) rem 2,N]) + end, + 0; +decode_arg(N,#type{by_val=true,single=array,base={comp,Class="wxPoint",_}},arg,A0) -> + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + w(" ~s *~s;~n",[Class,N]), + w(" ~s = (~s *) driver_alloc(sizeof(~s) * *~sLen);~n",[N,Class,Class,N]), + store_free(N), + w(" for(int i=0; i < *~sLen; i++) {~n", [N]), + w(" int x = * (int *) bp; bp += 4;~n int y = * (int *) bp; bp += 4;~n", []), + w(" ~s[i] = wxPoint(x,y);}~n", [N]), + align(A0,32); +decode_arg(N,#type{by_val=true,single=array,base={class,Class}},arg,A0) -> + A = align(A0,32), + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + w(" ~s *~s;~n",[Class,N]), + w(" ~s = (~s *) driver_alloc(sizeof(~s) * *~sLen);", [N, Class, Class, N]), + store_free(N), + w(" for(int i=0; i < *~sLen; i++) {", [N]), + w(" ~s[i] = * (~s *) getPtr(bp,memenv); bp += 4;}~n", [N,Class]), + w(" bp += ((~p+ *~sLen)%2 )*4;~n", [A, N]), + 0; +decode_arg(N,#type{name=Type,single=list,base={class,Class}},arg,A0) -> + w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]), + A = align(A0,32), + w(" ~s ~s;~n",[Type,N]), + w(" for(int i=0; i < *~sLen; i++) {", [N]), + w(" ~s.Append(*(~s *) getPtr(bp,memenv)); bp += 4;}~n", [N,Class]), + w(" bp += ((~p+ *~sLen)%2 )*4;~n", [A,N]), + 0; +decode_arg(Name,T, Arg,_A) -> + ?error({unhandled_type, {Name,T, Arg}}). + +align(0, 32) -> 1; +align(1, 32) -> 0; +align(0, 64) -> 0; +align(1, 64) -> + w(" bp += 4; /* Align */~n"), + 0; +align(N,Sz) -> + align(N rem 2, Sz). + +call_wx(_N,{constructor,_},#type{base={class,RClass}},Ps) -> + #class{id=Id} = ClassDef = get({class,RClass}), + Class = case is_derived(ClassDef) of + true -> "E" ++ RClass; + false -> RClass + end, + w(" ~s * Result = new ~s(~s);~n", + [RClass, Class,args(fun call_arg/1, ",",filter(Ps))]), + CType = case is_window(RClass) of + true -> %% Windows have parents that should be deleted first + case is_dialog(RClass) of + true -> 2; %% Dialogs must be closed first event before windows + false -> 0 + end; + false -> + case hd(reverse(wx_gen_erl:parents(RClass))) of + root -> Id; + _ -> 1 + end + end, + case virtual_dest(ClassDef) orelse (CType =/= 0) of + true -> + w(" newPtr((void *) Result, ~p, memenv);~n", [CType]); + false -> %% Hmm window without virt dest + w(" /* Possible memory leak here, class is missing virt dest */ \n") + end, + Ps; +call_wx(N,{member,_},Type,Ps) -> + {Beg,End} = return_res(Type), + w(" if(!This) throw wxe_badarg(0);~n",[]), + w(" ~sThis->~s(~s)~s;~n",[Beg,N,args(fun call_arg/1, ",",filter(Ps)),End]), + Ps; +call_wx(N,{static,Class},Type,Ps) -> + {Beg,End} = return_res(Type), + #class{parent=Parent} = get({class,Class}), + case Parent of + "static" -> + w(" ~s::~s(~s)~s;~n",[Beg,N,args(fun call_arg/1, ",",filter(Ps)),End]); + _ -> + w(" ~s~s::~s(~s)~s;~n",[Beg,Class,N,args(fun call_arg/1, ",",filter(Ps)),End]) + end, + Ps. + + +return_res(void) -> {"", ""}; +return_res(Type = #type{mod=Mod}) -> + case lists:member(const, Mod) of + true -> + {Beg, End} = return_res1(Type), + {"const " ++ Beg, End}; + _ -> + return_res1(Type) + end. + +return_res1(#type{name=Type,ref={pointer,_}, base={term,_}}) -> + {Type ++ " * Result = (" ++ Type ++ "*)", ""}; +return_res1(#type{name=Type,ref={pointer,_}}) -> + {Type ++ " * Result = (" ++ Type ++ "*)", ""}; +return_res1(#type{name=Type,single=true,ref=reference}) -> + {Type ++ " * Result = &", ""}; +return_res1(#type{name=Type,single=true,by_val=true}) + when is_atom(Type) -> + {atom_to_list(Type) ++ " Result = ", ""}; +return_res1(#type{name=Type="wxArrayInt"}) -> + {Type ++ " Result = ", ""}; +return_res1(#type{name=Type,base={class,_},single=list,ref=reference}) -> + {Type ++ " Result = ", ""}; +return_res1(#type{name=Type,base={comp,_,_},single=array,by_val=true}) -> + {Type ++ " Result = ", ""}; +return_res1(#type{name=Type,single=true,by_val=true, base={class, _}}) -> + %% Memory leak !!!!!! XXXX BUGBUG FIXME or doument!! + case Type of + "wxImage" -> ok; + "wxFont" -> ok; + "wxBitmap" -> ok; + "wxIcon" -> ok; + "wxGraphics" ++ _ -> ok; + _ -> + io:format("~s::~s Building return value of temp ~s~n", + [get(current_class),get(current_func),Type]) + end, + %% #class{id=Id} = get({class,Type}), + {Type ++ " * Result = new " ++ Type ++ "(", "); newPtr((void *) Result," + ++ "3, memenv);"}; +return_res1(#type{base={enum,_Type},single=true,by_val=true}) -> + {"int Result = " , ""}; +return_res1(#type{name="wxCharBuffer", base={binary,_},single=true,by_val=true}) -> + {"char * Result = ", ".data()"}; +return_res1(#type{name=Type,single=array,ref=reference}) -> + {Type ++ " Result = ", ""}; +return_res1(#type{name=Type,single=true,by_val=true}) -> + {Type ++ " Result = ", ""}. + +filter(Ps) -> + lists:filter(fun filter_arg/1, Ps). +filter_arg(#param{where=erl}) -> false; +filter_arg(#param{where=this}) -> false; +filter_arg(#param{}) -> true. +%%filter_arg(#param{def=Def, in=In}) -> Def =:= none orelse In =:= false. + + +call_arg(#param{where=c, alt={length,Alt}}) when is_list(Alt) -> + "*" ++ Alt ++ "Len"; +call_arg(#param{where=c, alt={size,Id}}) when is_integer(Id) -> + %% It's a binary + "Ecmd.bin["++ integer_to_list(Id) ++ "]->size"; +call_arg(#param{name=N,def=Def,type=#type{name=Type,by_val=true,single=true,base=Base}}) + when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool -> + case Def of + none -> "(" ++ to_string(Type) ++ ") *" ++ N; + _ -> N + end; + +call_arg(#param{name=N,type=#type{base={enum,Type}, by_val=true,single=true}}) -> + "(" ++ enum_type(Type) ++") " ++ N; +call_arg(#param{name=N,type=#type{base={class,_},by_val=true,single=true}}) -> "*" ++ N; +call_arg(#param{name=N,type=#type{base={class,_},ref=reference,single=true}}) -> "*" ++ N; +call_arg(#param{name=N,type=#type{base=eventType}}) -> + N ++ ", (wxObjectEventFunction)(wxEventFunction) &WxeApp::handle_evt, Evt_cb, this"; +call_arg(#param{name=N,type=#type{by_val=true, single=_False}}) -> N; +call_arg(#param{name=N,def=Def,type=#type{by_val=false, ref={pointer,2}}}) + when Def =/= none -> N; +call_arg(#param{name=N,type=#type{by_val=false, ref={pointer,2}}}) -> "&" ++ N; +call_arg(#param{name=N,in=false,type=#type{ref=reference, single=true}}) -> N; +call_arg(#param{name=N,in=false,type=#type{by_val=false, single=true}}) -> "&" ++ N; +call_arg(#param{name=N,def=Def,type=#type{base={comp,_,_},ref={pointer,1},single=true}}) + when Def =:= none -> + "&" ++N; +call_arg(#param{name=N,type=#type{by_val=false}}) -> N; +call_arg(#param{name=N,type={merged,_,#type{base={class,_},single=true, + by_val=ByVal, + ref=Ref},_,_,_,_}}) + when ByVal =:= true; Ref =:= reference -> + "*" ++ N; +call_arg(#param{def=Def, type=void}) when Def =/= none -> Def; +call_arg(#param{name=N,type=#type{base={ref,_},by_val=true,single=true}}) -> N; +call_arg(#param{name=N,type={merged,_,_,_,_,_,_}}) -> N. + +%% call_arg(#param{name=N,type=#type{base=Tuple,ref=reference}}) +%% when is_tuple(Tuple) -> "&" ++ N; + +to_string(Type) when is_atom(Type) -> atom_to_list(Type); +to_string(Type) when is_list(Type) -> Type. + +virtual_dest(#class{abstract=true, parent="root"}) -> false; +virtual_dest(#class{abstract=true, parent="object"}) -> true; +virtual_dest(#class{abstract=true, parent=Parent}) -> + virtual_dest(get({class,Parent})); +virtual_dest(#class{methods=Ms, parent=Parent}) -> + case lists:keysearch(destructor,#method.method_type, lists:append(Ms)) of + {value, #method{method_type=destructor, virtual=Virtual}} -> + case Virtual of + undefined -> + case get({class,Parent}) of + undefined -> + case Parent of + "object" -> + true; + "root" -> + false; + _ -> + io:format("Error: ~p ~n",[Parent]), + erlang:error(no_parent) + end; + PClass -> + virtual_dest(PClass) + end; + _ -> + Virtual + end; + false -> + false + end. + +debug(F,A) -> + case get(debug) of + true -> ?warning(F,A); + _ -> ok + end. + +is_derived(#class{abstract=true}) -> false; +is_derived(C = #class{}) -> virtual_dest(C). + +is_window(Class) -> + lists:member("wxWindow", wx_gen_erl:parents(Class)). + +is_dialog(Class) -> + lists:member("wxDialog", wx_gen_erl:parents(Class)). + +build_return_vals(Type,Ps) -> + HaveType = case Type of void -> 0; _ -> 1 end, + NoOut = lists:sum([1 || #param{in=In} <- Ps, In =/= true]) + HaveType, + OutTupSz = if NoOut > 1 -> NoOut; true -> 0 end, + + build_ret_types(Type,Ps), + if + OutTupSz > 1 -> w(" rt.addTupleCount(~p);~n",[OutTupSz]); + true -> ignore + end, + Ps. + +build_ret_types(void,Ps) -> + Calc = fun(#param{name=N,in=False,type=T}, Free) when False =/= true -> + case build_ret(N, False, T) of + ok -> Free; + Other -> [Other|Free] + end; + (_, Free) -> Free + end, + lists:foldl(Calc, [], Ps); +build_ret_types(Type,Ps) -> + Free = case build_ret("Result", out, Type) of + ok -> []; + FreeStr -> [FreeStr] + end, + Calc = fun(#param{name=N,in=False,type=T}, FreeAcc) when False =/= true -> + case build_ret(N, False, T) of + ok -> FreeAcc; + FreeMe -> [FreeMe|FreeAcc] + end; + (_, FreeAcc) -> FreeAcc + end, + lists:foldl(Calc, Free, Ps). + +build_ret(Name,_,#type{base={class,Class},single=true}) -> + w(" rt.addRef(getRef((void *)~s,memenv), \"~s\");~n",[Name,Class]); +build_ret(Name,_,#type{base={ref,"wxTreeItemId"=Class},single=true}) -> + w(" rt.addRef(getRef((void *)~s.m_pItem,memenv), \"~s\");~n",[Name,Class]); +build_ret(Name,_,#type{base={term,_},single=true}) -> + w(" rt.addExt2Term(~s);~n", [Name]); +build_ret(Name,_,#type{base={binary,Size},single=true}) -> + w(" if(~s) {~n", [Name]), + w(" rt.addBinary(~s, ~s);~n", [Name,Size]), + w(" } else {rt.addAtom(\"null\");};~n"); +build_ret(Name,_,#type{name="wxUIntPtr", ref={pointer,1}, single=true}) -> + w(" rt.add(~s);~n", [Name]); +build_ret(Name,_,#type{base={enum,_Type},single=true}) -> + w(" rt.addInt(~s);~n",[Name]); +build_ret(Name,_,#type{base={comp,_,{record, _}},single=true}) -> + w(" rt.add(~s);~n", [Name]); +build_ret(Name,_,#type{base={comp,_,_},single=true, ref=reference}) -> + w(" rt.add((*~s));~n",[Name]); +build_ret(Name,_,#type{base={comp,_,_},single=true}) -> + w(" rt.add(~s);~n",[Name]); +build_ret(Name,_,#type{base=bool,single=true,by_val=true}) -> + w(" rt.addBool(~s);~n",[Name]); +build_ret(Name,both,#type{base=int,single=true,mod=M}) -> + case lists:member(unsigned, M) of + true -> w(" rt.addUint(*~s);~n",[Name]); + false -> w(" rt.addInt(*~s);~n",[Name]) + end; +build_ret(Name,_,#type{base=int,single=true,mod=M}) -> + case lists:member(unsigned, M) of + true -> w(" rt.addUint(~s);~n",[Name]); + false -> w(" rt.addInt(~s);~n",[Name]) + end; +build_ret(Name,_,#type{name="wxArrayInt"}) -> + w(" rt.add(~s);~n", [Name]); +build_ret(Name,_,#type{base={comp,_,_},single=array}) -> + w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]), + w(" rt.add(~s[i]);~n }~n",[Name]), + w(" rt.endList(~s.GetCount());~n",[Name]); +build_ret(Name,_,#type{name=List,single=list,base={class,Class}}) -> + w(" int i=0;~n"), + w(" for(~s::const_iterator it = ~s.begin(); it != ~s.end(); ++it) {~n", + [List, Name, Name]), + w(" ~s * ~sTmp = *it;~n", [Class,Name]), + w(" rt.addRef(getRef((void *)~sTmp,memenv), \"~s\"); i++;}~n",[Name,Class]), + w(" rt.endList(~s.GetCount());~n",[Name]); + +build_ret(Name,_,#type{name="wxArrayTreeItemIds"}) -> + w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]), + w(" rt.addRef(getRef((void *)~s[i].m_pItem,memenv), \"wxTreeItemId\");}~n",[Name]), + w(" rt.endList(~s.GetCount());~n",[Name]); + +build_ret(Name,_,#type{base=float,single=true}) -> +%% w(" double Temp~s = ~s;~n", [Name,Name]), + w(" rt.addFloat(~s);~n",[Name]); +build_ret(Name,_,#type{base=double,single=true}) -> + w(" rt.addFloat(~s);~n",[Name]); +build_ret(Name,_,#type{base=string,single=true}) -> + w(" rt.add(~s);~n",[Name]); +build_ret(Name,_,#type{name="wxArrayString", single=array}) -> + w(" rt.add(~s);~n", [Name]); +build_ret(Name,In,T) -> + ?error({nyi, Name,In, T}). + +mods([const|R]) -> "const " ++ mods(R); +mods([unsigned|R]) -> "unsigned " ++ mods(R); +mods([]) -> "". + +build_enums() -> + Tree = get(consts), + w(" /* This file is also generated */~n"), + w("#include <wx/wx.h>~n"), + w("#include \"../wxe_impl.h\"~n"), + w("#include \"wxe_macros.h\"~n"), + w("#include \"../wxe_return.h\"~n"), + w("void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {~n"), + NotConsts = [NC || NC = #const{is_const=false} <- gb_trees:values(Tree)], + Size = length(NotConsts), + GVars = get(gvars), + GSize = length(GVars), + w(" wxeReturn rt = wxeReturn(WXE_DRV_PORT, caller);~n"), + w(" rt.addAtom((char*)\"wx_consts\");~n"), + [build_enum(NConst) || NConst <- lists:keysort(#const.val, NotConsts)], + _Cnt = foldl(fun(Gvar, I) -> build_gvar(Gvar,I) end, 0, lists:sort(GVars)), + w(" rt.endList(~p);~n", [Size+GSize]), + w(" rt.addTupleCount(2);~n"), + w(" rt.send();~n"), + w("}~n"), + ok. + +build_enum(#const{name=Name}) -> + w(" rt.addAtom(\"~s\"); rt.addInt(~s);~n", [Name, Name]), + w(" rt.addTupleCount(2);~n"). + +build_gvar({Name, "wxColour", _Id}, Cnt) -> + w(" rt.addAtom(\"~s\"); rt.add(*(~s));~n",[Name,Name]), + w(" rt.addTupleCount(2);~n"), + Cnt; +build_gvar({Name, {address,Class}, _Id}, Cnt) -> + w(" rt.addAtom(\"~s\"); rt.addRef(getRef((void *)&~s,memenv), \"~s\");~n",[Name,Name,Class]), + w(" rt.addTupleCount(2);~n"), + Cnt+1; +build_gvar({Name, Class, _Id}, Cnt) -> + w(" rt.addAtom(\"~s\"); rt.addRef(getRef((void *)~s,memenv),\"~s\");~n",[Name,Name,Class]), + w(" rt.addTupleCount(2);~n"), + Cnt+1. + +gen_macros() -> + w("#include <wx/caret.h>~n"), %% Arrg wxw forgot?? some files + w("#include <wx/tooltip.h>~n"), + w("#include <wx/gbsizer.h>~n"), + w("#include <wx/splash.h>~n"), + w("#include <wx/grid.h>~n"), + w("#include <wx/image.h>~n"), + w("#include <wx/tglbtn.h>~n"), + w("#include <wx/calctrl.h>~n"), + w("#include <wx/dirctrl.h>~n"), + w("#include <wx/listctrl.h>~n"), + w("#include <wx/treectrl.h>~n"), + w("#include <wx/spinbutt.h>~n"), + w("#include <wx/spinctrl.h>~n"), + w("#include <wx/colordlg.h>~n"), + w("#include <wx/fdrepdlg.h>~n"), + w("#include <wx/fontdlg.h>~n"), + w("#include <wx/progdlg.h>~n"), + w("#include <wx/printdlg.h>~n"), + w("#include <wx/dcbuffer.h>~n"), + w("#include <wx/dcmirror.h>~n"), + w("#include <wx/glcanvas.h>~n"), + w("#include <wx/dcps.h>~n"), + w("#include <wx/xrc/xmlres.h>~n"), + w("#include <wx/html/htmprint.h>~n"), + w("#include <wx/stc/stc.h>~n"), + w("#include <wx/minifram.h>~n"), + w("#include <wx/sashwin.h>~n"), + w("#include <wx/laywin.h>~n"), + w("#include <wx/graphics.h>~n"), + w("#include <wx/aui/aui.h>~n"), + w("#include <wx/datectrl.h>~n"), + w("#include <wx/filepicker.h>~n"), + w("#include <wx/fontpicker.h>~n"), + w("#include <wx/clrpicker.h>~n"), + w("#include <wx/statline.h>~n"), + w("#include <wx/clipbrd.h>~n"), + w("#include <wx/splitter.h>~n"), + w("#include <wx/choicebk.h>~n"), + w("#include <wx/toolbook.h>~n"), + w("#include <wx/listbook.h>~n"), + w("#include <wx/treebook.h>~n"), + w("#include <wx/html/htmlwin.h>~n"), + w("#include <wx/html/htmlcell.h>~n"), + w("#include <wx/filename.h>~n"), + + w("~n~n", []), + [w("#define ~s_~s ~p~n", [Class,Name,Id]) || + {Class,Name,_,Id} <- wx_gen_erl:get_unique_names()], + w("~n~n"). + +build_events() -> + open_write("../c_src/gen/wxe_events.cpp"), + c_copyright(), + w("~n/***** This file is generated do not edit ****/ ~n~n"), + w("#include <wx/wx.h>~n"), + w("#include \"../wxe_impl.h\"~n~n"), + w("#include \"wxe_macros.h\"~n"), + w("#include \"../wxe_events.h\"~n~n"), + w("#include \"../wxe_return.h\"~n~n"), + + w("wxeEtype::wxeEtype(const char *name, int Id) {eName = name;cID = Id;}~n~n"), + w("WX_DECLARE_HASH_MAP(int, wxeEtype*, wxIntegerHash, wxIntegerEqual, wxeETmap );~n~n"), + + w("wxeETmap etmap; ~n~n"), + + w( +"int wxeEventTypeFromAtom(char *etype_atom) { + wxeETmap::iterator it; + for(it = etmap.begin(); it != etmap.end(); ++it) { + wxeEtype * value = it->second; + if(strcmp(value->eName, etype_atom) == 0) { + if(it->first > wxEVT_USER_FIRST) { + return it->first - wxEVT_USER_FIRST; + } else { + return it->first; + } + } + } + return -1; +} + +"), + + Evs0 = [C || {_,C=#class{event=Evs}} <- get(), Evs =/= false], + Evs = lists:keysort(#class.id, Evs0), + initEventTable(Evs), + encode_events(Evs), + close(). + +initEventTable(Evs) -> + w("void initEventTable() ~n{~n"), + w(" struct { ",[]), + w("int ev_type; int class_id; const char * ev_name;} event_types[] = ~n {~n",[]), + + lists:foreach(fun(Ev) -> init_event_classes(Ev) end, + [#class{id=0,event=[wxEVT_NULL]}|Evs]), + w(" {-1, 0, ""}~n };~n",[]), + w(" for(int i=0; event_types[i].ev_type != -1; i++) {~n",[]), + w(" if(NULL == etmap[event_types[i].ev_type]) {~n",[]), + w(" etmap[event_types[i].ev_type] = ~n" + " new wxeEtype(event_types[i].ev_name, event_types[i].class_id);~n"), + w(" } else {~n",[]), + w(" wxeEtype *prev = etmap[event_types[i].ev_type];~n" + " wxString msg(wxT(\"Duplicate event defs: \"));~n" + " msg += wxString::FromAscii(event_types[i].ev_name);~n" + " msg += wxString::Format(wxT(\" %d \"), event_types[i].class_id);~n" + " msg += wxString::FromAscii(prev->eName);~n" + " msg += wxString::Format(wxT(\" %d\"), prev->cID);~n" + " send_msg(\"internal_error\", &msg);~n" + " }~n" + " }~n", []), + w("}~n~n"). + +init_event_classes(#class{event=ETs, id=Id}) -> + F = fun({Eev, Cev, OtherClass}) -> + w(" {~w + wxEVT_USER_FIRST, ~w, ~p},~n", + [Cev, find_id(OtherClass), wx_gen_erl:event_type_name(Eev)]); + ({Ev, {test_if, Test}}) -> + w("#if ~s ~n", [Test]), + w(" {~w, ~w, ~p},~n", + [Ev, Id, wx_gen_erl:event_type_name(Ev)]), + w("#endif ~n", []); + (Ev) -> + w(" {~w, ~w, ~p},~n", + [Ev, Id, wx_gen_erl:event_type_name(Ev)]) + end, + [F(ET) || ET <- ETs]. + +find_id(OtherClass) -> + Class = get({class,atom_to_list(OtherClass)}), + %%{value, Class} = lists:keysearch(atom_to_list(OtherClass), #class.name, All), + Class#class.id. + +encode_events(Evs) -> + ?WTC("encode_events"), + w("void wxeEvtListener::forward(wxEvent& event) ~n" + "{ ~n" + "#ifdef DEBUG~n" + " if(!sendevent(&event, port)) ~n" + " fprintf(stderr, \"Couldn't send event!\\r\\n\");~n" + "#else~n" + "sendevent(&event, port);~n" + "#endif~n" + "}~n~n"), + w("int getRef(void* ptr, wxeMemEnv* memenv) ~n" + "{ ~n" + " WxeApp * app = (WxeApp *) wxTheApp;~n" + " return app->getRef(ptr,memenv);~n" + "} ~n~n"), + w("bool sendevent(wxEvent *event, ErlDrvPort port)~n{~n" + " int send_res ;~n" + " char * evClass = NULL;~n" + " wxMBConvUTF32 UTFconverter;~n" + " wxeEtype *Etype = etmap[event->GetEventType()];~n" + " wxeCallbackData *cb = (wxeCallbackData *)event->m_callbackUserData;~n" + " WxeApp * app = (WxeApp *) wxTheApp;~n" + " wxeMemEnv *memenv = app->getMemEnv(port);~n" + " if(!memenv) return 0;~n~n" + " wxeReturn rt = wxeReturn(port, cb->listener);~n"), + + w("~n rt.addAtom((char*)\"wx\");~n" + " rt.addInt((int) event->GetId());~n" + " rt.addRef(getRef((void *)(cb->obj), memenv), cb->class_name);~n" + " rt.addExt2Term(cb->user_data);~n"), + + w(" switch(Etype->cID) {~n"), + lists:foreach(fun(Ev) -> encode_event(Ev) end, Evs), + w(" }~n~n"), + + w(" rt.addTupleCount(5);~n"), + w(" if(cb->fun_id) {~n"), + w(" rt.addRef(getRef((void *)event,memenv), evClass);~n"), + w(" rt.addTupleCount(2);~n"), + w(" rt.addInt(cb->fun_id);~n"), + w(" rt.addAtom(\"_wx_invoke_cb_\");~n"), + w(" rt.addTupleCount(3);~n"), + w(" pre_callback();~n"), + w(" send_res = rt.send();~n"), + w(" if(send_res) handle_event_callback(port, cb->listener);~n"), + w(" app->clearPtr((void *) event);~n"), + w(" } else {~n"), + w(" send_res = rt.send();~n"), + w(" if(cb->skip) event->Skip();~n"), + w(" };~n"), + w(" return send_res;~n"), + w(" }~n"). + +encode_event(C = #class{name=Class, id=Id, options=Opts}) -> + ?WTC("encode_event"), + case proplists:get_value("mixed_event", Opts) of + undefined -> + w("case ~p: {// ~s~n", [Id,Class]), + encode_event2(C), + ok; + Mixed -> + w("case ~p: {// ~s or ~s~n", [Id,Class,Mixed]), + w(" if(event->IsKindOf(CLASSINFO(~s))) {~n",[Class]), + encode_event2(C), + w(" } else {~n",[]), + w(" Etype = etmap[event->GetEventType() + wxEVT_USER_FIRST];~n",[]), + encode_event2(get({class,atom_to_list(Mixed)})), + w(" }~n",[]), + ok + end, + w(" break;~n}~n"). + +encode_event2(Class = #class{name=Name}) -> + Attrs = build_event_attrs(Class), + w(" evClass = (char*)\"~s\";~n",[Name]), + w(" rt.addAtom((char*)\"~s\");~n", [wx_gen_erl:event_rec_name(Name)]), + w(" rt.addAtom(Etype->eName);~n"), + build_ret_types(void, Attrs), + w(" rt.addTupleCount(~p);~n",[length(Attrs) + 2]). + +build_event_attrs(ClassRec = #class{name=Class}) -> + Attrs0 = wx_gen_erl:filter_attrs(ClassRec), + Rename = + fun(Att = #param{name=Name,prot=public,acc=undefined}, {All,Use}) -> + {[Att#param{name= "ev->" ++ Name}|All],Use}; + (Att = #param{acc=Acc}, {All,_}) -> + {[Att#param{name= "ev->" ++ Acc}|All], true} + end, + case foldr(Rename,{[],false},Attrs0) of + {[],_} -> []; +%% {Attrs,false} -> +%% w(" ~s ev = dynamic_cast<~s&>(event);~n",[Class,Class]), +%% Attrs; + {Attrs,_} -> + w(" ~s * ev = (~s *) event;~n",[Class,Class]), + FixClass = + fun(P=#param{name=N,acc=Acc,type=#type{single=Single,by_val=ByVal, + base={class,C}}}) + when Acc =/= undefined -> + Var = var_name(N), + if Single, ByVal -> + w(" ~s * ~s = new ~s(~s);~n", [C,Var,C,N]), + w(" app->newPtr((void *) ~s,3, memenv);~n", [Var]); + true -> + w(" ~s * ~s = ~s;~n", [C,Var,N]) + end, + P#param{name=Var}; + (P) -> P + end, + lists:map(FixClass, Attrs) + end. + +var_name("ev->" ++ Name0) -> + case reverse(Name0) of + ")(" ++ Name -> reverse(Name); + _ -> Name0 + end; +var_name(Name) -> Name. + +enum_name({Class,Type}) -> + uppercase_all(Class ++ "_" ++ Type); +enum_name(Type) -> + uppercase_all(Type). + + +enum_type({Class,Type}) -> + Class ++ "::" ++ Type; +enum_type(Type) -> Type. |