~statik/ubuntu/maverick/erlang/erlang-merge-testing

« back to all changes in this revision

Viewing changes to lib/wx/api_gen/wx_gen_cpp.erl

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-05-01 10:14:38 UTC
  • mfrom: (3.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090501101438-6qlr6rsdxgyzrg2z
Tags: 1:13.b-dfsg-2
* Cleaned up patches: removed unneeded patch which helped to support
  different SCTP library versions, made sure that changes for m68k
  architecture applied only when building on this architecture.
* Removed duplicated information from binary packages descriptions.
* Don't require libsctp-dev build-dependency on solaris-i386 architecture
  which allows to build Erlang on Nexenta (thanks to Tim Spriggs for
  the suggestion).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%%
 
2
%% %CopyrightBegin%
 
3
%% 
 
4
%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
 
5
%% 
 
6
%% The contents of this file are subject to the Erlang Public License,
 
7
%% Version 1.1, (the "License"); you may not use this file except in
 
8
%% compliance with the License. You should have received a copy of the
 
9
%% Erlang Public License along with this software. If not, it can be
 
10
%% retrieved online at http://www.erlang.org/.
 
11
%% 
 
12
%% Software distributed under the License is distributed on an "AS IS"
 
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
14
%% the License for the specific language governing rights and limitations
 
15
%% under the License.
 
16
%% 
 
17
%% %CopyrightEnd%
 
18
%%
 
19
%%%-------------------------------------------------------------------
 
20
%%% File    : wx_gen_cpp.erl
 
21
%%% Author  : Dan Gudmundsson <dgud@erix.ericsson.se>
 
22
%%% Description : 
 
23
%%%
 
24
%%% Created : 19 Feb 2007 by Dan Gudmundsson <dgud@erix.ericsson.se>
 
25
%%%-------------------------------------------------------------------
 
26
-module(wx_gen_cpp).
 
27
 
 
28
-include("wx_gen.hrl").
 
29
 
 
30
-compile(export_all).
 
31
 
 
32
-import(lists, [foldl/3,foldr/3,reverse/1, keysearch/3, map/2, filter/2]).
 
33
-import(gen_util, [lowercase/1, lowercase_all/1, uppercase/1, uppercase_all/1,
 
34
                   open_write/1, close/0, c_copyright/0, w/2, w/1,
 
35
                   args/3, strip_name/2]).
 
36
-import(wx_gen, [next_id/1]).
 
37
 
 
38
gen(Defs) ->   
 
39
    open_write("../c_src/gen/wxe_derived_dest.h"),
 
40
    c_copyright(),
 
41
    w("~n/***** This file is generated do not edit ****/ ~n~n", []),
 
42
    gen_derived_dest(Defs),
 
43
    close(),
 
44
 
 
45
    open_write("../c_src/gen/wxe_funcs.cpp"),
 
46
    c_copyright(),
 
47
    Res = gen_funcs(Defs),
 
48
    close(),
 
49
 
 
50
    open_write("../c_src/gen/wxe_macros.h"),
 
51
    c_copyright(),
 
52
    gen_macros(), 
 
53
    close(),
 
54
 
 
55
    open_write("../c_src/gen/wxe_init.cpp"),
 
56
    c_copyright(),
 
57
    build_enums(),
 
58
    close(),
 
59
    
 
60
    build_events(),
 
61
    Res.
 
62
            
 
63
gen_derived_dest(Defs) ->
 
64
    [gen_derived_dest_2(Class) || Class <- Defs],
 
65
    
 
66
    UglySkipList = ["wxCaret", "wxCalendarDateAttr", 
 
67
                    "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject"
 
68
                   ],
 
69
 
 
70
    ?WTC("gen_derived_dest"),
 
71
    w("void WxeApp::delete_object(void *ptr, wxeRefData *refd) {~n", []),
 
72
    w(" switch(refd->type) {~n", []),
 
73
    Case = fun(#class{name=Class, id=Id, abstract=IsAbs, parent=P}) when P /= "static" ->
 
74
                   UglyWorkaround = lists:member(Class, UglySkipList),
 
75
                   case hd(reverse(wx_gen_erl:parents(Class))) of
 
76
                       root when IsAbs == false, UglyWorkaround == false ->
 
77
                           w("  case ~p: delete (~s *) ptr; break;~n", [Id, Class]);
 
78
                       root when IsAbs == false, UglyWorkaround == true ->
 
79
                           w("  case ~p: /* delete (~s *) ptr;"
 
80
                             "These objects must be deleted by owner object */ "
 
81
                             "break;~n", [Id, Class]);
 
82
                       _ -> ok
 
83
                   end;
 
84
              (_) -> ok
 
85
           end,
 
86
    [Case(Class) || Class <- Defs],
 
87
    w("  default: delete (wxObject *) ptr;~n", []),
 
88
    w("}}~n~n", []).
 
89
 
 
90
gen_derived_dest_2(C=#class{name=Class}) ->
 
91
    case is_derived(C) of
 
92
        true -> 
 
93
            ?WTC("gen_derived_dest_2"),
 
94
            w("class E~s : public ~s { ~n",[Class,Class]),
 
95
            case Class of
 
96
                "wxGLCanvas" ->  %% Special for cleaning up gl context
 
97
                    w(" public: ~~E~s() {deleteActiveGL(this);"
 
98
                      "((WxeApp *)wxTheApp)->clearPtr(this);}; ~n", [Class]);
 
99
                _ ->
 
100
                    w(" public: ~~E~s() {((WxeApp *)wxTheApp)->clearPtr(this);}; ~n", [Class])
 
101
            end,
 
102
            gen_constructors(C),
 
103
            w("}; ~n~n", []);
 
104
        false ->
 
105
            ignore
 
106
    end.
 
107
 
 
108
gen_constructors(#class{name=Class, methods=Ms0}) ->
 
109
    Ms = lists:append(Ms0),
 
110
    Cs = lists:filter(fun(#method{method_type=MT}) -> MT =:= constructor end, Ms),
 
111
    [gen_constructor(Class, Const) || Const <- Cs].
 
112
    
 
113
gen_constructor(_Class, #method{where=merged_c}) -> ok;
 
114
gen_constructor(_Class, #method{where=erl_no_opt}) -> ok;
 
115
gen_constructor(Class, _M=#method{params=Ps}) ->
 
116
    Gen1  = fun(#param{name=N, type=T}) -> gen_type(T,1) ++ N end,
 
117
    Gen2  = fun(#param{name=N, type=T}) -> gen_type(T,2) ++ N end,
 
118
    CallA = fun(#param{name=N}) -> N end,
 
119
    HaveMergedType = fun(#param{type={merged,_,_,_,_,_,_}}) -> true; (_) -> false end,
 
120
    ?WTC("gen_constructor"),
 
121
    case lists:any(HaveMergedType, Ps) of
 
122
        false -> 
 
123
            w(" E~s(~s) : ~s(~s) {};~n",
 
124
              [Class,args(Gen1,",",Ps),Class,args(CallA,",",Ps)]);
 
125
        true ->
 
126
            w(" E~s(~s) : ~s(~s) {};~n",
 
127
              [Class,args(Gen1,",",Ps),Class,args(CallA,",",Ps)]),
 
128
            w(" E~s(~s) : ~s(~s) {};~n",
 
129
              [Class,args(Gen2,",",Ps),Class,args(CallA,",",Ps)])
 
130
    end.
 
131
 
 
132
gen_type(#type{name=Type, ref={pointer,1}, mod=Mod},_) ->
 
133
    mods(Mod) ++ to_string(Type) ++ " * ";
 
134
gen_type(#type{name=Type, ref={pointer,2}, mod=Mod},_) ->
 
135
    mods(Mod) ++ to_string(Type) ++ " ** ";
 
136
gen_type(#type{name=Type, ref=reference, mod=Mod},_) ->
 
137
    mods(Mod) ++ to_string(Type) ++ "& ";
 
138
gen_type(#type{name=Type, ref=undefined, base=binary, mod=Mod},_) ->
 
139
    mods(Mod) ++ to_string(Type) ++ " * ";
 
140
gen_type(#type{name=Type, ref=undefined, single=array, mod=Mod},_) ->
 
141
    mods(Mod) ++ to_string(Type) ++ " * ";
 
142
gen_type(#type{name=Type, ref=undefined, mod=Mod},_) ->
 
143
    mods(Mod) ++ to_string(Type) ++ " ";
 
144
gen_type({merged, _, T1, _,_, _T2,_}, 1) -> 
 
145
    gen_type(T1,error);
 
146
gen_type({merged, _, _T1,_, _, T2,_}, 2) -> 
 
147
    gen_type(T2,error).
 
148
 
 
149
gen_funcs(Defs) ->
 
150
    w("~n/***** This file is generated do not edit ****/ ~n~n"),
 
151
    w("#include <wx/wx.h>~n"),
 
152
    w("#include \"../wxe_impl.h\"~n"),
 
153
    w("#include \"../wxe_events.h\"~n"),
 
154
    w("#include \"../wxe_return.h\"~n"),
 
155
    w("#include \"wxe_macros.h\"~n"),
 
156
    w("#include \"wxe_derived_dest.h\"~n~n"),
 
157
 
 
158
    w("void WxeApp::wxe_dispatch(wxeCommand& Ecmd)~n{~n"),
 
159
    w(" char * bp = Ecmd.buffer; ~n"),
 
160
    w(" wxeMemEnv *memenv = getMemEnv(Ecmd.port);~n"),
 
161
%%    w(" wxMBConvUTF32 UTFconverter;~n"),
 
162
    w("  wxeReturn rt = wxeReturn(WXE_DRV_PORT, Ecmd.caller, true);~n"),
 
163
    w(" try { ~n"),
 
164
    w(" switch (Ecmd.op) ~n{~n"),
 
165
%%     w("  case WXE_CREATE_PORT: ~n", []),
 
166
%%     w("   { newMemEnv(Ecmd.port); } break; ~n", []),
 
167
%%     w("  case WXE_REMOVE_PORT: ~n", []),
 
168
%%     w("   { destroyMemEnv(Ecmd.port); } break; ~n", []),
 
169
    w("  case DESTROY_OBJECT: { ~n"),
 
170
    w("     wxObject *This = (wxObject *) getPtr(bp,memenv); "),   
 
171
    w("     if(This) {"),
 
172
    w("       ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n"),
 
173
    w("       delete This; }~n  } break; ~n"),
 
174
    w("  case WXE_REGISTER_OBJECT: {~n"
 
175
      "     wxeErlTerm * term = new wxeErlTerm(Ecmd.bin[0]);~n"
 
176
      "     registerPid(bp, term, memenv);~n"
 
177
      "     rt.addAtom(\"ok\");~n"
 
178
      "     break;~n"
 
179
      " }~n"),
 
180
 
 
181
    Res = [gen_class(Class) || Class <- Defs],
 
182
 
 
183
    w("  default: {~n"),
 
184
    w("    wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false);"),
 
185
    w("    error.addAtom(\"_wxe_error_\");~n"),
 
186
    w("    error.addInt((int) Ecmd.op);~n"),
 
187
    w("    error.addAtom(\"undef\");~n"),
 
188
    w("    error.addTupleCount(3);~n"),
 
189
    w("    return ;~n"),
 
190
    w("  }~n"),
 
191
    w("}  // switch~n"),
 
192
    w(" rt.send();~n"),
 
193
    w("} catch (wxe_badarg badarg) {  // try ~n"),
 
194
    w("    wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false);"),
 
195
    w("    error.addAtom(\"_wxe_error_\");~n"),
 
196
    w("    error.addInt((int) Ecmd.op);~n"),
 
197
    w("    error.addAtom(\"badarg\");~n"),
 
198
    w("    error.addInt((int) badarg.ref);~n"),
 
199
    w("    error.addTupleCount(2);~n"),
 
200
    w("    error.addTupleCount(3);~n"),
 
201
    w("    error.send();~n"),
 
202
    w("}} /* The End */ ~n"),
 
203
    Res.
 
204
                 
 
205
gen_class(C=#class{name=Name,methods=Ms,options=Opts}) ->
 
206
    put(current_class, Name),
 
207
    NewMs = 
 
208
        case lists:member(taylormade, Opts) of
 
209
            true ->
 
210
                {ok, Bin} = file:read_file(filename:join([wx_extra,Name++".c_src"])),
 
211
        ?WTC("gen_class"),
 
212
                w("~s~n", [binary_to_list(Bin)]),
 
213
                Ms;
 
214
            false ->
 
215
                case lists:keysearch(ifdef,1,Opts) of
 
216
                    {value, {ifdef, What}} ->
 
217
                        w("#if ~p~n",[What]),
 
218
                        Methods = lists:flatten(Ms),
 
219
                        MsR = [gen_method(Name,M) || 
 
220
                                  M <- lists:keysort(#method.id, Methods)],
 
221
                        w("#endif // ~p~n",[What]),
 
222
                        MsR;
 
223
                    false ->
 
224
                        Methods = lists:flatten(Ms),
 
225
                        [gen_method(Name,M) || 
 
226
                            M <- lists:keysort(#method.id, Methods)]
 
227
                end
 
228
        end,
 
229
    erase(current_class),
 
230
    C#class{methods=NewMs}.
 
231
 
 
232
%%gen_methods(ClassName, Ms) ->
 
233
%%    [gen_method(ClassName, M) ||  M <- Ms].
 
234
 
 
235
gen_method(_CName, M=#method{where=erl_no_opt}) ->     M;
 
236
gen_method(CName, M=#method{where=taylormade, name=Name, id=Id}) ->     
 
237
    {ok, Bin} = file:read_file(filename:join([wx_extra, CName ++".c_src"])),
 
238
    Str0 = binary_to_list(Bin),
 
239
    %%    io:format("C++ Class ~p ~p ~n", [CName, Name]),
 
240
    {match, Start, Len} = regexp:first_match(Str0, "<<" ++ Name),
 
241
    {match, End, _} = regexp:first_match(Str0, Name ++ ">>"),
 
242
    Str1 = string:substr(Str0, Start+Len, End-Start-Len),
 
243
    %% {ok, Str, _} = regexp:sub(Str1, "FUNCID", integer_to_list(Id)),
 
244
    ?WTC("gen_method"),
 
245
    w(Str1, [wx_gen_erl:get_unique_name(Id)]),
 
246
    M;
 
247
gen_method(CName, M=#method{name=N,params=[Ps],method_type=destructor,id=MethodId}) ->
 
248
    case hd(reverse(wx_gen_erl:parents(CName))) of
 
249
        root ->
 
250
            ?WTC("gen_method"),
 
251
            w("case ~s: { // ~s::~s ~n", [wx_gen_erl:get_unique_name(MethodId),CName,N]),
 
252
            decode_arguments([Ps]),
 
253
            w(" if(This) {", []),
 
254
            w("   ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n", []),
 
255
            w("   delete This;}~n", []),
 
256
            free_args(), 
 
257
            w(" break; ~n}~n", []);
 
258
        object ->  %% Use default
 
259
            ignore
 
260
    end,
 
261
    M;
 
262
gen_method(CName,  M=#method{name=N,params=Ps0,type=T,method_type=MT,id=MethodId}) ->
 
263
    put(current_func, N),
 
264
    put(bin_count,-1),
 
265
    ?WTC("gen_method"),
 
266
    w("case ~s: { // ~s::~s ~n", [wx_gen_erl:get_unique_name(MethodId),CName,N]),
 
267
    Ps1 = declare_variables(void, Ps0),
 
268
    {Ps2,Align} = decode_arguments(Ps1),
 
269
    Opts = [Opt || Opt = #param{def=Def,in=In,where=Where} <- Ps2, 
 
270
                   Def =/= none, In =/= false, Where =/= c],
 
271
    decode_options(Opts, Align),
 
272
    case M#method.pre_hook of
 
273
        undefined -> skip;
 
274
        Pre -> w(" ~s;~n", [Pre])
 
275
    end,
 
276
    Ps3 = call_wx(N,{MT,CName},T,Ps2),
 
277
    case M#method.post_hook of
 
278
        undefined -> skip;
 
279
        Post -> w(" ~s;~n", [Post])
 
280
    end,
 
281
    free_args(),
 
282
    build_return_vals(T,Ps3),
 
283
    w(" break; ~n}~n", []),
 
284
    erase(current_func),
 
285
    M.
 
286
 
 
287
declare_variables(void,Ps) ->
 
288
    [declare_var(P) || P <- Ps];
 
289
declare_variables(T, Ps) ->
 
290
    declare_type("result", out, ignore, T),
 
291
    [declare_var(P) || P <- Ps].
 
292
 
 
293
declare_var(P = #param{where=erl}) -> P;
 
294
declare_var(P = #param{where=this}) -> P;
 
295
declare_var(P = #param{name=Name,def=Def,type=Type,in=true}) when Def =/= none -> 
 
296
    declare_type(Name, true, Def, Type),
 
297
    P;
 
298
declare_var(P = #param{in=In}) when In =/= false -> P;
 
299
declare_var(P = #param{name=Name,in=In,def=Def,type=Type}) ->
 
300
    declare_type(Name, In, Def, Type),
 
301
    P.
 
302
 
 
303
declare_type(N,false,_,#type{name="wxArrayInt"}) ->
 
304
    w(" wxArrayInt ~s;~n", [N]);
 
305
declare_type(N,false,_,#type{name="wxArrayString"}) ->
 
306
    w(" wxArrayString ~s;~n", [N]);
 
307
declare_type(N,false,_,#type{base=Base,single=true,name=Type,by_val=false,mod=Mod}) 
 
308
  when Base =:= int; Base =:= long; Base =:= float; Base =:= double ->
 
309
    w(" ~s~s ~s;~n", [mods(Mod),Type,N]);
 
310
declare_type(N,false,_,#type{base={enum,_},single=true,name=Type,by_val=false,mod=Mod}) ->
 
311
    w(" ~s~s ~s;~n", [mods(Mod),Type,N]);
 
312
declare_type(N,false,_,#type{name="wxArrayTreeItemIds",ref=reference}) ->
 
313
    w(" wxArrayTreeItemIds ~s;~n", [N]);
 
314
declare_type(N,false,_,#type{name="wxDateTime"}) ->
 
315
    w(" wxDateTime ~s;~n", [N]);
 
316
declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=true}) 
 
317
  when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
 
318
    w(" ~s ~s=~s;~n", [Type,N,Def]);
 
319
declare_type(N,true,Def,#type{base={comp,_,_},single=true,name=Type,mod=Mod,ref={pointer,1}}) ->
 
320
    w(" ~s~s *~s=~s; ~s ~s;~n", [mods(Mod),Type,N,Def,Type,N++"Tmp"]);
 
321
declare_type(N,true,Def,#type{base={comp,_,_},single=true,name=Type,ref=reference}) ->
 
322
    w(" ~s ~s= ~s;~n", [Type,N,Def]);
 
323
declare_type(N,true,Def,#type{base={enum,Type},single=true}) ->
 
324
    w(" ~s ~s=~s;~n", [enum_type(Type),N,Def]);
 
325
declare_type(N,true,Def,#type{base={class,_},single=true,name=Type,ref={pointer,1},mod=Mod}) ->
 
326
    w(" ~s~s * ~s=~s;~n", [mods(Mod),Type,N,Def]);
 
327
declare_type(N,true,Def,#type{base={class,_},single=true,name=Type,ref=reference,mod=Mod}) ->
 
328
    w(" ~s~s * ~s= &~s;~n", [mods(Mod),Type,N,Def]);
 
329
declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=false,ref={pointer,1}}) 
 
330
  when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
 
331
    w(" ~s *~s=~s;~n", [Type,N,Def]);
 
332
declare_type(N,true,Def,#type{single=true,name="wxString"}) ->
 
333
    w(" wxString ~s= ~s;~n", [N,Def]);
 
334
declare_type(N,true,Def,#type{single=true,name="wxArtClient"}) ->
 
335
    w(" wxArtClient ~s= ~s;~n", [N,Def]);
 
336
%% declare_type(N,true,_Def,#type{name="wxString"}) ->
 
337
%%     w(" wxString ~s= wxEmptyString;~n", [N]);
 
338
declare_type(N,true,Def,#type{base=binary, name=char}) ->
 
339
    w(" char ~sD[] = {~s}, * ~s = ~sD;~n", [N,Def,N,N]);
 
340
declare_type(_N,true,_Def,void) ->
 
341
    skip;
 
342
declare_type(N,true,Def,#type{name=Type, ref={pointer,2}}) ->
 
343
    %% xxxx
 
344
    w(" ~s ** ~s = ~s;~n", [Type,N,Def]);
 
345
declare_type(N,true,Def,#type{name=Type, single=array, ref={pointer,1}}) ->
 
346
    w(" int * ~sLen = 0;~n", [N]),    
 
347
    w(" ~s * ~s = ~s;~n", [Type,N,Def]);
 
348
declare_type(N,true,"",#type{name="wxArrayString", single=array, ref=reference}) ->
 
349
    w(" wxArrayString ~s;~n", [N]);
 
350
declare_type(N,true,Def,#type{name=Type, base={term,_}}) ->
 
351
    w(" ~s * ~s= ~s;~n", [Type,N,Def]);
 
352
declare_type(N,In,Def,T) ->
 
353
    ?error({unhandled_type, {N,In,Def,T}}).
 
354
 
 
355
decode_options([], _Align) -> ok;
 
356
decode_options(Opts, Align) ->
 
357
    align(Align, 64),
 
358
    w(" while( * (int*) bp) { switch (* (int*) bp) { ~n", []),
 
359
    foldl(fun decode_opt/2, 1, Opts),
 
360
    w(" }}; ~n", []).
 
361
 
 
362
decode_opt(#param{name=Name,type=Type}, N) ->
 
363
    w("  case ~p: {bp += 4;~n", [N]),
 
364
    Align = decode_arg(Name,Type,opt,1), 
 
365
    align(Align, 64),
 
366
    w("  } break;~n", []),
 
367
    N+1.
 
368
 
 
369
decode_arguments(Ps0) -> 
 
370
    lists:mapfoldl(fun decode_arg/2,0,Ps0).
 
371
 
 
372
store_free(N) ->
 
373
    case get(free_args) of
 
374
        undefined -> put(free_args, [N]);
 
375
        List -> put(free_args, [N|List])
 
376
    end.
 
377
 
 
378
free_args() ->
 
379
    case get(free_args) of
 
380
        undefined -> ignore;
 
381
        List -> 
 
382
            erase(free_args),
 
383
            [w(" driver_free(~s);~n", [Arg]) || Arg <- List]
 
384
    end.
 
385
 
 
386
decode_arg(P = #param{where=erl},A) -> {P,A};
 
387
decode_arg(P = #param{where=c},A) ->  {P,A};
 
388
decode_arg(P = #param{in=false},A) -> {P,A};
 
389
decode_arg(P = #param{def=Def},A) when Def =/= none -> {P,A}; 
 
390
decode_arg(P = #param{name=Name,type=Type},A0) ->
 
391
    A = decode_arg(Name, Type, arg, A0),
 
392
    {P, A}.
 
393
 
 
394
wa(Decl,DA,Get,GetA,arg) ->
 
395
    w(Decl,DA),
 
396
    w(Get,GetA);
 
397
wa(_Decl,_DA,Get,GetA,opt) ->
 
398
    w(Get,GetA).
 
399
 
 
400
decode_arg(N,#type{name=Class,base={class,_},single=true},Arg,A0) ->
 
401
    A = align(A0,32),
 
402
    wa(" ~s *",[Class],"~s = (~s *) getPtr(bp,memenv); bp += 4;~n",[N,Class],Arg),
 
403
    A;
 
404
decode_arg(N,{merged,_,#type{name=Class,base={class,_},single=true},_,_,_,_},arg,A0) ->
 
405
    A = align(A0,32),
 
406
    w(" ~s * ~s = (~s *) getPtr(bp,memenv); bp += 4;~n", [Class,N,Class]),
 
407
    A;
 
408
decode_arg(N,#type{base=long,single=true,name=Type},arg,A0) ->
 
409
    A = align(A0,64),
 
410
    w(" long * ~s = (~s *) bp; bp += 8;~n", [N,Type]),
 
411
    A;
 
412
decode_arg(N,#type{base=int,single=true,mod=Mod0,name=Type},Arg,A0) ->
 
413
    Mod = mods(Mod0),
 
414
    case Arg of
 
415
        arg -> w(" ~s~s * ~s = (~s~s *) bp; bp += 4;~n", [Mod,int,N,Mod,int]);
 
416
        opt -> w(" ~s = (~s)*(~s~s *) bp; bp += 4;~n", [N,Type,Mod,int])
 
417
    end,
 
418
    align(A0,32);
 
419
decode_arg(N,#type{base=float,single=true,name=Type},arg,A0) ->
 
420
    w(" ~s * ~s = (~s *) bp; bp += 4;~n", [Type,N,Type]),
 
421
    align(A0,32);
 
422
decode_arg(N,#type{base=double,single=true,name=Type},Arg,A0) ->
 
423
    A = align(A0,64),
 
424
    case Arg of 
 
425
        arg -> w(" ~s * ~s = (~s *) bp; bp += 8;~n", [Type,N,Type]);
 
426
        opt -> w(" ~s = * (~s *) bp; bp += 8;~n",    [N,Type])
 
427
    end,
 
428
    A;
 
429
decode_arg(N,#type{base=bool,single=true,name=Type},Arg,A0) ->
 
430
    case Arg of 
 
431
        arg -> w(" bool * ~s = (~s *) bp; bp += 4;~n", [N,Type]);
 
432
        opt -> w(" ~s = *(~s *) bp; bp += 4;~n", [N,Type])
 
433
    end,
 
434
    align(A0,32);
 
435
decode_arg(N,#type{base={enum,Type},single=true},Arg,A0) ->
 
436
    wa(" ~s ", [enum_type(Type)], "~s = *(~s *) bp; bp += 4;;~n",[N, enum_type(Type)], Arg), 
 
437
    align(A0,32);
 
438
decode_arg(N,#type{base={comp,"wxDateTime",List},single=true,name=Type,ref=Ref},Arg,A0) ->
 
439
    Decl = fun({int,Spec}) -> 
 
440
                   w(" int * ~s~s = (int *) bp; bp += 4;~n", [N,Spec])
 
441
           end,
 
442
    align(A0,32),
 
443
    lists:foreach(Decl,List),
 
444
    Name = fun({_,"Mo"}) -> "(wxDateTime::Month) *"++N++"Mo";
 
445
              ({_,"Y"}) -> "*"++N++"Y";
 
446
              ({_,Spec}) -> "(wxDateTime::wxDateTime_t) *"++N++Spec
 
447
           end,
 
448
    case Arg of
 
449
        arg -> w(" ~s ~s = ~s(~s);~n", [Type,N,Type,args(Name, ",", List)]);
 
450
        opt when Ref =:= {pointer,1} -> 
 
451
            w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n", 
 
452
              [N,Type,args(Name, ",", List), N,N]);
 
453
        opt ->
 
454
            w(" ~s = ~s(~s);~n", [N,Type,args(Name, ",", List)])
 
455
    end,
 
456
    (A0+length(List)) rem 2;
 
457
decode_arg(N,#type{base={comp,_,List},single=true,name=Type,ref=Ref},Arg,A0) ->
 
458
    Decl = fun({int,Spec}) -> 
 
459
                   w(" int * ~s~s = (int *) bp; bp += 4;~n", [N,Spec]);
 
460
              ({double, Spec}) ->
 
461
                   w(" wxDouble * ~s~s = (wxDouble *) bp; bp += 8;~n", [N,Spec])
 
462
           end,
 
463
    case hd(List) of
 
464
        {int, _} ->    align(A0,32);
 
465
        {double, _} -> align(A0,64)
 
466
    end,
 
467
    lists:foreach(Decl,List),
 
468
    Name = fun({_,Spec}) -> "*"++N++Spec end,
 
469
    case Arg of
 
470
        arg -> w(" ~s ~s = ~s(~s);~n", [Type,N,Type,args(Name, ",", List)]);
 
471
        opt when Ref =:= {pointer,1} -> 
 
472
            w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n", 
 
473
              [N,Type,args(Name, ",", List), N,N]);
 
474
        opt ->
 
475
            w(" ~s = ~s(~s);~n", [N,Type,args(Name, ",", List)])
 
476
    end,
 
477
    case hd(List) of
 
478
        {int, _} ->    (A0+length(List)) rem 2;
 
479
        {double, _} -> 0
 
480
    end;
 
481
  
 
482
decode_arg(N,#type{name=Class,base={ref,"wxTreeItemId"},single=true},Arg,A0) ->
 
483
    A = align(A0,32),
 
484
    wa(" ~s ",[Class],"~s = wxTreeItemId(getPtr(bp,memenv)); bp += 4;~n",[N],Arg),
 
485
    A;
 
486
decode_arg(N,#type{name="wxChar", single=S},Arg,A0) 
 
487
  when S =/= true ->
 
488
    w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
 
489
    wa(" wxString", []," ~s = wxString(bp, wxConvUTF8);~n", [N],Arg),
 
490
    w(" bp += *~sLen+((8-((~p+ *~sLen) & 7)) & 7);~n", [N,4*((A0+1) rem 2),N]),
 
491
    0;
 
492
decode_arg(N,#type{base=[int], name=Name},Arg,A0) 
 
493
  when Name =:= "wxString"; Name =:= "wxArtClient" ->
 
494
    w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
 
495
    wa(" wxString", []," ~s = wxString(bp, wxConvUTF8);~n", [N],Arg),
 
496
    w(" bp += *~sLen+((8-((~p+ *~sLen) & 7)) & 7);~n", [N,4*((A0+1) rem 2),N]),
 
497
    0;
 
498
decode_arg(N,#type{name="wxArrayString"},Place,A0) ->
 
499
    w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
 
500
    case Place of
 
501
        arg -> w(" wxArrayString ~s;~n", [N]);
 
502
        opt -> ignore %% Allready declared
 
503
    end,
 
504
    w(" int ~sASz = 0, * ~sTemp;~n", [N,N]),
 
505
    w(" for(int i=0; i < *~sLen; i++) {~n", [N]),
 
506
    w("   ~sTemp = (int *) bp; bp += 4;~n", [N]),
 
507
    w("   ~s.Add(wxString(bp, wxConvUTF8));~n", [N]),
 
508
    w("   bp += *~sTemp;~n", [N]),
 
509
    w("   ~sASz += *~sTemp+4;~n }~n", [N,N]),
 
510
    w(" bp += (8-((~p+ ~sASz) & 7 )) & 7;~n", [4*((A0+1) rem 2),N]),
 
511
    0;
 
512
 
 
513
decode_arg(N,#type{name="wxArrayInt"},arg,A0) ->
 
514
    w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
 
515
    w(" wxArrayInt ~s;~n", [N]),
 
516
    w(" for(int i=0; i < *~sLen; i++) {", [N]),
 
517
    w("  ~s.Add(*(int *) bp); bp += 4;}~n", [N]),
 
518
    w(" bp += ((*~sLen + ~p) % 2 )*4;~n",[N, (A0+1)]),
 
519
    0;
 
520
decode_arg(N,#type{name="wxArrayDouble"},arg,A0) ->
 
521
    w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
 
522
    align(A0+1,64),
 
523
    w(" wxArrayDouble ~s;~n", [N]),
 
524
    w(" for(int i=0; i < *~sLen; i++) {", [N]),
 
525
    w("  ~s.Add(*(int *) bp); bp += 4;}~n", [N]),
 
526
    0;
 
527
decode_arg(_N,#type{base=eventType},_Arg,A0) ->
 
528
%%     w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
 
529
%%     case Arg of
 
530
%%      arg -> 
 
531
%%          w(" int ~s = wxeEventTypeFromAtom(bp);bp += *~sLen;~n",[N,N]),
 
532
%%          w(" char *class_name = bp;~n", []),
 
533
%%          w(" wxeCallbackData * Evt_cb = new wxeCallbackData(Ecmd.caller,This,class_name);~n",
 
534
%%            [])
 
535
%%     end,
 
536
    A0;
 
537
decode_arg(N,#type{name=Type,base=binary,mod=Mod0},Arg,A0) ->
 
538
    Mod = mods([M || M <- Mod0]),
 
539
    case Arg of
 
540
        arg -> 
 
541
            w(" ~s~s * ~s = (~s~s*) Ecmd.bin[~p]->base; ~n",
 
542
              [Mod,Type,N,Mod,Type, next_id(bin_count)]);
 
543
        opt ->
 
544
            w(" ~s = (~s~s*) Ecmd.bin[~p]->base; ~n", 
 
545
              [N,Mod,Type,next_id(bin_count)])
 
546
    end,
 
547
    A0;
 
548
decode_arg(N,#type{base={term,"wxTreeItemData"},mod=Mod0},Arg,A0) ->
 
549
    Mod = mods([M || M <- Mod0]),
 
550
    Type = "wxETreeItemData",
 
551
    BinCnt = next_id(bin_count),
 
552
    case Arg of
 
553
        arg -> 
 
554
            w(" ~s~s * ~s =  new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base); ~n",
 
555
              [Mod,Type,N,Type,BinCnt,BinCnt]);
 
556
        opt -> 
 
557
            w(" ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base); ~n", 
 
558
              [N,Type,BinCnt,BinCnt])
 
559
    end,
 
560
    A0;
 
561
decode_arg(N,#type{name=Type,base={term,_},mod=Mod0},Arg,A0) ->
 
562
    Mod = mods([M || M <- Mod0]),
 
563
    BinCnt = next_id(bin_count),
 
564
    case Arg of
 
565
        arg -> 
 
566
            w(" ~s~s * ~s =  new ~s(Ecmd.bin[~p]); ~n",
 
567
              [Mod,Type,N,Type,BinCnt]);
 
568
        opt -> 
 
569
            w(" ~s = new ~s(Ecmd.bin[~p]); ~n", 
 
570
              [N,Type,BinCnt])
 
571
    end,
 
572
    A0;
 
573
decode_arg(N,#type{single=array,base=int},Arg,A0)  ->
 
574
    case Arg of
 
575
        arg ->
 
576
            w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
 
577
            w(" int * ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n", 
 
578
              [N,N,(A0+1) rem 2,N]);
 
579
        opt ->  
 
580
            w(" ~sLen = (int *) bp; bp += 4;~n", [N]),
 
581
            w(" ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n", 
 
582
              [N,N,(A0+1) rem 2,N])
 
583
    end,
 
584
    0;
 
585
decode_arg(N,#type{by_val=true,single=array,base={comp,Class="wxPoint",_}},arg,A0) ->
 
586
    w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),    
 
587
    w(" ~s *~s;~n",[Class,N]), 
 
588
    w(" ~s = (~s *) driver_alloc(sizeof(~s) * *~sLen);~n",[N,Class,Class,N]),
 
589
    store_free(N),
 
590
    w(" for(int i=0; i < *~sLen; i++) {~n", [N]),
 
591
    w("   int x = * (int *) bp; bp += 4;~n   int y = * (int *) bp; bp += 4;~n", []),
 
592
    w("   ~s[i] = wxPoint(x,y);}~n", [N]),
 
593
    align(A0,32);
 
594
decode_arg(N,#type{by_val=true,single=array,base={class,Class}},arg,A0) ->
 
595
    A = align(A0,32),
 
596
    w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
 
597
    w(" ~s *~s;~n",[Class,N]),
 
598
    w(" ~s = (~s *) driver_alloc(sizeof(~s) * *~sLen);", [N, Class, Class, N]),
 
599
    store_free(N),
 
600
    w(" for(int i=0; i < *~sLen; i++) {", [N]),
 
601
    w(" ~s[i] = * (~s *) getPtr(bp,memenv); bp += 4;}~n", [N,Class]),
 
602
    w(" bp += ((~p+ *~sLen)%2 )*4;~n", [A, N]),
 
603
    0;
 
604
decode_arg(N,#type{name=Type,single=list,base={class,Class}},arg,A0) ->
 
605
    w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
 
606
    A = align(A0,32),
 
607
    w(" ~s ~s;~n",[Type,N]),
 
608
    w(" for(int i=0; i < *~sLen; i++) {", [N]),
 
609
    w("  ~s.Append(*(~s *) getPtr(bp,memenv)); bp += 4;}~n", [N,Class]),
 
610
    w(" bp += ((~p+ *~sLen)%2 )*4;~n", [A,N]),
 
611
    0;
 
612
decode_arg(Name,T, Arg,_A) ->
 
613
    ?error({unhandled_type, {Name,T, Arg}}).
 
614
 
 
615
align(0, 32) -> 1;
 
616
align(1, 32) -> 0;
 
617
align(0, 64) -> 0;
 
618
align(1, 64) -> 
 
619
    w(" bp += 4; /* Align */~n"),
 
620
    0;
 
621
align(N,Sz) ->
 
622
    align(N rem 2, Sz).
 
623
 
 
624
call_wx(_N,{constructor,_},#type{base={class,RClass}},Ps) -> 
 
625
    #class{id=Id} = ClassDef = get({class,RClass}),
 
626
    Class = case is_derived(ClassDef) of
 
627
                true ->  "E" ++ RClass;
 
628
                false -> RClass
 
629
            end,
 
630
    w(" ~s * Result = new ~s(~s);~n",
 
631
      [RClass, Class,args(fun call_arg/1, ",",filter(Ps))]),
 
632
    CType = case is_window(RClass) of
 
633
                true -> %% Windows have parents that should be deleted first
 
634
                    case is_dialog(RClass) of
 
635
                        true -> 2;   %% Dialogs must be closed first event before windows
 
636
                        false -> 0
 
637
                    end;                        
 
638
                false -> 
 
639
                    case hd(reverse(wx_gen_erl:parents(RClass))) of
 
640
                        root -> Id;
 
641
                        _ -> 1
 
642
                    end
 
643
            end,
 
644
    case virtual_dest(ClassDef) orelse (CType =/= 0) of
 
645
        true ->
 
646
            w(" newPtr((void *) Result, ~p, memenv);~n", [CType]);
 
647
        false ->  %% Hmm window without virt dest
 
648
            w(" /* Possible memory leak here, class is missing virt dest */ \n")
 
649
    end,
 
650
    Ps;
 
651
call_wx(N,{member,_},Type,Ps) ->
 
652
    {Beg,End} = return_res(Type),
 
653
    w(" if(!This) throw wxe_badarg(0);~n",[]),
 
654
    w(" ~sThis->~s(~s)~s;~n",[Beg,N,args(fun call_arg/1, ",",filter(Ps)),End]),
 
655
    Ps;
 
656
call_wx(N,{static,Class},Type,Ps) ->
 
657
    {Beg,End} = return_res(Type),
 
658
    #class{parent=Parent} = get({class,Class}),
 
659
    case Parent of
 
660
        "static" ->
 
661
            w(" ~s::~s(~s)~s;~n",[Beg,N,args(fun call_arg/1, ",",filter(Ps)),End]);
 
662
        _ ->
 
663
            w(" ~s~s::~s(~s)~s;~n",[Beg,Class,N,args(fun call_arg/1, ",",filter(Ps)),End])
 
664
    end,
 
665
    Ps.
 
666
 
 
667
 
 
668
return_res(void) -> {"", ""};
 
669
return_res(Type = #type{mod=Mod}) ->
 
670
    case lists:member(const, Mod) of
 
671
        true -> 
 
672
            {Beg, End} = return_res1(Type), 
 
673
            {"const " ++ Beg, End};
 
674
        _ -> 
 
675
            return_res1(Type)
 
676
    end.
 
677
 
 
678
return_res1(#type{name=Type,ref={pointer,_}, base={term,_}}) ->
 
679
    {Type ++ " * Result = (" ++ Type ++ "*)", ""};
 
680
return_res1(#type{name=Type,ref={pointer,_}}) ->
 
681
    {Type ++ " * Result = (" ++ Type ++ "*)", ""};
 
682
return_res1(#type{name=Type,single=true,ref=reference}) ->
 
683
    {Type ++ " * Result = &", ""};
 
684
return_res1(#type{name=Type,single=true,by_val=true}) 
 
685
  when is_atom(Type) -> 
 
686
    {atom_to_list(Type) ++ " Result = ", ""};
 
687
return_res1(#type{name=Type="wxArrayInt"}) ->
 
688
    {Type ++ " Result = ", ""};
 
689
return_res1(#type{name=Type,base={class,_},single=list,ref=reference}) ->
 
690
    {Type ++ " Result = ", ""};
 
691
return_res1(#type{name=Type,base={comp,_,_},single=array,by_val=true}) ->
 
692
    {Type ++ " Result = ", ""};
 
693
return_res1(#type{name=Type,single=true,by_val=true, base={class, _}}) ->
 
694
    %% Memory leak !!!!!!   XXXX BUGBUG FIXME or doument!!    
 
695
    case Type of 
 
696
        "wxImage" ->  ok;
 
697
        "wxFont"  ->  ok;
 
698
        "wxBitmap" -> ok;
 
699
        "wxIcon" ->   ok;
 
700
        "wxGraphics" ++ _ -> ok;
 
701
        _ ->
 
702
            io:format("~s::~s Building return value of temp ~s~n", 
 
703
                      [get(current_class),get(current_func),Type])
 
704
    end,
 
705
    %% #class{id=Id} = get({class,Type}),
 
706
    {Type ++ " * Result = new " ++ Type ++ "(", "); newPtr((void *) Result," 
 
707
     ++ "3, memenv);"};
 
708
return_res1(#type{base={enum,_Type},single=true,by_val=true}) ->
 
709
    {"int Result = " , ""};
 
710
return_res1(#type{name="wxCharBuffer", base={binary,_},single=true,by_val=true}) ->
 
711
    {"char * Result = ", ".data()"};
 
712
return_res1(#type{name=Type,single=array,ref=reference}) ->
 
713
    {Type ++ " Result = ", ""};
 
714
return_res1(#type{name=Type,single=true,by_val=true}) ->
 
715
    {Type ++ " Result = ", ""}.
 
716
 
 
717
filter(Ps) ->
 
718
    lists:filter(fun filter_arg/1, Ps).
 
719
filter_arg(#param{where=erl}) -> false;    
 
720
filter_arg(#param{where=this}) -> false;
 
721
filter_arg(#param{}) -> true.
 
722
%%filter_arg(#param{def=Def, in=In}) -> Def =:= none orelse In =:= false.
 
723
 
 
724
 
 
725
call_arg(#param{where=c, alt={length,Alt}}) when is_list(Alt) ->
 
726
    "*" ++ Alt ++ "Len";
 
727
call_arg(#param{where=c, alt={size,Id}}) when is_integer(Id) ->
 
728
    %% It's a binary 
 
729
    "Ecmd.bin["++ integer_to_list(Id) ++ "]->size";
 
730
call_arg(#param{name=N,def=Def,type=#type{name=Type,by_val=true,single=true,base=Base}}) 
 
731
  when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool -> 
 
732
    case Def of
 
733
        none -> "(" ++ to_string(Type) ++ ") *" ++ N;
 
734
        _ ->  N
 
735
    end;
 
736
 
 
737
call_arg(#param{name=N,type=#type{base={enum,Type}, by_val=true,single=true}}) -> 
 
738
    "(" ++ enum_type(Type) ++") " ++ N;
 
739
call_arg(#param{name=N,type=#type{base={class,_},by_val=true,single=true}}) -> "*" ++ N;
 
740
call_arg(#param{name=N,type=#type{base={class,_},ref=reference,single=true}}) -> "*" ++ N;
 
741
call_arg(#param{name=N,type=#type{base=eventType}}) -> 
 
742
    N ++ ", (wxObjectEventFunction)(wxEventFunction) &WxeApp::handle_evt, Evt_cb, this";
 
743
call_arg(#param{name=N,type=#type{by_val=true, single=_False}}) -> N;
 
744
call_arg(#param{name=N,def=Def,type=#type{by_val=false, ref={pointer,2}}})
 
745
  when Def =/= none -> N;
 
746
call_arg(#param{name=N,type=#type{by_val=false, ref={pointer,2}}}) -> "&" ++ N;
 
747
call_arg(#param{name=N,in=false,type=#type{ref=reference, single=true}}) -> N;
 
748
call_arg(#param{name=N,in=false,type=#type{by_val=false, single=true}}) -> "&" ++ N;
 
749
call_arg(#param{name=N,def=Def,type=#type{base={comp,_,_},ref={pointer,1},single=true}}) 
 
750
  when Def =:= none ->
 
751
    "&" ++N;
 
752
call_arg(#param{name=N,type=#type{by_val=false}}) -> N;
 
753
call_arg(#param{name=N,type={merged,_,#type{base={class,_},single=true,
 
754
                                            by_val=ByVal,
 
755
                                            ref=Ref},_,_,_,_}}) 
 
756
  when ByVal =:= true; Ref =:= reference -> 
 
757
    "*" ++ N;
 
758
call_arg(#param{def=Def, type=void}) when Def =/= none -> Def;  
 
759
call_arg(#param{name=N,type=#type{base={ref,_},by_val=true,single=true}}) -> N;
 
760
call_arg(#param{name=N,type={merged,_,_,_,_,_,_}}) -> N.
 
761
 
 
762
%% call_arg(#param{name=N,type=#type{base=Tuple,ref=reference}}) 
 
763
%%   when is_tuple(Tuple) -> "&" ++ N;
 
764
 
 
765
to_string(Type) when is_atom(Type) -> atom_to_list(Type);
 
766
to_string(Type) when is_list(Type) -> Type.
 
767
 
 
768
virtual_dest(#class{abstract=true, parent="root"}) -> false;
 
769
virtual_dest(#class{abstract=true, parent="object"}) -> true;
 
770
virtual_dest(#class{abstract=true, parent=Parent}) ->  
 
771
    virtual_dest(get({class,Parent}));
 
772
virtual_dest(#class{methods=Ms, parent=Parent}) ->
 
773
    case lists:keysearch(destructor,#method.method_type, lists:append(Ms)) of
 
774
        {value, #method{method_type=destructor, virtual=Virtual}} ->
 
775
            case Virtual of
 
776
                undefined -> 
 
777
                    case get({class,Parent}) of
 
778
                        undefined -> 
 
779
                            case Parent of
 
780
                                "object" -> 
 
781
                                    true;
 
782
                                "root"   -> 
 
783
                                    false;
 
784
                                _ ->
 
785
                                    io:format("Error: ~p ~n",[Parent]),
 
786
                                    erlang:error(no_parent)
 
787
                            end;
 
788
                        PClass ->
 
789
                            virtual_dest(PClass)
 
790
                    end;
 
791
                _ -> 
 
792
                    Virtual
 
793
            end;
 
794
        false -> 
 
795
            false
 
796
    end.
 
797
 
 
798
debug(F,A) ->
 
799
    case get(debug) of
 
800
        true ->  ?warning(F,A);
 
801
        _ -> ok
 
802
    end.
 
803
 
 
804
is_derived(#class{abstract=true}) -> false;
 
805
is_derived(C = #class{}) -> virtual_dest(C).
 
806
 
 
807
is_window(Class) ->
 
808
    lists:member("wxWindow", wx_gen_erl:parents(Class)).    
 
809
 
 
810
is_dialog(Class) ->
 
811
    lists:member("wxDialog", wx_gen_erl:parents(Class)).
 
812
   
 
813
build_return_vals(Type,Ps) ->
 
814
    HaveType = case Type of  void -> 0; _ -> 1 end,
 
815
    NoOut = lists:sum([1 || #param{in=In} <- Ps, In =/= true]) + HaveType,
 
816
    OutTupSz = if NoOut > 1 -> NoOut; true -> 0 end,
 
817
    
 
818
    build_ret_types(Type,Ps),
 
819
    if 
 
820
        OutTupSz > 1 -> w(" rt.addTupleCount(~p);~n",[OutTupSz]);
 
821
        true -> ignore
 
822
    end,            
 
823
    Ps.
 
824
 
 
825
build_ret_types(void,Ps) -> 
 
826
    Calc = fun(#param{name=N,in=False,type=T}, Free) when False =/= true ->
 
827
                   case build_ret(N, False, T) of
 
828
                       ok -> Free;
 
829
                       Other -> [Other|Free]
 
830
                   end;
 
831
              (_, Free) -> Free
 
832
           end,
 
833
    lists:foldl(Calc, [], Ps);
 
834
build_ret_types(Type,Ps) -> 
 
835
    Free = case build_ret("Result", out, Type) of
 
836
               ok -> [];
 
837
               FreeStr -> [FreeStr]
 
838
           end,
 
839
    Calc = fun(#param{name=N,in=False,type=T}, FreeAcc) when False =/= true ->
 
840
                   case build_ret(N, False, T) of
 
841
                       ok -> FreeAcc;
 
842
                       FreeMe -> [FreeMe|FreeAcc]
 
843
                   end;       
 
844
              (_, FreeAcc) -> FreeAcc 
 
845
           end,
 
846
    lists:foldl(Calc, Free, Ps).
 
847
 
 
848
build_ret(Name,_,#type{base={class,Class},single=true}) ->
 
849
    w(" rt.addRef(getRef((void *)~s,memenv), \"~s\");~n",[Name,Class]);
 
850
build_ret(Name,_,#type{base={ref,"wxTreeItemId"=Class},single=true}) ->
 
851
    w(" rt.addRef(getRef((void *)~s.m_pItem,memenv), \"~s\");~n",[Name,Class]);
 
852
build_ret(Name,_,#type{base={term,_},single=true}) ->
 
853
    w(" rt.addExt2Term(~s);~n", [Name]);
 
854
build_ret(Name,_,#type{base={binary,Size},single=true}) ->
 
855
    w(" if(~s) {~n", [Name]),
 
856
    w("    rt.addBinary(~s, ~s);~n", [Name,Size]),
 
857
    w(" } else {rt.addAtom(\"null\");};~n");
 
858
build_ret(Name,_,#type{name="wxUIntPtr", ref={pointer,1}, single=true}) ->
 
859
    w(" rt.add(~s);~n", [Name]);
 
860
build_ret(Name,_,#type{base={enum,_Type},single=true}) ->
 
861
    w(" rt.addInt(~s);~n",[Name]);
 
862
build_ret(Name,_,#type{base={comp,_,{record, wxMouseState}},single=true}) ->
 
863
    w(" rt.add(~s);~n", [Name]);
 
864
build_ret(Name,_,#type{base={comp,_,_},single=true, ref=reference}) ->
 
865
    w(" rt.add((*~s));~n",[Name]);
 
866
build_ret(Name,_,#type{base={comp,_,_},single=true}) ->
 
867
    w(" rt.add(~s);~n",[Name]);
 
868
build_ret(Name,_,#type{base=bool,single=true,by_val=true}) ->
 
869
    w(" rt.addBool(~s);~n",[Name]);
 
870
build_ret(Name,both,#type{base=int,single=true,mod=M}) ->
 
871
    case lists:member(unsigned, M) of
 
872
        true ->  w(" rt.addUint(*~s);~n",[Name]);
 
873
        false -> w(" rt.addInt(*~s);~n",[Name])
 
874
    end;
 
875
build_ret(Name,_,#type{base=int,single=true,mod=M}) ->
 
876
    case lists:member(unsigned, M) of
 
877
        true ->  w(" rt.addUint(~s);~n",[Name]);
 
878
        false -> w(" rt.addInt(~s);~n",[Name])
 
879
    end;
 
880
build_ret(Name,_,#type{name="wxArrayInt"}) ->
 
881
    w(" rt.add(~s);~n", [Name]);
 
882
build_ret(Name,_,#type{base={comp,_,_},single=array}) ->
 
883
    w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]),
 
884
    w("  rt.add(~s[i]);~n }~n",[Name]),
 
885
    w(" rt.endList(~s.GetCount());~n",[Name]);    
 
886
build_ret(Name,_,#type{name=List,single=list,base={class,Class}}) ->
 
887
    w(" int i=0;~n"),
 
888
    w(" for(~s::Node *node = ~s.GetFirst(); node; node = node->GetNext()) {~n",
 
889
      [List, Name]),
 
890
    w("   ~s * ~sTmp = node->GetData();~n", [Class,Name]),
 
891
    w("   rt.addRef(getRef((void *)~sTmp,memenv), \"~s\"); i++;}~n",[Name,Class]),
 
892
    w(" rt.endList(~s.GetCount());~n",[Name]);    
 
893
    
 
894
build_ret(Name,_,#type{name="wxArrayTreeItemIds"}) ->
 
895
    w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]),   
 
896
    w("    rt.addRef(getRef((void *)~s[i].m_pItem,memenv), \"wxTreeItemId\");}~n",[Name]),
 
897
    w(" rt.endList(~s.GetCount());~n",[Name]);
 
898
 
 
899
build_ret(Name,_,#type{base=float,single=true}) ->
 
900
%%    w(" double Temp~s = ~s;~n", [Name,Name]),
 
901
    w(" rt.addFloat(~s);~n",[Name]);
 
902
build_ret(Name,_,#type{base=double,single=true}) ->
 
903
    w(" rt.addFloat(~s);~n",[Name]);
 
904
build_ret(Name,_,#type{name="wxString",single=true}) ->
 
905
    w(" rt.add(~s);~n",[Name]);
 
906
build_ret(Name,_,#type{name="wxArrayString", single=array}) ->
 
907
    w(" rt.add(~s);~n", [Name]);
 
908
build_ret(Name,In,T) ->
 
909
    ?error({nyi, Name,In, T}).
 
910
                 
 
911
mods([const|R]) -> "const " ++ mods(R);
 
912
mods([unsigned|R]) -> "unsigned " ++ mods(R);
 
913
mods([]) -> "".   
 
914
 
 
915
build_enums() ->
 
916
    Tree = get(consts),
 
917
    w(" /* This file is also generated */~n"),
 
918
    w("#include <wx/wx.h>~n"),
 
919
    w("#include \"../wxe_impl.h\"~n"),
 
920
    w("#include \"wxe_macros.h\"~n"),
 
921
    w("#include \"../wxe_return.h\"~n"),
 
922
    w("void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {~n"), 
 
923
    NotConsts = [NC || NC = #const{is_const=false} <- gb_trees:values(Tree)],
 
924
    Size = length(NotConsts),
 
925
    GVars = get(gvars),
 
926
    GSize = length(GVars),
 
927
    w("  wxeReturn rt = wxeReturn(WXE_DRV_PORT, caller);~n"),
 
928
    w(" rt.addAtom((char*)\"wx_consts\");~n"),    
 
929
    [build_enum(NConst) || NConst <- lists:keysort(#const.val, NotConsts)],
 
930
    _Cnt = foldl(fun(Gvar, I) -> build_gvar(Gvar,I) end, 0, lists:sort(GVars)),
 
931
    w(" rt.endList(~p);~n", [Size+GSize]),
 
932
    w(" rt.addTupleCount(2);~n"),
 
933
    w("  rt.send();~n"),
 
934
    w("}~n"),
 
935
    ok.
 
936
 
 
937
build_enum(#const{name=Name}) ->
 
938
    w(" rt.addAtom(\"~s\"); rt.addInt(~s);~n", [Name, Name]),
 
939
    w(" rt.addTupleCount(2);~n").
 
940
 
 
941
build_gvar({Name, "wxColour", _Id}, Cnt) ->
 
942
    w("   rt.addAtom(\"~s\"); rt.add(*(~s));~n",[Name,Name]),
 
943
    w("   rt.addTupleCount(2);~n"),
 
944
    Cnt;
 
945
build_gvar({Name, {address,Class}, _Id}, Cnt) ->
 
946
    w("   rt.addAtom(\"~s\"); rt.addRef(getRef((void *)&~s,memenv), \"~s\");~n",[Name,Name,Class]),
 
947
    w("   rt.addTupleCount(2);~n"),
 
948
    Cnt+1;
 
949
build_gvar({Name, Class, _Id}, Cnt) ->
 
950
    w("   rt.addAtom(\"~s\"); rt.addRef(getRef((void *)~s,memenv),\"~s\");~n",[Name,Name,Class]),
 
951
    w("   rt.addTupleCount(2);~n"),
 
952
    Cnt+1.
 
953
 
 
954
gen_macros() ->
 
955
    w("#include <wx/caret.h>~n"),   %% Arrg wxw forgot?? some files 
 
956
    w("#include <wx/tooltip.h>~n"), 
 
957
    w("#include <wx/gbsizer.h>~n"), 
 
958
    w("#include <wx/splash.h>~n"),
 
959
    w("#include <wx/grid.h>~n"),
 
960
    w("#include <wx/image.h>~n"),
 
961
    w("#include <wx/tglbtn.h>~n"),
 
962
    w("#include <wx/calctrl.h>~n"),
 
963
    w("#include <wx/dirctrl.h>~n"),
 
964
    w("#include <wx/listctrl.h>~n"),
 
965
    w("#include <wx/treectrl.h>~n"),
 
966
    w("#include <wx/spinbutt.h>~n"),
 
967
    w("#include <wx/spinctrl.h>~n"),
 
968
    w("#include <wx/colordlg.h>~n"),
 
969
    w("#include <wx/fdrepdlg.h>~n"),
 
970
    w("#include <wx/fontdlg.h>~n"),
 
971
    w("#include <wx/progdlg.h>~n"),
 
972
    w("#include <wx/printdlg.h>~n"),
 
973
    w("#include <wx/dcbuffer.h>~n"),
 
974
    w("#include <wx/dcmirror.h>~n"),
 
975
    w("#include <wx/glcanvas.h>~n"),
 
976
    w("#include <wx/dcps.h>~n"),
 
977
    w("#include <wx/xrc/xmlres.h>~n"),
 
978
    w("#include <wx/html/htmprint.h>~n"),
 
979
    w("#include <wx/stc/stc.h>~n"),
 
980
    w("#include <wx/minifram.h>~n"),
 
981
    w("#include <wx/sashwin.h>~n"),
 
982
    w("#include <wx/laywin.h>~n"), 
 
983
    w("#include <wx/graphics.h>~n"), 
 
984
    w("#include <wx/aui/aui.h>~n"), 
 
985
    w("#include <wx/datectrl.h>~n"), 
 
986
    w("#include <wx/filepicker.h>~n"), 
 
987
    w("#include <wx/fontpicker.h>~n"), 
 
988
    w("#include <wx/clrpicker.h>~n"), 
 
989
    w("#include <wx/statline.h>~n"), 
 
990
    w("#include <wx/clipbrd.h>~n"), 
 
991
    w("#include <wx/splitter.h>~n"),
 
992
 
 
993
    w("~n~n", []),
 
994
    [w("#define ~s_~s ~p~n", [Class,Name,Id]) || 
 
995
        {Class,Name,_,Id} <- wx_gen_erl:get_unique_names()],
 
996
    w("~n~n").
 
997
 
 
998
build_events() ->
 
999
    open_write("../c_src/gen/wxe_events.cpp"),
 
1000
    c_copyright(),
 
1001
    w("~n/***** This file is generated do not edit ****/ ~n~n"),
 
1002
    w("#include <wx/wx.h>~n"),
 
1003
    w("#include \"../wxe_impl.h\"~n~n"),
 
1004
    w("#include \"wxe_macros.h\"~n"),
 
1005
    w("#include \"../wxe_events.h\"~n~n"),
 
1006
    w("#include \"../wxe_return.h\"~n~n"),
 
1007
    
 
1008
    w("wxeEtype::wxeEtype(const char *name, int Id) {eName = name;cID = Id;}~n~n"),
 
1009
    w("WX_DECLARE_HASH_MAP(int, wxeEtype*, wxIntegerHash, wxIntegerEqual, wxeETmap );~n~n"),
 
1010
    
 
1011
    w("wxeETmap etmap; ~n~n"),
 
1012
    
 
1013
    w(
 
1014
"int wxeEventTypeFromAtom(char *etype_atom) {
 
1015
  wxeETmap::iterator it;
 
1016
  for(it = etmap.begin(); it != etmap.end(); ++it) {
 
1017
       wxeEtype * value = it->second;
 
1018
       if(strcmp(value->eName, etype_atom) == 0) { 
 
1019
         if(it->first > wxEVT_USER_FIRST) {        
 
1020
               return it->first - wxEVT_USER_FIRST;
 
1021
            } else {
 
1022
               return it->first;
 
1023
            }
 
1024
       }
 
1025
  }   
 
1026
  return -1; 
 
1027
}
 
1028
 
 
1029
"), 
 
1030
 
 
1031
    Evs0 = [C || {_,C=#class{event=Evs}} <- get(), Evs =/= false],
 
1032
    Evs = lists:keysort(#class.id, Evs0),
 
1033
    initEventTable(Evs),
 
1034
    encode_events(Evs),
 
1035
    close().
 
1036
 
 
1037
initEventTable(Evs) ->
 
1038
    w("void initEventTable() ~n{~n"),
 
1039
    w("  struct { ",[]),
 
1040
    w("int ev_type;  int class_id; char * ev_name;} event_types[] = ~n  {~n",[]),
 
1041
 
 
1042
    lists:foreach(fun(Ev) -> init_event_classes(Ev) end, 
 
1043
                  [#class{id=0,event=[wxEVT_NULL]}|Evs]),
 
1044
    w("   {-1, 0, ""}~n  };~n",[]),
 
1045
    w("  for(int i=0; event_types[i].ev_type != -1; i++) {~n",[]),
 
1046
    w("     if(NULL == etmap[event_types[i].ev_type]) {~n",[]),
 
1047
    w("       etmap[event_types[i].ev_type] = ~n"
 
1048
      "        new wxeEtype(event_types[i].ev_name, event_types[i].class_id);~n"),
 
1049
    w("     } else {~n",[]),
 
1050
    w("       wxeEtype *prev = etmap[event_types[i].ev_type];~n"
 
1051
      "       wxString msg(wxT(\"Duplicate event defs: \"));~n"
 
1052
      "       msg += wxString::FromAscii(event_types[i].ev_name);~n"
 
1053
      "       msg += wxString::Format(wxT(\" %d \"), event_types[i].class_id);~n"
 
1054
      "       msg += wxString::FromAscii(prev->eName);~n"
 
1055
      "       msg += wxString::Format(wxT(\" %d\"), prev->cID);~n"
 
1056
      "       send_msg(\"internal_error\", &msg);~n"
 
1057
      "     }~n"
 
1058
      "  }~n", []),
 
1059
    w("}~n~n").
 
1060
    
 
1061
init_event_classes(#class{event=ETs, id=Id}) ->
 
1062
    F = fun({Eev, Cev, OtherClass}) ->
 
1063
                w("   {~w + wxEVT_USER_FIRST, ~w, ~p},~n",
 
1064
                  [Cev, find_id(OtherClass), wx_gen_erl:event_type_name(Eev)]);
 
1065
           (Ev) ->
 
1066
                w("   {~w, ~w, ~p},~n",
 
1067
                  [Ev, Id, wx_gen_erl:event_type_name(Ev)])
 
1068
        end,
 
1069
    [F(ET) || ET <- ETs].
 
1070
 
 
1071
find_id(OtherClass) ->
 
1072
    Class = get({class,atom_to_list(OtherClass)}),
 
1073
    %%{value, Class} = lists:keysearch(atom_to_list(OtherClass), #class.name, All),
 
1074
    Class#class.id.
 
1075
    
 
1076
encode_events(Evs) ->
 
1077
    ?WTC("encode_events"),
 
1078
    w("void wxeEvtListener::forward(wxEvent& event) ~n"
 
1079
      "{ ~n"  
 
1080
      "#ifdef DEBUG~n"
 
1081
      "  if(!sendevent(&event, port)) ~n"
 
1082
      "    fprintf(stderr, \"Couldn't send event!\\r\\n\");~n"
 
1083
      "#else~n"
 
1084
      "sendevent(&event, port);~n"
 
1085
      "#endif~n"
 
1086
      "}~n~n"),
 
1087
    w("int getRef(void* ptr, wxeMemEnv* memenv) ~n" 
 
1088
      "{ ~n"
 
1089
      "  WxeApp * app = (WxeApp *) wxTheApp;~n"
 
1090
      "  return app->getRef(ptr,memenv);~n"
 
1091
      "} ~n~n"),
 
1092
    w("bool sendevent(wxEvent *event, ErlDrvPort port)~n{~n"
 
1093
      " int send_res ;~n"
 
1094
      " char * evClass = NULL;~n"
 
1095
      " wxMBConvUTF32 UTFconverter;~n"
 
1096
      " wxeEtype *Etype = etmap[event->GetEventType()];~n"
 
1097
      " wxeCallbackData *cb = (wxeCallbackData *)event->m_callbackUserData;~n"
 
1098
      "  WxeApp * app = (WxeApp *) wxTheApp;~n"
 
1099
      " wxeMemEnv *memenv = app->getMemEnv(port);~n"
 
1100
      "  wxeReturn rt = wxeReturn(port, cb->listener);~n"),
 
1101
    
 
1102
    w("~n rt.addAtom((char*)\"wx\");~n"
 
1103
      " rt.addInt((int) event->GetId());~n"
 
1104
      " rt.addRef(getRef((void *)(cb->obj), memenv), cb->class_name);~n"
 
1105
      " rt.addExt2Term(cb->user_data);~n"),
 
1106
 
 
1107
    w(" if(!memenv) return 0;~n~n"),
 
1108
    w(" switch(Etype->cID) {~n"),
 
1109
    lists:foreach(fun(Ev) -> encode_event(Ev) end, Evs),
 
1110
    w(" }~n~n"),
 
1111
 
 
1112
    w(" rt.addTupleCount(5);~n"),
 
1113
    w(" if(cb->fun_id) {~n"),
 
1114
    w("   rt.addRef(getRef((void *)event,memenv), evClass);~n"),
 
1115
    w("   rt.addTupleCount(2);~n"),
 
1116
    w("   rt.addInt(cb->fun_id);~n"),
 
1117
    w("   rt.addAtom(\"_wx_invoke_cb_\");~n"),
 
1118
    w("   rt.addTupleCount(3);~n"),
 
1119
    w("   pre_callback();~n"),
 
1120
    w("   send_res =  rt.send();~n"),
 
1121
    w("   if(send_res) handle_event_callback(port, cb->listener);~n"),
 
1122
    w("   app->clearPtr((void *) event);~n"),
 
1123
    w(" } else {~n"),
 
1124
    w("   send_res =  rt.send();~n"),
 
1125
    w("   if(cb->skip) event->Skip();~n"),  
 
1126
    w(" };~n"),
 
1127
    w(" return send_res;~n"),
 
1128
    w(" }~n").
 
1129
 
 
1130
encode_event(C = #class{name=Class, id=Id, options=Opts}) ->
 
1131
    ?WTC("encode_event"),
 
1132
    case proplists:get_value("mixed_event", Opts) of 
 
1133
        undefined -> 
 
1134
            w("case ~p: {// ~s~n", [Id,Class]),
 
1135
            encode_event2(C),
 
1136
            ok;
 
1137
        Mixed ->
 
1138
            w("case ~p: {// ~s or ~s~n", [Id,Class,Mixed]),
 
1139
            w("  if(event->IsKindOf(CLASSINFO(~s))) {~n",[Class]),
 
1140
            encode_event2(C),
 
1141
            w("  } else {~n",[]),
 
1142
            w("    Etype = etmap[event->GetEventType() + wxEVT_USER_FIRST];~n",[]),
 
1143
            encode_event2(get({class,atom_to_list(Mixed)})),
 
1144
            w("  }~n",[]),
 
1145
            ok
 
1146
    end,
 
1147
    w("  break;~n}~n").
 
1148
 
 
1149
encode_event2(Class = #class{name=Name}) ->
 
1150
    Attrs = build_event_attrs(Class),
 
1151
    w("    evClass = (char*)\"~s\";~n",[Name]),
 
1152
    w("    rt.addAtom((char*)\"~s\");~n", [wx_gen_erl:event_rec_name(Name)]),
 
1153
    w("    rt.addAtom(Etype->eName);~n"),
 
1154
    build_ret_types(void, Attrs),
 
1155
    w("    rt.addTupleCount(~p);~n",[length(Attrs) + 2]).
 
1156
 
 
1157
build_event_attrs(ClassRec = #class{name=Class}) ->
 
1158
    Attrs0 = wx_gen_erl:filter_attrs(ClassRec),
 
1159
    Rename = 
 
1160
        fun(Att = #param{name=Name,prot=public,acc=undefined}, {All,Use}) -> 
 
1161
                {[Att#param{name= "ev->" ++ Name}|All],Use};
 
1162
           (Att = #param{acc=Acc}, {All,_}) -> 
 
1163
                {[Att#param{name= "ev->" ++ Acc}|All], true}
 
1164
        end,
 
1165
    case foldr(Rename,{[],false},Attrs0) of
 
1166
        {[],_} ->  [];
 
1167
%%      {Attrs,false} ->
 
1168
%%          w(" ~s ev = dynamic_cast<~s&>(event);~n",[Class,Class]),
 
1169
%%          Attrs;
 
1170
        {Attrs,_} ->
 
1171
            w(" ~s * ev = (~s *) event;~n",[Class,Class]),
 
1172
            FixClass = 
 
1173
                fun(P=#param{name=N,acc=Acc,type=#type{single=Single,by_val=ByVal,
 
1174
                                                       base={class,C}}}) 
 
1175
                   when Acc =/= undefined ->
 
1176
                        Var = var_name(N),
 
1177
                        if Single, ByVal ->
 
1178
                                w(" ~s * ~s = new ~s(~s);~n", [C,Var,C,N]),
 
1179
                                w(" app->newPtr((void *) ~s,3, memenv);~n", [Var]);
 
1180
                           true ->
 
1181
                                w(" ~s * ~s = ~s;~n", [C,Var,N])
 
1182
                        end,
 
1183
                        P#param{name=Var};
 
1184
                   (P) -> P
 
1185
                end, 
 
1186
            lists:map(FixClass, Attrs)
 
1187
    end.
 
1188
 
 
1189
var_name("ev->" ++ Name0) -> 
 
1190
    case reverse(Name0) of
 
1191
        ")(" ++ Name -> reverse(Name);
 
1192
        _ -> Name0
 
1193
    end;
 
1194
var_name(Name) -> Name.
 
1195
     
 
1196
enum_name({Class,Type}) ->
 
1197
    uppercase_all(Class ++ "_" ++ Type);
 
1198
enum_name(Type) ->
 
1199
    uppercase_all(Type).
 
1200
 
 
1201
 
 
1202
enum_type({Class,Type}) ->
 
1203
    Class ++ "::" ++ Type;
 
1204
enum_type(Type) -> Type.